976 lines
22 KiB
C++
976 lines
22 KiB
C++
/*
|
||
* $Id$
|
||
*
|
||
* Author Jeffrey O. Hill
|
||
* johill@lanl.gov
|
||
* 505 665 1831
|
||
*
|
||
* Experimental Physics and Industrial Control System (EPICS)
|
||
*
|
||
* Copyright 1991, the Regents of the University of California,
|
||
* and the University of Chicago Board of Governors.
|
||
*
|
||
* This software was produced under U.S. Government contracts:
|
||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||
*
|
||
* Initial development by:
|
||
* The Controls and Automation Group (AT-8)
|
||
* Ground Test Accelerator
|
||
* Accelerator Technology Division
|
||
* Los Alamos National Laboratory
|
||
*
|
||
* Co-developed with
|
||
* The Controls and Computing Group
|
||
* Accelerator Systems Division
|
||
* Advanced Photon Source
|
||
* Argonne National Laboratory
|
||
*
|
||
*
|
||
* History
|
||
* $Log$
|
||
* Revision 1.22 1998/04/20 18:14:57 jhill
|
||
* made clientHostName virtual in casDGClient
|
||
*
|
||
* Revision 1.21 1998/02/18 22:46:47 jhill
|
||
* fixed warning
|
||
*
|
||
* Revision 1.20 1998/02/05 23:05:27 jhill
|
||
* removed static members
|
||
*
|
||
* Revision 1.19 1997/08/05 00:47:16 jhill
|
||
* fixed warnings
|
||
*
|
||
* Revision 1.18 1997/06/30 22:54:30 jhill
|
||
* use %p with pointers
|
||
*
|
||
* Revision 1.17 1997/06/13 09:16:06 jhill
|
||
* connect proto changes
|
||
*
|
||
* Revision 1.16 1997/04/10 19:34:23 jhill
|
||
* API changes
|
||
*
|
||
* Revision 1.15 1997/01/10 21:18:05 jhill
|
||
* code around gnu g++ inline bug when -O isnt used
|
||
*
|
||
* Revision 1.14 1996/12/11 00:57:56 jhill
|
||
* moved casEventMaskEntry here
|
||
*
|
||
* Revision 1.13 1996/12/06 22:36:30 jhill
|
||
* use destroyInProgress flag now functional nativeCount()
|
||
*
|
||
* Revision 1.12 1996/11/02 00:54:31 jhill
|
||
* many improvements
|
||
*
|
||
* Revision 1.11 1996/09/16 18:24:09 jhill
|
||
* vxWorks port changes
|
||
*
|
||
* Revision 1.10 1996/09/04 20:27:02 jhill
|
||
* doccasdef.h
|
||
*
|
||
* Revision 1.9 1996/08/13 22:56:14 jhill
|
||
* added init for mutex class
|
||
*
|
||
* Revision 1.8 1996/08/05 23:22:58 jhill
|
||
* gddScaler => gddScalar
|
||
*
|
||
* Revision 1.7 1996/08/05 19:27:28 jhill
|
||
* added process()
|
||
*
|
||
* Revision 1.5 1996/07/24 22:00:50 jhill
|
||
* added pushOnToEventQueue()
|
||
*
|
||
* Revision 1.4 1996/07/09 22:51:14 jhill
|
||
* store copy of msg in ctx
|
||
*
|
||
* Revision 1.3 1996/06/26 21:19:04 jhill
|
||
* now matches gdd api revisions
|
||
*
|
||
* Revision 1.2 1996/06/21 02:30:58 jhill
|
||
* solaris port
|
||
*
|
||
* Revision 1.1.1.1 1996/06/20 00:28:15 jhill
|
||
* ca server installation
|
||
*
|
||
*
|
||
*/
|
||
|
||
#ifndef INCLserverh
|
||
#define INCLserverh
|
||
|
||
//
|
||
// ANSI C
|
||
//
|
||
#include <stdio.h>
|
||
|
||
#if defined(epicsExportSharedSymbols)
|
||
#error suspect that libCom, ca, and gdd were not imported
|
||
#endif
|
||
|
||
//
|
||
// EPICS
|
||
// (some of these are included from casdef.h but
|
||
// are included first here so that they are included
|
||
// once only before epicsExportSharedSymbols is defined)
|
||
//
|
||
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
|
||
#include "epicsAssert.h" // EPICS assert() macros
|
||
#include "osiTime.h" // EPICS os independent time
|
||
#include "alarm.h" // EPICS alarm severity/condition
|
||
#include "errMdef.h" // EPICS error codes
|
||
#include "gdd.h" // EPICS data descriptors
|
||
#include "resourceLib.h" // EPICS hashing templates
|
||
|
||
//
|
||
// CA
|
||
//
|
||
#include "caCommonDef.h"
|
||
#include "caerr.h"
|
||
|
||
#if defined(epicsExportSharedSymbols)
|
||
#error suspect that libCom, ca, cxxTemplates, and gdd were not imported
|
||
#endif
|
||
|
||
//
|
||
// CAS
|
||
//
|
||
#define epicsExportSharedSymbols
|
||
#include "casdef.h" // sets proper def for shareLib.h defines
|
||
#include "osiMutexCAS.h" // NOOP on single threaded OS
|
||
void casVerifyFunc(const char *pFile, unsigned line, const char *pExp);
|
||
void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment);
|
||
#define serverToolDebug(COMMENT) \
|
||
{serverToolDebugFunc(__FILE__, __LINE__, COMMENT); }
|
||
#define casVerify(EXP) {if ((EXP)==0) casVerifyFunc(__FILE__, __LINE__, #EXP); }
|
||
caStatus createDBRDD(unsigned dbrType, aitIndex dbrCount, smartGDDPointer &pDescRet);
|
||
caStatus copyBetweenDD(gdd &dest, gdd &src);
|
||
|
||
enum xRecvStatus {xRecvOK, xRecvDisconnect};
|
||
enum xSendStatus {xSendOK, xSendDisconnect};
|
||
enum xBlockingStatus {xIsBlocking, xIsntBlocking};
|
||
enum casIOState {casOnLine, casOffLine};
|
||
typedef unsigned bufSizeT;
|
||
|
||
enum casProcCond {casProcOk, casProcDisconnect};
|
||
|
||
/*
|
||
* maximum peak log entries for each event block (registartion)
|
||
* (events cached into the last queue entry if over flow occurs)
|
||
* (if this exceeds 256 then the casMonitor::nPend must
|
||
* be assigned a new data type)
|
||
*/
|
||
#define individualEventEntries 16u
|
||
|
||
/*
|
||
* maximum average log entries for each event block (registartion)
|
||
* (events cached into the last queue entry if over flow occurs)
|
||
* (if this exceeds 256 then the casMonitor::nPend must
|
||
* be assigned a new data type)
|
||
*/
|
||
#define averageEventEntries 4u
|
||
|
||
typedef caResId caEventId;
|
||
|
||
//
|
||
// fwd ref
|
||
//
|
||
class caServerI;
|
||
|
||
//
|
||
// casEventSys
|
||
//
|
||
class casEventSys {
|
||
public:
|
||
inline casEventSys (casCoreClient &coreClientIn);
|
||
|
||
inline caStatus init();
|
||
|
||
virtual ~casEventSys();
|
||
|
||
virtual void destroy()=0;
|
||
|
||
void show(unsigned level) const;
|
||
casProcCond process();
|
||
|
||
void installMonitor();
|
||
void removeMonitor();
|
||
|
||
inline void removeFromEventQueue(casEvent &);
|
||
inline void addToEventQueue(casEvent &);
|
||
|
||
inline void insertEventQueue(casEvent &insert, casEvent &prevEvent);
|
||
inline void pushOnToEventQueue(casEvent &event);
|
||
|
||
inline aitBool full();
|
||
|
||
inline casMonitor *resIdToMon(const caResId id);
|
||
|
||
inline casCoreClient &getCoreClient();
|
||
|
||
inline aitBool getEventsOff () const;
|
||
|
||
inline void setEventsOn();
|
||
|
||
inline void setEventsOff();
|
||
|
||
inline void setDestroyPending();
|
||
|
||
private:
|
||
tsDLList<casEvent> eventLogQue;
|
||
osiMutex mutex;
|
||
casCoreClient &coreClient;
|
||
unsigned numEventBlocks; // N event blocks installed
|
||
unsigned maxLogEntries; // max log entries
|
||
unsigned char eventsOff;
|
||
unsigned char destroyPending;
|
||
};
|
||
|
||
//
|
||
// casClientMon
|
||
//
|
||
class casClientMon : public casMonitor {
|
||
public:
|
||
casClientMon(casChannelI &, caResId clientId,
|
||
const unsigned long count, const unsigned type,
|
||
const casEventMask &maskIn, osiMutex &mutexIn);
|
||
~casClientMon();
|
||
|
||
caStatus callBack(gdd &value);
|
||
|
||
virtual casResType resourceType() const;
|
||
|
||
caResId getId() const
|
||
{
|
||
return this->casRes::getId();
|
||
}
|
||
|
||
virtual void destroy();
|
||
private:
|
||
};
|
||
|
||
class casCtx {
|
||
public:
|
||
inline casCtx();
|
||
|
||
//
|
||
// get
|
||
//
|
||
inline const caHdr *getMsg() const;
|
||
inline void *getData() const;
|
||
inline caServerI * getServer() const;
|
||
inline casCoreClient * getClient() const;
|
||
inline casPVI * getPV() const;
|
||
inline casChannelI * getChannel() const;
|
||
|
||
//
|
||
// set
|
||
// (assumes incoming message is in network byte order)
|
||
//
|
||
inline void setMsg(const char *pBuf);
|
||
|
||
inline void setData(void *p);
|
||
|
||
inline void setServer(caServerI *p);
|
||
|
||
inline void setClient(casCoreClient *p);
|
||
|
||
inline void setPV(casPVI *p);
|
||
|
||
inline void setChannel(casChannelI *p);
|
||
|
||
void show (unsigned level) const;
|
||
|
||
private:
|
||
caHdr msg; // ca message header
|
||
void *pData; // pointer to data following header
|
||
caServerI *pCAS;
|
||
casCoreClient *pClient;
|
||
casChannelI *pChannel;
|
||
casPVI *pPV;
|
||
unsigned nAsyncIO; // checks for improper use of async io
|
||
};
|
||
|
||
enum casFillCondition{
|
||
casFillNone,
|
||
casFillPartial,
|
||
casFillFull,
|
||
casFillDisconnect};
|
||
//
|
||
// inBuf
|
||
//
|
||
class inBuf {
|
||
public:
|
||
//
|
||
// this needs to be here (and not in dgInBufIL.h) if we
|
||
// are to avoid undefined symbols under gcc 2.7.x without -O
|
||
//
|
||
inline inBuf(osiMutex &mutexIn, unsigned bufSizeIn);
|
||
inline caStatus init(); //constructor does not return status
|
||
virtual ~inBuf();
|
||
|
||
inline bufSizeT bytesPresent() const;
|
||
|
||
inline bufSizeT bytesAvailable() const ;
|
||
|
||
inline aitBool full() const;
|
||
|
||
inline void clear();
|
||
|
||
inline char *msgPtr() const;
|
||
|
||
inline void removeMsg(unsigned nBytes);
|
||
|
||
//
|
||
// fill the input buffer with any incoming messages
|
||
//
|
||
casFillCondition fill ();
|
||
|
||
void show (unsigned level) const;
|
||
|
||
virtual unsigned getDebugLevel() const = 0;
|
||
virtual bufSizeT incommingBytesPresent() const = 0;
|
||
virtual xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv,
|
||
bufSizeT &nByesRecv) = 0;
|
||
virtual void clientHostName (char *pBuf,
|
||
unsigned bufSize) const = 0;
|
||
|
||
private:
|
||
osiMutex &mutex;
|
||
char *pBuf;
|
||
bufSizeT bufSize;
|
||
bufSizeT bytesInBuffer;
|
||
bufSizeT nextReadIndex;
|
||
};
|
||
|
||
//
|
||
// dgInBuf
|
||
//
|
||
class dgInBuf : public inBuf {
|
||
public:
|
||
dgInBuf (osiMutex &mutexIn, unsigned bufSizeIn);
|
||
virtual ~dgInBuf();
|
||
|
||
inline void clear();
|
||
|
||
int hasAddress() const;
|
||
|
||
caNetAddr getSender() const;
|
||
|
||
xRecvStatus xRecv (char *pBufIn, bufSizeT nBytesToRecv,
|
||
bufSizeT &nByesRecv);
|
||
|
||
virtual xRecvStatus xDGRecv (char *pBuf, bufSizeT nBytesToRecv,
|
||
bufSizeT &nByesRecv, caNetAddr &sender) = 0;
|
||
|
||
private:
|
||
caNetAddr from;
|
||
};
|
||
|
||
//
|
||
// outBuf
|
||
//
|
||
enum casFlushCondition{
|
||
casFlushNone,
|
||
casFlushPartial,
|
||
casFlushCompleted,
|
||
casFlushDisconnect};
|
||
enum casFlushRequest{
|
||
casFlushAll,
|
||
casFlushSpecified};
|
||
|
||
class outBuf {
|
||
public:
|
||
outBuf (osiMutex &, unsigned bufSizeIn);
|
||
caStatus init(); //constructor does not return status
|
||
virtual ~outBuf()=0;
|
||
|
||
inline bufSizeT bytesPresent() const;
|
||
|
||
inline bufSizeT bytesFree() const;
|
||
|
||
//
|
||
// flush output queue
|
||
// (returns the number of bytes sent)
|
||
//
|
||
casFlushCondition flush(casFlushRequest req = casFlushAll,
|
||
bufSizeT spaceRequired=0u);
|
||
|
||
//
|
||
// allocate message buffer space
|
||
// (leaves message buffer locked)
|
||
//
|
||
caStatus allocMsg (unsigned extsize, caHdr **ppMsg, int lockRequired=1);
|
||
|
||
//
|
||
// commits message allocated with allocMsg()
|
||
//
|
||
void commitMsg ();
|
||
|
||
void show(unsigned level) const;
|
||
|
||
virtual unsigned getDebugLevel() const = 0;
|
||
virtual void sendBlockSignal();
|
||
|
||
//
|
||
// io dependent
|
||
//
|
||
virtual xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend,
|
||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent) = 0;
|
||
virtual void clientHostName (char *pBuf, unsigned bufSize) const = 0;
|
||
|
||
inline void clear();
|
||
|
||
private:
|
||
osiMutex &mutex;
|
||
char *pBuf;
|
||
const bufSizeT bufSize;
|
||
bufSizeT stack;
|
||
};
|
||
|
||
//
|
||
// dgOutBuf
|
||
//
|
||
class dgOutBuf : public outBuf {
|
||
public:
|
||
dgOutBuf (osiMutex &mutexIn, unsigned bufSizeIn);
|
||
|
||
virtual ~dgOutBuf();
|
||
|
||
caNetAddr getRecipient();
|
||
|
||
void setRecipient(const caNetAddr &addr);
|
||
|
||
void clear();
|
||
|
||
xSendStatus xSend (char *pBufIn, bufSizeT nBytesAvailableToSend,
|
||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent);
|
||
|
||
virtual xSendStatus xDGSend (char *pBuf, bufSizeT nBytesNeedToBeSent,
|
||
bufSizeT &nBytesSent, const caNetAddr &recipient) = 0;
|
||
private:
|
||
caNetAddr to;
|
||
};
|
||
|
||
|
||
//
|
||
// casCoreClient
|
||
// (this will eventually support direct communication
|
||
// between the client lib and the server lib)
|
||
//
|
||
class casCoreClient : public osiMutex, public ioBlocked,
|
||
public casEventSys {
|
||
|
||
//
|
||
// allows casAsyncIOI constructor to check for asynch IO duplicates
|
||
//
|
||
friend casAsyncIOI::casAsyncIOI(casCoreClient &clientIn, casAsyncIO &ioExternalIn);
|
||
|
||
public:
|
||
casCoreClient(caServerI &serverInternal);
|
||
caStatus init();
|
||
|
||
virtual ~casCoreClient();
|
||
virtual void destroy();
|
||
virtual caStatus disconnectChan(caResId id);
|
||
virtual void eventSignal() = 0;
|
||
virtual void eventFlush() = 0;
|
||
virtual caStatus start () = 0;
|
||
virtual void show (unsigned level) const;
|
||
virtual void installChannel (casChannelI &);
|
||
virtual void removeChannel (casChannelI &);
|
||
|
||
inline void installAsyncIO(casAsyncIOI &ioIn);
|
||
|
||
inline void removeAsyncIO(casAsyncIOI &ioIn);
|
||
|
||
inline casRes *lookupRes(const caResId &idIn, casResType type);
|
||
|
||
inline caServerI &getCAS() const;
|
||
|
||
virtual caStatus monitorResponse(casChannelI *,
|
||
const caHdr &, gdd *, const caStatus);
|
||
|
||
virtual caStatus accessRightsResponse(casChannelI *);
|
||
|
||
//
|
||
// one virtual function for each CA request type that has
|
||
// asynchronous completion
|
||
//
|
||
virtual caStatus asyncSearchResponse(
|
||
casDGIntfIO &outMsgIO, const caNetAddr &outAddr,
|
||
const caHdr &, const pvExistReturn &);
|
||
virtual caStatus createChanResponse(
|
||
const caHdr &, const pvCreateReturn &);
|
||
virtual caStatus readResponse(
|
||
casChannelI *, const caHdr &,
|
||
gdd *, const caStatus);
|
||
virtual caStatus readNotifyResponse(
|
||
casChannelI *, const caHdr &,
|
||
gdd *, const caStatus);
|
||
virtual caStatus writeResponse(
|
||
casChannelI *, const caHdr &, const caStatus);
|
||
virtual caStatus writeNotifyResponse(
|
||
casChannelI *, const caHdr &, const caStatus);
|
||
|
||
//
|
||
// The following are only used with async IO for
|
||
// DG clients
|
||
//
|
||
virtual caNetAddr fetchRespAddr();
|
||
virtual casDGIntfIO* fetchOutIntf();
|
||
protected:
|
||
casCtx ctx;
|
||
unsigned char asyncIOFlag;
|
||
|
||
private:
|
||
tsDLList<casAsyncIOI> ioInProgList;
|
||
};
|
||
|
||
//
|
||
// casClient
|
||
//
|
||
class casClient;
|
||
typedef caStatus (casClient::*pCASMsgHandler) ();
|
||
class casClient : public casCoreClient {
|
||
public:
|
||
casClient (caServerI &, inBuf &, outBuf &);
|
||
caStatus init(); //constructor does not return status
|
||
virtual ~casClient ();
|
||
|
||
void show(unsigned level) const;
|
||
|
||
//
|
||
// send error response to a message
|
||
//
|
||
caStatus sendErr(const caHdr *, const int reportedStatus,
|
||
const char *pFormat, ...);
|
||
|
||
unsigned getMinorVersion() const {return this->minor_version_number;}
|
||
|
||
|
||
//
|
||
// find the channel associated with a resource id
|
||
//
|
||
casChannelI *resIdToChannel(const caResId &id);
|
||
|
||
virtual void clientHostName (char *pBuf,
|
||
unsigned bufSize) const = 0;
|
||
|
||
protected:
|
||
unsigned minor_version_number;
|
||
osiTime elapsedAtLastSend;
|
||
osiTime elapsedAtLastRecv;
|
||
|
||
caStatus processMsg();
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
caStatus sendErrWithEpicsStatus(const caHdr *pMsg,
|
||
caStatus epicsStatus, caStatus clientStatus);
|
||
|
||
//
|
||
// logBadIdWithFileAndLineno()
|
||
//
|
||
# define logBadId(MP, DP, CACSTAT) \
|
||
this->logBadIdWithFileAndLineno(MP, DP, CACSTAT, __FILE__, __LINE__)
|
||
caStatus logBadIdWithFileAndLineno(const caHdr *mp,
|
||
const void *dp, int cacStat, const char *pFileName,
|
||
const unsigned lineno);
|
||
|
||
private:
|
||
inBuf &inBufRef;
|
||
outBuf &outBufRef;
|
||
|
||
//
|
||
// dump message to stderr
|
||
//
|
||
void dumpMsg(const caHdr *mp, const void *dp);
|
||
|
||
//
|
||
// one function for each CA request type
|
||
//
|
||
caStatus uknownMessageAction ();
|
||
caStatus ignoreMsgAction ();
|
||
caStatus noopAction ();
|
||
virtual caStatus eventAddAction ();
|
||
virtual caStatus eventCancelAction ();
|
||
virtual caStatus readAction ();
|
||
virtual caStatus readNotifyAction ();
|
||
virtual caStatus writeAction ();
|
||
virtual caStatus searchAction ();
|
||
virtual caStatus eventsOffAction ();
|
||
virtual caStatus eventsOnAction ();
|
||
virtual caStatus readSyncAction ();
|
||
virtual caStatus clearChannelAction ();
|
||
virtual caStatus claimChannelAction ();
|
||
virtual caStatus writeNotifyAction ();
|
||
virtual caStatus clientNameAction ();
|
||
virtual caStatus hostNameAction ();
|
||
virtual caStatus echoAction ();
|
||
|
||
//
|
||
// obtain the user name and host from the derived class
|
||
//
|
||
virtual const char *hostName() const;
|
||
virtual const char *userName() const;
|
||
|
||
//
|
||
// static members
|
||
//
|
||
static void loadProtoJumpTable();
|
||
static pCASMsgHandler msgHandlers[CA_PROTO_LAST_CMMD+1u];
|
||
static int msgHandlersInit;
|
||
};
|
||
|
||
|
||
|
||
//
|
||
// casStrmClient
|
||
//
|
||
class casStrmClient : public inBuf, public outBuf, public casClient,
|
||
public tsDLNode<casStrmClient> {
|
||
public:
|
||
casStrmClient (caServerI &cas);
|
||
caStatus init(); //constructor does not return status
|
||
~casStrmClient();
|
||
|
||
void show (unsigned level) const;
|
||
|
||
//
|
||
// installChannel()
|
||
//
|
||
void installChannel(casChannelI &chan);
|
||
|
||
//
|
||
// removeChannel()
|
||
//
|
||
void removeChannel(casChannelI &chan);
|
||
|
||
//
|
||
// one function for each CA request type that has
|
||
// asynchronous completion
|
||
//
|
||
virtual caStatus createChanResponse(const caHdr &, const pvCreateReturn &);
|
||
caStatus readResponse(casChannelI *pChan, const caHdr &msg,
|
||
gdd *pDesc, const caStatus status);
|
||
caStatus readNotifyResponse(casChannelI *pChan, const caHdr &msg,
|
||
gdd *pDesc, const caStatus status);
|
||
caStatus writeResponse(casChannelI *pChan, const caHdr &msg,
|
||
const caStatus status);
|
||
caStatus writeNotifyResponse(casChannelI *pChan, const caHdr &msg,
|
||
const caStatus status);
|
||
caStatus monitorResponse(casChannelI *pChan, const caHdr &msg,
|
||
gdd *pDesc, const caStatus status);
|
||
|
||
//
|
||
//
|
||
//
|
||
caStatus noReadAccessEvent(casClientMon *);
|
||
|
||
//
|
||
// obtain the user name and host
|
||
//
|
||
const char *hostName () const;
|
||
const char *userName () const;
|
||
|
||
caStatus disconnectChan (caResId id);
|
||
|
||
unsigned getDebugLevel() const;
|
||
private:
|
||
tsDLList<casChannelI> chanList;
|
||
char *pUserName;
|
||
char *pHostName;
|
||
|
||
//
|
||
// createChannel()
|
||
//
|
||
caStatus createChannel (const char *pName);
|
||
|
||
//
|
||
// verify read/write requests
|
||
//
|
||
caStatus verifyRequest (casChannelI *&pChan);
|
||
|
||
//
|
||
// one function for each CA request type
|
||
//
|
||
caStatus eventAddAction ();
|
||
caStatus eventCancelAction ();
|
||
caStatus readAction ();
|
||
caStatus readNotifyAction ();
|
||
caStatus writeAction ();
|
||
caStatus eventsOffAction ();
|
||
caStatus eventsOnAction ();
|
||
caStatus readSyncAction ();
|
||
caStatus clearChannelAction ();
|
||
caStatus claimChannelAction ();
|
||
caStatus writeNotifyAction ();
|
||
caStatus clientNameAction ();
|
||
caStatus hostNameAction ();
|
||
|
||
//
|
||
// accessRightsResponse()
|
||
//
|
||
caStatus accessRightsResponse (casChannelI *pciu);
|
||
//
|
||
|
||
// these prepare the gdd based on what is in the ca hdr
|
||
//
|
||
caStatus read (smartGDDPointer &pDesc);
|
||
caStatus write ();
|
||
|
||
//
|
||
// channelCreateFailed()
|
||
//
|
||
caStatus channelCreateFailed (const caHdr *mp, caStatus createStatus);
|
||
|
||
caStatus writeArrayData();
|
||
caStatus writeScalarData();
|
||
caStatus writeString();
|
||
|
||
//
|
||
// io independent send/recv
|
||
//
|
||
xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend,
|
||
bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent);
|
||
xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv,
|
||
bufSizeT &nByesRecv);
|
||
virtual xBlockingStatus blockingState() const = 0;
|
||
virtual xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq,
|
||
bufSizeT &nBytesActual) = 0;
|
||
virtual xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq,
|
||
bufSizeT &nBytesActual) = 0;
|
||
};
|
||
|
||
class casDGIntfIO;
|
||
|
||
|
||
//
|
||
// casDGClient
|
||
//
|
||
class casDGClient : public dgInBuf, public dgOutBuf, public casClient {
|
||
public:
|
||
casDGClient (caServerI &serverIn);
|
||
virtual ~casDGClient();
|
||
|
||
caStatus init(); // constructor does not return status
|
||
|
||
void show (unsigned level) const;
|
||
|
||
//
|
||
// only for use with DG io
|
||
//
|
||
static void sendBeacon(casDGIntfIO &io);
|
||
|
||
void destroy();
|
||
|
||
void processDG(casDGIntfIO &inMsgIO, casDGIntfIO &outMsgIO);
|
||
|
||
unsigned getDebugLevel() const;
|
||
|
||
virtual void clientHostName (char *pBuf,
|
||
unsigned bufSize) const = 0;
|
||
|
||
protected:
|
||
|
||
casProcCond eventSysProcess()
|
||
{
|
||
return this->casEventSys::process();
|
||
}
|
||
|
||
private:
|
||
casDGIntfIO *pOutMsgIO;
|
||
casDGIntfIO *pInMsgIO;
|
||
|
||
void ioBlockedSignal(); // dummy
|
||
|
||
//
|
||
// one function for each CA request type
|
||
//
|
||
caStatus searchAction ();
|
||
|
||
//
|
||
// searchFailResponse()
|
||
//
|
||
caStatus searchFailResponse(const caHdr *pMsg);
|
||
|
||
caStatus searchResponse(const caHdr &, const pvExistReturn &);
|
||
|
||
caStatus asyncSearchResponse(
|
||
casDGIntfIO &outMsgIO, const caNetAddr &outAddr,
|
||
const caHdr &msg, const pvExistReturn &);
|
||
caNetAddr fetchRespAddr();
|
||
casDGIntfIO* fetchOutIntf();
|
||
|
||
//
|
||
// IO depen
|
||
//
|
||
xRecvStatus xDGRecv (char *pBuf, bufSizeT nBytesToRecv,
|
||
bufSizeT &nByesRecv, caNetAddr &sender);
|
||
xSendStatus xDGSend (char *pBuf, bufSizeT nBytesNeedToBeSent,
|
||
bufSizeT &nBytesSent, const caNetAddr &recipient);
|
||
bufSizeT incommingBytesPresent() const;
|
||
};
|
||
|
||
//
|
||
// casEventMaskEntry
|
||
//
|
||
class casEventMaskEntry : public tsSLNode<casEventMaskEntry>,
|
||
public casEventMask, public stringId {
|
||
public:
|
||
casEventMaskEntry (casEventRegistry ®In,
|
||
casEventMask maskIn, const char *pName);
|
||
virtual ~casEventMaskEntry();
|
||
void show (unsigned level) const;
|
||
|
||
virtual void destroy();
|
||
private:
|
||
casEventRegistry ®
|
||
};
|
||
|
||
//
|
||
// casEventRegistry
|
||
//
|
||
class casEventRegistry : private resTable <casEventMaskEntry, stringId> {
|
||
friend class casEventMaskEntry;
|
||
public:
|
||
casEventRegistry(osiMutex &mutexIn) :
|
||
mutex(mutexIn), allocator(0), hasBeenInitialized(0) {}
|
||
|
||
int init();
|
||
|
||
~casEventRegistry()
|
||
{
|
||
this->destroyAllEntries();
|
||
}
|
||
|
||
casEventMask registerEvent (const char *pName);
|
||
|
||
void show (unsigned level) const;
|
||
|
||
private:
|
||
osiMutex &mutex;
|
||
unsigned allocator;
|
||
unsigned char hasBeenInitialized;
|
||
|
||
casEventMask maskAllocator();
|
||
};
|
||
|
||
#include "casIOD.h" // IO dependent
|
||
#include "casOSD.h" // OS dependent
|
||
|
||
class casClientMon;
|
||
|
||
//
|
||
// caServerI
|
||
//
|
||
class caServerI :
|
||
public osiMutex, // osiMutex must be first because it is used
|
||
// by ioBlockedList and casEventRegistry
|
||
public caServerOS,
|
||
public caServerIO,
|
||
public ioBlockedList,
|
||
private uintResTable<casRes>,
|
||
public casEventRegistry {
|
||
public:
|
||
caServerI (caServer &tool, unsigned pvCountEstimate);
|
||
~caServerI ();
|
||
|
||
//
|
||
// find the channel associated with a resource id
|
||
//
|
||
inline casChannelI *resIdToChannel(const caResId &id);
|
||
|
||
//
|
||
// find the PV associated with a resource id
|
||
//
|
||
casPVI *resIdToPV(const caResId &id);
|
||
|
||
//
|
||
// find the client monitor associated with a resource id
|
||
//
|
||
casClientMon *resIdToClientMon(const caResId &idIn);
|
||
|
||
casDGClient &castClient() {return this->dgClient;}
|
||
|
||
void installClient(casStrmClient *pClient);
|
||
|
||
void removeClient(casStrmClient *pClient);
|
||
|
||
//
|
||
// is there space for a new channel
|
||
//
|
||
aitBool roomForNewChannel() const;
|
||
|
||
//
|
||
// send beacon and advance beacon timer
|
||
//
|
||
void sendBeacon();
|
||
|
||
unsigned getDebugLevel() const { return debugLevel; }
|
||
inline void setDebugLevel(unsigned debugLevelIn);
|
||
|
||
osiTime getBeaconPeriod() const { return this->beaconPeriod; }
|
||
|
||
void show(unsigned level) const;
|
||
|
||
inline casRes *lookupRes(const caResId &idIn, casResType type);
|
||
|
||
inline caServer *getAdapter();
|
||
|
||
inline void installItem(casRes &res);
|
||
|
||
inline casRes *removeItem(casRes &res);
|
||
|
||
//
|
||
// call virtual function in the interface class
|
||
//
|
||
inline caServer * operator -> ();
|
||
|
||
void connectCB(casIntfOS &);
|
||
|
||
inline aitBool ready();
|
||
|
||
caStatus addAddr(const caNetAddr &addr, int autoBeaconAddr,
|
||
int addConfigAddr);
|
||
private:
|
||
void advanceBeaconPeriod();
|
||
|
||
casDGOS dgClient;
|
||
//casCtx ctx;
|
||
tsDLList<casStrmClient> clientList;
|
||
tsDLList<casIntfOS> intfList;
|
||
osiTime beaconPeriod;
|
||
caServer &adapter;
|
||
unsigned debugLevel;
|
||
|
||
// the estimated number of proces variables default = 1024u
|
||
const unsigned pvCountEstimate;
|
||
|
||
unsigned char haveBeenInitialized;
|
||
};
|
||
|
||
#define CAServerConnectPendQueueSize 10
|
||
|
||
/*
|
||
* If there is insufficent space to allocate an
|
||
* asynch IO in progress block then we will end up
|
||
* with pIoInProgress nill and activeAsyncIO true.
|
||
* This protects the app from simultaneous multiple
|
||
* invocation of async IO on the same PV.
|
||
*/
|
||
#define maxIOInProg 50
|
||
|
||
/*
|
||
* this really should be in another header file
|
||
*/
|
||
extern "C" {
|
||
void ca_printf (const char *pFormat, ...);
|
||
}
|
||
|
||
#endif /*INCLserverh*/
|
||
|
||
|