diff --git a/src/ioc/db/dbCAC.h b/src/ioc/db/dbCAC.h index ad3d0287b..82b20b619 100644 --- a/src/ioc/db/dbCAC.h +++ b/src/ioc/db/dbCAC.h @@ -201,6 +201,7 @@ private: cacContextNotify & notify; epics_auto_ptr < cacContext > pNetContext; char * pStateNotifyCache; + bool isolated; cacChannel & createChannel ( epicsGuard < epicsMutex > &, diff --git a/src/ioc/db/dbCa.c b/src/ioc/db/dbCa.c index 984b59f13..029037f0e 100644 --- a/src/ioc/db/dbCa.c +++ b/src/ioc/db/dbCa.c @@ -52,8 +52,11 @@ #include "link.h" #include "recSup.h" +/* defined in dbContext.cpp + * Setup local CA access + */ extern void dbServiceIOInit(); - +extern int dbServiceIsolate; static ELLLIST workList = ELLLIST_INIT; /* Work list for dbCaTask */ static epicsMutexId workListLock; /*Mutual exclusions semaphores for workList*/ @@ -224,25 +227,16 @@ void dbCaShutdown(void) } } -static void dbCaExit(void *arg) +static void dbCaLinkInitImpl(int isolate) { - dbCaShutdown(); -} + dbServiceIsolate = isolate; + dbServiceIOInit(); -void dbCaLinkInitIsolated(void) -{ if (!workListLock) workListLock = epicsMutexMustCreate(); if (!workListEvent) workListEvent = epicsEventMustCreate(epicsEventEmpty); - dbCaCtl = ctlExit; - epicsAtExit(dbCaExit, NULL); -} -void dbCaLinkInit(void) -{ - dbServiceIOInit(); - dbCaLinkInitIsolated(); startStopEvent = epicsEventMustCreate(epicsEventEmpty); dbCaCtl = ctlPause; @@ -252,6 +246,16 @@ void dbCaLinkInit(void) epicsEventMustWait(startStopEvent); } +void dbCaLinkInitIsolated(void) +{ + dbCaLinkInitImpl(1); +} + +void dbCaLinkInit(void) +{ + dbCaLinkInitImpl(0); +} + void dbCaRun(void) { if (dbCaCtl == ctlPause) { diff --git a/src/ioc/db/dbChannelNOOP.h b/src/ioc/db/dbChannelNOOP.h new file mode 100644 index 000000000..d48540d88 --- /dev/null +++ b/src/ioc/db/dbChannelNOOP.h @@ -0,0 +1,118 @@ +#ifndef DBCHANNELNOOP_H +#define DBCHANNELNOOP_H + +#include +#include + +#include "cacIO.h" +#include "caerr.h" + +/** @brief A channel which never connects + * + * Used when dbCa is placed in isolated mode for unittests + */ +class dbChannelNOOP : public cacChannel +{ + std::string myname; +public: + dbChannelNOOP(const char *name, cacChannelNotify ¬ify) + :cacChannel(notify) + ,myname(name) + {} + + virtual void destroy ( + CallbackGuard & /*callbackGuard*/, + epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ ) + { + delete this; // goodbye cruel world + } + + virtual unsigned getName ( + epicsGuard < epicsMutex > &, + char * pBuf, unsigned bufLen ) const throw () + { + const char* name = myname.c_str(); + if(bufLen>myname.size()+1) { + bufLen=myname.size()+1; + } + memcpy(pBuf, name, bufLen); + pBuf[--bufLen] = '\0'; + return bufLen; + } + + // !! deprecated, avoid use !! + virtual const char * pName ( + epicsGuard < epicsMutex > & guard ) const throw () + {return myname.c_str();} + + virtual void show ( + epicsGuard < epicsMutex > &, + unsigned level ) const + {} + + virtual void initiateConnect ( + epicsGuard < epicsMutex > & ) + {} + + virtual unsigned requestMessageBytesPending ( + epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ ) + {return 0;} + + virtual void flush ( + epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ ) + {} + + virtual ioStatus read ( + epicsGuard < epicsMutex > &mut, + unsigned type, arrayElementCount count, + cacReadNotify ¬ify, ioid * = 0 ) + { + notify.exception(mut, ECA_NORDACCESS, "dbChannelNOOP", type, count); + return iosSynch; + } + + virtual void write ( + epicsGuard < epicsMutex > &, + unsigned type, arrayElementCount count, + const void *pValue ) + {} + + virtual ioStatus write ( + epicsGuard < epicsMutex > &mut, + unsigned type, arrayElementCount count, + const void */*pValue*/, cacWriteNotify & notify, ioid * = 0 ) + { + notify.exception(mut, ECA_NOWTACCESS, "dbChannelNOOP", type, count); + return iosSynch; + } + + virtual void subscribe ( + epicsGuard < epicsMutex > &mut, unsigned type, + arrayElementCount count, unsigned /*mask*/, cacStateNotify & notify, + ioid * = 0 ) + { + // should never subscribe + notify.exception(mut, ECA_BADMASK, "dbChannelNOOP", type, count); + } + + virtual void ioCancel ( + CallbackGuard & callbackGuard, + epicsGuard < epicsMutex > & mutualExclusionGuard, + const ioid & ) + {} + + virtual void ioShow ( + epicsGuard < epicsMutex > &, + const ioid &, unsigned level ) const + {} + + virtual short nativeType ( + epicsGuard < epicsMutex > & ) const + {return 0;} // DBR_STRING + + virtual arrayElementCount nativeElementCount ( + epicsGuard < epicsMutex > & ) const + {return 1;} +}; + +#endif // DBCHANNELNOOP_H diff --git a/src/ioc/db/dbContext.cpp b/src/ioc/db/dbContext.cpp index d005f084a..124a836cf 100644 --- a/src/ioc/db/dbContext.cpp +++ b/src/ioc/db/dbContext.cpp @@ -39,6 +39,7 @@ #include "dbCAC.h" #include "dbChannel.h" #include "dbChannelIO.h" +#include "dbChannelNOOP.h" #include "dbPutNotifyBlocker.h" class dbService : public cacService { @@ -61,9 +62,16 @@ cacContext & dbService::contextCreate ( mutualExclusion, notify ); } +extern "C" int dbServiceIsolate; +int dbServiceIsolate = 0; + extern "C" void dbServiceIOInit () { - caInstallDefaultService ( dbs ); + static int init=0; + if(!init) { + caInstallDefaultService ( dbs ); + init=1; + } } dbBaseIO::dbBaseIO () {} @@ -72,7 +80,8 @@ dbContext::dbContext ( epicsMutex & cbMutexIn, epicsMutex & mutexIn, cacContextNotify & notifyIn ) : readNotifyCache ( mutexIn ), ctx ( 0 ), stateNotifyCacheSize ( 0 ), mutex ( mutexIn ), cbMutex ( cbMutexIn ), - notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 ) + notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 ), + isolated(dbServiceIsolate) { } @@ -92,7 +101,10 @@ cacChannel & dbContext::createChannel ( dbChannel *dbch = dbChannel_create ( pName ); if ( ! dbch ) { - if ( ! this->pNetContext.get() ) { + if ( isolated ) { + return *new dbChannelNOOP(pName, notifyIn); + + } else if ( ! this->pNetContext.get() ) { this->pNetContext.reset ( & this->notify.createNetworkContext ( this->mutex, this->cbMutex ) ); diff --git a/src/ioc/misc/iocInit.c b/src/ioc/misc/iocInit.c index a66de064a..508f0312d 100644 --- a/src/ioc/misc/iocInit.c +++ b/src/ioc/misc/iocInit.c @@ -693,6 +693,7 @@ int iocShutdown(void) dbProcessNotifyExit(); iocshFree(); } + dbCaShutdown(); iocState = iocStopped; iocBuildMode = buildRSRV; return 0;