From 33d29a458daa6389eeabc710221543e837faca34 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Thu, 2 Sep 1999 21:50:29 +0000 Subject: [PATCH] o changed UDP to non-blocking IO o cleaned up (consolodated) UDP interface class structure --- src/cas/RELEASE_NOTES | 9 + src/cas/build/singleThread/Makefile.Host | 10 +- src/cas/example/directoryService/main.cc | 2 +- src/cas/example/simple/exChannel.cc | 8 +- src/cas/example/simple/exPV.cc | 4 +- src/cas/example/simple/exServer.cc | 16 +- src/cas/example/simple/exServer.h | 36 +- src/cas/example/simple/main.cc | 30 +- src/cas/generic/caNetAddr.h | 99 ++- src/cas/generic/caServer.cc | 134 ++-- src/cas/generic/caServerI.cc | 291 ++++--- src/cas/generic/caServerIIL.h | 35 +- src/cas/generic/casAsyncIO.cc | 62 -- src/cas/generic/casAsyncIOI.cc | 114 ++- src/cas/generic/casAsyncIOIIL.h | 34 +- src/cas/generic/casAsyncPVAttachIO.cc | 111 +++ ...{casAsyncExIOI.cc => casAsyncPVExistIO.cc} | 58 +- .../{casAsyncRdIOI.cc => casAsyncReadIO.cc} | 72 +- .../{casAsyncWtIOI.cc => casAsyncWriteIO.cc} | 87 +-- src/cas/generic/casAsyncXXIO.cc | 100 --- src/cas/generic/casChanDelEv.cc | 5 +- src/cas/generic/casChannel.cc | 37 +- src/cas/generic/casChannelI.cc | 145 ++-- src/cas/generic/casChannelIIL.h | 22 +- src/cas/generic/casClient.cc | 121 ++- src/cas/generic/casCoreClient.cc | 40 +- src/cas/generic/casCoreClientIL.h | 21 +- src/cas/generic/casDGClient.cc | 723 ++++++++--------- src/cas/generic/casEventMask.cc | 12 +- src/cas/generic/casEventMask.h | 94 +-- src/cas/generic/casEventSys.cc | 39 +- src/cas/generic/casEventSysIL.h | 57 +- src/cas/generic/casInternal.h | 437 ++++------- src/cas/generic/casMonitor.cc | 51 +- src/cas/generic/casMsgIO.cc | 206 ----- src/cas/generic/casPV.cc | 85 +- src/cas/generic/casPVI.cc | 116 +-- src/cas/generic/casPVIIL.h | 85 +- src/cas/generic/casPVListChan.cc | 15 +- src/cas/generic/casStrmClient.cc | 542 +++++-------- src/cas/generic/casdef.h | 318 ++++---- src/cas/generic/dgInBuf.cc | 55 -- src/cas/generic/dgInBufIL.h | 9 - src/cas/generic/dgOutBuf.cc | 69 -- src/cas/generic/dgOutBufIL.h | 13 - src/cas/generic/inBuf.cc | 147 ++-- src/cas/generic/inBufIL.h | 64 +- src/cas/generic/outBuf.cc | 290 +++---- src/cas/generic/outBufIL.h | 79 +- src/cas/generic/server.h | 522 +++++++------ src/cas/generic/st/caServerOS.cc | 77 +- src/cas/generic/st/casDGIntfOS.cc | 514 ++++++++++++- src/cas/generic/st/casDGOS.cc | 31 +- src/cas/generic/st/casIntfOS.cc | 69 +- src/cas/generic/st/casOSD.h | 135 ++-- src/cas/generic/st/casStreamOS.cc | 110 +-- src/cas/generic/st/ioBlocked.cc | 13 +- src/cas/io/bsdSocket/caServerIO.cc | 267 +++---- src/cas/io/bsdSocket/casDGIO.cc | 21 - src/cas/io/bsdSocket/casDGIntfIO.cc | 724 +++++++++--------- src/cas/io/bsdSocket/casIOD.h | 98 +-- src/cas/io/bsdSocket/casIODIL.h | 34 +- src/cas/io/bsdSocket/casIntfIO.cc | 189 ++--- src/cas/io/bsdSocket/casStreamIO.cc | 209 ++--- src/cas/os/vxWorks/casOSD.h | 87 +-- src/cas/os/vxWorks/casStreamOS.cc | 43 +- 66 files changed, 3771 insertions(+), 4581 deletions(-) delete mode 100644 src/cas/generic/casAsyncIO.cc create mode 100644 src/cas/generic/casAsyncPVAttachIO.cc rename src/cas/generic/{casAsyncExIOI.cc => casAsyncPVExistIO.cc} (59%) rename src/cas/generic/{casAsyncRdIOI.cc => casAsyncReadIO.cc} (60%) rename src/cas/generic/{casAsyncWtIOI.cc => casAsyncWriteIO.cc} (56%) delete mode 100644 src/cas/generic/casAsyncXXIO.cc delete mode 100644 src/cas/generic/casMsgIO.cc delete mode 100644 src/cas/generic/dgOutBuf.cc delete mode 100644 src/cas/generic/dgOutBufIL.h diff --git a/src/cas/RELEASE_NOTES b/src/cas/RELEASE_NOTES index da22905a8..7037312b1 100644 --- a/src/cas/RELEASE_NOTES +++ b/src/cas/RELEASE_NOTES @@ -242,3 +242,12 @@ implemented ANSI STD C++ "bool" type. o In class osiTimer type double, and not type osiTime, is returned from virtual member function delay(). +o The public const event mask member data in the caServer class were changed to member +functions in order to avoid problems on some compiler where const event masks cant be +created until the server is fully constructed. The constants have been replaced by the +following member functions. + casEventMask valueEventMask() const; // DBE_VALUE registerEvent("value") + casEventMask logEventMask() const; // DBE_LOG registerEvent("log") + casEventMask alarmEventMask() const; // DBE_ALARM registerEvent("alarm") + + diff --git a/src/cas/build/singleThread/Makefile.Host b/src/cas/build/singleThread/Makefile.Host index a25a03add..1d93f3c62 100644 --- a/src/cas/build/singleThread/Makefile.Host +++ b/src/cas/build/singleThread/Makefile.Host @@ -27,13 +27,11 @@ LIBSRCS += casChannelI.cc LIBSRCS += casPVListChan.cc LIBSRCS += casClientMon.cc LIBSRCS += casChanDelEv.cc -LIBSRCS += casAsyncIO.cc LIBSRCS += casAsyncIOI.cc -LIBSRCS += casAsyncXXIO.cc -LIBSRCS += casAsyncRdIOI.cc -LIBSRCS += casAsyncWtIOI.cc -LIBSRCS += casAsyncExIOI.cc -LIBSRCS += casAsyncAtIOI.cc +LIBSRCS += casAsyncReadIO.cc +LIBSRCS += casAsyncWriteIO.cc +LIBSRCS += casAsyncPVExistIO.cc +LIBSRCS += casAsyncPVAttachIO.cc LIBSRCS += casEventSys.cc LIBSRCS += casMonitor.cc LIBSRCS += casMonEvent.cc diff --git a/src/cas/example/directoryService/main.cc b/src/cas/example/directoryService/main.cc index abb3b8f60..f8688b5b6 100644 --- a/src/cas/example/directoryService/main.cc +++ b/src/cas/example/directoryService/main.cc @@ -31,7 +31,7 @@ extern int main (int argc, const char **argv) char pvPrefix[128] = ""; char fileName[128] = "pvDirectory.txt"; unsigned aliasCount = 0u; - aitBool forever = aitTrue; + bool forever = true; int nPV; int i; diff --git a/src/cas/example/simple/exChannel.cc b/src/cas/example/simple/exChannel.cc index 4ea6c2a39..0a6300d6d 100644 --- a/src/cas/example/simple/exChannel.cc +++ b/src/cas/example/simple/exChannel.cc @@ -16,17 +16,17 @@ void exChannel::setOwner(const char * const /* pUserName */, // // exChannel::readAccess () // -aitBool exChannel::readAccess () const +bool exChannel::readAccess () const { - return aitTrue; + return true; } // // exChannel::writeAccess () // -aitBool exChannel::writeAccess () const +bool exChannel::writeAccess () const { - return aitTrue; + return true; } diff --git a/src/cas/example/simple/exPV.cc b/src/cas/example/simple/exPV.cc index f1f5deee0..b3ce6d824 100644 --- a/src/cas/example/simple/exPV.cc +++ b/src/cas/example/simple/exPV.cc @@ -21,7 +21,7 @@ class exFixedStringDestructor: public gddDestructor { // // exPV::exPV() // -exPV::exPV (pvInfo &setup, aitBool preCreateFlag, aitBool scanOnIn) : +exPV::exPV (pvInfo &setup, bool preCreateFlag, bool scanOnIn) : info (setup), interest (aitFalse), preCreate (preCreateFlag), @@ -95,7 +95,7 @@ caStatus exPV::update(gdd &valueIn) // post a value change event // if (this->interest==aitTrue && pCAS!=NULL) { - casEventMask select(pCAS->valueEventMask|pCAS->logEventMask); + casEventMask select(pCAS->valueEventMask()|pCAS->logEventMask()); this->postEvent (select, *this->pValue); } diff --git a/src/cas/example/simple/exServer.cc b/src/cas/example/simple/exServer.cc index 159e4a815..c4c6b9702 100644 --- a/src/cas/example/simple/exServer.cc +++ b/src/cas/example/simple/exServer.cc @@ -35,6 +35,9 @@ pvInfo exServer::pvList[] = { pvInfo (2.0, "alan", 10.0f, -10.0f, excasIoSync, 100u), pvInfo (20.0, "albert", 10.0f, -10.0f, excasIoSync, 1000u) }; + +const unsigned exServer::pvListNElem = NELEMENTS (exServer::pvList); + // // static on-the-fly PVs // @@ -44,17 +47,16 @@ pvInfo exServer::billy (2.0, "billy", 10.0f, -10.0f, excasIoAsync, 1u); // // exServer::exServer() // -exServer::exServer(const char * const pvPrefix, unsigned aliasCount, aitBool scanOnIn) : - caServer (NELEMENTS(this->pvList)+2u), - stringResTbl (NELEMENTS(this->pvList)*(aliasCount+1u)+2u), +exServer::exServer(const char * const pvPrefix, unsigned aliasCount, bool scanOnIn) : + caServer (pvListNElem+2u), + stringResTbl (pvListNElem*(aliasCount+1u)+2u), simultAsychIOCount (0u), scanOn (scanOnIn) { unsigned i; exPV *pPV; pvInfo *pPVI; - pvInfo *pPVAfter = - &exServer::pvList[NELEMENTS(exServer::pvList)]; + pvInfo *pPVAfter = &exServer::pvList[pvListNElem]; char pvAlias[256]; const char * const pNameFmtStr = "%.100s%.20s"; const char * const pAliasFmtStr = "%.100s%.20s%u"; @@ -240,13 +242,13 @@ pvAttachReturn exServer::pvAttach // // pvInfo::createPV() // -exPV *pvInfo::createPV (exServer &, aitBool preCreateFlag, aitBool scanOn) +exPV *pvInfo::createPV (exServer &, bool preCreateFlag, bool scanOn) { if (this->pPV) { return this->pPV; } - exPV *pNewPV; + exPV *pNewPV; // // create an instance of the appropriate class diff --git a/src/cas/example/simple/exServer.h b/src/cas/example/simple/exServer.h index 2e2538cbb..a2bb2777b 100644 --- a/src/cas/example/simple/exServer.h +++ b/src/cas/example/simple/exServer.h @@ -87,7 +87,7 @@ public: { return this->elementCount; } void unlinkPV() { this->pPV=NULL; } - exPV *createPV (exServer &exCAS, aitBool preCreateFlag, aitBool scanOn); + exPV *createPV (exServer &exCAS, bool preCreateFlag, bool scanOn); void deletePV (); private: @@ -155,7 +155,7 @@ class exPV : public casPV, public tsSLNode { // allow the exScanTimer destructor to set dangling pScanTimer pointer to NULL friend exScanTimer::~exScanTimer(); public: - exPV (pvInfo &setup, aitBool preCreateFlag, aitBool scanOn); + exPV (pvInfo &setup, bool preCreateFlag, bool scanOn); virtual ~exPV(); void show(unsigned level) const; @@ -241,12 +241,12 @@ public: const char * const pUserName, const char * const pHostName); protected: - smartGDDPointer pValue; - exScanTimer *pScanTimer; - pvInfo & info; - aitBool interest; - aitBool preCreate; - aitBool scanOn; + smartGDDPointer pValue; + exScanTimer *pScanTimer; + pvInfo & info; + bool interest; + bool preCreate; + bool scanOn; static osiTime currentTime; virtual caStatus updateValue (gdd &value) = 0; @@ -274,7 +274,7 @@ private: // class exScalarPV : public exPV { public: - exScalarPV (pvInfo &setup, aitBool preCreateFlag, aitBool scanOnIn) : + exScalarPV (pvInfo &setup, bool preCreateFlag, bool scanOnIn) : exPV (setup, preCreateFlag, scanOnIn) {} void scan(); private: @@ -286,7 +286,7 @@ private: // class exVectorPV : public exPV { public: - exVectorPV (pvInfo &setup, aitBool preCreateFlag, aitBool scanOnIn) : + exVectorPV (pvInfo &setup, bool preCreateFlag, bool scanOnIn) : exPV (setup, preCreateFlag, scanOnIn) {} void scan(); @@ -302,7 +302,7 @@ private: // class exServer : public caServer { public: - exServer(const char * const pvPrefix, unsigned aliasCount, aitBool scanOn); + exServer(const char * const pvPrefix, unsigned aliasCount, bool scanOn); ~exServer(); void show (unsigned level) const; @@ -328,12 +328,14 @@ public: private: resTable stringResTbl; unsigned simultAsychIOCount; - aitBool scanOn; + bool scanOn; // // list of pre-created PVs // static pvInfo pvList[]; + static const unsigned pvListNElem; + // // on-the-fly PVs @@ -350,7 +352,7 @@ public: // // exAsyncPV() // - exAsyncPV (pvInfo &setup, aitBool preCreateFlag, aitBool scanOnIn) : + exAsyncPV (pvInfo &setup, bool preCreateFlag, bool scanOnIn) : exScalarPV (setup, preCreateFlag, scanOnIn), simultAsychIOCount(0u) {} @@ -390,8 +392,8 @@ public: virtual void setOwner(const char * const pUserName, const char * const pHostName); - virtual aitBool readAccess () const; - virtual aitBool writeAccess () const; + virtual bool readAccess () const; + virtual bool writeAccess () const; private: }; @@ -535,7 +537,7 @@ public: // exAsyncCreateIO() // exAsyncCreateIO(pvInfo &pviIn, exServer &casIn, - const casCtx &ctxIn, aitBool scanOnIn) : + const casCtx &ctxIn, bool scanOnIn) : casAsyncPVAttachIO(ctxIn), exOSITimer(0.00001), pvi(pviIn), cas(casIn), scanOn(scanOnIn) {} @@ -555,7 +557,7 @@ public: private: pvInfo &pvi; exServer &cas; - aitBool scanOn; + bool scanOn; }; // diff --git a/src/cas/example/simple/main.cc b/src/cas/example/simple/main.cc index 5fbfa3162..dbc29f689 100644 --- a/src/cas/example/simple/main.cc +++ b/src/cas/example/simple/main.cc @@ -8,15 +8,16 @@ // extern int main (int argc, const char **argv) { - osiTime begin(osiTime::getCurrent()); - exServer *pCAS; - unsigned debugLevel = 0u; - double executionTime; - char pvPrefix[128] = ""; - unsigned aliasCount = 1u; - unsigned scanOn = 1u; - aitBool forever = aitTrue; - int i; + osiTime begin (osiTime::getCurrent()); + exServer *pCAS; + unsigned debugLevel = 0u; + double executionTime; + char pvPrefix[128] = ""; + unsigned aliasCount = 1u; + unsigned scanOnAsUnsignedInt = true; + bool scanOn; + bool forever = aitTrue; + int i; for (i=1; iclear(); } - inline int isSock () const + inline bool isInet () const { - return this->type == casnaSock; + return this->type == casnaInet; } + inline bool isValid () const + { + return this->type != casnaUDF; + } + + inline bool operator == (const caNetAddr &rhs) const + { + if (this->type != rhs.type) { + return false; + } +# ifdef caNetAddrSock + if (this->type==casnaInet) { + return (this->addr.ip.sin_addr.s_addr == rhs.addr.ip.sin_addr.s_addr) && + (this->addr.ip.sin_port == rhs.addr.ip.sin_port); + } +# endif + else { + return false; + } + } + + inline bool operator != (const caNetAddr &rhs) const + { + return ! this->operator == (rhs); + } + // // This is specified so that compilers will not use one of // the following assignment operators after converting to a @@ -67,6 +94,11 @@ public: return *this; } + // + // convert to the string equivalent of the address + // + void stringConvert (char *pString, unsigned stringLength) const; + // // conditionally drag BSD socket headers into the server // and server tool @@ -74,60 +106,59 @@ public: // to use this #define caNetAddrSock // # ifdef caNetAddrSock - inline void setSockIP(unsigned long inaIn, unsigned short portIn) + inline void setSockIP (unsigned long inaIn, unsigned short portIn) { - this->type = casnaSock; - this->addr.sock.sin_family = AF_INET; - this->addr.sock.sin_addr.s_addr = inaIn; - this->addr.sock.sin_port = portIn; + this->type = casnaInet; + this->addr.ip.sin_family = AF_INET; + this->addr.ip.sin_addr.s_addr = inaIn; + this->addr.ip.sin_port = portIn; } - inline void setSockIP(const struct sockaddr_in &sockIPIn) + inline void setSockIP (const struct sockaddr_in &sockIPIn) { - this->type = casnaSock; - assert(sockIPIn.sin_family == AF_INET); - this->addr.sock = sockIPIn; + this->type = casnaInet; + assert (sockIPIn.sin_family == AF_INET); + this->addr.ip = sockIPIn; } - inline void setSock(const struct sockaddr &sock) + inline void setSock (const struct sockaddr &sock) { - this->type = casnaSock; + assert (sock.sa_family == AF_INET); + this->type = casnaInet; const struct sockaddr_in *psip = (const struct sockaddr_in *) &sock; - assert(sizeof(sock)==sizeof(this->addr.sock)); - this->addr.sock = *psip; + this->addr.ip = *psip; } - inline caNetAddr(const struct sockaddr_in &sockIPIn) + inline caNetAddr (const struct sockaddr_in &sockIPIn) { - this->setSockIP(sockIPIn); + this->setSockIP (sockIPIn); } inline caNetAddr operator = (const struct sockaddr_in &sockIPIn) { - this->setSockIP(sockIPIn); + this->setSockIP (sockIPIn); return *this; } inline caNetAddr operator = (const struct sockaddr &sockIn) { - this->setSock(sockIn); + this->setSock (sockIn); return *this; } inline struct sockaddr_in getSockIP() const { - assert (this->type==casnaSock); - return this->addr.sock; + assert (this->type==casnaInet); + return this->addr.ip; } inline struct sockaddr getSock() const { struct sockaddr sa; - assert (this->type==casnaSock); - assert (sizeof(sa)==sizeof(this->addr.sock)); + assert (this->type==casnaInet); struct sockaddr_in *psain = (struct sockaddr_in *) &sa; - *psain = this->addr.sock; + *psain = this->addr.ip; return sa; } @@ -147,7 +178,7 @@ public: private: union { # ifdef caNetAddrSock - struct sockaddr_in sock; + struct sockaddr_in ip; # endif // // this must be as big or bigger @@ -174,5 +205,21 @@ inline void verifyCANetAddr::checkSize() assert (ds==as); } +// +// caNetAddr::stringConvert () +// +inline void caNetAddr::stringConvert (char *pString, unsigned stringLength) const +{ +# ifdef caNetAddrSock + if (this->type==casnaInet) { + ipAddrToA (&this->addr.ip, pString, stringLength); + return; + } +# endif + if (stringLength) { + strncpy (pString, "", stringLength); + pString[stringLength-1] = '\n'; + } +} #endif // caNetAddrH diff --git a/src/cas/generic/caServer.cc b/src/cas/generic/caServer.cc index 0c04b6999..074324fb1 100644 --- a/src/cas/generic/caServer.cc +++ b/src/cas/generic/caServer.cc @@ -26,49 +26,6 @@ * Advanced Photon Source * Argonne National Laboratory * - * -<<<<<<< caServer.cc -======= - * History - * $Log$ - * Revision 1.12 1999/08/07 00:55:35 jhill - * solaris compiler issues - * - * Revision 1.11 1999/08/04 23:05:29 jhill - * applied chronIntId name change - * - * Revision 1.10 1999/01/28 20:18:14 jhill - * removed implicit int - * - * Revision 1.9 1998/12/19 00:04:49 jhill - * renamed createPV() to pvAttach() - * - * Revision 1.8 1997/08/05 00:46:56 jhill - * fixed warnings - * - * Revision 1.7 1997/06/25 05:09:00 jhill - * removed templInst.cc - * - * Revision 1.6 1997/06/13 09:15:50 jhill - * connect proto changes - * - * Revision 1.5 1997/04/10 19:33:52 jhill - * API changes - * - * Revision 1.4 1996/11/02 00:53:53 jhill - * many improvements - * - * Revision 1.3 1996/09/16 18:23:56 jhill - * vxWorks port changes - * - * Revision 1.2 1996/06/21 02:30:52 jhill - * solaris port - * - * Revision 1.1.1.1 1996/06/20 00:28:14 jhill - * ca server installation - * - * ->>>>>>> 1.8 */ #include "dbMapper.h" // ait to dbr types @@ -96,29 +53,20 @@ // // caServer::caServer() // -epicsShareFunc caServer::caServer(unsigned pvCountEstimateIn) : - pCAS (new caServerI(*this, pvCountEstimateIn)), - valueEventMask(this->registerEvent("value")), - logEventMask(this->registerEvent("log")), - alarmEventMask(this->registerEvent("alarm")) +epicsShareFunc caServer::caServer (unsigned pvCountEstimateIn) { - static int init; + static bool init = false; + + if (!init) { + gddMakeMapDBR(gddApplicationTypeTable::app_table); + init = true; + } - if (!init) { - gddMakeMapDBR(gddApplicationTypeTable::app_table); - init = TRUE; - } - - if (!this->pCAS) { - errMessage(S_cas_noMemory, NULL); - return; - } - - if (!this->pCAS->ready()) { - delete this->pCAS; - this->pCAS = NULL; - return; - } + this->pCAS = new caServerI(*this, pvCountEstimateIn); + if (this->pCAS==NULL) { + errMessage (S_cas_noMemory, " - unable to create caServer"); + throw S_cas_noMemory; + } } // @@ -202,15 +150,57 @@ epicsShareFunc void caServer::setDebugLevel (unsigned level) // // caServer::getDebugLevel() // -epicsShareFunc unsigned caServer::getDebugLevel () +epicsShareFunc unsigned caServer::getDebugLevel () const { - if (pCAS) { - return this->pCAS->getDebugLevel(); - } - else { - printf("caServer:: no server internals attached\n"); - return 0u; - } + if (pCAS) { + return this->pCAS->getDebugLevel(); + } + else { + printf("caServer:: no server internals attached\n"); + return 0u; + } +} + +// +// caServer::valueEventMask () +// +epicsShareFunc casEventMask caServer::valueEventMask () const +{ + if (pCAS) { + return this->pCAS->valueEventMask(); + } + else { + printf("caServer:: no server internals attached\n"); + return casEventMask(); + } +} + +// +// caServer::logEventMask () +// +epicsShareFunc casEventMask caServer::logEventMask () const +{ + if (pCAS) { + return this->pCAS->logEventMask(); + } + else { + printf("caServer:: no server internals attached\n"); + return casEventMask(); + } +} + +// +// caServer::alarmEventMask () +// +epicsShareFunc casEventMask caServer::alarmEventMask () const +{ + if (pCAS) { + return this->pCAS->alarmEventMask(); + } + else { + printf("caServer:: no server internals attached\n"); + return casEventMask(); + } } // diff --git a/src/cas/generic/caServerI.cc b/src/cas/generic/caServerI.cc index 23b474572..e512aba30 100644 --- a/src/cas/generic/caServerI.cc +++ b/src/cas/generic/caServerI.cc @@ -45,77 +45,11 @@ static const double CAServerMaxBeaconPeriod = 15.0; // seconds // static const double CAServerMinBeaconPeriod = 1.0e-3; // seconds -// -// caServerI::show() -// -void caServerI::show (unsigned level) const -{ - int bytes_reserved; - - printf( "Channel Access Server Status V%d.%d\n", - CA_PROTOCOL_VERSION, CA_MINOR_VERSION); - - this->osiMutex::show(level); - - this->osiLock(); - tsDLIterBD iterCl(this->clientList.first()); - while ( iterCl!=tsDLIterBD::eol() ) { - iterCl->show(level); - ++iterCl; - } - this->dgClient.show(level); - - tsDLIterBD iterIF(this->intfList.first()); - while ( iterIF!=tsDLIterBD::eol() ) { - iterIF->show(level); - ++iterIF; - } - - this->osiUnlock(); - - bytes_reserved = 0u; -#if 0 - bytes_reserved += sizeof(casClient) * - ellCount(&this->freeClientQ); - bytes_reserved += sizeof(casChannel) * - ellCount(&this->freeChanQ); - bytes_reserved += sizeof(casEventBlock) * - ellCount(&this->freeEventQ); - bytes_reserved += sizeof(casAsyncIIO) * - ellCount(&this->freePendingIO); -#endif - if (level>=1) { - printf( - "There are currently %d bytes on the server's free list\n", - bytes_reserved); -#if 0 - printf( - "%d client(s), %d channel(s), %d event(s) (monitors), and %d IO blocks\n", - ellCount(&this->freeClientQ), - ellCount(&this->freeChanQ), - ellCount(&this->freeEventQ), - ellCount(&this->freePendingIO)); -#endif - printf( - "The server's integer resource id conversion table:\n"); - this->osiLock(); - this->chronIntIdResTable::show(level); - this->osiUnlock(); - } - - // @@@@@@ caPrintAddrList(&destAddr); - - return; -} - // // caServerI::caServerI() // caServerI::caServerI (caServer &tool, unsigned nPV) : - caServerOS (*this), chronIntIdResTable(nPV*2u), - casEventRegistry (* (osiMutex *) this), - dgClient (*this), // // Set up periodic beacon interval // (exponential back off to a plateau @@ -123,41 +57,19 @@ caServerI::caServerI (caServer &tool, unsigned nPV) : // beaconPeriod (CAServerMinBeaconPeriod), adapter (tool), - debugLevel (0u), - haveBeenInitialized (FALSE) + debugLevel (0u) { caStatus status; double maxPeriod; assert (&adapter != NULL); - - if (this->osiMutex::init ()) { - errMessage (S_cas_noMemory, "CA server mutex init"); - return; - } - - status = caServerIO::init (*this); - if (status) { - errMessage (status, "CA server IO internals init"); - return; - } - - if (this->intfList.count()==0u) { - errMessage (S_cas_noInterface, "CA server internals init"); - return; - } - - status = caServerOS::init(); - if (status) { - errMessage (status, "CA server OS dependent init"); - return; - } - - status = this->dgClient.init(); - if (status) { - errMessage (status, "CA server DG init"); - return; - } + + // + // create predefined event types + // + this->valueEvent = registerEvent ("value"); + this->logEvent = registerEvent ("log"); + this->alarmEvent = registerEvent ("alarm"); status = envGetDoubleConfigParam (&EPICS_CA_BEACON_PERIOD, &maxPeriod); if (status || maxPeriod<=0.0) { @@ -172,7 +84,13 @@ caServerI::caServerI (caServer &tool, unsigned nPV) : this->maxBeaconInterval = maxPeriod; } - this->haveBeenInitialized = TRUE; + this->locateInterfaces (); + + if (this->intfList.count()==0u) { + errMessage (S_cas_noInterface, "CA server internals init"); + return; + } + return; } @@ -182,7 +100,7 @@ caServerI::caServerI (caServer &tool, unsigned nPV) : caServerI::~caServerI() { - this->osiLock(); + this->lock(); // // delete all clients @@ -204,7 +122,7 @@ caServerI::~caServerI() delete pIF; } - this->osiUnlock(); + this->unlock(); } // @@ -212,40 +130,37 @@ caServerI::~caServerI() // void caServerI::installClient(casStrmClient *pClient) { - this->osiLock(); + this->lock(); this->clientList.add(*pClient); - this->osiUnlock(); + this->unlock(); } // // caServerI::removeClient() // -void caServerI::removeClient(casStrmClient *pClient) +void caServerI::removeClient (casStrmClient *pClient) { - this->osiLock(); - this->clientList.remove(*pClient); - this->osiUnlock(); + this->lock(); + this->clientList.remove (*pClient); + this->unlock(); } // // caServerI::connectCB() // -void caServerI::connectCB(casIntfOS &intf) +void caServerI::connectCB (casIntfOS &intf) { - casStreamOS *pNewClient; - caStatus status; - - pNewClient = intf.newStreamClient(*this); - if (!pNewClient) { - errMessage(S_cas_noMemory, NULL); - return; - } - - status = pNewClient->init(); - if (status) { - errMessage(status, NULL); - delete pNewClient; + casStreamOS *pNewClient; + + try { + pNewClient = intf.newStreamClient (*this); + if (!pNewClient) { + throw S_cas_noMemory; } + } + catch (...) { + epicsPrintf ("Attempt to create entry for new client failed (C++ exception)\n"); + } } // @@ -272,54 +187,45 @@ void caServerI::advanceBeaconPeriod() // // 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); - fprintf(stderr, -"and therefore internal problems are suspected at line %u in \"%s\"\n", - line, pFile); - fprintf(stderr, - "Please forward above text to johill@lanl.gov - thanks\n"); + fprintf(stderr, "the expression \"%s\" didnt evaluate to boolean true \n", + pExp); + fprintf(stderr, + "and therefore internal problems are suspected at line %u in \"%s\"\n", + line, pFile); + fprintf(stderr, + "Please forward above text to johill@lanl.gov - thanks\n"); } - + // // serverToolDebugFunc() // -void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment) +void serverToolDebugFunc (const char *pFile, unsigned line, const char *pComment) { - fprintf(stderr, + fprintf (stderr, "Bad server tool response detected at line %u in \"%s\" because \"%s\"\n", line, pFile, pComment); } // -// caServerI::addAddr() +// caServerI::attachInterface() // -caStatus caServerI::addAddr(const caNetAddr &addr, int autoBeaconAddr, - int addConfigBeaconAddr) +caStatus caServerI::attachInterface (const caNetAddr &addr, bool autoBeaconAddr, + bool addConfigBeaconAddr) { - caStatus stat; - casIntfOS *pIntf; - - pIntf = new casIntfOS(*this); - if (pIntf) { - stat = pIntf->init(addr, this->dgClient, - autoBeaconAddr, addConfigBeaconAddr); - if (stat==S_cas_success) { - this->osiLock(); - this->intfList.add(*pIntf); - this->osiUnlock(); - } - else { - errMessage(stat, NULL); - delete pIntf; - } - } - else { - stat = S_cas_noMemory; - } - return stat; + casIntfOS *pIntf; + + pIntf = new casIntfOS (*this, addr, autoBeaconAddr, addConfigBeaconAddr); + if (pIntf==NULL) { + return S_cas_noMemory; + } + + this->lock (); + this->intfList.add (*pIntf); + this->unlock (); + + return S_cas_success; } @@ -335,13 +241,13 @@ void caServerI::sendBeacon() // otherwise. Also send a beacon to all configured // addresses. // - this->osiLock(); + this->lock(); tsDLIterBD iter(this->intfList.first()); while ( iter ) { - iter->requestBeacon(); + iter->sendBeacon(); iter++; } - this->osiUnlock(); + this->unlock(); // // double the period between beacons (but dont exceed max) @@ -349,6 +255,76 @@ void caServerI::sendBeacon() this->advanceBeaconPeriod(); } +// +// caServerI::getBeaconPeriod() +// +double caServerI::getBeaconPeriod() const +{ + return this->beaconPeriod; +} + +// +// caServerI::show() +// +void caServerI::show (unsigned level) const +{ + int bytes_reserved; + + printf( "Channel Access Server Status V%d.%d\n", + CA_PROTOCOL_VERSION, CA_MINOR_VERSION); + + this->osiMutex::show(level); + + this->lock(); + tsDLIterBD iterCl(this->clientList.first()); + while ( iterCl!=tsDLIterBD::eol() ) { + iterCl->show(level); + ++iterCl; + } + + tsDLIterBD iterIF(this->intfList.first()); + while ( iterIF!=tsDLIterBD::eol() ) { + iterIF->casIntfOS::show(level); + ++iterIF; + } + + this->unlock(); + + bytes_reserved = 0u; +#if 0 + bytes_reserved += sizeof(casClient) * + ellCount(&this->freeClientQ); + bytes_reserved += sizeof(casChannel) * + ellCount(&this->freeChanQ); + bytes_reserved += sizeof(casEventBlock) * + ellCount(&this->freeEventQ); + bytes_reserved += sizeof(casAsyncIIO) * + ellCount(&this->freePendingIO); +#endif + if (level>=1) { + printf( + "There are currently %d bytes on the server's free list\n", + bytes_reserved); +#if 0 + printf( + "%d client(s), %d channel(s), %d event(s) (monitors), and %d IO blocks\n", + ellCount(&this->freeClientQ), + ellCount(&this->freeChanQ), + ellCount(&this->freeEventQ), + ellCount(&this->freePendingIO)); +#endif + printf( + "The server's integer resource id conversion table:\n"); + this->lock(); + this->chronIntIdResTable::show(level); + this->unlock(); + } + + // @@@@@@ caPrintAddrList(&destAddr); + + return; +} + // // casEventRegistry::~casEventRegistry() // @@ -358,3 +334,4 @@ casEventRegistry::~casEventRegistry() { this->destroyAllEntries(); } + diff --git a/src/cas/generic/caServerIIL.h b/src/cas/generic/caServerIIL.h index 8c1a9c55c..9e13166e8 100644 --- a/src/cas/generic/caServerIIL.h +++ b/src/cas/generic/caServerIIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.6 1999/08/04 23:52:10 jhill + * chronIntIdResTable name change + * * Revision 1.5 1997/06/13 09:15:52 jhill * connect proto changes * @@ -75,14 +78,14 @@ inline casRes *caServerI::lookupRes(const caResId &idIn, casResType type) chronIntId id (idIn); casRes *pRes; - this->osiLock(); + this->lock(); pRes = this->chronIntIdResTable::lookup (id); if (pRes) { if (pRes->resourceType()!=type) { pRes = NULL; } } - this->osiUnlock(); + this->unlock(); return pRes; } @@ -118,19 +121,6 @@ inline casRes *caServerI::removeItem(casRes &res) return this->chronIntIdResTable::remove(res); } -// -// caServerI::ready() -// -inline aitBool caServerI::ready() -{ - if (this->haveBeenInitialized) { - return aitTrue; - } - else { - return aitFalse; - } -} - // // caServerI::setDebugLevel() // @@ -139,5 +129,20 @@ inline void caServerI::setDebugLevel(unsigned debugLevelIn) this->debugLevel = debugLevelIn; } +inline casEventMask caServerI::valueEventMask() const +{ + return this->valueEvent; +} + +inline casEventMask caServerI::logEventMask() const +{ + return this->logEvent; +} + +inline casEventMask caServerI::alarmEventMask() const +{ + return this->alarmEvent; +} + #endif // caServerIIL_h diff --git a/src/cas/generic/casAsyncIO.cc b/src/cas/generic/casAsyncIO.cc deleted file mode 100644 index f18dcd1b1..000000000 --- a/src/cas/generic/casAsyncIO.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * - * History - * $Log$ - * Revision 1.3 1997/04/10 19:33:55 jhill - * API changes - * - * Revision 1.2 1996/11/02 00:53:57 jhill - * many improvements - * - * Revision 1.1.1.1 1996/06/20 00:28:14 jhill - * ca server installation - * - * - */ - -#include"server.h" - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -epicsShareFunc casAsyncIO::~casAsyncIO() -{ -} - -// -// casAsyncIO::destroy() -// (default is a normal delete) -// -epicsShareFunc void casAsyncIO::destroy() -{ - delete this; -} - diff --git a/src/cas/generic/casAsyncIOI.cc b/src/cas/generic/casAsyncIOI.cc index 4792af47b..224b1ef47 100644 --- a/src/cas/generic/casAsyncIOI.cc +++ b/src/cas/generic/casAsyncIOI.cc @@ -26,32 +26,12 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.9 1998/04/16 21:17:38 jhill - * fixed spelling in comment - * - * Revision 1.8 1998/04/14 00:49:26 jhill - * cosmetic - * - * Revision 1.7 1997/08/05 00:47:00 jhill - * fixed warnings - * - * Revision 1.6 1997/04/10 19:33:56 jhill - * API changes - * - * Revision 1.5 1996/12/13 00:08:35 jhill - * dont unlock after destroy - * - * Revision 1.4 1996/11/02 00:53:58 jhill - * many improvements - * - * */ #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 "casAsyncIOIIL.h" // casAsyncIOI in line func #include "casCtxIL.h" // casCtx in line func @@ -59,13 +39,12 @@ // // casAsyncIOI::casAsyncIOI() // -casAsyncIOI::casAsyncIOI(casCoreClient &clientIn, casAsyncIO &ioExternalIn) : - client(clientIn), - ioExternal(ioExternalIn), - inTheEventQueue(FALSE), - posted(FALSE), - ioComplete(FALSE), - serverDelete(FALSE) +casAsyncIOI::casAsyncIOI (casCoreClient &clientIn) : + client (clientIn), + inTheEventQueue (FALSE), + posted (FALSE), + ioComplete (FALSE), + serverDelete (FALSE) { // // catch situation where they create more than one @@ -89,7 +68,7 @@ casAsyncIOI::casAsyncIOI(casCoreClient &clientIn, casAsyncIO &ioExternalIn) : // 1) io completes, this is pulled off the queue, and result // is sent to the client // 2) client, channel, or PV is deleted -// 3) server tool deletes the casAsyncIO obj +// 3) server tool deletes the casAsyncXxxxIO obj // // Case 1) => normal completion // @@ -138,12 +117,11 @@ casAsyncIOI::~casAsyncIOI() this->unlock(); } - // // casAsyncIOI::cbFunc() // (called when IO completion event reaches top of event queue) // -epicsShareFunc caStatus casAsyncIOI::cbFunc(class casEventSys &) +caStatus casAsyncIOI::cbFunc(class casEventSys &) { casCoreClient &theClient = this->client; caStatus status; @@ -153,7 +131,7 @@ epicsShareFunc caStatus casAsyncIOI::cbFunc(class casEventSys &) // asynch IO's lock) here because we need to leave the lock // applied around the destroy() call here. // - theClient.osiLock(); + theClient.lock(); this->inTheEventQueue = FALSE; @@ -177,15 +155,13 @@ epicsShareFunc caStatus casAsyncIOI::cbFunc(class casEventSys &) // dont use "this" after potentially destroying the // object here // - this->serverDelete = TRUE; - (*this)->destroy(); + this->serverDestroy(); - theClient.osiUnlock(); + theClient.unlock(); return S_cas_success; } - // // casAsyncIOI::postIOCompletionI() // @@ -210,9 +186,8 @@ caStatus casAsyncIOI::postIOCompletionI() // dont use "this" after potentially destroying the // object here // - this->serverDelete = TRUE; this->unlock(); - (*this)->destroy(); + this->serverDestroy(); return S_cas_redundantPost; } @@ -253,47 +228,52 @@ caServer *casAsyncIOI::getCAS() const // // casAsyncIOI::readOP() // -epicsShareFunc int casAsyncIOI::readOP() +epicsShareFunc bool casAsyncIOI::readOP() const { // // not a read op // - return FALSE; + return false; } // -// casAsyncIOI::destroyIfReadOP() +// casAsyncIOI::serverDestroyIfReadOP() // -void casAsyncIOI::destroyIfReadOP() +void casAsyncIOI::serverDestroyIfReadOP() { - casCoreClient &clientCopy = this->client; - - // - // client lock used because this object's - // lock may be destroyed - // - clientCopy.osiLock(); - - if (this->readOP()) { - this->serverDelete = TRUE; - (*this)->destroy(); - } - - // - // NO REF TO THIS OBJECT BELOW HERE - // BECAUSE OF THE DELETE ABOVE - // - - clientCopy.osiUnlock(); + casCoreClient &clientCopy = this->client; + + // + // client lock used because this object's + // lock may be destroyed + // + clientCopy.lock(); + + if (this->readOP()) { + this->serverDestroy(); + } + + // + // NO REF TO THIS OBJECT BELOW HERE + // BECAUSE OF THE DELETE ABOVE + // + + clientCopy.unlock(); } // -// casAsyncIOI::reportInvalidAsynchIO() +// void casAsyncIOI::serverDestroy () // -void casAsyncIOI::reportInvalidAsynchIO(unsigned request) +void casAsyncIOI::serverDestroy () { - ca_printf("Server tools selection of async IO type\n"); - ca_printf("is inappropriate = %u and will be ignored\n", - request); + this->serverDelete = TRUE; + this->destroy(); } +// +// void casAsyncIOI::destroy () +// +void casAsyncIOI::destroy () +{ + delete this; +} \ No newline at end of file diff --git a/src/cas/generic/casAsyncIOIIL.h b/src/cas/generic/casAsyncIOIIL.h index 25e73f00e..0faa4dc05 100644 --- a/src/cas/generic/casAsyncIOIIL.h +++ b/src/cas/generic/casAsyncIOIIL.h @@ -26,19 +26,6 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.3 1996/09/16 18:23:58 jhill - * vxWorks port changes - * - * Revision 1.2 1996/09/04 20:16:24 jhill - * moved operator -> here - * - * Revision 1.1.1.1 1996/06/20 00:28:16 jhill - * ca server installation - * - * */ @@ -55,7 +42,7 @@ // inline void casAsyncIOI::lock() { - client.osiLock(); + client.lock(); } // @@ -63,24 +50,7 @@ inline void casAsyncIOI::lock() // inline void casAsyncIOI::unlock() { - client.osiUnlock(); -} - -// -// casAsyncIO * casAsyncIOI::operator -> () -// -inline casAsyncIO * casAsyncIOI::operator -> () -{ - return &this->ioExternal; -} - -// -// void casAsyncIOI::destroy () -// -inline void casAsyncIOI::destroy () -{ - this->serverDelete = TRUE; - (*this)->destroy(); + client.unlock(); } #endif // casAsyncIOIIL_h diff --git a/src/cas/generic/casAsyncPVAttachIO.cc b/src/cas/generic/casAsyncPVAttachIO.cc new file mode 100644 index 000000000..c6ace87fb --- /dev/null +++ b/src/cas/generic/casAsyncPVAttachIO.cc @@ -0,0 +1,111 @@ +/* + * $Id$ + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + */ + +#include "server.h" +#include "casAsyncIOIIL.h" // casAsyncIOI in line func +#include "casChannelIIL.h" // casChannelI in line func +#include "casCtxIL.h" // casCtx in line func +#include "casCoreClientIL.h" // casCoreClient in line func + +// +// casAsyncPVAttachIO::casAsyncPVAttachIO() +// +casAsyncPVAttachIO::casAsyncPVAttachIO (const casCtx &ctx) : + casAsyncIOI (*ctx.getClient()), + msg (*ctx.getMsg()), + retVal (S_cas_badParameter) +{ + this->client.installAsyncIO (*this); +} + +// +// casAsyncPVAttachIO::~casAsyncPVAttachIO() +// +casAsyncPVAttachIO::~casAsyncPVAttachIO() +{ + this->client.removeAsyncIO (*this); +} + +// +// casAsyncPVAttachIO::postIOCompletion() +// +caStatus casAsyncPVAttachIO::postIOCompletion(const pvAttachReturn &retValIn) +{ + this->retVal = retValIn; + return this->postIOCompletionI (); +} + +// +// casAsyncPVAttachIO::cbFuncAsyncIO() +// (called when IO completion event reaches top of event queue) +// +epicsShareFunc 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; +} + +// +// depricated +// +casAsyncPVCreateIO::casAsyncPVCreateIO(const casCtx &ctx) : + casAsyncPVAttachIO (ctx) +{ +} + +// +// depricated +// +epicsShareFunc casAsyncPVCreateIO::~casAsyncPVCreateIO() +{ +} + + diff --git a/src/cas/generic/casAsyncExIOI.cc b/src/cas/generic/casAsyncPVExistIO.cc similarity index 59% rename from src/cas/generic/casAsyncExIOI.cc rename to src/cas/generic/casAsyncPVExistIO.cc index e589fecc9..aca342168 100644 --- a/src/cas/generic/casAsyncExIOI.cc +++ b/src/cas/generic/casAsyncPVExistIO.cc @@ -36,61 +36,63 @@ #include "casCoreClientIL.h" // casCoreClient in line func // -// casAsyncExIOI::casAsyncExIOI() +// casAsyncPVExistIO::casAsyncPVExistIO() // -epicsShareFunc casAsyncExIOI::casAsyncExIOI( - const casCtx &ctx, casAsyncPVExistIO &ioIn) : - casAsyncIOI(*ctx.getClient(), ioIn), - msg(*ctx.getMsg()), - retVal(pverDoesNotExistHere), - pOutDGIntfIO(ctx.getClient()->fetchOutIntf()), - dgOutAddr(ctx.getClient()->fetchRespAddr()) +casAsyncPVExistIO::casAsyncPVExistIO (const casCtx &ctx) : + casAsyncIOI ( *ctx.getClient () ), + msg ( *ctx.getMsg () ), + retVal (pverDoesNotExistHere), + dgOutAddr ( ctx.getClient ()->fetchLastRecvAddr () ) { - assert (&this->msg); - this->client.installAsyncIO(*this); + this->client.installAsyncIO (*this); } // -// casAsyncExIOI::~casAsyncExIOI() +// casAsyncPVExistIO::~casAsyncPVExistIO () // -casAsyncExIOI::~casAsyncExIOI() +casAsyncPVExistIO::~casAsyncPVExistIO () { - this->client.removeAsyncIO(*this); + this->client.removeAsyncIO (*this); } // -// casAsyncExIOI::postIOCompletion() +// casAsyncPVExistIO::postIOCompletion () // -epicsShareFunc caStatus casAsyncExIOI::postIOCompletion(const pvExistReturn &retValIn) +caStatus casAsyncPVExistIO::postIOCompletion (const pvExistReturn &retValIn) { this->retVal = retValIn; - return this->postIOCompletionI(); + return this->postIOCompletionI (); } // -// casAsyncExIOI::cbFuncAsyncIO() +// casAsyncPVExistIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -epicsShareFunc caStatus casAsyncExIOI::cbFuncAsyncIO() +epicsShareFunc caStatus casAsyncPVExistIO::cbFuncAsyncIO() { caStatus status; - switch (this->msg.m_cmmd) { - case CA_PROTO_SEARCH: + if (this->msg.m_cmmd==CA_PROTO_SEARCH) { // // pass output DG address parameters // - assert(this->pOutDGIntfIO); - status = this->client.asyncSearchResponse(*this->pOutDGIntfIO, + status = this->client.asyncSearchResponse ( this->dgOutAddr, this->msg, this->retVal); - break; - - default: - this->reportInvalidAsynchIO(this->msg.m_cmmd); - status = S_cas_internal; - break; + } + else { + errPrintf (S_cas_invalidAsynchIO, __FILE__, __LINE__, + " - client request type = %u", this->msg.m_cmmd); + status = S_cas_invalidAsynchIO; } return status; } +// +// void casAsyncPVExistIO::destroy () +// +void casAsyncPVExistIO::destroy () +{ + delete this; +} + diff --git a/src/cas/generic/casAsyncRdIOI.cc b/src/cas/generic/casAsyncReadIO.cc similarity index 60% rename from src/cas/generic/casAsyncRdIOI.cc rename to src/cas/generic/casAsyncReadIO.cc index 7e583d9a2..663555c03 100644 --- a/src/cas/generic/casAsyncRdIOI.cc +++ b/src/cas/generic/casAsyncReadIO.cc @@ -26,40 +26,6 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.7 1998/07/08 15:38:03 jhill - * fixed lost monitors during flow control problem - * - * Revision 1.6 1998/06/18 00:08:30 jhill - * deleted unused variables - * - * Revision 1.5 1998/06/16 02:18:53 jhill - * use smart gdd ptr - * - * Revision 1.4 1997/08/05 00:47:01 jhill - * fixed warnings - * - * Revision 1.3 1997/04/10 19:33:56 jhill - * API changes - * - * Revision 1.2 1996/11/06 22:15:54 jhill - * allow monitor init read to using rd async io - * - * Revision 1.1 1996/11/02 01:01:03 jhill - * installed - * - * Revision 1.3 1996/09/04 20:13:16 jhill - * initialize new member - asyncIO - * - * Revision 1.2 1996/06/26 21:18:50 jhill - * now matches gdd api revisions - * - * Revision 1.1.1.1 1996/06/20 00:28:14 jhill - * ca server installation - * - * */ @@ -69,25 +35,24 @@ #include "casCtxIL.h" // casCtxI in line func // -// casAsyncRdIOI::casAsyncRdIOI() +// casAsyncReadIO::casAsyncReadIO() // -epicsShareFunc casAsyncRdIOI::casAsyncRdIOI(const casCtx &ctx, casAsyncReadIO &ioIn) : - casAsyncIOI(*ctx.getClient(), ioIn), +casAsyncReadIO::casAsyncReadIO(const casCtx &ctx) : + casAsyncIOI(*ctx.getClient()), msg(*ctx.getMsg()), chan(*ctx.getChannel()), pDD(NULL), completionStatus(S_cas_internal) { - assert (&this->msg); assert (&this->chan); this->chan.installAsyncIO(*this); } // -// casAsyncRdIOI::~casAsyncRdIOI() +// casAsyncReadIO::~casAsyncReadIO() // -casAsyncRdIOI::~casAsyncRdIOI() +casAsyncReadIO::~casAsyncReadIO() { this->lock(); @@ -97,9 +62,9 @@ casAsyncRdIOI::~casAsyncRdIOI() } // -// casAsyncRdIOI::postIOCompletion() +// casAsyncReadIO::postIOCompletion() // -epicsShareFunc caStatus casAsyncRdIOI::postIOCompletion(caStatus completionStatusIn, +caStatus casAsyncReadIO::postIOCompletion(caStatus completionStatusIn, gdd &valueRead) { this->lock(); @@ -111,19 +76,18 @@ epicsShareFunc caStatus casAsyncRdIOI::postIOCompletion(caStatus completionStatu } // -// casAsyncRdIOI::readOP() +// casAsyncReadIO::readOP() // -epicsShareFunc int casAsyncRdIOI::readOP() +epicsShareFunc bool casAsyncReadIO::readOP() const { - return TRUE; // it is a read op + return true; // it is a read op } - // -// casAsyncRdIOI::cbFuncAsyncIO() +// casAsyncReadIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -caStatus casAsyncRdIOI::cbFuncAsyncIO() +epicsShareFunc caStatus casAsyncReadIO::cbFuncAsyncIO() { caStatus status; @@ -146,11 +110,19 @@ caStatus casAsyncRdIOI::cbFuncAsyncIO() break; default: - this->reportInvalidAsynchIO(this->msg.m_cmmd); - status = S_cas_internal; + 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; +} \ No newline at end of file diff --git a/src/cas/generic/casAsyncWtIOI.cc b/src/cas/generic/casAsyncWriteIO.cc similarity index 56% rename from src/cas/generic/casAsyncWtIOI.cc rename to src/cas/generic/casAsyncWriteIO.cc index ce5d7e785..19a5d3446 100644 --- a/src/cas/generic/casAsyncWtIOI.cc +++ b/src/cas/generic/casAsyncWriteIO.cc @@ -26,49 +26,31 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.4 1997/08/05 00:47:02 jhill - * fixed warnings - * - * Revision 1.3 1997/04/10 19:33:57 jhill - * API changes - * - * Revision 1.2 1996/11/06 22:15:56 jhill - * allow monitor init read to using rd async io - * - * Revision 1.1 1996/11/02 01:01:04 jhill - * installed - * - * */ #include "server.h" -#include "casAsyncIOIIL.h" // casAsyncIOI in line func #include "casChannelIIL.h" // casChannelI in line func +#include "casAsyncIOIIL.h" // casAsyncIOI in line func #include "casCtxIL.h" // casCtx in line func // -// casAsyncWtIOI::casAsyncWtIOI() +// casAsyncWriteIO::casAsyncWriteIO() // -epicsShareFunc casAsyncWtIOI::casAsyncWtIOI(const casCtx &ctx, casAsyncWriteIO &ioIn) : - casAsyncIOI(*ctx.getClient(), ioIn), +casAsyncWriteIO::casAsyncWriteIO(const casCtx &ctx) : + casAsyncIOI(*ctx.getClient()), msg(*ctx.getMsg()), chan(*ctx.getChannel()), completionStatus(S_cas_internal) { - assert (&this->msg); assert (&this->chan); - this->chan.installAsyncIO(*this); } // -// casAsyncWtIOI::~casAsyncWtIOI() +// casAsyncWriteIO::~casAsyncWriteIO() // -casAsyncWtIOI::~casAsyncWtIOI() +casAsyncWriteIO::~casAsyncWriteIO() { this->lock(); this->chan.removeAsyncIO(*this); @@ -76,40 +58,47 @@ casAsyncWtIOI::~casAsyncWtIOI() } // -// casAsyncWtIOI::postIOCompletion() +// casAsyncWriteIO::postIOCompletion() // -epicsShareFunc caStatus casAsyncWtIOI::postIOCompletion(caStatus completionStatusIn) +caStatus casAsyncWriteIO::postIOCompletion(caStatus completionStatusIn) { this->completionStatus = completionStatusIn; return this->postIOCompletionI(); } - // -// casAsyncWtIOI::cbFuncAsyncIO() +// casAsyncWriteIO::cbFuncAsyncIO() // (called when IO completion event reaches top of event queue) // -caStatus casAsyncWtIOI::cbFuncAsyncIO() +epicsShareFunc 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: - this->reportInvalidAsynchIO(this->msg.m_cmmd); - status = S_cas_internal; - break; - } - - return status; + 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; + } + + return status; } +// +// void casAsyncWriteIO::destroy () +// +void casAsyncWriteIO::destroy () +{ + delete this; +} diff --git a/src/cas/generic/casAsyncXXIO.cc b/src/cas/generic/casAsyncXXIO.cc deleted file mode 100644 index f8516763e..000000000 --- a/src/cas/generic/casAsyncXXIO.cc +++ /dev/null @@ -1,100 +0,0 @@ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * - * History - * $Log$ - * Revision 1.4 1998/02/05 22:51:34 jhill - * include resourceLib.h - * - * Revision 1.3 1997/08/05 00:47:02 jhill - * fixed warnings - * - * Revision 1.2 1997/04/10 19:33:58 jhill - * API changes - * - * Revision 1.1 1996/11/02 01:01:05 jhill - * installed - * - * - * - */ - -// -// 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 "alarm.h" // EPICS alarm severity/condition -#include "errMdef.h" // EPICS error codes -#include "gdd.h" // EPICS data descriptors -#include "resourceLib.h" // EPICS hashing templates - -#define epicsExportSharedSymbols -#include "casdef.h" - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -epicsShareFunc casAsyncReadIO::~casAsyncReadIO() -{ -} - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -epicsShareFunc casAsyncWriteIO::~casAsyncWriteIO() -{ -} - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -epicsShareFunc casAsyncPVExistIO::~casAsyncPVExistIO() -{ -} - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -epicsShareFunc casAsyncPVCreateIO::~casAsyncPVCreateIO() -{ -} - -// -// This must be virtual so that derived destructor will -// be run indirectly. Therefore it cannot be inline. -// -epicsShareFunc casAsyncPVAttachIO::~casAsyncPVAttachIO() -{ -} \ No newline at end of file diff --git a/src/cas/generic/casChanDelEv.cc b/src/cas/generic/casChanDelEv.cc index a71f08391..edc47fdce 100644 --- a/src/cas/generic/casChanDelEv.cc +++ b/src/cas/generic/casChanDelEv.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.4 1997/06/13 09:15:54 jhill + * connect proto changes + * * Revision 1.3 1997/04/10 19:33:58 jhill * API changes * @@ -58,7 +61,7 @@ casChanDelEv::~casChanDelEv() caStatus casChanDelEv::cbFunc(casEventSys &eSys) { caStatus status; - status = eSys.getCoreClient().disconnectChan(this->id); + status = eSys.disconnectChan (this->id); if (status == S_cas_success) { delete this; } diff --git a/src/cas/generic/casChannel.cc b/src/cas/generic/casChannel.cc index c9d034d89..df9c87358 100644 --- a/src/cas/generic/casChannel.cc +++ b/src/cas/generic/casChannel.cc @@ -27,24 +27,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.5 1997/04/10 19:33:59 jhill - * API changes - * - * Revision 1.4 1996/09/04 20:17:34 jhill - * use ptr not ref to satisfy MSVISC++ - * - * Revision 1.3 1996/08/13 22:52:31 jhill - * changes for MVC++ - * - * Revision 1.2 1996/07/01 19:56:09 jhill - * one last update prior to first release - * - * Revision 1.1.1.1 1996/06/20 00:28:14 jhill - * ca server installation - * - * */ #include "server.h" @@ -55,7 +37,7 @@ // casChannel::casChannel() // epicsShareFunc casChannel::casChannel(const casCtx &ctx) : - casPVListChan (ctx, *this) + casPVListChan (ctx) { } @@ -66,12 +48,15 @@ epicsShareFunc casChannel::~casChannel() { } +// +// casChannel::getPV() +// epicsShareFunc casPV *casChannel::getPV() { casPVI *pPVI = &this->casChannelI::getPVI(); if (pPVI!=NULL) { - return pPVI->interfaceObjectPointer(); + return pPVI->apiPointer(); } else { return NULL; @@ -92,26 +77,26 @@ epicsShareFunc void casChannel::setOwner(const char * const /* pUserName */, // // casChannel::readAccess() // -epicsShareFunc aitBool casChannel::readAccess () const +epicsShareFunc bool casChannel::readAccess () const { - return aitTrue; + return true; } // // casChannel::writeAccess() // -epicsShareFunc aitBool casChannel::writeAccess() const +epicsShareFunc bool casChannel::writeAccess() const { - return aitTrue; + return true; } // // casChannel::confirmationRequested() // -epicsShareFunc aitBool casChannel::confirmationRequested() const +epicsShareFunc bool casChannel::confirmationRequested() const { - return aitFalse; + return false; } // diff --git a/src/cas/generic/casChannelI.cc b/src/cas/generic/casChannelI.cc index 94c5a9bf3..92d5b08e9 100644 --- a/src/cas/generic/casChannelI.cc +++ b/src/cas/generic/casChannelI.cc @@ -26,31 +26,6 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.7 1998/09/24 20:33:03 jhill - * cosmetic - * - * Revision 1.6 1998/07/08 15:38:03 jhill - * fixed lost monitors during flow control problem - * - * Revision 1.5 1998/04/14 00:50:00 jhill - * cosmetic - * - * Revision 1.4 1997/04/10 19:34:00 jhill - * API changes - * - * Revision 1.3 1996/11/02 00:54:02 jhill - * many improvements - * - * Revision 1.2 1996/09/04 20:18:03 jhill - * init new chan member - * - * Revision 1.1.1.1 1996/06/20 00:28:14 jhill - * ca server installation - * - * */ #include "server.h" @@ -59,34 +34,26 @@ #include "casPVIIL.h" // casPVI inline func #include "casCtxIL.h" // casCtx inline func - // // casChannelI::casChannelI() // -casChannelI::casChannelI(const casCtx &ctx, casChannel &chanAdapter) : - client(* (casStrmClient *) ctx.getClient()), - pv(*ctx.getPV()), - chan(chanAdapter), - cid(ctx.getMsg()->m_cid), - clientDestroyPending(FALSE), - accessRightsEvPending(FALSE) +casChannelI::casChannelI (const casCtx &ctx) : + client ( * (casStrmClient *) ctx.getClient ()), + pv (*ctx.getPV()), + cid (ctx.getMsg()->m_cid), + accessRightsEvPending (FALSE) { - assert(&this->client); - assert(&this->pv); - assert(&this->chan); + assert (&this->client); + assert (&this->pv); - this->client.installChannel(*this); + this->client.installChannel (*this); } - // // casChannelI::~casChannelI() // casChannelI::~casChannelI() -{ - casChanDelEv *pCDEV; - caStatus status; - +{ this->lock(); // @@ -99,14 +66,14 @@ casChannelI::~casChannelI() // tsDLIterBD tmpAIO = iterAIO; ++tmpAIO; - iterAIO->destroy(); + iterAIO->serverDestroy(); iterAIO = tmpAIO; } // // cancel the monitors // - tsDLIterBD iterMon(this->monitorList.first()); + tsDLIterBD iterMon (this->monitorList.first()); while ( iterMon!=tsDLIterBD::eol() ) { casMonitor *pMonitor; // @@ -126,40 +93,9 @@ casChannelI::~casChannelI() // this->pv.deleteSignal(); - // - // If we are not in the process of deleting the client - // then inform the client that we have deleted its - // channel - // - if (!this->clientDestroyPending) { - pCDEV = new casChanDelEv(this->getCID()); - if (pCDEV) { - this->client.casEventSys::addToEventQueue(*pCDEV); - } - else { - status = this->client.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->client.setDestroyPending(); - } - } - } - this->unlock(); } - // // casChannelI::clearOutstandingReads() // @@ -177,14 +113,13 @@ void casChannelI::clearOutstandingReads() // tsDLIterBD tmp = iterIO; ++tmp; - iterIO->destroyIfReadOP(); + iterIO->serverDestroyIfReadOP(); iterIO = tmp; } this->unlock(); } - // // casChannelI::show() // @@ -195,19 +130,18 @@ void casChannelI::show(unsigned level) const tsDLIterBD iter(this->monitorList.first()); if ( iter!=tsDLIterBD::eol() ) { printf("List of CA events (monitors) for \"%s\".\n", - this->pv->getName()); + this->pv.getName()); } while ( iter!=tsDLIterBD::eol() ) { iter->show(level); ++iter; } - (*this)->show(level); + this->show(level); this->unlock(); } - // // casChannelI::cbFunc() // @@ -224,16 +158,6 @@ caStatus casChannelI::cbFunc(casEventSys &) return stat; } -// -// casChannelI::destroy() -// -// call the destroy in the server tool -// -void casChannelI::destroy() -{ - this->chan.destroy(); -} - // // casChannelI::resourceType() // @@ -242,3 +166,44 @@ casResType casChannelI::resourceType() const return casChanT; } +// +// casChannelI::destroy() +// +// this noop version is safe to be called indirectly +// from casChannelI::~casChannelI +// +epicsShareFunc void casChannelI::destroy() +{ +} + +void casChannelI::destroyClientNotify () +{ + casChanDelEv *pCDEV; + caStatus status; + + pCDEV = new casChanDelEv (this->getCID()); + if (pCDEV) { + this->client.casEventSys::addToEventQueue (*pCDEV); + } + else { + status = this->client.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->client.setDestroyPending(); + } + } + this->destroy(); +} + + diff --git a/src/cas/generic/casChannelIIL.h b/src/cas/generic/casChannelIIL.h index cf9f04a5a..279ebea18 100644 --- a/src/cas/generic/casChannelIIL.h +++ b/src/cas/generic/casChannelIIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.7 1999/08/04 23:18:59 jhill + * updated to new DLL terminators + * * Revision 1.6 1997/04/10 19:34:00 jhill * API changes * @@ -57,20 +60,12 @@ #include "casCoreClientIL.h" #include "casEventSysIL.h" -// -// casChannelI::operator -> () -// -inline casChannel * casChannelI::operator -> () const -{ - return &this->chan; -} - // // casChannelI::lock() // inline void casChannelI::lock() const { - this->client.osiLock(); + this->client.lock(); } // @@ -78,7 +73,7 @@ inline void casChannelI::lock() const // inline void casChannelI::unlock() const { - this->client.osiUnlock(); + this->client.unlock(); } // @@ -144,12 +139,11 @@ inline casMonitor *casChannelI::findMonitor(const caResId clientIdIn) } // -// casChannelI::clientDestroy() +// casChannelI::destroyNoClientNotify() // -inline void casChannelI::clientDestroy() +inline void casChannelI::destroyNoClientNotify() { - this->clientDestroyPending=TRUE; - (*this)->destroy(); + this->destroy (); } #include "casPVIIL.h" diff --git a/src/cas/generic/casClient.cc b/src/cas/generic/casClient.cc index 6ca9895a3..d502016df 100644 --- a/src/cas/generic/casClient.cc +++ b/src/cas/generic/casClient.cc @@ -35,6 +35,7 @@ #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 "db_access.h" @@ -45,49 +46,19 @@ static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u}; // static declartions for class casClient // int casClient::msgHandlersInit; -pCASMsgHandler casClient::msgHandlers[CA_PROTO_LAST_CMMD+1u]; +casClient::pCASMsgHandler casClient::msgHandlers[CA_PROTO_LAST_CMMD+1u]; - - // // casClient::casClient() // -casClient::casClient(caServerI &serverInternal, inBuf &inBufIn, outBuf &outBufIn) : - casCoreClient(serverInternal), - inBufRef(inBufIn), outBufRef(outBufIn) +casClient::casClient(caServerI &serverInternal, bufSizeT ioSizeMinIn) : + inBuf (MAX_MSG_SIZE, ioSizeMinIn), outBuf (MAX_MSG_SIZE), + casCoreClient (serverInternal) { - // - // static member init - // - casClient::loadProtoJumpTable(); -} - - -// -// casClient::init() -// -caStatus casClient::init() -{ - unsigned serverDebugLevel; - caStatus status; - - // - // call base class initializers - // - status = this->casCoreClient::init(); - if (status) { - return status; - } - - serverDebugLevel = this->ctx.getServer()->getDebugLevel(); - if (serverDebugLevel>0u) { - char pName[64u]; - - this->clientHostName (pName, sizeof (pName)); - ca_printf("CAS: created a new client for %s\n", pName); - } - - return S_cas_success; + // + // static member init + // + casClient::loadProtoJumpTable(); } // @@ -125,7 +96,6 @@ casChannelI *casClient::resIdToChannel(const caResId &id) return pChan; } - // // casClient::loadProtoJumpTable() // @@ -198,7 +168,6 @@ void casClient::loadProtoJumpTable() casClient::msgHandlersInit = TRUE; } - // // casClient::~casClient () // @@ -206,7 +175,6 @@ casClient::~casClient () { } - // // casClient::show() // @@ -216,25 +184,23 @@ void casClient::show(unsigned level) const this->casCoreClient::show(level); } - -/* - * casClient::processMsg() - */ -caStatus casClient::processMsg() +// +// casClient::processMsg () +// +caStatus casClient::processMsg () { - unsigned msgsize; - unsigned bytesLeft; - int status; - const caHdr *mp; - const char *rawMP; + unsigned msgsize; + unsigned bytesLeft; + int status; + const caHdr *mp; + const char *rawMP; // // process any messages in the in buffer // status = S_cas_success; - bytesLeft = this->inBufRef.bytesPresent(); - while (bytesLeft) { + while (bytesLeft = this->inBuf::bytesPresent()) { /* * incomplete message - return success and @@ -245,7 +211,7 @@ caStatus casClient::processMsg() break; } - rawMP = this->inBufRef.msgPtr(); + rawMP = this->inBuf::msgPtr(); this->ctx.setMsg(rawMP); // @@ -275,8 +241,8 @@ caStatus casClient::processMsg() // (guarantees that previous message does not get mixed // up with the current message) // - this->ctx.setChannel(NULL); - this->ctx.setPV(NULL); + this->ctx.setChannel (NULL); + this->ctx.setPV (NULL); // // Check for bad protocol element @@ -289,19 +255,28 @@ caStatus casClient::processMsg() // // Call protocol stub // - status = (this->*casClient::msgHandlers[mp->m_cmmd]) (); - if (status) { - break; - } + try { + status = (this->*casClient::msgHandlers[mp->m_cmmd]) (); + if (status) { + break; + } + } + catch (...) { + this->dumpMsg (mp, this->ctx.getData() ); + epicsPrintf ("Attempt to execute client request failed (C++ exception)\n"); + status = this->sendErr (mp, ECA_INTERNAL, "request resulted in C++ exception"); + if (status) { + break; + } + break; + } - this->inBufRef.removeMsg(msgsize); - bytesLeft = this->inBufRef.bytesPresent(); + this->inBuf::removeMsg (msgsize); } return status; } - /* * casClient::ignoreMsgAction() */ @@ -310,7 +285,6 @@ caStatus casClient::ignoreMsgAction () return S_cas_success; } - /* * casClient::uknownMessageAction() */ @@ -384,7 +358,6 @@ caStatus casClient::clientNameAction () caStatus casClient::hostNameAction () {return this->uknownMessageAction ();} - // // echoAction() // @@ -395,7 +368,7 @@ caStatus casClient::echoAction () int status; caHdr *reply; - status = this->outBufRef.allocMsg(mp->m_postsize, &reply); + status = this->outBuf::allocMsg (mp->m_postsize, &reply); if (status) { if (status==S_cas_hugeRequest) { status = sendErr(mp, ECA_TOLARGE, NULL); @@ -404,12 +377,11 @@ caStatus casClient::echoAction () } *reply = *mp; memcpy((char *) (reply+1), (char *) dp, mp->m_postsize); - this->outBufRef.commitMsg(); + this->outBuf::commitMsg(); return S_cas_success; } - /* * casClient::noopAction() */ @@ -418,9 +390,6 @@ caStatus casClient::noopAction () return S_cas_success; } - - - // // casClient::sendErr() // @@ -458,7 +427,7 @@ const char *pformat, /* * allocate plenty of space for a sprintf() buffer */ - status = this->outBufRef.allocMsg (size+sizeof(caHdr), &reply); + status = this->outBuf::allocMsg (size+sizeof(caHdr), &reply); if (status) { return status; } @@ -521,12 +490,11 @@ const char *pformat, reply->m_postsize = size + sizeof(caHdr); - this->outBufRef.commitMsg(); + this->outBuf::commitMsg(); return S_cas_success; } - /* * casClient::sendErrWithEpicsStatus() * @@ -548,7 +516,6 @@ caStatus casClient::sendErrWithEpicsStatus(const caHdr *pMsg, return this->sendErr(pMsg, clientStatus, buf); } - /* * casClient::logBadIdWithFileAndLineno() */ @@ -580,7 +547,6 @@ const unsigned id return status; } - // // casClient::dumpMsg() // @@ -600,7 +566,7 @@ void casClient::dumpMsg(const caHdr *mp, const void *dp) pciu = this->resIdToChannel(mp->m_cid); if (pciu) { - strncpy(pPVName, pciu->getPVI()->getName(), sizeof(pPVName)); + strncpy(pPVName, pciu->getPVI().getName(), sizeof(pPVName)); if (&pciu->getClient()!=this) { strncat(pPVName, "!Bad Client!", sizeof(pPVName)); } @@ -637,4 +603,3 @@ const char *casClient::userName() const { return "?"; } - diff --git a/src/cas/generic/casCoreClient.cc b/src/cas/generic/casCoreClient.cc index b72d86e08..f246aad68 100644 --- a/src/cas/generic/casCoreClient.cc +++ b/src/cas/generic/casCoreClient.cc @@ -37,25 +37,14 @@ #include "inBufIL.h" // inBuf in line func #include "outBufIL.h" // outBuf in line func -// -// casCoreClient::init() -// -caStatus casCoreClient::init() -{ - if (this->osiMutex::init()) { - return S_cas_noMemory; - } - return this->casEventSys::init(); -} - // // casCoreClient::casCoreClient() // -casCoreClient::casCoreClient (caServerI &serverInternal) : casEventSys(*this) +casCoreClient::casCoreClient (caServerI &serverInternal) { - assert(&serverInternal); - ctx.setServer(&serverInternal); - ctx.setClient(this); + assert (&serverInternal); + ctx.setServer (&serverInternal); + ctx.setClient (this); } // @@ -67,7 +56,7 @@ casCoreClient::~casCoreClient() ca_printf ("CAS: Connection Terminated\n"); } - this->osiLock(); + this->lock(); tsDLIterBD iterIO(this->ioInProgList.first()); // @@ -79,11 +68,11 @@ casCoreClient::~casCoreClient() // tsDLIterBD tmpIO = iterIO; ++tmpIO; - iterIO->destroy(); + iterIO->serverDestroy(); iterIO = tmpIO; } - this->osiUnlock(); + this->unlock(); } // @@ -115,7 +104,7 @@ void casCoreClient::show (unsigned level) const // one of these for each CA request type that has // asynchronous completion // -caStatus casCoreClient::asyncSearchResponse(casDGIntfIO &, +caStatus casCoreClient::asyncSearchResponse ( const caNetAddr &, const caHdr &, const pvExistReturn &) { return S_casApp_noSupport; @@ -171,18 +160,19 @@ void casCoreClient::removeChannel(casChannelI &) } // -// casCoreClient::fetchRespAddr() +// casCoreClient::fetchLastRecvAddr () // -caNetAddr casCoreClient::fetchRespAddr() +caNetAddr casCoreClient::fetchLastRecvAddr () const { return caNetAddr(); // sets addr type to UDF } // -// casCoreClient::fetchOutIntf() +// casCoreClient::lookupRes() // -casDGIntfIO* casCoreClient::fetchOutIntf() +casRes *casCoreClient::lookupRes(const caResId &idIn, casResType type) { - return NULL; + casRes *pRes; + pRes = this->ctx.getServer()->lookupRes(idIn, type); + return pRes; } - diff --git a/src/cas/generic/casCoreClientIL.h b/src/cas/generic/casCoreClientIL.h index 19a330b3c..16caa786f 100644 --- a/src/cas/generic/casCoreClientIL.h +++ b/src/cas/generic/casCoreClientIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.2 1997/04/10 19:34:04 jhill + * API changes + * * Revision 1.1 1996/11/02 01:01:06 jhill * installed * @@ -50,24 +53,14 @@ inline caServerI &casCoreClient::getCAS() const return *this->ctx.getServer(); } -// -// casCoreClient::lookupRes() -// -inline casRes *casCoreClient::lookupRes(const caResId &idIn, casResType type) -{ - casRes *pRes; - pRes = this->ctx.getServer()->lookupRes(idIn, type); - return pRes; -} - // // casCoreClient::installAsyncIO() // inline void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) { - this->osiLock(); + this->lock(); this->ioInProgList.add(ioIn); - this->osiUnlock(); + this->unlock(); } // @@ -75,10 +68,10 @@ inline void casCoreClient::installAsyncIO(casAsyncIOI &ioIn) // inline void casCoreClient::removeAsyncIO(casAsyncIOI &ioIn) { - this->osiLock(); + this->lock(); this->ioInProgList.remove(ioIn); this->ctx.getServer()->ioBlockedList::signal(); - this->osiUnlock(); + this->unlock(); } #endif // casCoreClientIL_h diff --git a/src/cas/generic/casDGClient.cc b/src/cas/generic/casDGClient.cc index 4f8eb5098..ef3d20ad2 100644 --- a/src/cas/generic/casDGClient.cc +++ b/src/cas/generic/casDGClient.cc @@ -27,63 +27,12 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.16 1998/12/19 00:04:51 jhill - * renamed createPV() to pvAttach() - * - * Revision 1.15 1998/04/20 18:11:01 jhill - * better debug mesg - * - * Revision 1.14 1998/04/10 23:13:14 jhill - * fixed byte swap problems, and use default port if server tool returns PV IP addr, but no port - * - * Revision 1.13 1998/02/05 22:54:19 jhill - * moved inline func here - * - * Revision 1.12 1997/08/05 00:47:06 jhill - * fixed warnings - * - * Revision 1.11 1997/06/30 22:54:27 jhill - * use %p with pointers - * - * Revision 1.10 1997/06/13 09:15:56 jhill - * connect proto changes - * - * Revision 1.9 1997/04/10 19:34:06 jhill - * API changes - * - * Revision 1.8 1997/01/10 21:17:53 jhill - * code around gnu g++ inline bug when -O isnt used - * - * Revision 1.7 1996/11/02 00:54:08 jhill - * many improvements - * - * Revision 1.6 1996/09/16 18:24:00 jhill - * vxWorks port changes - * - * Revision 1.5 1996/09/04 20:19:47 jhill - * added missing byte swap on search reply port no - * - * Revision 1.4 1996/08/13 22:54:20 jhill - * fixed little endian problem - * - * Revision 1.3 1996/08/05 19:26:15 jhill - * made os specific code smaller - * - * Revision 1.2 1996/06/26 21:18:52 jhill - * now matches gdd api revisions - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * */ #include "gddApps.h" #include "server.h" #include "caServerIIL.h" // caServerI inline func -#include "dgOutBufIL.h" // dgOutBuf inline func +#include "outBufIL.h" // inline func for outBuf #include "dgInBufIL.h" // dgInBuf inline func #include "casCtxIL.h" // casCtx inline func #include "casCoreClientIL.h" // casCoreClient inline func @@ -95,33 +44,11 @@ // // casDGClient::casDGClient() // -casDGClient::casDGClient(caServerI &serverIn) : - dgInBuf(*(osiMutex *)this, casDGIntfIO::optimumInBufferSize()), - dgOutBuf(*(osiMutex *)this, casDGIntfIO::optimumOutBufferSize()), - casClient(serverIn, *this, *this), - pOutMsgIO(NULL), - pInMsgIO(NULL) +casDGClient::casDGClient (caServerI &serverIn) : + casClient (serverIn, MAX_UDP+sizeof(cadg)) { } -// -// casDGClient::init() -// -caStatus casDGClient::init() -{ - caStatus status; - - status = this->dgInBuf::init(); - if (status) { - return status; - } - status = this->dgOutBuf::init(); - if (status) { - return status; - } - return S_cas_success; -} - // // casDGClient::~casDGClient() // (virtual destructor) @@ -141,12 +68,16 @@ void casDGClient::destroy() // // casDGClient::show() // -void casDGClient::show(unsigned level) const +void casDGClient::show (unsigned level) const { this->casClient::show(level); printf("casDGClient at %p\n", this); - this->dgInBuf::show(level); - this->dgOutBuf::show(level); + if (level>=1u) { + char buf[64]; + this->clientHostName (buf, sizeof(buf)); + printf ("Client Host=%s\n", buf); + } + this->inBuf::show(level); } // @@ -159,7 +90,7 @@ caStatus casDGClient::searchAction() const char *pChanName = (const char *) dp; caStatus status; - if (this->ctx.getServer()->getDebugLevel()>2u) { + if (this->getCAS().getDebugLevel()>2u) { char pName[64u]; this->clientHostName (pName, sizeof (pName)); printf("%s is searching for \"%s\"\n", pName, pChanName); @@ -182,7 +113,7 @@ caStatus casDGClient::searchAction() // this->asyncIOFlag = 0u; pvExistReturn pver = - (*this->ctx.getServer())->pvExistTest(this->ctx, pChanName); + this->getCAS()->pvExistTest(this->ctx, pChanName); // // prevent problems when they initiate @@ -190,158 +121,167 @@ caStatus casDGClient::searchAction() // indicating so (and vise versa) // if (this->asyncIOFlag) { - pver = pverAsyncCompletion; + if (pver.getStatus()!=pverAsyncCompletion) { + errMessage (S_cas_badParameter, + "- assuming asynch IO status from caServer::pvExistTest()"); + } + status = S_cas_success; } - else if (pver.getStatus() == pverAsyncCompletion) { - pver = pverDoesNotExistHere; - errMessage(S_cas_badParameter, - "- expected asynch IO status from caServer::pvExistTest()"); + else { + // + // otherwise we assume sync IO operation was initiated + // + switch (pver.getStatus()) { + case pverExistsHere: + status = this->searchResponse (*mp, pver); + break; + + case pverDoesNotExistHere: + status = S_cas_success; + break; + + case pverAsyncCompletion: + errMessage (S_cas_badParameter, + "- unexpected asynch IO status from caServer::pvExistTest() ignored"); + status = S_cas_success; + break; + + default: + errMessage (S_cas_badParameter, + "- invalid return from caServer::pvExistTest() ignored"); + status = S_cas_success; + break; + } } - - // - // otherwise we assume sync IO operation was initiated - // - switch (pver.getStatus()) { - case pverDoesNotExistHere: - case pverAsyncCompletion: - status = S_cas_success; - break; - - case pverExistsHere: - status = this->searchResponse(*mp, pver); - break; - - default: - status = S_cas_badParameter; - break; - } - - return status; + return status; } - // // caStatus casDGClient::searchResponse() // caStatus casDGClient::searchResponse(const caHdr &msg, - const pvExistReturn &retVal) + const pvExistReturn &retVal) { - caStatus status; - caHdr *search_reply; - unsigned short *pMinorVersion; - - // - // normal search failure is ignored - // - if (retVal.getStatus()==pverDoesNotExistHere) { - return S_cas_success; - } - - if (retVal.getStatus()!=pverExistsHere) { - fprintf(stderr, -"async exist completion with invalid return code \"pverAsynchCompletion\"?\n"); - return S_cas_success; - } - - // - // if we dont have a virtual out msg io pointer - // then ignore the request - // - if (!this->pOutMsgIO) { - return S_cas_success; - } - - /* - * starting with V4.1 the count field is used (abused) - * by the client to store the minor version number of - * the client. - * - * Old versions expect alloc of channel in response - * to a search request. This is no longer supported. - */ - if ( !CA_V44(CA_PROTOCOL_VERSION,msg.m_count) ) { - if (this->ctx.getServer()->getDebugLevel()>0u) { - char pName[64u]; - this->clientHostName (pName, sizeof (pName)); - printf("client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n", pName); - } - // - // 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(&msg, ECA_DEFUNCT, - "R3.11 connect sequence from old client was ignored"); - return status; - } - - /* - * obtain space for the reply message - */ - status = this->allocMsg(sizeof(*pMinorVersion), &search_reply); - if (status) { - return status; - } - - - *search_reply = msg; - search_reply->m_postsize = sizeof(*pMinorVersion); - /* - * cid field is abused to carry the IP - * address in CA_V48 or higher - * (this allows a CA servers to serve - * as a directory service) - * - * type field is abused to carry the IP - * port number here CA_V44 or higher - * (this allows multiple CA servers on one - * host) - */ - if (CA_V48(CA_PROTOCOL_VERSION,msg.m_count)) { - if (retVal.addrIsValid()) { - caNetAddr addr = retVal.getAddr(); - struct sockaddr_in ina = addr.getSockIP(); - search_reply->m_cid = ntohl (ina.sin_addr.s_addr); - if (ina.sin_port==0u) { - // - // If they dont specify a port number then the default - // CA server port is assumed when it it is a server - // address redirect (it is never correct to use this - // server's port when it is a redirect). - // - search_reply->m_type = CA_SERVER_PORT; - } - else { - search_reply->m_type = ntohs (ina.sin_port); - } - } - else { - search_reply->m_cid = ~0U; - search_reply->m_type = this->pOutMsgIO->serverPortNumber(); - } - } - else { - search_reply->m_cid = ~0U; - search_reply->m_type = this->pOutMsgIO->serverPortNumber(); - } - - search_reply->m_count = 0ul; - - /* - * Starting with CA V4.1 the minor version number - * is appended to the end of each search reply. - * This value is ignored by earlier clients. - */ - pMinorVersion = (unsigned short *) (search_reply+1); - *pMinorVersion = htons (CA_MINOR_VERSION); - - this->commitMsg(); - - return S_cas_success; + caStatus status; + caHdr *search_reply; + struct sockaddr_in ina; + unsigned short *pMinorVersion; + + // + // normal search failure is ignored + // + if (retVal.getStatus()==pverDoesNotExistHere) { + return S_cas_success; + } + + if (retVal.getStatus()!=pverExistsHere) { + fprintf(stderr, + "async exist completion with invalid return code \"pverAsynchCompletion\"?\n"); + return S_cas_success; + } + + // + // starting with V4.1 the count field is used (abused) + // by the client to store the minor version number of + // the client. + // + // Old versions expect alloc of channel in response + // to a search request. This is no longer supported. + // + if ( !CA_V44(CA_PROTOCOL_VERSION,msg.m_count) ) { + if (this->getCAS().getDebugLevel()>0u) { + char pName[64u]; + this->clientHostName (pName, sizeof (pName)); + printf("client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n", pName); + } + // + // 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(&msg, ECA_DEFUNCT, + "R3.11 connect sequence from old client was ignored"); + return status; + } + + // + // obtain space for the reply message + // + status = this->allocMsg(sizeof(*pMinorVersion), &search_reply); + if (status) { + return status; + } + + *search_reply = msg; + search_reply->m_postsize = sizeof(*pMinorVersion); + // + // cid field is abused to carry the IP + // address in CA_V48 or higher + // (this allows a CA servers to serve + // as a directory service) + // + // type field is abused to carry the IP + // port number here CA_V44 or higher + // (this allows multiple CA servers on one + // host) + // + if (CA_V48(CA_PROTOCOL_VERSION,msg.m_count)) { + if (retVal.addrIsValid()) { + caNetAddr addr = retVal.getAddr(); + ina = addr.getSockIP(); + // + // If they dont specify a port number then the default + // CA server port is assumed when it it is a server + // address redirect (it is never correct to use this + // server's port when it is a redirect). + // + if (ina.sin_port==0u) { + ina.sin_port = htons (CA_SERVER_PORT); + } + } + else { + caNetAddr addr = this->serverAddress (); + ina = addr.getSockIP(); + // + // We dont fill in the servers address here + // because the server was not bound to a particular + // interface, and we would need to waste CPU performing + // the following steps to determine the interface that + // will be used: + // + // o connect UDP socket to the destination IP + // o perform a getsockname() call + // o disconnect UDP socket from the destination IP + // + if ( ina.sin_addr.s_addr == INADDR_ANY ) { + ina.sin_addr.s_addr = ntohl(~0U); + } + } + search_reply->m_cid = ntohl (ina.sin_addr.s_addr); + search_reply->m_type = ntohs (ina.sin_port); + } + else { + caNetAddr addr = this->serverAddress (); + struct sockaddr_in ina = addr.getSockIP(); + search_reply->m_cid = ~0U; + search_reply->m_type = ntohs (ina.sin_port); + } + + search_reply->m_count = 0ul; + + // + // Starting with CA V4.1 the minor version number + // is appended to the end of each search reply. + // This value is ignored by earlier clients. + // + pMinorVersion = (unsigned short *) (search_reply+1); + *pMinorVersion = htons (CA_MINOR_VERSION); + + this->commitMsg(); + + return S_cas_success; } - - // // casDGClient::searchFailResponse() // (only when requested by the client @@ -366,12 +306,11 @@ caStatus casDGClient::searchFailResponse(const caHdr *mp) return S_cas_success; } - // // casDGClient::sendBeacon() // (implemented here because this has knowledge of the protocol) // -void casDGClient::sendBeacon(casDGIntfIO &io) +void casDGClient::sendBeacon () { union { caHdr msg; @@ -387,163 +326,232 @@ void casDGClient::sendBeacon(casDGIntfIO &io) // // send it to all addresses on the beacon list // - io.sendBeacon(buf, sizeof(msg), msg.m_available, msg.m_count); + this->sendBeaconIO(buf, sizeof(msg), msg.m_available, msg.m_count); } // -// casDGClient::ioBlockedSignal() +// casDGClient::xSend() // -void casDGClient::ioBlockedSignal() +outBuf::flushCondition casDGClient::xSend (char *pBufIn, + bufSizeT nBytesAvailableToSend, bufSizeT nBytesNeedToBeSent, + bufSizeT &nBytesSent) { - // - // NOOP - // - // The DG client never blocks - if we exceed the - // max simultaneous io in progress limit - // then we discard the current request - // (the client will resend later) - // + outBuf::flushCondition stat; + bufSizeT totalBytes; + char *pBuf = pBufIn; + cadg *pHdr; + + assert (nBytesAvailableToSend>=nBytesNeedToBeSent); + + totalBytes = 0; + while (1) { + pHdr = reinterpret_cast(&pBuf[totalBytes]); + + assert (totalBytes<=bufSizeT_MAX-pHdr->cadg_nBytes); + assert (totalBytes+pHdr->cadg_nBytes<=nBytesAvailableToSend); + + if (pHdr->cadg_addr.isValid()) { + stat = this->osdSend (reinterpret_cast(pHdr+1), + pHdr->cadg_nBytes-sizeof(*pHdr), pHdr->cadg_addr); + if (stat!=outBuf::flushProgress) { + break; + } + } + + totalBytes += pHdr->cadg_nBytes; + + if (totalBytes>=nBytesNeedToBeSent) { + break; + } + } + + if (totalBytes) { + // + // !! this time fetch may be slowing things down !! + // + //this->lastSendTS = osiTime::getCurrent(); + nBytesSent = totalBytes; + return outBuf::flushProgress; + } + else { + return outBuf::flushNone; + } } // -// casDGClient::processDG() +// casDGClient::xRecv () // -void casDGClient::processDG(casDGIntfIO &inMsgIO, casDGIntfIO &outMsgIO) +inBuf::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRecv, + fillParameter parm, bufSizeT &nByesRecv) { - caStatus status; - - // - // !! special locking required here in mt case - // - // - // force all replies to be sent to the client - // that made the request - // - this->pInMsgIO = &inMsgIO; - this->pOutMsgIO = &outMsgIO; - this->inBuf::clear(); - this->outBuf::clear(); + const char *pAfter = pBufIn + nBytesToRecv; + char *pBuf = pBufIn; + bufSizeT nDGBytesRecv; + inBuf::fillCondition stat; + cadg *pHdr; - // - // read in new input - // - if (this->fill() != casFillDisconnect) { + while (pAfter-pBuf >= MAX_UDP+sizeof(cadg)) { + pHdr = reinterpret_cast(pBuf); + stat = this->osdRecv (reinterpret_cast(pHdr+1), MAX_UDP, parm, + nDGBytesRecv, pHdr->cadg_addr); + if (stat==casFillProgress) { + pHdr->cadg_nBytes = nDGBytesRecv + sizeof(*pHdr); + pBuf += pHdr->cadg_nBytes; + // + // !! this time fetch may be slowing things down !! + // + //this->lastRecvTS = osiTime::getCurrent(); + } + else { + break; + } + } - // - // verify that we have a message to process - // - if (this->inBuf::bytesPresent()>0u) { - this->setRecipient(this->getSender()); - - // - // process the message - // - status = this->processMsg(); - if (status) { - char pName[64u]; - this->clientHostName (pName, sizeof (pName)); - errPrintf (status, __FILE__, __LINE__, - "- bad stateless protocol from \"%s\"", pName); - } - // - // force all replies to go to the sender - // - if (this->outBuf::bytesPresent()>0u) { - casVerify (this->flush()==casFlushCompleted); - } - } - } - - // - // clear the input/output buffers so replies - // are always sent to the sender of the request - // - this->pInMsgIO = NULL; - this->pOutMsgIO = NULL; - this->inBuf::clear(); - this->outBuf::clear(); + nDGBytesRecv = pBuf - pBufIn; + if (nDGBytesRecv) { + nByesRecv = nDGBytesRecv; + return casFillProgress; + } + else { + return casFillNone; + } } // // casDGClient::asyncSearchResp() // -caStatus casDGClient::asyncSearchResponse( - casDGIntfIO &outMsgIO, const caNetAddr &outAddr, +// +// this results in many small UDP frames which unfortunately +// isnt particularly efficient +// +caStatus casDGClient::asyncSearchResponse (const caNetAddr &outAddr, const caHdr &msg, const pvExistReturn &retVal) { caStatus stat; - // - // !! special locking required here in mt case - // - this->pOutMsgIO = &outMsgIO; - this->dgOutBuf::clear(); - this->setRecipient(outAddr); + // + // start a DG context in the output protocol stream + // and grab the send lock + // + void *pRaw; + const outBufCtx outctx = this->outBuf::pushCtx + (sizeof(cadg), MAX_UDP, pRaw); + if (outctx.pushResult()!=outBufCtx::pushCtxSuccess) { + return S_cas_sendBlocked; + } - stat = this->searchResponse(msg, retVal); + cadg *pRespHdr = reinterpret_cast(pRaw); + stat = this->searchResponse (msg, retVal); - this->dgOutBuf::flush(); - this->dgOutBuf::clear(); - this->pOutMsgIO = NULL; + pRespHdr->cadg_nBytes = this->outBuf::popCtx (outctx); + if (pRespHdr->cadg_nBytes>0) { + pRespHdr->cadg_addr = outAddr; + this->outBuf::commitRawMsg (pRespHdr->cadg_nBytes); + } return stat; } // -// casDGClient::xDGSend() +// casDGClient::processDG () // -xSendStatus casDGClient::xDGSend (char *pBufIn, bufSizeT nBytesNeedToBeSent, - bufSizeT &nBytesSent, const caNetAddr &recipient) +caStatus casDGClient::processDG () { - xSendStatus stat; + bufSizeT bytesLeft; + caStatus status; + + status = S_cas_success; + while (bytesLeft = this->inBuf::bytesPresent()) { + bufSizeT dgInBytesConsumed; + const cadg *pReqHdr = reinterpret_cast(this->inBuf::msgPtr ()); - if (!this->pOutMsgIO) { - return xSendDisconnect; - } - stat = this->pOutMsgIO->osdSend(pBufIn, nBytesNeedToBeSent, - nBytesSent, recipient); - if (stat==xSendOK) { - // - // !! this time fetch may be slowing things down !! - // - this->lastSendTS = osiTime::getCurrent(); - } - return stat; -} + if (bytesLeftinBuf::removeMsg (bytesLeft); + ca_printf ("casDGClient::processMsg: incomplete DG header?"); + status = S_cas_internal; + break; + } -// -// casDGClient::xDGRecv() -// -xRecvStatus casDGClient::xDGRecv (char *pBufIn, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv, caNetAddr &sender) -{ - xRecvStatus stat; + // + // start a DG context in the output protocol stream + // and grab the send lock + // + void *pRaw; + const outBufCtx outctx = this->outBuf::pushCtx (sizeof(cadg), MAX_UDP, pRaw); + if ( outctx.pushResult() != outBufCtx::pushCtxSuccess ) { + status = S_cas_sendBlocked; + break; + } + + cadg *pRespHdr = reinterpret_cast (pRaw); + + // + // select the next DG in the input stream and start processing it + // + const bufSizeT reqBodySize = pReqHdr->cadg_nBytes-sizeof (*pReqHdr); + const inBufCtx inctx = this->inBuf::pushCtx (sizeof (*pReqHdr), reqBodySize); + if ( inctx.pushResult() != inBufCtx::pushCtxSuccess ) { + this->inBuf::removeMsg (bytesLeft); + this->outBuf::popCtx (outctx); + ca_printf ("casDGClient::processMsg: incomplete DG?\n"); + status = S_cas_internal; + break; + } - if (!this->pInMsgIO) { - return xRecvDisconnect; - } - stat = this->pInMsgIO->osdRecv(pBufIn, nBytesToRecv, - nByesRecv, sender); - if (stat==xRecvOK) { - // - // !! this time fetch may be slowing things down !! - // - this->lastRecvTS = osiTime::getCurrent(); - } - return stat; -} + this->lastRecvAddr = pReqHdr->cadg_addr; -// -// casDGClient::incommingBytesPresent() -// -bufSizeT casDGClient::incommingBytesPresent() const -{ - // - // !!!! perhaps this would run faster if we - // !!!! checked to see if UDP frames are in - // !!!! the queue from the same client - // - return 0u; + status = this->processMsg (); + dgInBytesConsumed = this->inBuf::popCtx (inctx); + if (dgInBytesConsumed>0) { + + // + // at this point processMsg() bailed out because: + // a) it used all of the incoming DG or + // b) it used all of the outgoing DG + // + // In either case commit the DG to the protocol stream and + // release the send lock + // + pRespHdr->cadg_nBytes = this->outBuf::popCtx (outctx) + sizeof(*pRespHdr); + if (pRespHdr->cadg_nBytes>sizeof(*pRespHdr)) { + pRespHdr->cadg_addr = pReqHdr->cadg_addr; + this->outBuf::commitRawMsg (pRespHdr->cadg_nBytes); + } + + // + // check to see that all of the incoming UDP frame was used + // + if (dgInBytesConsumedinBuf::removeMsg (dgInBytesConsumed); + + // + // slide the UDP header forward and correct the byte count + // + { + cadg *pReqHdrMove; + cadg copy = *pReqHdr; + pReqHdrMove = reinterpret_cast (this->inBuf::msgPtr ()); + pReqHdrMove->cadg_addr = copy.cadg_addr; + pReqHdrMove->cadg_nBytes = copy.cadg_nBytes - dgInBytesConsumed; + } + } + else { + // + // remove the header and all of the body + // + this->inBuf::removeMsg ( pReqHdr->cadg_nBytes ); + } + } + + if (status!=S_cas_success) { + break; + } + } + return status; } // @@ -555,18 +563,17 @@ unsigned casDGClient::getDebugLevel() const } // -// casDGClient::fetchRespAddr() +// casDGClient::fetchLastRecvAddr () // -caNetAddr casDGClient::fetchRespAddr() +caNetAddr casDGClient::fetchLastRecvAddr () const { - return this->getRecipient(); -} - -// -// casDGClient::fetchOutIntf() -// -casDGIntfIO* casDGClient::fetchOutIntf() -{ - return this->pOutMsgIO; + return this->lastRecvAddr; } +// +// casDGClient::clientHostName() +// +void casDGClient::clientHostName (char *pBufIn, unsigned bufSizeIn) const +{ + this->lastRecvAddr.stringConvert (pBufIn, bufSizeIn); +} diff --git a/src/cas/generic/casEventMask.cc b/src/cas/generic/casEventMask.cc index 1f435363f..f4317b1e3 100644 --- a/src/cas/generic/casEventMask.cc +++ b/src/cas/generic/casEventMask.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.14 1999/08/09 20:18:43 jhill + * back out stringIdentifier class + * * Revision 1.13 1999/08/07 01:02:31 jhill * solaris compiler issues * @@ -126,11 +129,9 @@ casEventMask casEventRegistry::maskAllocator() { casEventMask evMask; - this->mutex.osiLock(); if (this->allocatorallocator++); } - this->mutex.osiUnlock(); return evMask; } @@ -147,7 +148,6 @@ casEventMask casEventRegistry::registerEvent(const char *pName) casEventMaskEntry *pEntry; casEventMask mask; - this->mutex.osiLock(); pEntry = this->lookup (id); if (pEntry) { mask = *pEntry; @@ -155,7 +155,7 @@ casEventMask casEventRegistry::registerEvent(const char *pName) else { mask = this->maskAllocator(); if (mask.mask == 0u) { - errMessage(S_cas_tooManyEvents, NULL); + errMessage (S_cas_tooManyEvents, NULL); } else { pEntry = new casEventMaskEntry(*this, mask, pName); @@ -166,10 +166,10 @@ casEventMask casEventRegistry::registerEvent(const char *pName) mask.mask = 0u; errMessage(S_cas_noMemory, "mask bit was lost during init"); + throw S_cas_noMemory; } } } - this->mutex.osiUnlock(); return mask; } @@ -193,13 +193,11 @@ casEventMask::casEventMask (casEventRegistry ®, const char *pName) // void casEventRegistry::show(unsigned level) const { - this->mutex.osiLock(); if (level>1u) { printf ("casEventRegistry: bit allocator = %d\n", this->allocator); } this->resTable ::show(level); - this->mutex.osiUnlock(); } // diff --git a/src/cas/generic/casEventMask.h b/src/cas/generic/casEventMask.h index 858b264e2..f6c4ee129 100644 --- a/src/cas/generic/casEventMask.h +++ b/src/cas/generic/casEventMask.h @@ -26,28 +26,6 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.6 1997/08/05 00:47:08 jhill - * fixed warnings - * - * Revision 1.5 1997/04/10 19:34:08 jhill - * API changes - * - * Revision 1.4 1996/12/11 01:02:35 jhill - * removed casEventMaskEntry def - * - * Revision 1.3 1996/12/06 22:32:10 jhill - * force virtual destructor - * - * Revision 1.2 1996/11/02 00:54:11 jhill - * many improvements - * - * Revision 1.1.1.1 1996/06/20 00:28:16 jhill - * ca server installation - * - * */ @@ -59,44 +37,44 @@ class casEventRegistry; class epicsShareClass casEventMask { - friend inline casEventMask operator| (const casEventMask &lhs, - const casEventMask &rhs); - friend inline casEventMask operator& (const casEventMask &lhs, - const casEventMask &rhs); - friend inline int operator== (const casEventMask &lhs, - const casEventMask &rhs); - friend inline int operator!= (const casEventMask &lhs, - const casEventMask &rhs); - friend class casEventRegistry; + friend inline casEventMask operator| (const casEventMask &lhs, + const casEventMask &rhs); + friend inline casEventMask operator& (const casEventMask &lhs, + const casEventMask &rhs); + friend inline int operator== (const casEventMask &lhs, + const casEventMask &rhs); + friend inline int operator!= (const casEventMask &lhs, + const casEventMask &rhs); + friend class casEventRegistry; public: - void clear () - { - this->mask = 0u; - } - - casEventMask (casEventRegistry ®, const char *pName); - - casEventMask () - { - this->clear(); - } - - void show (unsigned level) const; - - int eventsSelected() - { - return this->mask!=0u; - } - int noEventsSelected() - { - return this->mask==0u; - } - - inline void operator|= (const casEventMask &rhs); - inline void operator&= (const casEventMask &rhs); - + void clear () + { + this->mask = 0u; + } + + casEventMask (casEventRegistry ®, const char *pName); + + casEventMask () + { + this->clear(); + } + + void show (unsigned level) const; + + int eventsSelected() + { + return this->mask!=0u; + } + int noEventsSelected() + { + return this->mask==0u; + } + + inline void operator|= (const casEventMask &rhs); + inline void operator&= (const casEventMask &rhs); + private: - unsigned mask; + unsigned mask; }; inline casEventMask operator| (const casEventMask &lhs, const casEventMask &rhs) diff --git a/src/cas/generic/casEventSys.cc b/src/cas/generic/casEventSys.cc index ad585c489..1247e9070 100644 --- a/src/cas/generic/casEventSys.cc +++ b/src/cas/generic/casEventSys.cc @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.9 1999/04/30 15:33:46 jhill + * better message + * * Revision 1.8 1998/07/23 16:48:15 jhill * eventsOff is no longere a private member * @@ -74,7 +77,6 @@ void casEventSys::show(unsigned level) const { printf ("casEventSys at %p\n", this); if (level>=1u) { - printf ("\thas coreClient at %p\n", &this->coreClient); printf ("\tnumEventBlocks = %u, maxLogEntries = %u\n", this->numEventBlocks, this->maxLogEntries); printf ("\tthere are %d events in the queue\n", @@ -84,7 +86,6 @@ void casEventSys::show(unsigned level) const } } - // // casEventSys::~casEventSys() // @@ -92,7 +93,7 @@ casEventSys::~casEventSys() { casEvent *pE; - this->mutex.osiLock(); + this->mutex.lock(); if (this->pPurgeEvent != NULL) { this->eventLogQue.remove(*this->pPurgeEvent); @@ -108,19 +109,18 @@ casEventSys::~casEventSys() delete pE; } - this->mutex.osiUnlock(); + this->mutex.unlock(); } - // // casEventSys::installMonitor() // void casEventSys::installMonitor() { - this->mutex.osiLock(); + this->mutex.lock(); this->numEventBlocks++; this->maxLogEntries += averageEventEntries; - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -128,14 +128,13 @@ void casEventSys::installMonitor() // void casEventSys::removeMonitor() { - this->mutex.osiLock(); + this->mutex.lock(); assert (this->numEventBlocks>=1u); this->numEventBlocks--; this->maxLogEntries -= averageEventEntries; - this->mutex.osiUnlock(); + this->mutex.unlock(); } - // // casEventSys::process() // @@ -146,7 +145,7 @@ casProcCond casEventSys::process() casProcCond cond = casProcOk; unsigned long nAccepted = 0u; - this->mutex.osiLock(); + this->mutex.lock(); while (!this->dontProcess) { @@ -192,10 +191,10 @@ casProcCond casEventSys::process() * call flush function if they provided one */ if (nAccepted > 0u) { - this->coreClient.eventFlush(); + this->eventFlush (); } - this->mutex.osiUnlock(); + this->mutex.unlock(); // // allows the derived class to be informed that it @@ -218,7 +217,7 @@ casProcCond casEventSys::process() // void casEventSys::eventsOn() { - this->mutex.osiLock(); + this->mutex.lock(); // // allow multiple events for each monitor @@ -239,12 +238,12 @@ void casEventSys::eventsOn() this->pPurgeEvent = NULL; } - this->mutex.osiUnlock(); + this->mutex.unlock(); // // wakes up the event queue consumer // - this->coreClient.eventSignal(); + this->eventSignal (); } // @@ -252,7 +251,7 @@ void casEventSys::eventsOn() // caStatus casEventSys::eventsOff() { - this->mutex.osiLock(); + this->mutex.lock(); // // new events will replace the last event on @@ -280,7 +279,7 @@ caStatus casEventSys::eventsOff() } } - this->mutex.osiUnlock(); + this->mutex.unlock(); return S_cas_success; } @@ -290,10 +289,10 @@ caStatus casEventSys::eventsOff() // caStatus casEventPurgeEv::cbFunc (casEventSys &evSys) { - evSys.mutex.osiLock(); + evSys.mutex.lock(); evSys.dontProcess = TRUE; evSys.pPurgeEvent = NULL; - evSys.mutex.osiUnlock(); + evSys.mutex.unlock(); delete this; diff --git a/src/cas/generic/casEventSysIL.h b/src/cas/generic/casEventSysIL.h index 9eafe8075..cd137eca6 100644 --- a/src/cas/generic/casEventSysIL.h +++ b/src/cas/generic/casEventSysIL.h @@ -29,6 +29,9 @@ * * History * $Log$ + * Revision 1.7 1998/07/08 15:38:05 jhill + * fixed lost monitors during flow control problem + * * Revision 1.6 1998/02/18 22:45:29 jhill * fixed warning * @@ -54,16 +57,10 @@ #ifndef casEventSysIL_h #define casEventSysIL_h -// -// required for casCoreClient::lookupRes() -// -#include "casCoreClientIL.h" - // // casEventSys::casEventSys () // -inline casEventSys::casEventSys (casCoreClient &coreClientIn) : - coreClient(coreClientIn), +inline casEventSys::casEventSys () : pPurgeEvent(NULL), numEventBlocks(0u), maxLogEntries(individualEventEntries), @@ -73,50 +70,34 @@ inline casEventSys::casEventSys (casCoreClient &coreClientIn) : { } -// -// casEventSys::init() -// -inline caStatus casEventSys::init() -{ - return (this->mutex.init() ? S_cas_noMemory : S_cas_success); -} - // // casEventSys::addToEventQueue() // inline void casEventSys::addToEventQueue(casEvent &event) { - this->mutex.osiLock(); + this->mutex.lock(); this->eventLogQue.add(event); - this->mutex.osiUnlock(); + this->mutex.unlock(); // // 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->coreClient.eventSignal(); + this->eventSignal(); } } -// -// casEventSys::getCoreClient -// -inline casCoreClient &casEventSys::getCoreClient() -{ - return this->coreClient; -} - // // casEventSys::setDestroyPending() // -void casEventSys::setDestroyPending() +inline void casEventSys::setDestroyPending() { this->destroyPending = aitTrue; // // wakes up the event queue consumer // - this->coreClient.eventSignal(); + this->eventSignal(); } // @@ -124,9 +105,9 @@ void casEventSys::setDestroyPending() // inline void casEventSys::insertEventQueue(casEvent &insert, casEvent &prevEvent) { - this->mutex.osiLock(); + this->mutex.lock(); this->eventLogQue.insertAfter(insert, prevEvent); - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -134,9 +115,9 @@ inline void casEventSys::insertEventQueue(casEvent &insert, casEvent &prevEvent) // inline void casEventSys::pushOnToEventQueue(casEvent &event) { - this->mutex.osiLock(); + this->mutex.lock(); this->eventLogQue.push(event); - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -144,21 +125,21 @@ inline void casEventSys::pushOnToEventQueue(casEvent &event) // inline void casEventSys::removeFromEventQueue(casEvent &event) { - this->mutex.osiLock(); + this->mutex.lock(); this->eventLogQue.remove(event); - this->mutex.osiUnlock(); + this->mutex.unlock(); } // // casEventSys::full() // -inline aitBool casEventSys::full() +inline bool casEventSys::full() { if (this->replaceEvents || this->eventLogQue.count()>=this->maxLogEntries) { - return aitTrue; + return true; } else { - return aitFalse; + return false; } } @@ -167,7 +148,7 @@ inline aitBool casEventSys::full() // inline casMonitor *casEventSys::resIdToMon(const caResId id) { - casRes *pRes = this->coreClient.lookupRes(id, casClientMonT); + casRes *pRes = this->lookupRes (id, casClientMonT); // // safe to cast because we have checked the type code above diff --git a/src/cas/generic/casInternal.h b/src/cas/generic/casInternal.h index d37f60eb5..d1cc9997f 100644 --- a/src/cas/generic/casInternal.h +++ b/src/cas/generic/casInternal.h @@ -27,72 +27,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.21 1999/08/04 23:54:51 jhill - * chronIntIdRes name change - * - * Revision 1.20 1999/04/30 15:37:31 jhill - * doc - * - * Revision 1.19 1998/12/19 00:04:51 jhill - * renamed createPV() to pvAttach() - * - * Revision 1.18 1998/11/18 18:52:49 jhill - * fixed casChannelI undefined symbols on WIN32 - * - * Revision 1.17 1998/10/23 00:28:20 jhill - * fixed HP-UX warnings - * - * Revision 1.16 1998/07/08 15:38:05 jhill - * fixed lost monitors during flow control problem - * - * Revision 1.15 1998/06/16 02:26:09 jhill - * allow PVs to exist without a server - * - * Revision 1.14 1998/02/05 22:56:12 jhill - * cosmetic - * - * Revision 1.13 1997/08/05 00:47:09 jhill - * fixed warnings - * - * Revision 1.12 1997/06/13 09:15:58 jhill - * connect proto changes - * - * Revision 1.11 1997/04/10 19:34:10 jhill - * API changes - * - * Revision 1.10 1997/01/10 21:17:55 jhill - * code around gnu g++ inline bug when -O isnt used - * - * Revision 1.9 1996/12/06 22:33:49 jhill - * virtual ~casPVI(), ~casPVListChan(), ~casChannelI() - * - * Revision 1.8 1996/11/02 00:54:14 jhill - * many improvements - * - * Revision 1.7 1996/09/16 18:24:02 jhill - * vxWorks port changes - * - * Revision 1.6 1996/09/04 20:21:41 jhill - * removed operator -> and added member pv - * - * Revision 1.5 1996/07/01 19:56:11 jhill - * one last update prior to first release - * - * Revision 1.4 1996/06/26 23:32:17 jhill - * changed where caProto.h comes from (again) - * - * Revision 1.3 1996/06/26 21:18:54 jhill - * now matches gdd api revisions - * - * Revision 1.2 1996/06/20 18:08:35 jhill - * changed where caProto.h comes from - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * */ // @@ -113,8 +47,8 @@ class casChannelI; // class casEvent : public tsDLNode { public: - virtual ~casEvent(); - virtual caStatus cbFunc(casEventSys &)=0; + virtual ~casEvent(); + virtual caStatus cbFunc (casEventSys &)=0; private: }; @@ -152,7 +86,7 @@ public: virtual ~ioBlocked (); private: ioBlockedList *pList; - virtual void ioBlockedSignal (); + virtual void ioBlockedSignal () = 0; }; // @@ -286,7 +220,6 @@ class casCoreClient; class casChannelI; class casCtx; class caServer; -class casAsyncIO; class casAsyncReadIO; class casAsyncWriteIO; class casAsyncPVExistIO; @@ -294,31 +227,24 @@ class casAsyncPVAttachIO; class casAsyncIOI : public casEvent, public tsDLNode { public: - casAsyncIOI (casCoreClient &client, casAsyncIO &ioExternal); + casAsyncIOI (casCoreClient &client); virtual ~casAsyncIOI(); + void serverDestroyIfReadOP (); + void serverDestroy (); + + caServer *getCAS() const; + +protected: + casCoreClient &client; + // // place notification of IO completion on the event queue // caStatus postIOCompletionI(); - inline void lock(); - inline void unlock(); - - virtual caStatus cbFuncAsyncIO()=0; - epicsShareFunc virtual int readOP(); - - void destroyIfReadOP(); - - caServer *getCAS() const; - - inline void destroy(); - - void reportInvalidAsynchIO(unsigned); - -protected: - casCoreClient &client; - casAsyncIO &ioExternal; + void lock(); + void unlock(); private: unsigned inTheEventQueue:1; @@ -326,110 +252,24 @@ private: unsigned ioComplete:1; unsigned serverDelete:1; unsigned duplicate:1; + // // casEvent virtual call back function // (called when IO completion event reaches top of event queue) // epicsShareFunc caStatus cbFunc(casEventSys &); - inline casAsyncIO * operator -> (); + // + // 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; }; -// -// casAsyncRdIOI -// -// (server internal asynchronous read IO class) -// -class casAsyncRdIOI : public casAsyncIOI { -public: - epicsShareFunc casAsyncRdIOI(const casCtx &ctx, casAsyncReadIO &ioIn); - virtual ~casAsyncRdIOI(); - - void destroyIfReadOP(); - - epicsShareFunc caStatus cbFuncAsyncIO(); - casAsyncIO &getAsyncIO(); - - epicsShareFunc caStatus postIOCompletion(caStatus completionStatus, - gdd &valueRead); - epicsShareFunc int readOP(); -private: - caHdr const msg; - casChannelI &chan; - smartGDDPointer pDD; - caStatus completionStatus; -}; - -// -// casAsyncWtIOI -// -// (server internal asynchronous write IO class) -// -class casAsyncWtIOI : public casAsyncIOI { -public: - epicsShareFunc casAsyncWtIOI(const casCtx &ctx, casAsyncWriteIO &ioIn); - virtual ~casAsyncWtIOI(); - - // - // place notification of IO completion on the event queue - // - epicsShareFunc caStatus postIOCompletion(caStatus completionStatus); - - epicsShareFunc caStatus cbFuncAsyncIO(); - casAsyncIO &getAsyncIO(); -private: - caHdr const msg; - casChannelI &chan; - caStatus completionStatus; -}; - -class casDGIntfIO; - -// -// casAsyncExIOI -// -// (server internal asynchronous PV exist test IO class) -// -class casAsyncExIOI : public casAsyncIOI { -public: - epicsShareFunc casAsyncExIOI(const casCtx &ctx, casAsyncPVExistIO &ioIn); - virtual ~casAsyncExIOI(); - - // - // place notification of IO completion on the event queue - // - epicsShareFunc caStatus postIOCompletion(const pvExistReturn &retVal); - - epicsShareFunc caStatus cbFuncAsyncIO(); - casAsyncIO &getAsyncIO(); -private: - caHdr const msg; - pvExistReturn retVal; - casDGIntfIO * const pOutDGIntfIO; - const caNetAddr dgOutAddr; -}; - -// -// casAsyncAtIOI -// -// (server internal asynchronous PV attach IO class) -// -class casAsyncAtIOI : public casAsyncIOI { -public: - epicsShareFunc casAsyncAtIOI(const casCtx &ctx, casAsyncPVAttachIO &ioIn); - virtual ~casAsyncAtIOI(); - - // - // place notification of IO completion on the event queue - // - epicsShareFunc caStatus postIOCompletion(const pvAttachReturn &retVal); - - epicsShareFunc caStatus cbFuncAsyncIO(); - casAsyncIO &getAsyncIO(); -private: - caHdr const msg; - pvAttachReturn retVal; -}; +class casDGClient; class casChannel; class casPVI; @@ -443,31 +283,31 @@ class casPVI; class casChannelI : public tsDLNode, public casRes, public casEvent { public: - casChannelI (const casCtx &ctx, casChannel &chanAdapter); + casChannelI (const casCtx &ctx); virtual ~casChannelI(); - casCoreClient &getClient() const + casCoreClient &getClient () const { return this->client; } - const caResId getCID() + const caResId getCID () { return this->cid; } // // fetch the unsigned integer server id for this PV // - inline const caResId getSID(); + const caResId getSID (); // // addMonitor() // - inline void addMonitor(casMonitor &mon); + void addMonitor (casMonitor &mon); // // deleteMonitor() // - inline void deleteMonitor(casMonitor &mon); + void deleteMonitor (casMonitor &mon); // // findMonitor @@ -475,48 +315,54 @@ public: // sane clients will require only one or two monitors // per channel) // - inline casMonitor *findMonitor(const caResId clientIdIn); + casMonitor *findMonitor (const caResId clientIdIn); - casPVI &getPVI() const + casPVI &getPVI () const { return this->pv; } - inline void installAsyncIO(casAsyncIOI &); - inline void removeAsyncIO(casAsyncIOI &); + void installAsyncIO (casAsyncIOI &); + void removeAsyncIO (casAsyncIOI &); - inline void postEvent (const casEventMask &select, gdd &event); + void postEvent (const casEventMask &select, gdd &event); - epicsShareFunc virtual casResType resourceType() const; + epicsShareFunc virtual casResType resourceType () const; - virtual void show (unsigned level) const; + void lock () const; + void unlock () const; - virtual void destroy(); + void destroyNoClientNotify (); + void destroyClientNotify (); - inline void lock() const; - inline void unlock() const; - - inline void clientDestroy(); - - inline casChannel * operator -> () const; - - void clearOutstandingReads(); + void clearOutstandingReads (); // // access rights event call back // - epicsShareFunc caStatus cbFunc(casEventSys &); + epicsShareFunc caStatus cbFunc (casEventSys &); + + void postAccessRightsEvent (); + + // + // 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; - inline void postAccessRightsEvent(); protected: - tsDLList monitorList; - tsDLList ioInProgList; - casCoreClient &client; - casPVI &pv; - casChannel &chan; + tsDLList monitorList; + tsDLList ioInProgList; + casCoreClient &client; + casPVI &pv; caResId const cid; // client id - unsigned clientDestroyPending:1; - unsigned accessRightsEvPending:1; + unsigned accessRightsEvPending:1; + + epicsShareFunc virtual void destroy (); }; // @@ -525,7 +371,7 @@ protected: class casPVListChan : public casChannelI, public tsDLNode { public: - casPVListChan (const casCtx &ctx, casChannel &chanAdapter); + casPVListChan (const casCtx &ctx); virtual ~casPVListChan(); }; @@ -538,84 +384,95 @@ 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 tsSLNode, // server resource table installation +public casRes, // server resource table installation +public ioBlockedList // list of clients io blocked on this pv { public: - casPVI (casPV &pvAdapter); - virtual ~casPVI(); - - // - // for use by the server library - // - inline caServerI *getPCAS() const; - - // - // attach to a server - // - caStatus attachToServer (caServerI &cas); - - // - // CA only does 1D arrays for now (and the new server - // temporarily does only scalars) - // - inline aitIndex nativeCount(); - - // - // only for use by casMonitor - // - caStatus registerEvent (); - void unregisterEvent (); - - // - // only for use by casAsyncIOI - // - inline void unregisterIO(); - - // - // only for use by casChannelI - // - inline void installChannel(casPVListChan &chan); - - // - // only for use by casChannelI - // - inline void removeChannel(casPVListChan &chan); - - // - // check for none attached and delete self if so - // - inline void deleteSignal(); - - inline void postEvent (const casEventMask &select, gdd &event); - - inline casPV *interfaceObjectPointer() const; - - caServer *getExtServer() const; - - // - // bestDBRType() - // - inline caStatus bestDBRType (unsigned &dbrType); - - inline casPV * operator -> () const; - - epicsShareFunc virtual casResType resourceType() const; - - virtual void show(unsigned level) const; - - virtual void destroy(); + casPVI (); + virtual ~casPVI (); + + // + // for use by the server library + // + caServerI *getPCAS () const; + + // + // attach to a server + // + caStatus attachToServer (caServerI &cas); + + // + // CA only does 1D arrays for now (and the new server + // temporarily does only scalars) + // + aitIndex nativeCount (); + + // + // only for use by casMonitor + // + caStatus registerEvent (); + void unregisterEvent (); + + // + // only for use by casAsyncIOI + // + void unregisterIO (); + + // + // only for use by casChannelI + // + void installChannel (casPVListChan &chan); + + // + // only for use by casChannelI + // + void removeChannel (casPVListChan &chan); + + // + // check for none attached and delete self if so + // + void deleteSignal (); + + void postEvent (const casEventMask &select, gdd &event); + + caServer *getExtServer () const; + + // + // bestDBRType() + // + caStatus bestDBRType (unsigned &dbrType); + + epicsShareFunc virtual casResType resourceType () const; + + // + // 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, 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 chanList; - caServerI *pCAS; - casPV &pv; - unsigned nMonAttached; - unsigned nIOAttached; - unsigned destroyInProgress:1; + tsDLList chanList; + caServerI *pCAS; + unsigned nMonAttached; + unsigned nIOAttached; + + inline void lock () const; + inline void unlock () const; - inline void lock() const; - inline void unlock() const; + + epicsShareFunc virtual void destroy (); // casPVI destructor noop }; diff --git a/src/cas/generic/casMonitor.cc b/src/cas/generic/casMonitor.cc index 8c3742c3f..011f82822 100644 --- a/src/cas/generic/casMonitor.cc +++ b/src/cas/generic/casMonitor.cc @@ -27,35 +27,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.9 1998/06/16 02:29:57 jhill - * use smart gdd ptr - * - * Revision 1.8 1997/05/05 04:50:11 jhill - * moved pLog = NULL down - * - * Revision 1.7 1997/04/10 19:34:12 jhill - * API changes - * - * Revision 1.6 1996/11/02 00:54:18 jhill - * many improvements - * - * Revision 1.5 1996/09/16 18:24:03 jhill - * vxWorks port changes - * - * Revision 1.4 1996/07/24 22:00:49 jhill - * added pushOnToEventQueue() - * - * Revision 1.3 1996/07/01 19:56:11 jhill - * one last update prior to first release - * - * Revision 1.2 1996/06/26 21:18:56 jhill - * now matches gdd api revisions - * - * Revision 1.1.1.1 1996/06/20 00:28:16 jhill - * ca server installation - * * */ @@ -100,7 +71,7 @@ casMonitor::~casMonitor() { casCoreClient &client = this->ciu.getClient(); - this->mutex.osiLock(); + this->mutex.lock(); this->disable(); @@ -113,7 +84,7 @@ casMonitor::~casMonitor() this->ciu.deleteMonitor(*this); - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -123,8 +94,8 @@ void casMonitor::enable() { caStatus status; - this->mutex.osiLock(); - if (!this->enabled && this->ciu->readAccess()) { + this->mutex.lock(); + if (!this->enabled && this->ciu.readAccess()) { this->enabled = TRUE; status = this->ciu.getPVI().registerEvent(); if (status) { @@ -132,7 +103,7 @@ void casMonitor::enable() "Server tool failed to register event\n"); } } - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -140,12 +111,12 @@ void casMonitor::enable() // void casMonitor::disable() { - this->mutex.osiLock(); + this->mutex.lock(); if (this->enabled) { this->enabled = FALSE; this->ciu.getPVI().unregisterEvent(); } - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -157,7 +128,7 @@ void casMonitor::push(gdd &newValue) casMonEvent *pLog; char full; - this->mutex.osiLock(); + this->mutex.lock(); // // get a new block if we havent exceeded quotas @@ -209,7 +180,7 @@ void casMonitor::push(gdd &newValue) client.addToEventQueue(*pLog); - this->mutex.osiUnlock(); + this->mutex.unlock(); } // @@ -223,9 +194,9 @@ caStatus casMonitor::executeEvent(casMonEvent *pEV) pVal = pEV->getValue (); assert (pVal!=NULL); - this->mutex.osiLock(); + this->mutex.lock(); status = this->callBack (*pVal); - this->mutex.osiUnlock(); + this->mutex.unlock(); // // if the event isnt accepted we will try diff --git a/src/cas/generic/casMsgIO.cc b/src/cas/generic/casMsgIO.cc deleted file mode 100644 index 9cfdaa703..000000000 --- a/src/cas/generic/casMsgIO.cc +++ /dev/null @@ -1,206 +0,0 @@ -/* - * $Id$ - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * - * History - * $Log$ - * Revision 1.5 1997/06/13 09:15:59 jhill - * connect proto changes - * - * Revision 1.4 1997/04/10 19:34:13 jhill - * API changes - * - * Revision 1.3 1996/11/02 00:54:19 jhill - * many improvements - * - * Revision 1.2 1996/09/16 18:24:04 jhill - * vxWorks port changes - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * - */ - -#include"server.h" - -class casMsgIO { -public: - casMsgIO(); - virtual ~casMsgIO(); - - osiTime timeOfLastXmit() const; - osiTime timeOfLAstRecv() const; - - // - // show status of IO subsystem - // (cant be const because a lock is taken) - // - void show (unsigned level) const; - - // - // io independent send/recv - // - xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent, - const caNetAddr &addr); - xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv, caNetAddr &addr); - - virtual bufSizeT incommingBytesPresent() const; - virtual casIOState state() const=0; - virtual void clientHostName (char *pBuf, unsigned bufSize) const =0; - virtual int getFD() const; - void setNonBlocking() - { - this->xSetNonBlocking(); - this->blockingStatus = xIsntBlocking; - } - - // - // The server's port number - // (to be used for connection requests) - // - virtual unsigned serverPortNumber()=0; -private: - // - // private data members - // - osiTime lastSendTS; - osiTime lastRecvTS; - xBlockingStatus blockingStatus; - - virtual xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, - bufSizeT &nBytesActual, const caNetAddr &addr) =0; - virtual xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, - bufSizeT &nBytesActual, caNetAddr &addr) =0; - virtual void osdShow (unsigned level) const = 0; - virtual void xSetNonBlocking(); -}; - - -casMsgIO::casMsgIO() -{ - this->lastSendTS = this->lastRecvTS = osiTime::getCurrent (); - this->blockingStatus = xIsBlocking; -} - -casMsgIO::~casMsgIO() -{ -} - -// -// casMsgIO::show(unsigned level) const -// -void casMsgIO::show(unsigned level) const -{ - osiTime current; - double send_delay; - double recv_delay; - - if (level>=1u) { - current = osiTime::getCurrent (); - send_delay = current - this->lastSendTS; - recv_delay = current - this->lastRecvTS; - printf( - "\tSecs since last send %6.2f, Secs since last receive %6.2f\n", - send_delay, recv_delay); - } -} - -// -// casMsgIO::xRecv() -// -xRecvStatus casMsgIO::xRecv(char *pBuf, bufSizeT nBytes, - bufSizeT &nActualBytes, caNetAddr &from) -{ - xRecvStatus stat; - - stat = this->osdRecv(pBuf, nBytes, nActualBytes, from); - if (stat==xRecvOK) { - this->lastRecvTS = osiTime::getCurrent(); - } - return stat; -} - -// -// casMsgIO::xSend() -// -xSendStatus casMsgIO::xSend(char *pBuf, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nActualBytes, - const caNetAddr &to) -{ - xSendStatus stat; - bufSizeT nActualBytesDelta; - - assert (nBytesAvailableToSend>=nBytesNeedToBeSent); - - nActualBytes = 0u; - if (this->blockingStatus == xIsntBlocking) { - stat = this->osdSend(pBuf, nBytesAvailableToSend, - nActualBytes, to); - if (stat == xSendOK) { - this->lastSendTS = osiTime::getCurrent(); - } - return stat; - } - - while (nBytesNeedToBeSent) { - stat = this->osdSend(pBuf, nBytesAvailableToSend, - nActualBytesDelta, to); - if (stat != xSendOK) { - return stat; - } - - this->lastSendTS = osiTime::getCurrent(); - nActualBytes += nActualBytesDelta; - if (nBytesNeedToBeSent>nActualBytesDelta) { - nBytesNeedToBeSent -= nActualBytesDelta; - } - else { - break; - } - } - return xSendOK; -} - -int casMsgIO::getFD() const -{ - return -1; // some os will not have file descriptors -} - -void casMsgIO::xSetNonBlocking() -{ - printf("virtual base casMsgIO::xSetNonBlocking() called?\n"); -} - -bufSizeT casMsgIO::incommingBytesPresent() const -{ - return 0u; -} - diff --git a/src/cas/generic/casPV.cc b/src/cas/generic/casPV.cc index 7414f459e..a872a3c31 100644 --- a/src/cas/generic/casPV.cc +++ b/src/cas/generic/casPV.cc @@ -27,39 +27,8 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.9 1998/06/18 00:09:09 jhill - * installed bwd compat casPV constructor - * - * Revision 1.8 1998/06/16 02:30:44 jhill - * allow PV to be created before the server - * - * Revision 1.7 1997/08/05 00:47:10 jhill - * fixed warnings - * - * Revision 1.6 1997/04/10 19:34:14 jhill - * API changes - * - * Revision 1.5 1996/12/06 22:34:22 jhill - * add maxDimension() and maxBound() - * - * Revision 1.4 1996/11/02 00:54:21 jhill - * many improvements - * - * Revision 1.3 1996/07/01 19:56:12 jhill - * one last update prior to first release - * - * Revision 1.2 1996/06/21 02:30:53 jhill - * solaris port - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * */ - // // Notes: // @@ -70,8 +39,7 @@ #include "casPVIIL.h" // casPVI inline func #include "casCtxIL.h" // casCtx inline func -epicsShareFunc casPV::casPV () : - casPVI (*this) +epicsShareFunc casPV::casPV () { } @@ -79,8 +47,7 @@ epicsShareFunc casPV::casPV () : // This constructor is preserved for backwards compatibility only. // Please do _not_ use this constructor. // -epicsShareFunc casPV::casPV (caServer &) : - casPVI (*this) +epicsShareFunc casPV::casPV (caServer &) { } @@ -89,14 +56,23 @@ epicsShareFunc casPV::~casPV() } // -// casPV::show() +// casPV::destroy() // -epicsShareFunc void casPV::show(unsigned level) const +// (this default action will _never_ be called while in the +// casPVI destructor) +// +void casPV::destroy () { - if (level>2u) { - printf ("casPV: Best external type = %d\n", - this->bestExternalType()); - } + delete this; +} + +// +// casPV::createChannel() +// +epicsShareFunc casChannel *casPV::createChannel (const casCtx &ctx, const char * const, + const char * const) +{ + return new casChannel (ctx); } // @@ -172,20 +148,11 @@ epicsShareFunc aitIndex casPV::maxBound(unsigned /* dimension */) const } // -// casPV::createChannel() +// casPV::show (unsigned level) // -epicsShareFunc casChannel *casPV::createChannel (const casCtx &ctx, const char * const, - const char * const) +epicsShareFunc void casPV::show (unsigned level) const { - return new casChannel (ctx); -} - -// -// casPV::destroy() -// -epicsShareFunc void casPV::destroy() -{ - delete this; + casPVI::show (level); } // @@ -200,9 +167,7 @@ epicsShareFunc void casPV::postEvent (const casEventMask &select, gdd &event) // Find the server associated with this PV // ****WARNING**** // this returns NULL if the PV isnt currently installed -// into a server (this situation will exist only if -// the pv isnt deleted in a derived classes replacement -// for virtual casPV::destroy() +// into a server. // *************** // epicsShareFunc caServer *casPV::getCAS() const @@ -210,3 +175,11 @@ epicsShareFunc caServer *casPV::getCAS() const return this->casPVI::getExtServer(); } +// +// casPV::apiPointer() +// +casPV *casPV::apiPointer () +{ + return this; +} + diff --git a/src/cas/generic/casPVI.cc b/src/cas/generic/casPVI.cc index 17e67b154..5d19b5715 100644 --- a/src/cas/generic/casPVI.cc +++ b/src/cas/generic/casPVI.cc @@ -26,40 +26,6 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.10 1998/06/16 02:31:36 jhill - * allow the PV to be created before the server - * - * Revision 1.9 1997/08/05 00:47:11 jhill - * fixed warnings - * - * Revision 1.8 1997/04/10 19:34:15 jhill - * API changes - * - * Revision 1.7 1996/12/12 18:55:38 jhill - * fixed client initiated pv delete calls interestDelete() VF bug - * - * Revision 1.6 1996/12/06 22:35:06 jhill - * added destroyInProgress flag - * - * Revision 1.5 1996/11/02 00:54:22 jhill - * many improvements - * - * Revision 1.4 1996/09/04 20:23:17 jhill - * init new member cas and add arg to serverToolDebug() - * - * Revision 1.3 1996/07/01 19:56:13 jhill - * one last update prior to first release - * - * Revision 1.2 1996/06/26 21:18:57 jhill - * now matches gdd api revisions - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * */ @@ -67,24 +33,16 @@ #include "casPVIIL.h" // casPVI inline func #include "caServerIIL.h" // caServerI inline func - // // casPVI::casPVI() // -casPVI::casPVI (casPV &pvAdapterIn) : - pCAS(NULL), // initially there is no server attachment - pv(pvAdapterIn), - nMonAttached(0u), - nIOAttached(0u), - destroyInProgress(FALSE) +casPVI::casPVI () : + pCAS (NULL), // initially there is no server attachment + nMonAttached (0u), + nIOAttached (0u) { - // - // this will always be true - // - assert (&this->pv!=NULL); } - // // casPVI::~casPVI() // @@ -99,9 +57,6 @@ casPVI::~casPVI() this->pCAS->removeItem(*this); - assert (!this->destroyInProgress); - this->destroyInProgress = TRUE; - // // delete any attached channels // @@ -113,7 +68,7 @@ casPVI::~casPVI() tsDLIterBD tmp = iter; ++tmp; - (*iter)->destroy(); + iter->destroyClientNotify (); iter = tmp; } @@ -133,6 +88,17 @@ casPVI::~casPVI() casVerify (this->nMonAttached==0u); } +// +// casPVI::destroy() +// +// This version of destroy() is provided only because it can +// be safely calle din the casPVI destructor as a side effect +// of deleting the last channel. +// +void casPVI::destroy () +{ +} + // // casPVI::attachToServer () // @@ -158,19 +124,6 @@ caStatus casPVI::attachToServer (caServerI &cas) return S_cas_success; } - -// -// casPVI::show() -// -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); - } - (*this)->show(level); -} - // // casPVI::registerEvent() // @@ -181,7 +134,7 @@ caStatus casPVI::registerEvent () this->lock(); this->nMonAttached++; if (this->nMonAttached==1u) { - status = (*this)->interestRegister(); + status = this->interestRegister (); } else { status = S_cas_success; @@ -202,8 +155,8 @@ void casPVI::unregisterEvent() // Dont call casPV::interestDelete() when we are in // casPVI::~casPVI() (and casPV no longr exists) // - if (this->nMonAttached==0u && !this->destroyInProgress) { - (*this)->interestDelete(); + if (this->nMonAttached==0u) { + this->interestDelete(); } this->unlock(); } @@ -216,7 +169,7 @@ void casPVI::unregisterEvent() caServer *casPVI::getExtServer() const { if (this->pCAS) { - return this->pCAS->getAdapter();; + return this->pCAS->getAdapter(); } else { return NULL; @@ -224,19 +177,20 @@ caServer *casPVI::getExtServer() const } // -// casPVI::destroy() +// casPVI::show() // -// call the destroy in the server tool -// -void casPVI::destroy() +epicsShareFunc void casPVI::show (unsigned level) const { - // - // Flag that a server is no longer using this PV - // - this->pCAS = NULL; - this->pv.destroy(); + if (level>1u) { + printf ("CA Server PV: nChanAttached=%u nMonAttached=%u nIOAttached=%u\n", + this->chanList.count(), this->nMonAttached, this->nIOAttached); + } + if (level>2u) { + printf ("\tBest external type = %d\n", this->bestExternalType()); + } } +// // casPVI::resourceType() // epicsShareFunc casResType casPVI::resourceType() const @@ -244,3 +198,13 @@ epicsShareFunc casResType casPVI::resourceType() const return casPVT; } +// +// casPVI::apiPointer() +// retuns NULL if casPVI isnt a base of casPV +// +epicsShareFunc casPV *casPVI::apiPointer () +{ + return NULL; +} + + diff --git a/src/cas/generic/casPVIIL.h b/src/cas/generic/casPVIIL.h index d35d8dec7..5c6b1fc9a 100644 --- a/src/cas/generic/casPVIIL.h +++ b/src/cas/generic/casPVIIL.h @@ -27,51 +27,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.13 1999/04/30 15:36:26 jhill - * better range check on index to gddAitToDbr - * - * Revision 1.12 1998/06/16 02:21:49 jhill - * dont require that a server must exist before a PV is created - * - * Revision 1.11 1997/08/05 00:47:12 jhill - * fixed warnings - * - * Revision 1.10 1997/04/10 19:34:16 jhill - * API changes - * - * Revision 1.9 1997/01/09 22:22:30 jhill - * MSC cannot use the default constructor - * - * Revision 1.8 1996/12/06 22:36:17 jhill - * use destroyInProgress flag now functional nativeCount() - * - * Revision 1.7.2.1 1996/11/25 16:31:55 jhill - * MSC cannot use the default constructor localCASRef(this->cas) - * - * Revision 1.7 1996/11/02 00:54:23 jhill - * many improvements - * - * Revision 1.6 1996/09/16 18:24:05 jhill - * vxWorks port changes - * - * Revision 1.5 1996/09/04 20:23:59 jhill - * added operator -> - * - * Revision 1.4 1996/07/01 19:56:13 jhill - * one last update prior to first release - * - * Revision 1.3 1996/06/26 21:18:58 jhill - * now matches gdd api revisions - * - * Revision 1.2 1996/06/21 02:30:55 jhill - * solaris port - * - * Revision 1.1.1.1 1996/06/20 00:28:16 jhill - * ca server installation - * - * */ @@ -88,25 +43,6 @@ inline caServerI *casPVI::getPCAS() const return this->pCAS; } -// -// casPVI::interfaceObjectPointer() -// -// casPVI must always be a base for casPV -// (the constructor assert fails if this isnt the case) -// -inline casPV *casPVI::interfaceObjectPointer() const -{ - return &this->pv; -} - -// -// casPVI::operator -> () -// -casPV * casPVI::operator -> () const -{ - return interfaceObjectPointer(); -} - // // casPVI::lock() // @@ -119,7 +55,7 @@ inline void casPVI::lock() const // comment in casPVI::deleteSignal() // if (this->pCAS) { - this->pCAS->osiLock(); + this->pCAS->lock(); } else { fprintf (stderr, "PV lock call when not attached to server?\n"); @@ -132,7 +68,7 @@ inline void casPVI::lock() const inline void casPVI::unlock() const { if (this->pCAS) { - this->pCAS->osiUnlock(); + this->pCAS->unlock(); } else { fprintf (stderr, "PV unlock call when not attached to server?\n"); @@ -191,16 +127,17 @@ inline void casPVI::deleteSignal() // lock when we add a new channel (and the // PV lock is realy the server's lock) // - pLocalCAS->osiLock(); + pLocalCAS->lock(); - if (this->chanList.count()==0u && !this->destroyInProgress) { - (*this)->destroy(); + if (this->chanList.count()==0u) { + this->pCAS = NULL; + this->destroy (); // // !! dont access self after destroy !! // } - pLocalCAS->osiUnlock(); + pLocalCAS->unlock(); } } @@ -209,7 +146,7 @@ inline void casPVI::deleteSignal() // inline caStatus casPVI::bestDBRType (unsigned &dbrType) { - unsigned bestAIT = (*this)->bestExternalType(); + unsigned bestAIT = this->bestExternalType(); if (bestAITmaxDimension()==0u) { + if (this->maxDimension()==0u) { return 1u; // scalar } - return (*this)->maxBound(0u); + return this->maxBound(0u); } #endif // casPVIIL_h diff --git a/src/cas/generic/casPVListChan.cc b/src/cas/generic/casPVListChan.cc index bf68427bc..20e2d4347 100644 --- a/src/cas/generic/casPVListChan.cc +++ b/src/cas/generic/casPVListChan.cc @@ -28,16 +28,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.2 1997/01/10 21:17:58 jhill - * code around gnu g++ inline bug when -O isnt used - * - * Revision 1.1 1996/12/06 22:36:18 jhill - * use destroyInProgress flag now functional nativeCount() - * - * - * */ #include "server.h" @@ -50,9 +40,8 @@ // // casPVListChan::casPVListChan() // -casPVListChan::casPVListChan - (const casCtx &ctx, casChannel &chanAdapterIn) : - casChannelI(ctx, chanAdapterIn) +casPVListChan::casPVListChan (const casCtx &ctx) : + casChannelI(ctx) { this->pv.installChannel(*this); } diff --git a/src/cas/generic/casStrmClient.cc b/src/cas/generic/casStrmClient.cc index f38179d41..1b00de785 100644 --- a/src/cas/generic/casStrmClient.cc +++ b/src/cas/generic/casStrmClient.cc @@ -27,97 +27,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.29 1999/05/07 23:07:11 jhill - * throw warning exception with get/put callback failure detail - * - * Revision 1.28 1999/04/30 15:46:54 jhill - * deal with situation where bounds on managed DD must be modified - * - * Revision 1.27 1998/12/19 00:04:52 jhill - * renamed createPV() to pvAttach() - * - * Revision 1.26 1998/10/28 23:51:01 jhill - * server nolonger throws exception when a poorly formed get/put call back - * request arrives. Instead a get/put call back response is sent which includes - * unsuccessful status - * - * Revision 1.25 1998/09/24 20:40:07 jhill - * o block if unable to get buffer space for the exception message - * o subtle changes related to properly dealing with situations where - * both the server tool and the client tool delete the same PV simultaneously - * - * Revision 1.24 1998/07/08 15:38:07 jhill - * fixed lost monitors during flow control problem - * - * Revision 1.23 1998/06/16 02:32:30 jhill - * use smart gdd ptr - * - * Revision 1.22 1998/05/05 16:32:17 jhill - * cleaned up file format - * - * Revision 1.21 1998/04/15 00:04:05 jhill - * cosmetic - * - * Revision 1.20 1998/04/14 23:51:10 jhill - * improved diagnostic - * - * Revision 1.19 1998/02/18 22:46:25 jhill - * improved message - * - * Revision 1.18 1997/08/05 00:47:13 jhill - * fixed warnings - * - * Revision 1.17 1997/06/30 22:54:28 jhill - * use %p with pointers - * - * Revision 1.16 1997/06/13 09:16:00 jhill - * connect proto changes - * - * Revision 1.15 1997/04/10 19:34:18 jhill - * API changes - * - * Revision 1.14 1996/12/12 18:56:27 jhill - * doc - * - * Revision 1.13 1996/12/11 01:03:52 jhill - * removed redundant bad client attach detect - * - * Revision 1.12 1996/12/06 22:36:22 jhill - * use destroyInProgress flag now functional nativeCount() - * - * Revision 1.11 1996/11/02 00:54:24 jhill - * many improvements - * - * Revision 1.10 1996/09/16 18:24:05 jhill - * vxWorks port changes - * - * Revision 1.9 1996/09/04 20:25:53 jhill - * use correct app type for exist test gdd, correct byte - * oder for mon mask, and efficient use of PV name gdd - * - * Revision 1.8 1996/08/05 23:22:57 jhill - * gddScaler => gddScalar - * - * Revision 1.7 1996/08/05 19:26:51 jhill - * doc - * - * Revision 1.5 1996/07/09 22:53:33 jhill - * init stat and sev in gdd - * - * Revision 1.4 1996/07/01 19:56:14 jhill - * one last update prior to first release - * - * Revision 1.3 1996/06/26 21:18:59 jhill - * now matches gdd api revisions - * - * Revision 1.2 1996/06/21 02:30:57 jhill - * solaris port - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * * */ @@ -137,6 +46,70 @@ static const caHdr nill_msg = {0u,0u,0u,0u,0u,0u}; +// +// casStrmClient::casStrmClient() +// +casStrmClient::casStrmClient (caServerI &serverInternal) : + casClient (serverInternal, 1) +{ + this->lock(); + + this->ctx.getServer()->installClient (this); + + this->pHostName = new char [1u]; + if (!this->pHostName) { + throw S_cas_noMemory; + } + *this->pHostName = '\0'; + + this->pUserName = new char [1u]; + if (!this->pUserName) { + free (this->pHostName); + throw S_cas_noMemory; + } + *this->pUserName= '\0'; + + this->unlock(); +} + +// +// casStrmClient::~casStrmClient() +// +casStrmClient::~casStrmClient() +{ + this->lock(); + + // + // remove this from the list of connected clients + // + this->ctx.getServer()->removeClient(this); + + if (this->pUserName) { + delete [] this->pUserName; + } + + if (this->pHostName) { + delete [] this->pHostName; + } + + // + // delete all channel attached + // + tsDLIterBD iter(this->chanList.first()); + while (iter!=tsDLIterBD::eol()) { + // + // destroying the channel removes it from the list + // + tsDLIterBD tmp = iter; + ++tmp; + iter->destroyNoClientNotify(); + iter = tmp; + } + + this->unlock(); +} + + // // casStrmClient::verifyRequest() // @@ -169,101 +142,10 @@ caStatus casStrmClient::verifyRequest (casChannelI *&pChan) return ECA_NORMAL; } - - - -// -// casStrmClient::casStrmClient() -// -casStrmClient::casStrmClient(caServerI &serverInternal) : - inBuf(*(osiMutex *)this, casStreamIO::optimumBufferSize()), - outBuf(*(osiMutex *)this, casStreamIO::optimumBufferSize()), - casClient(serverInternal, *this, *this), - pUserName(NULL), pHostName(NULL) -{ - this->ctx.getServer()->installClient(this); -} - -// -// casStrmClient::init() -// -caStatus casStrmClient::init() -{ - caStatus status; - - // - // call base class initializers - // - status = casClient::init(); - if (status) { - return status; - } - status = this->inBuf::init(); - if (status) { - return status; - } - status = this->outBuf::init(); - if (status) { - return status; - } - - this->pHostName = new char [1u]; - if (!this->pHostName) { - return S_cas_noMemory; - } - *this->pHostName = '\0'; - - this->pUserName = new char [1u]; - if (!this->pUserName) { - return S_cas_noMemory; - } - *this->pUserName= '\0'; - - return this->start(); -} - - -// -// casStrmClient::~casStrmClient() -// -casStrmClient::~casStrmClient() -{ - this->osiLock(); - - // - // remove this from the list of connected clients - // - this->ctx.getServer()->removeClient(this); - - if (this->pUserName) { - delete [] this->pUserName; - } - - if (this->pHostName) { - delete [] this->pHostName; - } - - // - // delete all channel attached - // - tsDLIterBD iter(this->chanList.first()); - while (iter!=tsDLIterBD::eol()) { - // - // destroying the channel removes it from the list - // - tsDLIterBD tmp = iter; - ++tmp; - iter->clientDestroy(); - iter = tmp; - } - - this->osiUnlock(); -} - // // find the monitor associated with a resource id // -inline casClientMon *caServerI::resIdToClientMon(const caResId &idIn) +inline casClientMon *caServerI::resIdToClientMon (const caResId &idIn) { casRes *pRes; @@ -275,7 +157,6 @@ inline casClientMon *caServerI::resIdToClientMon(const caResId &idIn) return (casClientMon *) pRes; } - // // casStrmClient::show (unsigned level) // @@ -309,7 +190,7 @@ caStatus casStrmClient::readAction () /* * verify read access */ - if ((*pChan)->readAccess()!=aitTrue) { + if (pChan->readAccess()!=aitTrue) { int v41; v41 = CA_V41(CA_PROTOCOL_VERSION,this->minor_version_number); @@ -340,8 +221,6 @@ caStatus casStrmClient::readAction () return status; } - - // // casStrmClient::readResponse() // @@ -382,7 +261,7 @@ caStatus casStrmClient::readResponse (casChannelI *pChan, const caHdr &msg, if (mapDBRStatus<0) { desc.dump(); errPrintf (S_cas_badBounds, __FILE__, __LINE__, "- get notify with PV=%s type=%u count=%u", - pChan->getPVI()->getName(), msg.m_type, msg.m_count); + pChan->getPVI().getName(), msg.m_type, msg.m_count); return this->sendErrWithEpicsStatus(&msg, S_cas_badBounds, ECA_GETFAIL); } #ifdef CONVERSION_REQUIRED @@ -408,7 +287,6 @@ caStatus casStrmClient::readResponse (casChannelI *pChan, const caHdr &msg, return localStatus; } - // // casStrmClient::readNotifyAction() // @@ -427,7 +305,7 @@ caStatus casStrmClient::readNotifyAction () // // verify read access // - if ((*pChan)->readAccess()!=aitTrue) { + if (pChan->readAccess()!=aitTrue) { if (CA_V41(CA_PROTOCOL_VERSION, this->minor_version_number)) { return this->readNotifyResponseECA_XXX (NULL, *mp, NULL, ECA_NORDACCESS); } @@ -545,7 +423,7 @@ caStatus casStrmClient::readNotifyResponseECA_XXX (casChannelI *pChan, if (mapDBRStatus<0) { pDesc->dump(); errPrintf (S_cas_badBounds, __FILE__, __LINE__, "- get notify with PV=%s type=%u count=%u", - pChan->getPVI()->getName(), msg.m_type, msg.m_count); + pChan->getPVI().getName(), msg.m_type, msg.m_count); reply->m_cid = ECA_GETFAIL; } else { @@ -637,7 +515,7 @@ caStatus casStrmClient::monitorResponse(casChannelI &chan, const caHdr &msg, // // verify read access // - if (!chan->readAccess()) { + if (!chan.readAccess()) { completionStatusCopy = S_cas_noRead; } @@ -722,8 +600,6 @@ caStatus casStrmClient::monitorResponse(casChannelI &chan, const caHdr &msg, return S_cas_success; } - - /* * casStrmClient::writeAction() */ @@ -741,7 +617,7 @@ caStatus casStrmClient::writeAction() // // verify write access // - if ((*pChan)->writeAccess()!=aitTrue) { + if (pChan->writeAccess()!=aitTrue) { int v41; v41 = CA_V41(CA_PROTOCOL_VERSION,this->minor_version_number); @@ -818,7 +694,7 @@ caStatus casStrmClient::writeNotifyAction() // // verify write access // - if ((*pChan)->writeAccess()!=aitTrue) { + if (pChan->writeAccess()!=aitTrue) { if (CA_V41(CA_PROTOCOL_VERSION,this->minor_version_number)) { return this->casStrmClient::writeNotifyResponseECA_XXX( *mp, ECA_NOWTACCESS); @@ -941,7 +817,7 @@ caStatus casStrmClient::hostNameAction() size-1); pMalloc[size-1]='\0'; - this->osiLock(); + this->lock(); if (this->pHostName) { delete [] this->pHostName; @@ -950,16 +826,15 @@ caStatus casStrmClient::hostNameAction() tsDLIterBD iter(this->chanList.first()); while ( iter!=tsDLIterBD::eol() ) { - (*iter)->setOwner(this->pUserName, this->pHostName); + iter->setOwner(this->pUserName, this->pHostName); ++iter; } - this->osiUnlock(); + this->unlock(); return S_cas_success; } - /* * casStrmClient::clientNameAction() */ @@ -990,7 +865,7 @@ caStatus casStrmClient::clientNameAction() size-1); pMalloc[size-1]='\0'; - this->osiLock(); + this->lock(); if (this->pUserName) { delete [] this->pUserName; @@ -999,16 +874,14 @@ caStatus casStrmClient::clientNameAction() tsDLIterBD iter(this->chanList.first()); while ( iter!=tsDLIterBD::eol() ) { - (*iter)->setOwner(this->pUserName, this->pHostName); + iter->setOwner(this->pUserName, this->pHostName); ++iter; } - this->osiUnlock(); + this->unlock(); return S_cas_success; } - - /* * casStrmClientMon::claimChannelAction() */ @@ -1064,7 +937,7 @@ caStatus casStrmClient::claimChannelAction() // prevent problems such as the PV being deleted before the // channel references it // - this->osiLock(); + this->lock(); this->asyncIOFlag = 0u; // @@ -1092,7 +965,7 @@ caStatus casStrmClient::claimChannelAction() else { status = this->createChanResponse(*mp, pvar); } - this->osiUnlock(); + this->unlock(); return status; } @@ -1107,12 +980,12 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur casChannel *pChan; casChannelI *pChanI; caHdr *claim_reply; - caHdr *dummy; unsigned dbrType; + bufSizeT nBytes; caStatus status; if (pvar.getStatus() != S_cas_success) { - return this->channelCreateFailed(&hdr, pvar.getStatus()); + return this->channelCreateFailed (&hdr, pvar.getStatus()); } pPV = pvar.getPV(); @@ -1122,7 +995,7 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur // pv isnt in this server // if (pPV == NULL) { - return this->channelCreateFailed(&hdr, S_casApp_pvNotFound); + return this->channelCreateFailed (&hdr, S_casApp_pvNotFound); } // @@ -1136,27 +1009,27 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur // // NOTE: // We are allocating enough space for both the claim - // response and the access response so that we know for + // response and the access rights response so that we know for // certain that they will both be sent together. // - status = this->allocMsg (sizeof(caHdr), &dummy); - if (status) { - return status; - } + void *pRaw; + const outBufCtx outctx = this->outBuf::pushCtx + (0, 2*sizeof(caHdr), pRaw); + if (outctx.pushResult()!=outBufCtx::pushCtxSuccess) { + return S_cas_sendBlocked; + } // // create server tool XXX derived from casChannel // - this->ctx.setPV(pPV); - pChan = (*pPV)->createChannel(this->ctx, - this->pUserName, this->pHostName); + this->ctx.setPV (pPV); + pChan = pPV->createChannel (this->ctx, this->pUserName, this->pHostName); if (!pChan) { - pvar.getPV()->deleteSignal(); - return this->channelCreateFailed(&hdr, S_cas_noMemory); + this->outBuf::popCtx (outctx); + pPV->deleteSignal(); + return this->channelCreateFailed (&hdr, S_cas_noMemory); } - this->osiUnlock(); - pChanI = (casChannelI *) pChan; // @@ -1167,15 +1040,17 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur // status = casStrmClient::accessRightsResponse(pChanI); if (status) { + this->outBuf::popCtx (outctx); errMessage(status, "incompplete channel create?"); - pChanI->clientDestroy(); + pChanI->destroyNoClientNotify(); return this->channelCreateFailed(&hdr, status); } status = pPV->bestDBRType(dbrType); if (status) { + this->outBuf::popCtx (outctx); errMessage(status, "best external dbr type fetch failed"); - pChanI->clientDestroy(); + pChanI->destroyNoClientNotify(); return this->channelCreateFailed(&hdr, status); } @@ -1189,15 +1064,8 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur // here to be certain that we are at the correct place in // the protocol buffer. // - // The 3rd arg indicates - dont lock the buffer again - // - status = this->allocMsg (0u, &claim_reply, FALSE); - // - // Not sending the access rights response and the claim - // response is a severe error which is avoided by - // the first (oversize) allocMsg - // - assert (status==S_cas_success); + status = this->allocMsg (0u, &claim_reply); + assert (status==S_cas_success); *claim_reply = nill_msg; claim_reply->m_cmmd = CA_PROTO_CLAIM_CIU; @@ -1205,16 +1073,18 @@ caStatus casStrmClient::createChanResponse(const caHdr &hdr, const pvAttachRetur claim_reply->m_count = pPV->nativeCount(); claim_reply->m_cid = hdr.m_cid; claim_reply->m_available = pChanI->getSID(); + this->commitMsg(); - // - // Unlock the buffer (and convert it to network format - // - this->commitMsg(); + // + // commit the message + // + nBytes = this->outBuf::popCtx (outctx); + assert ( nBytes == 2*sizeof(caHdr) ); + this->outBuf::commitRawMsg (nBytes); return status; } - /* * casStrmClient::channelCreateFailed() * @@ -1259,7 +1129,6 @@ caStatus createStatus) return createStatus; } - /* * casStrmClient::disconnectChan() * @@ -1293,8 +1162,6 @@ caStatus casStrmClient::disconnectChan(caResId id) return createStatus; } - - // // casStrmClient::eventsOnAction() // @@ -1312,8 +1179,6 @@ caStatus casStrmClient::eventsOffAction() return this->casEventSys::eventsOff(); } - - // // eventAddAction() // @@ -1339,15 +1204,15 @@ caStatus casStrmClient::eventAddAction () // caProtoMask = ntohs (pMonInfo->m_mask); if (caProtoMask&DBE_VALUE) { - mask |= this->getCAS().getAdapter()->valueEventMask; + mask |= this->getCAS().valueEventMask(); } if (caProtoMask&DBE_LOG) { - mask |= this->getCAS().getAdapter()->logEventMask; + mask |= this->getCAS().logEventMask(); } if (caProtoMask&DBE_ALARM) { - mask |= this->getCAS().getAdapter()->alarmEventMask; + mask |= this->getCAS().alarmEventMask(); } if (mask.noEventsSelected()) { @@ -1362,7 +1227,7 @@ caStatus casStrmClient::eventAddAction () // to postpone asynchronous IO we can safely restart this // request later. // - status = this->read(pDD); + status = this->read (pDD); // // always send immediate monitor response at event add // @@ -1384,7 +1249,7 @@ caStatus casStrmClient::eventAddAction () // there isnt pool space for a gdd then delete // (disconnect) the channel // - (*pciu)->destroy(); + pciu->destroyClientNotify (); return S_cas_success; } else { @@ -1402,7 +1267,7 @@ caStatus casStrmClient::eventAddAction () // If we cant allocate space for a monitor then // delete (disconnect) the channel // - (*pciu)->destroy(); + pciu->destroyClientNotify (); } return status; } @@ -1412,7 +1277,6 @@ caStatus casStrmClient::eventAddAction () } - // // casStrmClient::clearChannelAction() // @@ -1463,7 +1327,7 @@ caStatus casStrmClient::clearChannelAction () // space for the response // if (pciu) { - pciu->clientDestroy (); + pciu->destroyNoClientNotify (); } *reply = *mp; @@ -1473,8 +1337,6 @@ caStatus casStrmClient::clearChannelAction () } - - // // casStrmClient::eventCancelAction() // @@ -1535,7 +1397,6 @@ caStatus casStrmClient::eventCancelAction () return S_cas_success; } - #if 0 /* * casStrmClient::noReadAccessEvent() @@ -1590,7 +1451,6 @@ caStatus casStrmClient::noReadAccessEvent(casClientMon *pMon) } #endif - // // casStrmClient::readSyncAction() // @@ -1606,13 +1466,13 @@ caStatus casStrmClient::readSyncAction() // any pending asynchronous IO associated with // a read. // - this->osiLock(); + this->lock(); tsDLIterBD iter(this->chanList.first()); while ( iter!=tsDLIterBD::eol() ) { iter->clearOutstandingReads(); ++iter; } - this->osiUnlock(); + this->unlock(); status = this->allocMsg(0u, &reply); if(status){ @@ -1626,8 +1486,6 @@ caStatus casStrmClient::readSyncAction() return S_cas_success; } - - // // casStrmClient::accessRightsResponse() // @@ -1637,42 +1495,41 @@ caStatus casStrmClient::readSyncAction() // caStatus casStrmClient::accessRightsResponse(casChannelI *pciu) { - caHdr *reply; - unsigned ar; - int v41; - int status; - - /* - * noop if this is an old client - */ - v41 = CA_V41(CA_PROTOCOL_VERSION, this->minor_version_number); - if(!v41){ - return S_cas_success; - } - - ar = 0; /* none */ - if ((*pciu)->readAccess()) { - ar |= CA_PROTO_ACCESS_RIGHT_READ; - } - if ((*pciu)->writeAccess()) { - ar |= CA_PROTO_ACCESS_RIGHT_WRITE; - } - - status = this->allocMsg(0u, &reply); - if(status){ - return status; - } - - *reply = nill_msg; - reply->m_cmmd = CA_PROTO_ACCESS_RIGHTS; - reply->m_cid = pciu->getCID(); - reply->m_available = ar; - this->commitMsg(); - - return S_cas_success; + caHdr *reply; + unsigned ar; + int v41; + int status; + + /* + * noop if this is an old client + */ + v41 = CA_V41(CA_PROTOCOL_VERSION, this->minor_version_number); + if(!v41){ + return S_cas_success; + } + + ar = 0; /* none */ + if (pciu->readAccess()) { + ar |= CA_PROTO_ACCESS_RIGHT_READ; + } + if (pciu->writeAccess()) { + ar |= CA_PROTO_ACCESS_RIGHT_WRITE; + } + + status = this->allocMsg(0u, &reply); + if(status){ + return status; + } + + *reply = nill_msg; + reply->m_cmmd = CA_PROTO_ACCESS_RIGHTS; + reply->m_cid = pciu->getCID(); + reply->m_available = ar; + this->commitMsg(); + + return S_cas_success; } - // // casStrmClient::write() // @@ -1701,7 +1558,7 @@ caStatus casStrmClient::write() // // the PV state must not be modified during a transaction // - status = (*pPV)->beginTransaction(); + status = pPV->beginTransaction(); if (status) { return status; } @@ -1741,12 +1598,11 @@ caStatus casStrmClient::write() "- expected asynch IO creation from casPV::write()"); } - (*pPV)->endTransaction(); + pPV->endTransaction(); return status; } - // // casStrmClient::writeScalarData() // @@ -1807,7 +1663,7 @@ caStatus casStrmClient::writeScalarData() // // call the server tool's virtual function // - status = (*this->ctx.getPV())->write(this->ctx, *pDD); + status = this->ctx.getPV()->write(this->ctx, *pDD); return status; } @@ -1891,7 +1747,7 @@ caStatus casStrmClient::writeArrayData() // // call the server tool's virtual function // - status = (*this->ctx.getPV())->write(this->ctx, *pDD); + status = this->ctx.getPV()->write(this->ctx, *pDD); return status; } @@ -1918,7 +1774,7 @@ caStatus casStrmClient::read(smartGDDPointer &pDescRet) // // the PV state must not be modified during a transaction // - status = (*this->ctx.getPV())->beginTransaction(); + status = this->ctx.getPV()->beginTransaction(); if (status) { return status; } @@ -1931,7 +1787,7 @@ caStatus casStrmClient::read(smartGDDPointer &pDescRet) // // call the server tool's virtual function // - status = (*this->ctx.getPV())->read(this->ctx, *pDescRet); + status = this->ctx.getPV()->read(this->ctx, *pDescRet); // // prevent problems when they initiate @@ -1956,7 +1812,7 @@ caStatus casStrmClient::read(smartGDDPointer &pDescRet) pDescRet = NULL; } - (*this->ctx.getPV())->endTransaction(); + this->ctx.getPV()->endTransaction(); return status; } @@ -2119,9 +1975,9 @@ const char *casStrmClient::hostName() const // // caServerI::roomForNewChannel() // -inline aitBool caServerI::roomForNewChannel() const +inline bool caServerI::roomForNewChannel() const { - return aitTrue; + return true; } // @@ -2129,10 +1985,10 @@ inline aitBool caServerI::roomForNewChannel() const // void casStrmClient::installChannel(casChannelI &chan) { - this->osiLock(); + this->lock(); this->getCAS().installItem (chan); this->chanList.add(chan); - this->osiUnlock(); + this->unlock(); } // @@ -2142,75 +1998,71 @@ void casStrmClient::removeChannel(casChannelI &chan) { casRes *pRes; - this->osiLock(); + this->lock(); pRes = this->getCAS().removeItem(chan); assert (&chan == (casChannelI *)pRes); this->chanList.remove(chan); - this->osiUnlock(); + this->unlock(); } // // casStrmClient::xSend() // -xSendStatus casStrmClient::xSend(char *pBufIn, bufSizeT nBytesAvailableToSend, +outBuf::flushCondition casStrmClient::xSend (char *pBufIn, bufSizeT nBytesAvailableToSend, bufSizeT nBytesNeedToBeSent, bufSizeT &nActualBytes) { - xSendStatus stat; + outBuf::flushCondition stat; bufSizeT nActualBytesDelta; - + bufSizeT totalBytes; + assert (nBytesAvailableToSend>=nBytesNeedToBeSent); - nActualBytes = 0u; - if (this->blockingState() == xIsntBlocking) { - // - // !! this time fetch may be slowing things down !! - // - stat = this->osdSend(pBufIn, nBytesAvailableToSend, - nActualBytes); - if (stat == xSendOK) { - this->lastSendTS = osiTime::getCurrent(); - } - return stat; - } - - nActualBytes = 0u; + totalBytes = 0u; while (TRUE) { - stat = this->osdSend(&pBufIn[nActualBytes], - nBytesAvailableToSend, nActualBytesDelta); - if (stat != xSendOK) { - return stat; + stat = this->osdSend (&pBufIn[totalBytes], + nBytesAvailableToSend-totalBytes, nActualBytesDelta); + if (stat != outBuf::flushProgress) { + if (totalBytes>0) { + nActualBytes = totalBytes; + // + // !! this time fetch may be slowing things down !! + // + //this->lastSendTS = osiTime::getCurrent(); + return outBuf::flushProgress; + } + else { + return stat; + } } - // - // !! this time fetch may be slowing things down !! - // - this->lastSendTS = osiTime::getCurrent(); - nActualBytes += nActualBytesDelta; + totalBytes += nActualBytesDelta; - if (nBytesNeedToBeSent <= nActualBytesDelta) { - break; + if (totalBytes>=nBytesNeedToBeSent) { + // + // !! this time fetch may be slowing things down !! + // + //this->lastSendTS = osiTime::getCurrent(); + nActualBytes = totalBytes; + return outBuf::flushProgress; } - nBytesAvailableToSend -= nActualBytesDelta; - nBytesNeedToBeSent -= nActualBytesDelta; } - return xSendOK; } // // casStrmClient::xRecv() // -xRecvStatus casStrmClient::xRecv(char *pBufIn, bufSizeT nBytes, - bufSizeT &nActualBytes) +inBuf::fillCondition casStrmClient::xRecv(char *pBufIn, bufSizeT nBytes, + enum inBuf::fillParameter, bufSizeT &nActualBytes) { - xRecvStatus stat; + inBuf::fillCondition stat; - stat = this->osdRecv(pBufIn, nBytes, nActualBytes); - if (stat==xRecvOK) { + stat = this->osdRecv (pBufIn, nBytes, nActualBytes); + //if (stat==casFillProgress) { // // !! this time fetch may be slowing things down !! // - this->lastRecvTS = osiTime::getCurrent(); - } + //this->lastRecvTS = osiTime::getCurrent(); + //} return stat; } diff --git a/src/cas/generic/casdef.h b/src/cas/generic/casdef.h index 3cc996a3d..0557400b8 100644 --- a/src/cas/generic/casdef.h +++ b/src/cas/generic/casdef.h @@ -40,17 +40,8 @@ #include "gdd.h" // EPICS data descriptors #include "shareLib.h" // EPICS compiler specific sharable lib keywords -// -// This eliminates a warning resulting from passing *this -// to a base class during derived class construction. -// -#if defined(_MSC_VER) -# pragma warning (disable:4355) -#endif - typedef aitUint32 caStatus; - /* * =========================================================== * for internal use by the server library @@ -88,6 +79,8 @@ typedef aitUint32 caStatus; #define S_cas_badBounds (M_cas | 30) /*server tool changed bounds on request*/ #define S_cas_pvAlreadyAttached (M_cas | 31) /*PV attached to another server*/ #define S_cas_badRequest (M_cas | 32) /*client's request was invalid*/ +#define S_cas_invalidAsynchIO (M_cas | 33) /*inappropriate asynchronous IO type*/ + /* * =========================================================== * returned by the application (to the server library) @@ -147,7 +140,7 @@ public: return *this; } pvExistReturnEnum getStatus() const {return this->status;} - int addrIsValid() const {return this->address.isSock();} + int addrIsValid() const {return this->address.isValid();} caNetAddr getAddr() const {return this->address;} private: pvExistReturnEnum status; @@ -251,6 +244,8 @@ class caServerI; // class caServer { private: + friend class casPVI; + // // this private data member appears first so that // initialization of the constant event masks below @@ -259,24 +254,12 @@ private: // We do not use private inheritance here in order // to avoid os/io dependent -I during server tool compile // - caServerI *pCAS; + caServerI *pCAS; + public: epicsShareFunc caServer (unsigned pvCountEstimate=1024u); epicsShareFunc virtual ~caServer() = 0; - //caStatus enableClients (); - //caStatus disableClients (); - - epicsShareFunc void setDebugLevel (unsigned level); - epicsShareFunc unsigned getDebugLevel (); - - epicsShareFunc casEventMask registerEvent (const char *pName); - - // - // show() - // - epicsShareFunc virtual void show (unsigned level) const; - // // pvExistTest() // @@ -353,20 +336,6 @@ public: epicsShareFunc virtual pvAttachReturn pvAttach (const casCtx &ctx, const char *pPVAliasName); - // - // common event masks - // (what is currently used by the CA clients) - // - const casEventMask valueEventMask; // DBE_VALUE - const casEventMask logEventMask; // DBE_LOG - const casEventMask alarmEventMask; // DBE_ALARM - - // - // this is only used by casPVI::casPVI() too convert from - // caServer to a caServerI - // - friend class casPVI; - // // createPV() (deprecated) // The virtual member function "createPV" will be deleted in a @@ -375,6 +344,31 @@ public: // epicsShareFunc virtual pvCreateReturn createPV (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); + + // + // 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 void setDebugLevel (unsigned level); + epicsShareFunc unsigned getDebugLevel () const; + + // + // show() + // + epicsShareFunc virtual void show (unsigned level) const; + + //caStatus enableClients (); + //caStatus disableClients (); }; // @@ -567,6 +561,9 @@ public: // pointer returned must remain valid for the life time // o fthe process variable // +// +// !! not thread safe !! +// epicsShareFunc virtual const char *getName() const = 0; // @@ -582,14 +579,19 @@ public: epicsShareFunc caServer *getCAS() const; // - // only used when caStrmClient converts between - // casPV * and casPVI * + // only used when caStrmClient converts from + // casPV * to casPVI * // friend class casStrmClient; + +private: + casPV *apiPointer (); //retruns NULL if casPVI isnt a base of casPV + +public: // - // This constructor is preserved for backwards compatibility only. - // Please do _not_ use this constructor. + // This constructor has been depricated, and is preserved for + // backwards compatibility only. Please do not use it. // epicsShareFunc casPV (caServer &); }; @@ -618,32 +620,32 @@ public: // class casChannel : private casPVListChan { public: - epicsShareFunc casChannel(const casCtx &ctx); + 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, + epicsShareFunc virtual void setOwner (const char * const pUserName, const char * const pHostName); // // the following are encouraged to change during an channel's // lifetime // - epicsShareFunc virtual aitBool readAccess () const; - epicsShareFunc virtual aitBool writeAccess () const; + epicsShareFunc virtual bool readAccess () const; + epicsShareFunc virtual bool writeAccess () const; // return true to hint that the opi should ask the operator // for confirmation prior writing to this PV - epicsShareFunc virtual aitBool confirmationRequested () const; + epicsShareFunc virtual bool confirmationRequested () const; // // This is called for each channel in the server if // caServer::show() is called and the level is high // enough // - epicsShareFunc virtual void show(unsigned level) const; + epicsShareFunc virtual void show (unsigned level) const; // // destroy() is called when @@ -653,13 +655,13 @@ public: // // the casChannel::destroy() executes a "delete this" // - epicsShareFunc virtual void destroy(); + epicsShareFunc virtual void destroy (); // // server tool calls this to indicate change in access // rights has occurred // - epicsShareFunc void postAccessRightsEvent(); + epicsShareFunc void postAccessRightsEvent (); // // Find the PV associated with this channel @@ -670,7 +672,7 @@ public: // for virtual casChannel::destroy() // *************** // - epicsShareFunc casPV *getPV(); + epicsShareFunc casPV *getPV (); // // only used when casStrmClient converts between @@ -684,12 +686,12 @@ public: // // The following virtual functions allow for asynchronous completion: // -// Virtual Function Asynchronous IO Class -// ----------------- --------------------- -// caServer::pvExistTest() casAsyncPVExistIO -// caServer::pvAttach() casAsyncPVAttachIO -// casPV::read() casAsyncReadIO -// casPV::write() casAsyncWriteIO +// Virtual Function Asynchronous IO Class +// ----------------- --------------------- +// caServer::pvExistTest() casAsyncPVExistIO +// caServer::pvAttach() casAsyncPVAttachIO +// casPV::read() casAsyncReadIO +// casPV::write() casAsyncWriteIO // // To initiate asynchronous completion create a corresponding // asynchronous IO object from within one of the virtual @@ -702,14 +704,14 @@ public: // Deletion Responsibility // -------- -------------- // o the server lib will not call "delete" directly for any -// casAsyncIO created by the server tool because we dont know +// casAsyncXxxIO created by the server tool because we dont know // that "new" was called to create the object. // o The server tool is responsible for reclaiming storage for any -// casAsyncIO it creates. The destroy virtual function will +// casAsyncXxxxIO it creates. The destroy virtual function will // assist the server tool with this responsibility. The -// virtual function casAsyncIO::destroy() does a "delete this". -// o Avoid deleting the casAsyncIO immediately after calling -// postIOCompletion(). Instead proper operation requires that +// virtual function casAsyncXxxxIO::destroy() does a "delete this". +// o Avoid deleting the async IO object immediately after calling +// postIOCompletion(). Instead, proper operation requires that // the server tool wait for the server lib to call destroy after // the response is successfully queued to the client // o If for any reason the server tool needs to cancel an IO @@ -717,33 +719,10 @@ public: // S_casApp_canceledAsyncIO. Deleting the asynchronous io // object prior to its being allowed to forward an IO termination // message to the client will result in NO IO CALL BACK TO THE -// CLIENT PROGRAM (in this situation a warning message will be printed by -// the server lib). +// CLIENT PROGRAM (in this situation a warning message will be +// printed by the server lib). // -// -// casAsyncIO -// -// this class implements a common virtual destroy for -// all of the asynchronous IO classes -// -class casAsyncIO { -public: - // - // force virtual destructor - // - epicsShareFunc virtual ~casAsyncIO() = 0; - - // - // called by the server lib after the response message - // is succesfully queued to the client or when the - // IO operation is canceled (client disconnects etc). - // - // default destroy executes a "delete this". - // - epicsShareFunc virtual void destroy(); -}; - // // casAsyncReadIO // - for use with casPV::read() @@ -758,29 +737,21 @@ public: // in the destructor, for the class deriving from // casAsyncReadIO. // ** -class casAsyncReadIO : public casAsyncIO, private casAsyncRdIOI { +class casAsyncReadIO : private casAsyncIOI { public: + // // casAsyncReadIO() // - epicsShareFunc casAsyncReadIO(const casCtx &ctx) : - casAsyncRdIOI(ctx, *this) {} - - // - // force virtual destructor - // - epicsShareFunc virtual ~casAsyncReadIO(); + epicsShareFunc casAsyncReadIO (const casCtx &ctx); + epicsShareFunc virtual ~casAsyncReadIO (); // // place notification of IO completion on the event queue - // (this function does not delete the casAsyncIO object). + // (this function does not delete the casAsyncReadIO object). // Only the first call to this function has any effect. // - epicsShareFunc caStatus postIOCompletion(caStatus completionStatusIn, gdd &valueRead) - { - return this->casAsyncRdIOI::postIOCompletion ( - completionStatusIn, valueRead); - } + epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn, gdd &valueRead); // // Find the server associated with this async IO @@ -789,10 +760,25 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS() const - { - return this->casAsyncRdIOI::getCAS(); - } + epicsShareFunc caServer *getCAS () const; + + // + // called by the server lib after the response message + // is succesfully queued to the client or when the + // IO operation is canceled (client disconnects etc). + // + // default destroy executes a "delete this". + // + epicsShareFunc virtual void destroy (); + +private: + caHdr const msg; + casChannelI &chan; + smartGDDPointer pDD; + caStatus completionStatus; + + epicsShareFunc bool readOP() const; + epicsShareFunc caStatus cbFuncAsyncIO(); }; // @@ -810,28 +796,20 @@ public: // casAsyncWriteIO. // ** // -class casAsyncWriteIO : public casAsyncIO, private casAsyncWtIOI { +class casAsyncWriteIO : private casAsyncIOI { public: // // casAsyncWriteIO() // - epicsShareFunc casAsyncWriteIO(const casCtx &ctx) : - casAsyncWtIOI(ctx, *this) {} - - // - // force virtual destructor - // - epicsShareFunc virtual ~casAsyncWriteIO(); + epicsShareFunc casAsyncWriteIO (const casCtx &ctx); + epicsShareFunc virtual ~casAsyncWriteIO (); // // place notification of IO completion on the event queue - // (this function does not delete the casAsyncIO object). + // (this function does not delete the casAsyncWriteIO object). // Only the first call to this function has any effect. // - epicsShareFunc caStatus postIOCompletion(caStatus completionStatusIn) - { - return this->casAsyncWtIOI::postIOCompletion (completionStatusIn); - } + epicsShareFunc caStatus postIOCompletion (caStatus completionStatusIn); // // Find the server associated with this async IO @@ -840,38 +818,44 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS() const - { - return this->casAsyncWtIOI::getCAS(); - } + epicsShareFunc caServer *getCAS () const; + + // + // called by the server lib after the response message + // is succesfully queued to the client or when the + // IO operation is canceled (client disconnects etc). + // + // default destroy executes a "delete this". + // + epicsShareFunc virtual void destroy (); + +private: + caHdr const msg; + casChannelI &chan; + caStatus completionStatus; + + epicsShareFunc caStatus cbFuncAsyncIO (); }; // // casAsyncPVExistIO // - for use with caServer::pvExistTest() // -class casAsyncPVExistIO : public casAsyncIO, private casAsyncExIOI { +class casAsyncPVExistIO : private casAsyncIOI { public: + // // casAsyncPVExistIO() // - epicsShareFunc casAsyncPVExistIO(const casCtx &ctx) : - casAsyncExIOI(ctx, *this) {} - - // - // force virtual destructor - // - epicsShareFunc virtual ~casAsyncPVExistIO(); + epicsShareFunc casAsyncPVExistIO (const casCtx &ctx); + epicsShareFunc virtual ~casAsyncPVExistIO (); // // place notification of IO completion on the event queue - // (this function does not delete the casAsyncIO object). + // (this function does not delete the casAsyncPVExistIO object). // Only the first call to this function has any effect. // - epicsShareFunc caStatus postIOCompletion(const pvExistReturn &retValIn) - { - return this->casAsyncExIOI::postIOCompletion (retValIn); - } + epicsShareFunc caStatus postIOCompletion (const pvExistReturn &retValIn); // // Find the server associated with this async IO @@ -880,38 +864,43 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS() const - { - return this->casAsyncExIOI::getCAS(); - } + epicsShareFunc caServer *getCAS() const; + + // + // called by the server lib after the response message + // is succesfully queued to the client or when the + // IO operation is canceled (client disconnects etc). + // + // default destroy executes a "delete this". + // + epicsShareFunc virtual void destroy(); + +private: + caHdr const msg; + pvExistReturn retVal; + const caNetAddr dgOutAddr; + + epicsShareFunc caStatus cbFuncAsyncIO(); }; // // casAsyncPVAttachIO // - for use with caServer::pvAttach() // -class casAsyncPVAttachIO : public casAsyncIO, private casAsyncAtIOI { +class casAsyncPVAttachIO : private casAsyncIOI { public: // // casAsyncPVAttachIO() // - epicsShareFunc casAsyncPVAttachIO (const casCtx &ctx) : - casAsyncAtIOI(ctx, *this) {} - - // - // force virtual destructor - // - epicsShareFunc virtual ~casAsyncPVAttachIO(); + epicsShareFunc casAsyncPVAttachIO (const casCtx &ctx); + epicsShareFunc virtual ~casAsyncPVAttachIO (); // // place notification of IO completion on the event queue - // (this function does not delete the casAsyncIO object). + // (this function does not delete the casAsyncPVAttachIO object). // Only the first call to this function has any effect. // - epicsShareFunc caStatus postIOCompletion(const pvAttachReturn &retValIn) - { - return this->casAsyncAtIOI::postIOCompletion (retValIn); - } + epicsShareFunc caStatus postIOCompletion (const pvAttachReturn &retValIn); // // Find the server associated with this async IO @@ -920,20 +909,31 @@ public: // into a server // *************** // - epicsShareFunc caServer *getCAS() const - { - return this->casAsyncAtIOI::getCAS(); - } + epicsShareFunc caServer *getCAS() const; + + // + // called by the server lib after the response message + // is succesfully queued to the client or when the + // IO operation is canceled (client disconnects etc). + // + // default destroy executes a "delete this". + // + epicsShareFunc virtual void destroy (); + +private: + caHdr const msg; + pvAttachReturn retVal; + + epicsShareFunc caStatus cbFuncAsyncIO (); }; // // casAsyncPVCreateIO (deprecated) // (this class will be deleted in a future release) // -class casAsyncPVCreateIO : public casAsyncPVAttachIO { +class casAsyncPVCreateIO : private casAsyncPVAttachIO { public: - epicsShareFunc casAsyncPVCreateIO(const casCtx &ctx) : - casAsyncPVAttachIO (ctx) {} + epicsShareFunc casAsyncPVCreateIO(const casCtx &ctx); epicsShareFunc virtual ~casAsyncPVCreateIO(); }; diff --git a/src/cas/generic/dgInBuf.cc b/src/cas/generic/dgInBuf.cc index c9abfc594..b355180ce 100644 --- a/src/cas/generic/dgInBuf.cc +++ b/src/cas/generic/dgInBuf.cc @@ -1,58 +1,3 @@ #include "server.h" #include "inBufIL.h" - -// -// this needs to be here (and not in dgInBufIL.h) if we -// are to avoid undefined symbols under gcc 2.7.x without -O -// -// dgInBuf::dgInBuf () -// -dgInBuf::dgInBuf (osiMutex &mutexIn, unsigned bufSizeIn) : - inBuf(mutexIn, bufSizeIn) -{ -} - -// -// dgInBuf::~dgInBuf() -// (force virtual constructor) -// -dgInBuf::~dgInBuf() -{ -} - -// -// this needs to be here (and not in dgInBufIL.h) if we -// are to avoid undefined symbols under gcc 2.7.x without -O -// -// dgInBuf::hasAddress() -// -int dgInBuf::hasAddress() const -{ - return this->from.isSock(); -} - -// -// dgInBuf::xRecv () -// -xRecvStatus dgInBuf::xRecv (char *pBufIn, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv) -{ - caNetAddr addr; - xRecvStatus stat; - - stat = this->xDGRecv (pBufIn, nBytesToRecv, nByesRecv, addr); - if (stat == xRecvOK) { - this->from = addr; - } - return stat; -} - -// -// dgInBuf::getSender() -// -caNetAddr dgInBuf::getSender() const -{ - return this->from; -} - diff --git a/src/cas/generic/dgInBufIL.h b/src/cas/generic/dgInBufIL.h index 0533e6371..be2e0113e 100644 --- a/src/cas/generic/dgInBufIL.h +++ b/src/cas/generic/dgInBufIL.h @@ -4,14 +4,5 @@ #include "inBufIL.h" -// -// dgInBuf::clear() -// -inline void dgInBuf::clear() -{ - this->from.clear(); - this->inBuf::clear(); -} - #endif // dgInBufILh diff --git a/src/cas/generic/dgOutBuf.cc b/src/cas/generic/dgOutBuf.cc deleted file mode 100644 index 286b9b248..000000000 --- a/src/cas/generic/dgOutBuf.cc +++ /dev/null @@ -1,69 +0,0 @@ - -#include "server.h" -#include "outBufIL.h" - -// -// this needs to be here (and not in dgInBufIL.h) if we -// are to avoid undefined symbols under gcc 2.7.x when -// -O is not used -// -// dgOutBuf::dgOutBuf () -// -dgOutBuf::dgOutBuf (osiMutex &mutexIn, unsigned bufSizeIn) : - outBuf(mutexIn, bufSizeIn) -{ -} - -// -// dgOutBuf::~dgOutBuf() -// (force virtual destructor) -// -dgOutBuf::~dgOutBuf() -{ -} - -// -// dgOutBuf::xSend() -// -xSendStatus dgOutBuf::xSend (char *pBufIn, - bufSizeT nBytesAvailableToSend, bufSizeT nBytesNeedToBeSent, - bufSizeT &nBytesSent) -{ - assert(nBytesAvailableToSend>=nBytesNeedToBeSent); - return xDGSend(pBufIn, nBytesAvailableToSend, nBytesSent, this->to); -} - -// -// this needs to be here (and not in dgInBufIL.h) if we -// are to avoid undefined symbols under gcc 2.7.x (without -O) -// -// dgOutBuf::clear() -// -void dgOutBuf::clear() -{ - this->to.clear(); - this->outBuf::clear(); -} - -// -// this needs to be here (and not in dgInBufIL.h) if we -// are to avoid undefined symbols under gcc 2.7.x (without -O) -// -// dgOutBuf::setRecipient() -// -void dgOutBuf::setRecipient(const caNetAddr &addr) -{ - this->to = addr; -} - -// -// this needs to be here (and not in dgInBufIL.h) if we -// are to avoid undefined symbols under gcc 2.7.x (without -O) -// -// dgOutBuf::getRecipient() -// -caNetAddr dgOutBuf::getRecipient() -{ - return this->to; -} - diff --git a/src/cas/generic/dgOutBufIL.h b/src/cas/generic/dgOutBufIL.h deleted file mode 100644 index dbe4d8cc8..000000000 --- a/src/cas/generic/dgOutBufIL.h +++ /dev/null @@ -1,13 +0,0 @@ - -#ifndef dgOutBufILh -#define dgOutBufILh - -#include "outBufIL.h" - -// -// All of the functions in this file moved to dgOutBuf.cc because -// of inline problems with g++ 2.7.2 (without -O) -// - -#endif // dgOutBufILh - diff --git a/src/cas/generic/inBuf.cc b/src/cas/generic/inBuf.cc index f68b1e588..7dbb639bf 100644 --- a/src/cas/generic/inBuf.cc +++ b/src/cas/generic/inBuf.cc @@ -26,59 +26,68 @@ * Advanced Photon Source * Argonne National Laboratory * - * - * History - * $Log$ - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * */ #include "server.h" #include "inBufIL.h" // inBuf in line func +// +// inBuf::inBuf() +// +inBuf::inBuf (bufSizeT bufSizeIn, bufSizeT ioMinSizeIn) : + bufSize (bufSizeIn), ioMinSize (ioMinSizeIn), + bytesInBuffer (0u), nextReadIndex (0u), + ctxRecursCount (0u) +{ + if (this->ioMinSize==0) { + this->ioMinSize = 1; + } + + assert (this->bufSize>this->ioMinSize); + + this->pBuf = new char [this->bufSize]; + if (!this->pBuf) { + this->bufSize = 0u; + throw S_cas_noMemory; + } +} + // // inBuf::~inBuf() // (virtual destructor) // -inBuf::~inBuf() +inBuf::~inBuf () { - if (this->pBuf) { - delete [] this->pBuf; - } + assert (this->ctxRecursCount==0); + delete [] this->pBuf; } // // inBuf::show() // -void inBuf::show(unsigned level) const +void inBuf::show (unsigned level) const { - if (level>1u) { - printf( - "\tUnprocessed request bytes = %d\n", - this->bytesAvailable()); - } + if (level>1u) { + printf( + "\tUnprocessed request bytes = %d\n", + this->bytesAvailable()); + } } // // inBuf::fill() // -casFillCondition inBuf::fill() +inBuf::fillCondition inBuf::fill (fillParameter parm) { - unsigned bytesReq; - unsigned bytesRecv; - xRecvStatus stat; - - if (!this->pBuf) { - return casFillDisconnect; - } + bufSizeT bytesOpen; + bufSizeT bytesRecv; + inBuf::fillCondition stat; // // move back any prexisting data to the start of the buffer // - if (this->nextReadIndex>0u) { - unsigned unprocessedBytes; + if ( this->nextReadIndex > 0 ) { + bufSizeT unprocessedBytes; unprocessedBytes = this->bytesInBuffer - this->nextReadIndex; // // memmove() handles overlapping buffers @@ -94,36 +103,72 @@ casFillCondition inBuf::fill() // // noop if the buffer is full // - bytesReq = this->bufSize - this->bytesInBuffer; - if (bytesReq <= 0u) { - return casFillFull; - } - - stat = this->xRecv(&this->pBuf[this->bytesInBuffer], - bytesReq, bytesRecv); - if (stat != xRecvOK) { - return casFillDisconnect; - } - if (bytesRecv==0u) { + bytesOpen = this->bufSize - this->bytesInBuffer; + if (bytesOpen < this->ioMinSize) { return casFillNone; } - assert (bytesRecv<=bytesReq); - this->bytesInBuffer += bytesRecv; - if (this->getDebugLevel()>2u) { - char buf[64]; + stat = this->xRecv (&this->pBuf[this->bytesInBuffer], + bytesOpen, parm, bytesRecv); + if (stat == casFillProgress) { + assert (bytesRecv<=bytesOpen); + this->bytesInBuffer += bytesRecv; - this->clientHostName(buf, sizeof(buf)); + if (this->getDebugLevel()>2u) { + char buf[64]; - printf ("CAS: incomming %u byte msg from %s\n", - bytesRecv, buf); + this->clientHostName(buf, sizeof(buf)); + + printf ("CAS: incomming %u byte msg from %s\n", + bytesRecv, buf); + } } - if (this->bufSize==this->bytesInBuffer) { - return casFillFull; - } - else { - return casFillPartial; - } + return stat; } +// +// inBuf::pushCtx () +// +const inBufCtx inBuf::pushCtx (bufSizeT headerSize, bufSizeT bodySize) +{ + if (headerSize+bodySize>(this->bytesInBuffer - this->nextReadIndex) || + this->ctxRecursCount==UINT_MAX) { + return inBufCtx (); + } + else { + inBufCtx result (*this); + bufSizeT effectiveNextReadIndex = this->nextReadIndex + headerSize; + this->pBuf = this->pBuf + effectiveNextReadIndex; + this->bytesInBuffer -= effectiveNextReadIndex; + this->nextReadIndex = 0; + this->bytesInBuffer = bodySize; + this->bufSize = this->bytesInBuffer; + this->ctxRecursCount++; + return result; + } +} + +// +// inBuf::popCtx () +// +bufSizeT inBuf::popCtx (const inBufCtx &ctx) +{ + if (ctx.stat==inBufCtx::pushCtxSuccess) { + bufSizeT bytesRemoved = this->nextReadIndex; + this->pBuf = ctx.pBuf; + this->bufSize = ctx.bufSize; + this->bytesInBuffer = ctx.bytesInBuffer; + this->nextReadIndex = ctx.nextReadIndex; + assert (this->ctxRecursCount>0); + this->ctxRecursCount--; + this->mutex.unlock(); + return bytesRemoved; + } + else { + return 0; + } +} + + + diff --git a/src/cas/generic/inBufIL.h b/src/cas/generic/inBufIL.h index 027f7c5f6..2e8e7e3ac 100644 --- a/src/cas/generic/inBufIL.h +++ b/src/cas/generic/inBufIL.h @@ -2,32 +2,10 @@ #ifndef inBufILh #define inBufILh -// -// inBuf::inBuf() -// -inline inBuf::inBuf(osiMutex &mutexIn, unsigned bufSizeIn) : - mutex(mutexIn), pBuf(NULL), bufSize(bufSizeIn), - bytesInBuffer(0u), nextReadIndex(0u) -{ -} - -// -// inBuf::init() -// -inline caStatus inBuf::init() -{ - this->pBuf = new char [this->bufSize]; - if (!this->pBuf) { - this->bufSize = 0u; - return S_cas_noMemory; - } - return S_cas_success; -} - // // inBuf::bytesPresent() // -inline bufSizeT inBuf::bytesPresent() const +inline bufSizeT inBuf::bytesPresent () const { return this->bytesInBuffer-this->nextReadIndex; } @@ -35,7 +13,7 @@ inline bufSizeT inBuf::bytesPresent() const // // inBuf::bytesAvailable() // -inline bufSizeT inBuf::bytesAvailable() const +inline bufSizeT inBuf::bytesAvailable () const { bufSizeT bp; bp = this->bytesPresent(); @@ -46,18 +24,18 @@ inline bufSizeT inBuf::bytesAvailable() const // // inBuf::full() // -inline aitBool inBuf::full() const +inline bool inBuf::full () const { - if (this->bytesPresent()>=this->bufSize) { - return aitTrue; + if (this->bufSize-this->bytesPresent()ioMinSize) { + return true; } - return aitFalse; + return false; } // // inBuf::clear() // -inline void inBuf::clear() +inline void inBuf::clear () { this->bytesInBuffer = 0u; this->nextReadIndex = 0u; @@ -66,7 +44,7 @@ inline void inBuf::clear() // // inBuf::msgPtr() // -inline char *inBuf::msgPtr() const +inline char *inBuf::msgPtr () const { return &this->pBuf[this->nextReadIndex]; } @@ -74,10 +52,32 @@ inline char *inBuf::msgPtr() const // // inBuf::removeMsg() // -inline void inBuf::removeMsg(unsigned nBytes) +inline void inBuf::removeMsg (bufSizeT nBytes) { this->nextReadIndex += nBytes; - assert(this->nextReadIndex<=this->bytesInBuffer); + 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/outBuf.cc b/src/cas/generic/outBuf.cc index edad16107..698139193 100644 --- a/src/cas/generic/outBuf.cc +++ b/src/cas/generic/outBuf.cc @@ -27,27 +27,6 @@ * Argonne National Laboratory * * - * History - * $Log$ - * Revision 1.6 1996/12/06 22:36:29 jhill - * use destroyInProgress flag now functional nativeCount() - * - * Revision 1.5 1996/11/02 00:54:30 jhill - * many improvements - * - * Revision 1.4 1996/09/16 18:24:07 jhill - * vxWorks port changes - * - * Revision 1.3 1996/09/04 20:27:01 jhill - * doccasdef.h - * - * Revision 1.2 1996/08/13 22:53:59 jhill - * fixed little endian problem - * - * Revision 1.1.1.1 1996/06/20 00:28:15 jhill - * ca server installation - * - * */ #include "server.h" @@ -56,25 +35,14 @@ // // outBuf::outBuf() // -outBuf::outBuf(osiMutex &mutexIn, unsigned bufSizeIn) : - mutex(mutexIn), - pBuf(NULL), - bufSize(bufSizeIn), - stack(0u) -{ -} - -// -// outBuf::init() -// -caStatus outBuf::init() +outBuf::outBuf (unsigned bufSizeIn) : + bufSize (bufSizeIn), stack (0u), ctxRecursCount (0u) { this->pBuf = new char [this->bufSize]; if (!this->pBuf) { - return S_cas_noMemory; + throw S_cas_noMemory; } memset (this->pBuf, '\0', this->bufSize); - return S_cas_success; } // @@ -82,86 +50,66 @@ caStatus outBuf::init() // outBuf::~outBuf() { - if (this->pBuf) { - delete [] this->pBuf; - } + assert (this->ctxRecursCount==0); + delete [] this->pBuf; } - // -// outBuf::allocMsg() +// outBuf::allocRawMsg () // -// allocates space in the outgoing message buffer -// -// (if space is avilable this leaves the send lock applied) -// -caStatus outBuf::allocMsg ( -bufSizeT extsize, // extension size -caHdr **ppMsg, -int lockRequired -) +caStatus outBuf::allocRawMsg (bufSizeT msgsize, void **ppMsg) { - bufSizeT msgsize; bufSizeT stackNeeded; - extsize = CA_MESSAGE_ALIGN(extsize); + msgsize = CA_MESSAGE_ALIGN (msgsize); - msgsize = extsize + sizeof(caHdr); - if (msgsize>this->bufSize || this->pBuf==NULL) { + this->mutex.lock (); + + if (msgsize>this->bufSize) { + this->mutex.unlock (); return S_cas_hugeRequest; } stackNeeded = this->bufSize - msgsize; - // - // In some special situations we preallocate space for - // two messages and prefer not to lock twice - // (so that lock/unlock pairs will match) - // - if (lockRequired) { - this->mutex.osiLock(); - } - if (this->stack > stackNeeded) { - /* - * Try to flush the output queue - */ - this->flush(casFlushSpecified, msgsize); + // + // Try to flush the output queue + // + this->flush (this->stack-stackNeeded); - /* - * If this failed then the fd is nonblocking - * and we will let select() take care of it - */ + // + // If this failed then the fd is nonblocking + // and we will let select() take care of it + // if (this->stack > stackNeeded) { - this->mutex.osiUnlock(); + this->mutex.unlock(); this->sendBlockSignal(); return S_cas_sendBlocked; } } - /* - * it fits so commitMsg() will move the stack pointer forward - */ - *ppMsg = (caHdr *) &this->pBuf[this->stack]; + // + // it fits so commitMsg() will move the stack pointer forward + // + *ppMsg = (void *) &this->pBuf[this->stack]; return S_cas_success; } - - -/* - * outBuf::commitMsg() - */ +// +// outBuf::commitMsg () +// void outBuf::commitMsg () { caHdr *mp; - bufSizeT extSize; - bufSizeT diff; + ca_uint16_t diff; + ca_uint16_t extSize; mp = (caHdr *) &this->pBuf[this->stack]; - extSize = CA_MESSAGE_ALIGN(mp->m_postsize); + extSize = static_cast ( CA_MESSAGE_ALIGN (mp->m_postsize) ); // // Guarantee that all portions of outgoing messages @@ -169,133 +117,141 @@ void outBuf::commitMsg () // diff = extSize - mp->m_postsize; if (diff>0u) { - char *pExt = (char *) (mp+1); - memset(pExt + mp->m_postsize, '\0', diff); + memset ( reinterpret_cast(mp+1) + mp->m_postsize, '\0', diff ); } - mp->m_postsize = extSize; - if (this->getDebugLevel()) { ca_printf ( "CAS Response => cmd=%d id=%x typ=%d cnt=%d psz=%d avail=%x outBuf ptr=%lx\n", - mp->m_cmmd, - mp->m_cid, - mp->m_type, - mp->m_count, - mp->m_postsize, - mp->m_available, - (long)mp); + mp->m_cmmd, mp->m_cid, mp->m_type, mp->m_count, mp->m_postsize, + mp->m_available, (long)mp); } - /* - * convert to network byte order - * (data following header is handled elsewhere) - */ + // + // convert to network byte order + // (data following header is handled elsewhere) + // mp->m_cmmd = htons (mp->m_cmmd); - mp->m_postsize = htons (mp->m_postsize); + mp->m_postsize = htons (extSize); mp->m_type = htons (mp->m_type); mp->m_count = htons (mp->m_count); mp->m_cid = htonl (mp->m_cid); mp->m_available = htonl (mp->m_available); - this->stack += sizeof(caHdr) + extSize; - assert (this->stack <= this->bufSize); - - this->mutex.osiUnlock(); + commitRawMsg (extSize + sizeof(*mp)); } // -// outBuf::flush() +// outBuf::flush () // -casFlushCondition outBuf::flush(casFlushRequest req, bufSizeT spaceRequired) +outBuf::flushCondition outBuf::flush (bufSizeT spaceRequired) { bufSizeT nBytes; - bufSizeT stackNeeded; - bufSizeT nBytesNeeded; - xSendStatus stat; - casFlushCondition cond; + bufSizeT nBytesRequired; + flushCondition cond; - if (!this->pBuf) { - return casFlushDisconnect; - } + this->mutex.lock(); - this->mutex.osiLock(); + if (this->ctxRecursCount>0) { + this->mutex.unlock(); + return flushNone; + } - if (req==casFlushAll) { - nBytesNeeded = this->stack; + if (spaceRequired>this->bufSize) { + nBytesRequired = this->stack; } else { - stackNeeded = this->bufSize - spaceRequired; - if (this->stack>stackNeeded) { - nBytesNeeded = this->stack - stackNeeded; + bufSizeT stackPermitted; + + stackPermitted = this->bufSize - spaceRequired; + if (this->stack>stackPermitted) { + nBytesRequired = this->stack - stackPermitted; } else { - nBytesNeeded = 0u; + nBytesRequired = 0u; } } - if (nBytesNeeded==0u) { - this->mutex.osiUnlock(); - return casFlushCompleted; - } + cond = this->xSend(this->pBuf, this->stack, + nBytesRequired, nBytes); + if (cond==flushProgress) { + bufSizeT len; - nBytes = 0u; - stat = this->xSend(this->pBuf, this->stack, - nBytesNeeded, nBytes); - if (stat == xSendOK) { - if (nBytes) { - bufSizeT len; - char buf[64]; - - if (nBytes >= this->stack) { - this->stack=0u; - cond = casFlushCompleted; - } - else { - len = this->stack-nBytes; - // - // memmove() is ok with overlapping buffers - // - memmove (this->pBuf, &this->pBuf[nBytes], len); - this->stack = len; - cond = casFlushPartial; - } - - if (this->getDebugLevel()>2u) { - this->clientHostName(buf,sizeof(buf)); - ca_printf( - "CAS: Sent a %d byte reply to %s\n", - nBytes, buf); - } + if (nBytes >= this->stack) { + this->stack = 0u; } else { - cond = casFlushNone; + len = this->stack-nBytes; + // + // memmove() is ok with overlapping buffers + // + memmove (this->pBuf, &this->pBuf[nBytes], len); + this->stack = len; } - } - else { - cond = casFlushDisconnect; - } - this->mutex.osiUnlock(); + + if (this->getDebugLevel()>2u) { + char buf[64]; + this->clientHostName (buf, sizeof(buf)); + ca_printf ("CAS: Sent a %d byte reply to %s\n", + nBytes, buf); + } + } + this->mutex.unlock(); return cond; } // -// outBuf::show(unsigned level) +// outBuf::pushCtx () // -void outBuf::show(unsigned level) const +const outBufCtx outBuf::pushCtx (bufSizeT headerSize, bufSizeT maxBodySize, void *&pHeader) { - if (level>1u) { - printf( - "\tUndelivered response bytes =%d\n", - this->bytesPresent()); - } + bufSizeT totalSize = headerSize + maxBodySize; + caStatus status; + + status = this->allocRawMsg (totalSize, &pHeader); + if (status!=S_cas_success) { + return outBufCtx (); + } + else if (this->ctxRecursCount==UINT_MAX) { + this->mutex.unlock(); + return outBufCtx (); + } + else { + outBufCtx result (*this); + this->pBuf = this->pBuf + this->stack + headerSize; + this->stack = 0; + this->bufSize = maxBodySize; + this->ctxRecursCount++; + return result; + } } // -// outBuf::sendBlockSignal() +// outBuf::popCtx () // -void outBuf::sendBlockSignal() +bufSizeT outBuf::popCtx (const outBufCtx &ctx) { - fprintf(stderr, "In virtula base sendBlockSignal() ?\n"); + if (ctx.stat==outBufCtx::pushCtxSuccess) { + bufSizeT bytesAdded = this->stack; + this->pBuf = ctx.pBuf; + this->bufSize = ctx.bufSize; + this->stack = ctx.stack; + assert (this->ctxRecursCount>0u); + this->ctxRecursCount--; + return bytesAdded; + } + else { + return 0; + } +} + +// +// outBuf::show (unsigned level) +// +void outBuf::show (unsigned level) const +{ + if (level>1u) { + printf("\tUndelivered response bytes = %d\n", this->bytesPresent()); + } } diff --git a/src/cas/generic/outBufIL.h b/src/cas/generic/outBufIL.h index 1ab94ebe7..cafd4f959 100644 --- a/src/cas/generic/outBufIL.h +++ b/src/cas/generic/outBufIL.h @@ -3,29 +3,80 @@ #define outBufILh // -// outBuf::bytesPresent() +// outBuf::bytesPresent () // number of bytes in the output queue // -inline bufSizeT outBuf::bytesPresent() const +inline bufSizeT outBuf::bytesPresent () const { - return this->stack; + // + // Note on use of lock here: + // This guarantees that any pushCtx() operation + // in progress completes before another thread checks. + // + this->mutex.lock (); + bufSizeT result = this->stack; + this->mutex.unlock (); + return result; } // -// outBuf::bytesFree() -// number of bytes unused in the output queue +// outBuf::clear () // -inline bufSizeT outBuf::bytesFree() const -{ - return this->bufSize - this->stack; -} - -// -// outBuf::clear() -// -inline void outBuf::clear() +inline void outBuf::clear () { + // + // Note on use of lock here: + // This guarantees that any pushCtx() operation + // in progress completes before another thread + // clears. + // + this->mutex.lock (); this->stack = 0u; + this->mutex.unlock (); +} + +// +// outBuf::allocMsg () +// +// allocates space in the outgoing message buffer +// +// (if space is avilable this leaves the send lock applied) +// +inline caStatus outBuf::allocMsg (bufSizeT extsize, caHdr **ppMsg) +{ + return this->allocRawMsg (extsize + sizeof(caHdr), (void **)ppMsg); +} + +// +// outBuf::commitRawMsg() +// +inline void outBuf::commitRawMsg (bufSizeT size) +{ + this->stack += size; + assert (this->stack <= this->bufSize); + + this->mutex.unlock(); +} + +// +// 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 index 205d1f0f7..59ba9764a 100644 --- a/src/cas/generic/server.h +++ b/src/cas/generic/server.h @@ -78,11 +78,10 @@ void serverToolDebugFunc(const char *pFile, unsigned line, const char *pComment) caStatus createDBRDD(unsigned dbrType, aitIndex dbrCount, smartGDDPointer &pDescRet); caStatus copyBetweenDD(gdd &dest, gdd &src); -enum xRecvStatus {xRecvOK, xRecvDisconnect}; -enum xSendStatus {xSendOK, xSendDisconnect}; enum xBlockingStatus {xIsBlocking, xIsntBlocking}; enum casIOState {casOnLine, casOffLine}; typedef unsigned bufSizeT; +static const unsigned bufSizeT_MAX = UINT_MAX; enum casProcCond {casProcOk, casProcDisconnect}; @@ -115,51 +114,48 @@ class caServerI; class casEventSys { friend class casEventPurgeEv; public: - inline casEventSys (casCoreClient &coreClientIn); - - inline caStatus init(); - + casEventSys (); virtual ~casEventSys(); - virtual void destroy()=0; + void show (unsigned level) const; + casProcCond process (); - void show(unsigned level) const; - casProcCond process(); + void installMonitor (); + void removeMonitor (); - void installMonitor(); - void removeMonitor(); + void removeFromEventQueue (casEvent &); + void addToEventQueue (casEvent &); - inline void removeFromEventQueue(casEvent &); - inline void addToEventQueue(casEvent &); + void insertEventQueue (casEvent &insert, casEvent &prevEvent); + void pushOnToEventQueue (casEvent &event); - inline void insertEventQueue(casEvent &insert, casEvent &prevEvent); - inline void pushOnToEventQueue(casEvent &event); + bool full (); - inline aitBool full(); + casMonitor *resIdToMon (const caResId id); - inline casMonitor *resIdToMon(const caResId id); + bool getNDuplicateEvents () const; - inline casCoreClient &getCoreClient(); - - - inline aitBool getNDuplicateEvents () const; - - inline void setDestroyPending(); + void setDestroyPending(); void eventsOn(); caStatus eventsOff(); + virtual caStatus disconnectChan (caResId id) = 0; + private: tsDLList eventLogQue; osiMutex mutex; - casCoreClient &coreClient; casEventPurgeEv *pPurgeEvent; // flow control purge complete event unsigned numEventBlocks; // N event blocks installed unsigned maxLogEntries; // max log entries unsigned char destroyPending; unsigned char replaceEvents; // replace last existing event on queue unsigned char dontProcess; // flow ctl is on - dont process event queue + + virtual void eventFlush () = 0; + virtual void eventSignal () = 0; + virtual casRes *lookupRes (const caResId &idIn, casResType type) = 0; }; // @@ -227,168 +223,188 @@ private: unsigned nAsyncIO; // checks for improper use of async io }; -enum casFillCondition{ - casFillNone, - casFillPartial, - casFillFull, - casFillDisconnect}; +// +// 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; +}; + // // inBuf // class inBuf { + friend class inBufCtx; public: - // - // this needs to be here (and not in dgInBufIL.h) if we - // are to avoid undefined symbols under gcc 2.7.x without -O - // - inline inBuf(osiMutex &mutexIn, unsigned bufSizeIn); - inline caStatus init(); //constructor does not return status - virtual ~inBuf(); - inline bufSizeT bytesPresent() const; + enum fillCondition {casFillNone, casFillProgress, + casFillDisconnect}; - inline bufSizeT bytesAvailable() const ; + // this is a hack for a Solaris IP kernel feature + enum fillParameter {fpNone, fpUseBroadcastInterface}; + + inBuf (bufSizeT bufSizeIn, bufSizeT ioMinSizeIn); + virtual ~inBuf (); + + bufSizeT bytesPresent () const; + + bufSizeT bytesAvailable () const; + + bool full () const; + + // + // fill the input buffer with any incoming messages + // + fillCondition fill (enum fillParameter parm=fpNone); + + void show (unsigned level) const; - inline aitBool full() const; +protected: - inline void clear(); + void clear (); + + char *msgPtr () const; + + void removeMsg (bufSizeT nBytes); - inline char *msgPtr() const; - - inline void removeMsg(unsigned nBytes); - - // - // fill the input buffer with any incoming messages - // - casFillCondition fill (); - - void show (unsigned level) const; - - virtual unsigned getDebugLevel() const = 0; - virtual bufSizeT incommingBytesPresent() const = 0; - virtual xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv) = 0; - virtual void clientHostName (char *pBuf, - unsigned bufSize) const = 0; + // + // 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 inBuf::pushCtx (bufSizeT headerSize, bufSizeT bodySize); + bufSizeT popCtx (const inBufCtx &); // returns actual size private: - osiMutex &mutex; - char *pBuf; - bufSizeT bufSize; - bufSizeT bytesInBuffer; - bufSizeT nextReadIndex; + osiMutex mutex; + char *pBuf; + bufSizeT bufSize; + bufSizeT bytesInBuffer; + bufSizeT nextReadIndex; + bufSizeT ioMinSize; + unsigned ctxRecursCount; + + virtual unsigned getDebugLevel () const = 0; + virtual bufSizeT incommingBytesPresent () const = 0; + virtual fillCondition xRecv (char *pBuf, bufSizeT nBytesToRecv, + enum inBuf::fillParameter parm, bufSizeT &nByesRecv) = 0; + virtual void clientHostName (char *pBuf, unsigned bufSize) const = 0; }; // -// dgInBuf +// outBufCtx // -class dgInBuf : public inBuf { +class outBufCtx { + friend class outBuf; public: - dgInBuf (osiMutex &mutexIn, unsigned bufSizeIn); - virtual ~dgInBuf(); + enum pushCtxResult {pushCtxNoSpace, pushCtxSuccess}; + outBufCtx (const outBuf &); // success + outBufCtx (); // failure - inline void clear(); - - int hasAddress() const; - - caNetAddr getSender() const; - - xRecvStatus xRecv (char *pBufIn, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv); - - virtual xRecvStatus xDGRecv (char *pBuf, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv, caNetAddr &sender) = 0; + pushCtxResult pushResult () const; private: - caNetAddr from; + pushCtxResult stat; + char *pBuf; + bufSizeT bufSize; + bufSizeT stack; }; // // outBuf // -enum casFlushCondition{ - casFlushNone, - casFlushPartial, - casFlushCompleted, - casFlushDisconnect}; -enum casFlushRequest{ - casFlushAll, - casFlushSpecified}; - class outBuf { + friend class outBufCtx; public: - outBuf (osiMutex &, unsigned bufSizeIn); - caStatus init(); //constructor does not return status - virtual ~outBuf()=0; - inline bufSizeT bytesPresent() const; + enum flushCondition {flushNone, flushProgress, flushDisconnect}; - inline bufSizeT bytesFree() const; + outBuf (bufSizeT bufSizeIn); + virtual ~outBuf ()=0; + + bufSizeT bytesPresent() const; // // flush output queue // (returns the number of bytes sent) - // - casFlushCondition flush(casFlushRequest req = casFlushAll, - bufSizeT spaceRequired=0u); + // + flushCondition flush (bufSizeT spaceRequired=bufSizeT_MAX); + + void show (unsigned level) const; + +protected: // // allocate message buffer space // (leaves message buffer locked) // - caStatus allocMsg (unsigned extsize, caHdr **ppMsg, int lockRequired=1); + caStatus allocMsg (bufSizeT extsize, caHdr **ppMsg); + + // + // allocate message buffer space + // (leaves message buffer locked) + // + caStatus allocRawMsg (bufSizeT size, void **ppMsg); + + // + // 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 // // commits message allocated with allocMsg() // void commitMsg (); - void show(unsigned level) const; + // + // commits message allocated with allocRawMsg() + // + void commitRawMsg (bufSizeT size); + + void clear (); + +private: + osiMutex mutex; + char *pBuf; + bufSizeT bufSize; + bufSizeT stack; + unsigned ctxRecursCount; virtual unsigned getDebugLevel() const = 0; - virtual void sendBlockSignal(); + virtual void sendBlockSignal() = 0; // // io dependent // - virtual xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, + virtual flushCondition xSend (char *pBuf, bufSizeT nBytesAvailableToSend, bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent) = 0; virtual void clientHostName (char *pBuf, unsigned bufSize) const = 0; - - inline void clear(); - -private: - osiMutex &mutex; - char *pBuf; - const bufSizeT bufSize; - bufSizeT stack; }; -// -// dgOutBuf -// -class dgOutBuf : public outBuf { -public: - dgOutBuf (osiMutex &mutexIn, unsigned bufSizeIn); - - virtual ~dgOutBuf(); - - caNetAddr getRecipient(); - - void setRecipient(const caNetAddr &addr); - - void clear(); - - xSendStatus xSend (char *pBufIn, bufSizeT nBytesAvailableToSend, - bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent); - - virtual xSendStatus xDGSend (char *pBuf, bufSizeT nBytesNeedToBeSent, - bufSizeT &nBytesSent, const caNetAddr &recipient) = 0; -private: - caNetAddr to; -}; - - // // casCoreClient // (this will eventually support direct communication @@ -400,31 +416,26 @@ class casCoreClient : public osiMutex, public ioBlocked, // // allows casAsyncIOI constructor to check for asynch IO duplicates // - friend casAsyncIOI::casAsyncIOI(casCoreClient &clientIn, casAsyncIO &ioExternalIn); + friend casAsyncIOI::casAsyncIOI(casCoreClient &clientIn); public: casCoreClient(caServerI &serverInternal); - caStatus init(); - virtual ~casCoreClient(); virtual void destroy(); virtual caStatus disconnectChan(caResId id); - virtual void eventSignal() = 0; - virtual void eventFlush() = 0; - virtual caStatus start () = 0; virtual void show (unsigned level) const; virtual void installChannel (casChannelI &); virtual void removeChannel (casChannelI &); - inline void installAsyncIO(casAsyncIOI &ioIn); + void installAsyncIO(casAsyncIOI &ioIn); - inline void removeAsyncIO(casAsyncIOI &ioIn); + void removeAsyncIO(casAsyncIOI &ioIn); - inline casRes *lookupRes(const caResId &idIn, casResType type); + casRes *lookupRes(const caResId &idIn, casResType type); - inline caServerI &getCAS() const; + caServerI &getCAS() const; - virtual caStatus monitorResponse(casChannelI &chan, const caHdr &msg, + virtual caStatus monitorResponse (casChannelI &chan, const caHdr &msg, const gdd *pDesc, const caStatus status); virtual caStatus accessRightsResponse(casChannelI *); @@ -434,7 +445,7 @@ public: // asynchronous completion // virtual caStatus asyncSearchResponse( - casDGIntfIO &outMsgIO, const caNetAddr &outAddr, + const caNetAddr &outAddr, const caHdr &, const pvExistReturn &); virtual caStatus createChanResponse( const caHdr &, const pvAttachReturn &); @@ -446,11 +457,10 @@ public: virtual caStatus writeNotifyResponse (const caHdr &, const caStatus); // - // The following are only used with async IO for - // DG clients + // used only with DG clients // - virtual caNetAddr fetchRespAddr(); - virtual casDGIntfIO* fetchOutIntf(); + virtual caNetAddr fetchLastRecvAddr () const; + protected: casCtx ctx; unsigned char asyncIOFlag; @@ -462,20 +472,19 @@ private: // // casClient // -class casClient; -typedef caStatus (casClient::*pCASMsgHandler) (); -class casClient : public casCoreClient { +class casClient : public casCoreClient, public inBuf, public outBuf { public: - casClient (caServerI &, inBuf &, outBuf &); - caStatus init(); //constructor does not return status + typedef caStatus (casClient::*pCASMsgHandler) (); + + casClient (caServerI &, bufSizeT ioMinSizeIn); virtual ~casClient (); - void show(unsigned level) const; + void show (unsigned level) const; // // send error response to a message // - caStatus sendErr(const caHdr *, const int reportedStatus, + caStatus sendErr (const caHdr *, const int reportedStatus, const char *pFormat, ...); unsigned getMinorVersion() const {return this->minor_version_number;} @@ -484,37 +493,27 @@ public: // // find the channel associated with a resource id // - casChannelI *resIdToChannel(const caResId &id); + casChannelI *resIdToChannel (const caResId &id); - virtual void clientHostName (char *pBuf, - unsigned bufSize) const = 0; + virtual void clientHostName (char *pBuf, unsigned bufSize) const = 0; protected: unsigned minor_version_number; osiTime lastSendTS; osiTime lastRecvTS; - caStatus processMsg(); - - - // - // - // caStatus sendErrWithEpicsStatus(const caHdr *pMsg, caStatus epicsStatus, caStatus clientStatus); - // - // logBadIdWithFileAndLineno() - // # define logBadId(MP, DP, CACSTAT, RESID) \ this->logBadIdWithFileAndLineno(MP, DP, CACSTAT, __FILE__, __LINE__, RESID) caStatus logBadIdWithFileAndLineno(const caHdr *mp, const void *dp, const int cacStat, const char *pFileName, const unsigned lineno, const unsigned resId); + caStatus processMsg(); + private: - inBuf &inBufRef; - outBuf &outBufRef; // // dump message to stderr @@ -557,16 +556,13 @@ private: static int msgHandlersInit; }; - - // // casStrmClient // -class casStrmClient : public inBuf, public outBuf, public casClient, +class casStrmClient : public casClient, public tsDLNode { public: casStrmClient (caServerI &cas); - caStatus init(); //constructor does not return status virtual ~casStrmClient(); void show (unsigned level) const; @@ -596,9 +592,6 @@ public: caStatus monitorResponse(casChannelI &chan, const caHdr &msg, const gdd *pDesc, const caStatus status); - // - // - // caStatus noReadAccessEvent(casClientMon *); // @@ -610,6 +603,11 @@ public: caStatus disconnectChan (caResId id); unsigned getDebugLevel() const; + + virtual void clientHostName (char *pBuf, unsigned bufSize) const = 0; + +protected: + private: tsDLList chanList; char *pUserName; @@ -665,14 +663,16 @@ private: // // io independent send/recv // - xSendStatus xSend (char *pBuf, bufSizeT nBytesAvailableToSend, + outBuf::flushCondition xSend (char *pBuf, bufSizeT nBytesAvailableToSend, bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent); - xRecvStatus xRecv (char *pBuf, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv); + inBuf::fillCondition xRecv (char *pBuf, bufSizeT nBytesToRecv, + fillParameter parm, bufSizeT &nByesRecv); + virtual xBlockingStatus blockingState() const = 0; - virtual xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, + + virtual outBuf::flushCondition osdSend (const char *pBuf, bufSizeT nBytesReq, bufSizeT &nBytesActual) = 0; - virtual xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, + virtual inBuf::fillCondition osdRecv (char *pBuf, bufSizeT nBytesReq, bufSizeT &nBytesActual) = 0; caStatus readNotifyResponseECA_XXX (casChannelI *pChan, @@ -683,32 +683,33 @@ private: class casDGIntfIO; - + // // casDGClient // -class casDGClient : public dgInBuf, public dgOutBuf, public casClient { +class casDGClient : public casClient { public: casDGClient (caServerI &serverIn); virtual ~casDGClient(); - caStatus init(); // constructor does not return status - void show (unsigned level) const; // // only for use with DG io // - static void sendBeacon(casDGIntfIO &io); + void sendBeacon (); + virtual void sendBeaconIO (char &msg, unsigned length, aitUint32 &m_ipa, aitUint16 &m_port) = 0; void destroy(); - void processDG(casDGIntfIO &inMsgIO, casDGIntfIO &outMsgIO); - unsigned getDebugLevel() const; - virtual void clientHostName (char *pBuf, - unsigned bufSize) const = 0; + void clientHostName (char *pBuf, unsigned bufSize) const; + + caNetAddr fetchLastRecvAddr () const; + + virtual caNetAddr serverAddress () const = 0; + protected: @@ -717,11 +718,10 @@ protected: return this->casEventSys::process(); } -private: - casDGIntfIO *pOutMsgIO; - casDGIntfIO *pInMsgIO; + caStatus processDG (); - void ioBlockedSignal(); // dummy +private: + caNetAddr lastRecvAddr; // // one function for each CA request type @@ -731,24 +731,34 @@ private: // // searchFailResponse() // - caStatus searchFailResponse(const caHdr *pMsg); + caStatus searchFailResponse (const caHdr *pMsg); - caStatus searchResponse(const caHdr &, const pvExistReturn &); + caStatus searchResponse (const caHdr &, const pvExistReturn &); - caStatus asyncSearchResponse( - casDGIntfIO &outMsgIO, const caNetAddr &outAddr, + caStatus asyncSearchResponse (const caNetAddr &outAddr, const caHdr &msg, const pvExistReturn &); - caNetAddr fetchRespAddr(); - casDGIntfIO* fetchOutIntf(); // // IO depen // - xRecvStatus xDGRecv (char *pBuf, bufSizeT nBytesToRecv, - bufSizeT &nByesRecv, caNetAddr &sender); - xSendStatus xDGSend (char *pBuf, bufSizeT nBytesNeedToBeSent, - bufSizeT &nBytesSent, const caNetAddr &recipient); - bufSizeT incommingBytesPresent() const; + outBuf::flushCondition xSend (char *pBufIn, bufSizeT nBytesAvailableToSend, + bufSizeT nBytesNeedToBeSent, bufSizeT &nBytesSent); + inBuf::fillCondition xRecv (char *pBufIn, bufSizeT nBytesToRecv, + fillParameter parm, bufSizeT &nByesRecv); + + virtual outBuf::flushCondition osdSend (const char *pBuf, bufSizeT nBytesReq, + const caNetAddr &addr) = 0; + virtual inBuf::fillCondition osdRecv (char *pBuf, bufSizeT nBytesReq, + fillParameter parm, bufSizeT &nBytesActual, caNetAddr &addr) = 0; + + // + // cadg + // + struct cadg { + caNetAddr cadg_addr; // invalid address indicates pad + bufSizeT cadg_nBytes; + }; + }; // @@ -776,9 +786,9 @@ class casEventRegistry : private resTable { friend class casEventMaskEntry; public: - casEventRegistry (osiMutex &mutexIn) : + casEventRegistry () : resTable (casEventRegistryHashTableSize), - mutex(mutexIn), allocator(0) {} + allocator(0) {} virtual ~casEventRegistry(); @@ -787,7 +797,6 @@ public: void show (unsigned level) const; private: - osiMutex &mutex; unsigned allocator; casEventMask maskAllocator(); @@ -816,7 +825,7 @@ public: // // find the channel associated with a resource id // - inline casChannelI *resIdToChannel(const caResId &id); + casChannelI *resIdToChannel(const caResId &id); // // find the PV associated with a resource id @@ -828,60 +837,69 @@ public: // casClientMon *resIdToClientMon(const caResId &idIn); - casDGClient &castClient() {return this->dgClient;} + void installClient (casStrmClient *pClient); - void installClient(casStrmClient *pClient); - - void removeClient(casStrmClient *pClient); + void removeClient (casStrmClient *pClient); // // is there space for a new channel // - aitBool roomForNewChannel() const; + bool roomForNewChannel() const; + + unsigned getDebugLevel() const { return debugLevel; } + inline void setDebugLevel (unsigned debugLevelIn); + + void show(unsigned level) const; + + casRes *lookupRes (const caResId &idIn, casResType type); + + caServer *getAdapter (); + + void installItem (casRes &res); + + casRes *removeItem (casRes &res); + + // + // call virtual function in the interface class + // + caServer * operator -> (); + + void connectCB (casIntfOS &); + + // + // common event masks + // (what is currently used by the CA clients) + // + casEventMask valueEventMask() const; // DBE_VALUE registerEvent("value") + casEventMask logEventMask() const; // DBE_LOG registerEvent("log") + casEventMask alarmEventMask() const; // DBE_ALARM registerEvent("alarm") + +private: + void advanceBeaconPeriod(); + + tsDLList clientList; + tsDLList intfList; + double maxBeaconInterval; + double beaconPeriod; + caServer &adapter; + unsigned debugLevel; + + // + // predefined event types + // + casEventMask valueEvent; // DBE_VALUE registerEvent("value") + casEventMask logEvent; // DBE_LOG registerEvent("log") + casEventMask alarmEvent; // DBE_ALARM registerEvent("alarm") + + double getBeaconPeriod() const; // // send beacon and advance beacon timer // void sendBeacon(); - unsigned getDebugLevel() const { return debugLevel; } - inline void setDebugLevel(unsigned debugLevelIn); - - double getBeaconPeriod() const { return this->beaconPeriod; } - - void show(unsigned level) const; - - inline casRes *lookupRes(const caResId &idIn, casResType type); - - inline caServer *getAdapter(); - - inline void installItem (casRes &res); - - inline casRes *removeItem(casRes &res); - - // - // call virtual function in the interface class - // - inline caServer * operator -> (); - - void connectCB(casIntfOS &); - - inline aitBool ready(); - - caStatus addAddr(const caNetAddr &addr, int autoBeaconAddr, - int addConfigAddr); -private: - void advanceBeaconPeriod(); - - casDGOS dgClient; - //casCtx ctx; - tsDLList clientList; - tsDLList intfList; - double maxBeaconInterval; - double beaconPeriod; - caServer &adapter; - unsigned debugLevel; - unsigned char haveBeenInitialized; + caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr, + bool addConfigAddr); }; #define CAServerConnectPendQueueSize 10 diff --git a/src/cas/generic/st/caServerOS.cc b/src/cas/generic/st/caServerOS.cc index 2f38e3681..44c879e38 100644 --- a/src/cas/generic/st/caServerOS.cc +++ b/src/cas/generic/st/caServerOS.cc @@ -4,21 +4,6 @@ * caServerOS.c * $Id$ * - * - * $Log$ - * Revision 1.2 1997/04/10 19:34:28 jhill - * API changes - * - * Revision 1.1 1996/11/02 01:01:27 jhill - * installed - * - * Revision 1.2 1996/08/05 19:28:49 jhill - * space became tab - * - * Revision 1.1.1.1 1996/06/20 00:28:06 jhill - * ca server installation - * - * */ @@ -32,23 +17,35 @@ // class casBeaconTimer : public osiTimer { public: - casBeaconTimer (double delay, caServerOS &osIn) : - osiTimer(delay), os (osIn) {} - void expire(); - double delay() const; - bool again() const; - const char *name() const; + casBeaconTimer (double delay, caServerOS &osIn) : + osiTimer(delay), os (osIn) {} + void expire(); + double delay() const; + bool again() const; + const char *name() const; private: - caServerOS &os; - + caServerOS &os; }; // -// aServerOS::operator -> () +// caServerOS::caServerOS() // -inline caServerI * caServerOS::operator -> () +caServerOS::caServerOS () { - return &this->cas; + this->pBTmr = new casBeaconTimer(0.0, *this); + if (!this->pBTmr) { + throw S_cas_noMemory; + } +} + +// +// caServerOS::~caServerOS() +// +caServerOS::~caServerOS() +{ + if (this->pBTmr) { + delete this->pBTmr; + } } // @@ -56,7 +53,7 @@ inline caServerI * caServerOS::operator -> () // void casBeaconTimer::expire() { - os->sendBeacon (); + os.sendBeacon (); } // @@ -72,7 +69,7 @@ bool casBeaconTimer::again() const // double casBeaconTimer::delay() const { - return os->getBeaconPeriod(); + return os.getBeaconPeriod(); } // @@ -83,27 +80,3 @@ const char *casBeaconTimer::name() const return "casBeaconTimer"; } -// -// caServerOS::init() -// -caStatus caServerOS::init() -{ - this->pBTmr = new casBeaconTimer((*this)->getBeaconPeriod(), *this); - if (!this->pBTmr) { - ca_printf("CAS: Unable to start server beacon\n"); - return S_cas_noMemory; - } - - return S_cas_success; -} - -// -// caServerOS::~caServerOS() -// -caServerOS::~caServerOS() -{ - if (this->pBTmr) { - delete this->pBTmr; - } -} - diff --git a/src/cas/generic/st/casDGIntfOS.cc b/src/cas/generic/st/casDGIntfOS.cc index 4edfcd298..e61e54e77 100644 --- a/src/cas/generic/st/casDGIntfOS.cc +++ b/src/cas/generic/st/casDGIntfOS.cc @@ -1,16 +1,18 @@ -/* - * - * casDGIntfOS.cc - * $Id$ - * - * - */ +// +// +// 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 // @@ -29,23 +31,302 @@ private: void callBack (); }; +// +// casDGBCastReadReg +// +class casDGBCastReadReg : public fdReg { +public: + casDGBCastReadReg (casDGIntfOS &osIn) : + fdReg (osIn.getBCastFD(), fdrRead), os (osIn) {} + ~casDGBCastReadReg (); + + void show (unsigned level) const; +private: + casDGIntfOS &os; + + void callBack (); +}; + +// +// casDGWriteReg +// +class casDGWriteReg : public fdReg { +public: + casDGWriteReg (casDGIntfOS &osIn) : + fdReg (osIn.getFD(), fdrWrite), os (osIn) {} + ~casDGWriteReg (); + + void show (unsigned level) const; +private: + casDGIntfOS &os; + + void callBack (); +}; + +// +// class casDGEvWakeup +// +class casDGEvWakeup : public osiTimer { +public: + + casDGEvWakeup(casDGIntfOS &osIn) : + osiTimer(0.0), os(osIn) {} + + ~casDGEvWakeup(); + + void expire(); + + void show(unsigned level) const; + + const char *name() const; + +private: + casDGIntfOS &os; +}; + +// +// class casDGIOWakeup +// +class casDGIOWakeup : public osiTimer { +public: + casDGIOWakeup (casDGIntfOS &osIn) : + osiTimer (0.0), os(osIn) {} + ~casDGIOWakeup (); + + void expire(); + + void show(unsigned level) const; + + const char *name() const; +private: + casDGIntfOS &os; +}; + // // casDGIntfOS::casDGIntfOS() // -casDGIntfOS::casDGIntfOS(casDGClient &clientIn) : - casDGIntfIO(clientIn), - pRdReg(NULL) +casDGIntfOS::casDGIntfOS (caServerI &serverIn, const caNetAddr &addr, + bool autoBeaconAddr, bool addConfigBeaconAddr) : + casDGIntfIO (serverIn, addr, autoBeaconAddr, addConfigBeaconAddr), + pRdReg (NULL), + pBCastRdReg (NULL), + pWtReg (NULL), + pEvWk (NULL), + pIOWk (NULL), + sendBlocked (false) { + this->xSetNonBlocking(); + this->armRecv(); } // // casDGIntfOS::~casDGIntfOS() // casDGIntfOS::~casDGIntfOS() +{ + this->disarmSend(); + + this->disarmRecv(); + + if (this->pEvWk) { + delete this->pEvWk; + } + + if (this->pIOWk) { + delete this->pIOWk; + } +} + + +// +// casDGEvWakeup::~casDGEvWakeup() +// +casDGEvWakeup::~casDGEvWakeup() +{ + this->os.pEvWk = NULL; +} + +// +// casDGEvWakeup::name() +// +const char *casDGEvWakeup::name() const +{ + return "casDGEvWakeup"; +} + +// +// casDGEvWakeup::show() +// +void casDGEvWakeup::show(unsigned level) const +{ + printf ("casDGEvWakeup at %p {\n", this); + this->osiTimer::show(level); + printf ("}\n"); +} + +// +// casDGEvWakeup::expire() +// +void casDGEvWakeup::expire() +{ + this->os.casEventSys::process(); +} + +// +// casDGIOWakeup::~casDGIOWakeup() +// +casDGIOWakeup::~casDGIOWakeup() +{ + this->os.pIOWk = NULL; +} + +// +// casDGIOWakeup::expire() +// +// Running this indirectly off of the timer queue +// guarantees that we will not call processInput() +// recursively +// +void casDGIOWakeup::expire() +{ + // + // in case there is something in the input buffer + // and currently nothing to be read from UDP + // + // processInput() does an armRecv() so + // if recv is not armed, there is space in + // the input buffer, and there eventually will + // be something to read from TCP this works + // + this->os.processInput (); +} + +// +// casDGIOWakeup::name() +// +const char *casDGIOWakeup::name() const +{ + return "casDGIOWakeup"; +} + +// +// casDGIOWakeup::show() +// +void casDGIOWakeup::show(unsigned level) const +{ + printf ("casDGIOWakeup at %p {\n", this); + this->osiTimer::show(level); + printf ("}\n"); +} + +// +// casDGIntfOS::armRecv () +// +inline void casDGIntfOS::armRecv() +{ + if (!this->pRdReg) { + if (this->inBuf::full()!=aitTrue) { + this->pRdReg = new casDGReadReg(*this); + if (!this->pRdReg) { + errMessage (S_cas_noMemory, "armRecv()"); + throw S_cas_noMemory; + } + } + } + if (this->validBCastFD() && this->pBCastRdReg==NULL) { + if (this->inBuf::full()!=aitTrue) { + this->pBCastRdReg = new casDGBCastReadReg(*this); + if (!this->pBCastRdReg) { + errMessage (S_cas_noMemory, "armRecv()"); + throw S_cas_noMemory; + } + } + } +} + +// +// casDGIntfOS::disarmRecv() +// +inline void casDGIntfOS::disarmRecv() { if (this->pRdReg) { delete this->pRdReg; } + if (this->pBCastRdReg) { + delete this->pBCastRdReg; + } +} + +// +// casDGIntfOS::armSend() +// +inline void casDGIntfOS::armSend() +{ + if (this->outBuf::bytesPresent()==0u) { + return; + } + + if (!this->pWtReg) { + this->pWtReg = new casDGWriteReg(*this); + if (!this->pWtReg) { + errMessage (S_cas_noMemory, "armSend()"); + throw S_cas_noMemory; + } + } +} + +// +// casDGIntfOS::disarmSend() +// +inline void casDGIntfOS::disarmSend () +{ + if (this->pWtReg) { + delete this->pWtReg; + } +} + +// +// casDGIntfOS::ioBlockedSignal() +// +void casDGIntfOS::ioBlockedSignal() +{ + if (!this->pIOWk) { + this->pIOWk = new casDGIOWakeup(*this); + if (!this->pIOWk) { + errMessage (S_cas_noMemory, + "casDGIntfOS::ioBlockedSignal()"); + throw S_cas_noMemory; + } + } +} + +// +// casDGIntfOS::eventSignal() +// +void casDGIntfOS::eventSignal() +{ + if (!this->pEvWk) { + this->pEvWk = new casDGEvWakeup (*this); + if (!this->pEvWk) { + errMessage (S_cas_noMemory, + "casDGIntfOS::eventSignal ()"); + throw S_cas_noMemory; + } + } +} + +// +// casDGIntfOS::eventFlush() +// +void casDGIntfOS::eventFlush() +{ + // + // if there is nothing pending in the input + // queue, then flush the output queue + // + if (this->inBuf::bytesAvailable()==0u) { + this->armSend (); + } } // @@ -55,22 +336,20 @@ void casDGIntfOS::show(unsigned level) const { printf ("casDGIntfOS at %p\n", this); if (this->pRdReg) { - this->pRdReg->show(level); + this->pRdReg->show (level); } -} - -/* - * casDGIntfOS::start() - */ -caStatus casDGIntfOS::start() -{ - if (this->pRdReg==NULL) { - this->pRdReg = new casDGReadReg (*this); - if (this->pRdReg==NULL) { - return S_cas_noMemory; - } + if (this->pWtReg) { + this->pWtReg->show (level); } - return S_cas_success; + if (this->pBCastRdReg) { + this->pBCastRdReg->show (level); + } + if (this->pEvWk) { + this->pEvWk->show (level); + } + if (this->pIOWk) { + this->pIOWk->show (level); + } } // @@ -78,16 +357,7 @@ caStatus casDGIntfOS::start() // void casDGReadReg::callBack() { - this->os.recvCB(); -} - -// -// casDGIntfOS::recvCB() -// -void casDGIntfOS::recvCB() -{ - assert (this->pRdReg); - this->processDG(); + this->os.recvCB (inBuf::fpNone); } // @@ -95,6 +365,7 @@ void casDGIntfOS::recvCB() // casDGReadReg::~casDGReadReg() { + os.pRdReg = NULL; } // @@ -106,3 +377,178 @@ void casDGReadReg::show(unsigned level) const printf("casDGReadReg at %p\n", this); } +// +// casDGBCastReadReg::callBack() +// +void casDGBCastReadReg::callBack() +{ + this->os.recvCB (inBuf::fpUseBroadcastInterface); +} + +// +// casDGBCastReadReg::~casDGBCastReadReg() +// +casDGBCastReadReg::~casDGBCastReadReg() +{ + os.pBCastRdReg = NULL; +} + +// +// casDGReadReg::show() +// +void casDGBCastReadReg::show(unsigned level) const +{ + this->fdReg::show(level); + printf("casDGBCastReadReg at %p\n", this); +} + +// +// casDGWriteReg::~casDGWriteReg() +// +casDGWriteReg::~casDGWriteReg() +{ + os.pWtReg = NULL; // allow rearm (send callbacks are one shots) +} + +// +// casDGWriteReg::callBack() +// +void casDGWriteReg::callBack() +{ + casDGIntfOS *pDGIOS = &this->os; + delete this; // allows rearm to occur if required + pDGIOS->sendCB(); + // + // NO CODE HERE - see delete above + // +} + +// +// casDGWriteReg::show() +// +void casDGWriteReg::show(unsigned level) const +{ + this->fdReg::show (level); + printf ("casDGWriteReg: at %p\n", this); +} + +// +// casDGIntfOS::sendBlockSignal() +// +void casDGIntfOS::sendBlockSignal() +{ + this->sendBlocked=TRUE; + this->armSend(); +} + +// +// casDGIntfOS::sendCB() +// +void casDGIntfOS::sendCB() +{ + flushCondition flushCond; + + // + // attempt to flush the output buffer + // + flushCond = this->flush(); + if (flushCond==flushProgress) { + if (this->sendBlocked) { + this->sendBlocked = FALSE; + } + // + // this reenables receipt of incoming frames once + // the output has been flushed when the incomming + // address is different + // + this->armRecv (); + } + +# if defined(DEBUG) + printf ("write attempted on %d result was %d\n", this->getFD(), flushCond); + printf ("Recv backlog %u\n", this->inBuf::bytesPresent()); + printf ("Send backlog %u\n", this->outBuf::bytesPresent()); +# endif + + // + // If we are unable to flush out all of the events + // in casDgEvWakeup::expire() because the + // client is slow then we must check again here when + // we _are_ able to write to see if additional events + // can be sent to the slow client. + // + this->casEventSys::process(); + + // + // If we were able to send something then we need + // to process the input queue in case we were send + // blocked. + // + this->processInput (); +} + +// +// casDGIntfOS::recvCB() +// +void casDGIntfOS::recvCB (inBuf::fillParameter parm) +{ + caNetAddr from; + + assert (this->pRdReg); + + // + // copy in new messages + // + this->inBuf::fill (parm); + this->processInput (); + + // + // If there isnt any space then temporarily + // stop calling this routine until problem is resolved + // either by: + // (1) sending or + // (2) a blocked IO op unblocks + // + // (casDGReadReg is _not_ a onceOnly fdReg - + // therefore an explicit delete is required here) + // + if (this->inBuf::full()==aitTrue) { + this->disarmRecv(); // this deletes the casDGReadReg object + } +} + +// +// casDGIntfOS::processInput() +// +void casDGIntfOS::processInput() +{ + caStatus status; + + // + // attempt to process the datagram in the input + // buffer + // + status = this->processDG (); + if (status!=S_cas_success && + status!=S_cas_sendBlocked && + status!=S_casApp_postponeAsyncIO) { + char pName[64u]; + + this->clientHostName (pName, sizeof (pName)); + errPrintf (status, __FILE__, __LINE__, + "unexpected problem with UDP input from \"%s\"", pName); + } + + // + // if anything is in the send buffer + // and there are not requests pending in the + // input buffer then keep sending the output + // buffer until it is empty + // + if (this->outBuf::bytesPresent()>0u) { + if ( this->bytesAvailable () == 0 ) { + this->armSend (); + } + } +} + diff --git a/src/cas/generic/st/casDGOS.cc b/src/cas/generic/st/casDGOS.cc index 5cff13603..2e6832549 100644 --- a/src/cas/generic/st/casDGOS.cc +++ b/src/cas/generic/st/casDGOS.cc @@ -6,6 +6,9 @@ * * * $Log$ + * Revision 1.7 1999/08/05 00:07:56 jhill + * osiTimer constructor now requires delay of type double + * * Revision 1.6 1998/10/23 00:27:14 jhill * fixed problem where send was not always rearmed if this * was indirectly necessary in the send callback because @@ -39,6 +42,8 @@ * */ +#if 0 + // // CA server // @@ -114,6 +119,8 @@ void casDGEvWakeup::expire() // void casDGOS::sendBlockSignal() { + this->sendBlocked=TRUE; + this->armSend(); } // @@ -124,8 +131,9 @@ void casDGOS::eventSignal() if (!this->pEvWk) { this->pEvWk = new casDGEvWakeup(*this); if (!this->pEvWk) { - errMessage(S_cas_noMemory, + errMessage (S_cas_noMemory, "casDGOS::eventSignal()"); + throw S_cas_noMemory; } } } @@ -135,10 +143,15 @@ void casDGOS::eventSignal() // void casDGOS::eventFlush() { - this->flush(); + // + // if there is nothing pending in the input + // queue, then flush the output queue + // + if (this->inBuf::bytesAvailable()==0u) { + this->armSend (); + } } - // // casDGOS::casDGOS() // @@ -148,7 +161,6 @@ casDGOS::casDGOS(caServerI &cas) : { } - // // casDGOS::~casDGOS() // @@ -171,7 +183,6 @@ void casDGOS::show(unsigned level) const } } - // // casDGOS::processInput () // - a noop @@ -181,12 +192,4 @@ casProcCond casDGOS::processInput () return casProcOk; } -// -// casDGOS::start() -// - a noop -// -caStatus casDGOS::start() -{ - return S_cas_success; -} - +#endif \ No newline at end of file diff --git a/src/cas/generic/st/casIntfOS.cc b/src/cas/generic/st/casIntfOS.cc index 9fb8e8271..4a4741015 100644 --- a/src/cas/generic/st/casIntfOS.cc +++ b/src/cas/generic/st/casIntfOS.cc @@ -12,6 +12,7 @@ // CA server // #include "server.h" +#include "casIODIL.h" // // casServerReg @@ -19,7 +20,7 @@ class casServerReg : public fdReg { public: casServerReg (casIntfOS &osIn) : - fdReg (osIn.getFD(), fdrRead), os (osIn) {} + fdReg (osIn.casIntfIO::getFD(), fdrRead), os (osIn) {} ~casServerReg (); private: casIntfOS &os; @@ -27,34 +28,25 @@ private: void callBack (); }; - // -// casIntfOS::init() +// casIntfOS::casIntfOS() // -caStatus casIntfOS::init(const caNetAddr &addrIn, casDGClient &dgClientIn, - int autoBeaconAddr, int addConfigBeaconAddr) -{ - caStatus stat; - - stat = this->casIntfIO::init(addrIn, dgClientIn, - autoBeaconAddr, addConfigBeaconAddr); - if (stat) { - return stat; - } - - this->setNonBlocking(); - - if (this->pRdReg==NULL) { - this->pRdReg = new casServerReg(*this); - if (this->pRdReg==NULL) { - return S_cas_noMemory; - } - } - - return S_cas_success; +casIntfOS::casIntfOS (caServerI &casIn, const caNetAddr &addrIn, + bool autoBeaconAddr, bool addConfigBeaconAddr) : + casDGIntfOS (casIn, addrIn, autoBeaconAddr, addConfigBeaconAddr), + cas (casIn), + casIntfIO (addrIn) +{ + this->setNonBlocking(); + + this->pRdReg = new casServerReg(*this); + if (this->pRdReg==NULL) { + errMessage (S_cas_noMemory, + "casIntfOS::casIntfOS()"); + throw S_cas_noMemory; + } } - // // casIntfOS::~casIntfOS() // @@ -65,15 +57,6 @@ casIntfOS::~casIntfOS() } } -// -// casIntfOS::newDGIntfIO() -// -casDGIntfIO *casIntfOS::newDGIntfIO(casDGClient &dgClientIn) const -{ - return new casDGIntfOS(dgClientIn); -} - - // // casServerReg::callBack() // @@ -90,3 +73,21 @@ casServerReg::~casServerReg() { } +// +// casIntfOS::show () +// +void casIntfOS::show (unsigned level) +{ + printf ("casIntfOS at %p\n", this); + this->casIntfIO::show (level); + 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 b375f51c7..ae704c2a8 100644 --- a/src/cas/generic/st/casOSD.h +++ b/src/cas/generic/st/casOSD.h @@ -27,61 +27,92 @@ class casBeaconTimer; // class caServerOS { friend class casServerReg; + friend class casBeaconTimer; public: - caServerOS (caServerI &casIn) : - cas (casIn), pBTmr (NULL) {} - caStatus init (); + caServerOS (); virtual ~caServerOS (); - caStatus start (); - - inline caServerI * operator -> (); private: - caServerI &cas; casBeaconTimer *pBTmr; + + virtual double getBeaconPeriod() const = 0; + virtual void sendBeacon() = 0; }; -class casDGClient; class casDGReadReg; +class casDGBCastReadReg; +class casDGWriteReg; +class casDGEvWakeup; +class casDGIOWakeup; // // casDGIntfOS // class casDGIntfOS : public casDGIntfIO { + friend class casDGReadReg; + friend class casDGBCastReadReg; + friend class casDGWriteReg; + friend class casDGEvWakeup; + friend class casDGIOWakeup; public: - casDGIntfOS(casDGClient &client); - virtual ~casDGIntfOS(); - caStatus start(); + casDGIntfOS (caServerI &serverIn, const caNetAddr &addr, + bool autoBeaconAddr=TRUE, bool addConfigBeaconAddr=FALSE); - void show(unsigned level) const; + virtual ~casDGIntfOS (); + + void show (unsigned level) const; - void recvCB(); - void sendCB(); private: - casDGReadReg *pRdReg; + casDGReadReg *pRdReg; + casDGBCastReadReg *pBCastRdReg; // fix for solaris bug + casDGWriteReg *pWtReg; + casDGEvWakeup *pEvWk; + casDGIOWakeup *pIOWk; + unsigned char sendBlocked; + + void armRecv (); + void armSend (); + + void disarmRecv (); + void disarmSend (); + + void recvCB (inBuf::fillParameter parm); + void sendCB (); + + void sendBlockSignal (); + + void ioBlockedSignal (); + + void eventSignal (); + void eventFlush (); + + void processInput(); }; // // casIntfOS // -class casIntfOS : public casIntfIO, public tsDLNode +class casIntfOS : public casIntfIO, public tsDLNode, + public casDGIntfOS { + friend class casDGEvWakeup; friend class casServerReg; public: - casIntfOS (caServerI &casIn) : - cas (casIn), pRdReg (NULL) {} - caStatus init(const caNetAddr &addr, casDGClient &dgClientIn, - int autoBeaconAddr, int addConfigBeaconAddr); + casIntfOS (caServerI &casIn, const caNetAddr &addr, + bool autoBeaconAddr=true, bool addConfigBeaconAddr=false); virtual ~casIntfOS(); + void show (unsigned level); + + caNetAddr serverAddress () const; + +private: + caServerI &cas; + casServerReg *pRdReg; + void recvCB (); void sendCB () {}; // NOOP satifies template - - casDGIntfIO *newDGIntfIO (casDGClient &dgClientIn) const; -private: - caServerI &cas; - casServerReg *pRdReg; }; class casStreamWriteReg; @@ -93,28 +124,13 @@ class casStreamIOWakeup; // casStreamOS // class casStreamOS : public casStreamIO { + friend class casStreamWriteReg; + friend class casStreamReadReg; friend class casStreamEvWakeup; friend class casStreamIOWakeup; public: - casStreamOS(caServerI &, const ioArgsToNewStreamIO &ioArgs); - caStatus init(); - ~casStreamOS(); - - // - // process any incomming messages - // - casProcCond processInput(); - caStatus start(); - - void recvCB(); - void sendCB(); - - void sendBlockSignal(); - - void ioBlockedSignal(); - - void eventSignal(); - void eventFlush(); + casStreamOS (caServerI &, const ioArgsToNewStreamIO &ioArgs); + ~casStreamOS (); void show (unsigned level) const; private: @@ -122,7 +138,7 @@ private: casStreamReadReg *pRdReg; casStreamEvWakeup *pEvWk; casStreamIOWakeup *pIOWk; - unsigned sendBlocked:1; + unsigned char sendBlocked; // // // @@ -130,34 +146,21 @@ private: inline void armRecv (); inline void disarmSend(); inline void disarmRecv(); -}; - -class casDGEvWakeup; - -// -// casDGOS -// -class casDGOS : public casDGIO { - friend class casDGEvWakeup; -public: - casDGOS(caServerI &cas); - ~casDGOS(); // // process any incomming messages // - casProcCond processInput(); + casProcCond processInput (); - void sendBlockSignal(); + void recvCB (); + void sendCB (); - void eventSignal(); - void eventFlush(); + void sendBlockSignal (); + + void ioBlockedSignal (); - void show(unsigned level) const; - - caStatus start(); -private: - casDGEvWakeup *pEvWk; + void eventSignal (); + void eventFlush (); }; // no additions below this line diff --git a/src/cas/generic/st/casStreamOS.cc b/src/cas/generic/st/casStreamOS.cc index 07c49c3b3..b22517a3f 100644 --- a/src/cas/generic/st/casStreamOS.cc +++ b/src/cas/generic/st/casStreamOS.cc @@ -51,6 +51,7 @@ inline casStreamReadReg::casStreamReadReg (casStreamOS &osIn) : // inline casStreamReadReg::~casStreamReadReg () { + os.pRdReg = NULL; # if defined(DEBUG) printf ("Read off %d\n", this->os.getFD()); printf ("Recv backlog %u\n", @@ -95,6 +96,7 @@ inline casStreamWriteReg::casStreamWriteReg (casStreamOS &osIn) : // inline casStreamWriteReg::~casStreamWriteReg () { + os.pWtReg = NULL; # if defined(DEBUG) printf ("Write off %d\n", this->os.getFD()); printf ("Recv backlog %u\n", @@ -231,6 +233,7 @@ inline void casStreamOS::armRecv() this->pRdReg = new casStreamReadReg(*this); if (!this->pRdReg) { errMessage(S_cas_noMemory, "armRecv()"); + throw S_cas_noMemory; } } } @@ -264,7 +267,6 @@ inline void casStreamOS::disarmRecv() { if (this->pRdReg) { delete this->pRdReg; - this->pRdReg = NULL; } } @@ -281,6 +283,7 @@ inline void casStreamOS::armSend() this->pWtReg = new casStreamWriteReg(*this); if (!this->pWtReg) { errMessage(S_cas_noMemory, "armSend() failed"); + throw S_cas_noMemory; } } } @@ -292,7 +295,6 @@ inline void casStreamOS::disarmSend () { if (this->pWtReg) { delete this->pWtReg; - this->pWtReg = NULL; } } @@ -306,6 +308,7 @@ void casStreamOS::ioBlockedSignal() if (!this->pIOWk) { errMessage(S_cas_noMemory, "casStreamOS::ioBlockedSignal()"); + throw S_cas_noMemory; } } } @@ -320,6 +323,7 @@ void casStreamOS::eventSignal() if (!this->pEvWk) { errMessage(S_cas_noMemory, "casStreamOS::eventSignal()"); + throw S_cas_noMemory; } } } @@ -338,41 +342,21 @@ void casStreamOS::eventFlush() } } - // // casStreamOS::casStreamOS() // casStreamOS::casStreamOS(caServerI &cas, const ioArgsToNewStreamIO &ioArgs) : - casStreamIO(cas, ioArgs), - pWtReg(NULL), - pRdReg(NULL), - pEvWk(NULL), - pIOWk(NULL), - sendBlocked(FALSE) + casStreamIO (cas, ioArgs), + pWtReg (NULL), + pRdReg (NULL), + pEvWk (NULL), + pIOWk (NULL), + sendBlocked (FALSE) { -} - -// -// casStreamOS::init() -// -caStatus casStreamOS::init() -{ - caStatus status; - - // - // init the base classes - // - status = this->casStreamIO::init(); - if (status) { - return status; - } - this->xSetNonBlocking(); - - return S_cas_success; + this->armRecv(); } - // // casStreamOS::~casStreamOS() // @@ -417,17 +401,6 @@ void casStreamOS::show(unsigned level) const } } - -// -// casClientStart () -// -caStatus casStreamOS::start() -{ - this->armRecv(); - return S_cas_success; -} - - // // casStreamReadReg::show() // @@ -454,7 +427,7 @@ void casStreamReadReg::callBack () // void casStreamOS::recvCB() { - casFillCondition fillCond; + inBuf::fillCondition fillCond; casProcCond procCond; assert (this->pRdReg); @@ -463,31 +436,34 @@ void casStreamOS::recvCB() // copy in new messages // fillCond = this->fill(); - procCond = this->processInput(); - if (fillCond == casFillDisconnect || - procCond == casProcDisconnect) { + if (fillCond == casFillDisconnect) { delete this; - } - else if (this->inBuf::full()==aitTrue) { - // - // If there isnt any space then temporarily - // stop calling this routine until problem is resolved - // either by: - // (1) sending or - // (2) a blocked IO op unblocks - // - // (casStreamReadReg is _not_ a onceOnly fdReg - - // therefore an explicit delete is required here) - // - this->disarmRecv(); // this deletes the casStreamReadReg object } + else { + procCond = this->processInput(); + if (procCond == casProcDisconnect) { + delete this; + } + else if (this->inBuf::full()==aitTrue) { + // + // If there isnt any space then temporarily + // stop calling this routine until problem is resolved + // either by: + // (1) sending or + // (2) a blocked IO op unblocks + // + // (casStreamReadReg is _not_ a onceOnly fdReg - + // therefore an explicit delete is required here) + // + this->disarmRecv(); // this deletes the casStreamReadReg object + } + } // // NO CODE HERE // (see delete above) // } - // // casStreamOS::sendBlockSignal() // @@ -497,7 +473,6 @@ void casStreamOS::sendBlockSignal() this->armSend(); } - // // casStreamWriteReg::show() // @@ -507,7 +482,6 @@ void casStreamWriteReg::show(unsigned level) const printf ("casStreamWriteReg at %p\n", this); } - // // casStreamWriteReg::callBack() // @@ -526,31 +500,21 @@ void casStreamWriteReg::callBack() // void casStreamOS::sendCB() { - casFlushCondition flushCond; + outBuf::flushCondition flushCond; casProcCond procCond; - this->pWtReg = NULL; // allow rearm (send callbacks are one shots) - // // attempt to flush the output buffer // flushCond = this->flush(); - if (flushCond==casFlushCompleted || - flushCond==casFlushPartial) { + if (flushCond==flushProgress) { if (this->sendBlocked) { this->sendBlocked = FALSE; } } - else if (flushCond==casFlushDisconnect) { + else if (flushCond==outBuf::flushDisconnect) { return; } -#if defined(DEBUG) - else if (flushCond==casFlushNone) { - } - else { - assert(0); - } -#endif // // If we are unable to flush out all of the events diff --git a/src/cas/generic/st/ioBlocked.cc b/src/cas/generic/st/ioBlocked.cc index d47351dc5..9d3aa6590 100644 --- a/src/cas/generic/st/ioBlocked.cc +++ b/src/cas/generic/st/ioBlocked.cc @@ -7,6 +7,9 @@ // (for single threaded version of the server) // // $Log$ +// Revision 1.4 1998/02/05 23:03:39 jhill +// hp comiler workaround changes +// // Revision 1.3 1997/06/13 09:16:10 jhill // connect proto changes // @@ -39,16 +42,6 @@ ioBlocked::~ioBlocked() { } -// -// ioBlocked::ioBlockedSignal() -// -void ioBlocked::ioBlockedSignal() -{ - // - // NOOP - // -} - // // ioBlockedList::ioBlockedList () // diff --git a/src/cas/io/bsdSocket/caServerIO.cc b/src/cas/io/bsdSocket/caServerIO.cc index baa3abd88..1b52e198f 100644 --- a/src/cas/io/bsdSocket/caServerIO.cc +++ b/src/cas/io/bsdSocket/caServerIO.cc @@ -4,32 +4,6 @@ // verify connection state prior to doing anything in this file // // -// $Log$ -// Revision 1.8 1998/05/29 20:08:20 jhill -// use new sock ioctl() typedef -// -// Revision 1.7 1997/08/05 00:47:22 jhill -// fixed warnings -// -// Revision 1.6 1997/06/30 23:40:48 jhill -// use %p for pointers -// -// Revision 1.5 1997/06/13 09:16:12 jhill -// connect proto changes -// -// Revision 1.4 1997/04/10 19:40:31 jhill -// API changes -// -// Revision 1.3 1996/11/02 00:54:42 jhill -// many improvements -// -// Revision 1.2 1996/06/21 02:12:40 jhill -// SOLARIS port -// -// Revision 1.1.1.1 1996/06/20 00:28:19 jhill -// ca server installation -// -// #include @@ -42,6 +16,105 @@ static char *getToken(const char **ppString, char *pBuf, unsigned bufSIze); int caServerIO::staticInitialized; +// +// caServerIO::caServerIO() +// +caServerIO::caServerIO () +{ + if (!bsdSockAttach()) { + throw S_cas_internal; + } + + caServerIO::staticInit(); +} + +// +// caServerIO::locateInterfaces() +// +void caServerIO::locateInterfaces () +{ + char buf[64u]; + const char *pStr; + char *pToken; + caStatus stat; + unsigned short port; + struct sockaddr_in saddr; + bool autoBeaconAddr; + + // + // first try for the server's private port number env var. + // If this available use the CA server port number (used by + // 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)) { + port = caFetchPortConfig(&EPICS_CAS_SERVER_PORT, CA_SERVER_PORT); + } + else { + port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT); + } + + memset ((char *)&saddr,0,sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = ntohs (port); + + pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf); + if (pStr) { + if (strstr(pStr,"no")||strstr(pStr,"NO")) { + autoBeaconAddr = false; + } + else if (strstr(pStr,"yes")||strstr(pStr,"YES")) { + autoBeaconAddr = true; + } + else { + fprintf(stderr, + "CAS: EPICS_CA_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr); + autoBeaconAddr = true; + } + } + else { + autoBeaconAddr = true; + } + + // + // 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); + if (pStr) { + bool configAddrOnceFlag = true; + stat = S_cas_noInterface; + while ( (pToken = getToken(&pStr, buf, sizeof(buf))) ) { + int status; + + status = aToIPAddr (pToken, 0u, &saddr); + if (status) { + ca_printf( + "%s: Parsing '%s'\n", + __FILE__, + EPICS_CAS_INTF_ADDR_LIST.name); + ca_printf( + "\tBad internet address or host name: '%s'\n", + pToken); + continue; + } + stat = this->attachInterface (caNetAddr(saddr), autoBeaconAddr, configAddrOnceFlag); + if (stat) { + errMessage(stat, NULL); + break; + } + configAddrOnceFlag = false; + } + } + else { + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + stat = this->attachInterface (caNetAddr(saddr), autoBeaconAddr, true); + if (stat) { + errMessage(stat, NULL); + } + } +} + // // caServerIO::~caServerIO() // @@ -64,102 +137,6 @@ inline void caServerIO::staticInit() caServerIO::staticInitialized = TRUE; } - -// -// caServerIO::init() -// -caStatus caServerIO::init(caServerI &cas) -{ - char buf[64u]; - const char *pStr; - char *pToken; - caStatus stat; - unsigned short port; - struct sockaddr_in saddr; - int autoBeaconAddr; - - if (!bsdSockAttach()) { - return S_cas_internal; - } - - caServerIO::staticInit(); - - // - // first try for the server's private port number env var. - // If this available use the CA server port number (used by - // 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)) { - port = caFetchPortConfig(&EPICS_CAS_SERVER_PORT, CA_SERVER_PORT); - } - else { - port = caFetchPortConfig(&EPICS_CA_SERVER_PORT, CA_SERVER_PORT); - } - - memset((char *)&saddr,0,sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_port = ntohs (port); - - pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf); - if (pStr) { - if (strstr(pStr,"no")||strstr(pStr,"NO")) { - autoBeaconAddr = FALSE; - } - else if (strstr(pStr,"yes")||strstr(pStr,"YES")) { - autoBeaconAddr = TRUE; - } - else { - fprintf(stderr, - "CAS: EPICS_CA_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr); - autoBeaconAddr = TRUE; - } - } - else { - autoBeaconAddr = TRUE; - } - - // - // 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); - if (pStr) { - int configAddrOnceFlag = TRUE; - stat = S_cas_noInterface; - while ( (pToken = getToken(&pStr, buf, sizeof(buf))) ) { - int status; - - status = aToIPAddr (pToken, 0u, &saddr); - if (status) { - ca_printf( - "%s: Parsing '%s'\n", - __FILE__, - EPICS_CAS_INTF_ADDR_LIST.name); - ca_printf( - "\tBad internet address or host name: '%s'\n", - pToken); - continue; - } - stat = cas.addAddr(caNetAddr(saddr), autoBeaconAddr, configAddrOnceFlag); - if (stat) { - errMessage(stat, NULL); - break; - } - configAddrOnceFlag = FALSE; - } - } - else { - saddr.sin_addr.s_addr = htonl(INADDR_ANY); - stat = cas.addAddr(caNetAddr(saddr), autoBeaconAddr, TRUE); - if (stat) { - errMessage(stat, NULL); - } - } - - return stat; -} - // // caServerIO::show() // @@ -173,29 +150,29 @@ void caServerIO::show (unsigned /* level */) const // static char *getToken(const char **ppString, char *pBuf, unsigned bufSIze) { - const char *pToken; - unsigned i; - - pToken = *ppString; - while(isspace(*pToken)&&*pToken){ - pToken++; - } - - for (i=0u; ihasAddress()) { - struct sockaddr_in addr = this->getSender(); - ipAddrToA (&addr, pBufIn, bufSizeIn); - } - else { - if (bufSizeIn>=1u) { - pBufIn[0u] = '\0'; - } - } -} - diff --git a/src/cas/io/bsdSocket/casDGIntfIO.cc b/src/cas/io/bsdSocket/casDGIntfIO.cc index f48dd077d..2ec440932 100644 --- a/src/cas/io/bsdSocket/casDGIntfIO.cc +++ b/src/cas/io/bsdSocket/casDGIntfIO.cc @@ -41,193 +41,161 @@ // // casDGIntfIO::casDGIntfIO() // -casDGIntfIO::casDGIntfIO(casDGClient &clientIn) : - pAltOutIO(NULL), - client(clientIn), - sock(INVALID_SOCKET), - sockState(casOffLine), - connectWithThisPort(0), - dgPort(0) +casDGIntfIO::casDGIntfIO (caServerI &serverIn, const caNetAddr &addr, + bool autoBeaconAddr, bool addConfigBeaconAddr) : + casDGClient (serverIn) { - ellInit(&this->beaconAddrList); -} + struct sockaddr_in serverAddr; + struct sockaddr_in serverBCastAddr; + int status; + unsigned short beaconPort; + + ellInit(&this->beaconAddrList); + + if (!bsdSockAttach()) { + throw S_cas_internal; + } + + this->sock = casDGIntfIO::makeSockDG(); + if (this->sock==INVALID_SOCKET) { + throw S_cas_internal; + } -// -// casDGIntfIO::init() -// -caStatus casDGIntfIO::init(const caNetAddr &addr, unsigned connectWithThisPortIn, - int autoBeaconAddr, int addConfigBeaconAddr, - int useBroadcastAddr, casDGIntfIO *pAltOutIn) -{ - int yes = TRUE; - struct sockaddr_in serverAddr; - int status; - unsigned short beaconPort; - ELLLIST BCastAddrList; + // + // Fetch port configuration from EPICS environment variables + // + if (envGetConfigParamPtr(&EPICS_CAS_SERVER_PORT)) { + this->dgPort = caFetchPortConfig(&EPICS_CAS_SERVER_PORT, + CA_SERVER_PORT); + } + else { + this->dgPort = caFetchPortConfig(&EPICS_CA_SERVER_PORT, + CA_SERVER_PORT); + } + beaconPort = caFetchPortConfig(&EPICS_CA_REPEATER_PORT, + CA_REPEATER_PORT); - if (!bsdSockAttach()) { - return S_cas_internal; - } + // + // set up the primary address of the server + // + serverAddr = addr; + serverAddr.sin_port = htons (this->dgPort); + + // + // discover beacon addresses associated with this interface + // + { + ELLLIST BCastAddrList; + caAddrNode *pAddr; - if (pAltOutIn) { - this->pAltOutIO = pAltOutIn; - } - else { - this->pAltOutIO = this; - } + ellInit (&BCastAddrList); + caDiscoverInterfaces (&BCastAddrList, this->sock, beaconPort, + serverAddr.sin_addr); // match addr - this->sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (this->sock == INVALID_SOCKET) { - errMessage(S_cas_noMemory, - "CAS: unable to create cast socket\n"); - return S_cas_noMemory; - } + if (ellCount(&BCastAddrList)<1) { + errMessage (S_cas_noInterface, "unable to continue"); + socket_close (this->sock); + throw S_cas_noInterface; + } + pAddr = (caAddrNode *) ellFirst (&BCastAddrList); + serverBCastAddr = pAddr->destAddr.in; + serverBCastAddr.sin_port = htons (this->dgPort); - status = setsockopt( - this->sock, - SOL_SOCKET, - SO_BROADCAST, - (char *)&yes, - sizeof(yes)); - if (status<0) { - errMessage(S_cas_internal, - "CAS: unable to set up cast socket\n"); - return S_cas_internal; - } + if (autoBeaconAddr) { + ellConcat(&this->beaconAddrList, &BCastAddrList); + } + else { + ellFree(&BCastAddrList); + } + } + + status = bind(this->sock, (struct sockaddr *)&serverAddr, + sizeof (serverAddr)); + if (status<0) { + char buf[64]; + int errnoCpy = SOCKERRNO; + ipAddrToA (&serverAddr, buf, sizeof(buf)); + errPrintf (S_cas_bindFail, __FILE__, __LINE__, + ("- bind UDP IP addr=%s failed because %s", + buf, SOCKERRSTR(errnoCpy)) ); + socket_close (this->sock); + throw S_cas_bindFail; + } + + if (addConfigBeaconAddr) { + + // + // by default use EPICS_CA_ADDR_LIST for the + // beacon address list + // + const ENV_PARAM *pParam; + + if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) || + envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) { + pParam = &EPICS_CAS_BEACON_ADDR_LIST; + } + else { + pParam = &EPICS_CA_ADDR_LIST; + } + + // + // add in the configured addresses + // + caAddConfiguredAddr( + &this->beaconAddrList, + pParam, + this->sock, + beaconPort); + } + + // + // Solaris specific: + // If they are binding to a particular interface then + // we will also need to bind to the broadcast address + // for that interface (if it has one). This allows + // broadcast packets to be received, but we must reply + // through the "normal" UDP binding or the client will + // appear to receive replies from the broadcast address. + // Since it should never be valid to fill in the UDP + // source address as the broadcast address, then we must + // conclude that the Solaris implementation is broken. + // + // WIN32 specific: + // On windows this appears to only create problems because + // they correctly allow broadcast to be received when + // binding to a particular interface's IP address, and + // always fill in this interface's address as the reply + // address. + // +#if !defined(_WIN32) || 1 + if (serverAddr.sin_addr.s_addr != htonl(INADDR_ANY)) { - /* - * some concern that vxWorks will run out of mBuf's - * if this change is made - * - * joh 11-10-98 - */ -#if 0 - { - /* - * - * this allows for faster connects by queuing - * additional incomming UDP search frames - * - * this allocates a 32k buffer - * (uses a power of two) - */ - int size = 1u<<15u; - status = setsockopt( - this->sock, - SOL_SOCKET, - SO_RCVBUF, - (char *)&size, - sizeof(size)); - if (status<0) { - errMessage(S_cas_internal, - "CAS: unable to set cast socket size\n"); - } - } + this->bcastRecvSock = casDGIntfIO::makeSockDG (); + if (this->bcastRecvSock==INVALID_SOCKET) { + socket_close (this->sock); + throw S_cas_internal; + } + + status = bind (this->bcastRecvSock, (struct sockaddr *)&serverBCastAddr, + sizeof (serverAddr)); + if (status<0) { + char buf[64]; + int errnoCpy = SOCKERRNO; + ipAddrToA (&serverBCastAddr, buf, sizeof(buf)); + errPrintf (S_cas_bindFail, __FILE__, __LINE__, + "- bind UDP IP addr=%s failed because %s", + buf, SOCKERRSTR(errnoCpy)); + socket_close (this->sock); + socket_close (this->bcastRecvSock); + throw S_cas_bindFail; + } + } + else { + this->bcastRecvSock=INVALID_SOCKET; + } +#else + this->bcastRecvSock=INVALID_SOCKET; #endif - - /* - * release the port in case we exit early. Also if - * on a kernel with MULTICAST mods then we can have - * two UDP servers on the same port number (requires - * setting SO_REUSEADDR prior to the bind step below). - */ - status = setsockopt( - this->sock, - SOL_SOCKET, - SO_REUSEADDR, - (char *) &yes, - sizeof (yes)); - if (status<0) { - errMessage(S_cas_internal, - "CAS: unable to set SO_REUSEADDR on UDP socket?\n"); - } - - // - // Fetch port configuration from EPICS environment variables - // - if (envGetConfigParamPtr(&EPICS_CAS_SERVER_PORT)) { - this->dgPort = caFetchPortConfig(&EPICS_CAS_SERVER_PORT, - CA_SERVER_PORT); - } - else { - this->dgPort = caFetchPortConfig(&EPICS_CA_SERVER_PORT, - CA_SERVER_PORT); - } - beaconPort = caFetchPortConfig(&EPICS_CA_REPEATER_PORT, - CA_REPEATER_PORT); - - /* - * discover beacon addresses associated with this interface - */ - serverAddr = addr; - if (autoBeaconAddr || useBroadcastAddr) { - ellInit(&BCastAddrList); - caDiscoverInterfaces( - &BCastAddrList, - this->sock, - beaconPort, - serverAddr.sin_addr); /* match addr */ - if (useBroadcastAddr) { - caAddrNode *pAddr; - if (ellCount(&BCastAddrList)!=1) { - return S_cas_noInterface; - } - pAddr = (caAddrNode *) ellFirst(&BCastAddrList); - serverAddr.sin_addr = pAddr->destAddr.in.sin_addr; - } - if (autoBeaconAddr) { - ellConcat(&this->beaconAddrList, &BCastAddrList); - } - else { - ellFree(&BCastAddrList); - } - } - - serverAddr.sin_port = htons (this->dgPort); - status = bind( - this->sock, - (struct sockaddr *)&serverAddr, - sizeof (serverAddr)); - if (status<0) { - char buf[64]; - ipAddrToA (&serverAddr, buf, sizeof(buf)); - errPrintf(S_cas_bindFail, - __FILE__, __LINE__, "- bind UDP IP addr=%s failed because %s", - buf, SOCKERRSTR); - - return S_cas_bindFail; - } - - if (addConfigBeaconAddr) { - - /* - * by default use EPICS_CA_ADDR_LIST for the - * beacon address list - */ - const ENV_PARAM *pParam; - - if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) || - envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) { - pParam = &EPICS_CAS_BEACON_ADDR_LIST; - } - else { - pParam = &EPICS_CA_ADDR_LIST; - } - - /* - * add in the configured addresses - */ - caAddConfiguredAddr( - &this->beaconAddrList, - pParam, - this->sock, - beaconPort); - } - - this->connectWithThisPort = connectWithThisPortIn; - this->sockState=casOnLine; - - return S_cas_success; } // @@ -235,21 +203,17 @@ caStatus casDGIntfIO::init(const caNetAddr &addr, unsigned connectWithThisPortIn // casDGIntfIO::~casDGIntfIO() { - if(this->sock!=INVALID_SOCKET){ - socket_close(this->sock); + if (this->sock!=INVALID_SOCKET) { + socket_close(this->sock); } - ellFree(&this->beaconAddrList); - - bsdSockRelease(); -} - -// -// casDGIntfIO::clientHostName() -// -void casDGIntfIO::clientHostName (char *pBufIn, unsigned bufSizeIn) const -{ - sockAddrToA (&this->lastRecvAddr, pBufIn, bufSizeIn); + if (this->bcastRecvSock!=INVALID_SOCKET) { + socket_close(this->bcastRecvSock); + } + + ellFree(&this->beaconAddrList); + + bsdSockRelease(); } // @@ -258,11 +222,6 @@ void casDGIntfIO::clientHostName (char *pBufIn, unsigned bufSizeIn) const void casDGIntfIO::osdShow (unsigned level) const { printf ("casDGIntfIO at %p\n", this); - if (level>=1u) { - char buf[64]; - this->clientHostName (buf, sizeof(buf)); - printf ("Client Host=%s\n", buf); - } } // @@ -270,72 +229,61 @@ void casDGIntfIO::osdShow (unsigned level) const // void casDGIntfIO::xSetNonBlocking() { - int status; - osiSockIoctl_t yes = TRUE; - - if (this->sockState!=casOnLine) { - return; - } - - status = socket_ioctl(this->sock, FIONBIO, &yes); - if (status<0) { - ca_printf("%s:CAS: UDP non blocking IO set fail because \"%s\"\n", - __FILE__, SOCKERRSTR); - this->sockState = casOffLine; - } + int status; + osiSockIoctl_t yes = TRUE; + + status = socket_ioctl(this->sock, FIONBIO, &yes); + if (status<0) { + ca_printf("%s:CAS: UDP non blocking IO set fail because \"%s\"\n", + __FILE__, SOCKERRSTR(SOCKERRNO)); + } } // // casDGIntfIO::osdRecv() // -xRecvStatus casDGIntfIO::osdRecv(char *pBuf, bufSizeT size, - bufSizeT &actualSize, caNetAddr &fromOut) +inBuf::fillCondition casDGIntfIO::osdRecv(char *pBuf, bufSizeT size, + fillParameter parm, bufSizeT &actualSize, caNetAddr &fromOut) { int status; int addrSize; + sockaddr addr; + SOCKET sockThisTime; - if (this->sockState!=casOnLine) { - return xRecvDisconnect; - } + if (parm==fpUseBroadcastInterface) { + sockThisTime = this->bcastRecvSock; + } + else { + sockThisTime = this->sock; + } - addrSize = sizeof (this->lastRecvAddr); + addrSize = sizeof (addr); status = recvfrom (this->sock, pBuf, size, 0, - &this->lastRecvAddr, &addrSize); - if (status<0) { - if(SOCKERRNO == SOCK_EWOULDBLOCK){ - actualSize = 0u; - return xRecvOK; - } - else { - ca_printf("CAS: UDP recv error was %s", - SOCKERRSTR); - actualSize = 0u; - return xRecvOK; + &addr, &addrSize); + if (status<=0) { + if (status<0) { + int errnoCpy = SOCKERRNO; + if( errnoCpy != SOCK_EWOULDBLOCK ){ + ca_printf("CAS: UDP recv error was %s", + SOCKERRSTR(errnoCpy)); + } } + return casFillNone; } - - fromOut = this->lastRecvAddr; - actualSize = (bufSizeT) status; - return xRecvOK; + else { + fromOut = addr; + actualSize = (bufSizeT) status; + return casFillProgress; + } } // // casDGIntfIO::osdSend() // -xSendStatus casDGIntfIO::osdSend(const char *pBuf, bufSizeT size, - bufSizeT &actualSize, const caNetAddr &to) +outBuf::flushCondition casDGIntfIO::osdSend (const char *pBuf, bufSizeT size, + const caNetAddr &to) { int status; - int anerrno; - - if (this->sockState!=casOnLine) { - return xSendDisconnect; - } - - if (size==0u) { - actualSize = 0u; - return xSendOK; - } // // (char *) cast below is for brain dead wrs prototype @@ -343,44 +291,61 @@ xSendStatus casDGIntfIO::osdSend(const char *pBuf, bufSizeT size, struct sockaddr dest = to; status = sendto (this->sock, (char *) pBuf, size, 0, &dest, sizeof(dest)); - if (status>0) { - if (size != (unsigned) status) { - ca_printf ("CAS: partial UDP msg discarded??\n"); - } - } - else if (status==0) { - this->sockState = casOffLine; - ca_printf ("CAS: UDP send returns zero??\n"); - return xSendDisconnect; + if (status>=0) { + assert ( size == (unsigned) status ); + return outBuf::flushProgress; } else { - anerrno = SOCKERRNO; - - if (anerrno != SOCK_EWOULDBLOCK) { + int errnoCpy = SOCKERRNO; + if (errnoCpy != SOCK_EWOULDBLOCK) { char buf[64]; - this->clientHostName(buf, sizeof(buf)); - ca_printf( + sockAddrToA (&dest, buf, sizeof(buf)); + ca_printf ( "CAS: UDP socket send to \"%s\" failed because \"%s\"\n", - buf, SOCKERRSTR); + buf, SOCKERRSTR(errnoCpy)); } + return outBuf::flushNone; } - - actualSize = size; - return xSendOK; } +// +// casDGIntfIO::incommingBytesPresent() +// +// OK to return a size of one here when a datagram is present, and +// zero otherwise. +// +bufSizeT casDGIntfIO::incommingBytesPresent () const +{ + int status; + osiSockIoctl_t nchars; + + status = socket_ioctl (this->sock, FIONREAD, &nchars); + if (status<0) { + ca_printf ("CAS: FIONREAD failed because \"%s\"\n", + SOCKERRSTR(SOCKERRNO)); + return 0u; + } + else if (nchars<0) { + return 0u; + } + else { + return (bufSizeT) nchars; + } +} + + // // casDGIntfIO::sendBeacon() // -void casDGIntfIO::sendBeacon(char &msg, unsigned length, aitUint32 &m_ipa, aitUint16 &m_port) +void casDGIntfIO::sendBeaconIO (char &msg, unsigned length, aitUint32 &m_ipa, aitUint16 &m_port) { caAddrNode *pAddr; int status; - if (this->sockState!=casOnLine) { - return; - } - + // + // the broadcast bound socket is not used here because + // it will have the wrong source address. + // for (pAddr = (caAddrNode *)ellFirst(&this->beaconAddrList); pAddr; pAddr = (caAddrNode *)ellNext(&pAddr->node)) { @@ -390,13 +355,13 @@ void casDGIntfIO::sendBeacon(char &msg, unsigned length, aitUint32 &m_ipa, aitUi &pAddr->destAddr.sa, sizeof(pAddr->destAddr.sa)); if (status < 0) { char buf[64]; + int errnoCpy = SOCKERRNO; + ipAddrToA(&pAddr->destAddr.in, buf, sizeof(buf)); ca_printf( "CAS:beacon error was \"%s\" dest=%s sock=%d\n", - SOCKERRSTR, - buf, - this->sock); + SOCKERRSTR(errnoCpy), buf, this->sock); } } } @@ -406,38 +371,34 @@ void casDGIntfIO::sendBeacon(char &msg, unsigned length, aitUint32 &m_ipa, aitUi // bufSizeT casDGIntfIO::optimumInBufferSize () { - + #if 1 - // - // must update client before the message size can be - // increased here - // - return ETHERNET_MAX_UDP; + // + // must update client before the message size can be + // increased here + // + return ETHERNET_MAX_UDP; #else - int n; - int size; - int status; - - if (this->sockState!=casOnLine) { - return ETHERNET_MAX_UDP; - } - - /* fetch the TCP send buffer size */ - n = sizeof(size); - status = getsockopt( - this->sock, - SOL_SOCKET, - SO_RCVBUF, - (char *)&size, - &n); - if(status < 0 || n != sizeof(size)){ - size = ETEHRNET_MAX_UDP; - } - - if (size<=0) { - size = ETHERNET_MAX_UDP; - } - return (bufSizeT) size; + int n; + int size; + int status; + + /* fetch the TCP send buffer size */ + n = sizeof(size); + status = getsockopt( + this->sock, + SOL_SOCKET, + SO_RCVBUF, + (char *)&size, + &n); + if(status < 0 || n != sizeof(size)){ + size = ETEHRNET_MAX_UDP; + } + + if (size<=0) { + size = ETHERNET_MAX_UDP; + } + return (bufSizeT) size; #endif } @@ -446,82 +407,117 @@ bufSizeT casDGIntfIO::optimumInBufferSize () // bufSizeT casDGIntfIO::optimumOutBufferSize () { - + #if 1 - // - // must update client before the message size can be - // increased here - // - return MAX_UDP; + // + // must update client before the message size can be + // increased here + // + return MAX_UDP; #else - int n; - int size; - int status; + int n; + int size; + int status; + - if (this->sockState!=casOnLine) { - return MAX_UDP; - } - - /* 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)){ - size = MAX_UDP; - } - - if (size<=0) { - size = MAX_UDP; - } - return (bufSizeT) size; + /* 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)){ + size = MAX_UDP; + } + + if (size<=0) { + size = MAX_UDP; + } + return (bufSizeT) size; #endif } -// -// casDGIntfIO::state() -// -casIOState casDGIntfIO::state() const -{ - return this->sockState; -} // -// casDGIntfIO::getFD() +// casDGIntfIO::makeSockDG () // -int casDGIntfIO::getFD() const +SOCKET casDGIntfIO::makeSockDG () { - return this->sock; -} + int yes = TRUE; + int status; + SOCKET newSock; -// -// casDGIntfIO::serverPortNumber() -// -// the server's port number -// (to be used for connection requests) -// -unsigned casDGIntfIO::serverPortNumber() -{ - return this->connectWithThisPort; -} - -// -// this was moved from casIODIL.h to here because -// of problems inline functions and g++ -g 2.7.2 -// -// casDGIntfIO::processDG() -// -void casDGIntfIO::processDG() -{ - assert(this->pAltOutIO); - + newSock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (newSock == INVALID_SOCKET) { + errMessage(S_cas_noMemory, "CAS: unable to create cast socket\n"); + return INVALID_SOCKET; + } + + status = setsockopt( + newSock, + SOL_SOCKET, + SO_BROADCAST, + (char *)&yes, + sizeof(yes)); + if (status<0) { + socket_close (newSock); + errMessage(S_cas_internal, + "CAS: unable to set up cast socket\n"); + return INVALID_SOCKET; + } + + // + // some concern that vxWorks will run out of mBuf's + // if this change is made + // + // joh 11-10-98 + // +#if 0 + { // - // process the request DG and send a response DG - // if it is required // - this->client.processDG(*this,*this->pAltOutIO); -} + // this allows for faster connects by queuing + // additional incomming UDP search frames + // + // this allocates a 32k buffer + // (uses a power of two) + // + int size = 1u<<15u; + status = setsockopt( + newSock, + SOL_SOCKET, + SO_RCVBUF, + (char *)&size, + sizeof(size)); + if (status<0) { + socket_close (newSock); + errMessage(S_cas_internal, + "CAS: unable to set cast socket size\n"); + return INVALID_SOCKET; + } + } +#endif + + // + // release the port in case we exit early. Also if + // on a kernel with MULTICAST mods then we can have + // two UDP servers on the same port number (requires + // setting SO_REUSEADDR prior to the bind step below). + // + status = setsockopt( + newSock, + SOL_SOCKET, + SO_REUSEADDR, + (char *) &yes, + sizeof (yes)); + if (status<0) { + socket_close (newSock); + errMessage(S_cas_internal, + "CAS: unable to set SO_REUSEADDR on UDP socket?\n"); + return INVALID_SOCKET; + } + return newSock; +} diff --git a/src/cas/io/bsdSocket/casIOD.h b/src/cas/io/bsdSocket/casIOD.h index 18aea5b00..099049ab9 100644 --- a/src/cas/io/bsdSocket/casIOD.h +++ b/src/cas/io/bsdSocket/casIOD.h @@ -21,48 +21,38 @@ class casDGClient; // // casDGIntfIO // -class casDGIntfIO { +class casDGIntfIO : public casDGClient { public: - casDGIntfIO (casDGClient &clientIn); - caStatus init(const caNetAddr &addr, unsigned connectWithThisPort, - int autoBeaconAddr=TRUE, int addConfigBeaconAddr=FALSE, - int useBroadcastAddr=FALSE, casDGIntfIO *pAltOutIn=NULL); + casDGIntfIO (caServerI &serverIn, const caNetAddr &addr, + bool autoBeaconAddr=TRUE, bool addConfigBeaconAddr=FALSE); virtual ~casDGIntfIO(); - int getFD() const; - void xSetNonBlocking(); - void sendBeacon(char &msg, bufSizeT length, aitUint32 &m_ipa, aitUint16 &m_port); - casIOState state() const; - void clientHostName (char *pBuf, unsigned bufSize) const; - - xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, - bufSizeT &nBytesActual, const caNetAddr &addr); - xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, - bufSizeT &nBytesActual, caNetAddr &addr); + int getFD () const; + int getBCastFD () const; + bool validBCastFD () const; + + void xSetNonBlocking (); + void sendBeaconIO (char &msg, bufSizeT length, aitUint32 &m_ipa, aitUint16 &m_port); + casIOState state () const; + + outBuf::flushCondition osdSend (const char *pBuf, bufSizeT nBytesReq, + const caNetAddr &addr); + inBuf::fillCondition osdRecv (char *pBuf, bufSizeT nBytesReq, + fillParameter parm, bufSizeT &nBytesActual, caNetAddr &addr); void osdShow (unsigned level) const; static bufSizeT optimumOutBufferSize (); static bufSizeT optimumInBufferSize (); - // - // The server's port number - // (to be used for connection requests) - // - unsigned serverPortNumber(); - - virtual caStatus start()=0; // OS specific - - void processDG(); + bufSizeT incommingBytesPresent () const; private: ELLLIST beaconAddrList; - struct sockaddr lastRecvAddr; - casDGIntfIO *pAltOutIO; - casDGClient &client; SOCKET sock; - casIOState sockState; - unsigned short connectWithThisPort; + SOCKET bcastRecvSock; // fix for solaris bug unsigned short dgPort; + + static SOCKET makeSockDG (); }; struct ioArgsToNewStreamIO { @@ -70,28 +60,12 @@ struct ioArgsToNewStreamIO { SOCKET sock; }; -// -// casDGIO -// -class casDGIO : public casDGClient { -public: - casDGIO(caServerI &cas) : - casDGClient(cas) {} - ~casDGIO(); - - // - // clientHostName() - // - void clientHostName (char *pBufIn, unsigned bufSizeIn) const; -}; - // // casStreamIO // class casStreamIO : public casStrmClient { public: casStreamIO(caServerI &cas, const ioArgsToNewStreamIO &args); - caStatus init(); ~casStreamIO(); int getFD() const; @@ -100,9 +74,9 @@ public: casIOState state() const; void clientHostName (char *pBuf, unsigned bufSize) const; - xSendStatus osdSend (const char *pBuf, bufSizeT nBytesReq, + outBuf::flushCondition osdSend (const char *pBuf, bufSizeT nBytesReq, bufSizeT &nBytesActual); - xRecvStatus osdRecv (char *pBuf, bufSizeT nBytesReq, + inBuf::fillCondition osdRecv (char *pBuf, bufSizeT nBytesReq, bufSizeT &nBytesActual); xBlockingStatus blockingState() const; @@ -113,18 +87,12 @@ public: void osdShow (unsigned level) const; - // - // The server's port number - // (to be used for connection requests) - // - unsigned serverPortNumber(); - - const caNetAddr getAddr() + const caNetAddr getAddr() const { return caNetAddr(this->addr); } + private: - casIOState sockState; SOCKET sock; struct sockaddr_in addr; xBlockingStatus blockingFlag; @@ -140,10 +108,7 @@ class casStreamOS; // class casIntfIO { public: - casIntfIO(); - //constructor does not return status - caStatus init(const caNetAddr &addr, casDGClient &dgClientIn, - int autoBeaconAddr, int addConfigBeaconAddr); + casIntfIO (const caNetAddr &addr); virtual ~casIntfIO(); void show(unsigned level) const; @@ -158,13 +123,10 @@ public: // client can be created // casStreamOS *newStreamClient(caServerI &cas) const; - - virtual casDGIntfIO *newDGIntfIO (casDGClient &dgClientIn) const = 0; - void requestBeacon(); + caNetAddr serverAddress () const; + private: - casDGIntfIO *pNormalUDP; // attached to this intf's addr - casDGIntfIO *pBCastUDP; // attached to this intf's broadcast addr SOCKET sock; struct sockaddr_in addr; }; @@ -174,8 +136,7 @@ private: // class caServerIO { public: - caServerIO() {} // make hp compiler happy - caStatus init(caServerI &cas); //constructor does not return status + caServerIO (); virtual ~caServerIO(); // @@ -183,6 +144,8 @@ public: // void show (unsigned level) const; + void locateInterfaces (); + private: // @@ -193,6 +156,9 @@ private: // static member func // static inline void staticInit(); + + virtual caStatus attachInterface (const caNetAddr &addr, bool autoBeaconAddr, + bool addConfigAddr) = 0; }; diff --git a/src/cas/io/bsdSocket/casIODIL.h b/src/cas/io/bsdSocket/casIODIL.h index e5869e4f2..c8d94b3ec 100644 --- a/src/cas/io/bsdSocket/casIODIL.h +++ b/src/cas/io/bsdSocket/casIODIL.h @@ -2,11 +2,39 @@ #ifndef casIODILh #define casIODILh +#include "bsdSocketResource.h" + // -// Problems with g++ -g 2.7.2 and inline functions -// caused all functions in this file to be moved to -// casDGIntfIO.cc +// casDGIntfIO::getFD() // +inline int casDGIntfIO::getFD() const +{ + return this->sock; +} + +// +// casDGIntfIO::getBCastFD() +// +inline int casDGIntfIO::getBCastFD() const +{ + return this->bcastRecvSock; +} + +// +// casDGIntfIO::getBCastFD() +// +inline bool casDGIntfIO::validBCastFD() const +{ + return this->bcastRecvSock!=INVALID_SOCKET; +} + +// +// casIntfIO::serverAddress () +// +inline caNetAddr casIntfIO::serverAddress () const +{ + return caNetAddr (this->addr); +} #endif // casIODILh diff --git a/src/cas/io/bsdSocket/casIntfIO.cc b/src/cas/io/bsdSocket/casIntfIO.cc index 2ddda6777..e52735dcd 100644 --- a/src/cas/io/bsdSocket/casIntfIO.cc +++ b/src/cas/io/bsdSocket/casIntfIO.cc @@ -6,6 +6,9 @@ // // // $Log$ +// Revision 1.7 1998/06/18 00:11:09 jhill +// use ipAddrToA +// // Revision 1.6 1998/06/16 02:35:51 jhill // use aToIPAddr and auto attach to winsock if its a static build // @@ -37,27 +40,16 @@ const unsigned caServerConnectPendQueueSize = 5u; // // casIntfIO::casIntfIO() // -casIntfIO::casIntfIO() : - pNormalUDP(NULL), - pBCastUDP(NULL), - sock(INVALID_SOCKET) -{ - memset(&addr, '\0', sizeof(addr)); -} - -// -// casIntfIO::init() -// -caStatus casIntfIO::init(const caNetAddr &addrIn, casDGClient &dgClientIn, - int autoBeaconAddr, int addConfigBeaconAddr) +casIntfIO::casIntfIO (const caNetAddr &addrIn) : + addr (addrIn.getSockIP()), + sock (INVALID_SOCKET) { int yes = TRUE; int status; - caStatus stat; int addrSize; if (!bsdSockAttach()) { - return S_cas_internal; + throw S_cas_internal; } /* @@ -65,8 +57,8 @@ caStatus casIntfIO::init(const caNetAddr &addrIn, casDGClient &dgClientIn, */ this->sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (this->sock==INVALID_SOCKET) { - printf("No socket error was %s\n", SOCKERRSTR); - return S_cas_noFD; + printf("No socket error was %s\n", SOCKERRSTR(SOCKERRNO)); + throw S_cas_noFD; } /* @@ -80,11 +72,11 @@ caStatus casIntfIO::init(const caNetAddr &addrIn, casDGClient &dgClientIn, sizeof (yes)); if (status<0) { ca_printf("CAS: server set SO_REUSEADDR failed? %s\n", - SOCKERRSTR); - return S_cas_internal; + SOCKERRSTR(SOCKERRNO)); + socket_close (this->sock); + throw S_cas_internal; } - this->addr = addrIn.getSockIP(); status = bind(this->sock,(sockaddr *) &this->addr, sizeof(this->addr)); if (status<0) { @@ -94,7 +86,6 @@ caStatus casIntfIO::init(const caNetAddr &addrIn, casDGClient &dgClientIn, // (so the getsockname() call below will // work correctly) // - this->addr.sin_port = ntohs (0); status = bind( this->sock, @@ -103,22 +94,26 @@ caStatus casIntfIO::init(const caNetAddr &addrIn, casDGClient &dgClientIn, } if (status<0) { char buf[64]; + int errnoCpy = SOCKERRNO; + ipAddrToA (&this->addr, buf, sizeof(buf)); errPrintf(S_cas_bindFail, __FILE__, __LINE__, "- bind TCP IP addr=%s failed because %s", - buf, SOCKERRSTR); - return S_cas_bindFail; + buf, SOCKERRSTR(errnoCpy)); + socket_close (this->sock); + throw S_cas_bindFail; } } - addrSize = sizeof(this->addr); - status = getsockname(this->sock, + addrSize = sizeof (this->addr); + status = getsockname (this->sock, (struct sockaddr *)&this->addr, &addrSize); if (status) { ca_printf("CAS: getsockname() error %s\n", - SOCKERRSTR); - return S_cas_internal; + SOCKERRSTR(SOCKERRNO)); + socket_close (this->sock); + throw S_cas_internal; } // @@ -129,57 +124,10 @@ caStatus casIntfIO::init(const caNetAddr &addrIn, casDGClient &dgClientIn, status = listen(this->sock, caServerConnectPendQueueSize); if(status < 0) { - ca_printf("CAS: listen() error %s\n", SOCKERRSTR); - return S_cas_internal; + ca_printf("CAS: listen() error %s\n", SOCKERRSTR(SOCKERRNO)); + socket_close (this->sock); + throw S_cas_internal; } - - // - // set up a DG socket bound to the specified interface - // (or INADDR_ANY) - // - this->pNormalUDP = this->newDGIntfIO(dgClientIn); - if (!this->pNormalUDP) { - return S_cas_noMemory; - } - stat = this->pNormalUDP->init(this->addr, this->portNumber(), - autoBeaconAddr, addConfigBeaconAddr); - if (stat) { - return stat; - } - else { - this->pNormalUDP->start(); - } - - // - // If they are binding to a particular interface then - // we will also need to bind to the broadcast address - // for that interface (if it has one) - // - if (this->addr.sin_addr.s_addr != htonl(INADDR_ANY)) { - this->pBCastUDP = this->newDGIntfIO(dgClientIn); - if (this->pBCastUDP) { - stat = this->pBCastUDP->init(addr, this->portNumber(), - FALSE, FALSE, TRUE, this->pNormalUDP); - if (stat) { - if (stat==S_cas_noInterface) { - delete this->pBCastUDP; - this->pBCastUDP = NULL; - } - else { - errMessage(stat, - "server will not receive broadcasts"); - } - } - else { - this->pBCastUDP->start(); - } - } - else { - errMessage(S_cas_noMemory, - "failed to create broadcast socket"); - } - } - return S_cas_success; } // @@ -190,12 +138,6 @@ casIntfIO::~casIntfIO() if (this->sock != INVALID_SOCKET) { socket_close(this->sock); } - if (this->pNormalUDP) { - delete this->pNormalUDP; - } - if (this->pBCastUDP) { - delete this->pBCastUDP; - } bsdSockRelease(); } @@ -205,36 +147,43 @@ casIntfIO::~casIntfIO() // casStreamOS *casIntfIO::newStreamClient(caServerI &cas) const { - struct sockaddr newAddr; - SOCKET newSock; - int length; - casStreamOS *pOS; - - length = sizeof(newAddr); - newSock = accept(this->sock, &newAddr, &length); - if (newSock==INVALID_SOCKET) { - if (SOCKERRNO!=SOCK_EWOULDBLOCK) { - ca_printf( - "CAS: %s accept error %s\n", - __FILE__, - SOCKERRSTR); - } - return NULL; + struct sockaddr newAddr; + SOCKET newSock; + int length; + casStreamOS *pOS; + + length = sizeof(newAddr); + newSock = accept(this->sock, &newAddr, &length); + if (newSock==INVALID_SOCKET) { + int errnoCpy = SOCKERRNO; + if (errnoCpy!=SOCK_EWOULDBLOCK) { + ca_printf ("CAS: %s accept error %s\n", + __FILE__,SOCKERRSTR(errnoCpy)); } - else if (sizeof(newAddr)>(size_t)length) { - socket_close(newSock); - ca_printf("CAS: accept returned bad address len?\n"); - return NULL; + return NULL; + } + else if (sizeof(newAddr)>(size_t)length) { + socket_close(newSock); + ca_printf("CAS: accept returned bad address len?\n"); + return NULL; + } + + ioArgsToNewStreamIO args; + args.addr = newAddr; + args.sock = newSock; + pOS = new casStreamOS(cas, args); + if (!pOS) { + socket_close(newSock); + } + else { + if ( cas.getDebugLevel()>0u) { + char pName[64u]; + + pOS->clientHostName (pName, sizeof (pName)); + ca_printf("CAS: allocated client object for \"%s\"\n", pName); } - - ioArgsToNewStreamIO args; - args.addr = newAddr; - args.sock = newSock; - pOS = new casStreamOS(cas, args); - if (!pOS) { - socket_close(newSock); - } - return pOS; + } + return pOS; } // @@ -249,7 +198,7 @@ void casIntfIO::setNonBlocking() if (status<0) { ca_printf( "%s:CAS: server non blocking IO set fail because \"%s\"\n", - __FILE__, SOCKERRSTR); + __FILE__, SOCKERRSTR(SOCKERRNO)); } } @@ -279,20 +228,4 @@ unsigned casIntfIO::portNumber() const return ntohs(this->addr.sin_port); } -// -// casIntfIO::requestBeacon() -// -void casIntfIO::requestBeacon() -{ - // - // the broadcast bound socket is not used here because - // it will have the wrong source address. This - // casDGIntfIO has a list of all beacon addresses - // that have been configured (no need to use - // this->pBCastUDP). - // - if (this->pNormalUDP) { - casDGClient::sendBeacon(*this->pNormalUDP); - } -} diff --git a/src/cas/io/bsdSocket/casStreamIO.cc b/src/cas/io/bsdSocket/casStreamIO.cc index 9b2b3e7c3..2a30642a0 100644 --- a/src/cas/io/bsdSocket/casStreamIO.cc +++ b/src/cas/io/bsdSocket/casStreamIO.cc @@ -5,6 +5,9 @@ // // // $Log$ +// Revision 1.18 1998/12/18 18:58:20 jhill +// fixed warning +// // Revision 1.17 1998/11/11 01:31:59 jhill // reduced socket buffer size // @@ -64,24 +67,13 @@ #include "server.h" #include "bsdSocketResource.h" - // // casStreamIO::casStreamIO() // casStreamIO::casStreamIO(caServerI &cas, const ioArgsToNewStreamIO &args) : - casStrmClient(cas), - sockState(casOffLine), sock(args.sock), addr(args.addr), - blockingFlag(xIsBlocking) + casStrmClient(cas), sock(args.sock), addr(args.addr), blockingFlag(xIsBlocking) { assert (sock>=0); -} - - -// -// casStreamIO::init() -// -caStatus casStreamIO::init() -{ int yes = TRUE; int status; @@ -98,8 +90,8 @@ caStatus casStreamIO::init() if (status<0) { ca_printf( "CAS: %s TCP_NODELAY option set failed %s\n", - __FILE__, SOCKERRSTR); - return S_cas_internal; + __FILE__, SOCKERRSTR(SOCKERRNO)); + throw S_cas_internal; } /* @@ -115,8 +107,8 @@ caStatus casStreamIO::init() if (status<0) { ca_printf( "CAS: %s SO_KEEPALIVE option set failed %s\n", - __FILE__, SOCKERRSTR); - return S_cas_internal; + __FILE__, SOCKERRSTR(SOCKERRNO)); + throw S_cas_internal; } /* @@ -141,7 +133,7 @@ caStatus casStreamIO::init() sizeof(i)); if(status < 0){ ca_printf("CAS: SO_SNDBUF set failed\n"); - return S_cas_internal; + throw S_cas_internal; } i = MAX_MSG_SIZE; status = setsockopt( @@ -152,16 +144,12 @@ caStatus casStreamIO::init() sizeof(i)); if(status < 0){ ca_printf("CAS: SO_RCVBUF set failed\n"); - return S_cas_internal; + throw S_cas_internal; } #endif - this->sockState = casOnLine; - - return this->casStrmClient::init(); } - // // casStreamIO::~casStreamIO() // @@ -172,95 +160,69 @@ casStreamIO::~casStreamIO() } } - // // casStreamIO::osdSend() // -xSendStatus casStreamIO::osdSend(const char *pInBuf, bufSizeT nBytesReq, - bufSizeT &nBytesActual) +outBuf::flushCondition casStreamIO::osdSend (const char *pInBuf, bufSizeT nBytesReq, + bufSizeT &nBytesActual) { - int status; + int status; + + status = send (this->sock, (char *) pInBuf, nBytesReq, 0); + if (status == 0) { + return outBuf::flushDisconnect; + } + else if (status<0) { + int anerrno = SOCKERRNO; + + if (anerrno != SOCK_EWOULDBLOCK) { + char buf[64]; + int errnoCpy = SOCKERRNO; - if (this->sockState!=casOnLine) { - return xSendDisconnect; + ipAddrToA (&this->addr, buf, sizeof(buf)); + ca_printf( + "CAS: TCP socket send to \"%s\" failed because \"%s\"\n", + buf, SOCKERRSTR(errnoCpy)); } - - if (nBytesReq<=0u) { - nBytesActual = 0u; - return xSendOK; - } - - status = send ( - this->sock, - (char *) pInBuf, - nBytesReq, - 0); - if (status == 0) { - this->sockState = casOffLine; - return xSendDisconnect; - } - else if (status<0) { - int anerrno = SOCKERRNO; - - if (anerrno != SOCK_EWOULDBLOCK) { - this->sockState = casOffLine; - } - nBytesActual = 0u; - return xSendOK; - } - nBytesActual = (bufSizeT) status; - return xSendOK; + return outBuf::flushNone; + } + nBytesActual = (bufSizeT) status; + return outBuf::flushProgress; } - // // casStreamIO::osdRecv() // -xRecvStatus casStreamIO::osdRecv(char *pInBuf, bufSizeT nBytes, +inBuf::fillCondition casStreamIO::osdRecv (char *pInBuf, bufSizeT nBytes, bufSizeT &nBytesActual) { - int nchars; + int nchars; - if (this->sockState!= casOnLine) { - return xRecvDisconnect; - } - - nchars = recv(this->sock, pInBuf, nBytes, 0); + nchars = recv (this->sock, pInBuf, nBytes, 0); if (nchars==0) { - this->sockState = casOffLine; - return xRecvDisconnect; + return casFillDisconnect; } else if (nchars<0) { + int myerrno = SOCKERRNO; char buf[64]; - /* - * normal conn lost conditions - */ - switch(SOCKERRNO){ - case SOCK_EWOULDBLOCK: - nBytesActual = 0u; - return xRecvOK; - - case SOCK_ECONNABORTED: - case SOCK_ECONNRESET: - case SOCK_ETIMEDOUT: - break; - - default: - ipAddrToA(&this->addr, buf, sizeof(buf)); + if (myerrno==SOCK_EWOULDBLOCK) { + return casFillNone; + } + else { + ipAddrToA (&this->addr, buf, sizeof(buf)); ca_printf( "CAS: client %s disconnected because \"%s\"\n", - buf, SOCKERRSTR); - break; - } - this->sockState = casOffLine; - return xRecvDisconnect; + buf, SOCKERRSTR(myerrno)); + return casFillDisconnect; + } } - nBytesActual = (bufSizeT) nchars; - return xRecvOK; + else { + nBytesActual = (bufSizeT) nchars; + return casFillProgress; + } } - // // casStreamIO::show() // @@ -276,7 +238,6 @@ void casStreamIO::osdShow (unsigned level) const } } - // // casStreamIO::xSsetNonBlocking() // @@ -285,18 +246,14 @@ void casStreamIO::xSetNonBlocking() int status; osiSockIoctl_t yes = TRUE; - if (this->sockState!=casOnLine) { - return; - } - status = socket_ioctl(this->sock, FIONBIO, &yes); if (status>=0) { this->blockingFlag = xIsntBlocking; } else { ca_printf("%s:CAS: TCP non blocking IO set fail because \"%s\"\n", - __FILE__, SOCKERRSTR); - this->sockState = casOffLine; + __FILE__, SOCKERRSTR(SOCKERRNO)); + throw S_cas_internal; } } @@ -308,45 +265,32 @@ xBlockingStatus casStreamIO::blockingState() const return this->blockingFlag; } - // // casStreamIO::incommingBytesPresent() // bufSizeT casStreamIO::incommingBytesPresent() const { - int status; - osiSockIoctl_t nchars; - - status = socket_ioctl(this->sock, FIONREAD, &nchars); - if (status<0) { - char buf[64]; - - /* - * normal conn lost conditions - */ - switch(SOCKERRNO){ - case SOCK_ECONNABORTED: - case SOCK_ECONNRESET: - case SOCK_ETIMEDOUT: - break; - - default: - ipAddrToA(&this->addr, buf, sizeof(buf)); - ca_printf( - "CAS: FIONREAD for %s failed because \"%s\"\n", - buf, SOCKERRSTR); - } - return 0u; - } - else if (nchars<0) { - return 0u; - } - else { - return (bufSizeT) nchars; - } + int status; + osiSockIoctl_t nchars; + + status = socket_ioctl(this->sock, FIONREAD, &nchars); + if (status<0) { + char buf[64]; + int errnoCpy = SOCKERRNO; + + ipAddrToA (&this->addr, buf, sizeof(buf) ); + ca_printf ("CAS: FIONREAD for %s failed because \"%s\"\n", + buf, SOCKERRSTR(errnoCpy)); + return 0u; + } + else if (nchars<0) { + return 0u; + } + else { + return (bufSizeT) nchars; + } } - // // casStreamIO::clientHostName() // @@ -366,10 +310,6 @@ bufSizeT casStreamIO::optimumBufferSize () int size; int status; - if (this->sockState!=casOnLine) { - return MAX_TCP; - } - /* fetch the TCP send buffer size */ n = sizeof(size); status = getsockopt( @@ -400,12 +340,3 @@ int casStreamIO::getFD() const { return this->sock; } - -// -// casStreamIO::state() -// -casIOState casStreamIO::state() const -{ - return this->sockState; -} - diff --git a/src/cas/os/vxWorks/casOSD.h b/src/cas/os/vxWorks/casOSD.h index 873f0afa7..2ab8813d6 100644 --- a/src/cas/os/vxWorks/casOSD.h +++ b/src/cas/os/vxWorks/casOSD.h @@ -7,6 +7,9 @@ // Some BSD calls have crept in here // // $Log$ +// Revision 1.5 1997/08/05 00:47:26 jhill +// fixed warnings +// // Revision 1.4 1997/06/13 09:16:17 jhill // connect proto changes // @@ -39,18 +42,18 @@ class caServerOS; // class casBeaconTimer : public osiTimer { public: - casBeaconTimer (const osiTime &delay, caServerOS &osIn) : - os (osIn), osiTimer(delay) {} - void expire(); - const osiTime delay(); - osiBool again(); - const char *name() - { - return "casBeaconTimer"; - } + casBeaconTimer (const osiTime &delay, caServerOS &osIn) : + os (osIn), osiTimer(delay) {} + void expire(); + const osiTime delay(); + osiBool again(); + const char *name() + { + return "casBeaconTimer"; + } private: - caServerOS &os; - int taskId; + caServerOS &os; + int taskId; }; class casServerReg; @@ -66,38 +69,20 @@ void caServerEntry(caServerI *pCAS); // caServerOS // class caServerOS { - friend class casServerReg; - friend void caServerEntry(caServerI *pCAS); + friend class casServerReg; + friend void caServerEntry(caServerI *pCAS); public: - caServerOS (caServerI &casIn) : - cas (casIn), pBTmr (NULL), tid(ERROR) {} - caStatus init (); - ~caServerOS (); + caServerOS (caServerI &casIn) : + cas (casIn), pBTmr (NULL), tid(ERROR) {} - inline caServerI * operator -> (); + caStatus init (); + ~caServerOS (); + inline caServerI * operator -> (); + private: - caServerI &cas; - casBeaconTimer *pBTmr; -}; - -// -// casDGIntfOS -// -class casDGIntfOS : public casDGIO { -public: - casDGIntfOS(casDGClient &client); - ~casDGIntfOS(); - - caStatus start(); - - void show(unsigned level) const; - - void recvCB(); - void sendCB(); -private: - casDGClient &client; - int tid; +// caServerI &cas; + casBeaconTimer *pBTmr; }; // @@ -106,19 +91,19 @@ private: class casIntfOS : public casIntfIO, public tsDLNode { public: - casIntfOS (caServerI &casIn) : - cas (casIn), pRdReg (NULL) {} - caStatus init(const caNetAddr &addr, casDGClient &dgClientIn, - int autoBeaconAddr, int addConfigBeaconAddr); - ~casIntfOS(); - - void recvCB (); - void sendCB () {}; // NOOP satifies template - - casDGIO *newDGIO (casDGClient &dgClientIn) const; + casIntfOS (caServerI &casIn) : + cas (casIn), pRdReg (NULL) {} + caStatus init (caServerI &casIn, const caNetAddr &addr, + bool autoBeaconAddr, bool addConfigBeaconAddr); + ~casIntfOS(); + + void recvCB (); + void sendCB () {}; // NOOP satifies template + + casDGIO *newDGIO (casDGClient &dgClientIn) const; private: - caServerI &cas; - int tid; + caServerI &cas; + int tid; }; // no additions below this line diff --git a/src/cas/os/vxWorks/casStreamOS.cc b/src/cas/os/vxWorks/casStreamOS.cc index 9cb0d0951..4d80160e8 100644 --- a/src/cas/os/vxWorks/casStreamOS.cc +++ b/src/cas/os/vxWorks/casStreamOS.cc @@ -4,6 +4,9 @@ // // // $Log$ +// Revision 1.6 1998/09/24 20:53:54 jhill +// cosmetic +// // Revision 1.5 1997/08/05 00:47:27 jhill // fixed warnings // @@ -61,32 +64,22 @@ casStreamOS::casStreamOS(caServerI &cas, casMsgIO &ioIn) : clientTId(NULL), eventTId(NULL) { + caStatus status; + + this->eventSignalSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); + if (this->eventSignalSem == NULL) { + throw S_cas_noMemory; + } + + // + // init the base classes + // + status = this->casStrmClient::init(); + if (status) { + throw status; + } } -// -// casStreamOS::init() -// -caStatus casStreamOS::init() -{ - caStatus status; - - this->eventSignalSem = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY); - if (this->eventSignalSem == NULL) { - return S_cas_noMemory; - } - - // - // init the base classes - // - status = this->casStrmClient::init(); - if (status) { - return status; - } - - return S_cas_success; -} - - // // casStreamOS::~casStreamOS() // @@ -211,7 +204,7 @@ casProcCond casStreamOS::processInput() // int casStrmServer (casStreamOS *pStrmOS) { - casFillCondition fillCond; + inBuf::fillCondition fillCond; casProcCond procCond; //