diff --git a/src/cas/build/Makefile b/src/cas/build/Makefile index 3cbeee0c1..fa8083e9d 100644 --- a/src/cas/build/Makefile +++ b/src/cas/build/Makefile @@ -25,7 +25,6 @@ SRC_DIRS += $(CA) INC += casdef.h INC += casEventMask.h -INC += casInternal.h INC += caNetAddr.h LIBSRCS += caServer.cc @@ -38,13 +37,15 @@ LIBSRCS += casPV.cc LIBSRCS += casPVI.cc LIBSRCS += casChannel.cc LIBSRCS += casChannelI.cc -LIBSRCS += casPVListChan.cc -LIBSRCS += casChanDelEv.cc LIBSRCS += casAsyncIOI.cc LIBSRCS += casAsyncReadIO.cc +LIBSRCS += casAsyncReadIOI.cc LIBSRCS += casAsyncWriteIO.cc +LIBSRCS += casAsyncWriteIOI.cc LIBSRCS += casAsyncPVExistIO.cc +LIBSRCS += casAsyncPVExistIOI.cc LIBSRCS += casAsyncPVAttachIO.cc +LIBSRCS += casAsyncPVAttachIOI.cc LIBSRCS += casEventSys.cc LIBSRCS += casMonitor.cc LIBSRCS += casMonEvent.cc @@ -60,8 +61,8 @@ LIBSRCS += caNetAddr.cc LIBSRCS += beaconTimer.cc LIBSRCS += beaconAnomalyGovernor.cc LIBSRCS += clientBufMemoryManager.cpp +LIBSRCS += chanIntfForPV.cc -LIBSRCS += caServerOS.cc LIBSRCS += casIntfOS.cc LIBSRCS += casDGIntfOS.cc LIBSRCS += casStreamOS.cc diff --git a/src/cas/example/directoryService/directoryServer.h b/src/cas/example/directoryService/directoryServer.h index ad5e2bf71..31a7b9348 100644 --- a/src/cas/example/directoryService/directoryServer.h +++ b/src/cas/example/directoryService/directoryServer.h @@ -8,12 +8,12 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ // -// Example EPICS CA directory server +// Example EPICS CA directory server // // -// caServer -// | -// directoryServer +// caServer +// | +// directoryServer // // @@ -27,6 +27,7 @@ // // EPICS // +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #define caNetAddrSock #include "casdef.h" #include "epicsAssert.h" @@ -34,7 +35,7 @@ #ifndef NELEMENTS -# define NELEMENTS(A) (sizeof(A)/sizeof(A[0])) +# define NELEMENTS(A) (sizeof(A)/sizeof(A[0])) #endif class directoryServer; @@ -44,24 +45,24 @@ class directoryServer; // class pvInfo { public: - pvInfo (const char *pNameIn, sockaddr_in addrIn) : - addr(addrIn), pNext(pvInfo::pFirst) - { - pvInfo::pFirst = this; - this->pName = new char [strlen(pNameIn)+1u]; - assert(this->pName); - strcpy(this->pName, pNameIn); - } - - const struct sockaddr_in getAddr() const { return this->addr; } - const char *getName () const { return this->pName; } - const pvInfo *getNext () const { return this->pNext; } - static const pvInfo *getFirst () { return pvInfo::pFirst; } + pvInfo (const char *pNameIn, sockaddr_in addrIn) : + addr(addrIn), pNext(pvInfo::pFirst) + { + pvInfo::pFirst = this; + this->pName = new char [strlen(pNameIn)+1u]; + assert(this->pName); + strcpy(this->pName, pNameIn); + } + + const struct sockaddr_in getAddr() const { return this->addr; } + const char *getName () const { return this->pName; } + const pvInfo *getNext () const { return this->pNext; } + static const pvInfo *getFirst () { return pvInfo::pFirst; } private: - struct sockaddr_in addr; - char *pName; - const pvInfo *pNext; - static const pvInfo *pFirst; + struct sockaddr_in addr; + char * pName; + const pvInfo * pNext; + static const pvInfo * pFirst; }; // @@ -77,41 +78,39 @@ private: class pvEntry // X aCC 655 : public stringId, public tsSLNode { public: - pvEntry (const pvInfo &infoIn, directoryServer &casIn, - const char *pAliasName) : - stringId(pAliasName), info(infoIn), cas(casIn) - { - assert(this->stringId::resourceName()!=NULL); - } + pvEntry (const pvInfo &infoIn, directoryServer &casIn, + const char *pAliasName) : + stringId(pAliasName), info(infoIn), cas(casIn) + { + assert(this->stringId::resourceName()!=NULL); + } - inline ~pvEntry(); + inline ~pvEntry(); - const pvInfo &getInfo() const { return this->info; } - - inline void destroy (); + const pvInfo &getInfo() const { return this->info; } + + inline void destroy (); private: - const pvInfo &info; - directoryServer &cas; + const pvInfo &info; + directoryServer &cas; }; - - // // directoryServer // class directoryServer : public caServer { public: - directoryServer (const char * const pvPrefix, unsigned aliasCount); - ~directoryServer(); - void show (unsigned level) const; - pvExistReturn pvExistTest (const casCtx&, const char *pPVName); + directoryServer ( const char * const pvPrefix, unsigned aliasCount ); + ~directoryServer(); + void show ( unsigned level ) const; + pvExistReturn pvExistTest ( const casCtx&, const char *pPVName ); - void installAliasName (const pvInfo &info, const char *pAliasName); - inline void removeAliasName(pvEntry &entry); + void installAliasName ( const pvInfo &info, const char *pAliasName ); + inline void removeAliasName ( pvEntry &entry ); private: - resTable stringResTbl; + resTable < pvEntry, stringId > stringResTbl; }; @@ -120,9 +119,9 @@ private: // inline void directoryServer::removeAliasName(pvEntry &entry) { - pvEntry *pE; - pE = this->stringResTbl.remove(entry); - assert(pE = &entry); + pvEntry *pE; + pE = this->stringResTbl.remove(entry); + assert(pE = &entry); } // @@ -130,7 +129,7 @@ inline void directoryServer::removeAliasName(pvEntry &entry) // inline pvEntry::~pvEntry() { - this->cas.removeAliasName(*this); + this->cas.removeAliasName(*this); } // @@ -138,9 +137,9 @@ inline pvEntry::~pvEntry() // inline void pvEntry::destroy () { - // - // always created with new - // - delete this; + // + // always created with new + // + delete this; } diff --git a/src/cas/example/directoryService/main.cc b/src/cas/example/directoryService/main.cc index f4acdc9d6..f0d448006 100644 --- a/src/cas/example/directoryService/main.cc +++ b/src/cas/example/directoryService/main.cc @@ -13,10 +13,8 @@ #include "directoryServer.h" #include "fdManager.h" -#define LOCAL static - -LOCAL int parseDirectoryFile (const char *pFileName); -LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName); +static int parseDirectoryFile (const char *pFileName); +static int parseDirectoryFP (FILE *pf, const char *pFileName); #ifndef INADDR_NONE #define INADDR_NONE (~0ul) @@ -109,7 +107,7 @@ extern int main (int argc, const char **argv) // [] // // -LOCAL int parseDirectoryFile (const char *pFileName) +static int parseDirectoryFile (const char *pFileName) { FILE *pf; @@ -139,7 +137,7 @@ LOCAL int parseDirectoryFile (const char *pFileName) // [] // // -LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName) +static int parseDirectoryFP (FILE *pf, const char *pFileName) { pvInfo *pPVI; char pvNameStr[128]; @@ -193,8 +191,8 @@ LOCAL int parseDirectoryFP (FILE *pf, const char *pFileName) ipa.sin_port = 0u; // use the default CA server port } - pPVI = new pvInfo (pvNameStr, ipa); - if (!pPVI) { + pPVI = new pvInfo ( pvNameStr, ipa ); + if ( ! pPVI ) { fprintf (stderr, "Unable to allocate space for a new PV in \"%s\" with PV=\"%s\" host=\"%s\"\n", pFileName, pvNameStr, hostNameStr); return -1; diff --git a/src/cas/example/simple/exAsyncPV.cc b/src/cas/example/simple/exAsyncPV.cc index 96396b7bb..103819bf3 100644 --- a/src/cas/example/simple/exAsyncPV.cc +++ b/src/cas/example/simple/exAsyncPV.cc @@ -29,7 +29,7 @@ caStatus exAsyncPV::read (const casCtx &ctx, gdd &valueIn) this->simultAsychIOCount++; - pIO = new exAsyncReadIO ( ctx, *this, valueIn ); + pIO = new exAsyncReadIO ( this->cas, ctx, *this, valueIn ); if (!pIO) { return S_casApp_noMemory; } @@ -51,7 +51,7 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn ) this->simultAsychIOCount++; - pIO = new exAsyncWriteIO ( ctx, *this, valueIn ); + pIO = new exAsyncWriteIO ( this->cas, ctx, *this, valueIn ); if ( ! pIO ) { return S_casApp_noMemory; } @@ -62,10 +62,10 @@ caStatus exAsyncPV::write ( const casCtx &ctx, const gdd &valueIn ) // // exAsyncWriteIO::exAsyncWriteIO() // -exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn, - const gdd &valueIn ) : +exAsyncWriteIO::exAsyncWriteIO ( exServer & cas, + const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn ) : casAsyncWriteIO ( ctxIn ), pv ( pvIn ), - timer ( pvIn.getCAS()->createTimer () ), pValue(valueIn) + timer ( cas.createTimer () ), pValue(valueIn) { this->timer.start ( *this, 0.1 ); } @@ -76,9 +76,7 @@ exAsyncWriteIO::exAsyncWriteIO ( const casCtx &ctxIn, exAsyncPV &pvIn, exAsyncWriteIO::~exAsyncWriteIO() { this->pv.removeIO(); - if ( this->pv.getCAS() ) { - this->timer.destroy (); - } + this->timer.destroy (); } // @@ -88,7 +86,7 @@ exAsyncWriteIO::~exAsyncWriteIO() epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* currentTime */ ) { caStatus status; - status = this->pv.update ( this->pValue ); + status = this->pv.update ( *this->pValue ); this->postIOCompletion ( status ); return noRestart; } @@ -96,10 +94,10 @@ epicsTimerNotify::expireStatus exAsyncWriteIO::expire ( const epicsTime & /* cur // // exAsyncReadIO::exAsyncReadIO() // -exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn, - gdd &protoIn ) : +exAsyncReadIO::exAsyncReadIO ( exServer & cas, const casCtx & ctxIn, + exAsyncPV & pvIn, gdd & protoIn ) : casAsyncReadIO ( ctxIn ), pv ( pvIn ), - timer ( pvIn.getCAS()->createTimer() ), pProto ( protoIn ) + timer ( cas.createTimer() ), pProto ( protoIn ) { this->timer.start ( *this, 0.1 ); } @@ -110,9 +108,7 @@ exAsyncReadIO::exAsyncReadIO ( const casCtx &ctxIn, exAsyncPV &pvIn, exAsyncReadIO::~exAsyncReadIO() { this->pv.removeIO (); - if ( this->pv.getCAS() ) { - this->timer.destroy (); - } + this->timer.destroy (); } diff --git a/src/cas/example/simple/exPV.cc b/src/cas/example/simple/exPV.cc index 944579f25..6be31c31d 100644 --- a/src/cas/example/simple/exPV.cc +++ b/src/cas/example/simple/exPV.cc @@ -30,8 +30,10 @@ class exFixedStringDestructor: public gddDestructor { // // exPV::exPV() // -exPV::exPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) : - timer ( this->getCAS()->createTimer() ), +exPV::exPV ( exServer & casIn, pvInfo & setup, + bool preCreateFlag, bool scanOnIn ) : + cas ( casIn ), + timer ( cas.createTimer() ), info ( setup ), interest ( false ), preCreate ( preCreateFlag ), @@ -77,17 +79,14 @@ void exPV::destroy() // // exPV::update() // -caStatus exPV::update(smartConstGDDPointer pValueIn) +caStatus exPV::update ( const gdd & valueIn ) { - caServer *pCAS = this->getCAS(); - caStatus cas; - # if DEBUG printf("Setting %s too:\n", this->info.getName().string()); valueIn.dump(); # endif - cas = this->updateValue (pValueIn); + caStatus cas = this->updateValue ( valueIn ); if ( cas || ( ! this->pValue.valid() ) ) { return cas; } @@ -95,9 +94,10 @@ caStatus exPV::update(smartConstGDDPointer pValueIn) // // post a value change event // - if (this->interest==true && pCAS!=NULL) { - casEventMask select(pCAS->valueEventMask()|pCAS->logEventMask()); - this->postEvent (select, *this->pValue); + caServer * pCAS = this->getCAS(); + if ( this->interest == true && pCAS != NULL ) { + casEventMask select ( pCAS->valueEventMask() | pCAS->logEventMask() ); + this->postEvent ( select, valueIn ); } return S_casApp_success; @@ -129,16 +129,13 @@ aitEnum exPV::bestExternalType () const // // exPV::interestRegister() // -caStatus exPV::interestRegister() +caStatus exPV::interestRegister () { - caServer *pCAS = this->getCAS(); - - if ( ! pCAS ) { + if ( ! this->getCAS() ) { return S_casApp_success; } this->interest = true; - if ( this->scanOn && this->getScanPeriod() > 0.0 && this->getScanPeriod() < this->timer.getExpireDelay() ) { this->timer.start ( *this, this->getScanPeriod() ); @@ -174,7 +171,7 @@ void exPV::show ( unsigned level ) const // // exPV::initFT() // -void exPV::initFT() +void exPV::initFT () { if ( exPV::hasBeenInitialized ) { return; @@ -203,7 +200,7 @@ void exPV::initFT() // // exPV::getPrecision() // -caStatus exPV::getPrecision(gdd &prec) +caStatus exPV::getPrecision ( gdd & prec ) { prec.put(4u); return S_cas_success; @@ -212,7 +209,7 @@ caStatus exPV::getPrecision(gdd &prec) // // exPV::getHighLimit() // -caStatus exPV::getHighLimit(gdd &value) +caStatus exPV::getHighLimit ( gdd & value ) { value.put(info.getHopr()); return S_cas_success; @@ -221,7 +218,7 @@ caStatus exPV::getHighLimit(gdd &value) // // exPV::getLowLimit() // -caStatus exPV::getLowLimit(gdd &value) +caStatus exPV::getLowLimit ( gdd & value ) { value.put(info.getLopr()); return S_cas_success; @@ -230,7 +227,7 @@ caStatus exPV::getLowLimit(gdd &value) // // exPV::getUnits() // -caStatus exPV::getUnits(gdd &units) +caStatus exPV::getUnits( gdd & units ) { aitString str("furlongs", aitStrRefConstImortal); units.put(str); @@ -283,7 +280,7 @@ caStatus exPV::getEnums ( gdd & enumsIn ) // // exPV::getValue() // -caStatus exPV::getValue(gdd &value) +caStatus exPV::getValue ( gdd & value ) { caStatus status; @@ -309,18 +306,18 @@ caStatus exPV::getValue(gdd &value) // exPV::write() // (synchronous default) // -caStatus exPV::write (const casCtx &, const gdd &valueIn) +caStatus exPV::write ( const casCtx &, const gdd & valueIn ) { - return this->update (valueIn); + return this->update ( valueIn ); } // // exPV::read() // (synchronous default) // -caStatus exPV::read (const casCtx &, gdd &protoIn) +caStatus exPV::read ( const casCtx &, gdd & protoIn ) { - return this->ft.read (*this, protoIn); + return this->ft.read ( *this, protoIn ); } // @@ -328,11 +325,11 @@ caStatus exPV::read (const casCtx &, gdd &protoIn) // // for access control - optional // -casChannel *exPV::createChannel (const casCtx &ctx, +casChannel *exPV::createChannel ( const casCtx &ctx, const char * const /* pUserName */, - const char * const /* pHostName */) + const char * const /* pHostName */ ) { - return new exChannel (ctx); + return new exChannel ( ctx ); } // @@ -340,7 +337,7 @@ casChannel *exPV::createChannel (const casCtx &ctx, // // special gddDestructor guarantees same form of new and delete // -void exFixedStringDestructor::run (void *pUntyped) +void exFixedStringDestructor::run ( void * pUntyped ) { aitFixedString *ps = (aitFixedString *) pUntyped; delete [] ps; diff --git a/src/cas/example/simple/exScalarPV.cc b/src/cas/example/simple/exScalarPV.cc index 1b3731435..4ac60ac8a 100644 --- a/src/cas/example/simple/exScalarPV.cc +++ b/src/cas/example/simple/exScalarPV.cc @@ -49,9 +49,9 @@ void exScalarPV::scan() // throughput under sunos4 because gettimeofday() is // slow) // - this->currentTime = epicsTime::getCurrent(); + this->currentTime = epicsTime::getCurrent (); - pDD = new gddScalar (gddAppType_value, aitEnumFloat64); + pDD = new gddScalar ( gddAppType_value, aitEnumFloat64 ); if ( ! pDD.valid () ) { return; } @@ -59,27 +59,27 @@ void exScalarPV::scan() // // smart pointer class manages reference count after this point // - gddStatus = pDD->unreference(); - assert (!gddStatus); + gddStatus = pDD->unreference (); + assert ( ! gddStatus ); - radians = (rand () * 2.0 * myPI)/RAND_MAX; + radians = ( rand () * 2.0 * myPI ) / RAND_MAX; if ( this->pValue.valid () ) { this->pValue->getConvert(newValue); } else { newValue = 0.0f; } - newValue += (float) (sin (radians) / 10.0); - limit = (float) this->info.getHopr(); - newValue = tsMin (newValue, limit); - limit = (float) this->info.getLopr(); - newValue = tsMax (newValue, limit); + newValue += (float) ( sin (radians) / 10.0 ); + limit = (float) this->info.getHopr (); + newValue = tsMin ( newValue, limit ); + limit = (float) this->info.getLopr (); + newValue = tsMax ( newValue, limit ); *pDD = newValue; aitTimeStamp gddts = this->currentTime; - pDD->setTimeStamp (&gddts); - status = this->update (pDD); + pDD->setTimeStamp ( & gddts ); + status = this->update ( *pDD ); if (status!=S_casApp_success) { - errMessage (status, "scalar scan update failed\n"); + errMessage ( status, "scalar scan update failed\n" ); } } @@ -95,21 +95,25 @@ void exScalarPV::scan() // result in each value change events retaining an // independent value on the event queue. // -caStatus exScalarPV::updateValue (smartConstGDDPointer pValueIn) +caStatus exScalarPV::updateValue ( const gdd & valueIn ) { - if ( ! pValueIn.valid () ) { - return S_casApp_undefined; - } - // // Really no need to perform this check since the // server lib verifies that all requests are in range // - if (!pValueIn->isScalar()) { + if ( ! valueIn.isScalar() ) { return S_casApp_outOfBounds; } - this->pValue = pValueIn; + if ( ! pValue.valid () ) { + this->pValue = new gddScalar ( + gddAppType_value, aitEnumFloat64 ); + if ( ! pValue.valid () ) { + return S_casApp_noMemory; + } + } + + this->pValue->put ( & valueIn ); return S_casApp_success; } diff --git a/src/cas/example/simple/exServer.cc b/src/cas/example/simple/exServer.cc index 8607bf7dd..52a82129a 100644 --- a/src/cas/example/simple/exServer.cc +++ b/src/cas/example/simple/exServer.cc @@ -44,9 +44,10 @@ pvInfo exServer::bloaty (-1.0, "bloaty", 10.0f, -10.0f, aitEnumFloat64, excasIoS // exServer::exServer() // exServer::exServer ( const char * const pvPrefix, - unsigned aliasCount, bool scanOnIn ) : - simultAsychIOCount (0u), - scanOn (scanOnIn) + unsigned aliasCount, bool scanOnIn, + bool asyncScan ) : + pTimerQueue ( 0 ), simultAsychIOCount ( 0u ), + scanOn ( scanOnIn ) { unsigned i; exPV *pPV; @@ -58,6 +59,16 @@ exServer::exServer ( const char * const pvPrefix, exPV::initFT(); + if ( asyncScan ) { + unsigned timerPriotity; + epicsThreadBooleanStatus etbs = epicsThreadLowestPriorityLevelAbove ( + epicsThreadGetPrioritySelf (), & timerPriotity ); + if ( etbs != epicsThreadBooleanStatusSuccess ) { + timerPriotity = epicsThreadGetPrioritySelf (); + } + this->pTimerQueue = & epicsTimerQueueActive::allocate ( false, timerPriotity ); + } + // // pre-create all of the simple PVs that this server will export // @@ -236,10 +247,31 @@ pvAttachReturn exServer::pvAttach // X aCC 361 } } +// +// exServer::setDebugLevel () +// +void exServer::setDebugLevel ( unsigned level ) +{ + this->caServer::setDebugLevel ( level ); +} + +// +// exServer::createTimer () +// +class epicsTimer & exServer::createTimer () +{ + if ( this->pTimerQueue ) { + return this->pTimerQueue->createTimer (); + } + else { + return this->caServer::createTimer (); + } +} + // // pvInfo::createPV() // -exPV *pvInfo::createPV ( exServer & /*cas*/, +exPV *pvInfo::createPV ( exServer & cas, bool preCreateFlag, bool scanOn ) { if (this->pPV) { @@ -256,10 +288,10 @@ exPV *pvInfo::createPV ( exServer & /*cas*/, if (this->elementCount==1u) { switch (this->ioType){ case excasIoSync: - pNewPV = new exScalarPV ( *this, preCreateFlag, scanOn ); + pNewPV = new exScalarPV ( cas, *this, preCreateFlag, scanOn ); break; case excasIoAsync: - pNewPV = new exAsyncPV ( *this, preCreateFlag, scanOn ); + pNewPV = new exAsyncPV ( cas, *this, preCreateFlag, scanOn ); break; default: pNewPV = NULL; @@ -268,7 +300,7 @@ exPV *pvInfo::createPV ( exServer & /*cas*/, } else { if ( this->ioType == excasIoSync ) { - pNewPV = new exVectorPV ( *this, preCreateFlag, scanOn ); + pNewPV = new exVectorPV ( cas, *this, preCreateFlag, scanOn ); } else { pNewPV = NULL; diff --git a/src/cas/example/simple/exServer.h b/src/cas/example/simple/exServer.h index 2235adfc3..56ad85814 100644 --- a/src/cas/example/simple/exServer.h +++ b/src/cas/example/simple/exServer.h @@ -38,6 +38,7 @@ // // EPICS // +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #include "gddAppFuncTable.h" #include "epicsTimer.h" #include "casdef.h" @@ -124,7 +125,8 @@ private: class exPV : public casPV, public epicsTimerNotify, public tsSLNode < exPV > { public: - exPV ( pvInfo & setup, bool preCreateFlag, bool scanOn ); + exPV ( exServer & cas, pvInfo & setup, + bool preCreateFlag, bool scanOn ); virtual ~exPV(); void show ( unsigned level ) const; @@ -158,7 +160,7 @@ public: // // This gets called when the pv gets a new value // - caStatus update ( smartConstGDDPointer pValue ); + caStatus update ( const gdd & ); // // Gets called when we add noise to the current value @@ -190,7 +192,8 @@ public: const char * const pHostName ); protected: - smartConstGDDPointer pValue; + smartGDDPointer pValue; + exServer & cas; epicsTimer & timer; pvInfo & info; bool interest; @@ -198,7 +201,7 @@ protected: bool scanOn; static epicsTime currentTime; - virtual caStatus updateValue ( smartConstGDDPointer pValue ) = 0; + virtual caStatus updateValue ( const gdd & ) = 0; private: @@ -229,11 +232,13 @@ private: // class exScalarPV : public exPV { public: - exScalarPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) : - exPV ( setup, preCreateFlag, scanOnIn) {} + exScalarPV ( exServer & cas, pvInfo &setup, + bool preCreateFlag, bool scanOnIn ) : + exPV ( cas, setup, + preCreateFlag, scanOnIn) {} void scan(); private: - caStatus updateValue (smartConstGDDPointer pValue); + caStatus updateValue ( const gdd & ); }; // @@ -241,36 +246,45 @@ private: // class exVectorPV : public exPV { public: - exVectorPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ) : - exPV ( setup, preCreateFlag, scanOnIn) {} + exVectorPV ( exServer & cas, pvInfo &setup, + bool preCreateFlag, bool scanOnIn ) : + exPV ( cas, setup, + preCreateFlag, scanOnIn) {} void scan(); unsigned maxDimension() const; aitIndex maxBound (unsigned dimension) const; private: - caStatus updateValue (smartConstGDDPointer pValue); + caStatus updateValue ( const gdd & ); }; // // exServer // -class exServer : public caServer { +class exServer : private caServer { public: exServer ( const char * const pvPrefix, - unsigned aliasCount, bool scanOn ); + unsigned aliasCount, bool scanOn, + bool asyncScan ); ~exServer (); void show ( unsigned level ) const; - pvExistReturn pvExistTest ( const casCtx &, const char * pPVName ); - pvAttachReturn pvAttach ( const casCtx &, const char * pPVName ); - void installAliasName ( pvInfo & info, const char * pAliasName ); - inline void removeAliasName ( pvEntry & entry ); - void removeIO(); + void removeIO (); + void removeAliasName ( pvEntry & entry ); + + class epicsTimer & createTimer (); + void setDebugLevel ( unsigned level ); + private: resTable < pvEntry, stringId > stringResTbl; + epicsTimerQueueActive * pTimerQueue; unsigned simultAsychIOCount; bool scanOn; + void installAliasName ( pvInfo & info, const char * pAliasName ); + pvExistReturn pvExistTest ( const casCtx &, const char * pPVName ); + pvAttachReturn pvAttach ( const casCtx &, const char * pPVName ); + // // list of pre-created PVs // @@ -292,7 +306,8 @@ private: // class exAsyncPV : public exScalarPV { public: - exAsyncPV ( pvInfo &setup, bool preCreateFlag, bool scanOnIn ); + exAsyncPV ( exServer & cas, pvInfo &setup, + bool preCreateFlag, bool scanOnIn ); caStatus read ( const casCtx & ctxIn, gdd & protoIn ); caStatus write ( const casCtx & ctxIn, const gdd & value ); void removeIO(); @@ -318,7 +333,7 @@ private: // class exAsyncWriteIO : public casAsyncWriteIO, public epicsTimerNotify { public: - exAsyncWriteIO ( const casCtx & ctxIn, exAsyncPV & pvIn, const gdd & valueIn ); + exAsyncWriteIO ( exServer &, const casCtx & ctxIn, exAsyncPV &, const gdd & ); ~exAsyncWriteIO (); private: exAsyncPV & pv; @@ -332,7 +347,7 @@ private: // class exAsyncReadIO : public casAsyncReadIO, public epicsTimerNotify { public: - exAsyncReadIO ( const casCtx & ctxIn, exAsyncPV & pvIn, gdd & protoIn ); + exAsyncReadIO ( exServer &, const casCtx &, exAsyncPV &, gdd & ); virtual ~exAsyncReadIO (); private: exAsyncPV & pv; @@ -519,9 +534,9 @@ inline void exServer::removeIO() } } -inline exAsyncPV::exAsyncPV ( pvInfo & setup, bool preCreateFlag, - bool scanOnIn ) : - exScalarPV ( setup, preCreateFlag, scanOnIn ), +inline exAsyncPV::exAsyncPV ( exServer & cas, pvInfo & setup, + bool preCreateFlag, bool scanOnIn ) : + exScalarPV ( cas, setup, preCreateFlag, scanOnIn ), simultAsychIOCount ( 0u ) { } diff --git a/src/cas/example/simple/exVectorPV.cc b/src/cas/example/simple/exVectorPV.cc index 829f8a258..869027093 100644 --- a/src/cas/example/simple/exVectorPV.cc +++ b/src/cas/example/simple/exVectorPV.cc @@ -141,8 +141,8 @@ void exVectorPV::scan() *(pF++) = newValue; } - status = this->update (pDD); - if (status!=S_casApp_success) { + status = this->update ( *pDD ); + if ( status != S_casApp_success ) { errMessage (status, "vector scan update failed\n"); } } @@ -161,16 +161,8 @@ void exVectorPV::scan() // this may result in too much memory consumtion on // the event queue. // -caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn) +caStatus exVectorPV::updateValue ( const gdd & value ) { - gddStatus gdds; - smartGDDPointer pNewValue; - exVecDestructor *pDest; - unsigned i; - - if ( ! pValueIn.valid () ) { - return S_casApp_undefined; - } // // Check bounds of incoming request @@ -180,50 +172,47 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn) // Perhaps much of this is unnecessary since the // server lib checks the bounds of all requests // - if (pValueIn->isAtomic()) { - if (pValueIn->dimension()!=1u) { + if ( value.isAtomic()) { + if ( value.dimension() != 1u ) { return S_casApp_badDimension; } - const gddBounds* pb = pValueIn->getBounds(); - if (pb[0u].first()!=0u) { + const gddBounds* pb = value.getBounds (); + if ( pb[0u].first() != 0u ) { return S_casApp_outOfBounds; } - else if (pb[0u].size()>this->info.getElementCount()) { + else if ( pb[0u].size() > this->info.getElementCount() ) { return S_casApp_outOfBounds; } } - else if (!pValueIn->isScalar()) { + else if ( ! value.isScalar() ) { // // no containers // return S_casApp_outOfBounds; } - - aitFloat64 *pF; - int gddStatus; - + // // Create a new array data descriptor // (so that old values that may be referenced on the // event queue are not replaced) // - pNewValue = new gddAtomic (gddAppType_value, aitEnumFloat64, - 1u, this->info.getElementCount()); - if ( ! pNewValue.valid () ) { + smartGDDPointer pNewValue ( new gddAtomic ( gddAppType_value, aitEnumFloat64, + 1u, this->info.getElementCount() ) ); + if ( ! pNewValue.valid() ) { return S_casApp_noMemory; } - + // // smart pointer class takes care of the reference count // from here down // - gddStatus = pNewValue->unreference(); - assert (!gddStatus); - + gddStatus gdds = pNewValue->unreference( ); + assert ( ! gdds ); + // // allocate array buffer // - pF = new aitFloat64 [this->info.getElementCount()]; + aitFloat64 * pF = new aitFloat64 [this->info.getElementCount()]; if (!pF) { return S_casApp_noMemory; } @@ -233,11 +222,11 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn) // if no old values exist // unsigned count = this->info.getElementCount(); - for ( i = 0u; i < count; i++ ) { + for ( unsigned i = 0u; i < count; i++ ) { pF[i] = 0.0f; } - pDest = new exVecDestructor; + exVecDestructor * pDest = new exVecDestructor; if (!pDest) { delete [] pF; return S_casApp_noMemory; @@ -247,13 +236,13 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn) // install the buffer into the DD // (do this before we increment pF) // - pNewValue->putRef(pF, pDest); + pNewValue->putRef ( pF, pDest ); // // copy in the values that they are writing // - gdds = pNewValue->put( & (*pValueIn) ); - if (gdds) { + gdds = pNewValue->put( & value ); + if ( gdds ) { return S_cas_noConvert; } @@ -267,8 +256,8 @@ caStatus exVectorPV::updateValue(smartConstGDDPointer pValueIn) // // special gddDestructor guarantees same form of new and delete // -void exVecDestructor::run (void *pUntyped) +void exVecDestructor::run ( void *pUntyped ) { - aitFloat32 *pf = (aitFloat32 *) pUntyped; + aitFloat32 * pf = reinterpret_cast < aitFloat32 * > ( pUntyped ); delete [] pf; } diff --git a/src/cas/example/simple/main.cc b/src/cas/example/simple/main.cc index 538041ac1..ea1d921db 100644 --- a/src/cas/example/simple/main.cc +++ b/src/cas/example/simple/main.cc @@ -25,37 +25,40 @@ extern int main (int argc, const char **argv) double executionTime; char pvPrefix[128] = ""; unsigned aliasCount = 1u; - unsigned scanOnAsUnsignedInt = true; + unsigned scanOn = true; + unsigned syncScan = true; char arraySize[64] = ""; - bool scanOn; bool forever = true; int i; for ( i = 1; i < argc; i++ ) { - if (sscanf(argv[i], "-d %u", &debugLevel)==1) { + if ( sscanf(argv[i], "-d %u", & debugLevel ) == 1 ) { continue; } - if (sscanf(argv[i],"-t %lf", &executionTime)==1) { + if ( sscanf ( argv[i],"-t %lf", & executionTime ) == 1 ) { forever = false; continue; } - if (sscanf(argv[i],"-p %127s", pvPrefix)==1) { + if ( sscanf ( argv[i], "-p %127s", pvPrefix ) == 1 ) { continue; } - if (sscanf(argv[i],"-c %u", &aliasCount)==1) { + if ( sscanf ( argv[i],"-c %u", & aliasCount ) == 1 ) { continue; } - if (sscanf(argv[i],"-s %u", &scanOnAsUnsignedInt)==1) { + if ( sscanf ( argv[i],"-s %u", & scanOn ) == 1 ) { continue; } - if (sscanf(argv[i],"-a %63s", arraySize)==1) { + if ( sscanf ( argv[i],"-a %63s", arraySize ) == 1 ) { + continue; + } + if ( sscanf ( argv[i],"-ss %u", & syncScan ) == 1 ) { continue; } printf ("\"%s\"?\n", argv[i]); printf ( "usage: %s [-d -t -p " - "-c -s<1=scan on (default), 0=scan off]> " - "-a]\n", + "-c -s<1=scan on (default), 0=scan off> " + "-ss<1=synchronous scan (default), 0=asynchronous scan>]\n", argv[0]); return (1); @@ -65,15 +68,9 @@ extern int main (int argc, const char **argv) epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", arraySize ); } - if (scanOnAsUnsignedInt) { - scanOn = true; - } - else { - scanOn = false; - } - try { - pCAS = new exServer ( pvPrefix, aliasCount, scanOn ); + pCAS = new exServer ( pvPrefix, aliasCount, + scanOn != 0, syncScan == 0 ); } catch ( ... ) { errlogPrintf ( "Server initialization error\n" ); diff --git a/src/cas/generic/beaconAnomalyGovernor.cc b/src/cas/generic/beaconAnomalyGovernor.cc index 52b4c1006..97e192f85 100644 --- a/src/cas/generic/beaconAnomalyGovernor.cc +++ b/src/cas/generic/beaconAnomalyGovernor.cc @@ -16,9 +16,12 @@ * 505 665 1831 */ +#include "fdManager.h" + +#define epicsExportSharedSymbols +#include "caServerI.h" #include "beaconAnomalyGovernor.h" #include "beaconTimer.h" -#include "server.h" // // the minimum period between beacon anomalies diff --git a/src/cas/generic/beaconAnomalyGovernor.h b/src/cas/generic/beaconAnomalyGovernor.h index 5b61db8ea..7c8605a0f 100644 --- a/src/cas/generic/beaconAnomalyGovernor.h +++ b/src/cas/generic/beaconAnomalyGovernor.h @@ -19,9 +19,20 @@ #ifndef beaconAnomalyGovernorh #define beaconAnomalyGovernorh +#ifdef epicsExportSharedSymbols +# define epicsExportSharedSymbols_beaconAnomalyGovernorh +# undef epicsExportSharedSymbols +#endif + +// external headers included here #include "epicsTimer.h" #include "epicsMutex.h" +#ifdef epicsExportSharedSymbols_beaconAnomalyGovernorh +# define epicsExportSharedSymbols +# include "shareLib.h" +#endif + class caServerI; class beaconAnomalyGovernor : public epicsTimerNotify { diff --git a/src/cas/generic/beaconTimer.cc b/src/cas/generic/beaconTimer.cc index b4623e93d..579c275ff 100644 --- a/src/cas/generic/beaconTimer.cc +++ b/src/cas/generic/beaconTimer.cc @@ -16,7 +16,11 @@ * 505 665 1831 */ -#include "server.h" +#include "fdManager.h" +#include "envDefs.h" + +#define epicsExportSharedSymbols +#include "caServerI.h" #include "beaconTimer.h" // the maximum beacon period if EPICS_CA_BEACON_PERIOD isnt available diff --git a/src/cas/generic/beaconTimer.h b/src/cas/generic/beaconTimer.h index b5762d118..80bac9cc2 100644 --- a/src/cas/generic/beaconTimer.h +++ b/src/cas/generic/beaconTimer.h @@ -19,14 +19,22 @@ #ifndef beaconTimerh #define beaconTimerh +#ifdef epicsExportSharedSymbols +# define epicsExportSharedSymbols_beaconTimerh +# undef epicsExportSharedSymbols +#endif + +// external headers included here #include "epicsTimer.h" #include "caProto.h" +#ifdef epicsExportSharedSymbols_beaconTimerh +# define epicsExportSharedSymbols +# include "shareLib.h" +#endif + class caServerI; -// -// beaconTimer -// class beaconTimer : public epicsTimerNotify { public: beaconTimer ( caServerI & casIn ); diff --git a/src/cas/generic/caCommonDef.h b/src/cas/generic/caCommonDef.h deleted file mode 100644 index aad85cd64..000000000 --- a/src/cas/generic/caCommonDef.h +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#ifndef includeCaCommonDefH -#define includeCaCommonDefH - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef NELEMENTS -#define NELEMENTS(array) (sizeof(array)/sizeof((array)[0])) -#endif - -#ifndef LOCAL -#define LOCAL static -#endif - -#ifndef min -#define min(A,B) ((A)>(B)?(B):(A)) -#endif - -#ifndef max -#define max(A,B) ((A)<(B)?(B):(A)) -#endif - -#endif /* ifndef includeCaCommonDefH (last line in this file) */ - diff --git a/src/cas/generic/caNetAddr.cc b/src/cas/generic/caNetAddr.cc index ea545082b..b4f47e49e 100644 --- a/src/cas/generic/caNetAddr.cc +++ b/src/cas/generic/caNetAddr.cc @@ -171,12 +171,12 @@ struct sockaddr caNetAddr::getSock() const caNetAddr::operator sockaddr_in () const { - return this->getSockIP(); + return this->getSockIP (); } caNetAddr::operator sockaddr () const { - return this->getSock(); + return this->getSock (); } void caNetAddr::selfTest () diff --git a/src/cas/generic/caNetAddr.h b/src/cas/generic/caNetAddr.h index 7248de3f8..01dc6c3ba 100644 --- a/src/cas/generic/caNetAddr.h +++ b/src/cas/generic/caNetAddr.h @@ -11,10 +11,9 @@ // caNetAddr // // special cas specific network address class so: -// 1) we dont drag BSD socket headers into -// the server tool +// 1) we dont drag BSD socket headers into the server tool // 2) we are not prevented from using other networking services -// besides sockets in the future +// besides sockets in the future // #ifndef caNetAddrH @@ -30,6 +29,8 @@ # define epicsExportSharedSymbols # include "shareLib.h" # endif +#else +# include "shareLib.h" #endif class epicsShareClass caNetAddr { diff --git a/src/cas/generic/caServer.cc b/src/cas/generic/caServer.cc index ca3b69177..8069b87ee 100644 --- a/src/cas/generic/caServer.cc +++ b/src/cas/generic/caServer.cc @@ -17,13 +17,11 @@ #include "dbMapper.h" // ait to dbr types #include "gddAppTable.h" // EPICS application type table +#include "fdManager.h" -#include "server.h" -#include "caServerIIL.h" // caServerI in line func +#define epicsExportSharedSymbols +#include "caServerI.h" -// -// caServer::caServer() -// caServer::caServer () { static bool init = false; @@ -33,12 +31,9 @@ caServer::caServer () init = true; } - this->pCAS = new caServerI(*this); + this->pCAS = new caServerI ( *this ); } -// -// caServer::~caServer() -// caServer::~caServer() { if (this->pCAS) { @@ -47,36 +42,22 @@ caServer::~caServer() } } -// -// caServer::pvExistTest() -// pvExistReturn caServer::pvExistTest (const casCtx &, const char *) { return pverDoesNotExistHere; } -// -// caServer::createPV() -// pvCreateReturn caServer::createPV (const casCtx &, const char *) { return S_casApp_pvNotFound; } -// -// caServer::pvAttach() -// pvAttachReturn caServer::pvAttach (const casCtx &ctx, const char *pAliasName) { - // // remain backwards compatible (call deprecated routine) - // return this->createPV(ctx, pAliasName); } -// -// caServer::registerEvent() -// casEventMask caServer::registerEvent (const char *pName) // X aCC 361 { if (this->pCAS) { @@ -89,9 +70,6 @@ casEventMask caServer::registerEvent (const char *pName) // X aCC 361 } } -// -// caServer::show() -// void caServer::show(unsigned level) const { if (this->pCAS) { @@ -102,9 +80,6 @@ void caServer::show(unsigned level) const } } -// -// caServer::setDebugLevel() -// void caServer::setDebugLevel (unsigned level) { if (pCAS) { @@ -115,9 +90,6 @@ void caServer::setDebugLevel (unsigned level) } } -// -// caServer::getDebugLevel() -// unsigned caServer::getDebugLevel () const // X aCC 361 { if (pCAS) { @@ -129,9 +101,6 @@ unsigned caServer::getDebugLevel () const // X aCC 361 } } -// -// caServer::valueEventMask () -// casEventMask caServer::valueEventMask () const // X aCC 361 { if (pCAS) { @@ -143,9 +112,6 @@ casEventMask caServer::valueEventMask () const // X aCC 361 } } -// -// caServer::logEventMask () -// casEventMask caServer::logEventMask () const // X aCC 361 { if (pCAS) { @@ -157,44 +123,32 @@ casEventMask caServer::logEventMask () const // X aCC 361 } } -// -// caServer::alarmEventMask () -// casEventMask caServer::alarmEventMask () const // X aCC 361 { - if (pCAS) { - return this->pCAS->alarmEventMask(); + if ( pCAS ) { + return this->pCAS->alarmEventMask (); } else { - printf("caServer:: no server internals attached\n"); - return casEventMask(); + printf ( "caServer:: no server internals attached\n" ); + return casEventMask (); } } -// -// caServer::alarmEventMask () -// class epicsTimer & caServer::createTimer () { return fileDescriptorManager.createTimer (); } -// -// caServer::subscriptionEventsProcessed -// unsigned caServer::subscriptionEventsProcessed () const // X aCC 361 { if ( pCAS ) { - return this->pCAS->subscriptionEventsProcessed(); + return this->pCAS->subscriptionEventsProcessed (); } else { return 0u; } } -// -// caServer::subscriptionEventsPosted -// unsigned caServer::subscriptionEventsPosted () const // X aCC 361 { if ( pCAS ) { @@ -211,22 +165,3 @@ void caServer::generateBeaconAnomaly () this->pCAS->generateBeaconAnomaly (); } } - -// -// casRes::~casRes() -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -casRes::~casRes() -{ -} - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -casEvent::~casEvent() -{ -} - diff --git a/src/cas/generic/caServerI.cc b/src/cas/generic/caServerI.cc index 9c085f4bb..4e7d41d53 100644 --- a/src/cas/generic/caServerI.cc +++ b/src/cas/generic/caServerI.cc @@ -22,33 +22,34 @@ #include "addrList.h" +#define epicsExportSharedSymbols #define caServerGlobal -#include "server.h" -#include "casCtxIL.h" // casCtx in line func +#include "caServerI.h" #include "beaconTimer.h" #include "beaconAnomalyGovernor.h" +#include "casStreamOS.h" +#include "casIntfOS.h" +// include a version string for POSIX systems static const char * pVersionCAS = - "@(#) " EPICS_VERSION_STRING ", CA Portable Server Library " + "@(#) " EPICS_VERSION_STRING + ", CA Portable Server Library " "$Date$"; -// -// caServerI::caServerI() -// -caServerI::caServerI (caServer &tool) : +caServerI::caServerI ( caServer & tool ) : adapter (tool), beaconTmr ( * new beaconTimer ( *this ) ), beaconAnomalyGov ( * new beaconAnomalyGovernor ( *this ) ), - debugLevel (0u), - nEventsProcessed (0u), - nEventsPosted (0u) + debugLevel ( 0u ), + nEventsProcessed ( 0u ), + nEventsPosted ( 0u ) { assert ( & adapter != NULL ); // create predefined event types - this->valueEvent = registerEvent ("value"); - this->logEvent = registerEvent ("log"); - this->alarmEvent = registerEvent ("alarm"); + this->valueEvent = registerEvent ( "value" ); + this->logEvent = registerEvent ( "log" ); + this->alarmEvent = registerEvent ( "alarm" ); this->locateInterfaces (); @@ -61,26 +62,14 @@ caServerI::caServerI (caServer &tool) : return; } -/* - * caServerI::~caServerI() - */ caServerI::~caServerI() { - epicsGuard < epicsMutex > locker ( this->mutex ); - delete & this->beaconAnomalyGov; delete & this->beaconTmr; // delete all clients - tsDLIter iter = this->clientList.firstIter (); - while ( iter.valid () ) { - tsDLIter tmp = iter; - ++tmp; - // - // destructor takes client out of list - // - delete iter.pointer (); - iter = tmp; + while ( casStrmClient * pClient = this->clientList.get() ) { + delete pClient; } casIntfOS *pIF; @@ -89,40 +78,29 @@ caServerI::~caServerI() } } -// -// caServerI::installClient() -// -void caServerI::installClient(casStrmClient *pClient) +void caServerI::destroyClient ( casStrmClient & client ) { - epicsGuard < epicsMutex > locker ( this->mutex ); - this->clientList.add(*pClient); + { + epicsGuard < epicsMutex > locker ( this->mutex ); + this->clientList.remove ( client ); + } + delete & client; } -// -// caServerI::removeClient() -// -void caServerI::removeClient (casStrmClient *pClient) -{ - epicsGuard < epicsMutex > locker ( this->mutex ); - this->clientList.remove (*pClient); -} - -// -// caServerI::connectCB() -// void caServerI::connectCB ( casIntfOS & intf ) { casStreamOS * pClient = intf.newStreamClient ( *this, this->clientBufMemMgr ); if ( pClient ) { + { + epicsGuard < epicsMutex > locker ( this->mutex ); + this->clientList.add ( *pClient ); + } pClient->sendVersion (); pClient->flush (); } } -// -// casVerifyFunc() -// -void casVerifyFunc (const char *pFile, unsigned line, const char *pExp) +void casVerifyFunc ( const char * pFile, unsigned line, const char * pExp ) { fprintf(stderr, "the expression \"%s\" didnt evaluate to boolean true \n", pExp); @@ -133,9 +111,6 @@ void casVerifyFunc (const char *pFile, unsigned line, const char *pExp) "Please forward above text to johill@lanl.gov - thanks\n"); } -// -// serverToolDebugFunc() -// void serverToolDebugFunc (const char *pFile, unsigned line, const char *pComment) { fprintf (stderr, @@ -143,9 +118,6 @@ void serverToolDebugFunc (const char *pFile, unsigned line, const char *pComment line, pFile, pComment); } -// -// caServerI::attachInterface() -// caStatus caServerI::attachInterface ( const caNetAddr & addrIn, bool autoBeaconAddr, bool addConfigBeaconAddr) { @@ -160,14 +132,10 @@ caStatus caServerI::attachInterface ( const caNetAddr & addrIn, return S_cas_success; } -// -// caServerI::sendBeacon() -// send a beacon over each configured address -// void caServerI::sendBeacon ( ca_uint32_t beaconNo ) { epicsGuard < epicsMutex > locker ( this->mutex ); - tsDLIter iter = this->intfList.firstIter (); + tsDLIter < casIntfOS > iter = this->intfList.firstIter (); while ( iter.valid () ) { iter->sendBeacon ( beaconNo ); iter++; @@ -179,47 +147,36 @@ void caServerI::generateBeaconAnomaly () this->beaconAnomalyGov.start (); } -// -// caServerI::lookupMonitor () -// -casMonitor * caServerI::lookupMonitor ( const caResId &idIn ) +void caServerI::destroyMonitor ( casMonitor & mon ) { - chronIntId tmpId ( idIn ); - - epicsGuard < epicsMutex > locker ( this->mutex ); - casRes * pRes = this->chronIntIdResTable::lookup ( tmpId ); - if ( pRes ) { - if ( pRes->resourceType() == casMonitorT ) { - // ok to avoid overhead of dynamic cast here because - // type code was checked above - return static_cast < casMonitor * > ( pRes ); - } - } - return 0; + mon.~casMonitor (); + this->casMonitorFreeList.release ( & mon ); } -// -// caServerI::lookupChannel () -// -casChannelI * caServerI::lookupChannel ( const caResId &idIn ) +void caServerI::updateEventsPostedCounter ( unsigned nNewPosts ) { - chronIntId tmpId ( idIn ); - - epicsGuard < epicsMutex > locker ( this->mutex ); - casRes * pRes = this->chronIntIdResTable::lookup ( tmpId ); - if ( pRes ) { - if ( pRes->resourceType() == casChanT ) { - // ok to avoid overhead of dynamic cast here because - // type code was checked above - return static_cast < casChannelI * > ( pRes ); - } - } - return 0; + epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex ); + this->nEventsPosted += nNewPosts; +} + +unsigned caServerI::subscriptionEventsPosted () const +{ + epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex ); + return this->nEventsPosted; +} + +void caServerI::incrEventsProcessedCounter () +{ + epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex ); + this->nEventsProcessed ++; +} + +unsigned caServerI::subscriptionEventsProcessed () const +{ + epicsGuard < epicsMutex > guard ( this->diagnosticCountersMutex ); + return this->nEventsProcessed; } -// -// caServerI::show() -// void caServerI::show (unsigned level) const { int bytes_reserved; @@ -232,13 +189,13 @@ void caServerI::show (unsigned level) const { epicsGuard < epicsMutex > locker ( this->mutex ); - tsDLIterConst iterCl = this->clientList.firstIter (); + tsDLIterConst < casStrmClient > iterCl = this->clientList.firstIter (); while ( iterCl.valid () ) { - iterCl->show (level); + iterCl->show ( level ); ++iterCl; } - tsDLIterConst iterIF = this->intfList.firstIter (); + tsDLIterConst < casIntfOS > iterIF = this->intfList.firstIter (); while ( iterIF.valid () ) { iterIF->casIntfOS::show ( level ); ++iterIF; @@ -270,22 +227,34 @@ void caServerI::show (unsigned level) const #endif printf( "The server's integer resource id conversion table:\n"); - { - epicsGuard < epicsMutex > locker ( this->mutex ); - this->chronIntIdResTable::show(level); - } } return; } -// -// casEventRegistry::~casEventRegistry() -// -// (must not be inline because it is virtual) -// +casMonitor & caServerI::casMonitorFactory ( + casChannelI & chan, caResId clientId, + const unsigned long count, const unsigned type, + const casEventMask & mask, + casMonitorCallbackInterface & cb ) +{ + casMonitor * pMon = + new ( this->casMonitorFreeList ) casMonitor + ( clientId, chan, count, type, mask, cb ); + return *pMon; +} + +void caServerI::casMonitorDestroy ( casMonitor & cm ) +{ + cm.~casMonitor (); + this->casMonitorFreeList.release ( & cm ); +} + casEventRegistry::~casEventRegistry() { this->traverse ( &casEventMaskEntry::destroy ); } + + + diff --git a/src/cas/generic/casAsyncIOI.cc b/src/cas/generic/casAsyncIOI.cc index ba75649b5..001a9653e 100644 --- a/src/cas/generic/casAsyncIOI.cc +++ b/src/cas/generic/casAsyncIOI.cc @@ -15,34 +15,26 @@ * 505 665 1831 */ +#include -#include "server.h" -#include "caServerIIL.h" // caServerI in line func -#include "casCoreClientIL.h" // casCoreClient in line func -#include "casEventSysIL.h" // casEventSys in line func -#include "casCtxIL.h" // casCtx in line func +#define epicsExportSharedSymbols +#include "casAsyncIOI.h" -// -// casAsyncIOI::casAsyncIOI() -// casAsyncIOI::casAsyncIOI ( const casCtx & ctx ) : client ( *ctx.getClient() ), inTheEventQueue ( false ), - posted ( false ), ioComplete ( false ), - serverDelete ( false ), duplicate ( false ) + posted ( false ), ioComplete ( false ) { // // catch situation where they create more than one // async IO object per request // if ( ! client.okToStartAsynchIO () ) { - errMessage ( S_cas_badParameter, - "- duplicate async IO creation" ); - this->duplicate = true; + throw std::logic_error ( + "server tool attempted to " + "start duplicate asynchronous IO" ); } } -// -// casAsyncIOI::~casAsyncIOI() // // ways this gets destroyed: // 1) io completes, this is pulled off the queue, and result @@ -71,92 +63,54 @@ casAsyncIOI::casAsyncIOI ( const casCtx & ctx ) : // casAsyncIOI::~casAsyncIOI() { - if ( ! this->serverDelete ) { - fprintf(stderr, - "WARNING: An async IO operation was deleted prematurely\n"); - fprintf(stderr, - "WARNING: by the server tool. This results in no IO cancel\n"); - fprintf(stderr, - "WARNING: message being sent to the client. Please cancel\n"); - fprintf(stderr, - "WARNING: IO by posting S_casApp_canceledAsyncIO instead of\n"); - fprintf(stderr, - "WARNING: by deleting the async IO object.\n"); - } - // // pulls itself out of the event queue // if it is installed there. // - this->client.removeFromEventQueue ( *this ); + this->client.removeFromEventQueue ( *this, this->inTheEventQueue ); } // -// casAsyncIOI::cbFunc() // o called when IO completion event reaches top of event queue // o clients lock is applied when calling this // -caStatus casAsyncIOI::cbFunc ( casCoreClient & ) +caStatus casAsyncIOI::cbFunc ( + casCoreClient &, epicsGuard < epicsMutex > & guard ) { - this->inTheEventQueue = false; - caStatus status = this->cbFuncAsyncIO(); + caStatus status = S_cas_success; + { + this->inTheEventQueue = false; - if (status == S_cas_sendBlocked) { - // - // causes this op to be pushed back on the queue - // - this->inTheEventQueue = true; - return status; - } - else if (status != S_cas_success) { - errMessage (status, "Asynch IO completion failed"); - } + { + epicsGuardRelease < epicsMutex > unlocker ( guard ); + status = this->cbFuncAsyncIO (); + } - this->ioComplete = true; + if ( status == S_cas_sendBlocked ) { + // + // causes this op to be pushed back on the queue + // + this->inTheEventQueue = true; + return status; + } + else if ( status != S_cas_success ) { + errMessage ( status, "Asynch IO completion failed" ); + } - // - // dont use "this" after potentially destroying the - // object here - // - this->serverDestroy(); + this->ioComplete = true; + } + + this->client.getCAS().ioBlockedList::signal (); + + // dont use "this" after destroying the object here + delete this; return S_cas_success; } -void casAsyncIOI::eventSysDestroyNotify ( casCoreClient & ) +caStatus casAsyncIOI::insertEventQueue () { - this->serverDestroy(); -} - -// -// casAsyncIOI::postIOCompletionI () -// -caStatus casAsyncIOI::postIOCompletionI () -{ - // - // detect the case where the server called destroy(), - // the server tool postponed deletion of the object, - // and then it called postIOCompletion() on this object - // when it was currently not in use by the server. - // - if ( this->serverDelete ) { - return S_cas_redundantPost; - } - - // this is only touched in the constructor so its - // ok not to not take a lock here - if ( this->duplicate ) { - errMessage ( S_cas_badParameter, - "- duplicate async IO"); - // - // dont use "this" after potentially destroying the - // object here - // - this->serverDestroy(); - return S_cas_redundantPost; - } - // // place this event in the event queue // o this also signals the event consumer @@ -165,55 +119,12 @@ caStatus casAsyncIOI::postIOCompletionI () return this->client.addToEventQueue ( *this, this->inTheEventQueue, this->posted ); } -// -// casAsyncIOI::getCAS() -// (not inline because this is used by the interface class) -// caServer *casAsyncIOI::getCAS() const { return this->client.getCAS().getAdapter(); } -// -// casAsyncIOI::readOP() -// -bool casAsyncIOI::readOP() const +bool casAsyncIOI::oneShotReadOP() const { - // - // not a read op - // return false; } - -// -// casAsyncIOI::serverDestroyIfReadOP() -// o clients lock is held when this is called -// -void casAsyncIOI::serverDestroyIfReadOP() -{ - if ( this->readOP() ) { - this->serverDestroy(); - } - - // - // NO REF TO THIS OBJECT BELOW HERE - // BECAUSE OF THE DELETE ABOVE - // -} - -// -// void casAsyncIOI::serverDestroy () -// -void casAsyncIOI::serverDestroy () -{ - this->serverDelete = true; - this->destroy(); -} - -// -// void casAsyncIOI::destroy () -// -void casAsyncIOI::destroy () -{ - delete this; -} diff --git a/src/cas/generic/casAsyncPVAttachIO.cc b/src/cas/generic/casAsyncPVAttachIO.cc index d72a6c12b..9a406fd57 100644 --- a/src/cas/generic/casAsyncPVAttachIO.cc +++ b/src/cas/generic/casAsyncPVAttachIO.cc @@ -15,83 +15,51 @@ * 505 665 1831 */ -#include "server.h" -#include "casChannelIIL.h" // casChannelI in line func -#include "casCtxIL.h" // casCtx in line func -#include "casCoreClientIL.h" // casCoreClient in line func +#include -// -// casAsyncPVAttachIO::casAsyncPVAttachIO() -// -casAsyncPVAttachIO::casAsyncPVAttachIO (const casCtx &ctx) : - casAsyncIOI ( ctx ), - msg ( *ctx.getMsg() ), - retVal ( S_cas_badParameter ) +#define epicsExportSharedSymbols +#include "casdef.h" +#include "casAsyncPVAttachIOI.h" + +casAsyncPVAttachIO::casAsyncPVAttachIO ( const casCtx &ctx ) : + pAsyncPVAttachIOI ( new casAsyncPVAttachIOI ( *this, ctx ) ) { - this->client.installAsyncIO ( *this ); } -// -// casAsyncPVAttachIO::~casAsyncPVAttachIO() -// +void casAsyncPVAttachIO::serverInitiatedDestroy () +{ + this->pAsyncPVAttachIOI = 0; + this->destroy (); +} + casAsyncPVAttachIO::~casAsyncPVAttachIO () { - this->client.removeAsyncIO ( *this ); + if ( this->pAsyncPVAttachIOI ) { + throw std::logic_error ( + "the server library *must* initiate asynchronous IO destroy" ); + } } -// -// casAsyncPVAttachIO::postIOCompletion() -// caStatus casAsyncPVAttachIO::postIOCompletion ( const pvAttachReturn & retValIn ) { - this->retVal = retValIn; - return this->postIOCompletionI (); + if ( this->pAsyncPVAttachIOI ) { + return this->pAsyncPVAttachIOI->postIOCompletion ( retValIn ); + } + else { + return S_cas_redundantPost; + } } -// -// casAsyncPVAttachIO::cbFuncAsyncIO() -// (called when IO completion event reaches top of event queue) -// -caStatus casAsyncPVAttachIO::cbFuncAsyncIO() -{ - caStatus status; - - switch ( this->msg.m_cmmd ) { - case CA_PROTO_CLAIM_CIU: - status = this->client.createChanResponse ( this->msg, this->retVal ); - break; - - default: - errPrintf ( S_cas_invalidAsynchIO, __FILE__, __LINE__, - " - client request type = %u", this->msg.m_cmmd ); - status = S_cas_invalidAsynchIO; - break; - } - - return status; -} - -// -// void casAsyncPVAttachIO::destroy () -// void casAsyncPVAttachIO::destroy () { delete this; } -// -// deprecated -// casAsyncPVCreateIO::casAsyncPVCreateIO ( const casCtx & ctx ) : casAsyncPVAttachIO ( ctx ) { } -// -// deprecated -// casAsyncPVCreateIO::~casAsyncPVCreateIO () { } - - diff --git a/src/cas/generic/casAsyncPVExistIO.cc b/src/cas/generic/casAsyncPVExistIO.cc index 075c61773..a22604715 100644 --- a/src/cas/generic/casAsyncPVExistIO.cc +++ b/src/cas/generic/casAsyncPVExistIO.cc @@ -15,71 +15,39 @@ * 505 665 1831 */ +#include -#include "server.h" -#include "casChannelIIL.h" // casChannelI in line func -#include "casCtxIL.h" // casCtx in line func -#include "casCoreClientIL.h" // casCoreClient in line func +#define epicsExportSharedSymbols +#include "casdef.h" +#include "casAsyncPVExistIOI.h" -// -// casAsyncPVExistIO::casAsyncPVExistIO() -// -casAsyncPVExistIO::casAsyncPVExistIO (const casCtx &ctx) : - casAsyncIOI ( ctx ), - msg ( *ctx.getMsg () ), - retVal (pverDoesNotExistHere), - dgOutAddr ( ctx.getClient ()->fetchLastRecvAddr () ), - protocolRevision ( ctx.getClient ()->protocolRevision () ), - sequenceNumber ( ctx.getClient ()->datagramSequenceNumber () ) +casAsyncPVExistIO::casAsyncPVExistIO ( const casCtx & ctx ) : + pAsyncPVExistIOI ( new casAsyncPVExistIOI ( *this, ctx ) ) {} + +void casAsyncPVExistIO::serverInitiatedDestroy () { - this->client.installAsyncIO (*this); + this->pAsyncPVExistIOI = 0; + this->destroy (); } -// -// casAsyncPVExistIO::~casAsyncPVExistIO () -// casAsyncPVExistIO::~casAsyncPVExistIO () { - this->client.removeAsyncIO (*this); + if ( this->pAsyncPVExistIOI ) { + throw std::logic_error ( + "the server library *must* initiate asynchronous IO destroy" ); + } } -// -// casAsyncPVExistIO::postIOCompletion () -// -caStatus casAsyncPVExistIO::postIOCompletion (const pvExistReturn &retValIn) +caStatus casAsyncPVExistIO::postIOCompletion ( const pvExistReturn & retValIn ) { - this->retVal = retValIn; - return this->postIOCompletionI (); -} - -// -// casAsyncPVExistIO::cbFuncAsyncIO() -// (called when IO completion event reaches top of event queue) -// -caStatus casAsyncPVExistIO::cbFuncAsyncIO() -{ - caStatus status; - - if (this->msg.m_cmmd==CA_PROTO_SEARCH) { - // - // pass output DG address parameters - // - status = this->client.asyncSearchResponse ( - this->dgOutAddr, this->msg, this->retVal, - this->protocolRevision, this->sequenceNumber ); + if ( this->pAsyncPVExistIOI ) { + return this->pAsyncPVExistIOI->postIOCompletion ( retValIn ); } else { - errPrintf (S_cas_invalidAsynchIO, __FILE__, __LINE__, - " - client request type = %u", this->msg.m_cmmd); - status = S_cas_invalidAsynchIO; + return S_cas_redundantPost; } - - return status; } -// -// void casAsyncPVExistIO::destroy () -// void casAsyncPVExistIO::destroy () { delete this; diff --git a/src/cas/generic/casAsyncReadIO.cc b/src/cas/generic/casAsyncReadIO.cc index 8070970a5..414b71f62 100644 --- a/src/cas/generic/casAsyncReadIO.cc +++ b/src/cas/generic/casAsyncReadIO.cc @@ -15,113 +15,45 @@ * 505 665 1831 */ -#include "dbMapper.h" +#include -#include "server.h" -#include "casChannelIIL.h" // casChannelI in line func -#include "casCtxIL.h" // casCtxI in line func +#define epicsExportSharedSymbols +#include "casdef.h" +#include "casAsyncReadIOI.h" -// -// casAsyncReadIO::casAsyncReadIO() -// casAsyncReadIO::casAsyncReadIO ( const casCtx & ctx ) : - casAsyncIOI ( ctx ), msg ( *ctx.getMsg() ), - chan ( *ctx.getChannel () ), pDD ( NULL ), completionStatus ( S_cas_internal ) + pAsyncReadIOI ( new casAsyncReadIOI ( *this, ctx ) ) {} + +void casAsyncReadIO::serverInitiatedDestroy () { - assert ( & this->chan ); - this->chan.installAsyncIO ( *this ); + this->pAsyncReadIOI = 0; + this->destroy (); } -// -// casAsyncReadIO::~casAsyncReadIO() -// casAsyncReadIO::~casAsyncReadIO () { - this->chan.removeAsyncIO ( *this ); + if ( this->pAsyncReadIOI ) { + throw std::logic_error ( + "the server library *must* initiate asynchronous IO destroy" ); + } } -// -// casAsyncReadIO::postIOCompletion() -// -caStatus casAsyncReadIO::postIOCompletion ( caStatus completionStatusIn, - const gdd & valueRead) +caStatus casAsyncReadIO::postIOCompletion ( + caStatus completionStatusIn, const gdd & valueRead ) { - this->pDD = & valueRead; - this->completionStatus = completionStatusIn; - return this->postIOCompletionI (); + if ( this->pAsyncReadIOI ) { + return this->pAsyncReadIOI->postIOCompletion ( + completionStatusIn, valueRead ); + } + else { + return S_cas_redundantPost; + } } -// -// casAsyncReadIO::readOP() -// -bool casAsyncReadIO::readOP () const -{ - return true; // it is a read op -} - -// -// casAsyncReadIO::cbFuncAsyncIO() -// (called when IO completion event reaches top of event queue) -// -caStatus casAsyncReadIO::cbFuncAsyncIO() -{ - caStatus status; - - switch ( this->msg.m_cmmd ) { - case CA_PROTO_READ: - status = client.readResponse ( &this->chan, this->msg, - *this->pDD, this->completionStatus); - break; - - case CA_PROTO_READ_NOTIFY: - status = client.readNotifyResponse ( &this->chan, - this->msg, this->pDD, - this->completionStatus); - break; - - case CA_PROTO_EVENT_ADD: - status = client.monitorResponse ( this->chan, - this->msg, this->pDD, - this->completionStatus); - break; - - case CA_PROTO_CLAIM_CIU: - unsigned nativeTypeDBR; - status = this->chan.getPVI().bestDBRType ( nativeTypeDBR ); - if ( status ) { - errMessage ( status, "best external dbr type fetch failed" ); - status = client.channelCreateFailedResp ( this->msg, status ); - } - else { - // we end up here if the channel claim protocol response is delayed - // by an asynchronous enum string table fetch response - if ( this->completionStatus == S_cas_success && this->pDD.valid() ) { - this->chan.getPVI().updateEnumStringTableAsyncCompletion ( *this->pDD ); - } - else { - errMessage ( this->completionStatus, - "unable to read application type \"enums\" string" - " conversion table for enumerated PV" ); - } - status = client.enumPostponedCreateChanResponse ( this->chan, - this->msg, nativeTypeDBR ); - } - break; - - default: - errPrintf ( S_cas_invalidAsynchIO, __FILE__, __LINE__, - " - client request type = %u", this->msg.m_cmmd ); - status = S_cas_invalidAsynchIO; - break; - } - - return status; -} - -// -// void casAsyncReadIO::destroy () -// void casAsyncReadIO::destroy () { delete this; } + + + diff --git a/src/cas/generic/casAsyncWriteIO.cc b/src/cas/generic/casAsyncWriteIO.cc index 3769c2ca7..713d0b985 100644 --- a/src/cas/generic/casAsyncWriteIO.cc +++ b/src/cas/generic/casAsyncWriteIO.cc @@ -15,73 +15,41 @@ * 505 665 1831 */ +#include -#include "server.h" -#include "casChannelIIL.h" // casChannelI in line func -#include "casCtxIL.h" // casCtx in line func +#define epicsExportSharedSymbols +#include "casdef.h" +#include "casAsyncWriteIOI.h" -// -// casAsyncWriteIO::casAsyncWriteIO() -// casAsyncWriteIO::casAsyncWriteIO ( const casCtx & ctx ) : - casAsyncIOI ( ctx ), - msg ( *ctx.getMsg() ), - chan ( *ctx.getChannel() ), - completionStatus ( S_cas_internal ) + pAsyncWriteIOI ( new casAsyncWriteIOI ( *this, ctx ) ) { - assert ( &this->chan ); - this->chan.installAsyncIO ( *this ); } -// -// casAsyncWriteIO::~casAsyncWriteIO() -// +void casAsyncWriteIO::serverInitiatedDestroy () +{ + this->pAsyncWriteIOI = 0; + this->destroy (); +} + casAsyncWriteIO::~casAsyncWriteIO() { - this->chan.removeAsyncIO ( *this ); + if ( this->pAsyncWriteIOI ) { + throw std::logic_error ( + "the server library *must* initiate asynchronous IO destroy" ); + } } -// -// casAsyncWriteIO::postIOCompletion() -// caStatus casAsyncWriteIO::postIOCompletion ( caStatus completionStatusIn ) { - this->completionStatus = completionStatusIn; - return this->postIOCompletionI (); -} - -// -// casAsyncWriteIO::cbFuncAsyncIO() -// (called when IO completion event reaches top of event queue) -// -caStatus casAsyncWriteIO::cbFuncAsyncIO () -{ - caStatus status; - - switch ( this->msg.m_cmmd ) { - case CA_PROTO_WRITE: - status = client.writeResponse ( this->msg, - this->completionStatus ); - break; - - case CA_PROTO_WRITE_NOTIFY: - status = client.writeNotifyResponse ( - this->msg, this->completionStatus ); - break; - - default: - errPrintf ( S_cas_invalidAsynchIO, __FILE__, __LINE__, - " - client request type = %u", this->msg.m_cmmd ); - status = S_cas_invalidAsynchIO; - break; + if ( this->pAsyncWriteIOI ) { + return this->pAsyncWriteIOI->postIOCompletion ( completionStatusIn ); + } + else { + return S_cas_redundantPost; } - - return status; } -// -// void casAsyncWriteIO::destroy () -// void casAsyncWriteIO::destroy () { delete this; diff --git a/src/cas/generic/casBufferFactory.cpp b/src/cas/generic/casBufferFactory.cpp index f64c4b754..d16b219c8 100644 --- a/src/cas/generic/casBufferFactory.cpp +++ b/src/cas/generic/casBufferFactory.cpp @@ -19,8 +19,11 @@ #include "envDefs.h" #include "freeList.h" +#include "errlog.h" -#include "server.h" +#define epicsExportSharedSymbols +#include "clientBufMemoryManager.h" +#include "caProto.h" casBufferFactory::casBufferFactory () : smallBufFreeList ( 0 ), largeBufFreeList ( 0 ), largeBufferSizePriv ( 0u ) diff --git a/src/cas/generic/casChanDelEv.cc b/src/cas/generic/casChanDelEv.cc deleted file mode 100644 index 69efb2196..000000000 --- a/src/cas/generic/casChanDelEv.cc +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#include "server.h" -#include "casEventSysIL.h" // casEventSys in line func - -// -// casChanDelEv() -// -casChanDelEv::~casChanDelEv() -{ -} - -// -// casChanDelEv() -// -caStatus casChanDelEv::cbFunc ( casCoreClient & client ) -{ - caStatus status; - status = client.disconnectChan ( this->id ); - if ( status == S_cas_success ) { - delete this; - } - return status; -} - -void casChanDelEv::eventSysDestroyNotify ( casCoreClient & ) -{ - delete this; -} - diff --git a/src/cas/generic/casChannel.cc b/src/cas/generic/casChannel.cc index c53b51621..55b9a9a73 100644 --- a/src/cas/generic/casChannel.cc +++ b/src/cas/generic/casChannel.cc @@ -15,43 +15,30 @@ * 505 665 1831 */ -#include "server.h" -#include "casChannelIIL.h" // casChannelI inline func -#include "casPVListChanIL.h" // casPVListChan inline func +#define epicsExportSharedSymbols +#include "casdef.h" +#include "casChannelI.h" -// -// casChannel::casChannel() -// -casChannel::casChannel(const casCtx &ctx) : - casPVListChan (ctx) +casChannel::casChannel ( const casCtx & ctx ) : + pChanI ( new casChannelI ( *this, ctx ) ) { } -// -// casChannel::~casChannel() -// -casChannel::~casChannel() +casChannel::~casChannel () { } -// -// casChannel::getPV() -// -casPV *casChannel::getPV() // X aCC 361 +casPV * casChannel::getPV () // X aCC 361 { - casPVI *pPVI = &this->casChannelI::getPVI(); - - if (pPVI!=NULL) { - return pPVI->apiPointer(); - } - else { - return NULL; - } + if ( this->pChanI ) { + casPVI & pvi = this->pChanI->getPVI (); + return pvi.apiPointer (); + } + else { + return 0; + } } -// -// casChannel::setOwner() -// void casChannel::setOwner(const char * const /* pUserName */, const char * const /* pHostName */) { @@ -60,33 +47,21 @@ void casChannel::setOwner(const char * const /* pUserName */, // } -// -// casChannel::readAccess() -// bool casChannel::readAccess () const { return true; } -// -// casChannel::writeAccess() -// bool casChannel::writeAccess() const { return true; } -// -// casChannel::confirmationRequested() -// bool casChannel::confirmationRequested() const { return false; } -// -// casChannel::show() -// void casChannel::show(unsigned level) const { if (level>2u) { @@ -99,19 +74,15 @@ void casChannel::show(unsigned level) const } } -// -// casChannel::destroy() -// void casChannel::destroy() { delete this; } -// -// casChannel::postAccessRightsEvent() -// void casChannel::postAccessRightsEvent() { - this->casChannelI::postAccessRightsEvent(); + if ( this->pChanI ) { + this->pChanI->postAccessRightsEvent (); + } } diff --git a/src/cas/generic/casChannelI.cc b/src/cas/generic/casChannelI.cc index 71034a492..ffb9e88c7 100644 --- a/src/cas/generic/casChannelI.cc +++ b/src/cas/generic/casChannelI.cc @@ -15,188 +15,61 @@ * 505 665 1831 */ -#include "server.h" -#include "casEventSysIL.h" // casEventSys inline func -#include "casPVIIL.h" // casPVI inline func -#include "casCtxIL.h" // casCtx inline func +#define epicsExportSharedSymbols +#include "casChannelI.h" +#include "casAsyncIOI.h" -// -// casChannelI::casChannelI() -// -casChannelI::casChannelI ( const casCtx & ctx ) : - pClient ( ctx.getClient() ), pPV ( ctx.getPV() ), - cid ( ctx.getMsg()->m_cid ), accessRightsEvPending ( false ) +casChannelI::casChannelI ( casChannel & chanIn, const casCtx & ctx ) : + chanForPV ( *ctx.getClient() ), pv ( *ctx.getPV() ), + chan ( chanIn ), cid ( ctx.getMsg()->m_cid ), + accessRightsEvPending ( false ) { } -// -// casChannelI::~casChannelI() -// -casChannelI::~casChannelI() +casChannelI::~casChannelI () { - // - // cancel any pending asynchronous IO - // - tsDLIter iterAIO = this->ioInProgList.firstIter (); - while ( iterAIO.valid () ) { - // - // destructor removes from this list - // - tsDLIter tmpAIO = iterAIO; - ++tmpAIO; - iterAIO->serverDestroy (); - iterAIO = tmpAIO; - } - - // - // cancel the monitors - // - while ( casMonitor * pMon = this->monitorList.get () ) { - this->getClient().destroyMonitor ( *pMon ); - } - - this->pClient->removeChannel ( *this ); - - // + this->pv.destroyAllIO ( this->ioList ); + // force PV delete if this is the last channel attached - // - this->pPV->deleteSignal (); + this->pv.deleteSignal (); + + delete & this->chan; } -// -// casChannelI::clearOutstandingReads() -// -void casChannelI::clearOutstandingReads() +void casChannelI::uninstallFromPV ( casEventSys & eventSys ) { - // - // cancel any pending asynchronous IO - // - tsDLIter iterIO = this->ioInProgList.firstIter (); - while ( iterIO.valid () ) { - // - // destructor removes from this list - // - tsDLIter tmp = iterIO; - ++tmp; - iterIO->serverDestroyIfReadOP(); - iterIO = tmp; + tsDLList < casMonitor > dest; + this->chanForPV.removeSelfFromPV ( this->pv, dest ); + while ( casMonitor * pMon = dest.get () ) { + eventSys.prepareMonitorForDestroy ( *pMon ); } } -// -// casChannelI::show() -// void casChannelI::show ( unsigned level ) const { printf ( "casChannelI: client id %u PV %s\n", - this->cid, this->pPV->getName() ); - if ( this->monitorList.count() ) { - printf ( "List of subscriptions attached\n" ); - // use the client's lock to protect the list - this->pClient->showMonitorsInList ( - this->monitorList, level ); + this->cid, this->pv.getName() ); + if ( level > 0 ) { + this->chanForPV.show ( level - 1 ); + this->chan.show ( level - 1 ); } } -// -// casChannelI::cbFunc() -// -// access rights event call back -// -caStatus casChannelI::cbFunc ( casCoreClient & ) +caStatus casChannelI::cbFunc ( + casCoreClient &, epicsGuard < epicsMutex > & guard ) { - caStatus stat; - - stat = this->pClient->accessRightsResponse ( this ); + caStatus stat = S_cas_success; + { + epicsGuardRelease < epicsMutex > guardRelease ( guard ); + stat = this->chanForPV.client().accessRightsResponse ( this ); + } if ( stat == S_cas_success ) { this->accessRightsEvPending = false; } return stat; } -void casChannelI::eventSysDestroyNotify ( casCoreClient & ) -{ - delete this; -} - -// -// casChannelI::resourceType() -// -casResType casChannelI::resourceType() const -{ - return casChanT; -} - -// -// casChannelI::destroy() -// -// this noop version is safe to be called indirectly -// from casChannelI::~casChannelI -// void casChannelI::destroy() { } -void casChannelI::destroyClientNotify () -{ - casChanDelEv *pCDEV; - caStatus status; - - pCDEV = new casChanDelEv ( this->getCID() ); - if ( pCDEV ) { - this->pClient->addToEventQueue ( *pCDEV ); - } - else { - status = this->pClient->disconnectChan ( this->getCID () ); - if ( status ) { - // - // At this point there is no space in pool - // for a tiny object and there is also - // no outgoing buffer space in which to place - // a message in which we inform the client - // that his channel was deleted. - // - // => disconnect this client via the event - // queue because deleting the client here - // will result in bugs because no doubt this - // could be called by a client member function. - // - this->pClient->setDestroyPending (); - } - } - this->destroy (); -} - -bool casChannelI::unistallMonitor ( ca_uint32_t clientIdIn ) -{ - // - // (it is reasonable to do a linear search here because - // sane clients will require only one or two monitors - // per channel) - // - tsDLIter iter = this->monitorList.firstIter (); - while ( iter.valid () ) { - if ( clientIdIn == iter->getClientId () ) { - this->monitorList.remove ( *iter.pointer() ); - this->getClient().destroyMonitor ( *iter.pointer() ); - return true; - } - iter++; - } - return false; -} - -// -// casChannelI::installMonitor () -// -void casChannelI::installMonitor ( - caResId clientId, - const unsigned long count, - const unsigned type, - const casEventMask & mask ) -{ - casMonitor & mon = this->pClient->monitorFactory ( - *this, clientId, count, type, mask ); - this->monitorList.add ( mon ); -} - diff --git a/src/cas/generic/casChannelIIL.h b/src/cas/generic/casChannelIIL.h deleted file mode 100644 index 93ab882a7..000000000 --- a/src/cas/generic/casChannelIIL.h +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#ifndef casChannelIIL_h -#define casChannelIIL_h - -#include "casCoreClientIL.h" -#include "casEventSysIL.h" - -// -// casChannelI::postEvent() -// -inline void casChannelI::postEvent ( const casEventMask &select, const gdd &event ) -{ - this->pClient->postEvent ( this->monitorList, select, event ); -} - -// -// casChannelI::destroyNoClientNotify() -// -inline void casChannelI::destroyNoClientNotify() -{ - this->destroy (); -} - -#include "casPVIIL.h" - -// -// functions that use casPVIIL.h below here -// - -// -// casChannelI::installAsyncIO() -// -inline void casChannelI::installAsyncIO ( casAsyncIOI & io ) -{ - // install through the client so that we can - // use its lock to protect the list - this->pClient->installChannelsAsynchIO ( this->ioInProgList, io ); -} - -// -// casChannelI::removeAsyncIO() -// -inline void casChannelI::removeAsyncIO ( casAsyncIOI & io ) -{ - // uninstall through the client so that we can - // use its lock to protect the list - this->pClient->uninstallChannelsAsynchIO ( this->ioInProgList, io ); - this->pPV->unregisterIO (); -} - -// -// casChannelI::getSID() -// fetch the unsigned integer server id for this PV -// -inline const caResId casChannelI::getSID() -{ - return this->casRes::getId(); -} - -// -// casChannelI::postAccessRightsEvent() -// -inline void casChannelI::postAccessRightsEvent() -{ - if ( ! this->accessRightsEvPending ) { - this->accessRightsEvPending = true; - this->pClient->addToEventQueue ( *this ); - } -} - -// -// casChannelI::enumStringTable () -// -inline const gddEnumStringTable & casChannelI::enumStringTable () const -{ - return this->pPV->enumStringTable (); -} - -#endif // casChannelIIL_h - diff --git a/src/cas/generic/casClient.cc b/src/cas/generic/casClient.cc index 1ce03b7b7..711d39619 100644 --- a/src/cas/generic/casClient.cc +++ b/src/cas/generic/casClient.cc @@ -17,16 +17,14 @@ #include -#include "server.h" -#include "casEventSysIL.h" // inline func for casEventSys -#include "casCtxIL.h" // inline func for casCtx -#include "inBufIL.h" // inline func for inBuf -#include "outBufIL.h" // inline func for outBuf -#include "casPVIIL.h" // inline func for casPVI +#include "caerr.h" +#include "osiWireFormat.h" #include "db_access.h" -static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u}; +#define epicsExportSharedSymbols +#include "casClient.h" +static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u}; // // static declartions for class casClient @@ -51,40 +49,6 @@ casClient::casClient ( caServerI & serverInternal, casClient::loadProtoJumpTable(); } -// -// find the channel associated with a resource id -// -casChannelI * casClient::lookupChannel ( const caResId & idIn ) -{ - // - // look up the id in a hash table - // - casChannelI * pChan = - this->ctx.getServer()->lookupChannel ( idIn ); - - // - // update the context - // - this->ctx.setChannel ( pChan ); - if ( ! pChan ) { - return NULL; - } - - // - // If the channel isnt attached to this client then - // something has gone wrong - // - if ( &pChan->getClient() != this ) { - return NULL; - } - - // - // update the context - // - this->ctx.setPV ( &pChan->getPVI() ); - return pChan; -} - // // casClient::loadProtoJumpTable() // @@ -258,8 +222,8 @@ caStatus casClient::processMsg () this->dumpMsg ( & msgTmp, 0, "The client requested transfer is greater than available " "memory in server or EPICS_CA_MAX_ARRAY_BYTES\n" ); - status = this->sendErr ( & msgTmp, ECA_TOLARGE, - "request didnt fit within the CA server's message buffer" ); + status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE, + "client's request didnt fit within the CA server's message buffer" ); this->in.removeMsg ( bytesLeft ); this->incommingBytesToDrain = msgSize - bytesLeft; } @@ -303,14 +267,14 @@ caStatus casClient::processMsg () } catch ( std::bad_alloc & ) { status = this->sendErr ( - this->ctx.getMsg(), ECA_ALLOCMEM, + this->ctx.getMsg(), invalidResID, ECA_ALLOCMEM, "inablility to allocate memory in " "the server disconnected client" ); status = S_cas_noMemory; } catch ( std::exception & except ) { status = this->sendErr ( - this->ctx.getMsg(), ECA_INTERNAL, + this->ctx.getMsg(), invalidResID, ECA_INTERNAL, "C++ exception \"%s\" in server " "diconnected client", except.what () ); @@ -318,7 +282,7 @@ caStatus casClient::processMsg () } catch (...) { status = this->sendErr ( - this->ctx.getMsg(), ECA_INTERNAL, + this->ctx.getMsg(), invalidResID, ECA_INTERNAL, "unexpected C++ exception in server " "diconnected client" ); status = S_cas_internal; @@ -420,11 +384,12 @@ void casClient::sendVersion () this->out.commitMsg (); } } + // // casClient::sendErr() // -caStatus casClient::sendErr ( const caHdrLargeArray *curp, const int reportedStatus, - const char *pformat, ... ) +caStatus casClient::sendErr ( const caHdrLargeArray *curp, + ca_uint32_t cid, const int reportedStatus, const char *pformat, ... ) { unsigned stringSize; char msgBuf[1024]; /* allocate plenty of space for the message string */ @@ -451,41 +416,6 @@ caStatus casClient::sendErr ( const caHdrLargeArray *curp, const int reportedSta hdrSize += 2 * sizeof ( ca_uint32_t ); } - ca_uint32_t cid = 0u; - switch ( curp->m_cmmd ) { - case CA_PROTO_SEARCH: - cid = curp->m_cid; - break; - - case CA_PROTO_EVENT_ADD: - case CA_PROTO_EVENT_CANCEL: - case CA_PROTO_READ: - case CA_PROTO_READ_NOTIFY: - case CA_PROTO_WRITE: - case CA_PROTO_WRITE_NOTIFY: - { - /* - * Verify the channel - */ - casChannelI * pciu = this->lookupChannel ( curp->m_cid ); - if ( pciu ) { - cid = pciu->getCID(); - } - else{ - cid = ~0u; - } - break; - } - - case CA_PROTO_EVENTS_ON: - case CA_PROTO_EVENTS_OFF: - case CA_PROTO_READ_SYNC: - case CA_PROTO_SNAPSHOT: - default: - cid = (caResId) ~0UL; - break; - } - caHdr * pReqOut; epicsGuard < epicsMutex > guard ( this->mutex ); caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR, @@ -539,11 +469,11 @@ caStatus casClient::sendErr ( const caHdrLargeArray *curp, const int reportedSta * to a string and send that additional detail */ caStatus casClient::sendErrWithEpicsStatus ( const caHdrLargeArray * pMsg, - caStatus epicsStatus, caStatus clientStatus ) + ca_uint32_t cid, caStatus epicsStatus, caStatus clientStatus ) { char buf[0x1ff]; errSymLookup ( epicsStatus, buf, sizeof(buf) ); - return this->sendErr ( pMsg, clientStatus, buf ); + return this->sendErr ( pMsg, cid, clientStatus, buf ); } /* @@ -567,7 +497,7 @@ caStatus casClient::logBadIdWithFileAndLineno ( const caHdrLargeArray * mp, } status = this->sendErr ( - mp, cacStatus, "Bad Resource ID=%u detected at %s.%d", + mp, invalidResID, cacStatus, "Bad Resource ID=%u detected at %s.%d", idIn, pFileName, lineno); return status; @@ -581,7 +511,7 @@ caStatus casClient::logBadIdWithFileAndLineno ( const caHdrLargeArray * mp, // dp arg allowed to be null // // -void casClient::dumpMsg ( const caHdrLargeArray *mp, +void casClient::dumpMsg ( const caHdrLargeArray *mp, const void *dp, const char *pFormat, ... ) { va_list theArgs; @@ -593,21 +523,7 @@ void casClient::dumpMsg ( const caHdrLargeArray *mp, } char pName[64u]; - this->hostName (pName, sizeof (pName)); - - casChannelI * pciu = this->lookupChannel ( mp->m_cid ); - - char pPVName[64u]; - if (pciu) { - strncpy(pPVName, pciu->getPVI().getName(), sizeof(pPVName)); - if (&pciu->getClient()!=this) { - strncat(pPVName, "!Bad Client!", sizeof(pPVName)); - } - pPVName[sizeof(pPVName)-1]='\0'; - } - else { - sprintf(pPVName,"%u", mp->m_cid); - } + this->hostName ( pName, sizeof ( pName ) ); char pUserName[32]; this->userName ( pUserName, sizeof ( pUserName) ); @@ -615,12 +531,12 @@ void casClient::dumpMsg ( const caHdrLargeArray *mp, this->hostName ( pHostName, sizeof ( pHostName) ); fprintf ( stderr, -"CAS Request: %s on %s at %s: cmd=%d cid=%s typ=%d cnt=%d psz=%d avail=%x\n", +"CAS Request: %s on %s at %s: cmd=%u cid=%u typ=%u cnt=%u psz=%u avail=%x\n", pUserName, pHostName, pName, mp->m_cmmd, - pPVName, + mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize, diff --git a/src/cas/generic/casClient.h b/src/cas/generic/casClient.h new file mode 100644 index 000000000..af60dd445 --- /dev/null +++ b/src/cas/generic/casClient.h @@ -0,0 +1,115 @@ + +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef casClienth +#define casClienth + +#ifdef epicsExportSharedSymbols +# define epicsExportSharedSymbols_casClienth +# undef epicsExportSharedSymbols +#endif + +#include "epicsTime.h" + +#ifdef epicsExportSharedSymbols_casClienth +# define epicsExportSharedSymbols +# include "shareLib.h" +#endif + + +#include "casCoreClient.h" +#include "inBuf.h" +#include "outBuf.h" + +// +// casClient +// +// this class exists so that udp and tcp can share certain +// protocol stubs but is this worth the extra complexity ???? +// +class casClient : public casCoreClient, public outBufClient, + public inBufClient { +public: + casClient ( caServerI &, clientBufMemoryManager &, bufSizeT ioMinSizeIn ); + virtual ~casClient (); + virtual void show ( unsigned level ) const; + caStatus sendErr ( const caHdrLargeArray *, ca_uint32_t cid, + const int reportedStatus, const char *pFormat, ... ); + ca_uint16_t protocolRevision() const {return this->minor_version_number;} + virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0; + void sendVersion (); + +protected: + inBuf in; + outBuf out; + ca_uint16_t minor_version_number; + unsigned incommingBytesToDrain; + epicsTime lastSendTS; + epicsTime lastRecvTS; + + caStatus sendErrWithEpicsStatus ( const caHdrLargeArray *pMsg, + ca_uint32_t cid, caStatus epicsStatus, caStatus clientStatus ); + +# define logBadId(MP, DP, CACSTAT, RESID) \ + this->logBadIdWithFileAndLineno(MP, DP, CACSTAT, __FILE__, __LINE__, RESID) + caStatus logBadIdWithFileAndLineno ( const caHdrLargeArray *mp, + const void *dp, const int cacStat, const char *pFileName, + const unsigned lineno, const unsigned resId ); + + caStatus processMsg(); + + // + // dump message to stderr + // + void dumpMsg ( const caHdrLargeArray *mp, const void *dp, + const char *pFormat, ... ); + + +private: + typedef caStatus ( casClient::*pCASMsgHandler ) (); + + // + // one function for each CA request type + // + virtual caStatus uknownMessageAction () = 0; + caStatus ignoreMsgAction (); + virtual caStatus versionAction (); + 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 (); + + virtual void userName ( char * pBuf, unsigned bufSize ) const = 0; + + // + // static members + // + static void loadProtoJumpTable(); + static pCASMsgHandler msgHandlers[CA_PROTO_LAST_CMMD+1u]; + static bool msgHandlersInit; + + casClient ( const casClient & ); + casClient & operator = ( const casClient & ); +}; + +#endif // casClienth + diff --git a/src/cas/generic/casCoreClient.cc b/src/cas/generic/casCoreClient.cc index 833c40e04..6bc0427d6 100644 --- a/src/cas/generic/casCoreClient.cc +++ b/src/cas/generic/casCoreClient.cc @@ -15,57 +15,32 @@ * 505 665 1831 */ +#define epicsExportSharedSymbols +#include "casCoreClient.h" +#include "casAsyncPVExistIOI.h" +#include "casAsyncPVAttachIOI.h" -#include "server.h" -#include "caServerIIL.h" -#include "casEventSysIL.h" -#include "casCtxIL.h" -#include "inBufIL.h" -#include "outBufIL.h" -#include "casCoreClientIL.h" - -// -// casCoreClient::casCoreClient() -// casCoreClient::casCoreClient ( caServerI & serverInternal ) : eventSys ( *this ) { - assert (&serverInternal); - ctx.setServer (&serverInternal); - ctx.setClient (this); + assert ( & serverInternal ); + ctx.setServer ( & serverInternal ); + ctx.setClient ( this ); } -// -// casCoreClient::~casCoreClient() -// casCoreClient::~casCoreClient() { - if (this->ctx.getServer()->getDebugLevel()>0u) { - errlogPrintf ("CAS: Connection Terminated\n"); - } - - epicsGuard < epicsMutex > guard ( this->mutex ); - - tsDLIter iterIO = this->ioInProgList.firstIter (); - - // - // cancel any pending asynchronous IO - // - while ( iterIO.valid () ) { - // - // destructor removes from this list - // - tsDLIter tmpIO = iterIO; - ++tmpIO; - iterIO->serverDestroy (); - iterIO = tmpIO; + // only used by io that does not have a channel + while ( casAsyncIOI * pIO = this->ioList.get() ) { + pIO->removeFromEventQueue (); + delete pIO; } + if ( this->ctx.getServer()->getDebugLevel() > 0u ) { + errlogPrintf ( "CAS: Connection Terminated\n" ); + } } -// -// casCoreClient::disconnectChan() -// -caStatus casCoreClient::disconnectChan(caResId) +caStatus casCoreClient::disconnectChan ( caResId ) { printf ("Disconnect Chan issued for inappropriate client type?\n"); return S_cas_success; @@ -76,7 +51,6 @@ void casCoreClient::show ( unsigned level ) const printf ( "Core client\n" ); epicsGuard < epicsMutex > guard ( this->mutex ); this->eventSys.show ( level ); - printf ( "\t%d io ops in progess\n", this->ioInProgList.count() ); this->ctx.show ( level ); this->mutex.show ( level ); } @@ -95,23 +69,23 @@ caStatus casCoreClient::createChanResponse ( const caHdrLargeArray &, const pvAt { return S_casApp_noSupport; } -caStatus casCoreClient::readResponse (casChannelI *, const caHdrLargeArray &, - const smartConstGDDPointer &, const caStatus) +caStatus casCoreClient::readResponse ( casChannelI *, const caHdrLargeArray &, + const smartConstGDDPointer &, const caStatus ) { return S_casApp_noSupport; } -caStatus casCoreClient::readNotifyResponse (casChannelI *, const caHdrLargeArray &, - const smartConstGDDPointer &, const caStatus) +caStatus casCoreClient::readNotifyResponse ( casChannelI *, const caHdrLargeArray &, + const smartConstGDDPointer &, const caStatus ) { return S_casApp_noSupport; } -caStatus casCoreClient::writeResponse (const caHdrLargeArray &, - const caStatus) +caStatus casCoreClient::writeResponse ( casChannelI &, + const caHdrLargeArray &, const caStatus ) { return S_casApp_noSupport; } -caStatus casCoreClient::writeNotifyResponse (const caHdrLargeArray &, - const caStatus) +caStatus casCoreClient::writeNotifyResponse ( casChannelI &, + const caHdrLargeArray &, const caStatus ) { return S_casApp_noSupport; } @@ -135,41 +109,16 @@ caStatus casCoreClient::channelCreateFailedResp ( const caHdrLargeArray &, return S_casApp_noSupport; } -// -// casCoreClient::installChannel() -// -void casCoreClient::installChannel ( casChannelI & ) -{ - assert (0); // dont install channels on the wrong type of client -} - -// -// casCoreClient::removeChannel() -// -void casCoreClient::removeChannel ( casChannelI & ) -{ - assert (0); // dont install channels on the wrong type of client -} - -// -// casCoreClient::fetchLastRecvAddr () -// caNetAddr casCoreClient::fetchLastRecvAddr () const { return caNetAddr(); // sets addr type to UDF } -// -// casCoreClient::datagramSequenceNumber () -// ca_uint32_t casCoreClient::datagramSequenceNumber () const { return 0; } -// -// casCoreClient::protocolRevision () -// ca_uint16_t casCoreClient::protocolRevision() const { return 0; @@ -197,139 +146,37 @@ casMonitor & casCoreClient::monitorFactory ( { casMonitor & mon = this->ctx.getServer()->casMonitorFactory ( chan, clientId, count, type, mask, *this ); - { - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.installMonitor (); - } + this->eventSys.installMonitor (); return mon; } void casCoreClient::destroyMonitor ( casMonitor & mon ) { - { - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.removeMonitor (); - } + this->eventSys.removeMonitor (); + assert ( mon.numEventsQueued() == 0 ); this->ctx.getServer()->casMonitorDestroy ( mon ); } -void casCoreClient::postEvent ( tsDLList < casMonitor > & monitorList, - const casEventMask & select, const gdd & event ) +void casCoreClient::installAsynchIO ( casAsyncPVAttachIOI & io ) { epicsGuard < epicsMutex > guard ( this->mutex ); - tsDLIter < casMonitor > iter = monitorList.firstIter (); - while ( iter.valid () ) { - iter->postEvent ( this->eventSys, select, event ); - ++iter; - } + this->ioList.add ( io ); } -void casCoreClient::showMonitorsInList ( - const tsDLList < casMonitor > & monitorList, unsigned level ) const +void casCoreClient::uninstallAsynchIO ( casAsyncPVAttachIOI & io ) { epicsGuard < epicsMutex > guard ( this->mutex ); - tsDLIterConst < casMonitor > iter = monitorList.firstIter (); - while ( iter.valid () ) { - iter->show ( level ); - ++iter; - } + this->ioList.remove ( io ); } -void casCoreClient::installChannelsAsynchIO ( - tsDLList < casAsyncIOI > & list, casAsyncIOI & io ) +void casCoreClient::installAsynchIO ( casAsyncPVExistIOI & io ) { epicsGuard < epicsMutex > guard ( this->mutex ); - list.add ( io ); + this->ioList.add ( io ); } -void casCoreClient::uninstallChannelsAsynchIO ( - tsDLList < casAsyncIOI > & list, casAsyncIOI & io ) +void casCoreClient::uninstallAsynchIO ( casAsyncPVExistIOI & io ) { epicsGuard < epicsMutex > guard ( this->mutex ); - list.remove ( io ); + this->ioList.remove ( io ); } - -// -// casCoreClient::installAsyncIO() -// -void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->ioInProgList.add ( ioIn ); -} - -// -// casCoreClient::removeAsyncIO() -// -void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->ioInProgList.remove ( ioIn ); - this->ctx.getServer()->ioBlockedList::signal (); -} - -casEventSys::processStatus casCoreClient::eventSysProcess () -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - return this->eventSys.process (); -} - -void casCoreClient::addToEventQueue ( casEvent & ev ) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.addToEventQueue ( ev ); -} - -// clients lock protects the event list and the -// flags in the asynch IO object -caStatus casCoreClient::addToEventQueue ( casAsyncIOI & io, - bool & onTheQueue, bool & posted ) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - // dont allow them to post completion more than once - if ( posted || onTheQueue ) { - return S_cas_redundantPost; - } - posted = true; - onTheQueue = true; - this->eventSys.addToEventQueue ( io ); - return S_cas_success; -} - -void casCoreClient::removeFromEventQueue ( casEvent & ev ) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.removeFromEventQueue ( ev ); -} - -void casCoreClient::removeFromEventQueue ( casAsyncIOI & io ) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - if ( io.onTheEventQueue () ) { - this->eventSys.removeFromEventQueue ( io ); - } -} - -void casCoreClient::enableEvents () -{ - { - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.eventsOn (); - } - this->eventSignal (); // wake up the event queue consumer -} - -void casCoreClient::disableEvents () -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.eventsOff (); -} - -void casCoreClient::setDestroyPending () -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->eventSys.setDestroyPending (); -} - - - diff --git a/src/cas/generic/casCoreClient.h b/src/cas/generic/casCoreClient.h new file mode 100644 index 000000000..5e9a943ae --- /dev/null +++ b/src/cas/generic/casCoreClient.h @@ -0,0 +1,227 @@ + +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef casCoreClienth +#define casCoreClienth + +#include "caServerI.h" +#include "ioBlocked.h" +#include "casMonitor.h" +#include "casEventSys.h" +#include "casCtx.h" + +// +// casCoreClient +// (this will eventually support direct communication +// between the client lib and the server lib) +// +class casCoreClient : public ioBlocked, + private casMonitorCallbackInterface { +public: + casCoreClient ( caServerI & serverInternal ); + virtual ~casCoreClient (); + virtual caStatus disconnectChan( caResId id ); + virtual void show ( unsigned level ) const; + + void installAsynchIO ( class casAsyncPVAttachIOI & io ); + void uninstallAsynchIO ( class casAsyncPVAttachIOI & io ); + void installAsynchIO ( class casAsyncPVExistIOI & io ); + void uninstallAsynchIO ( class casAsyncPVExistIOI & io ); + + caServerI & getCAS () const; + + // + // one virtual function for each CA request type that has + // asynchronous completion + // + virtual caStatus asyncSearchResponse ( + const caNetAddr & outAddr, + const caHdrLargeArray &, const pvExistReturn &, + ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber ); + virtual caStatus createChanResponse ( + const caHdrLargeArray &, const pvAttachReturn &); + virtual caStatus readResponse ( + casChannelI *, const caHdrLargeArray &, + const smartConstGDDPointer &, const caStatus ); + virtual caStatus readNotifyResponse ( + casChannelI *, const caHdrLargeArray &, + const smartConstGDDPointer &, const caStatus ); + virtual caStatus writeResponse ( casChannelI &, + const caHdrLargeArray &, const caStatus ); + virtual caStatus writeNotifyResponse ( casChannelI &, + const caHdrLargeArray &, const caStatus ); + virtual caStatus monitorResponse ( casChannelI &, + const caHdrLargeArray &, const smartConstGDDPointer &, + const caStatus status ); + virtual caStatus accessRightsResponse ( casChannelI * ); + virtual caStatus enumPostponedCreateChanResponse ( + casChannelI &, const caHdrLargeArray &, + unsigned dbrType ); + virtual caStatus channelCreateFailedResp ( + const caHdrLargeArray &, const caStatus createStatus ); + + virtual ca_uint16_t protocolRevision () const = 0; + + // used only with DG clients + virtual caNetAddr fetchLastRecvAddr () const; + virtual ca_uint32_t datagramSequenceNumber () const; + + bool okToStartAsynchIO (); + void setDestroyPending (); + + casEventSys::processStatus eventSysProcess(); + + void addToEventQueue ( casMonEvent & ); + void removeFromEventQueue ( casMonEvent & ); + caStatus addToEventQueue ( casAsyncIOI &, + bool & onTheQueue, bool & posted ); + void removeFromEventQueue ( casAsyncIOI &, + bool & onTheEventQueue ); + void addToEventQueue ( + casChannelI &, bool & inTheEventQueue ); + void enableEvents (); + void disableEvents (); + caStatus casMonitorCallBack ( casMonitor &, + const smartConstGDDPointer & ); + void postEvent ( tsDLList &, + const casEventMask &select, const gdd &event ); + + casMonitor & monitorFactory ( + casChannelI & , + caResId clientId, + const unsigned long count, + const unsigned type, + const casEventMask & ); + void destroyMonitor ( casMonitor & mon ); + + void casMonEventDestroy ( + casMonEvent &, epicsGuard < epicsMutex > & ); + +protected: + mutable epicsMutex mutex; + casEventSys eventSys; + casCtx ctx; + bool userStartedAsyncIO; + +private: + // for io that does not have a channel + tsDLList < casAsyncIOI > ioList; + + virtual void eventSignal () = 0; + + casCoreClient ( const casCoreClient & ); + casCoreClient & operator = ( const casCoreClient & ); +}; + +inline caServerI & casCoreClient::getCAS() const +{ + return *this->ctx.getServer(); +} + +inline bool casCoreClient::okToStartAsynchIO () +{ + if ( ! this->userStartedAsyncIO ) { + this->userStartedAsyncIO = true; + return true; + } + return false; +} + +inline void casCoreClient::postEvent ( tsDLList < casMonitor > & monitorList, + const casEventMask & select, const gdd & event ) +{ + bool signalNeeded = + this->eventSys.postEvent ( monitorList, select, event ); + if ( signalNeeded ) { + this->eventSignal (); + } + +} + +inline casEventSys::processStatus casCoreClient::eventSysProcess () +{ + return this->eventSys.process (); +} + +inline caStatus casCoreClient::addToEventQueue ( casAsyncIOI & io, + bool & onTheQueue, bool & posted ) +{ + bool wakeupNeeded; + caStatus status = this->eventSys.addToEventQueue ( io, + onTheQueue, posted, wakeupNeeded ); + if ( wakeupNeeded ) { + this->eventSignal (); + } + return status; +} + +inline void casCoreClient::removeFromEventQueue ( + casAsyncIOI & io, bool & onTheEventQueue ) +{ + this->eventSys.removeFromEventQueue ( io, onTheEventQueue ); +} + +inline void casCoreClient::addToEventQueue ( casMonEvent & ev ) +{ + this->eventSys.addToEventQueue ( ev ); +} + +inline void casCoreClient::removeFromEventQueue ( casMonEvent & ev ) +{ + this->eventSys.removeFromEventQueue ( ev ); +} + +inline void casCoreClient::addToEventQueue ( + casChannelI & ev, bool & inTheEventQueue ) +{ + bool signalNeeded = + this->eventSys.addToEventQueue ( ev, inTheEventQueue ); + if ( signalNeeded ) { + this->eventSignal (); + } +} + +inline void casCoreClient::enableEvents () +{ + this->eventSys.eventsOn (); + this->eventSignal (); // wake up the event queue consumer +} + +inline void casCoreClient::disableEvents () +{ + bool signalNeeded = + this->eventSys.eventsOff (); + if ( signalNeeded ) { + this->eventSignal (); + } +} + +inline void casCoreClient::setDestroyPending () +{ + this->eventSys.setDestroyPending (); + this->eventSignal (); +} + +inline void casCoreClient::casMonEventDestroy ( + casMonEvent & ev, epicsGuard < epicsMutex > & guard ) +{ + this->eventSys.casMonEventDestroy ( ev, guard ); +} + +#endif // casCoreClienth + diff --git a/src/cas/generic/casCtx.cc b/src/cas/generic/casCtx.cc index a7dbd8340..305d582e3 100644 --- a/src/cas/generic/casCtx.cc +++ b/src/cas/generic/casCtx.cc @@ -8,12 +8,20 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -#include "server.h" +#include +#include -// -// casCtx::show() -// -void casCtx::show (unsigned level) const +#define epicsExportSharedSymbols +#include "casCtx.h" + +casCtx::casCtx() : + pData(NULL), pCAS(NULL), pClient(NULL), + pChannel(NULL), pPV(NULL), nAsyncIO(0u) +{ + memset(&this->msg, 0, sizeof(this->msg)); +} + +void casCtx::show ( unsigned level ) const { printf ( "casCtx at %p\n", static_cast ( this ) ); diff --git a/src/cas/generic/casDGClient.cc b/src/cas/generic/casDGClient.cc index 9a30d1d2d..c00cb05db 100644 --- a/src/cas/generic/casDGClient.cc +++ b/src/cas/generic/casDGClient.cc @@ -14,20 +14,15 @@ * johill@lanl.gov * 505 665 1831 */ + #include "gddApps.h" +#include "caerr.h" +#include "osiWireFormat.h" -#include "server.h" -#include "caServerIIL.h" // caServerI inline func -#include "inBufIL.h" // inline functions for inBuf -#include "outBufIL.h" // inline func for outBuf -#include "casCtxIL.h" // casCtx inline func -#include "casCoreClientIL.h" // casCoreClient inline func +#define epicsExportSharedSymbols +#include "casDGClient.h" #include "osiPoolStatus.h" // osi pool monitoring functions -// -// CA Server Datagram (DG) Client -// - // // casDGClient::casDGClient() // @@ -130,24 +125,24 @@ caStatus casDGClient::searchAction() // search requests, and therefore dont thrash through // caServer::pvExistTest() and casCreatePV::pvAttach() // - if (!osiSufficentSpaceInPool(0)) { + if ( ! osiSufficentSpaceInPool ( 0 ) ) { return S_cas_success; } // // ask the server tool if this PV exists // - this->asyncIOFlag = false; + this->userStartedAsyncIO = false; pvExistReturn pver = - this->getCAS()->pvExistTest(this->ctx, pChanName); + this->getCAS()->pvExistTest ( this->ctx, pChanName ); // // prevent problems when they initiate // async IO but dont return status // indicating so (and vise versa) // - if ( this->asyncIOFlag ) { - if (pver.getStatus()!=pverAsyncCompletion) { + if ( this->userStartedAsyncIO ) { + if ( pver.getStatus() != pverAsyncCompletion ) { errMessage (S_cas_badParameter, "- assuming asynch IO status from caServer::pvExistTest()"); } @@ -157,7 +152,7 @@ caStatus casDGClient::searchAction() // // otherwise we assume sync IO operation was initiated // - switch (pver.getStatus()) { + switch ( pver.getStatus() ) { case pverExistsHere: status = this->searchResponse (*mp, pver); break; @@ -213,8 +208,8 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg, // new API was added to the server (they must // now use clients at EPICS 3.12 or higher) // - status = this->sendErr(&msg, ECA_DEFUNCT, - "R3.11 connect sequence from old client was ignored"); + status = this->sendErr ( &msg, ECA_DEFUNCT, invalidResID, + "R3.11 connect sequence from old client was ignored" ); return status; } @@ -457,10 +452,6 @@ caStatus casDGClient::asyncSearchResponse ( const caNetAddr & outAddr, epicsGuard < epicsMutex > guard ( this->mutex ); - // - // start a DG context in the output protocol stream - // and grab the send lock - // void * pRaw; const outBufCtx outctx = this->out.pushCtx ( sizeof(cadg), MAX_UDP_SEND, pRaw ); diff --git a/src/cas/generic/casDGClient.h b/src/cas/generic/casDGClient.h new file mode 100644 index 000000000..4fd14f666 --- /dev/null +++ b/src/cas/generic/casDGClient.h @@ -0,0 +1,98 @@ + + +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef casDGClienth +#define casDGClienth + +#include "casClient.h" + +class casDGClient : public casClient { +public: + casDGClient ( class caServerI & serverIn, + clientBufMemoryManager & ); + virtual ~casDGClient (); + + virtual void show (unsigned level) const; + + void sendBeacon ( ca_uint32_t beaconNumber ); + + virtual void sendBeaconIO ( char &msg, bufSizeT length, + aitUint16 &portField, aitUint32 &addrField ) = 0; + + void destroy (); + + unsigned getDebugLevel () const; + + void hostName ( char * pBuf, unsigned bufSize ) const; + void userName ( char * pBuf, unsigned bufSize ) const; + + caNetAddr fetchLastRecvAddr () const; + + virtual caNetAddr serverAddress () const = 0; + +protected: + + caStatus processDG (); + +private: + caNetAddr lastRecvAddr; + ca_uint32_t seqNoOfReq; + + // + // one function for each CA request type + // + caStatus searchAction (); + caStatus uknownMessageAction (); + + // + // searchFailResponse() + // + caStatus searchFailResponse ( const caHdrLargeArray *pMsg ); + + caStatus searchResponse ( const caHdrLargeArray &, + const pvExistReturn & retVal ); + + caStatus asyncSearchResponse ( const caNetAddr & outAddr, + const caHdrLargeArray & msg, const pvExistReturn & retVal, + ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber ); + + // + // IO depen + // + outBufClient::flushCondition xSend ( char *pBufIn, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent ); + inBufClient::fillCondition xRecv ( char *pBufIn, bufSizeT nBytesToRecv, + fillParameter parm, bufSizeT &nByesRecv ); + + virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq, + const caNetAddr & addr ) = 0; + virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq, + fillParameter parm, bufSizeT &nBytesActual, caNetAddr & addr ) = 0; + + caStatus versionAction (); + + ca_uint32_t datagramSequenceNumber () const; + + // + // cadg + // + struct cadg { + caNetAddr cadg_addr; // invalid address indicates pad + bufSizeT cadg_nBytes; + }; + + casDGClient ( const casDGClient & ); + casDGClient & operator = ( const casDGClient & ); +}; + +#endif // casDGClienth + diff --git a/src/cas/generic/casEventMask.cc b/src/cas/generic/casEventMask.cc index ea4b26e00..8ddb8d9d5 100644 --- a/src/cas/generic/casEventMask.cc +++ b/src/cas/generic/casEventMask.cc @@ -18,7 +18,9 @@ #include #include -#include "server.h" +#define epicsExportSharedSymbols +#include "casdef.h" +#include "casEventRegistry.h" #ifdef TEST main () @@ -63,117 +65,88 @@ main () } #endif -// -// casEventRegistry::maskAllocator() -// -casEventMask casEventRegistry::maskAllocator() +casEventMask casEventRegistry::maskAllocator () { casEventMask evMask; - if (this->maskBitAllocatormaskBitAllocator++); + if ( this->maskBitAllocator < CHAR_BIT * sizeof ( evMask.mask ) ) { + evMask.mask = 1u << ( this->maskBitAllocator++ ); } return evMask; } -// -// casEventRegistry::registerEvent() -// -casEventMask casEventRegistry::registerEvent(const char *pName) +casEventMask casEventRegistry::registerEvent ( const char *pName ) { // // NOTE: pName outlives id here // (so the refString option is ok) // - stringId id (pName, stringId::refString); - casEventMaskEntry *pEntry; - casEventMask mask; + stringId id ( pName, stringId::refString ); + casEventMaskEntry * pEntry; + casEventMask mask; - pEntry = this->lookup (id); + pEntry = this->lookup ( id ); if (pEntry) { mask = *pEntry; } else { - mask = this->maskAllocator(); - if (mask.mask == 0u) { - errMessage (S_cas_tooManyEvents, NULL); + mask = this->maskAllocator (); + if ( mask.mask == 0u ) { + errMessage ( S_cas_tooManyEvents, NULL ); } else { - pEntry = new casEventMaskEntry(*this, mask, pName); + pEntry = new casEventMaskEntry ( *this, mask, pName ); mask = *pEntry; } } return mask; } -// -// casEventMask::show() -// -void casEventMask::show(unsigned level) const +void casEventMask::show ( unsigned level ) const { - if (level>0u) { - printf ("casEventMask = %x\n", this->mask); + if ( level > 0u ) { + printf ( "casEventMask = %x\n", this->mask ); } } -casEventMask::casEventMask (casEventRegistry ®, const char *pName) +casEventMask::casEventMask ( casEventRegistry & reg, const char * pName ) { - *this = reg.registerEvent (pName); + *this = reg.registerEvent ( pName ); } -// -// casEventRegistry::show() -// -void casEventRegistry::show(unsigned level) const +void casEventRegistry::show ( unsigned level ) const { - if (level>1u) { + if ( level > 1u ) { printf ("casEventRegistry: bit allocator = %d\n", this->maskBitAllocator); } - this->resTable ::show(level); + this->resTable < casEventMaskEntry, stringId >::show ( level ); } -// -// casEventMaskEntry::casEventMaskEntry() -// -casEventMaskEntry::casEventMaskEntry( - casEventRegistry ®In, casEventMask maskIn, const char *pName) : - casEventMask (maskIn), stringId (pName), reg (regIn) +casEventMaskEntry::casEventMaskEntry ( + casEventRegistry & regIn, casEventMask maskIn, const char * pName ) : + casEventMask ( maskIn ), stringId ( pName ), reg ( regIn ) { int stat; - assert (this->resourceName()!=NULL); - stat = this->reg.add(*this); - assert (stat==0); + assert ( this->resourceName() != NULL ); + stat = this->reg.add ( *this ); + assert ( stat == 0 ); } -// -// casEventMaskEntry::~casEventMaskEntry() -// -// empty destructor forces virtual -// -// (not inline so that we avoid duplication resulting -// in the object code created by some compilers) -// casEventMaskEntry::~casEventMaskEntry() { - this->reg.remove (*this); + this->reg.remove ( *this ); } -// -// casEventMaskEntry::destroy() -// -void casEventMaskEntry::destroy() +void casEventMaskEntry::destroy () { delete this; } -// -// casEventMaskEntry::show() -// -void casEventMaskEntry::show (unsigned level) const +void casEventMaskEntry::show ( unsigned level ) const { - this->casEventMask::show(level); - this->stringId::show(level); + this->casEventMask::show ( level ); + this->stringId::show ( level ); } diff --git a/src/cas/generic/casEventMask.h b/src/cas/generic/casEventMask.h index 785e0675d..3f47a6bb7 100644 --- a/src/cas/generic/casEventMask.h +++ b/src/cas/generic/casEventMask.h @@ -47,26 +47,26 @@ public: this->mask = 0u; } - casEventMask (casEventRegistry ®, const char *pName); + casEventMask ( casEventRegistry ®, const char *pName ); casEventMask () { this->clear(); } - void show (unsigned level) const; + void show ( unsigned level ) const; - int eventsSelected() + bool eventsSelected () const { - return this->mask!=0u; + return this->mask != 0u; } - int noEventsSelected() + bool noEventsSelected () const { - return this->mask==0u; + return this->mask == 0u; } - inline void operator|= (const casEventMask &rhs); - inline void operator&= (const casEventMask &rhs); + inline void operator |= ( const casEventMask & rhs ); + inline void operator &= ( const casEventMask & rhs ); private: unsigned mask; diff --git a/src/cas/generic/casEventSys.cc b/src/cas/generic/casEventSys.cc index 1a39c67de..7642a8638 100644 --- a/src/cas/generic/casEventSys.cc +++ b/src/cas/generic/casEventSys.cc @@ -15,38 +15,30 @@ * 505 665 1831 */ -/* - * ANSI C - */ #include -/* - * EPICS - */ -#include "server.h" -#include "casEventSysIL.h" // casMonitor inline func +#define epicsExportSharedSymbols +#include "caHdrLargeArray.h" +#include "casCoreClient.h" +#include "casAsyncIOI.h" +#include "casChannelI.h" -// -// casEventSys::show() -// void casEventSys::show(unsigned level) const { + epicsGuard < epicsMutex > guard ( this->mutex ); printf ( "casEventSys at %p\n", static_cast ( this ) ); if (level>=1u) { - printf ("\tnumEventBlocks = %u, maxLogEntries = %u\n", - this->numEventBlocks, this->maxLogEntries); - printf ("\tthere are %d events in the queue\n", - this->eventLogQue.count()); - printf ("Replace events flag = %d, dontProcess flag = %d\n", + printf ( "\numSubscriptions = %u, maxLogEntries = %u\n", + this->numSubscriptions, this->maxLogEntries ); + printf ( "\tthere are %d events in the queue\n", + this->eventLogQue.count() ); + printf ( "Replace events flag = %d, dontProcess flag = %d\n", static_cast < int > ( this->replaceEvents ), static_cast < int > ( this->dontProcess ) ); } } -// -// casEventSys::~casEventSys() -// casEventSys::~casEventSys() { if ( this->pPurgeEvent != NULL ) { @@ -54,44 +46,53 @@ casEventSys::~casEventSys() delete this->pPurgeEvent; } - /* - * all active event blocks must be canceled first - */ - casVerify ( this->numEventBlocks == 0 ); + // at this point: + // o all channels delete + // o all IO deleted + // o any subscription events remaining on the queue + // are pending destroy - while ( casEvent * pE = this->eventLogQue.get () ) { - pE->eventSysDestroyNotify ( this->client ); - } + // this will clean up the event queue because all + // channels have been deleted and any events left on + // the queue are there because they are going to + // execute a subscription delete + this->process (); + + // verify above assertion is true + casVerify ( this->eventLogQue.count() == 0 ); + + // all active subscriptions should also have been + // uninstalled + casVerify ( this->numSubscriptions == 0 ); + if ( this->numSubscriptions != 0 ) { + printf ( "numSubscriptions=%u\n", this->numSubscriptions ); + } } -// -// casEventSys::installMonitor() -// -void casEventSys::installMonitor() +void casEventSys::installMonitor () { - this->numEventBlocks++; + epicsGuard < epicsMutex > guard ( this->mutex ); + assert ( this->numSubscriptions < UINT_MAX ); + this->numSubscriptions++; this->maxLogEntries += averageEventEntries; } -// -// casEventSys::removeMonitor () -// void casEventSys::removeMonitor () { - assert (this->numEventBlocks>=1u); - this->numEventBlocks--; + epicsGuard < epicsMutex > guard ( this->mutex ); + assert ( this->numSubscriptions >= 1u ); + this->numSubscriptions--; this->maxLogEntries -= averageEventEntries; } -// -// casEventSys::process() -// casEventSys::processStatus casEventSys::process () { casEventSys::processStatus ps; ps.cond = casProcOk; ps.nAccepted = 0u; + epicsGuard < epicsMutex > guard ( this->mutex ); + while ( ! this->dontProcess ) { casEvent * pEvent; @@ -101,14 +102,15 @@ casEventSys::processStatus casEventSys::process () break; } - caStatus status = pEvent->cbFunc ( this->client ); + caStatus status = pEvent->cbFunc ( + this->client, guard ); if ( status == S_cas_success ) { ps.nAccepted++; } else if ( status == S_cas_sendBlocked ) { // not accepted so return to the head of the list // (we will try again later) - this->pushOnToEventQueue ( *pEvent ); + this->eventLogQue.push ( *pEvent ); ps.cond = casProcOk; break; } @@ -140,11 +142,10 @@ casEventSys::processStatus casEventSys::process () return ps; } -// -// casEventSys::eventsOn() -// -void casEventSys::eventsOn() +void casEventSys::eventsOn () { + epicsGuard < epicsMutex > guard ( this->mutex ); + // // allow multiple events for each monitor // @@ -165,62 +166,188 @@ void casEventSys::eventsOn() } } -// -// casEventSys::eventsOff() -// -void casEventSys::eventsOff() +bool casEventSys::eventsOff () { - // - // new events will replace the last event on - // the queue for a particular monitor - // - this->replaceEvents = true; + bool signalNeeded = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); - // - // suppress the processing and sending of events - // only after we have purged the event queue - // for this particular client - // - if ( this->pPurgeEvent == NULL ) { - this->pPurgeEvent = new casEventPurgeEv ( *this ); - if ( this->pPurgeEvent == NULL ) { - // - // if there is no room for the event then immediately - // stop processing and sending events to the client - // until we exit flow control - // - this->dontProcess = true; - } - else { - this->casEventSys::addToEventQueue ( *this->pPurgeEvent ); - } - } + // + // new events will replace the last event on + // the queue for a particular monitor + // + this->replaceEvents = true; + + // + // suppress the processing and sending of events + // only after we have purged the event queue + // for this particular client + // + if ( this->pPurgeEvent == NULL ) { + this->pPurgeEvent = new casEventPurgeEv ( *this ); + if ( this->pPurgeEvent == NULL ) { + // + // if there is no room for the event then immediately + // stop processing and sending events to the client + // until we exit flow control + // + this->dontProcess = true; + } + else { + if ( this->eventLogQue.count() == 0 ) { + signalNeeded = true; + } + this->eventLogQue.add ( *this->pPurgeEvent ); + signalNeeded = true; + } + } + } + return signalNeeded; } -// -// casEventPurgeEv::casEventPurgeEv () -// casEventPurgeEv::casEventPurgeEv ( casEventSys & evSysIn ) : evSys ( evSysIn ) { } -// -// casEventPurgeEv::cbFunc() -// -caStatus casEventPurgeEv::cbFunc ( casCoreClient & ) +caStatus casEventPurgeEv::cbFunc ( casCoreClient &, epicsGuard < epicsMutex > & guard ) { this->evSys.dontProcess = true; this->evSys.pPurgeEvent = NULL; - - delete this; + { + epicsGuardRelease < epicsMutex > unklocker ( guard ); + delete this; + } return S_cas_success; } -void casEventPurgeEv::eventSysDestroyNotify ( casCoreClient & ) +caStatus casEventSys::addToEventQueue ( casAsyncIOI & event, + bool & onTheQueue, bool & posted, bool & wakeupNeeded ) { - delete this; + wakeupNeeded = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); + // dont allow them to post completion more than once + if ( posted || onTheQueue ) { + return S_cas_redundantPost; + } + posted = true; + onTheQueue = true; + wakeupNeeded = ! this->dontProcess && this->eventLogQue.count() == 0; + this->eventLogQue.add ( event ); + } + + return S_cas_success; } +bool casEventSys::addToEventQueue ( casChannelI & event, bool & inTheEventQueue ) +{ + bool wakeupRequired = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); + if ( ! inTheEventQueue ) { + inTheEventQueue = true; + wakeupRequired = ! this->dontProcess && this->eventLogQue.count()==0; + this->eventLogQue.add ( event ); + } + } + return wakeupRequired; +} + +void casEventSys::removeFromEventQueue ( casMonEvent & event ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->eventLogQue.remove ( event ); +} +void casEventSys::removeFromEventQueue ( casAsyncIOI & io, bool & onTheEventQueue ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + if ( onTheEventQueue ) { + onTheEventQueue = false; + this->eventLogQue.remove ( io ); + } +} + +void casEventSys::setDestroyPending () +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + this->destroyPending = true; +} + +inline bool casEventSys::full () const // X aCC 361 +{ + if ( this->replaceEvents || this->eventLogQue.count() >= this->maxLogEntries ) { + return true; + } + else { + return false; + } +} + +bool casEventSys::postEvent ( tsDLList < casMonitor > & monitorList, + const casEventMask & select, const gdd & event ) +{ + bool signalNeeded = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); + tsDLIter < casMonitor > iter = monitorList.firstIter (); + while ( iter.valid () ) { + if ( iter->selected ( select ) ) { + // get a new block if we havent exceeded quotas + bool full = ( iter->numEventsQueued() >= individualEventEntries ) + || this->full (); + casMonEvent * pLog; + if ( ! full ) { + // should I get rid of this try block by implementing a no + // throw version of the free list alloc? However, crude + // tests on windows with ms visual C++ dont appear to argue + // against the try block. + try { + pLog = new ( this->casMonEventFreeList ) + casMonEvent ( *iter, event ); + } + catch ( ... ) { + pLog = 0; + } + } + else { + pLog = 0; + } + + if ( this->eventLogQue.count() == 0 ) { + signalNeeded = true; + } + iter->installNewEventLog ( this->eventLogQue, pLog, event ); + } + ++iter; + } + } + return signalNeeded; +} + +void casEventSys::casMonEventDestroy ( + casMonEvent & ev, epicsGuard < epicsMutex > & guard ) +{ + guard.assertIdenticalMutex ( this->mutex ); + ev.~casMonEvent (); + this->casMonEventFreeList.release ( & ev ); +} + +void casEventSys::prepareMonitorForDestroy ( casMonitor & mon ) +{ + bool safeToDestroy = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); + mon.markDestroyPending (); + // if events reference it on the queue then it gets + // deleted when it reaches the top of the queue + if ( mon.numEventsQueued () == 0 ) { + safeToDestroy = true; + } + } + if ( safeToDestroy ) { + this->client.destroyMonitor ( mon ); + } +} diff --git a/src/cas/generic/casEventSysIL.h b/src/cas/generic/casEventSysIL.h deleted file mode 100644 index 5ddf1b574..000000000 --- a/src/cas/generic/casEventSysIL.h +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#ifndef casEventSysIL_h -#define casEventSysIL_h - -// -// casEventSys::casEventSys () -// -inline casEventSys::casEventSys ( casCoreClient & clientIn ) : - client ( clientIn ), - pPurgeEvent ( NULL ), - numEventBlocks ( 0u ), - maxLogEntries ( individualEventEntries ), - destroyPending ( false ), - replaceEvents ( false ), - dontProcess ( false ) -{ -} - -// -// casEventSys::addToEventQueue() -// -inline void casEventSys::addToEventQueue ( casEvent & event ) -{ - this->eventLogQue.add ( event ); - - // - // wake up the event queue consumer only if - // we are not supressing events to a client that - // is in flow control - // - if ( ! this->dontProcess ) { - this->client.eventSignal (); - } -} - -// -// casEventSys::setDestroyPending() -// -inline void casEventSys::setDestroyPending() -{ - this->destroyPending = true; - // - // wakes up the event queue consumer - // - this->client.eventSignal (); -} - -// -// casEventSys::insertEventQueue() -// -inline void casEventSys::insertEventQueue( casEvent & insert, casEvent & prevEvent ) -{ - this->eventLogQue.insertAfter ( insert, prevEvent ); -} - -// -// casEventSys::pushOnToEventQueue() -// -inline void casEventSys::pushOnToEventQueue ( casEvent & event ) -{ - this->eventLogQue.push ( event ); -} - -// -// casEventSys::removeFromEventQueue() -// -inline void casEventSys::removeFromEventQueue ( casEvent & event ) -{ - this->eventLogQue.remove ( event ); -} - -// -// casEventSys::full() -// -inline bool casEventSys::full() // X aCC 361 -{ - if ( this->replaceEvents || this->eventLogQue.count() >= this->maxLogEntries ) { - return true; - } - else { - return false; - } -} - -#endif // casEventSysIL_h - diff --git a/src/cas/generic/casInternal.h b/src/cas/generic/casInternal.h deleted file mode 100644 index c4a508bc7..000000000 --- a/src/cas/generic/casInternal.h +++ /dev/null @@ -1,451 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -// -// EPICS -// -#include "cxxCompilerDependencies.h" -#include "tsDLList.h" -#include "tsFreeList.h" -#include "resourceLib.h" -#define CA_MINOR_PROTOCOL_REVISION 11 -#include "caProto.h" -#include "smartGDDPointer.h" - -typedef aitUint32 caResId; - -class casChannelI; -class casCoreClient; - -// -// casEvent -// -class casEvent : public tsDLNode < casEvent > { -public: - virtual caStatus cbFunc ( casCoreClient & ) = 0; - virtual void eventSysDestroyNotify ( casCoreClient & ) = 0; -protected: - epicsShareFunc virtual ~casEvent(); -}; - -class casChanDelEv : public casEvent { -public: - casChanDelEv ( caResId idIn ) : id(idIn) {} - ~casChanDelEv (); -private: - caResId id; - caStatus cbFunc ( casCoreClient & ); - void eventSysDestroyNotify ( casCoreClient & ); -}; - -enum casResType {casChanT=1, casMonitorT, casPVT}; - -class casRes : public chronIntIdRes -{ -public: - casRes (); - epicsShareFunc virtual ~casRes(); - virtual casResType resourceType () const = 0; - virtual void show ( unsigned level ) const = 0; - //virtual void destroy() = 0; -private: - casRes ( const casRes & ); - casRes & operator = ( const casRes & ); -}; - -class ioBlockedList; -class epicsMutex; - -// -// ioBlocked -// -class ioBlocked : public tsDLNode { -friend class ioBlockedList; -public: - ioBlocked (); - virtual ~ioBlocked (); -private: - ioBlockedList * pList; - virtual void ioBlockedSignal (); -}; - -// -// ioBlockedList -// -class ioBlockedList : private tsDLList { -friend class ioBlocked; -public: - ioBlockedList (); - epicsShareFunc virtual ~ioBlockedList (); - void signal (); - void addItemToIOBLockedList (ioBlocked &item); - ioBlockedList ( const ioBlockedList & ); - ioBlockedList & operator = ( const ioBlockedList & ); -}; - -class casMonitor; - -// -// casMonEvent -// -class casMonEvent : public casEvent { -public: - casMonEvent (); - casMonEvent (casMonitor &monitor, const smartConstGDDPointer &pNewValue); - casMonEvent (const casMonEvent &initValue); - ~casMonEvent (); - smartConstGDDPointer getValue () const; - void operator = (const class casMonEvent &monEventIn); - void clear (); - void assign (casMonitor &monitor, const smartConstGDDPointer &pValueIn); - void * operator new ( size_t size, tsFreeList < class casMonEvent, 1024 > & ); - epicsPlacementDeleteOperator (( void *, tsFreeList < class casMonEvent, 1024 > & )) -private: - smartConstGDDPointer pValue; - caResId id; - void * operator new ( size_t ); - void operator delete ( void * ); - caStatus cbFunc ( casCoreClient & ); - void eventSysDestroyNotify ( casCoreClient & ); -}; - -class casMonitorCallbackInterface { // X aCC 655 -public: - virtual caStatus casMonitorCallBack ( casMonitor &, - const smartConstGDDPointer & pValue ) = 0; -}; - -// -// casMonitor() -// -class casMonitor : - public tsDLNode < casMonitor >, public casRes { -public: - casMonitor ( caResId clientIdIn, casChannelI & chan, - unsigned long nElem, unsigned dbrType, - const casEventMask & maskIn, - casMonitorCallbackInterface & ); - virtual ~casMonitor(); - - void show ( unsigned level ) const; - - caStatus executeEvent ( casMonEvent & ); - - void postEvent ( class casEventSys & evSys, - const casEventMask & select, - const smartConstGDDPointer & pValue ); - - caResId getClientId () const - { - return this->clientId; - } - - unsigned getType () const - { - return this->dbrType; - } - - unsigned long getCount () const - { - return this->nElem; - } - casChannelI & getChannel () const - { - return this->ciu; - } - void * operator new ( size_t size, - tsFreeList < casMonitor, 1024 > & ) - epicsThrows ( (std::bad_alloc) ); - epicsPlacementDeleteOperator (( void *, - tsFreeList < casMonitor, 1024 > & )) - -private: - casMonEvent overFlowEvent; - unsigned long const nElem; - casChannelI & ciu; - casMonitorCallbackInterface & callBackIntf; - const casEventMask mask; - caResId const clientId; - unsigned char const dbrType; - unsigned char nPend; - bool ovf; - bool enabled; - void enable (); - void disable (); - casResType resourceType () const; - void push ( casEventSys & evSys, const smartConstGDDPointer & pValue ); - void * operator new ( size_t ); - void operator delete ( void * ); - casMonitor ( const casMonitor & ); - casMonitor & operator = ( const casMonitor & ); -}; - -// -// casMonitor::postEvent() -// (check for NOOP case in line) -// -inline void casMonitor::postEvent ( casEventSys & evSys, - const casEventMask & select, const smartConstGDDPointer & pValue) -{ - casEventMask result ( select & this->mask ); - - // - // NOOP if this event isnt selected - // or if it is disabled - // - if ( result.noEventsSelected() || ! this->enabled ) { - return; - } - - // - // else push it on the queue - // - this->push ( evSys, pValue ); -} - -class caServer; -class casChannelI; -class casCtx; -class caServer; -class casAsyncReadIO; -class casAsyncWriteIO; -class casAsyncPVExistIO; -class casAsyncPVAttachIO; - -class casAsyncIOI : public casEvent, public tsDLNode { -public: - casAsyncIOI ( const casCtx & ctx ); - epicsShareFunc virtual ~casAsyncIOI (); - - void serverDestroyIfReadOP (); - void serverDestroy (); - - caServer *getCAS () const; - - bool onTheEventQueue () const - { - return this->inTheEventQueue; - } - -protected: - casCoreClient & client; - - // - // place notification of IO completion on the event queue - // - caStatus postIOCompletionI(); - -private: - bool inTheEventQueue; - bool posted; - bool ioComplete; - bool serverDelete; - bool duplicate; - - // - // casEvent virtual call back function - // (called when IO completion event reaches top of event queue) - // - epicsShareFunc caStatus cbFunc ( casCoreClient & ); - - epicsShareFunc void eventSysDestroyNotify ( casCoreClient & ); - - // - // derived class specic call back - // (called when IO completion event reaches top of event queue) - // - epicsShareFunc virtual caStatus cbFuncAsyncIO() = 0; - epicsShareFunc virtual void destroy (); - - epicsShareFunc virtual bool readOP() const; - - casAsyncIOI ( const casAsyncIOI & ); - casAsyncIOI & operator = ( const casAsyncIOI & ); -}; - -class casDGClient; - -class casChannel; -class casPVI; - -// -// casChannelI -// -// this derives from casEvent so that access rights -// events can be posted -// -class casChannelI : public tsDLNode < casChannelI >, - public casRes, public casEvent { -public: - casChannelI ( const casCtx & ctx ); - epicsShareFunc virtual ~casChannelI (); - - class casCoreClient & getClient () const - { - return *this->pClient; - } - const caResId getCID () - { - return this->cid; - } - // - // fetch the unsigned integer server id for this PV - // - const caResId getSID (); - - void installMonitor ( - caResId clientId, - const unsigned long count, - const unsigned type, - const casEventMask & ); - - bool unistallMonitor ( ca_uint32_t monId ); - - casPVI &getPVI () const - { - return *this->pPV; - } - - void installAsyncIO ( casAsyncIOI & ); - void removeAsyncIO ( casAsyncIOI & ); - - void postEvent ( const casEventMask & select, const gdd & event ); - - epicsShareFunc virtual casResType resourceType () const; - - void destroyNoClientNotify (); - void destroyClientNotify (); - - void clearOutstandingReads (); - - void postAccessRightsEvent (); - - const gddEnumStringTable & enumStringTable () const; - - // - // virtual functions - // - epicsShareFunc virtual void setOwner ( const char * const pUserName, - const char * const pHostName ) = 0; - epicsShareFunc virtual bool readAccess () const = 0; - epicsShareFunc virtual bool writeAccess () const = 0; - epicsShareFunc virtual bool confirmationRequested () const = 0; - epicsShareFunc virtual void show ( unsigned level ) const; - -protected: - tsDLList < casMonitor > monitorList; - tsDLList < casAsyncIOI > ioInProgList; - class casCoreClient * pClient; - casPVI * pPV; - caResId cid; // client id - bool accessRightsEvPending; - - epicsShareFunc virtual void destroy (); - epicsShareFunc caStatus cbFunc ( casCoreClient & ); // access rights event call back - epicsShareFunc void eventSysDestroyNotify ( casCoreClient & ); - casChannelI ( const casChannelI & ); - casChannelI & operator = ( const casChannelI & ); -}; - -// -// class hierarchy added here solely because we need two list nodes -// -class casPVListChan : public casChannelI, public tsDLNode -{ -public: - casPVListChan ( const casCtx &ctx ); - epicsShareFunc virtual ~casPVListChan(); -private: - casPVListChan ( const casPVListChan & ); - casPVListChan & operator = ( const casPVListChan & ); -}; - -class caServerI; -class casCtx; -class casChannel; -class casPV; - -// -// casPVI -// -class casPVI : - public tsSLNode, // server resource table installation - public casRes, // server resource table installation - public ioBlockedList // list of clients io blocked on this pv -{ -public: - casPVI (); - epicsShareFunc virtual ~casPVI (); - caServerI *getPCAS () const; - caStatus attachToServer ( caServerI & cas ); - aitIndex nativeCount (); - caStatus registerEvent (); - void unregisterEvent (); - void unregisterIO (); - void installChannel ( casPVListChan & chan ); - void removeChannel ( casPVListChan & chan ); - void deleteSignal (); - void postEvent ( const casEventMask & select, const gdd & event ); - caServer * getExtServer () const; - caStatus bestDBRType ( unsigned & dbrType ); - epicsShareFunc virtual casResType resourceType () const; - const gddEnumStringTable & enumStringTable () const; - caStatus updateEnumStringTable ( casCtx & ); - void updateEnumStringTableAsyncCompletion ( const gdd & resp ); - - // - // virtual functions in the public interface class - // - epicsShareFunc virtual void show ( unsigned level ) const; - epicsShareFunc virtual caStatus interestRegister () = 0; - epicsShareFunc virtual void interestDelete () = 0; - epicsShareFunc virtual caStatus beginTransaction () = 0; - epicsShareFunc virtual void endTransaction () = 0; - epicsShareFunc virtual caStatus read ( const casCtx & ctx, gdd & prototype ) = 0; - epicsShareFunc virtual caStatus write ( const casCtx & ctx, const gdd & value ) = 0; - epicsShareFunc virtual casChannel * createChannel ( const casCtx & ctx, - const char * const pUserName, const char * const pHostName ) = 0; - epicsShareFunc virtual aitEnum bestExternalType () const = 0; - epicsShareFunc virtual unsigned maxDimension () const = 0; - epicsShareFunc virtual aitIndex maxBound ( unsigned dimension ) const = 0; - epicsShareFunc virtual const char * getName () const = 0; - epicsShareFunc casPV *apiPointer (); //retuns NULL if casPVI isnt a base of casPV - -private: - tsDLList < casPVListChan > chanList; - gddEnumStringTable enumStrTbl; - caServerI * pCAS; - unsigned nMonAttached; - unsigned nIOAttached; - bool destroyInProgress; - - epicsShareFunc virtual void destroy (); // casPVI destructor noop - casPVI ( const casPVI & ); - casPVI & operator = ( const casPVI & ); -}; - -/* a modified ca header with capacity for large arrays */ -struct caHdrLargeArray { - ca_uint32_t m_postsize; /* size of message extension */ - ca_uint32_t m_count; /* operation data count */ - ca_uint32_t m_cid; /* channel identifier */ - ca_uint32_t m_available; /* protocol stub dependent */ - ca_uint16_t m_dataType; /* operation data type */ - ca_uint16_t m_cmmd; /* operation to be performed */ -}; - - diff --git a/src/cas/generic/casMonEvent.cc b/src/cas/generic/casMonEvent.cc index c5ac711f1..49eb5f934 100644 --- a/src/cas/generic/casMonEvent.cc +++ b/src/cas/generic/casMonEvent.cc @@ -17,72 +17,36 @@ #include -#include "server.h" -#include "casEventSysIL.h" // casEventSys in line func -#include "casMonEventIL.h" // casMonEvent in line func -#include "casCtxIL.h" // casCtx in line func -#include "casCoreClientIL.h" // casCoreClient in line func +#define epicsExportSharedSymbols +#include "casMonEvent.h" +#include "casMonitor.h" +#include "casCoreClient.h" -// -// casMonEvent::cbFunc() -// -caStatus casMonEvent::cbFunc ( casCoreClient & client ) +caStatus casMonEvent::cbFunc ( + casCoreClient & client, epicsGuard < epicsMutex > & guard ) { - caStatus status; - - // - // ignore this event if it is stale and there is - // no call back object associated with it - // - casMonitor * pMon = client.lookupMonitor ( this->id ); - if ( ! pMon ) { - // we know this isnt an overflow event because those are - // removed from the queue when the casMonitor object is - // destroyed - client.casMonEventDestroy ( *this ); - status = S_casApp_success; - } - else { - // this object may have been destroyed - // here by the executeEvent() call below - status = pMon->executeEvent ( *this ); - } - - return status; + return this->monitor.executeEvent ( + client, * this, this->pValue, guard ); } -void casMonEvent::eventSysDestroyNotify ( casCoreClient & client ) +void casMonEvent::assign ( const gdd & valueIn ) { - client.casMonEventDestroy ( *this ); + this->pValue = & valueIn; } -// -// casMonEvent::assign () -// -void casMonEvent::assign (casMonitor &monitor, const smartConstGDDPointer &pValueIn) +void casMonEvent::swapValues ( casMonEvent & in ) { - this->pValue = pValueIn; - this->id = monitor.casRes::getId(); + assert ( & in.monitor == & this->monitor ); + this->pValue.swap ( in.pValue ); } -// -// ~casMonEvent () -// (this is not in line because it is virtual in the base) -// casMonEvent::~casMonEvent () { - this->clear(); -} - -void * casMonEvent::operator new ( size_t size, - tsFreeList < class casMonEvent, 1024 > & freeList ) -{ - return freeList.allocate ( size ); } #ifdef CXX_PLACEMENT_DELETE -void casMonEvent::operator delete ( void *pCadaver, - tsFreeList < class casMonEvent, 1024 > & freeList ) epicsThrows(()) +void casMonEvent::operator delete ( void * pCadaver, + tsFreeList < class casMonEvent, 1024, epicsMutexNOOP > & freeList ) { freeList.release ( pCadaver, sizeof ( casMonEvent ) ); } diff --git a/src/cas/generic/casMonEventIL.h b/src/cas/generic/casMonEventIL.h deleted file mode 100644 index 31bbf6dba..000000000 --- a/src/cas/generic/casMonEventIL.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#ifndef casMonEventIL_h -#define casMonEventIL_h - -// -// casMonEvent::casMonEvent() -// -inline casMonEvent::casMonEvent () : - id(0u) {} - -// -// casMonEvent::casMonEvent() -// -inline casMonEvent::casMonEvent (casMonitor &monitor, const smartConstGDDPointer &pNewValue) : - pValue ( pNewValue ), - id ( monitor.casRes::getId () ) {} - -// -// casMonEvent::casMonEvent() -// -inline casMonEvent::casMonEvent (const casMonEvent &initValue) : - pValue ( initValue.pValue ), - id ( initValue.id ) {} - -// -// casMonEvent::operator = () -// -inline void casMonEvent::operator = (const class casMonEvent &monEventIn) -{ - this->pValue = monEventIn.pValue; - this->id = monEventIn.id; -} - -// -// casMonEvent::clear() -// -inline void casMonEvent::clear() -{ - this->pValue = NULL; - this->id = 0u; -} - -// -// casMonEvent::getValue() -// -inline smartConstGDDPointer casMonEvent::getValue() const -{ - return this->pValue; -} - -#endif // casMonEventIL_h - diff --git a/src/cas/generic/casMonitor.cc b/src/cas/generic/casMonitor.cc index fc1210208..8c7124d9c 100644 --- a/src/cas/generic/casMonitor.cc +++ b/src/cas/generic/casMonitor.cc @@ -15,229 +15,151 @@ * 505 665 1831 */ +#define epicsExportSharedSymbols +#include "casMonitor.h" +#include "casChannelI.h" -#include "server.h" -#include "casChannelIIL.h" // casChannelI inline func -#include "casEventSysIL.h" // casEventSys inline func -#include "casMonEventIL.h" // casMonEvent inline func -#include "casCtxIL.h" // casCtx inline func +casEvent::~casEvent () {} - -// -// casMonitor::casMonitor() -// casMonitor::casMonitor ( caResId clientIdIn, casChannelI & chan, - unsigned long nElemIn, + ca_uint32_t nElemIn, unsigned dbrTypeIn, const casEventMask & maskIn, casMonitorCallbackInterface & cb ) : + overFlowEvent ( *this ), nElem ( nElemIn ), - ciu ( chan ), + pChannel ( & chan ), callBackIntf ( cb ), mask ( maskIn ), clientId ( clientIdIn ), dbrType ( static_cast ( dbrTypeIn ) ), nPend ( 0u ), - ovf ( false ), - enabled ( false ) + ovf ( false ) { - assert ( &this->ciu ); assert ( dbrTypeIn <= 0xff ); - this->enable(); } -// -// casMonitor::~casMonitor() -// casMonitor::~casMonitor() { - this->disable(); - if ( this->ovf ) { - casCoreClient &client = this->ciu.getClient(); - client.removeFromEventQueue ( this->overFlowEvent ); - } } -// -// casMonitor::enable() -// -void casMonitor::enable() +caStatus casMonitor::response ( casCoreClient & client, + const smartConstGDDPointer & value ) { - if ( ! this->enabled && this->ciu.readAccess() ) { - this->enabled = true; - caStatus status = this->ciu.getPVI().registerEvent(); - if ( status ) { - errMessage ( status, - "Server tool failed to register event\n" ); - } - } + if ( this->pChannel ) { + // reconstruct request header + caHdrLargeArray msg; + msg.m_cmmd = CA_PROTO_EVENT_ADD; + msg.m_postsize = 0u; + msg.m_dataType = this->dbrType; + msg.m_count = this->nElem; + msg.m_cid = this->pChannel->getSID(); + msg.m_available = this->clientId; + return client.monitorResponse ( *this->pChannel, + msg, value, S_cas_success ); + } + else { + return S_cas_success; + } } -// -// casMonitor::disable() -// -void casMonitor::disable() +void casMonitor::installNewEventLog ( + tsDLList < casEvent > & eventLogQue, + casMonEvent * pLog, const gdd & event ) { - if ( this->enabled ) { - this->enabled = false; - this->ciu.getPVI().unregisterEvent(); - } -} - -// -// casMonitor::push() -// -void casMonitor::push ( casEventSys & evSys, - const smartConstGDDPointer & pNewValue ) -{ - casCoreClient & client = this->ciu.getClient (); - client.getCAS().incrEventsPostedCounter (); - - // - // get a new block if we havent exceeded quotas - // - bool full = ( this->nPend >= individualEventEntries ) || evSys.full (); - casMonEvent * pLog; - if ( ! full ) { - try { - // I should get rid of this try block by implementing a no - // throw version of the free list alloc - pLog = & client.casMonEventFactory ( *this, pNewValue ); - assert ( this->nPend != UCHAR_MAX ); - this->nPend++; // X aCC 818 - } - catch ( ... ) { - pLog = 0; - } - } - else { - pLog = 0; - } - if ( this->ovf ) { if ( pLog ) { - // swap values - smartConstGDDPointer pOldValue = this->overFlowEvent.getValue (); - if ( ! pOldValue ) { - assert ( 0 ); // due to limitations in class smartConstGDDPointer - } - // copy old OVF value into the new entry which must remain - // ordered in the queue where the OVF entry was before - pLog->assign ( *this, pOldValue ); - // copy new value into OVF event entry which must be last - this->overFlowEvent.assign ( *this, *pNewValue ); - // this inserts it out of order, but this is fixed below when the - // overflow event is removed from the queue - evSys.insertEventQueue ( *pLog, this->overFlowEvent ); + pLog->assign ( event ); + this->overFlowEvent.swapValues ( *pLog ); + eventLogQue.insertAfter ( *pLog, this->overFlowEvent ); + assert ( this->nPend != UCHAR_MAX ); + this->nPend++; // X aCC 818 } else { // replace the old OVF value with the current one - this->overFlowEvent.assign ( *this, pNewValue ); + this->overFlowEvent.assign ( event ); } // remove OVF entry (with its new value) from the queue so // that it ends up properly ordered at the back of the // queue - evSys.removeFromEventQueue ( this->overFlowEvent ); + eventLogQue.remove ( this->overFlowEvent ); pLog = & this->overFlowEvent; } - else if ( ! pLog ) { - // - // no log block - // => use the over flow block in the event structure - // - this->ovf = true; - this->overFlowEvent.assign ( * this, pNewValue ); + else { + if ( pLog == 0 ) { + // use the over flow block in the event structure + this->ovf = true; + pLog = & this->overFlowEvent; + } + pLog->assign ( event ); assert ( this->nPend != UCHAR_MAX ); this->nPend++; // X aCC 818 - pLog = &this->overFlowEvent; - } - - evSys.addToEventQueue ( * pLog ); + } + eventLogQue.add ( *pLog ); } -// -// casMonitor::executeEvent() -// -caStatus casMonitor::executeEvent ( casMonEvent & ev ) +caStatus casMonitor::executeEvent ( casCoreClient & client, + casMonEvent & ev, smartConstGDDPointer & pValue, + epicsGuard < epicsMutex > & guard ) { - smartConstGDDPointer pVal = ev.getValue (); - if ( ! pVal ) { - assert ( 0 ); + assert ( pValue.valid() ); + + if ( this->pChannel ) { + epicsGuardRelease < epicsMutex > unguard ( guard ); + caStatus status = this->callBackIntf.casMonitorCallBack ( + *this, pValue ); + if ( status != S_cas_success ) { + return status; + } } - - caStatus status; - { - status = - this->callBackIntf. - casMonitorCallBack ( *this, *pVal ); - } - - // - // if the event isnt accepted we will try - // again later (and the event returns to the queue) - // - if ( status ) { - return status; - } - - // - // decrement the count of the number of events pending - // + + client.getCAS().incrEventsProcessedCounter (); assert ( this->nPend != 0u ); this->nPend--; // X aCC 818 - - // + // delete event object if it isnt a cache entry // saved in the call back object - // - if ( &ev == &this->overFlowEvent ) { + if ( & ev == & this->overFlowEvent ) { assert ( this->ovf ); this->ovf = false; - ev.clear(); + this->overFlowEvent.clear (); } else { - this->ciu.getClient().casMonEventDestroy ( ev ); + client.casMonEventDestroy ( ev, guard ); } - this->ciu.getClient().getCAS().incrEventsProcessedCounter (); - - return S_cas_success; + if ( ! this->pChannel && this->nPend == 0 ) { + // we are careful here not to invert + // the lock hierarchy + epicsGuardRelease < epicsMutex > unguard ( guard ); + client.destroyMonitor ( *this ); + } + + return S_cas_success; } -// -// casMonitor::show(unsigned level) -// void casMonitor::show ( unsigned level ) const { if ( level > 1u ) { printf ( -"\tmonitor type=%u count=%lu client id=%u enabled=%u OVF=%u nPend=%u\n", - dbrType, nElem, clientId, enabled, ovf, nPend ); +"\tmonitor type=%u count=%lu client id=%u OVF=%u nPend=%u\n", + dbrType, nElem, clientId, ovf, nPend ); this->mask.show ( level ); } } -// -// casMonitor::resourceType() -// -casResType casMonitor::resourceType() const -{ - return casMonitorT; -} - void * casMonitor::operator new ( size_t size, tsFreeList < casMonitor, 1024 > & freeList ) - epicsThrows ( ( std::bad_alloc ) ) { return freeList.allocate ( size ); } #ifdef CXX_PLACEMENT_DELETE void casMonitor::operator delete ( void * pCadaver, - tsFreeList < casMonitor, 1024 > & freeList ) epicsThrows(()) + tsFreeList < casMonitor, 1024 > & freeList ) { freeList.release ( pCadaver ); } diff --git a/src/cas/generic/casOpaqueAddr.cc b/src/cas/generic/casOpaqueAddr.cc index ffd611030..02f2c870f 100644 --- a/src/cas/generic/casOpaqueAddr.cc +++ b/src/cas/generic/casOpaqueAddr.cc @@ -8,6 +8,7 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ +#define epicsExportSharedSymbols #include "casdef.h" // diff --git a/src/cas/generic/casPV.cc b/src/cas/generic/casPV.cc index 0becab6a7..3950d7888 100644 --- a/src/cas/generic/casPV.cc +++ b/src/cas/generic/casPV.cc @@ -15,17 +15,10 @@ * 505 665 1831 */ -// -// Notes: -// -// 1) Always verify that pPVI isnt nill prior to using it -// +#define epicsExportSharedSymbols +#include "casPVI.h" -#include "server.h" -#include "casPVIIL.h" // casPVI inline func -#include "casCtxIL.h" // casCtx inline func - -casPV::casPV () +casPV::casPV () : pPVI ( 0 ) { } @@ -33,7 +26,7 @@ casPV::casPV () // This constructor is preserved for backwards compatibility only. // Please do _not_ use this constructor. // -casPV::casPV (caServer &) +casPV::casPV ( caServer & ) : pPVI ( 0 ) { } @@ -136,17 +129,18 @@ aitIndex casPV::maxBound (unsigned /* dimension */) const // // casPV::show (unsigned level) // -void casPV::show (unsigned level) const +void casPV::show ( unsigned /* level */ ) const { - casPVI::show (level); } // // Server tool calls this function to post a PV event. // -void casPV::postEvent (const casEventMask &select, const gdd &event) +void casPV::postEvent ( const casEventMask &select, const gdd &event ) { - this->casPVI::postEvent (select, event); + if ( this->pPVI ) { + this->pPVI->postEvent ( select, event ); + } } // @@ -156,16 +150,14 @@ void casPV::postEvent (const casEventMask &select, const gdd &event) // into a server. // *************** // -caServer *casPV::getCAS () const +caServer * casPV::getCAS () const { - return this->casPVI::getExtServer (); + if ( this->pPVI ) { + return this->pPVI->getExtServer (); + } + else { + return 0; + } } -// -// casPV::apiPointer() -// -casPV *casPV::apiPointer () -{ - return this; -} diff --git a/src/cas/generic/casPVI.cc b/src/cas/generic/casPVI.cc index d6e363603..6f306fac3 100644 --- a/src/cas/generic/casPVI.cc +++ b/src/cas/generic/casPVI.cc @@ -15,118 +15,92 @@ * 505 665 1831 */ +#include "epicsGuard.h" #include "gddAppTable.h" // EPICS application type table #include "gddApps.h" #include "dbMapper.h" // EPICS application type table -#include "server.h" -#include "casPVIIL.h" // caServerI inline func +#define epicsExportSharedSymbols +#include "caServerDefs.h" +#include "caServerI.h" +#include "casPVI.h" +#include "chanIntfForPV.h" +#include "casAsyncIOI.h" +#include "casMonitor.h" -casRes::casRes () {} +casPVI::casPVI ( casPV & intf ) : + pCAS ( NULL ), pv ( intf ), + nMonAttached ( 0u ), nIOAttached ( 0u ) {} -// -// casPVI::casPVI() -// -casPVI::casPVI () : - pCAS (NULL), // initially there is no server attachment - nMonAttached (0u), - nIOAttached (0u), - destroyInProgress (false) -{ -} - -// -// casPVI::~casPVI() -// casPVI::~casPVI () { - this->destroyInProgress = true; - // - // only relevant if we are attached to a server + // all channels should have been destroyed + // (otherwise the server tool is yanking the + // PV out from under the server) // - if ( this->pCAS != NULL ) { - - epicsGuard < caServerI > guard ( * this->pCAS ); - - this->pCAS->removeItem ( *this ); - - // - // delete any attached channels - // - tsDLIter < casPVListChan > iter = this->chanList.firstIter (); - while ( iter.valid () ) { - tsDLIter < casPVListChan > tmp = iter; - ++tmp; - iter->destroyClientNotify (); - iter = tmp; - } - } + casVerify ( this->chanList.count() == 0u ); // // all outstanding IO should have been deleted // when we destroyed the channels // casVerify ( this->nIOAttached == 0u ); + if (this->nIOAttached) { + errlogPrintf ( "The number of IO objected supposedly attached is %u\n", this->nIOAttached ); + } // // all monitors should have been deleted // when we destroyed the channels // casVerify ( this->nMonAttached == 0u ); + + this->pv.pPVI = 0; + this->pv.destroy (); } // -// casPVI::deleteSignal() // check for none attached and delete self if so // +// this call must be protected by the server's lock +// ( which also protects channel creation) +// void casPVI::deleteSignal () { - // - // if we are not attached to a server then the - // following steps are not relevant - // - if ( this->pCAS ) { - // - // We dont take the PV lock here because - // the PV may be destroyed and we must - // keep the lock unlock pairs consistent - // (because the PV's lock is really a ref - // to the server's lock) - // - // This is safe to do because we take the PV - // lock when we add a new channel (and the - // PV lock is realy the server's lock) - // - epicsGuard < caServerI > guard ( * this->pCAS ); + bool destroyNeeded = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); - if ( this->chanList.count() == 0u ) { - this->pCAS->removeItem ( *this ); - this->pCAS = NULL; - // refresh the table whenever the server reattaches to the PV - this->enumStrTbl.clear (); - this->destroy (); - // - // !! dont access self after destroy !! - // - } - } + // + // if we are not attached to a server then the + // following steps are not relevant + // + if ( this->pCAS ) { + if ( this->chanList.count() == 0u ) { + this->pCAS = NULL; + // refresh the table whenever the server reattaches to the PV + this->enumStrTbl.clear (); + destroyNeeded = true; + } + } + } + + if ( destroyNeeded ) { + delete this; + } + + // !! dont access self after potential delete above !! } -// -// casPVI::destroy() -// -// This version of destroy() is provided only because it can -// be safely called in the casPVI destructor as a side effect -// of deleting the last channel. -// -void casPVI::destroy () +casPVI * casPVI::attachPV ( casPV & pv ) { + if ( ! pv.pPVI ) { + pv.pPVI = new ( std::nothrow ) casPVI ( pv ); + } + return pv.pPVI; } -// -// casPVI::attachToServer () -// caStatus casPVI::attachToServer ( caServerI & cas ) { if ( this->pCAS ) { @@ -139,11 +113,7 @@ caStatus casPVI::attachToServer ( caServerI & cas ) } } else { - // - // install the PV into the server - // - cas.installItem ( *this ); - this->pCAS = &cas; + this->pCAS = & cas; } return S_cas_success; } @@ -216,6 +186,8 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctx ) void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) { + epicsGuard < epicsMutex > guard ( this->mutex ); + // // keep trying to fill in the table if client disconnects // prevented previous asynchronous IO from finishing, but if @@ -297,85 +269,193 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp ) } } -// -// casPVI::registerEvent() -// -caStatus casPVI::registerEvent () +void casPVI::postEvent ( const casEventMask & select, const gdd & event ) { - caStatus status; - - epicsGuard < caServerI > guard ( * this->pCAS ); - this->nMonAttached++; - if ( this->nMonAttached == 1u ) { - status = this->interestRegister (); - } - else { - status = S_cas_success; - } - - return status; -} - -// -// casPVI::unregisterEvent() -// -void casPVI::unregisterEvent() -{ - epicsGuard < caServerI > guard ( * this->pCAS ); - this->nMonAttached--; - // - // Dont call casPV::interestDelete() when we are in - // casPVI::~casPVI() (and casPV no longr exists) - // - if ( this->nMonAttached == 0u && !this->destroyInProgress ) { - this->interestDelete(); + epicsGuard < epicsMutex > guard ( this->mutex ); + if ( this->nMonAttached ) { + // we are paying some significant locking overhead for + // these diagnostic counters + this->pCAS->updateEventsPostedCounter ( this->nMonAttached ); + tsDLIter < chanIntfForPV > iter = this->chanList.firstIter (); + while ( iter.valid () ) { + iter->postEvent ( select, event ); + ++iter; + } } } -// -// casPVI::getExtServer() -// (not inline because details of caServerI must not -// leak into server tool) -// -caServer *casPVI::getExtServer() const // X aCC 361 +caStatus casPVI::installMonitor ( + casMonitor & mon, tsDLList < casMonitor > & monitorList ) { - if (this->pCAS) { - return this->pCAS->getAdapter(); + bool newInterest = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); + assert ( this->nMonAttached < UINT_MAX ); + this->nMonAttached++; + if ( this->nMonAttached == 1u ) { + newInterest = true; + } + // use pv lock to protect channel's monitor list + monitorList.add ( mon ); + } + if ( newInterest ) { + return this->pv.interestRegister (); + } + else { + return S_cas_success; + } +} + +casMonitor * casPVI::removeMonitor ( + tsDLList < casMonitor > & list, ca_uint32_t clientIdIn ) +{ + casMonitor * pMon = 0; + bool noInterest = false; + { + // + // (it is reasonable to do a linear search here because + // sane clients will require only one or two monitors + // per channel) + // + epicsGuard < epicsMutex > guard ( this->mutex ); + tsDLIter < casMonitor > iter = list.firstIter (); + while ( iter.valid () ) { + if ( iter->matchingClientId ( clientIdIn ) ) { + list.remove ( *iter.pointer () ); + assert ( this->nMonAttached > 0 ); + this->nMonAttached--; + noInterest = + ( this->nMonAttached == 0u ); + pMon = iter.pointer (); + break; + } + iter++; + } + } + if ( noInterest ) { + this->pv.interestDelete (); + } + return pMon; +} + +caServer *casPVI::getExtServer () const // X aCC 361 +{ + if ( this->pCAS ) { + return this->pCAS->getAdapter (); } else { return NULL; } } -// -// casPVI::show() -// -void casPVI::show (unsigned level) const +void casPVI::show ( unsigned level ) const { - if (level>1u) { - printf ("CA Server PV: nChanAttached=%u nMonAttached=%u nIOAttached=%u\n", - this->chanList.count(), this->nMonAttached, this->nIOAttached); + epicsGuard < epicsMutex > guard ( this->mutex ); + printf ( "CA Server PV: nChanAttached=%u nMonAttached=%u nIOAttached=%u\n", + this->chanList.count(), this->nMonAttached, this->nIOAttached ); + if ( level >= 1u ) { + printf ( "\tBest external type = %d\n", this->bestExternalType() ); } - if (level>2u) { - printf ("\tBest external type = %d\n", this->bestExternalType()); + if ( level >= 2u ) { + this->pv.show ( level - 2u ); } } -// -// casPVI::resourceType() -// -casResType casPVI::resourceType() const +casPV * casPVI::apiPointer () { - return casPVT; + return & this->pv; } -// -// casPVI::apiPointer() -// retuns NULL if casPVI isnt a base of casPV -// -casPV *casPVI::apiPointer () +void casPVI::installChannel ( chanIntfForPV & chan ) { - return NULL; + epicsGuard < epicsMutex > guard ( this->mutex ); + this->chanList.add ( chan ); +} + +void casPVI::removeChannel ( + chanIntfForPV & chan, tsDLList < casMonitor > & src, + tsDLList < casMonitor > & dest ) +{ + bool noInterest = false; + { + epicsGuard < epicsMutex > guard ( this->mutex ); + src.removeAll ( dest ); + if ( dest.count() ) { + assert ( this->nMonAttached >= dest.count() ); + this->nMonAttached -= dest.count (); + noInterest = ( this->nMonAttached == 0u ); + } + this->chanList.remove ( chan ); + } + if ( noInterest ) { + this->pv.interestDelete (); + } +} + +void casPVI::clearOutstandingReads ( tsDLList < casAsyncIOI > & ioList ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + + // cancel any pending asynchronous IO + tsDLIter < casAsyncIOI > iterIO = + ioList.firstIter (); + while ( iterIO.valid () ) { + tsDLIter < casAsyncIOI > tmp = iterIO; + ++tmp; + if ( iterIO->oneShotReadOP () ) { + ioList.remove ( *iterIO ); + assert ( this->nIOAttached != 0 ); + this->nIOAttached--; + } + delete iterIO.pointer (); + iterIO = tmp; + } +} + +void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + while ( casAsyncIOI * pIO = ioList.get() ) { + pIO->removeFromEventQueue (); + delete pIO; + assert ( this->nIOAttached != 0 ); + this->nIOAttached--; + } +} + +void casPVI::installIO ( + tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io ) +{ + epicsGuard < epicsMutex > guard ( this->mutex ); + ioList.add ( io ); + assert ( this->nIOAttached != UINT_MAX ); + this->nIOAttached++; +} + +void casPVI::uninstallIO ( + tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io ) +{ + { + epicsGuard < epicsMutex > guard ( this->mutex ); + ioList.remove ( io ); + assert ( this->nIOAttached != 0 ); + this->nIOAttached--; + } + this->ioBlockedList::signal(); +} + +caStatus casPVI::bestDBRType ( unsigned & dbrType ) // X aCC 361 +{ + aitEnum bestAIT = this->bestExternalType (); + if ( bestAIT == aitEnumInvalid || bestAIT < 0 ) { + return S_cas_badType; + } + unsigned aitIndex = static_cast < unsigned > ( bestAIT ); + if ( aitIndex >= sizeof ( gddAitToDbr ) / sizeof ( gddAitToDbr[0] ) ) { + return S_cas_badType; + } + dbrType = gddAitToDbr[bestAIT]; + return S_cas_success; } diff --git a/src/cas/generic/casPVIIL.h b/src/cas/generic/casPVIIL.h deleted file mode 100644 index 3e4a605e9..000000000 --- a/src/cas/generic/casPVIIL.h +++ /dev/null @@ -1,121 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#ifndef casPVIIL_h -#define casPVIIL_h - -#include "dbMapper.h" -#include "caServerIIL.h" - -// -// casPVI::getPCAS() -// -inline caServerI *casPVI::getPCAS() const -{ - return this->pCAS; -} - -// -// casPVI::installChannel() -// -inline void casPVI::installChannel ( casPVListChan & chan ) -{ - epicsGuard < caServerI > guard ( * this->pCAS ); - this->chanList.add(chan); -} - -// -// casPVI::removeChannel() -// -inline void casPVI::removeChannel ( casPVListChan & chan ) -{ - epicsGuard < caServerI > guard ( * this->pCAS ); - this->chanList.remove(chan); -} - -// -// casPVI::unregisterIO() -// -inline void casPVI::unregisterIO() -{ - this->ioBlockedList::signal(); -} - -// -// casPVI::bestDBRType() -// -inline caStatus casPVI::bestDBRType ( unsigned & dbrType ) // X aCC 361 -{ - aitEnum bestAIT = this->bestExternalType (); - if ( bestAIT == aitEnumInvalid || bestAIT < 0 ) { - return S_cas_badType; - } - unsigned aitIndex = static_cast < unsigned > ( bestAIT ); - if ( aitIndex >= NELEMENTS ( gddAitToDbr ) ) { - return S_cas_badType; - } - dbrType = gddAitToDbr[bestAIT]; - return S_cas_success; -} - -#include "casChannelIIL.h" // inline func for casChannelI - -// -// functions that use casChannelIIL.h below here -// - -// -// casPVI::postEvent() -// -inline void casPVI::postEvent (const casEventMask &select, const gdd &event) -{ - if ( this->nMonAttached == 0u ) { - return; - } - - epicsGuard < caServerI > guard ( * this->pCAS ); - tsDLIter < casPVListChan > iter = this->chanList.firstIter (); - while ( iter.valid () ) { - iter->postEvent ( select, event ); - ++iter; - } -} - -// -// CA only does 1D arrays for now -// -inline aitIndex casPVI::nativeCount () -{ - if (this->maxDimension()==0u) { - return 1u; // scalar - } - return this->maxBound(0u); -} - -// -// casPVI::enumStringTable () -// -inline const gddEnumStringTable & casPVI::enumStringTable () const -{ - return this->enumStrTbl; -} - -#endif // casPVIIL_h - - - diff --git a/src/cas/generic/casPVListChan.cc b/src/cas/generic/casPVListChan.cc deleted file mode 100644 index 90edf175a..000000000 --- a/src/cas/generic/casPVListChan.cc +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#include "server.h" -#include "casPVIIL.h" - -// -// casPVListChan::casPVListChan() -// -casPVListChan::casPVListChan (const casCtx &ctx) : - casChannelI(ctx) -{ -} - -// -// casPVListChan::~casPVListChan() -// -casPVListChan::~casPVListChan() -{ - this->pPV->removeChannel(*this); - // - // delete signal to PV occurs in - // casChannelI::~casChannelI - // -} - diff --git a/src/cas/generic/casPVListChanIL.h b/src/cas/generic/casPVListChanIL.h deleted file mode 100644 index 9a12ba51f..000000000 --- a/src/cas/generic/casPVListChanIL.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -#ifndef casPVListChanIL_h -#define casPVListChanIL_h - -#include "casPVIIL.h" - -// -// empty for now since casPVListChan::casPVListChan() -// causes undefined sym when it is inline under g++ 2.7.x -// (without -O) -// - -#endif // casPVListChanIL_h - diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index 90535d8dd..0193d33bb 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -15,21 +15,21 @@ * 505 665 1831 */ +// *must* be defined before including net_convert.h +typedef unsigned long arrayElementCount; + +#include "osiWireFormat.h" +#include "net_convert.h" // byte order conversion from libca #include "dbMapper.h" // ait to dbr types #include "gddAppTable.h" // EPICS application type table #include "gddApps.h" // gdd predefined application type codes -typedef unsigned long arrayElementCount; -#include "net_convert.h" // byte order conversion from libca -#include "server.h" -#include "caServerIIL.h" // caServerI inline functions -#include "casChannelIIL.h" // casChannelI inline functions -#include "casCtxIL.h" // casCtx inline functions -#include "casEventSysIL.h" // casEventSys inline functions -#include "inBufIL.h" // inBuf inline functions -#include "outBufIL.h" // outBuf inline functions +#define epicsExportSharedSymbols +#include "casStrmClient.h" +#include "casChannelI.h" +#include "casAsyncIOI.h" -static const caHdr nill_msg = { 0u,0u,0u,0u,0u,0u }; +static const caHdr nill_msg = { 0u, 0u, 0u, 0u, 0u, 0u }; // // casStrmClient::casStrmClient() @@ -46,33 +46,20 @@ casStrmClient::casStrmClient ( caServerI & cas, clientBufMemoryManager & memMgr throw std::bad_alloc(); } *this->pUserName= '\0'; - this->ctx.getServer()->installClient ( this ); } // -// casStrmClient::~casStrmClient() +// casStrmClient::~casStrmClient () // -casStrmClient::~casStrmClient() +casStrmClient::~casStrmClient () { - this->ctx.getServer()->removeClient ( this ); - + while ( casChannelI * pChan = this->chanList.get() ) { + pChan->uninstallFromPV ( this->eventSys ); + this->chanTable.remove ( *pChan ); + delete pChan; + } delete [] this->pUserName; - delete [] this->pHostName; - - // - // delete all channels attached - // - tsDLIter iter = this->chanList.firstIter (); - while ( iter.valid () ) { - // - // destroying the channel removes it from the list - // - tsDLIter tmp = iter; - ++tmp; - iter->destroyNoClientNotify(); - iter = tmp; - } } // @@ -89,7 +76,7 @@ caStatus casStrmClient::uknownMessageAction () /* * most clients dont recover from this */ - status = this->sendErr ( mp, ECA_INTERNAL, "Invalid Request Code" ); + status = this->sendErr ( mp, invalidResID, ECA_INTERNAL, "Invalid Request Code" ); if (status) { return status; } @@ -104,14 +91,15 @@ caStatus casStrmClient::uknownMessageAction () // // casStrmClient::verifyRequest() // -caStatus casStrmClient::verifyRequest (casChannelI *&pChan) +caStatus casStrmClient::verifyRequest ( casChannelI * & pChan ) { const caHdrLargeArray * mp = this->ctx.getMsg(); // // channel exists for this resource id ? // - pChan = this->lookupChannel ( mp->m_cid ); + chronIntId tmpId ( mp->m_cid ); + pChan = this->chanTable.lookup ( tmpId ); if ( ! pChan ) { return ECA_BADCHID; } @@ -119,33 +107,35 @@ caStatus casStrmClient::verifyRequest (casChannelI *&pChan) // // data type out of range ? // - if (mp->m_dataType>((unsigned)LAST_BUFFER_TYPE)) { + if ( mp->m_dataType > ((unsigned)LAST_BUFFER_TYPE) ) { return ECA_BADTYPE; } // // element count out of range ? // - if (mp->m_count > pChan->getPVI().nativeCount() || mp->m_count==0u) { + if ( mp->m_count > pChan->getPVI().nativeCount() || mp->m_count == 0u ) { return ECA_BADCOUNT; } + this->ctx.setChannel ( pChan ); + this->ctx.setPV ( &pChan->getPVI() ); + return ECA_NORMAL; } -// -// casStrmClient::show (unsigned level) -// void casStrmClient::show ( unsigned level ) const { - this->casClient::show (level); + epicsGuard < epicsMutex > locker ( this->mutex ); printf ( "casStrmClient at %p\n", static_cast ( this ) ); - if (level > 1u) { + if ( level > 1u ) { printf ("\tuser %s at %s\n", this->pUserName, this->pHostName); + this->casClient::show ( level - 1 ); + this->in.show ( level - 1 ); + this->out.show ( level - 1 ); + this->chanTable.show ( level - 1 ); } - this->in.show(level); - this->out.show(level); } /* @@ -158,40 +148,49 @@ caStatus casStrmClient::readAction () casChannelI *pChan; smartGDDPointer pDesc; - status = this->verifyRequest (pChan); - if (status != ECA_NORMAL) { - return this->sendErr(mp, status, "get request"); + status = this->verifyRequest ( pChan ); + if ( status != ECA_NORMAL ) { + if ( pChan ) { + return this->sendErr ( mp, pChan->getCID(), + status, "get request" ); + } + else { + return this->sendErr ( mp, invalidResID, + status, "get request" ); + } } /* * verify read access */ - if (!pChan->readAccess()) { + if ( ! pChan->readAccess() ) { int v41; - v41 = CA_V41(this->minor_version_number); - if(v41){ + v41 = CA_V41 ( this->minor_version_number ); + if ( v41 ) { status = ECA_NORDACCESS; } else{ status = ECA_GETFAIL; } - return this->sendErr(mp, status, "read access denied"); + return this->sendErr ( mp, pChan->getCID(), + status, "read access denied" ); } - status = this->read (pDesc); - if (status==S_casApp_success) { - status = this->readResponse(pChan, *mp, *pDesc, S_cas_success); + status = this->read ( pDesc ); + if ( status == S_casApp_success ) { + status = this->readResponse ( pChan, *mp, *pDesc, S_cas_success ); } - else if (status == S_casApp_asyncCompletion) { + else if ( status == S_casApp_asyncCompletion ) { status = S_cas_success; } - else if (status == S_casApp_postponeAsyncIO) { - pChan->getPVI().addItemToIOBLockedList(*this); + else if ( status == S_casApp_postponeAsyncIO ) { + pChan->getPVI().addItemToIOBLockedList ( *this ); } else { - status = this->sendErrWithEpicsStatus (mp, status, ECA_GETFAIL); + status = this->sendErrWithEpicsStatus ( mp, + pChan->getCID(), status, ECA_GETFAIL ); } return status; @@ -204,7 +203,8 @@ caStatus casStrmClient::readResponse ( casChannelI * pChan, const caHdrLargeArra const smartConstGDDPointer & pDesc, const caStatus status ) { if ( status != S_casApp_success ) { - return this->sendErrWithEpicsStatus ( & msg, status, ECA_GETFAIL ); + return this->sendErrWithEpicsStatus ( & msg, + pChan->getCID(), status, ECA_GETFAIL ); } epicsGuard < epicsMutex > guard ( this->mutex ); @@ -217,7 +217,8 @@ caStatus casStrmClient::readResponse ( casChannelI * pChan, const caHdrLargeArra msg.m_available, & pPayload ); if ( localStatus ) { if ( localStatus==S_cas_hugeRequest ) { - localStatus = sendErr ( &msg, ECA_TOLARGE, NULL ); + localStatus = sendErr ( &msg, pChan->getCID(), ECA_TOLARGE, + "unable to fit read response into server's buffer" ); } return localStatus; } @@ -230,17 +231,16 @@ caStatus casStrmClient::readResponse ( casChannelI * pChan, const caHdrLargeArra int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr( pPayload, msg.m_count, *pDesc, pChan->enumStringTable() ); if ( mapDBRStatus < 0 ) { - pDesc->dump(); - errPrintf (S_cas_badBounds, __FILE__, __LINE__, "- get with PV=%s type=%u count=%u", - pChan->getPVI().getName(), msg.m_dataType, msg.m_count); + pDesc->dump (); + errPrintf ( S_cas_badBounds, __FILE__, __LINE__, "- get with PV=%s type=%u count=%u", + pChan->getPVI().getName(), msg.m_dataType, msg.m_count ); return this->sendErrWithEpicsStatus ( - &msg, S_cas_badBounds, ECA_GETFAIL ); + & msg, pChan->getCID(), S_cas_badBounds, ECA_GETFAIL ); } #ifdef CONVERSION_REQUIRED ( * cac_dbr_cvrt[msg.m_dataType] ) ( pPayload, pPayload, true, msg.m_count ); #endif - if ( msg.m_dataType == DBR_STRING && msg.m_count == 1u ) { unsigned reducedPayloadSize = strlen ( static_cast < char * > ( pPayload ) ) + 1u; this->out.commitMsg ( reducedPayloadSize ); @@ -257,9 +257,9 @@ caStatus casStrmClient::readResponse ( casChannelI * pChan, const caHdrLargeArra // caStatus casStrmClient::readNotifyAction () { - const caHdrLargeArray *mp = this->ctx.getMsg(); + const caHdrLargeArray * mp = this->ctx.getMsg(); int status; - casChannelI *pChan; + casChannelI * pChan; smartGDDPointer pDesc; status = this->verifyRequest ( pChan ); @@ -270,8 +270,8 @@ caStatus casStrmClient::readNotifyAction () // // verify read access // - if (!pChan->readAccess()) { - if (CA_V41(this->minor_version_number)) { + if ( ! pChan->readAccess() ) { + if ( CA_V41 ( this->minor_version_number ) ) { return this->readNotifyFailureResponse ( *mp, ECA_NORDACCESS ); } else { @@ -279,18 +279,18 @@ caStatus casStrmClient::readNotifyAction () } } - status = this->read (pDesc); - if (status == S_casApp_success) { - status = this->readNotifyResponse (pChan, *mp, pDesc, status); + status = this->read ( pDesc ); + if ( status == S_casApp_success ) { + status = this->readNotifyResponse ( pChan, *mp, pDesc, status ); } - else if (status == S_casApp_asyncCompletion) { + else if ( status == S_casApp_asyncCompletion ) { status = S_cas_success; } - else if (status == S_casApp_postponeAsyncIO) { - pChan->getPVI().addItemToIOBLockedList(*this); + else if ( status == S_casApp_postponeAsyncIO ) { + pChan->getPVI().addItemToIOBLockedList ( *this ); } else { - status = this->readNotifyResponse(pChan, *mp, pDesc, status); + status = this->readNotifyResponse ( pChan, *mp, pDesc, status ); } return status; @@ -300,7 +300,8 @@ caStatus casStrmClient::readNotifyAction () // casStrmClient::readNotifyResponse() // caStatus casStrmClient::readNotifyResponse ( casChannelI * pChan, - const caHdrLargeArray & msg, const smartConstGDDPointer & pDesc, const caStatus completionStatus ) + const caHdrLargeArray & msg, const smartConstGDDPointer & pDesc, + const caStatus completionStatus ) { if ( completionStatus != S_cas_success ) { caStatus ecaStatus = this->readNotifyFailureResponse ( msg, ECA_GETFAIL ); @@ -317,7 +318,8 @@ caStatus casStrmClient::readNotifyResponse ( casChannelI * pChan, // The message is logged to the console in the rare situations when // we are unable to send. // - caStatus tmpStatus = this->sendErrWithEpicsStatus ( & msg, completionStatus, ECA_NOCONVERT ); + caStatus tmpStatus = this->sendErrWithEpicsStatus ( & msg, pChan->getCID(), + completionStatus, ECA_NOCONVERT ); if ( tmpStatus ) { errMessage ( completionStatus, "<= get callback failure detail not passed to client" ); } @@ -340,7 +342,8 @@ caStatus casStrmClient::readNotifyResponse ( casChannelI * pChan, msg.m_available, & pPayload ); if ( status ) { if ( status == S_cas_hugeRequest ) { - status = sendErr ( & msg, ECA_TOLARGE, NULL ); + status = sendErr ( & msg, pChan->getCID(), ECA_TOLARGE, + "unable to fit read notify response into server's buffer" ); } return status; } @@ -406,7 +409,7 @@ bool convertContainerMemberToAtomic ( gdd & dd, return true; } - gdd *pVal; + gdd * pVal; if ( dd.isContainer() ) { // All DBR types have a value member aitUint32 valIndex; @@ -531,8 +534,9 @@ caStatus casStrmClient::monitorResponse ( casChannelI & chan, const caHdrLargeAr msg.m_available, & pPayload ); if ( status ) { if ( status == S_cas_hugeRequest ) { - status = sendErr ( & msg, ECA_TOLARGE, - "unable to xmit event" ); + status = sendErr ( & msg, chan.getCID(), ECA_TOLARGE, + "unable to fit read subscription update response " + "into server's buffer" ); } return status; } @@ -575,10 +579,6 @@ caStatus casStrmClient::monitorResponse ( casChannelI & chan, const caHdrLargeAr } } - // - // there appears to be no success/fail - // status from this routine - // int mapDBRStatus = gddMapDbr[msg.m_dataType].conv_dbr ( pPayload, msg.m_count, *pDBRDD, chan.enumStringTable() ); if ( mapDBRStatus < 0 ) { @@ -613,9 +613,16 @@ caStatus casStrmClient::writeAction() caStatus status; casChannelI *pChan; - status = this->verifyRequest (pChan); + status = this->verifyRequest ( pChan ); if (status != ECA_NORMAL) { - return this->sendErr(mp, status, "put request"); + if ( pChan ) { + return this->sendErr ( mp, pChan->getCID(), + status, "get request" ); + } + else { + return this->sendErr ( mp, invalidResID, + status, "get request" ); + } } // @@ -632,21 +639,23 @@ caStatus casStrmClient::writeAction() status = ECA_PUTFAIL; } - return this->sendErr(mp, status, "write access denied"); + return this->sendErr(mp, pChan->getCID(), + status, "write access denied"); } // // initiate the write operation // status = this->write(); - if (status==S_casApp_success || status == S_casApp_asyncCompletion) { + if ( status == S_casApp_success || status == S_casApp_asyncCompletion ) { status = S_cas_success; } - else if (status==S_casApp_postponeAsyncIO) { - pChan->getPVI().addItemToIOBLockedList(*this); + else if ( status == S_casApp_postponeAsyncIO ) { + pChan->getPVI().addItemToIOBLockedList ( *this ); } else { - status = this->sendErrWithEpicsStatus(mp, status, ECA_PUTFAIL); + status = this->sendErrWithEpicsStatus ( mp, pChan->getCID(), + status, ECA_PUTFAIL ); // // I have assumed that the server tool has deleted the gdd here // @@ -655,23 +664,21 @@ caStatus casStrmClient::writeAction() // // The gdd created above is deleted by the server tool // - return status; - } // // casStrmClient::writeResponse() // -caStatus casStrmClient::writeResponse ( - const caHdrLargeArray &msg, const caStatus completionStatus) +caStatus casStrmClient::writeResponse ( casChannelI & chan, + const caHdrLargeArray & msg, const caStatus completionStatus ) { caStatus status; - if (completionStatus) { - errMessage(completionStatus, NULL); - status = this->sendErrWithEpicsStatus(&msg, - completionStatus, ECA_PUTFAIL); + if ( completionStatus ) { + errMessage ( completionStatus, NULL ); + status = this->sendErrWithEpicsStatus ( & msg, + chan.getCID(), completionStatus, ECA_PUTFAIL ); } else { status = S_cas_success; @@ -686,10 +693,9 @@ caStatus casStrmClient::writeResponse ( caStatus casStrmClient::writeNotifyAction() { const caHdrLargeArray *mp = this->ctx.getMsg(); - int status; - casChannelI *pChan; - status = this->verifyRequest (pChan); + casChannelI *pChan; + int status = this->verifyRequest ( pChan ); if (status != ECA_NORMAL) { return casStrmClient::writeNotifyResponseECA_XXX(*mp, status); } @@ -703,8 +709,8 @@ caStatus casStrmClient::writeNotifyAction() *mp, ECA_NOWTACCESS); } else { - return this->casStrmClient::writeNotifyResponse( - *mp, S_cas_noWrite); + return this->casStrmClient::writeNotifyResponse ( + *pChan, *mp, S_cas_noWrite ); } } @@ -719,7 +725,7 @@ caStatus casStrmClient::writeNotifyAction() pChan->getPVI().addItemToIOBLockedList(*this); } else { - status = casStrmClient::writeNotifyResponse(*mp, status); + status = casStrmClient::writeNotifyResponse ( *pChan, *mp, status ); } return status; @@ -728,12 +734,12 @@ caStatus casStrmClient::writeNotifyAction() /* * casStrmClient::writeNotifyResponse() */ -caStatus casStrmClient::writeNotifyResponse( - const caHdrLargeArray &msg, const caStatus completionStatus) +caStatus casStrmClient::writeNotifyResponse ( casChannelI & chan, + const caHdrLargeArray & msg, const caStatus completionStatus ) { caStatus ecaStatus; - if (completionStatus==S_cas_success) { + if ( completionStatus == S_cas_success ) { ecaStatus = ECA_NORMAL; } else { @@ -759,7 +765,8 @@ caStatus casStrmClient::writeNotifyResponse( // we are unable to send. // if (completionStatus!=S_cas_success) { - ecaStatus = this->sendErrWithEpicsStatus (&msg, completionStatus, ECA_NOCONVERT); + ecaStatus = this->sendErrWithEpicsStatus ( &msg, chan.getCID(), + completionStatus, ECA_NOCONVERT ); if (ecaStatus) { errMessage (completionStatus, "<= put callback failure detail not passed to client"); } @@ -795,37 +802,36 @@ caStatus casStrmClient::hostNameAction() char *pMalloc; caStatus status; + // currently this has to occur prior to + // creating channels or its not allowed + if ( this->chanList.count () ) { + return this->sendErr ( mp, invalidResID, + ECA_UNAVAILINSERV, pName ); + } + size = strlen(pName)+1u; /* * user name will not change if there isnt enough memory */ pMalloc = new char [size]; - if(!pMalloc){ - status = this->sendErr(mp, ECA_ALLOCMEM, pName); + if ( ! pMalloc ){ + status = this->sendErr ( mp, invalidResID, + ECA_ALLOCMEM, pName ); if (status) { return status; } return S_cas_internal; } - strncpy( - pMalloc, - pName, - size-1); - pMalloc[size-1]='\0'; + strncpy ( pMalloc, pName, size - 1 ); + pMalloc[ size - 1 ]='\0'; epicsGuard < epicsMutex > guard ( this->mutex ); - if (this->pHostName) { + if ( this->pHostName ) { delete [] this->pHostName; } this->pHostName = pMalloc; - tsDLIter iter = this->chanList.firstIter (); - while ( iter.valid () ) { - iter->setOwner(this->pUserName, this->pHostName); - ++iter; - } - return S_cas_success; } @@ -840,6 +846,13 @@ caStatus casStrmClient::clientNameAction() char *pMalloc; caStatus status; + // currently this has to occur prior to + // creating channels or its not allowed + if ( this->chanList.count () ) { + return this->sendErr ( mp, invalidResID, + ECA_UNAVAILINSERV, pName ); + } + size = strlen(pName)+1; /* @@ -847,38 +860,30 @@ caStatus casStrmClient::clientNameAction() */ pMalloc = new char [size]; if(!pMalloc){ - status = this->sendErr(mp, ECA_ALLOCMEM, pName); + status = this->sendErr ( mp, invalidResID, + ECA_ALLOCMEM, pName ); if (status) { return status; } return S_cas_internal; } - strncpy( - pMalloc, - pName, - size-1); + strncpy ( pMalloc, pName, size - 1 ); pMalloc[size-1]='\0'; epicsGuard < epicsMutex > guard ( this->mutex ); - if (this->pUserName) { + if ( this->pUserName ) { delete [] this->pUserName; } this->pUserName = pMalloc; - tsDLIter iter = this->chanList.firstIter (); - while ( iter.valid () ) { - iter->setOwner ( this->pUserName, this->pHostName ); - ++iter; - } - return S_cas_success; } /* * casStrmClientMon::claimChannelAction() */ -caStatus casStrmClient::claimChannelAction() +caStatus casStrmClient::claimChannelAction () { const caHdrLargeArray *mp = this->ctx.getMsg(); char *pName = (char *) this->ctx.getData(); @@ -904,13 +909,13 @@ caStatus casStrmClient::claimChannelAction() // an R3.11 client because we will not respond to their // search requests (if so we disconnect) // - if (!CA_V44(this->minor_version_number)) { + if ( ! CA_V44(this->minor_version_number) ) { // // old connect protocol was dropped when the // new API was added to the server (they must // now use clients at EPICS 3.12 or higher) // - status = this->sendErr(mp, ECA_DEFUNCT, + status = this->sendErr ( mp, mp->m_cid, ECA_DEFUNCT, "R3.11 connect sequence from old client was ignored"); if (status) { return status; @@ -928,12 +933,7 @@ caStatus casStrmClient::claimChannelAction() return S_cas_badProtocol; // disconnect client } - // - // prevent problems such as the PV being deleted before the - // channel references it - // - epicsGuard < epicsMutex > guard ( this->mutex ); - this->asyncIOFlag = false; + this->userStartedAsyncIO = false; // // attach to the PV @@ -945,7 +945,7 @@ caStatus casStrmClient::claimChannelAction() // async IO but dont return status // indicating so (and vise versa) // - if ( this->asyncIOFlag ) { + if ( this->userStartedAsyncIO ) { if ( pvar.getStatus() != S_casApp_asyncCompletion ) { fprintf ( stderr, "Application returned %d from cas::pvAttach()" @@ -974,27 +974,23 @@ caStatus casStrmClient::claimChannelAction() // // casStrmClient::createChanResponse() // -// LOCK must be applied -// -caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const pvAttachReturn & pvar ) +caStatus casStrmClient::createChanResponse ( + const caHdrLargeArray & hdr, const pvAttachReturn & pvar ) { if ( pvar.getStatus() != S_cas_success ) { return this->channelCreateFailedResp ( hdr, pvar.getStatus() ); } - casPVI * pPV = pvar.getPV(); - - // - // If status is ok and the PV isnt set then guess that the - // pv isnt in this server - // - if ( pPV == NULL ) { + casPVI * pPVI = casPVI::attachPV ( * pvar.getPV() ); + if ( ! pPVI ) { + pvar.getPV()->destroy (); return this->channelCreateFailedResp ( hdr, S_casApp_pvNotFound ); - } + } unsigned nativeTypeDBR; - caStatus status = pPV->bestDBRType ( nativeTypeDBR ); + caStatus status = pPVI->bestDBRType ( nativeTypeDBR ); if ( status ) { + pPVI->deleteSignal(); errMessage ( status, "best external dbr type fetch failed" ); return this->channelCreateFailedResp ( hdr, status ); } @@ -1002,8 +998,9 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const // // attach the PV to this server // - status = pPV->attachToServer ( this->getCAS() ); + status = pPVI->attachToServer ( this->getCAS() ); if ( status ) { + pPVI->deleteSignal(); return this->channelCreateFailedResp ( hdr, status ); } @@ -1013,30 +1010,27 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const // casCtx tmpCtx; tmpCtx.setClient ( this ); - tmpCtx.setPV ( pPV ); + tmpCtx.setPV ( pPVI ); tmpCtx.setMsg ( hdr, 0 ); - casChannel * pChan = pPV->createChannel ( + casChannel * pChan = pPVI->createChannel ( tmpCtx, this->pUserName, this->pHostName ); if ( ! pChan ) { - pPV->deleteSignal(); + pPVI->deleteSignal(); return this->channelCreateFailedResp ( hdr, S_cas_noMemory ); } - this->installChannel ( *pChan ); - pPV->installChannel ( *pChan ); - // // check to see if the enum table is empty and therefore // an update is needed every time that a PV attaches // to the server in case the client disconnected before - // an asynchronous IO to get the table comleted + // an asynchronous IO to get the table completed // if ( nativeTypeDBR == DBR_ENUM ) { - this->ctx.setPV ( pPV ); - this->ctx.setChannel ( pChan ); - this->asyncIOFlag = false; - status = pPV->updateEnumStringTable ( this->ctx ); - if ( this->asyncIOFlag ) { + this->ctx.setPV ( pPVI ); + this->ctx.setChannel ( pChan->pChanI ); + this->userStartedAsyncIO = false; + status = pPVI->updateEnumStringTable ( this->ctx ); + if ( this->userStartedAsyncIO ) { if ( status != S_casApp_asyncCompletion ) { fprintf ( stderr, "Application returned %d from casPV::read()" @@ -1045,7 +1039,8 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const status = S_cas_success; } else if ( status == S_casApp_success ) { - status = enumPostponedCreateChanResponse ( *pChan, hdr, nativeTypeDBR ); + status = enumPostponedCreateChanResponse ( + * pChan->pChanI, hdr, nativeTypeDBR ); } else if ( status == S_casApp_asyncCompletion ) { status = S_cas_badParameter; @@ -1053,16 +1048,19 @@ caStatus casStrmClient::createChanResponse ( const caHdrLargeArray & hdr, const "- asynch IO creation status returned, but async IO not started?"); } else if ( status == S_casApp_postponeAsyncIO ) { - status = S_cas_badParameter; errlogPrintf ( "The server library does not currently support postponment of " ); errlogPrintf ( "string table cache update of casPV::read()." ); - errlogPrintf ( "To pospone this request please postpone the PC attach IO request." ); + errlogPrintf ( "To postpone this request please postpone the PC attach IO request." ); errlogPrintf ( "String table cache update did not occur." ); - status = enumPostponedCreateChanResponse ( *pChan, hdr, nativeTypeDBR ); + status = enumPostponedCreateChanResponse ( *pChan->pChanI, hdr, nativeTypeDBR ); } } else { - status = enumPostponedCreateChanResponse ( *pChan, hdr, nativeTypeDBR ); + status = enumPostponedCreateChanResponse ( *pChan->pChanI, hdr, nativeTypeDBR ); + } + + if ( status != S_cas_success ) { + delete pChan->pChanI; } return status; @@ -1099,10 +1097,19 @@ caStatus casStrmClient::enumPostponedCreateChanResponse ( if ( status ) { this->out.popCtx ( outctx ); errMessage ( status, "incomplete channel create?" ); - chan.destroyNoClientNotify (); - return this->channelCreateFailedResp ( hdr, status ); + status = this->channelCreateFailedResp ( hdr, status ); + if ( status == S_cas_success ) { + delete & chan; + } + return status; } + // must install into server table before using server id + // member of channel + this->chanTable.add ( chan ); + this->chanList.add ( chan ); + chan.installIntoPV (); + // // We are allocated enough space for both the claim // response and the access response so that we know for @@ -1119,20 +1126,27 @@ caStatus casStrmClient::enumPostponedCreateChanResponse ( static_cast ( nativeCount ), hdr.m_cid, chan.getSID(), 0 ); if ( status != S_cas_success ) { + this->chanTable.remove ( chan ); + this->chanList.remove ( chan ); + chan.uninstallFromPV ( this->eventSys ); + this->out.popCtx ( outctx ); errMessage ( status, "incomplete channel create?" ); - chan.destroyNoClientNotify (); - return this->channelCreateFailedResp ( hdr, status ); - } + status = this->channelCreateFailedResp ( hdr, status ); + if ( status == S_cas_success ) { + delete & chan; + } + return status; + } this->out.commitMsg (); // // commit the message // - bufSizeT nBytes = this->out.popCtx (outctx); + bufSizeT nBytes = this->out.popCtx ( outctx ); assert ( nBytes == 2*sizeof(caHdr) ); - this->out.commitRawMsg (nBytes); + this->out.commitRawMsg ( nBytes ); return status; } @@ -1166,7 +1180,7 @@ caStatus casStrmClient::channelCreateFailedResp ( } else { status = this->sendErrWithEpicsStatus ( - & hdr, createStatus, ECA_ALLOCMEM ); + & hdr, hdr.m_cid, createStatus, ECA_ALLOCMEM ); } return status; } @@ -1227,21 +1241,25 @@ caStatus casStrmClient::eventAddAction () const caHdrLargeArray *mp = this->ctx.getMsg(); struct mon_info *pMonInfo = (struct mon_info *) this->ctx.getData(); - casChannelI *pciu; - smartGDDPointer pDD; - caStatus status; - casEventMask mask; - unsigned short caProtoMask; - status = casStrmClient::verifyRequest (pciu); - if (status != ECA_NORMAL) { - return this->sendErr(mp, status, NULL); + casChannelI *pciu; + caStatus status = casStrmClient::verifyRequest ( pciu ); + if ( status != ECA_NORMAL ) { + if ( pciu ) { + return this->sendErr ( mp, + pciu->getCID(), status, NULL); + } + else { + return this->sendErr ( mp, + invalidResID, status, NULL ); + } } // // place monitor mask in correct byte order // - caProtoMask = epicsNTOH16 (pMonInfo->m_mask); + casEventMask mask; + ca_uint16_t caProtoMask = epicsNTOH16 (pMonInfo->m_mask); if (caProtoMask&DBE_VALUE) { mask |= this->getCAS().valueEventMask(); } @@ -1256,8 +1274,8 @@ caStatus casStrmClient::eventAddAction () if (mask.noEventsSelected()) { char errStr[40]; - sprintf(errStr, "event add req with mask=0X%X\n", caProtoMask); - return this->sendErr(mp, ECA_BADMASK, errStr); + sprintf ( errStr, "event add req with mask=0X%X\n", caProtoMask ); + return this->sendErr ( mp, pciu->getCID(), ECA_BADMASK, errStr ); } // @@ -1266,30 +1284,19 @@ caStatus casStrmClient::eventAddAction () // to postpone asynchronous IO we can safely restart this // request later. // - status = this->read (pDD); + smartGDDPointer pDD; + status = this->read ( pDD ); // // always send immediate monitor response at event add // - if (status == S_casApp_success) { - status = this->monitorResponse (*pciu, *mp, pDD, status); - } - else if (status == S_casApp_asyncCompletion) { + if ( status == S_casApp_asyncCompletion ) { status = S_cas_success; } - else if (status == S_casApp_postponeAsyncIO) { + else if ( status == S_casApp_postponeAsyncIO ) { // // try again later // - pciu->getPVI().addItemToIOBLockedList(*this); - } - else if (status == S_casApp_noMemory) { - // - // If we cant send the first monitor value because - // there isnt pool space for a gdd then delete - // (disconnect) the channel - // - pciu->destroyClientNotify (); - return S_cas_success; + pciu->getPVI().addItemToIOBLockedList ( *this ); } else { status = this->monitorResponse ( *pciu, @@ -1297,10 +1304,10 @@ caStatus casStrmClient::eventAddAction () } if ( status == S_cas_success ) { - epicsGuard < epicsMutex > guard ( this->mutex ); - pciu->installMonitor ( - mp->m_available, mp->m_count, - mp->m_dataType, mask ); + casMonitor & mon = this->monitorFactory ( + *pciu, mp->m_available, mp->m_count, + mp->m_dataType, mask ); + pciu->installMonitor ( mon ); } return status; @@ -1314,13 +1321,27 @@ caStatus casStrmClient::clearChannelAction () { const caHdrLargeArray * mp = this->ctx.getMsg(); const void * dp = this->ctx.getData(); - casChannelI * pciu; int status; + // + // send delete confirmed message + // + { + epicsGuard < epicsMutex > guard ( this->mutex ); + status = this->out.copyInHeader ( mp->m_cmmd, 0, + mp->m_dataType, mp->m_count, + mp->m_cid, mp->m_available, 0 ); + if ( status ) { + return status; + } + this->out.commitMsg (); + } + /* * Verify the channel */ - pciu = this->lookupChannel ( mp->m_cid ); + chronIntId tmpId ( mp->m_cid ); + casChannelI * pciu = this->chanTable.remove ( tmpId ); if ( pciu == NULL ) { /* * it is possible that the channel delete arrives just @@ -1341,69 +1362,59 @@ caStatus casStrmClient::clearChannelAction () // delete confirm message even if the channel couldnt be // located so that the client can finish cleaning up // + return status; } - // - // send delete confirmed message - // - epicsGuard < epicsMutex > guard ( this->mutex ); - status = this->out.copyInHeader ( mp->m_cmmd, 0, - mp->m_dataType, mp->m_count, - mp->m_cid, mp->m_available, 0 ); - if ( ! status ) { - this->out.commitMsg (); - if ( pciu ) { - pciu->destroyNoClientNotify (); - } - } + this->chanList.remove ( *pciu ); + pciu->uninstallFromPV ( this->eventSys ); + delete pciu; return status; } - -// // casStrmClient::eventCancelAction() -// caStatus casStrmClient::eventCancelAction () { const caHdrLargeArray * mp = this->ctx.getMsg (); const void * dp = this->ctx.getData (); - - /* - * Verify the channel - */ - casChannelI * pciu = this->lookupChannel ( mp->m_cid ); - if ( ! pciu ) { - /* - * it is possible that the event delete arrives just - * after the server tool has deleted the PV. In this - * rare situation we are unable to look up the client's - * resource id for the return message and so we must force - * the client to reconnect. - */ - logBadId ( mp, dp, ECA_BADCHID, mp->m_cid ); - return S_cas_badResourceId; - } - epicsGuard < epicsMutex > guard ( this->mutex ); - int status = this->out.copyInHeader ( - CA_PROTO_EVENT_ADD, 0, - mp->m_dataType, mp->m_count, - pciu->getCID (), mp->m_available, 0 ); - if ( ! status ) { - if ( ! pciu->unistallMonitor ( mp->m_available ) ) { - // + { + epicsGuard < epicsMutex > guard ( this->mutex ); + + chronIntId tmpId ( mp->m_cid ); + casChannelI * pChan = this->chanTable.lookup ( tmpId ); + if ( ! pChan ) { + // It is possible that the event delete arrives just + // after the server tool has deleted the PV. Its probably + // best to just diconnect for now since some old clients + // may still exist. + logBadId ( mp, dp, ECA_BADCHID, mp->m_cid ); + return S_cas_badResourceId; + } + + caStatus status = this->out.copyInHeader ( + CA_PROTO_EVENT_ADD, 0, + mp->m_dataType, mp->m_count, + mp->m_cid, mp->m_available, 0 ); + if ( status != S_cas_success ) { + return status; + } + this->out.commitMsg (); + + casMonitor * pMon = pChan->removeMonitor ( mp->m_available ); + if ( pMon ) { + this->eventSys.prepareMonitorForDestroy ( *pMon ); + } + else { // this indicates client or server library // corruption so a disconnect is probably // the best option - // logBadId ( mp, dp, ECA_BADMONID, mp->m_available ); - status = S_cas_badResourceId; + return S_cas_badResourceId; } - this->out.commitMsg (); - } - - return status; + } + + return S_cas_success; } #if 0 @@ -1413,7 +1424,7 @@ caStatus casStrmClient::eventCancelAction () * substantial complication introduced here by the need for backwards * compatibility */ -caStatus casStrmClient::noReadAccessEvent(casClientMon *pMon) +caStatus casStrmClient::noReadAccessEvent ( casClientMon * pMon ) { caHdr falseReply; unsigned size; @@ -1431,10 +1442,10 @@ caStatus casStrmClient::noReadAccessEvent(casClientMon *pMon) epicsGuard < epicsMutex > guard ( this->mutex ); - status = this->allocMsg(size, &reply); + status = this->allocMsg ( size, &reply ); if ( status ) { if( status == S_cas_hugeRequest ) { - return this->sendErr(&falseReply, ECA_TOLARGE, NULL); + return this->sendErr ( &falseReply, ECA_TOLARGE, NULL ); } return status; } @@ -1465,26 +1476,24 @@ caStatus casStrmClient::noReadAccessEvent(casClientMon *pMon) // // casStrmClient::readSyncAction() // -caStatus casStrmClient::readSyncAction() +// This message indicates that the R3.13 or before client +// timed out on a read so we must clear out any pending +// asynchronous IO associated with a read. +// +caStatus casStrmClient::readSyncAction () { - const caHdrLargeArray *mp = this->ctx.getMsg(); - int status; + tsDLIter < casChannelI > iter = + this->chanList.firstIter (); + while ( iter.valid() ) { + iter->clearOutstandingReads (); + iter++; + } + + const caHdrLargeArray * mp = this->ctx.getMsg (); epicsGuard < epicsMutex > guard ( this->mutex ); - // - // This messages indicates that the client - // timed out on a read so we must clear out - // any pending asynchronous IO associated with - // a read. - // - tsDLIter iter = this->chanList.firstIter (); - while ( iter.valid () ) { - iter->clearOutstandingReads (); - ++iter; - } - - status = this->out.copyInHeader ( mp->m_cmmd, 0, + int status = this->out.copyInHeader ( mp->m_cmmd, 0, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 ); if ( ! status ) { @@ -1539,8 +1548,8 @@ caStatus casStrmClient::accessRightsResponse(casChannelI *pciu) caStatus casStrmClient::write() { const caHdrLargeArray *pHdr = this->ctx.getMsg(); - casPVI *pPV = this->ctx.getPV(); - caStatus status; + casPVI * pPV = this->ctx.getPV(); + caStatus status; // // no puts via compound types (for now) @@ -1561,25 +1570,25 @@ caStatus casStrmClient::write() // // the PV state must not be modified during a transaction // - status = pPV->beginTransaction(); - if (status) { + status = pPV->beginTransaction (); + if ( status ) { return status; } // // clear async IO flag // - this->asyncIOFlag = false; + this->userStartedAsyncIO = false; // // DBR_STRING is stored outside the DD so it // lumped in with arrays // - if (pHdr->m_count > 1u) { - status = this->writeArrayData(); + if ( pHdr->m_count > 1u ) { + status = this->writeArrayData (); } else { - status = this->writeScalarData(); + status = this->writeScalarData (); } // @@ -1587,7 +1596,7 @@ caStatus casStrmClient::write() // async IO but dont return status // indicating so (and vise versa) // - if ( this->asyncIOFlag ) { + if ( this->userStartedAsyncIO ) { if (status!=S_casApp_asyncCompletion) { fprintf(stderr, "Application returned %d from casPV::write() - expected S_casApp_asyncCompletion\n", @@ -1595,13 +1604,13 @@ caStatus casStrmClient::write() status = S_casApp_asyncCompletion; } } - else if (status == S_casApp_asyncCompletion) { + else if ( status == S_casApp_asyncCompletion ) { status = S_cas_badParameter; - errMessage(status, - "- expected asynch IO creation from casPV::write()"); + errMessage ( status, + "- expected asynch IO creation from casPV::write()" ); } - pPV->endTransaction(); + pPV->endTransaction (); return status; } @@ -1609,10 +1618,10 @@ caStatus casStrmClient::write() // // casStrmClient::writeScalarData() // -caStatus casStrmClient::writeScalarData() +caStatus casStrmClient::writeScalarData () { smartGDDPointer pDD; - const caHdrLargeArray *pHdr = this->ctx.getMsg(); + const caHdrLargeArray * pHdr = this->ctx.getMsg (); gddStatus gddStat; caStatus status; aitEnum type; @@ -1772,10 +1781,9 @@ caStatus casStrmClient::writeArrayData() // // casStrmClient::read() // -caStatus casStrmClient::read (smartGDDPointer &pDescRet) +caStatus casStrmClient::read ( smartGDDPointer & pDescRet ) { - const caHdrLargeArray *pHdr = this->ctx.getMsg(); - caStatus status; + const caHdrLargeArray * pHdr = this->ctx.getMsg(); pDescRet = createDBRDD ( pHdr->m_dataType, pHdr->m_count ); if ( ! pDescRet ) { @@ -1785,7 +1793,7 @@ caStatus casStrmClient::read (smartGDDPointer &pDescRet) // // the PV state must not be modified during a transaction // - status = this->ctx.getPV()->beginTransaction(); + caStatus status = this->ctx.getPV()->beginTransaction(); if (status) { return status; } @@ -1793,7 +1801,7 @@ caStatus casStrmClient::read (smartGDDPointer &pDescRet) // // clear the async IO flag // - this->asyncIOFlag = false; + this->userStartedAsyncIO = false; // // call the server tool's virtual function @@ -1805,7 +1813,7 @@ caStatus casStrmClient::read (smartGDDPointer &pDescRet) // async IO but dont return status // indicating so (and vise versa) // - if ( this->asyncIOFlag ) { + if ( this->userStartedAsyncIO ) { if (status!=S_casApp_asyncCompletion) { fprintf(stderr, "Application returned %d from casPV::read() - expected S_casApp_asyncCompletion\n", @@ -1848,27 +1856,6 @@ inline bool caServerI::roomForNewChannel() const return true; } -// -// casStrmClient::installChannel() -// -void casStrmClient::installChannel(casChannelI &chan) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - this->getCAS().installItem (chan); - this->chanList.add(chan); -} - -// -// casStrmClient::removeChannel() -// -void casStrmClient::removeChannel(casChannelI &chan) -{ - epicsGuard < epicsMutex > guard ( this->mutex ); - casRes * pRes = this->getCAS().removeItem(chan); - assert (&chan == (casChannelI *)pRes); - this->chanList.remove(chan); -} - // // casStrmClient::xSend() // @@ -1953,26 +1940,5 @@ void casStrmClient::flush () caStatus casStrmClient::casMonitorCallBack ( casMonitor & mon, const smartConstGDDPointer & value ) { - caStatus status; - caHdrLargeArray msg; - - // - // reconstruct the msg header - // - msg.m_cmmd = CA_PROTO_EVENT_ADD; - msg.m_postsize = 0u; - unsigned type = mon.getType(); - assert ( type <= 0xffff ); - msg.m_dataType = static_cast ( type ); - unsigned long count = mon.getCount(); - assert ( count <= 0xffffffff ); - msg.m_count = static_cast ( count ); - msg.m_cid = mon.getChannel().getSID(); - msg.m_available = mon.getClientId(); - - status = this->monitorResponse ( mon.getChannel(), - msg, value, S_cas_success ); - return status; + return mon.response ( *this, value ); } - - diff --git a/src/cas/generic/casStrmClient.h b/src/cas/generic/casStrmClient.h new file mode 100644 index 000000000..cf795938a --- /dev/null +++ b/src/cas/generic/casStrmClient.h @@ -0,0 +1,138 @@ + +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef casStrmClienth +#define casStrmClienth + +#include "casClient.h" + +enum xBlockingStatus { xIsBlocking, xIsntBlocking }; + +// +// casStrmClient +// +class casStrmClient : + public casClient, + public tsDLNode < casStrmClient > { +public: + casStrmClient ( caServerI &, clientBufMemoryManager & ); + virtual ~casStrmClient(); + void show ( unsigned level ) const; + void flush (); + + // + // one function for each CA request type that has + // asynchronous completion + // + virtual caStatus createChanResponse ( + const caHdrLargeArray &, const pvAttachReturn & ); + caStatus readResponse ( casChannelI *pChan, const caHdrLargeArray &msg, + const smartConstGDDPointer &pDesc, const caStatus status); + caStatus readNotifyResponse ( casChannelI *pChan, const caHdrLargeArray &msg, + const smartConstGDDPointer &pDesc, const caStatus status); + caStatus writeResponse ( casChannelI &, + const caHdrLargeArray & msg, const caStatus status ); + caStatus writeNotifyResponse ( casChannelI &, + const caHdrLargeArray &, const caStatus status ); + caStatus monitorResponse ( casChannelI & chan, const caHdrLargeArray & msg, + const smartConstGDDPointer & pDesc, const caStatus status ); + caStatus enumPostponedCreateChanResponse ( casChannelI & chan, + const caHdrLargeArray & hdr, unsigned dbrType ); + caStatus channelCreateFailedResp ( const caHdrLargeArray &, + const caStatus createStatus ); + + caStatus disconnectChan ( caResId id ); + unsigned getDebugLevel () const; + virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0; + void userName ( char * pBuf, unsigned bufSize ) const; + +private: + chronIntIdResTable < casChannelI > chanTable; + 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 uknownMessageAction (); + 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 (); + + caStatus writeArrayData(); + caStatus writeScalarData(); + caStatus writeString(); + + // + // io independent send/recv + // + outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT & nBytesSent ); + inBufClient::fillCondition xRecv ( char * pBuf, bufSizeT nBytesToRecv, + inBufClient::fillParameter parm, bufSizeT & nByesRecv ); + + virtual xBlockingStatus blockingState () const = 0; + + virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq, + bufSizeT & nBytesActual ) = 0; + virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual ) = 0; + + caStatus readNotifyFailureResponse ( const caHdrLargeArray & msg, + const caStatus ECA_XXXX ); + + caStatus monitorFailureResponse ( const caHdrLargeArray & msg, + const caStatus ECA_XXXX ); + + caStatus writeNotifyResponseECA_XXX ( const caHdrLargeArray &msg, + const caStatus status ); + + caStatus casMonitorCallBack ( casMonitor &, + const smartConstGDDPointer & pValue ); + + casStrmClient ( const casStrmClient & ); + casStrmClient & operator = ( const casStrmClient & ); +}; + +#endif // casStrmClienth + diff --git a/src/cas/generic/casdef.h b/src/cas/generic/casdef.h index 90aa585f0..47146375e 100644 --- a/src/cas/generic/casdef.h +++ b/src/cas/generic/casdef.h @@ -27,9 +27,10 @@ // // EPICS // -#include "alarm.h" // EPICS alarm severity/condition -#include "errMdef.h" // EPICS error codes -#include "gdd.h" // EPICS data descriptors +#include "errMdef.h" // EPICS error codes +#include "gdd.h" // EPICS data descriptors +#include "smartGDDPointer.h" // auto ref gdd pointer +#include "alarm.h" // EPICS alarm severity/condition #ifdef epicsExportSharedSymbols_casdefh # define epicsExportSharedSymbols @@ -37,6 +38,7 @@ #endif #include "caNetAddr.h" +#include "casEventMask.h" // EPICS event select class typedef aitUint32 caStatus; @@ -107,6 +109,10 @@ typedef aitUint32 caStatus; enum pvExistReturnEnum { pverExistsHere, pverDoesNotExistHere, pverAsyncCompletion }; +class casPV; +class casCtx; +class casChannel; + class epicsShareClass pvExistReturn { // X aCC 361 public: // most server tools will use this @@ -124,8 +130,6 @@ private: pvExistReturnEnum status; }; -class casPV; - // // pvAttachReturn // @@ -143,17 +147,11 @@ private: caStatus stat; }; -#include "casEventMask.h" // EPICS event select class -#include "casInternal.h" // CA server private - -class caServerI; - // // caServer - Channel Access Server API Class // class caServer { friend class casPVI; - public: epicsShareFunc caServer (); epicsShareFunc virtual ~caServer() = 0; @@ -231,30 +229,30 @@ public: // subset of named process variables at its privately specified date by // attaching to additional client private process variables. // - epicsShareFunc virtual pvAttachReturn pvAttach (const casCtx &ctx, - const char *pPVAliasName); + epicsShareFunc virtual pvAttachReturn pvAttach ( const casCtx &ctx, + const char *pPVAliasName ); // // obtain an event mask for a named event type // to be used with casPV::postEvent() // - epicsShareFunc casEventMask registerEvent (const char *pName); + epicsShareFunc casEventMask registerEvent ( const char *pName ); // // common event masks // (what is currently used by the CA clients) // - epicsShareFunc casEventMask valueEventMask() const; // DBE_VALUE - epicsShareFunc casEventMask logEventMask() const; // DBE_LOG - epicsShareFunc casEventMask alarmEventMask() const; // DBE_ALARM + epicsShareFunc casEventMask valueEventMask () const; // DBE_VALUE + epicsShareFunc casEventMask logEventMask () const; // DBE_LOG + epicsShareFunc casEventMask alarmEventMask () const; // DBE_ALARM - epicsShareFunc void setDebugLevel (unsigned level); + epicsShareFunc void setDebugLevel ( unsigned level ); epicsShareFunc unsigned getDebugLevel () const; // // dump internal state of server to standard out // - epicsShareFunc virtual void show (unsigned level) const; + epicsShareFunc virtual void show ( unsigned level ) const; // // server diagnostic counters (allowed to roll over) @@ -275,11 +273,11 @@ public: // caStatus disableClients (); private: - caServerI *pCAS; + class caServerI * pCAS; // deprecated interfaces (will be deleted in a future release) epicsShareFunc virtual class pvCreateReturn createPV ( const casCtx & ctx, - const char *pPVAliasName); + const char *pPVAliasName ); }; // @@ -307,7 +305,7 @@ private: // then it may decide to provide a "destroy()" implementation in the // derived class which is a noop. // -class casPV : private casPVI { +class casPV { public: epicsShareFunc casPV (); @@ -318,7 +316,7 @@ public: // caServer::show() is called and the level is high // enough // - epicsShareFunc virtual void show (unsigned level) const; + epicsShareFunc virtual void show ( unsigned level ) const; // // called by the server libary each time that it wishes to @@ -406,7 +404,7 @@ public: // implements this function then it must create a casChannel object // (or a derived class) each time that this routine is called // - epicsShareFunc virtual casChannel *createChannel (const casCtx &ctx, + epicsShareFunc virtual casChannel * createChannel ( const casCtx &ctx, const char * const pUserName, const char * const pHostName); // @@ -468,13 +466,13 @@ public: // set to one then the bound on the second dimension // are being fetched... // - epicsShareFunc virtual unsigned maxDimension() const; // return zero if scalar - epicsShareFunc virtual aitIndex maxBound (unsigned dimension) const; + epicsShareFunc virtual unsigned maxDimension () const; // return zero if scalar + epicsShareFunc virtual aitIndex maxBound ( unsigned dimension ) const; // // Server tool calls this function to post a PV event. // - epicsShareFunc void postEvent (const casEventMask &select, const gdd &event); + epicsShareFunc void postEvent ( const casEventMask & select, const gdd & event ); // // peek at the pv name @@ -489,7 +487,7 @@ public: // // !! not thread safe !! // - epicsShareFunc virtual const char *getName() const = 0; + epicsShareFunc virtual const char * getName () const = 0; // // Find the server associated with this PV @@ -501,18 +499,17 @@ public: // before the server // *************** // - epicsShareFunc caServer *getCAS() const; + epicsShareFunc caServer * getCAS () const; // // only used when caStrmClient converts from // casPV * to casPVI * // - friend class casStrmClient; + //friend class casStrmClient; - private: - casPV *apiPointer (); //retruns NULL if casPVI isnt a base of casPV - casPV ( const casPV & ); + casPVI * pPVI; + friend class casPVI; // used ony to get casPVI casPV ( const casPV & ); casPV & operator = ( const casPV & ); public: @@ -545,17 +542,17 @@ public: // client attachment to this channel (and reclaim any resources // allocated by the server library on its behalf) // -class casChannel : private casPVListChan { +class casChannel { public: - epicsShareFunc casChannel (const casCtx &ctx); - epicsShareFunc virtual ~casChannel(); + epicsShareFunc casChannel ( const casCtx & ctx ); + epicsShareFunc virtual ~casChannel (); // // Called when the user name and the host name are changed // for a live connection. // - epicsShareFunc virtual void setOwner (const char * const pUserName, - const char * const pHostName); + epicsShareFunc virtual void setOwner ( const char * const pUserName, + const char * const pHostName ); // // the following are encouraged to change during an channel's @@ -599,17 +596,13 @@ public: // for virtual casChannel::destroy() // *************** // - epicsShareFunc casPV *getPV (); + epicsShareFunc casPV * getPV (); private: + class casChannelI * pChanI; + friend class casStrmClient; // used ony to get casChannelI casChannel ( const casChannel & ); casChannel & operator = ( const casChannel & ); - - // - // only used when casStrmClient converts between - // casChannel * and casChannelI * - // - friend class casStrmClient; }; // @@ -668,13 +661,13 @@ private: // in the destructor, for the class deriving from // casAsyncReadIO. // ** -class casAsyncReadIO : private casAsyncIOI { +class casAsyncReadIO { public: // // casAsyncReadIO() // - epicsShareFunc casAsyncReadIO (const casCtx &ctx); + epicsShareFunc casAsyncReadIO ( const casCtx & ctx ); epicsShareFunc virtual ~casAsyncReadIO (); // @@ -683,7 +676,8 @@ public: // // only the first call to this function has any effect // - epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn, const gdd &valueRead); + epicsShareFunc caStatus postIOCompletion ( + caStatus completionStatusIn, const gdd & valueRead ); // // Find the server associated with this async IO @@ -692,8 +686,12 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS () const; + epicsShareFunc caServer * getCAS () const; + void serverInitiatedDestroy (); + +private: + class casAsyncReadIOI * pAsyncReadIOI; // // called by the server lib after the response message // is succesfully queued to the client or when the @@ -703,15 +701,6 @@ public: // epicsShareFunc virtual void destroy (); -private: - caHdrLargeArray const msg; - casChannelI &chan; - smartConstGDDPointer pDD; - caStatus completionStatus; - - epicsShareFunc bool readOP() const; - epicsShareFunc caStatus cbFuncAsyncIO(); - casAsyncReadIO ( const casAsyncReadIO & ); casAsyncReadIO & operator = ( const casAsyncReadIO & ); }; @@ -731,12 +720,12 @@ private: // casAsyncWriteIO. // ** // -class casAsyncWriteIO : private casAsyncIOI { +class casAsyncWriteIO { public: // // casAsyncWriteIO() // - epicsShareFunc casAsyncWriteIO (const casCtx &ctx); + epicsShareFunc casAsyncWriteIO ( const casCtx & ctx ); epicsShareFunc virtual ~casAsyncWriteIO (); // @@ -744,7 +733,7 @@ public: // (this function does not delete the casAsyncWriteIO object). // Only the first call to this function has any effect. // - epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn); + epicsShareFunc caStatus postIOCompletion ( caStatus completionStatusIn ); // // Find the server associated with this async IO @@ -753,8 +742,12 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS () const; + epicsShareFunc caServer * getCAS () const; + void serverInitiatedDestroy (); + +private: + class casAsyncWriteIOI * pAsyncWriteIOI; // // called by the server lib after the response message // is succesfully queued to the client or when the @@ -764,12 +757,6 @@ public: // epicsShareFunc virtual void destroy (); -private: - caHdrLargeArray const msg; - casChannelI &chan; - caStatus completionStatus; - - epicsShareFunc caStatus cbFuncAsyncIO (); casAsyncWriteIO ( const casAsyncWriteIO & ); casAsyncWriteIO & operator = ( const casAsyncWriteIO & ); }; @@ -778,7 +765,7 @@ private: // casAsyncPVExistIO // - for use with caServer::pvExistTest() // -class casAsyncPVExistIO : private casAsyncIOI { +class casAsyncPVExistIO { public: // @@ -802,7 +789,12 @@ public: // into a server // *************** // - epicsShareFunc caServer * getCAS() const; + epicsShareFunc caServer * getCAS () const; + + void serverInitiatedDestroy (); + +private: + class casAsyncPVExistIOI * pAsyncPVExistIOI; // // called by the server lib after the response message @@ -812,15 +804,7 @@ public: // default destroy executes a "delete this" // epicsShareFunc virtual void destroy (); - -private: - const caHdrLargeArray msg; - pvExistReturn retVal; - const caNetAddr dgOutAddr; - const ca_uint16_t protocolRevision; - const ca_uint32_t sequenceNumber; - - epicsShareFunc caStatus cbFuncAsyncIO(); + casAsyncPVExistIO ( const casAsyncPVExistIO & ); casAsyncPVExistIO & operator = ( const casAsyncPVExistIO & ); }; @@ -829,12 +813,12 @@ private: // casAsyncPVAttachIO // - for use with caServer::pvAttach() // -class casAsyncPVAttachIO : private casAsyncIOI { +class casAsyncPVAttachIO { public: // // casAsyncPVAttachIO() // - epicsShareFunc casAsyncPVAttachIO (const casCtx &ctx); + epicsShareFunc casAsyncPVAttachIO ( const casCtx & ctx ); epicsShareFunc virtual ~casAsyncPVAttachIO (); // @@ -842,7 +826,7 @@ public: // (this function does not delete the casAsyncPVAttachIO object). // Only the first call to this function has any effect. // - epicsShareFunc caStatus postIOCompletion (const pvAttachReturn &retValIn); + epicsShareFunc caStatus postIOCompletion ( const pvAttachReturn & retValIn ); // // Find the server associated with this async IO @@ -851,7 +835,12 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS() const; + epicsShareFunc caServer * getCAS () const; + + void serverInitiatedDestroy (); + +private: + class casAsyncPVAttachIOI * pAsyncPVAttachIOI; // // called by the server lib after the response message @@ -862,11 +851,6 @@ public: // epicsShareFunc virtual void destroy (); -private: - caHdrLargeArray const msg; - pvAttachReturn retVal; - - epicsShareFunc caStatus cbFuncAsyncIO (); casAsyncPVAttachIO ( const casAsyncPVAttachIO & ); casAsyncPVAttachIO & operator = ( const casAsyncPVAttachIO & ); }; @@ -877,8 +861,8 @@ private: // class casAsyncPVCreateIO : private casAsyncPVAttachIO { public: - epicsShareFunc casAsyncPVCreateIO(const casCtx &ctx); - epicsShareFunc virtual ~casAsyncPVCreateIO(); + epicsShareFunc casAsyncPVCreateIO ( const casCtx & ctx ); + epicsShareFunc virtual ~casAsyncPVCreateIO (); private: casAsyncPVCreateIO ( const casAsyncPVCreateIO & ); casAsyncPVCreateIO & operator = ( const casAsyncPVCreateIO & ); @@ -890,8 +874,8 @@ private: // class epicsShareClass pvCreateReturn : public pvAttachReturn { public: - pvCreateReturn (caStatus statIn) : pvAttachReturn(statIn) {}; - pvCreateReturn (casPV &pvIn) : pvAttachReturn (pvIn) {}; + pvCreateReturn ( caStatus statIn ) : pvAttachReturn ( statIn ) {}; + pvCreateReturn ( casPV & pvIn ) : pvAttachReturn ( pvIn ) {}; }; // TODO: diff --git a/src/cas/generic/clientBufMemoryManager.cpp b/src/cas/generic/clientBufMemoryManager.cpp index 4b39ca94a..70a0a5e46 100644 --- a/src/cas/generic/clientBufMemoryManager.cpp +++ b/src/cas/generic/clientBufMemoryManager.cpp @@ -16,7 +16,8 @@ * 505 665 1831 */ -#include "server.h" +#define epicsExportSharedSymbols +#include "clientBufMemoryManager.h" bufSizeT clientBufMemoryManager::maxSize () const { diff --git a/src/cas/generic/clientBufMemoryManager.h b/src/cas/generic/clientBufMemoryManager.h new file mode 100644 index 000000000..9d63431e7 --- /dev/null +++ b/src/cas/generic/clientBufMemoryManager.h @@ -0,0 +1,50 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef clientBufMemoryManagerh +#define clientBufMemoryManagerh + +#include + +typedef unsigned bufSizeT; +static const unsigned bufSizeT_MAX = UINT_MAX; + +class casBufferFactory { +public: + casBufferFactory (); + ~casBufferFactory (); + unsigned smallBufferSize () const; + char * newSmallBuffer (); + void destroySmallBuffer ( char * pBuf ); + unsigned largeBufferSize () const; + char * newLargeBuffer (); + void destroyLargeBuffer ( char * pBuf ); +private: + void * smallBufFreeList; + void * largeBufFreeList; + unsigned largeBufferSizePriv; +}; + +struct casBufferParm { + char * pBuf; + bufSizeT bufSize; +}; + +class clientBufMemoryManager { +public: + casBufferParm allocate ( bufSizeT newMinSize ); + void release ( char * pBuf, bufSizeT bufSize ); + bufSizeT maxSize () const; +private: + casBufferFactory bufferFactory; +}; + +#endif // clientBufMemoryManagerh + diff --git a/src/cas/generic/inBuf.cc b/src/cas/generic/inBuf.cc index 025166490..4e62540fa 100644 --- a/src/cas/generic/inBuf.cc +++ b/src/cas/generic/inBuf.cc @@ -15,8 +15,11 @@ * 505 665 1831 */ -#include "server.h" -#include "inBufIL.h" // inBuf in line func +#include +#include + +#define epicsExportSharedSymbols +#include "inBuf.h" // // inBuf::inBuf() diff --git a/src/cas/generic/inBuf.h b/src/cas/generic/inBuf.h new file mode 100644 index 000000000..50df7c932 --- /dev/null +++ b/src/cas/generic/inBuf.h @@ -0,0 +1,170 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef inBufh +#define inBufh + +#ifdef epicsExportSharedSymbols +# define epicsExportSharedSymbols_inBufh +# undef epicsExportSharedSymbols +#endif + +#undef epicsAssertAuthor +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" +#include "epicsAssert.h" + +#ifdef epicsExportSharedSymbols_inBufh +# define epicsExportSharedSymbols +# include "shareLib.h" +#endif + +#include "clientBufMemoryManager.h" + +class inBufCtx { + friend class inBuf; +public: + enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess }; + inBufCtx ( const inBuf & ); // success + inBufCtx (); // failure + + pushCtxResult pushResult () const; + +private: + pushCtxResult stat; + char * pBuf; + bufSizeT bufSize; + bufSizeT bytesInBuffer; + bufSizeT nextReadIndex; +}; + +class inBufClient { // X aCC 655 +public: + enum fillCondition { casFillNone, casFillProgress, + casFillDisconnect }; + // this is a hack for a Solaris IP kernel feature + enum fillParameter { fpNone, fpUseBroadcastInterface }; + virtual unsigned getDebugLevel () const = 0; + virtual bufSizeT incomingBytesPresent () const = 0; + virtual fillCondition xRecv ( char *pBuf, bufSizeT nBytesToRecv, + enum fillParameter parm, bufSizeT &nByesRecv ) = 0; + virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0; +}; + +class inBuf { + friend class inBufCtx; +public: + inBuf ( class inBufClient &, class clientBufMemoryManager &, + bufSizeT ioMinSizeIn ); + virtual ~inBuf (); + bufSizeT bytesPresent () const; + bufSizeT bytesAvailable () const; + bool full () const; + inBufClient::fillCondition fill ( + inBufClient::fillParameter parm = inBufClient::fpNone ); + void show ( unsigned level ) const; + void removeMsg ( bufSizeT nBytes ); + char * msgPtr () const; + // + // This is used to create recursive protocol stacks. A subsegment + // of the buffer of max size "maxSize" is assigned to the next + // layer down in the protocol stack by pushCtx () until popCtx () + // is called. The roiutine popCtx () returns the actual number + // of bytes used by the next layer down. + // + // pushCtx() returns an outBufCtx to be restored by popCtx() + // + const inBufCtx pushCtx ( bufSizeT headerSize, bufSizeT bodySize ); + bufSizeT popCtx ( const inBufCtx & ); // returns actual size + unsigned bufferSize () const; + void expandBuffer (); +private: + class inBufClient & client; + class clientBufMemoryManager & memMgr; + char * pBuf; + bufSizeT bufSize; + bufSizeT bytesInBuffer; + bufSizeT nextReadIndex; + bufSizeT ioMinSize; + unsigned ctxRecursCount; + inBuf ( const inBuf & ); + inBuf & operator = ( const inBuf & ); +}; + +// +// inBuf::bytesPresent() +// +inline bufSizeT inBuf::bytesPresent () const +{ + return this->bytesInBuffer-this->nextReadIndex; +} + +// +// inBuf::bytesAvailable() +// +inline bufSizeT inBuf::bytesAvailable () const +{ + bufSizeT bp; + bp = this->bytesPresent (); + bp += this->client.incomingBytesPresent (); + return bp; +} + +// +// inBuf::full() +// +inline bool inBuf::full () const +{ + if (this->bufSize-this->bytesPresent()ioMinSize) { + return true; + } + return false; +} + +// +// inBuf::msgPtr() +// +inline char *inBuf::msgPtr () const +{ + return &this->pBuf[this->nextReadIndex]; +} + +// +// inBuf::removeMsg() +// +inline void inBuf::removeMsg ( bufSizeT nBytes ) +{ + this->nextReadIndex += nBytes; + assert ( this->nextReadIndex <= this->bytesInBuffer ); +} + +// +// inBufCtx::inBufCtx () +// +inline inBufCtx::inBufCtx () : + stat (pushCtxNoSpace) {} + +// +// inBufCtx::inBufCtx () +// +inline inBufCtx::inBufCtx (const inBuf &inBufIn) : + stat (pushCtxSuccess), pBuf (inBufIn.pBuf), + bufSize (inBufIn.bufSize), bytesInBuffer (inBufIn.bytesInBuffer), + nextReadIndex (inBufIn.nextReadIndex) {} + +// +// inBufCtx::pushResult +// +inline inBufCtx::pushCtxResult inBufCtx::pushResult () const +{ + return this->stat; +} + +#endif // inBufh + diff --git a/src/cas/generic/inBufIL.h b/src/cas/generic/inBufIL.h deleted file mode 100644 index 16f977fe0..000000000 --- a/src/cas/generic/inBufIL.h +++ /dev/null @@ -1,84 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -#ifndef inBufILh -#define inBufILh - -// -// inBuf::bytesPresent() -// -inline bufSizeT inBuf::bytesPresent () const -{ - return this->bytesInBuffer-this->nextReadIndex; -} - -// -// inBuf::bytesAvailable() -// -inline bufSizeT inBuf::bytesAvailable () const -{ - bufSizeT bp; - bp = this->bytesPresent (); - bp += this->client.incomingBytesPresent (); - return bp; -} - -// -// inBuf::full() -// -inline bool inBuf::full () const -{ - if (this->bufSize-this->bytesPresent()ioMinSize) { - return true; - } - return false; -} - -// -// inBuf::msgPtr() -// -inline char *inBuf::msgPtr () const -{ - return &this->pBuf[this->nextReadIndex]; -} - -// -// inBuf::removeMsg() -// -inline void inBuf::removeMsg ( bufSizeT nBytes ) -{ - this->nextReadIndex += nBytes; - assert ( this->nextReadIndex <= this->bytesInBuffer ); -} - -// -// inBufCtx::inBufCtx () -// -inline inBufCtx::inBufCtx () : - stat (pushCtxNoSpace) {} - -// -// inBufCtx::inBufCtx () -// -inline inBufCtx::inBufCtx (const inBuf &inBufIn) : - stat (pushCtxSuccess), pBuf (inBufIn.pBuf), - bufSize (inBufIn.bufSize), bytesInBuffer (inBufIn.bytesInBuffer), - nextReadIndex (inBufIn.nextReadIndex) {} - -// -// inBufCtx::pushResult -// -inline inBufCtx::pushCtxResult inBufCtx::pushResult () const -{ - return this->stat; -} - -#endif // inBufILh - diff --git a/src/cas/generic/ioBlocked.h b/src/cas/generic/ioBlocked.h new file mode 100644 index 000000000..f581eab69 --- /dev/null +++ b/src/cas/generic/ioBlocked.h @@ -0,0 +1,56 @@ + +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef ioBlockedh +#define ioBlockedh + +#ifdef epicsExportSharedSymbols +# define epicsExportSharedSymbols_ioBlockedh +# undef epicsExportSharedSymbols +#endif + +#include "tsDLList.h" + +#ifdef epicsExportSharedSymbols_ioBlockedh +# define epicsExportSharedSymbols +# include "shareLib.h" +#endif + +class ioBlocked : public tsDLNode < ioBlocked > { +friend class ioBlockedList; +public: + ioBlocked (); + virtual ~ioBlocked (); +private: + ioBlockedList * pList; + virtual void ioBlockedSignal (); +}; + +class ioBlockedList : private tsDLList { +friend class ioBlocked; +public: + ioBlockedList (); + virtual ~ioBlockedList (); + void signal (); + void addItemToIOBLockedList ( ioBlocked & item ); + ioBlockedList ( const ioBlockedList & ); + ioBlockedList & operator = ( const ioBlockedList & ); +}; + +#endif // ioBlockedh + diff --git a/src/cas/generic/mt/ioBlocked.cc b/src/cas/generic/mt/ioBlocked.cc index 89ad2ba27..2d9b4873e 100644 --- a/src/cas/generic/mt/ioBlocked.cc +++ b/src/cas/generic/mt/ioBlocked.cc @@ -15,9 +15,9 @@ #include +#define epicsExportSharedSymbols #include "casdef.h" - // // ioBlocked::~ioBlocked() // diff --git a/src/cas/generic/outBuf.cc b/src/cas/generic/outBuf.cc index 0346e60dc..f9f973531 100644 --- a/src/cas/generic/outBuf.cc +++ b/src/cas/generic/outBuf.cc @@ -15,8 +15,8 @@ * 505 665 1831 */ -#include "server.h" -#include "outBufIL.h" // outBuf in line func +#define epicsExportSharedSymbols +#include "outBuf.h" #include "osiWireFormat.h" // diff --git a/src/cas/generic/outBuf.h b/src/cas/generic/outBuf.h new file mode 100644 index 000000000..2d815b51a --- /dev/null +++ b/src/cas/generic/outBuf.h @@ -0,0 +1,169 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef outBufh +#define outBufh + +#ifdef epicsExportSharedSymbols +# define epicsExportSharedSymbols_outBufh +# undef epicsExportSharedSymbols +#endif + +#include "caProto.h" + +#ifdef epicsExportSharedSymbols_outBufh +# define epicsExportSharedSymbols +# include "shareLib.h" +#endif + +#include "casdef.h" +#include "clientBufMemoryManager.h" + +// +// outBufCtx +// +class outBufCtx { + friend class outBuf; +public: + enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess }; + outBufCtx ( const outBuf & ); // success + outBufCtx (); // failure + + pushCtxResult pushResult () const; + +private: + pushCtxResult stat; + char * pBuf; + bufSizeT bufSize; + bufSizeT stack; +}; + +class outBufClient { // X aCC 655 +public: + enum flushCondition { flushNone, flushProgress, flushDisconnect }; + virtual unsigned getDebugLevel () const = 0; + virtual void sendBlockSignal () = 0; + virtual flushCondition xSend ( char *pBuf, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent ) = 0; + virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0; +}; + +// +// outBuf +// +class outBuf { + friend class outBufCtx; +public: + outBuf ( outBufClient &, clientBufMemoryManager & ); + virtual ~outBuf (); + + bufSizeT bytesPresent () const; + + // + // flush output queue + // (returns the number of bytes sent) + // + outBufClient::flushCondition flush ( bufSizeT spaceRequired=bufSizeT_MAX ); + + void show (unsigned level) const; + + unsigned bufferSize () const; + + // + // allocate message buffer space + // (leaves message buffer locked) + // + caStatus copyInHeader ( ca_uint16_t response, ca_uint32_t payloadSize, + ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, + ca_uint32_t responseSpecific, void **pPayload ); + + // + // commit message created with copyInHeader + // + void commitMsg (); + void commitMsg ( ca_uint32_t reducedPayloadSize ); + + caStatus allocRawMsg ( bufSizeT msgsize, void **ppMsg ); + void commitRawMsg ( bufSizeT size ); + + // + // This is used to create recursive protocol stacks. A subsegment + // of the buffer of max size "maxSize" is assigned to the next + // layer down in the protocol stack by pushCtx () until popCtx () + // is called. The routine popCtx () returns the actual number + // of bytes used by the next layer down. + // + // pushCtx() returns an outBufCtx to be restored by popCtx() + // + const outBufCtx pushCtx ( bufSizeT headerSize, + bufSizeT maxBodySize, void *&pHeader ); + bufSizeT popCtx ( const outBufCtx & ); // returns actual size + +private: + outBufClient & client; + clientBufMemoryManager & memMgr; + char * pBuf; + bufSizeT bufSize; + bufSizeT stack; + unsigned ctxRecursCount; + + void expandBuffer (); + + outBuf ( const outBuf & ); + outBuf & operator = ( const outBuf & ); +}; + +// +// outBuf::bytesPresent () +// number of bytes in the output queue +// +inline bufSizeT outBuf::bytesPresent () const +{ + // + // Note on use of lock here: + // This guarantees that any pushCtx() operation + // in progress completes before another thread checks. + // + bufSizeT result = this->stack; + return result; +} + +// +// outBuf::commitRawMsg() +// +inline void outBuf::commitRawMsg (bufSizeT size) +{ + this->stack += size; + assert ( this->stack <= this->bufSize ); +} + +// +// outBufCtx::outBufCtx () +// +inline outBufCtx::outBufCtx () : + stat (pushCtxNoSpace) {} + +// +// outBufCtx::outBufCtx () +// +inline outBufCtx::outBufCtx (const outBuf &outBufIn) : + stat (pushCtxSuccess), pBuf (outBufIn.pBuf), + bufSize (outBufIn.bufSize), stack (outBufIn.stack) {} + +// +// outBufCtx::pushResult +// +inline outBufCtx::pushCtxResult outBufCtx::pushResult () const +{ + return this->stat; +} + +#endif // outBufh + diff --git a/src/cas/generic/outBufIL.h b/src/cas/generic/outBufIL.h deleted file mode 100644 index e149a68b7..000000000 --- a/src/cas/generic/outBufIL.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -#ifndef outBufILh -#define outBufILh - -#ifdef epicsExportSharedSymbols -#define outBufILh_epicsExportSharedSymbols -#undef epicsExportSharedSymbols -#endif - -#include "epicsGuard.h" - -#ifdef outBufILh_epicsExportSharedSymbols -#define epicsExportSharedSymbols -#endif - -// -// outBuf::bytesPresent () -// number of bytes in the output queue -// -inline bufSizeT outBuf::bytesPresent () const -{ - // - // Note on use of lock here: - // This guarantees that any pushCtx() operation - // in progress completes before another thread checks. - // - bufSizeT result = this->stack; - return result; -} - -// -// outBuf::commitRawMsg() -// -inline void outBuf::commitRawMsg (bufSizeT size) -{ - this->stack += size; - assert ( this->stack <= this->bufSize ); -} - -// -// outBufCtx::outBufCtx () -// -inline outBufCtx::outBufCtx () : - stat (pushCtxNoSpace) {} - -// -// outBufCtx::outBufCtx () -// -inline outBufCtx::outBufCtx (const outBuf &outBufIn) : - stat (pushCtxSuccess), pBuf (outBufIn.pBuf), - bufSize (outBufIn.bufSize), stack (outBufIn.stack) {} - -// -// outBufCtx::pushResult -// -inline outBufCtx::pushCtxResult outBufCtx::pushResult () const -{ - return this->stat; -} - -#endif // outBufILh - diff --git a/src/cas/generic/server.h b/src/cas/generic/server.h deleted file mode 100644 index 4b3b94de9..000000000 --- a/src/cas/generic/server.h +++ /dev/null @@ -1,974 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef INCLserverh -#define INCLserverh - -// -// ANSI C -// -#include - -#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) -// -#include "gdd.h" // EPICS data descriptors -#undef epicsAssertAuthor -#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -#include "epicsAssert.h" // EPICS assert() macros -#include "epicsTime.h" // EPICS os independent time -#include "alarm.h" // EPICS alarm severity/condition -#include "errMdef.h" // EPICS error codes -#include "resourceLib.h" // EPICS hashing templates -#include "errlog.h" // EPICS error logging interface - -// -// 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 "epicsMutex.h" -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 copyBetweenDD(gdd &dest, gdd &src); - -enum xBlockingStatus {xIsBlocking, xIsntBlocking}; -enum casIOState {casOnLine, casOffLine}; -typedef unsigned bufSizeT; -static const unsigned bufSizeT_MAX = UINT_MAX; - -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; - -class casCtx { -public: - casCtx(); - - // - // get - // - const caHdrLargeArray * getMsg () const; - void * getData () const; - caServerI * getServer () const; - casCoreClient * getClient () const; - casPVI * getPV () const; - casChannelI * getChannel () const; - - void setMsg ( const caHdrLargeArray &, void * pBody ); - - void setServer ( caServerI * p ); - - void setClient ( casCoreClient * p ); - - void setPV ( casPVI * p ); - - void setChannel ( casChannelI * p ); - - void show ( unsigned level ) const; - -private: - caHdrLargeArray 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 -}; - -// -// inBufCtx -// -class inBufCtx { - friend class inBuf; -public: - enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess }; - inBufCtx ( const inBuf & ); // success - inBufCtx (); // failure - - pushCtxResult pushResult () const; - -private: - pushCtxResult stat; - char * pBuf; - bufSizeT bufSize; - bufSizeT bytesInBuffer; - bufSizeT nextReadIndex; -}; - -class casBufferFactory { -public: - casBufferFactory (); - ~casBufferFactory (); - unsigned smallBufferSize () const; - char * newSmallBuffer (); - void destroySmallBuffer ( char * pBuf ); - unsigned largeBufferSize () const; - char * newLargeBuffer (); - void destroyLargeBuffer ( char * pBuf ); -private: - void * smallBufFreeList; - void * largeBufFreeList; - unsigned largeBufferSizePriv; -}; - -struct casBufferParm { - char * pBuf; - bufSizeT bufSize; -}; - -class clientBufMemoryManager { -public: - casBufferParm allocate ( bufSizeT newMinSize ); - void release ( char * pBuf, bufSizeT bufSize ); - bufSizeT maxSize () const; -private: - casBufferFactory bufferFactory; -}; - -class inBufClient { // X aCC 655 -public: - enum fillCondition { casFillNone, casFillProgress, - casFillDisconnect }; - // this is a hack for a Solaris IP kernel feature - enum fillParameter { fpNone, fpUseBroadcastInterface }; - virtual unsigned getDebugLevel () const = 0; - virtual bufSizeT incomingBytesPresent () const = 0; - virtual fillCondition xRecv ( char *pBuf, bufSizeT nBytesToRecv, - enum fillParameter parm, bufSizeT &nByesRecv ) = 0; - virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0; -}; - -// -// inBuf -// -class inBuf { - friend class inBufCtx; -public: - - inBuf ( inBufClient &, clientBufMemoryManager &, - bufSizeT ioMinSizeIn ); - virtual ~inBuf (); - - bufSizeT bytesPresent () const; - - bufSizeT bytesAvailable () const; - - bool full () const; - - // - // fill the input buffer with any incoming messages - // - inBufClient::fillCondition fill ( - inBufClient::fillParameter parm = inBufClient::fpNone ); - - void show ( unsigned level ) const; - - void removeMsg ( bufSizeT nBytes ); - - char * msgPtr () const; - - // - // This is used to create recursive protocol stacks. A subsegment - // of the buffer of max size "maxSize" is assigned to the next - // layer down in the protocol stack by pushCtx () until popCtx () - // is called. The roiutine popCtx () returns the actual number - // of bytes used by the next layer down. - // - // pushCtx() returns an outBufCtx to be restored by popCtx() - // - const inBufCtx pushCtx ( bufSizeT headerSize, bufSizeT bodySize ); - bufSizeT popCtx ( const inBufCtx & ); // returns actual size - - unsigned bufferSize () const; - - void expandBuffer (); - -private: - inBufClient & client; - clientBufMemoryManager & memMgr; - char * pBuf; - bufSizeT bufSize; - bufSizeT bytesInBuffer; - bufSizeT nextReadIndex; - bufSizeT ioMinSize; - unsigned ctxRecursCount; - inBuf ( const inBuf & ); - inBuf & operator = ( const inBuf & ); -}; - -// -// outBufCtx -// -class outBufCtx { - friend class outBuf; -public: - enum pushCtxResult { pushCtxNoSpace, pushCtxSuccess }; - outBufCtx ( const outBuf & ); // success - outBufCtx (); // failure - - pushCtxResult pushResult () const; - -private: - pushCtxResult stat; - char * pBuf; - bufSizeT bufSize; - bufSizeT stack; -}; - -class outBufClient { // X aCC 655 -public: - enum flushCondition { flushNone, flushProgress, flushDisconnect }; - virtual unsigned getDebugLevel () const = 0; - virtual void sendBlockSignal () = 0; - virtual flushCondition xSend ( char *pBuf, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent ) = 0; - virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0; -}; - -// -// outBuf -// -class outBuf { - friend class outBufCtx; -public: - - outBuf ( outBufClient &, clientBufMemoryManager & ); - virtual ~outBuf (); - - bufSizeT bytesPresent () const; - - // - // flush output queue - // (returns the number of bytes sent) - // - outBufClient::flushCondition flush ( bufSizeT spaceRequired=bufSizeT_MAX ); - - void show (unsigned level) const; - - unsigned bufferSize () const; - - // - // allocate message buffer space - // (leaves message buffer locked) - // - caStatus copyInHeader ( ca_uint16_t response, ca_uint32_t payloadSize, - ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, - ca_uint32_t responseSpecific, void **pPayload ); - - // - // commit message created with copyInHeader - // - void commitMsg (); - void commitMsg ( ca_uint32_t reducedPayloadSize ); - - caStatus allocRawMsg ( bufSizeT msgsize, void **ppMsg ); - void commitRawMsg ( bufSizeT size ); - - // - // This is used to create recursive protocol stacks. A subsegment - // of the buffer of max size "maxSize" is assigned to the next - // layer down in the protocol stack by pushCtx () until popCtx () - // is called. The roiutine popCtx () returns the actual number - // of bytes used by the next layer down. - // - // pushCtx() returns an outBufCtx to be restored by popCtx() - // - const outBufCtx pushCtx ( bufSizeT headerSize, bufSizeT maxBodySize, void *&pHeader ); - bufSizeT popCtx ( const outBufCtx & ); // returns actual size - -private: - outBufClient & client; - clientBufMemoryManager & memMgr; - char * pBuf; - bufSizeT bufSize; - bufSizeT stack; - unsigned ctxRecursCount; - - void expandBuffer (); - - outBuf ( const outBuf & ); - outBuf & operator = ( const outBuf & ); -}; - -// -// casEventSys -// -class casEventSys { -public: - casEventSys ( casCoreClient & ); - ~casEventSys (); - - void show ( unsigned level ) const; - struct processStatus { - casProcCond cond; - unsigned nAccepted; - }; - processStatus process (); - - void installMonitor (); - void removeMonitor (); - - void removeFromEventQueue ( casEvent & ); - void addToEventQueue ( casEvent & ); - - void insertEventQueue ( casEvent & insert, casEvent & prevEvent ); - void pushOnToEventQueue ( casEvent & event ); - - bool full (); - - bool getNDuplicateEvents () const; - - void setDestroyPending (); - - void eventsOn (); - void eventsOff (); - -private: - tsDLList < casEvent > eventLogQue; - casCoreClient & client; - class casEventPurgeEv * pPurgeEvent; // flow control purge complete event - unsigned numEventBlocks; // N event blocks installed - unsigned maxLogEntries; // max log entries - bool destroyPending; - bool replaceEvents; // replace last existing event on queue - bool dontProcess; // flow ctl is on - dont process event queue - - casEventSys ( const casEventSys & ); - casEventSys & operator = ( const casEventSys & ); - friend class casEventPurgeEv; -}; - -/* - * when this event reaches the top of the queue we - * know that all duplicate events have been purged - * and that now no events should not be sent to the - * client until it exits flow control mode - */ -class casEventPurgeEv : public casEvent { -public: - casEventPurgeEv ( class casEventSys & ); -private: - casEventSys & evSys; - caStatus cbFunc ( casCoreClient & ); - void eventSysDestroyNotify ( casCoreClient & ); -}; - -// -// casCoreClient -// (this will eventually support direct communication -// between the client lib and the server lib) -// -class casCoreClient : public ioBlocked, - private casMonitorCallbackInterface { -public: - casCoreClient ( caServerI & serverInternal ); - virtual ~casCoreClient (); - virtual caStatus disconnectChan( caResId id ); - virtual void show ( unsigned level ) const; - virtual void installChannel ( casChannelI & ); - virtual void removeChannel ( casChannelI & ); - - void installAsyncIO ( casAsyncIOI & ioIn ); - void removeAsyncIO ( casAsyncIOI & ioIn ); - void installChannelsAsynchIO ( - tsDLList < casAsyncIOI > & list, casAsyncIOI & io ); - void uninstallChannelsAsynchIO ( - tsDLList < casAsyncIOI > & list, casAsyncIOI & io ); - - caServerI & getCAS () const; - - // - // one virtual function for each CA request type that has - // asynchronous completion - // - virtual caStatus asyncSearchResponse ( - const caNetAddr & outAddr, - const caHdrLargeArray &, const pvExistReturn &, - ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber ); - virtual caStatus createChanResponse ( - const caHdrLargeArray &, const pvAttachReturn &); - virtual caStatus readResponse ( - casChannelI *, const caHdrLargeArray &, const smartConstGDDPointer &, const caStatus ); - virtual caStatus readNotifyResponse ( - casChannelI *, const caHdrLargeArray &, const smartConstGDDPointer &, const caStatus ); - virtual caStatus writeResponse ( const caHdrLargeArray &, const caStatus ); - virtual caStatus writeNotifyResponse ( const caHdrLargeArray &, const caStatus ); - virtual caStatus monitorResponse ( casChannelI &chan, const caHdrLargeArray &msg, - const smartConstGDDPointer & pDesc, const caStatus status ); - virtual caStatus accessRightsResponse ( casChannelI * ); - virtual caStatus enumPostponedCreateChanResponse ( casChannelI & chan, - const caHdrLargeArray & hdr, unsigned dbrType ); - virtual caStatus channelCreateFailedResp ( const caHdrLargeArray &, - const caStatus createStatus ); - - virtual void eventSignal () = 0; - - virtual ca_uint16_t protocolRevision () const = 0; - - // - // used only with DG clients - // - virtual caNetAddr fetchLastRecvAddr () const; - virtual ca_uint32_t datagramSequenceNumber () const; - - bool okToStartAsynchIO (); - - casMonEvent & casMonEventFactory ( casMonitor & monitor, - const smartConstGDDPointer & pNewValue ); - void casMonEventDestroy ( casMonEvent & ); - - casEventSys::processStatus eventSysProcess(); - - void addToEventQueue ( casEvent & ); - caStatus addToEventQueue ( casAsyncIOI &, - bool & onTheQueue, bool & posted ); - void removeFromEventQueue ( casEvent & ); - void removeFromEventQueue ( casAsyncIOI & ); - void enableEvents (); - void disableEvents (); - - void setDestroyPending (); - - casMonitor & monitorFactory ( - casChannelI & , - caResId clientId, - const unsigned long count, - const unsigned type, - const casEventMask & ); - void destroyMonitor ( casMonitor & ); - caStatus casMonitorCallBack ( casMonitor &, - const smartConstGDDPointer & ); - casMonitor * lookupMonitor ( const caResId &idIn ); - void postEvent ( tsDLList &, - const casEventMask &select, const gdd &event ); - void showMonitorsInList ( - const tsDLList < casMonitor > & monitorList, - unsigned level ) const; - -protected: - mutable epicsMutex mutex; - casCtx ctx; - bool asyncIOFlag; - - void lock (); - void unlock (); - -private: - casEventSys eventSys; - tsDLList < casAsyncIOI > ioInProgList; - casCoreClient ( const casCoreClient & ); - casCoreClient & operator = ( const casCoreClient & ); -}; - -// -// casClient -// -class casClient : public casCoreClient, public outBufClient, - public inBufClient { -public: - - casClient ( caServerI &, clientBufMemoryManager &, bufSizeT ioMinSizeIn ); - virtual ~casClient (); - - virtual void show ( unsigned level ) const; - - caStatus sendErr ( const caHdrLargeArray *, const int reportedStatus, - const char *pFormat, ... ); - - ca_uint16_t protocolRevision() const {return this->minor_version_number;} - - casChannelI * lookupChannel ( const caResId &id ); - - virtual void hostName ( char *pBuf, unsigned bufSize ) const = 0; - - void sendVersion (); - -protected: - inBuf in; - outBuf out; - ca_uint16_t minor_version_number; - unsigned incommingBytesToDrain; - epicsTime lastSendTS; - epicsTime lastRecvTS; - - caStatus sendErrWithEpicsStatus ( const caHdrLargeArray *pMsg, - caStatus epicsStatus, caStatus clientStatus ); - -# define logBadId(MP, DP, CACSTAT, RESID) \ - this->logBadIdWithFileAndLineno(MP, DP, CACSTAT, __FILE__, __LINE__, RESID) - caStatus logBadIdWithFileAndLineno ( const caHdrLargeArray *mp, - const void *dp, const int cacStat, const char *pFileName, - const unsigned lineno, const unsigned resId ); - - caStatus processMsg(); - - // - // dump message to stderr - // - void dumpMsg ( const caHdrLargeArray *mp, const void *dp, const char *pFormat, ... ); - - -private: - typedef caStatus ( casClient::*pCASMsgHandler ) (); - - // - // one function for each CA request type - // - virtual caStatus uknownMessageAction () = 0; - caStatus ignoreMsgAction (); - virtual caStatus versionAction (); - 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 (); - - virtual void userName ( char * pBuf, unsigned bufSize ) const = 0; - - // - // static members - // - static void loadProtoJumpTable(); - static pCASMsgHandler msgHandlers[CA_PROTO_LAST_CMMD+1u]; - static bool msgHandlersInit; - - casClient ( const casClient & ); - casClient & operator = ( const casClient & ); -}; - -// -// casStrmClient -// -class casStrmClient : - public casClient, - public tsDLNode { -public: - casStrmClient ( caServerI &, clientBufMemoryManager & ); - virtual ~casStrmClient(); - - void show ( unsigned level ) const; - - void flush (); - - // - // 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 caHdrLargeArray &, const pvAttachReturn &); - caStatus readResponse (casChannelI *pChan, const caHdrLargeArray &msg, - const smartConstGDDPointer &pDesc, const caStatus status); - caStatus readNotifyResponse (casChannelI *pChan, const caHdrLargeArray &msg, - const smartConstGDDPointer &pDesc, const caStatus status); - caStatus writeResponse (const caHdrLargeArray &msg, const caStatus status); - caStatus writeNotifyResponse (const caHdrLargeArray &msg, const caStatus status); - caStatus monitorResponse ( casChannelI & chan, const caHdrLargeArray & msg, - const smartConstGDDPointer & pDesc, const caStatus status ); - caStatus enumPostponedCreateChanResponse ( casChannelI & chan, - const caHdrLargeArray & hdr, unsigned dbrType ); - caStatus channelCreateFailedResp ( const caHdrLargeArray &, - const caStatus createStatus ); - - caStatus disconnectChan ( caResId id ); - - unsigned getDebugLevel () const; - - virtual void hostName ( char * pBuf, unsigned bufSize ) const = 0; - void userName ( char * pBuf, unsigned bufSize ) const; - -private: - tsDLList 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 uknownMessageAction (); - 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 (); - - caStatus writeArrayData(); - caStatus writeScalarData(); - caStatus writeString(); - - // - // io independent send/recv - // - outBufClient::flushCondition xSend ( char * pBuf, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT & nBytesSent ); - inBufClient::fillCondition xRecv ( char * pBuf, bufSizeT nBytesToRecv, - inBufClient::fillParameter parm, bufSizeT & nByesRecv ); - - virtual xBlockingStatus blockingState() const = 0; - - virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq, - bufSizeT & nBytesActual ) = 0; - virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq, - bufSizeT &nBytesActual ) = 0; - - caStatus readNotifyFailureResponse ( const caHdrLargeArray & msg, - const caStatus ECA_XXXX ); - - caStatus monitorFailureResponse ( const caHdrLargeArray & msg, - const caStatus ECA_XXXX ); - - caStatus writeNotifyResponseECA_XXX ( const caHdrLargeArray &msg, - const caStatus status ); - - caStatus casMonitorCallBack ( casMonitor &, - const smartConstGDDPointer & pValue ); - - casStrmClient ( const casStrmClient & ); - casStrmClient & operator = ( const casStrmClient & ); -}; - -class casDGIntfIO; - - -// -// casDGClient -// -class casDGClient : public casClient { -public: - casDGClient ( caServerI &serverIn, clientBufMemoryManager & ); - virtual ~casDGClient(); - - virtual void show (unsigned level) const; - - // - // only for use with DG io - // - void sendBeacon ( ca_uint32_t beaconNumber ); - - virtual void sendBeaconIO ( char &msg, bufSizeT length, - aitUint16 &portField, aitUint32 &addrField ) = 0; - - void destroy (); - - unsigned getDebugLevel () const; - - void hostName ( char * pBuf, unsigned bufSize ) const; - void userName ( char * pBuf, unsigned bufSize ) const; - - caNetAddr fetchLastRecvAddr () const; - - virtual caNetAddr serverAddress () const = 0; - -protected: - - caStatus processDG (); - -private: - caNetAddr lastRecvAddr; - ca_uint32_t seqNoOfReq; - - // - // one function for each CA request type - // - caStatus searchAction (); - caStatus uknownMessageAction (); - - // - // searchFailResponse() - // - caStatus searchFailResponse ( const caHdrLargeArray *pMsg ); - - caStatus searchResponse ( const caHdrLargeArray &, - const pvExistReturn & retVal ); - - caStatus asyncSearchResponse ( const caNetAddr & outAddr, - const caHdrLargeArray & msg, const pvExistReturn & retVal, - ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber ); - - // - // IO depen - // - outBufClient::flushCondition xSend ( char *pBufIn, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent ); - inBufClient::fillCondition xRecv ( char *pBufIn, bufSizeT nBytesToRecv, - fillParameter parm, bufSizeT &nByesRecv ); - - virtual outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq, - const caNetAddr & addr ) = 0; - virtual inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq, - fillParameter parm, bufSizeT &nBytesActual, caNetAddr & addr ) = 0; - - caStatus versionAction (); - - ca_uint32_t datagramSequenceNumber () const; - - // - // cadg - // - struct cadg { - caNetAddr cadg_addr; // invalid address indicates pad - bufSizeT cadg_nBytes; - }; - - casDGClient ( const casDGClient & ); - casDGClient & operator = ( const casDGClient & ); -}; - -// -// casEventMaskEntry -// -class casEventMaskEntry : public tsSLNode, - 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 ® - casEventMaskEntry ( const casEventMaskEntry & ); - casEventMaskEntry & operator = ( const casEventMaskEntry & ); -}; - -// -// casEventRegistry -// -class casEventRegistry : private resTable { - friend class casEventMaskEntry; -public: - - casEventRegistry () : maskBitAllocator(0) {} - - virtual ~casEventRegistry(); - - casEventMask registerEvent (const char *pName); - - void show (unsigned level) const; - -private: - unsigned maskBitAllocator; - - casEventMask maskAllocator(); - casEventRegistry ( const casEventRegistry & ); - casEventRegistry & operator = ( const casEventRegistry & ); -}; - -#include "casIOD.h" // IO dependent -#include "casOSD.h" // OS dependent - -class beaconTimer; -class beaconAnomalyGovernor; - -// -// caServerI -// -class caServerI : - public caServerOS, - public caServerIO, - public ioBlockedList, - private chronIntIdResTable, - public casEventRegistry { -public: - caServerI ( caServer &tool ); - ~caServerI (); - - void installClient (casStrmClient *pClient); - void removeClient (casStrmClient *pClient); - - bool roomForNewChannel() const; - - unsigned getDebugLevel() const { return debugLevel; } - inline void setDebugLevel ( unsigned debugLevelIn ); - - void show ( unsigned level ) const; - - casMonitor * lookupMonitor ( const caResId &idIn ); - casChannelI * lookupChannel ( const caResId &idIn ); - - caServer *getAdapter (); - - void installItem ( casRes & res ); - casRes * removeItem ( casRes & res ); - - caServer * operator -> (); - - void connectCB (casIntfOS &); - - casEventMask valueEventMask() const; // DBE_VALUE registerEvent("value") - casEventMask logEventMask() const; // DBE_LOG registerEvent("log") - casEventMask alarmEventMask() const; // DBE_ALARM registerEvent("alarm") - - unsigned subscriptionEventsProcessed () const; - void incrEventsProcessedCounter (); - - unsigned subscriptionEventsPosted () const; - void incrEventsPostedCounter (); - - void lock () const; - void unlock () const; - - void generateBeaconAnomaly (); - - casMonEvent & casMonEventFactory ( casMonitor & monitor, - const smartConstGDDPointer & pNewValue ); - void casMonEventDestroy ( casMonEvent & ); - - casMonitor & casMonitorFactory ( casChannelI &, - caResId clientId, const unsigned long count, - const unsigned type, const casEventMask &, - casMonitorCallbackInterface & ); - void casMonitorDestroy ( casMonitor & ); - -private: - clientBufMemoryManager clientBufMemMgr; - mutable epicsMutex mutex; - tsDLList < casStrmClient > clientList; - tsDLList < casIntfOS > intfList; - tsFreeList < casMonEvent, 1024 > casMonEventFreeList; - tsFreeList < casMonitor, 1024 > casMonitorFreeList; - caServer & adapter; - beaconTimer & beaconTmr; - beaconAnomalyGovernor & beaconAnomalyGov; - unsigned debugLevel; - unsigned nEventsProcessed; - unsigned nEventsPosted; - - casEventMask valueEvent; // DBE_VALUE registerEvent("value") - casEventMask logEvent; // DBE_LOG registerEvent("log") - casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm") - - caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr, - bool addConfigAddr); - - void sendBeacon ( ca_uint32_t beaconNo ); - - caServerI ( const caServerI & ); - caServerI & operator = ( const caServerI & ); - - friend class beaconAnomalyGovernor; - friend class beaconTimer; -}; - -#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 - -bool convertContainerMemberToAtomic ( gdd & dd, - aitUint32 appType, aitUint32 elemCount ); - -#endif /*INCLserverh*/ - - diff --git a/src/cas/generic/st/caServerOS.cc b/src/cas/generic/st/caServerOS.cc index a60f0265e..e69de29bb 100644 --- a/src/cas/generic/st/caServerOS.cc +++ b/src/cas/generic/st/caServerOS.cc @@ -1,39 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* - * - * caServerOS.c - * $Id$ - * - */ - - -// -// CA server -// -#include "server.h" -#include "fdManager.h" - -// -// caServerOS::caServerOS() -// -caServerOS::caServerOS () -{ -} - -// -// caServerOS::~caServerOS() -// -caServerOS::~caServerOS() -{ -} - - diff --git a/src/cas/generic/st/casDGIntfOS.cc b/src/cas/generic/st/casDGIntfOS.cc index eae55ebbb..15715a92c 100644 --- a/src/cas/generic/st/casDGIntfOS.cc +++ b/src/cas/generic/st/casDGIntfOS.cc @@ -8,29 +8,23 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -// // // casDGIntfOS.cc // $Id$ // -// -// -// -// CA server -// -#include "server.h" -#include "inBufIL.h" // inBuf in line func -#include "outBufIL.h" // outBuf in line func -#include "casIODIL.h" // IO Depen in line func -#include "casCoreClientIL.h" + +#include "fdManager.h" + +#define epicsExportSharedFunc +#include "casDGIntfOS.h" // // casDGReadReg // class casDGReadReg : public fdReg { public: - casDGReadReg (casDGIntfOS &osIn) : + casDGReadReg ( casDGIntfOS & osIn ) : fdReg (osIn.getFD(), fdrRead), os (osIn) {} ~casDGReadReg (); diff --git a/src/cas/generic/st/casIntfOS.cc b/src/cas/generic/st/casIntfOS.cc index 916c1ea58..1c83be5c0 100644 --- a/src/cas/generic/st/casIntfOS.cc +++ b/src/cas/generic/st/casIntfOS.cc @@ -16,15 +16,11 @@ * */ +#include "fdManager.h" -// -// CA server -// -#include "server.h" +#define epicsExportSharedSymbols +#include "casIntfOS.h" -// -// casServerReg -// class casServerReg : public fdReg { public: casServerReg (casIntfOS &osIn) : @@ -37,9 +33,6 @@ private: casServerReg & operator = ( const casServerReg & ); }; -// -// casIntfOS::casIntfOS() -// casIntfOS::casIntfOS ( caServerI & casIn, clientBufMemoryManager & memMgrIn, const caNetAddr & addrIn, bool autoBeaconAddr, bool addConfigBeaconAddr ) : casIntfIO ( addrIn ), @@ -52,9 +45,6 @@ casIntfOS::casIntfOS ( caServerI & casIn, clientBufMemoryManager & memMgrIn, this->pRdReg = new casServerReg(*this); } -// -// casIntfOS::~casIntfOS() -// casIntfOS::~casIntfOS() { if (this->pRdReg) { @@ -62,25 +52,16 @@ casIntfOS::~casIntfOS() } } -// -// casServerReg::callBack() -// void casServerReg::callBack() { assert(this->os.pRdReg); this->os.cas.connectCB(this->os); } -// -// casServerReg::~casServerReg() -// casServerReg::~casServerReg() { } -// -// casIntfOS::show () -// void casIntfOS::show ( unsigned level ) const { printf ( "casIntfOS at %p\n", @@ -88,9 +69,6 @@ void casIntfOS::show ( unsigned level ) const this->casDGIntfOS::show ( level ); } -// -// casIntfOS::serverAddress () -// caNetAddr casIntfOS::serverAddress () const { return this->casIntfIO::serverAddress(); diff --git a/src/cas/generic/st/casOSD.h b/src/cas/generic/st/casOSD.h index 5fba2b166..95311b68a 100644 --- a/src/cas/generic/st/casOSD.h +++ b/src/cas/generic/st/casOSD.h @@ -29,208 +29,23 @@ #endif class caServerI; -class caServerOS; class casServerReg; -// -// caServerOS -// -class caServerOS { -public: - caServerOS (); - virtual ~caServerOS (); -private: - friend class casServerReg; -}; - class casDGReadReg; class casDGBCastReadReg; class casDGWriteReg; -// -// class casDGEvWakeup -// -class casDGEvWakeup : public epicsTimerNotify { -public: - casDGEvWakeup (); - virtual ~casDGEvWakeup(); - void show ( unsigned level ) const; - void start ( class casDGIntfOS &osIn ); -private: - epicsTimer &timer; - class casDGIntfOS *pOS; - expireStatus expire( const epicsTime & currentTime ); - casDGEvWakeup ( const casDGEvWakeup & ); - casDGEvWakeup & operator = ( const casDGEvWakeup & ); -}; -// -// class casDGIOWakeup -// -class casDGIOWakeup : public epicsTimerNotify { -public: - casDGIOWakeup (); - virtual ~casDGIOWakeup (); - void show ( unsigned level ) const; - void start ( class casDGIntfOS &osIn ); -private: - epicsTimer &timer; - class casDGIntfOS *pOS; - expireStatus expire( const epicsTime & currentTime ); - casDGIOWakeup ( const casDGIOWakeup & ); - casDGIOWakeup & operator = ( const casDGIOWakeup & ); -}; -// -// casDGIntfOS -// -class casDGIntfOS : public casDGIntfIO { - friend class casDGReadReg; - friend class casDGBCastReadReg; - friend class casDGWriteReg; -public: - casDGIntfOS ( caServerI &, clientBufMemoryManager &, - const caNetAddr & addr, bool autoBeaconAddr = true, - bool addConfigBeaconAddr = false); - virtual ~casDGIntfOS (); - virtual void show (unsigned level) const; - - void processInput(); - - void eventFlush (); - -private: - casDGIOWakeup ioWk; - casDGEvWakeup evWk; - casDGReadReg *pRdReg; - casDGBCastReadReg *pBCastRdReg; // fix for solaris bug - casDGWriteReg *pWtReg; - bool sendBlocked; - - void armRecv (); - void armSend (); - - void disarmRecv (); - void disarmSend (); - - void recvCB ( inBufClient::fillParameter parm ); - void sendCB (); - - void sendBlockSignal (); - - void ioBlockedSignal (); - - void eventSignal (); - - casDGIntfOS ( const casDGIntfOS & ); - casDGIntfOS & operator = ( const casDGIntfOS & ); -}; - -// -// casIntfOS -// -class casIntfOS : public casIntfIO, public tsDLNode, - public casDGIntfOS -{ - friend class casServerReg; -public: - casIntfOS ( caServerI &, clientBufMemoryManager &, const caNetAddr &, - bool autoBeaconAddr = true, bool addConfigBeaconAddr = false ); - virtual ~casIntfOS(); - void show ( unsigned level ) const; - caNetAddr serverAddress () const; -private: - caServerI & cas; - casServerReg * pRdReg; - - casIntfOS ( const casIntfOS & ); - casIntfOS & operator = ( const casIntfOS & ); -}; class casStreamWriteReg; class casStreamReadReg; -// -// class casStreamIOWakeup -// -class casStreamIOWakeup : public epicsTimerNotify { -public: - casStreamIOWakeup (); - virtual ~casStreamIOWakeup (); - void show ( unsigned level ) const; - void start ( casStreamOS &osIn ); -private: - epicsTimer &timer; - casStreamOS *pOS; - expireStatus expire ( const epicsTime & currentTime ); - casStreamIOWakeup ( const casStreamIOWakeup & ); - casStreamIOWakeup & operator = ( const casStreamIOWakeup & ); -}; -// -// class casStreamEvWakeup -// -class casStreamEvWakeup : public epicsTimerNotify { -public: - casStreamEvWakeup (); - virtual ~casStreamEvWakeup (); - void show ( unsigned level ) const; - void start ( casStreamOS &osIn ); -private: - epicsTimer &timer; - casStreamOS *pOS; - expireStatus expire ( const epicsTime & currentTime ); - casStreamEvWakeup ( const casStreamEvWakeup & ); - casStreamEvWakeup & operator = ( const casStreamEvWakeup & ); -}; -// -// casStreamOS -// -class casStreamOS : public casStreamIO { -public: - casStreamOS ( caServerI &, clientBufMemoryManager &, - const ioArgsToNewStreamIO & ); - ~casStreamOS (); - - void show ( unsigned level ) const; - - casProcCond processInput (); - - void eventFlush (); - -private: - casStreamEvWakeup evWk; - casStreamIOWakeup ioWk; - casStreamWriteReg * pWtReg; - casStreamReadReg * pRdReg; - bool sendBlocked; - // - // - // - inline void armSend (); - inline void armRecv (); - inline void disarmSend(); - inline void disarmRecv(); - - void recvCB (); - void sendCB (); - - void sendBlockSignal (); - - void ioBlockedSignal (); - - void eventSignal (); - - casStreamOS ( const casStreamOS & ); - casStreamOS & operator = ( const casStreamOS & ); - - friend class casStreamWriteReg; - friend class casStreamReadReg; -}; // no additions below this line #endif // includeCASOSDH diff --git a/src/cas/generic/st/casStreamOS.cc b/src/cas/generic/st/casStreamOS.cc index 4f8cc7093..da1bab815 100644 --- a/src/cas/generic/st/casStreamOS.cc +++ b/src/cas/generic/st/casStreamOS.cc @@ -18,13 +18,10 @@ // there isnt enough memory // -// -// CA server -// -#include "server.h" -#include "inBufIL.h" // inBuf inline func -#include "outBufIL.h" // outBuf inline func -#include "casCoreClientIL.h" // casCoreClient in line func +#include "fdManager.h" + +#define epicsExportSharedFunc +#include "casStreamOS.h" // // casStreamReadReg @@ -262,7 +259,7 @@ inline void casStreamOS::armRecv() // inline void casStreamOS::disarmRecv() { - if (this->pRdReg) { + if ( this->pRdReg ) { delete this->pRdReg; } } @@ -286,7 +283,7 @@ inline void casStreamOS::armSend() // inline void casStreamOS::disarmSend () { - if (this->pWtReg) { + if ( this->pWtReg ) { delete this->pWtReg; } } @@ -329,8 +326,8 @@ casStreamOS::casStreamOS ( caServerI & cas, clientBufMemoryManager & bufMgrIn, casStreamIO ( cas, bufMgrIn, ioArgs ), pWtReg ( 0 ), pRdReg ( 0 ), sendBlocked ( false ) { - this->xSetNonBlocking(); - this->armRecv(); + this->xSetNonBlocking (); + this->armRecv (); } // @@ -341,16 +338,16 @@ casStreamOS::~casStreamOS() // // attempt to flush out any remaining messages // - this->flush(); + this->flush (); - this->disarmSend(); - this->disarmRecv(); + this->disarmSend (); + this->disarmRecv (); } // // casStreamOS::show() // -void casStreamOS::show(unsigned level) const +void casStreamOS::show ( unsigned level ) const { this->casStrmClient::show(level); printf("casStreamOS at %p\n", @@ -371,7 +368,7 @@ void casStreamOS::show(unsigned level) const // void casStreamReadReg::show(unsigned level) const { - this->fdReg::show(level); + this->fdReg::show ( level ); printf ( "casStreamReadReg at %p\n", static_cast ( this ) ); } @@ -381,7 +378,7 @@ void casStreamReadReg::show(unsigned level) const // void casStreamReadReg::callBack () { - this->os.recvCB(); + this->os.recvCB (); // // NO CODE HERE // (casStreamOS::recvCB() may up indirectly deleting this object) @@ -391,7 +388,7 @@ void casStreamReadReg::callBack () // // casStreamOS::recvCB() // -void casStreamOS::recvCB() +void casStreamOS::recvCB () { assert ( this->pRdReg ); @@ -400,12 +397,12 @@ void casStreamOS::recvCB() // inBufClient::fillCondition fillCond = this->in.fill(); if ( fillCond == casFillDisconnect ) { - delete this; + this->getCAS().destroyClient ( *this ); } else { casProcCond procCond = this->processInput(); if (procCond == casProcDisconnect) { - delete this; + this->getCAS().destroyClient ( *this ); } else if ( this->in.full() ) { // @@ -482,7 +479,7 @@ void casStreamOS::sendCB() // called from a client member function // higher up on the stack // - delete this; + this->getCAS().destroyClient ( *this ); // // must _not_ touch "this" pointer // after the destroy @@ -507,7 +504,7 @@ void casStreamOS::sendCB() // called from a client member function // higher up on the stack // - delete this; + this->getCAS().destroyClient ( *this ); // // must _not_ touch "this" pointer // after the destroy @@ -527,9 +524,9 @@ void casStreamOS::sendCB() // to process the input queue in case we were send // blocked. // - casProcCond procCond = this->processInput(); - if (procCond == casProcDisconnect) { - delete this; + casProcCond procCond = this->processInput (); + if ( procCond == casProcDisconnect ) { + this->getCAS().destroyClient ( *this ); } else { // diff --git a/src/cas/generic/st/ioBlocked.cc b/src/cas/generic/st/ioBlocked.cc index 0d9fabd94..d3b93ae60 100644 --- a/src/cas/generic/st/ioBlocked.cc +++ b/src/cas/generic/st/ioBlocked.cc @@ -18,7 +18,11 @@ #include -#include "server.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" +#include "epicsAssert.h" + +#define epicsExportSharedSymbols +#include "ioBlocked.h" // // ioBlocked::ioBlocked () diff --git a/src/cas/io/bsdSocket/caServerIO.cc b/src/cas/io/bsdSocket/caServerIO.cc index 3bbaa50a5..49d0ed843 100644 --- a/src/cas/io/bsdSocket/caServerIO.cc +++ b/src/cas/io/bsdSocket/caServerIO.cc @@ -17,10 +17,13 @@ #include #include "epicsSignal.h" +#include "envDefs.h" +#include "caProto.h" -#include "server.h" +#define epicsExportSharedSymbols +#include "caServerIO.h" -static char *getToken (const char **ppString, char *pBuf, unsigned bufSIze); +static char * getToken ( const char **ppString, char *pBuf, unsigned bufSIze ); int caServerIO::staticInitialized; @@ -33,7 +36,7 @@ caServerIO::caServerIO () throw S_cas_internal; } - caServerIO::staticInit(); + caServerIO::staticInit (); } // @@ -55,22 +58,22 @@ void caServerIO::locateInterfaces () // clients to find the server). If this also isnt available // then use a hard coded default - CA_SERVER_PORT. // - if (envGetConfigParamPtr(&EPICS_CAS_SERVER_PORT)) { + if ( envGetConfigParamPtr ( & EPICS_CAS_SERVER_PORT ) ) { port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, - static_cast (CA_SERVER_PORT)); + static_cast ( CA_SERVER_PORT ) ); } else { port = envGetInetPortConfigParam ( - &EPICS_CA_SERVER_PORT, - static_cast (CA_SERVER_PORT)); + & EPICS_CA_SERVER_PORT, + static_cast ( CA_SERVER_PORT ) ); } memset ((char *)&saddr,0,sizeof(saddr)); - pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf); + pStr = envGetConfigParam ( &EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf ); if ( ! pStr ) { - pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf); + pStr = envGetConfigParam ( &EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf ); } if (pStr) { if (strstr(pStr,"no")||strstr(pStr,"NO")) { @@ -93,11 +96,11 @@ void caServerIO::locateInterfaces () // bind to the the interfaces specified - otherwise wildcard // with INADDR_ANY and allow clients to attach from any interface // - pStr = envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST); + pStr = envGetConfigParamPtr ( & EPICS_CAS_INTF_ADDR_LIST ); if (pStr) { bool configAddrOnceFlag = true; stat = S_cas_noInterface; - while ( (pToken = getToken(&pStr, buf, sizeof(buf))) ) { + while ( (pToken = getToken ( & pStr, buf, sizeof ( buf ) ) ) ) { int status; status = aToIPAddr (pToken, port, &saddr); diff --git a/src/cas/io/bsdSocket/casDGIntfIO.cc b/src/cas/io/bsdSocket/casDGIntfIO.cc index 67b8059ac..11f1144af 100644 --- a/src/cas/io/bsdSocket/casDGIntfIO.cc +++ b/src/cas/io/bsdSocket/casDGIntfIO.cc @@ -13,19 +13,16 @@ * (505) 665 1831 */ -// // // Should I fetch the MTU from the outgoing interface? // -// -#include "server.h" #include "addrList.h" -#include "casIODIL.h" -/* - * forcePort () - */ +#define epicsExportSharedSymbols +#include "casDGIntfIO.h" +#include "ipIgnoreEntry.h" + static void forcePort (ELLLIST *pList, unsigned short port) { osiSockAddrNode *pNode; @@ -40,9 +37,6 @@ static void forcePort (ELLLIST *pList, unsigned short port) } -// -// casDGIntfIO::casDGIntfIO() -// casDGIntfIO::casDGIntfIO ( caServerI & serverIn, clientBufMemoryManager & memMgr, const caNetAddr & addr, bool autoBeaconAddr, bool addConfigBeaconAddr ) : casDGClient ( serverIn, memMgr ) @@ -276,9 +270,6 @@ casDGIntfIO::~casDGIntfIO() osiSockRelease (); } -// -// casDGIntfIO::show() -// void casDGIntfIO::show (unsigned level) const { printf ( "casDGIntfIO at %p\n", @@ -287,9 +278,6 @@ void casDGIntfIO::show (unsigned level) const this->casDGClient::show (level); } -// -// casDGIntfIO::xSetNonBlocking() -// void casDGIntfIO::xSetNonBlocking() { int status; @@ -302,9 +290,6 @@ void casDGIntfIO::xSetNonBlocking() } } -// -// casDGIntfIO::osdRecv() -// inBufClient::fillCondition casDGIntfIO::osdRecv ( char * pBufIn, bufSizeT size, // X aCC 361 fillParameter parm, bufSizeT & actualSize, caNetAddr & fromOut ) @@ -352,9 +337,6 @@ casDGIntfIO::osdRecv ( char * pBufIn, bufSizeT size, // X aCC 361 } } -// -// casDGIntfIO::osdSend() -// outBufClient::flushCondition casDGIntfIO::osdSend ( const char * pBufIn, bufSizeT size, // X aCC 361 const caNetAddr & to ) @@ -384,9 +366,6 @@ casDGIntfIO::osdSend ( const char * pBufIn, bufSizeT size, // X aCC 361 } } -// -// casDGIntfIO::incomingBytesPresent() -// bufSizeT casDGIntfIO::incomingBytesPresent () const // X aCC 361 { int status; @@ -407,9 +386,6 @@ bufSizeT casDGIntfIO::incomingBytesPresent () const // X aCC 361 } } -// -// casDGIntfIO::sendBeaconIO() -// void casDGIntfIO::sendBeaconIO ( char & msg, unsigned length, aitUint16 & portField, aitUint32 & addrField ) { @@ -455,9 +431,6 @@ void casDGIntfIO::sendBeaconIO ( char & msg, unsigned length, } } -// -// casDGIntfIO::optimumInBufferSize() -// bufSizeT casDGIntfIO::optimumInBufferSize () { @@ -491,9 +464,6 @@ bufSizeT casDGIntfIO::optimumInBufferSize () #endif } -// -// casDGIntfIO::optimumOutBufferSize() -// bufSizeT casDGIntfIO::optimumOutBufferSize () { @@ -528,10 +498,6 @@ bufSizeT casDGIntfIO::optimumOutBufferSize () #endif } - -// -// casDGIntfIO::makeSockDG () -// SOCKET casDGIntfIO::makeSockDG () { int yes = true; @@ -611,10 +577,6 @@ SOCKET casDGIntfIO::makeSockDG () return newSock; } -// -// casDGIntfIO::getFD() -// (avoid problems with the GNU inliner) -// int casDGIntfIO::getFD() const { return this->sock; diff --git a/src/cas/io/bsdSocket/casIOD.h b/src/cas/io/bsdSocket/casIOD.h index 79b813f6d..319509eca 100644 --- a/src/cas/io/bsdSocket/casIOD.h +++ b/src/cas/io/bsdSocket/casIOD.h @@ -10,10 +10,6 @@ // // $Id$ // -// casIOD.h - Channel Access Server BSD socket dependent wrapper -// -// -// #ifndef includeCASIODH #define includeCASIODH @@ -35,178 +31,9 @@ # include "shareLib.h" #endif -void hostNameFromIPAddr ( const class caNetAddr * pAddr, - char * pBuf, unsigned bufSize ); - -class ipIgnoreEntry : public tsSLNode < ipIgnoreEntry > { -public: - ipIgnoreEntry ( unsigned ipAddr ); - void show ( unsigned level ) const; - bool operator == ( const ipIgnoreEntry & ) const; - resTableIndex hash () const; - void * operator new ( size_t size, - tsFreeList < class ipIgnoreEntry, 128 > & ); - epicsPlacementDeleteOperator (( void *, - tsFreeList < class ipIgnoreEntry, 128 > & )) -private: - unsigned ipAddr; - ipIgnoreEntry ( const ipIgnoreEntry & ); - ipIgnoreEntry & operator = ( const ipIgnoreEntry & ); - void * operator new ( size_t size ); - void operator delete ( void * ); -}; - -// -// casDGIntfIO -// -class casDGIntfIO : public casDGClient { -public: - casDGIntfIO ( caServerI & serverIn, clientBufMemoryManager &, - const caNetAddr & addr, bool autoBeaconAddr = true, - bool addConfigBeaconAddr = false ); - virtual ~casDGIntfIO(); - - int getFD () const; - int getBCastFD () const; - bool validBCastFD () const; - - void xSetNonBlocking (); - void sendBeaconIO ( char & msg, bufSizeT length, - aitUint16 &portField, aitUint32 & addrField ); - casIOState state () const; - - outBufClient::flushCondition osdSend ( const char * pBuf, bufSizeT nBytesReq, - const caNetAddr & addr); - inBufClient::fillCondition osdRecv ( char * pBuf, bufSizeT nBytesReq, - inBufClient::fillParameter parm, bufSizeT & nBytesActual, caNetAddr & addr ); - virtual void show ( unsigned level ) const; - - static bufSizeT optimumOutBufferSize (); - static bufSizeT optimumInBufferSize (); - - bufSizeT incomingBytesPresent () const; - -private: - tsFreeList < class ipIgnoreEntry, 128 > ipIgnoreEntryFreeList; - resTable < ipIgnoreEntry, ipIgnoreEntry > ignoreTable; - ELLLIST beaconAddrList; - SOCKET sock; - SOCKET bcastRecvSock; // fix for solaris bug - SOCKET beaconSock; // allow connect - unsigned short dgPort; - - static SOCKET makeSockDG (); - casDGIntfIO ( const casDGIntfIO & ); - casDGIntfIO & operator = ( const casDGIntfIO & ); -}; - -struct ioArgsToNewStreamIO { - caNetAddr addr; - SOCKET sock; -}; - -// -// casStreamIO -// -class casStreamIO : public casStrmClient { -public: - casStreamIO ( caServerI &, clientBufMemoryManager &, - const ioArgsToNewStreamIO & ); - ~casStreamIO (); - - int getFD () const; - void xSetNonBlocking (); - - casIOState state () const; - void hostName ( char *pBuf, unsigned bufSize ) const; - - outBufClient::flushCondition osdSend ( const char *pBuf, bufSizeT nBytesReq, - bufSizeT & nBytesActual ); - inBufClient::fillCondition osdRecv ( char *pBuf, bufSizeT nBytesReq, - bufSizeT & nBytesActual ); - - xBlockingStatus blockingState() const; - - bufSizeT incomingBytesPresent() const; - - static bufSizeT optimumBufferSize (); - - void osdShow ( unsigned level ) const; - - const caNetAddr getAddr() const - { - return caNetAddr ( this->addr ); - } - -private: - SOCKET sock; - struct sockaddr_in addr; - xBlockingStatus blockingFlag; - casStreamIO ( const casStreamIO & ); - casStreamIO & operator = ( const casStreamIO & ); -}; - class caServerIO; -class casDGClient; - class casStreamOS; -// -// casIntfIO -// -class casIntfIO { -public: - casIntfIO (const caNetAddr &addr); - virtual ~casIntfIO(); - void show(unsigned level) const; - - int getFD() const; - - void setNonBlocking(); - - // - // called when we expect that a virtual circuit for a - // client can be created - // - casStreamOS * newStreamClient ( caServerI & cas, - clientBufMemoryManager & ) const; - - caNetAddr serverAddress () const; - -private: - SOCKET sock; - struct sockaddr_in addr; -}; - -// -// caServerIO -// -class caServerIO { -public: - caServerIO (); - virtual ~caServerIO(); - - // - // show status of IO subsystem - // - void show (unsigned level) const; - - void locateInterfaces (); - -private: - - // - // static member data - // - static int staticInitialized; - // - // static member func - // - static inline void staticInit(); - - virtual caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr, - bool addConfigAddr) = 0; -}; // no additions below this line #endif // includeCASIODH diff --git a/src/cas/io/bsdSocket/casIODIL.h b/src/cas/io/bsdSocket/casIODIL.h deleted file mode 100644 index 4f115cc57..000000000 --- a/src/cas/io/bsdSocket/casIODIL.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -#ifndef casIODILh -#define casIODILh - -// -// casDGIntfIO::getBCastFD() -// -inline int casDGIntfIO::getBCastFD() const -{ - return this->bcastRecvSock; -} - -// -// casDGIntfIO::getBCastFD() -// -inline bool casDGIntfIO::validBCastFD() const -{ - return this->bcastRecvSock != INVALID_SOCKET; -} - -#endif // casIODILh - diff --git a/src/cas/io/bsdSocket/casIntfIO.cc b/src/cas/io/bsdSocket/casIntfIO.cc index 76df0a198..2e54259ae 100644 --- a/src/cas/io/bsdSocket/casIntfIO.cc +++ b/src/cas/io/bsdSocket/casIntfIO.cc @@ -13,9 +13,18 @@ // Author Jeff Hill // +#include -#include "server.h" +#include "errlog.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" +#include "epicsAssert.h" +#define epicsExportSharedSymbols +#include "casdef.h" +#include "caNetAddr.h" +#include "casIntfIO.h" +#include "casStreamIO.h" +#include "casStreamOS.h" // // 5 appears to be a TCP/IP built in maximum @@ -25,9 +34,9 @@ const unsigned caServerConnectPendQueueSize = 5u; // // casIntfIO::casIntfIO() // -casIntfIO::casIntfIO (const caNetAddr &addrIn) : - sock (INVALID_SOCKET), - addr (addrIn.getSockIP()) +casIntfIO::casIntfIO ( const caNetAddr & addrIn ) : + sock ( INVALID_SOCKET ), + addr ( addrIn.getSockIP() ) { int status; osiSocklen_t addrSize; @@ -160,7 +169,7 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas, struct sockaddr newAddr; SOCKET newSock; osiSocklen_t length; - casStreamOS *pOS; + casStreamOS * pOS; length = ( osiSocklen_t ) sizeof ( newAddr ); newSock = accept ( this->sock, & newAddr, & length ); @@ -192,7 +201,7 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas, if ( cas.getDebugLevel() > 0u ) { char pName[64u]; - pOS->hostName ( pName, sizeof (pName) ); + pOS->hostName ( pName, sizeof ( pName ) ); errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName ); } } diff --git a/src/cas/io/bsdSocket/casStreamIO.cc b/src/cas/io/bsdSocket/casStreamIO.cc index 02017cd4d..a58700cc2 100644 --- a/src/cas/io/bsdSocket/casStreamIO.cc +++ b/src/cas/io/bsdSocket/casStreamIO.cc @@ -11,7 +11,8 @@ // $Id$ // -#include "server.h" +#define epicsExportSharedSymbols +#include "casStreamIO.h" // // casStreamIO::casStreamIO() @@ -290,14 +291,10 @@ bufSizeT casStreamIO::optimumBufferSize () int status; /* fetch the TCP send buffer size */ - n = sizeof(size); - status = getsockopt( - this->sock, - SOL_SOCKET, - SO_SNDBUF, - (char *)&size, - &n); - if(status < 0 || n != sizeof(size)){ + n = sizeof ( size) ; + status = getsockopt ( this->sock, SOL_SOCKET, + SO_SNDBUF, (char *) & size, & n ); + if ( status < 0 || n != sizeof ( size ) ) { size = 0x400; } diff --git a/src/cas/io/bsdSocket/ipIgnoreEntry.cpp b/src/cas/io/bsdSocket/ipIgnoreEntry.cpp index 135ca6be8..f16167ce0 100644 --- a/src/cas/io/bsdSocket/ipIgnoreEntry.cpp +++ b/src/cas/io/bsdSocket/ipIgnoreEntry.cpp @@ -17,8 +17,11 @@ #include +#include "osiSock.h" + +#define epicsExportSharedSymbols #define caNetAddrSock -#include "server.h" +#include "ipIgnoreEntry.h" void ipIgnoreEntry::show ( unsigned /* level */ ) const { @@ -57,7 +60,7 @@ void * ipIgnoreEntry::operator new ( size_t size, #ifdef CXX_PLACEMENT_DELETE void ipIgnoreEntry::operator delete ( void * pCadaver, - tsFreeList < class ipIgnoreEntry, 128 > & freeList ) epicsThrows(()) + tsFreeList < class ipIgnoreEntry, 128 > & freeList ) { freeList.release ( pCadaver ); } diff --git a/src/cas/os/vms/mitfp.c b/src/cas/os/vms/mitfp.c index ff08ed832..0cbce11f4 100644 --- a/src/cas/os/vms/mitfp.c +++ b/src/cas/os/vms/mitfp.c @@ -16,10 +16,6 @@ * * */ - -#include - - /************************************************************************/ /* float convert */