diff --git a/src/ca/Makefile b/src/ca/Makefile index 7f0ca5973..9f4d4d9fc 100644 --- a/src/ca/Makefile +++ b/src/ca/Makefile @@ -77,11 +77,12 @@ Com_DIR = $(INSTALL_LIB) caRepeater_SRCS = caRepeater.cpp PROD += caRepeater -PROD_DEFAULT += catime acctst +PROD_DEFAULT += catime acctst caConnTest catime_SRCS = catimeMain.c catime.c acctst_SRCS = acctstMain.c acctst.c +caConnTest_SRCS = caConnTestMain.c caConnTest.c -PROD_vxWorks = catime acctst +PROD_vxWorks = catime acctst caConnTest include $(TOP)/configure/RULES diff --git a/src/ca/access.cpp b/src/ca/access.cpp index 2461c6a91..14343ed89 100644 --- a/src/ca/access.cpp +++ b/src/ca/access.cpp @@ -790,19 +790,25 @@ unsigned epicsShareAPI ca_get_ioc_connection_count () return pcac->connectionCount (); } -epicsShareFunc int epicsShareAPI ca_channel_status (threadId /* tid */) +epicsShareFunc int epicsShareAPI ca_channel_status ( threadId tid ) +{ + printf ("new OSI API does not allow peeking at thread private storage of another thread\n"); + printf ("please call \"ca_client_status ( unsigned level )\" from the subsystem specific diagnostic code.\n"); + return ECA_ANACHRONISM; +} + +epicsShareFunc int epicsShareAPI ca_client_status ( unsigned level ) { cac *pcac; int caStatus; - caStatus = fetchClientContext (&pcac); + caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } - pcac->show (10u); - - return ECA_NORMAL; + pcac->show ( level ); + return ECA_NORMAL; } /* @@ -1079,7 +1085,7 @@ extern "C" epicsShareDef const unsigned short dbr_value_offset[LAST_BUFFER_TYPE+ 0, /* string */ }; -extern "C" epicsShareDef const char *db_field_text[] = { +extern "C" epicsShareDef const char *dbf_text[LAST_TYPE+1] = { "DBF_STRING", "DBF_SHORT", "DBF_FLOAT", diff --git a/src/ca/acctst.c b/src/ca/acctst.c index 0bed64168..b795a3e90 100644 --- a/src/ca/acctst.c +++ b/src/ca/acctst.c @@ -302,8 +302,14 @@ void verifyBlockingConnect ( appChan *pChans, unsigned chanCount, unsigned repet assert ( VALID_DB_REQ ( ca_field_type ( pChans[j].channel ) ) == TRUE ); } else { - assert ( INVALID_DB_REQ ( ca_field_type ( pChans[j].channel ) ) == TRUE ); - assert ( ca_test_io () == ECA_IOINPROGRESS ); + /* + * its possible for the channel to connect while this test is going on + */ + unsigned ctr; + for ( ctr = 0u; ctr < 100u; ctr ++ ) { + assert ( INVALID_DB_REQ ( ca_field_type ( pChans[j].channel ) ) == TRUE ); + assert ( ca_test_io () == ECA_IOINPROGRESS ); + } } status = ca_replace_access_rights_event ( diff --git a/src/ca/baseNMIU.cpp b/src/ca/baseNMIU.cpp index 248b7cfa7..f9975e054 100644 --- a/src/ca/baseNMIU.cpp +++ b/src/ca/baseNMIU.cpp @@ -32,3 +32,8 @@ int baseNMIU::subscriptionMsg () { return ECA_NORMAL; } + +void baseNMIU::show ( unsigned /* level */ ) const +{ + printf ( "CA IO primitive at %p for channel %s\n", this, chan.pName () ); +} \ No newline at end of file diff --git a/src/ca/bhe.cpp b/src/ca/bhe.cpp index aecf2f5a8..9f2184b6f 100644 --- a/src/ca/bhe.cpp +++ b/src/ca/bhe.cpp @@ -139,3 +139,10 @@ bool bhe::updateBeaconPeriod (osiTime programBeginTime) return netChange; } +void bhe::show ( unsigned level ) const +{ + printf ( "CA beacon hash entry at %p with average period %f\n", this, this->averagePeriod ); + if ( level > 0u ) { + printf ( "network IO pointer %p, client pointer %p\n", this->piiu, &this->cac ); + } +} diff --git a/src/ca/caConnTest.c b/src/ca/caConnTest.c index 378f649c2..a63b8852e 100644 --- a/src/ca/caConnTest.c +++ b/src/ca/caConnTest.c @@ -50,8 +50,7 @@ void caConnTest ( const char *pNameIn, unsigned channelCountIn, double delayIn ) status = ca_pend_io ( 60.0 * 10.0 ); SEVCHK ( status, "channels didnt connect" ); - status = ca_pend_event ( delayIn ); - SEVCHK ( status, "CA pend event failed" ); + ca_pend_event ( delayIn ); status = ca_task_exit(); SEVCHK ( status, "task exit problems" ); diff --git a/src/ca/caDiagnostics.h b/src/ca/caDiagnostics.h index 0623d35ed..52dffc4b3 100644 --- a/src/ca/caDiagnostics.h +++ b/src/ca/caDiagnostics.h @@ -5,6 +5,8 @@ int catime ( char *channelName, unsigned channelCount, enum appendNumberFlag app int acctst ( char *pname, unsigned channelCount, unsigned repititionCount ); +void caConnTest ( const char *pNameIn, unsigned channelCountIn, double delayIn ); + #define CATIME_OK 0 #define CATIME_ERROR -1 diff --git a/src/ca/cac.cpp b/src/ca/cac.cpp index 2afd3ee34..e2eb8f9b9 100644 --- a/src/ca/cac.cpp +++ b/src/ca/cac.cpp @@ -87,11 +87,6 @@ cac::cac ( bool enablePreemptiveCallbackIn ) : this->ca_exception_arg = NULL; this->readSeq = 0u; - this->ca_blockSem = semBinaryCreate(semEmpty); - if (!this->ca_blockSem) { - throwWithLocation ( caErrorCode (ECA_ALLOCMEM) ); - } - installSigPipeIgnore (); { @@ -106,7 +101,6 @@ cac::cac ( bool enablePreemptiveCallbackIn ) : len = strlen ( tmp ) + 1; this->pUserName = new char [len]; if ( ! this->pUserName ) { - semBinaryDestroy (this->ca_blockSem); throwWithLocation ( caErrorCode (ECA_ALLOCMEM) ); } strncpy ( this->pUserName, tmp, len ); @@ -209,7 +203,6 @@ cac::~cac () this->beaconTable.destroyAllEntries (); this->chanTable.destroyAllEntries (); this->ioTable.destroyAllEntries (); - semBinaryDestroy ( this->ca_blockSem ); osiSockRelease (); @@ -275,21 +268,89 @@ unsigned cac::connectionCount () const return this->iiuList.count (); } -void cac::show (unsigned level) const +void cac::show ( unsigned level ) const { - if ( this->pudpiiu ) { - this->pudpiiu->show (level); + ::printf ( "Channel Access Client Context at %p for user %s\n", + this, this->pUserName ); + if (level > 0u ) { + this->iiuListMutex.lock (); + tsDLIterConstBD < tcpiiu > piiu ( this->iiuList.first () ); + while ( piiu.valid () ) { + piiu->show ( level - 1u ); + piiu++; + } + this->iiuListMutex.unlock (); + + this->defaultMutex.lock (); + tsDLIterConstBD < cacLocalChannelIO > pChan ( this->localChanList.first () ); + while ( pChan.valid () ) { + pChan->show ( level - 1u ); + pChan++; + } + this->defaultMutex.unlock (); + + ::printf ( "\tconnection time out watchdog period %f\n", this->connTMO ); + ::printf ( "\tthere are %u unsatisfied IO operations blocking ca_pend_io()\n", + this->pndrecvcnt ); + ::printf ( "\tpreemptive calback is %s\n", + this->enablePreemptiveCallback ? "enabled" : "disabled" ); + ::printf ( "list of installed services:\n" ); + this->services.show ( level - 1u ); } - this->iiuListMutex.lock (); + if ( level > 1u ) { + if ( this->pudpiiu ) { + this->pudpiiu->show ( level - 2u ); + } + ::printf ( "\texception function %p, exception arg %p\n", + this->ca_exception_func, this->ca_exception_arg ); + ::printf ( "\tCA printf function %p\n", + this->pVPrintfFunc); + ::printf ( "\tfile descriptor registration function %p, file descriptor registration arg %p\n", + this->fdRegFunc, this->fdRegArg ); + } - tsDLIterConstBD piiu ( this->iiuList.first () ); - while ( piiu.valid () ) { - piiu->show (level); - piiu++; - } + if ( level > 2u ) { + ::printf ( "Program begin time:\n"); + ::printf ( "the current read sequence for ca_pend_io() is %u\n", + this->readSeq ); + this->programBeginTime.show ( level - 3u ); + ::printf ( "IO identifier hash table:\n" ); + this->ioTable.show ( level - 3u ); + ::printf ( "Channel identifier hash table:\n" ); + this->chanTable.show ( level - 3u ); + ::printf ( "Synchronous group identifier hash table:\n" ); + this->sgTable.show ( level - 3u ); + ::printf ( "Beacon source identifier hash table:\n" ); + this->beaconTable.show ( level - 3u ); + if ( this->pTimerQueue ) { + ::printf ( "Timer queue:\n" ); + this->pTimerQueue->show ( level - 3u ); + } + if ( this->pRecvProcThread ) { + ::printf ( "incoming messages processing thread:\n" ); + this->pRecvProcThread->show ( level - 3u ); + } + if ( this->pSearchTmr ) { + ::printf ( "search message timer:\n" ); + this->pSearchTmr->show ( level - 3u ); + } + if ( this->pRepeaterSubscribeTmr ) { + ::printf ( "repeater subscribee timer:\n" ); + this->pRepeaterSubscribeTmr->show ( level - 3u ); + } + ::printf ( "IP address to name conversion engine:\n" ); + this->ipToAEngine.show ( level - 3u ); + } - this->iiuListMutex.unlock (); + if ( level > 3u ) { + ::printf ( "IO done event:\n"); + this->ioDone.show ( level - 4u ); + ::printf ( "Default mutex:\n"); + this->defaultMutex.show ( level - 4u ); + ::printf ( "Virtual circuit list mutex:\n"); + this->iiuListMutex.show ( level - 4u ); + } } void cac::installIIU ( tcpiiu &iiu ) @@ -451,8 +512,8 @@ void cac::beaconNotify ( const inetAddrID &addr ) delay /= MSEC_PER_SEC; delay += CA_RECAST_DELAY; - if ( this->pSearchTmr ) { - this->pSearchTmr->reset ( delay ); + if ( this->pudpiiu->channelCount () > 0u && this->pSearchTmr ) { + this->pSearchTmr->resetPeriod ( delay ); } } @@ -1054,7 +1115,7 @@ void cac::installDisconnectedChannel ( nciu &chan ) chan.attachChanToIIU ( *this->pudpiiu ); chan.resetRetryCount (); - this->pSearchTmr->reset ( CA_RECAST_DELAY ); + this->pSearchTmr->resetPeriod ( CA_RECAST_DELAY ); } void cac::notifySearchResponse ( unsigned short retrySeqNo ) diff --git a/src/ca/cacIO.h b/src/ca/cacIO.h index 1ec2fee62..ef196f629 100644 --- a/src/ca/cacIO.h +++ b/src/ca/cacIO.h @@ -119,6 +119,8 @@ public: virtual void lockOutstandingIO () const = 0; virtual void unlockOutstandingIO () const = 0; + virtual void show ( unsigned level ) const = 0u; + private: virtual int read ( unsigned type, unsigned long count, void *pValue) = 0; virtual int read ( unsigned type, unsigned long count, cacNotify ¬ify ) = 0; @@ -144,15 +146,16 @@ private: }; class cacLocalChannelIO : - public cacChannelIO, public tsDLNode { + public cacChannelIO, public tsDLNode < cacLocalChannelIO > { public: epicsShareFunc cacLocalChannelIO ( cacChannel &chan ); epicsShareFunc virtual ~cacLocalChannelIO () = 0; }; -struct cacServiceIO : public tsDLNode { +struct cacServiceIO : public tsDLNode < cacServiceIO > { public: epicsShareFunc virtual cacLocalChannelIO *createChannelIO ( cacChannel &chan, const char *pName ) = 0; + epicsShareFunc virtual void show ( unsigned level ) const = 0u; private: }; @@ -160,9 +163,10 @@ class cacServiceList : private osiMutex { public: epicsShareFunc cacServiceList (); epicsShareFunc void registerService ( cacServiceIO &service ); - epicsShareFunc cacLocalChannelIO * createChannelIO (const char *pName, cacChannel &chan); + epicsShareFunc cacLocalChannelIO * createChannelIO ( const char *pName, cacChannel &chan ); + epicsShareFunc void show ( unsigned level ) const; private: - tsDLList services; + tsDLList < cacServiceIO > services; }; epicsShareExtern cacServiceList cacGlobalServiceList; diff --git a/src/ca/cacServiceList.cpp b/src/ca/cacServiceList.cpp index 48b12c3e9..03f9887d3 100644 --- a/src/ca/cacServiceList.cpp +++ b/src/ca/cacServiceList.cpp @@ -48,3 +48,16 @@ cacLocalChannelIO * cacServiceList::createChannelIO (const char *pName, cacChann return pChanIO; } +void cacServiceList::show ( unsigned level ) const +{ + cacLocalChannelIO *pChanIO = 0; + + this->lock (); + tsDLIterConstBD < cacServiceIO > iter ( this->services.first () ); + while ( iter.valid () ) { + iter->show ( level ); + iter++; + } + this->unlock (); +} + diff --git a/src/ca/cadef.h b/src/ca/cadef.h index d4e93e980..4ec01c1f4 100644 --- a/src/ca/cadef.h +++ b/src/ca/cadef.h @@ -940,6 +940,7 @@ epicsShareFunc int epicsShareAPI ca_current_context (caClientCtx *pCurrentContex epicsShareFunc int epicsShareAPI ca_attach_context (caClientCtx context); epicsShareFunc int epicsShareAPI ca_channel_status (threadId tid); +epicsShareFunc int epicsShareAPI ca_client_status (threadId tid, unsigned level); /* * deprecated @@ -996,6 +997,7 @@ epicsShareFunc char * epicsShareAPI ca_version(); epicsShareFunc int epicsShareAPI ca_import(); epicsShareFunc int epicsShareAPI ca_import_cancel(); epicsShareFunc int epicsShareAPI ca_channel_status (); +epicsShareFunc int epicsShareAPI ca_client_status (); #define ca_build_channel(NAME,XXXXX,CHIDPTR,YYYYY)\ ca_build_and_connect(NAME, XXXXX, 1, CHIDPTR, YYYYY, 0, 0) #define ca_array_build(NAME,XXXXX, ZZZZZZ, CHIDPTR,YYYYY)\ diff --git a/src/ca/db_access.h b/src/ca/db_access.h index 70e36d59f..2d6007588 100644 --- a/src/ca/db_access.h +++ b/src/ca/db_access.h @@ -736,7 +736,7 @@ union db_access_val{ #define dbf_type_to_text(type) \ ( ((type) >= 0 && (type) < dbf_text_dim) ? \ - db_field_text[type] : dbf_text_invalid ) + dbf_text[type] : dbf_text_invalid ) #define dbf_text_to_type(text, type) \ for (type=dbf_text_dim-1; type>=0; type--) { \ @@ -775,7 +775,7 @@ union db_access_val{ (type) + 4*(dbf_text_dim-2) : -1 ) -epicsShareExtern READONLY char *dbf_text[LAST_TYPE+2]; +epicsShareExtern READONLY char *dbf_text[LAST_TYPE+1]; epicsShareExtern READONLY short dbf_text_dim; epicsShareExtern READONLY char *dbf_text_invalid; diff --git a/src/ca/iocinf.h b/src/ca/iocinf.h index ae881b422..59b2568c3 100644 --- a/src/ca/iocinf.h +++ b/src/ca/iocinf.h @@ -320,21 +320,23 @@ public: void ioInstall ( class baseNMIU & ); void ioDestroy ( unsigned id ); + void show ( unsigned level ) const; + private: - caar ar; /* access rights */ + caar ar; // access rights unsigned count; char *pNameStr; netiiu *piiu; - unsigned sid; /* server id */ - unsigned retry; /* search retry number */ - mutable unsigned short ptrLockCount; /* number of times IIU pointer was locked */ - mutable unsigned short ptrUnlockWaitCount; /* number of threads waiting for IIU pointer unlock */ - unsigned short retrySeqNo; /* search retry seq number */ - unsigned short nameLength; /* channel name length */ + unsigned sid; // server id + unsigned retry; // search retry number + mutable unsigned short ptrLockCount; // number of times IIU pointer was locked + mutable unsigned short ptrUnlockWaitCount; // number of threads waiting for IIU pointer unlock + unsigned short retrySeqNo; // search retry seq number + unsigned short nameLength; // channel name length unsigned short typeCode; unsigned f_connected:1; unsigned f_fullyConstructed:1; - unsigned previousConn:1; /* T if connected in the past */ + unsigned previousConn:1; // T if connected in the past static tsFreeList < class nciu, 1024 > freeList; @@ -358,8 +360,9 @@ public: virtual void completionNotify ( unsigned type, unsigned long count, const void *pData ) = 0; virtual void exceptionNotify ( int status, const char *pContext ) = 0; virtual void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count ) = 0; - virtual int subscriptionMsg (); virtual void disconnect ( const char *pHostName ) = 0; + virtual void show ( unsigned level ) const; + virtual int subscriptionMsg (); void destroy (); protected: virtual ~baseNMIU (); // must be allocated from pool @@ -372,6 +375,7 @@ public: void disconnect ( const char *pHostName ); static bool factory ( nciu &chan, chtype type, unsigned long count, unsigned short mask, cacNotify ¬ify, unsigned &id ); + void show ( unsigned level ) const; private: chtype type; unsigned long count; @@ -396,6 +400,7 @@ public: void disconnect ( const char *pHostName ); static bool factory ( nciu &chan, unsigned type, unsigned long count, void *pValue, unsigned seqNumber, ca_uint32_t &id ); + void show ( unsigned level ) const; private: unsigned type; unsigned long count; @@ -418,6 +423,7 @@ class netReadNotifyIO : public cacNotifyIO, private baseNMIU { public: void disconnect ( const char *pHostName ); static bool factory ( nciu &chan, cacNotify ¬ify, ca_uint32_t &id ); + void show ( unsigned level ) const; private: netReadNotifyIO ( nciu &chan, cacNotify ¬ify ); ~netReadNotifyIO (); @@ -435,6 +441,7 @@ class netWriteNotifyIO : public cacNotifyIO, private baseNMIU { public: void disconnect ( const char *pHostName ); static bool factory ( nciu &chan, cacNotify ¬ify, ca_uint32_t &id ); + void show ( unsigned level ) const; private: netWriteNotifyIO ( nciu &chan, cacNotify ¬ify ); ~netWriteNotifyIO (); @@ -529,7 +536,7 @@ protected: void lock () const; void unlock () const; private: - tsDLList < nciu > chidList; + tsDLList < nciu > channelList; class cac &cacRef; osiMutex mutex; @@ -545,15 +552,14 @@ class searchTimer : private osiTimer, private osiMutex { public: searchTimer ( udpiiu &iiu, osiTimerQueue &queue ); void notifySearchResponse ( unsigned short retrySeqNo ); - void reset ( double delayToNextTry ); - + void resetPeriod ( double delayToNextTry ); + void show ( unsigned level ) const; private: - virtual void expire (); - virtual void destroy (); - virtual bool again () const; - virtual double delay () const; - virtual void show (unsigned level) const; - virtual const char *name () const; + void expire (); + void destroy (); + bool again () const; + double delay () const; + const char *name () const; void setRetryInterval (unsigned retryNo); @@ -573,14 +579,14 @@ class repeaterSubscribeTimer : private osiTimer { public: repeaterSubscribeTimer (udpiiu &iiu, osiTimerQueue &queue); void confirmNotify (); + void show (unsigned level) const; private: - virtual void expire (); - virtual void destroy (); - virtual bool again () const; - virtual double delay () const; - virtual void show (unsigned level) const; - virtual const char *name () const; + void expire (); + void destroy (); + bool again () const; + double delay () const; + const char *name () const; udpiiu &iiu; unsigned attempts; @@ -602,12 +608,12 @@ public: void flush (); SOCKET getSock () const; bool repeaterInstalled (); + void show ( unsigned level ) const; // exceptions class noSocket {}; class noMemory {}; private: - osiTime recvTime; char xmitBuf [MAX_UDP_SEND]; char recvBuf [MAX_UDP_RECV]; ELLLIST dest; @@ -649,6 +655,7 @@ public: void beaconArrivalNotify (); void beaconAnomalyNotify (); void connectNotify (); + void show (unsigned level ) const; private: void expire (); @@ -764,15 +771,8 @@ private: unsigned long curDataMax; class bhe &bhe; void *pCurData; - unsigned minor_version_number; + unsigned minorProtocolVersionNumber; iiu_conn_state state; - - bool ca_v42_ok () const; - void postMsg (); - unsigned sendBytes ( const void *pBuf, unsigned nBytesInBuf ); - unsigned recvBytes ( void *pBuf, unsigned nBytesInBuf ); - bool flushToWirePermit (); - claimsPendingIIU *pClaimsPendingIIU; semBinaryId sendThreadFlushSignal; semBinaryId recvThreadRingBufferSpaceAvailableSignal; @@ -783,12 +783,16 @@ private: bool fullyConstructedFlag; bool busyStateDetected; // only modified by the recv thread bool flowControlActive; // only modified by the send process thread - bool flowControlStateChange; bool echoRequestPending; - bool recvPending; + bool recvMessagePending; bool flushPending; bool msgHeaderAvailable; - static tsFreeList < class tcpiiu, 16 > freeList; + + bool ca_v42_ok () const; + void postMsg (); + unsigned sendBytes ( const void *pBuf, unsigned nBytesInBuf ); + unsigned recvBytes ( void *pBuf, unsigned nBytesInBuf ); + bool flushToWirePermit (); friend void cacSendThreadTCP ( void *pParam ); friend void cacRecvThreadTCP ( void *pParam ); @@ -812,6 +816,7 @@ private: typedef void ( tcpiiu::*pProtoStubTCP ) (); static const pProtoStubTCP tcpJumpTableCAC []; + static tsFreeList < class tcpiiu, 16 > freeList; }; class inetAddrID { @@ -825,13 +830,14 @@ private: struct sockaddr_in addr; }; -class bhe : public tsSLNode , public inetAddrID { +class bhe : public tsSLNode < bhe >, public inetAddrID { public: bhe ( class cac &cacIn, const osiTime &initialTimeStamp, const inetAddrID &addr ); tcpiiu *getIIU () const; void bindToIIU ( tcpiiu & ); void destroy (); bool updateBeaconPeriod ( osiTime programBeginTime ); + void show ( unsigned level) const; static void * operator new ( size_t size ); static void operator delete ( void *pCadaver, size_t size ); @@ -848,7 +854,7 @@ private: class caErrorCode { public: - caErrorCode (int status) : code (status) {}; + caErrorCode ( int status ) : code ( status ) {}; private: int code; }; @@ -862,6 +868,7 @@ public: void enable (); void disable (); void signalActivity (); + void show ( unsigned level ) const; private: // // The additional complexity associated with @@ -1052,7 +1059,6 @@ public: private: ipAddrToAsciiEngine ipToAEngine; - char ca_new_err_code_msg_buf[128u]; cacServiceList services; tsDLList iiuList; tsDLList @@ -1067,21 +1073,20 @@ private: < bhe, inetAddrID > beaconTable; osiTime programBeginTime; double connTMO; + osiEvent ioDone; + osiMutex defaultMutex; + osiMutex iiuListMutex; osiTimerQueue *pTimerQueue; caExceptionHandler *ca_exception_func; void *ca_exception_arg; caPrintfFunc *pVPrintfFunc; char *pUserName; - osiEvent ioDone; recvProcessThread *pRecvProcThread; CAFDHANDLER *fdRegFunc; void *fdRegArg; udpiiu *pudpiiu; searchTimer *pSearchTmr; repeaterSubscribeTimer *pRepeaterSubscribeTmr; - semBinaryId ca_blockSem; - osiMutex defaultMutex; - osiMutex iiuListMutex; unsigned pndrecvcnt; unsigned readSeq; bool enablePreemptiveCallback; diff --git a/src/ca/nciu.cpp b/src/ca/nciu.cpp index b8a21483b..345b04ece 100644 --- a/src/ca/nciu.cpp +++ b/src/ca/nciu.cpp @@ -515,31 +515,36 @@ void nciu::disconnect () { char hostNameBuf[64]; this->hostName ( hostNameBuf, sizeof (hostNameBuf) ); + bool wasConnected; this->lock (); - if ( ! this->f_connected ) { - this->unlock (); - return; - } - this->retry = 0u; this->typeCode = USHRT_MAX; this->count = 0u; this->sid = UINT_MAX; this->ar.read_access = false; this->ar.write_access = false; + + if ( this->f_connected ) { + wasConnected = true; + } + else { + wasConnected = false; + } this->f_connected = false; this->unlock (); - /* - * look for events that have an event cancel in progress - */ - disconnectAllIO ( hostNameBuf ); - this->disconnectNotify (); - this->accessRightsNotify ( this->ar ); + if ( wasConnected ) { + /* + * look for events that have an event cancel in progress + */ + disconnectAllIO ( hostNameBuf ); + this->disconnectNotify (); + this->accessRightsNotify ( this->ar ); + } this->cacCtx.installDisconnectedChannel ( *this ); } @@ -626,8 +631,8 @@ void nciu::attachChanToIIU ( netiiu &iiu ) if ( this->piiu ) { this->piiu->mutex.lock (); - this->piiu->chidList.remove ( *this ); - if ( this->piiu->chidList.count () == 0u ) { + this->piiu->channelList.remove ( *this ); + if ( this->piiu->channelList.count () == 0u ) { this->piiu->lastChannelDetachNotify (); } this->piiu->mutex.unlock (); @@ -637,7 +642,7 @@ void nciu::attachChanToIIU ( netiiu &iiu ) // add to the front of the list so that // search requests for new channels will be sent first - iiu.chidList.push ( *this ); + iiu.channelList.push ( *this ); this->piiu = &iiu; iiu.mutex.unlock (); @@ -650,8 +655,8 @@ void nciu::detachChanFromIIU () this->lockPIIU (); if ( this->piiu ) { this->piiu->mutex.lock (); - this->piiu->chidList.remove ( *this ); - if ( this->piiu->chidList.count () == 0u ) { + this->piiu->channelList.remove ( *this ); + if ( this->piiu->channelList.count () == 0u ) { this->piiu->lastChannelDetachNotify (); } this->piiu->mutex.unlock (); @@ -808,3 +813,37 @@ int nciu::subscribe ( unsigned type, unsigned long countIn, return ECA_ALLOCMEM; } } + +void nciu::show ( unsigned level ) const +{ + if ( this->f_connected ) { + char hostNameTmp [256]; + this->hostName ( hostNameTmp, sizeof ( hostNameTmp ) ); + printf ( "Channel \"%s\", connected to server %s", + this->pNameStr, hostNameTmp ); + if ( level > 1u ) { + printf ( ", native type %s, native element count %u", + dbf_type_to_text ( this->typeCode ), this->count ); + printf ( ", %sread access, %swrite access", + this->ar.read_access ? "" : "no ", + this->ar.write_access ? "" : "no "); + } + printf ( "\n" ); + } + else if ( this->previousConn ) { + printf ( "Channel \"%s\" (previously connected to a server)\n", this->pNameStr, hostName ); + } + else { + printf ( "Channel \"%s\" (unable to locate server)\n", this->pNameStr, hostName ); + } + + if ( level > 2u ) { + printf ( "\tnetwork IO pointer=%p, ptr lock count=%u, ptr unlock wait count=%u\n", + this->piiu, this->ptrLockCount, this->ptrUnlockWaitCount ); + printf ( "\tserver identifier %u\n", this->sid ); + printf ( "\tsearch retry number=%u, search retry sequence number=%u\n", + this->retry, this->retrySeqNo ); + printf ( "\tname length=%u\n", this->nameLength ); + printf ( "\tfully cunstructed boolean=%u\n", this->f_fullyConstructed ); + } +} diff --git a/src/ca/netReadCopyIO.cpp b/src/ca/netReadCopyIO.cpp index 8ff8d3d00..9d1b4ecdd 100644 --- a/src/ca/netReadCopyIO.cpp +++ b/src/ca/netReadCopyIO.cpp @@ -70,3 +70,14 @@ void netReadCopyIO::exceptionNotify ( int status, "%s type=%d count=%ld\n", pContextIn, typeIn, countIn); } + +void netReadCopyIO::show ( unsigned level ) const +{ + printf ( "read copy IO at %p, type %s, element count %u\n", + this, this->type, this->count ); + if ( level > 0u ) { + printf ( "\tsequence number %u, user's storage %p\n", + this->seqNumber, this->pValue ); + this->baseNMIU::show ( level - 1u ); + } +} diff --git a/src/ca/netReadNotifyIO.cpp b/src/ca/netReadNotifyIO.cpp index 21c5edaaf..186bef624 100644 --- a/src/ca/netReadNotifyIO.cpp +++ b/src/ca/netReadNotifyIO.cpp @@ -57,3 +57,11 @@ void netReadNotifyIO::exceptionNotify ( int status, const char *pContext, { this->cacNotifyIO::exceptionNotify ( status, pContext, type ,count ); } + +void netReadNotifyIO::show ( unsigned level ) const +{ + printf ( "read notify IO at %p\n", this ); + if ( level > 0u ) { + this->baseNMIU::show ( level - 1u ); + } +} diff --git a/src/ca/netSubscription.cpp b/src/ca/netSubscription.cpp index df8212fd7..a8716adaf 100644 --- a/src/ca/netSubscription.cpp +++ b/src/ca/netSubscription.cpp @@ -67,3 +67,11 @@ void netSubscription::exceptionNotify ( int statusIn, pContextIn, typeIn, countIn ); } +void netSubscription::show ( unsigned level ) const +{ + printf ( "event subscription IO at %p, type %s, element count %lu, mask %u\n", + this, dbf_type_to_text ( this->type ), this->count, this->mask ); + if ( level > 0u ) { + this->baseNMIU::show ( level - 1u ); + } +} diff --git a/src/ca/netWriteNotifyIO.cpp b/src/ca/netWriteNotifyIO.cpp index fe7251ce7..d12bb1fd7 100644 --- a/src/ca/netWriteNotifyIO.cpp +++ b/src/ca/netWriteNotifyIO.cpp @@ -57,3 +57,11 @@ void netWriteNotifyIO::exceptionNotify ( int status, const char *pContext, unsig { this->cacNotifyIO::exceptionNotify (status, pContext, type, count); } + +void netWriteNotifyIO::show ( unsigned level ) const +{ + printf ( "read write notify IO at %p\n", this ); + if ( level > 0u ) { + this->baseNMIU::show ( level - 1u ); + } +} \ No newline at end of file diff --git a/src/ca/netiiu.cpp b/src/ca/netiiu.cpp index 54aa1a184..aab29fc61 100644 --- a/src/ca/netiiu.cpp +++ b/src/ca/netiiu.cpp @@ -18,46 +18,30 @@ netiiu::~netiiu () { + assert ( this->channelList.count () == 0u ); } -void netiiu::show ( unsigned /* level */ ) const +void netiiu::show ( unsigned level ) const { this->lock (); - - tsDLIterConstBD pChan ( this->chidList.first () ); - while ( pChan.valid () ) { - char hostName [256]; - printf( "%s native type=%d ", - pChan->pName (), pChan->nativeType () ); - pChan->hostName ( hostName, sizeof (hostName) ); - printf( "N elements=%lu server=%s state=", - pChan->nativeElementCount (), hostName ); - switch ( pChan->state () ) { - case cs_never_conn: - printf ( "never connected to an IOC" ); - break; - case cs_prev_conn: - printf ( "disconnected from IOC" ); - break; - case cs_conn: - printf ( "connected to an IOC" ); - break; - case cs_closed: - printf ( "invalid channel" ); - break; - default: - break; - } - printf ( "\n" ); - } - + printf ( "network IO base class\n" ); + if ( level > 1 ) { + tsDLIterConstBD < nciu > pChan ( this->channelList.first () ); + while ( pChan.valid () ) { + pChan->show ( level - 1u ); + pChan = pChan.itemAfter (); + } + } + if ( level > 2u ) { + printf ("\tcac pointer %p\n", &this->cacRef ); + this->mutex.show ( level - 2u ); + } this->unlock (); - } unsigned netiiu::channelCount () const { - return this->chidList.count (); + return this->channelList.count (); } void netiiu::lock () const @@ -73,7 +57,7 @@ void netiiu::unlock () const void netiiu::detachAllChan () { this->lock (); - tsDLIterBD chan ( this->chidList.first () ); + tsDLIterBD chan ( this->channelList.first () ); while ( chan.valid () ) { tsDLIterBD next = chan.itemAfter (); chan->detachChanFromIIU (); @@ -85,7 +69,7 @@ void netiiu::detachAllChan () void netiiu::disconnectAllChan () { this->lock (); - tsDLIterBD chan ( this->chidList.first () ); + tsDLIterBD chan ( this->channelList.first () ); while ( chan.valid () ) { tsDLIterBD next = chan.itemAfter (); chan->disconnect (); @@ -97,7 +81,7 @@ void netiiu::disconnectAllChan () void netiiu::connectTimeoutNotify () { this->lock (); - tsDLIterBD chan ( this->chidList.first () ); + tsDLIterBD chan ( this->channelList.first () ); while ( chan.valid () ) { chan->connectTimeoutNotify (); chan++; @@ -108,7 +92,7 @@ void netiiu::connectTimeoutNotify () void netiiu::resetChannelRetryCounts () { this->lock (); - tsDLIterBD chan ( this->chidList.first () ); + tsDLIterBD chan ( this->channelList.first () ); while ( chan.valid () ) { chan->resetRetryCount (); chan++; @@ -122,12 +106,12 @@ bool netiiu::searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThis this->lock (); - tsDLIterBD chan = this->chidList.first (); + tsDLIterBD chan = this->channelList.first (); if ( chan.valid () ) { status = chan->searchMsg ( retrySeqNumber, retryNoForThisChannel ); if ( status ) { - this->chidList.remove ( *chan ); - this->chidList.add ( *chan ); + this->channelList.remove ( *chan ); + this->channelList.add ( *chan ); } } else { @@ -149,7 +133,7 @@ void netiiu::sendPendingClaims ( tcpiiu &iiu, bool v42Ok, claimMsgCache &cache ) while ( 1 ) { while (1) { this->lock (); - tsDLIterBD < nciu > chan ( this->chidList.last () ); + tsDLIterBD < nciu > chan ( this->channelList.last () ); if ( ! chan.valid () ) { this->unlock (); return; @@ -172,7 +156,7 @@ void netiiu::sendPendingClaims ( tcpiiu &iiu, bool v42Ok, claimMsgCache &cache ) this->lock (); // if the channel was not deleted while the lock was off - tsDLIterBD < nciu > chan ( this->chidList.last () ); + tsDLIterBD < nciu > chan ( this->channelList.last () ); if ( chan.valid () ) { if ( cache.channelMatches ( *chan ) ) { if ( ! v42Ok ) { diff --git a/src/ca/recvProcessThread.cpp b/src/ca/recvProcessThread.cpp index 18483990b..415ab3e04 100644 --- a/src/ca/recvProcessThread.cpp +++ b/src/ca/recvProcessThread.cpp @@ -115,3 +115,29 @@ void recvProcessThread::signalActivity () { this->recvActivity.signal (); } + +void recvProcessThread::show ( unsigned level ) const +{ + this->mutex.lock (); + printf ( "CA receive processing thread at %p state=%s\n", + this, this->processing ? "busy" : "idle"); + if ( level > 0u ) { + printf ( "enable count %u\n", this->enableRefCount ); + printf ( "blocking for completion count %u\n", this->blockingForCompletion ); + } + if ( level > 1u ) { + printf ( "\tCA client at %p\n", this->pcac ); + printf ( "\tshutdown command boolean %u\n", this->shutDown ); + } + if ( level > 2u ) { + printf ( "Receive activity event:\n" ); + this->recvActivity.show ( level - 3u ); + printf ( "exit event:\n" ); + this->exit.show ( level - 3u ); + printf ( "processing done event:\n" ); + this->processingDone.show ( level - 3u ); + printf ( "mutex:\n" ); + this->mutex.show ( level - 3u ); + } + this->mutex.unlock (); +} diff --git a/src/ca/searchTimer.cpp b/src/ca/searchTimer.cpp index e0fc070a2..eecf9514c 100644 --- a/src/ca/searchTimer.cpp +++ b/src/ca/searchTimer.cpp @@ -37,9 +37,9 @@ searchTimer::searchTimer (udpiiu &iiuIn, osiTimerQueue &queueIn) : } // -// searchTimer::reset () +// searchTimer::resetPeriod () // -void searchTimer::reset ( double delayToNextTry ) +void searchTimer::resetPeriod ( double delayToNextTry ) { bool reschedule; diff --git a/src/ca/tcpRecvWatchdog.cpp b/src/ca/tcpRecvWatchdog.cpp index 162f60479..de89b3789 100644 --- a/src/ca/tcpRecvWatchdog.cpp +++ b/src/ca/tcpRecvWatchdog.cpp @@ -100,3 +100,16 @@ const char *tcpRecvWatchdog::name () const return "TCP Receive Watchdog"; } +void tcpRecvWatchdog::show ( unsigned level ) const +{ + printf ( "Receive virtual circuit watchdog at %p, period %s\n", + this, this->period ); + if ( level > 0u ) { + printf ( "\tresponse pending boolean %u, beacon anomaly boolean %u\n", + this->responsePending, this->beaconAnomaly ); + } + if ( level > 1u ) { + printf ( "\techo protocol accepted boolean %u\n", + this->echoProtocolAccepted ); + } +} diff --git a/src/ca/tcpiiu.cpp b/src/ca/tcpiiu.cpp index 3fc7b1b65..51ac538bd 100644 --- a/src/ca/tcpiiu.cpp +++ b/src/ca/tcpiiu.cpp @@ -132,7 +132,7 @@ void tcpiiu::connect () extern "C" void cacSendThreadTCP ( void *pParam ) { tcpiiu *piiu = ( tcpiiu * ) pParam; - claimMsgCache cache ( CA_V44 ( CA_PROTOCOL_VERSION, piiu->minor_version_number ) ); + claimMsgCache cache ( CA_V44 ( CA_PROTOCOL_VERSION, piiu->minorProtocolVersionNumber ) ); while ( true ) { @@ -144,7 +144,7 @@ extern "C" void cacSendThreadTCP ( void *pParam ) if ( piiu->pClaimsPendingIIU->channelCount () > 0u ) { piiu->pClaimsPendingIIU->sendPendingClaims ( *piiu, - CA_V42 ( CA_PROTOCOL_VERSION, piiu->minor_version_number ), cache ); + CA_V42 ( CA_PROTOCOL_VERSION, piiu->minorProtocolVersionNumber ), cache ); piiu->flushPending = true; } @@ -281,10 +281,6 @@ unsigned tcpiiu::recvBytes ( void *pBuf, unsigned nBytesInBuf ) this->contigRecvMsgCount = 0u; this->busyStateDetected = false; } - - // care is taken not to post the busy/ready message to the send buffer - // here so that we avoid push/pull deadlocks - this->flowControlStateChange = this->busyStateDetected != this->flowControlActive; this->messageArrivalNotify (); // reschedule connection activity watchdog @@ -319,7 +315,7 @@ extern "C" void cacRecvThreadTCP (void *pParam) else { unsigned nBytesIn = piiu->fillFromWire (); if ( nBytesIn ) { - piiu->recvPending = true; + piiu->recvMessagePending = true; piiu->clientCtx ().signalRecvActivity (); } } @@ -351,8 +347,7 @@ tcpiiu::tcpiiu ( cac &cac, const osiSockAddr &addrIn, contigRecvMsgCount ( 0u ), busyStateDetected ( false ), flowControlActive ( false ), - flowControlStateChange ( false ), - recvPending ( false ), + recvMessagePending ( false ), flushPending ( false ), msgHeaderAvailable ( false ) { @@ -414,7 +409,7 @@ tcpiiu::tcpiiu ( cac &cac, const osiSockAddr &addrIn, #endif this->sock = newSocket; - this->minor_version_number = minorVersion; + this->minorProtocolVersionNumber = minorVersion; this->echoRequestPending = false; this->curDataMax = 0ul; memset ( (void *) &this->curMsg, '\0', sizeof (this->curMsg) ); @@ -524,7 +519,6 @@ void tcpiiu::cleanShutdown () } semBinaryGive ( this->sendThreadFlushSignal ); semBinaryGive ( this->recvThreadRingBufferSpaceAvailableSignal ); - this->recvPending = true; this->clientCtx ().signalRecvActivity (); } this->unlock (); @@ -545,7 +539,6 @@ void tcpiiu::forcedShutdown () } semBinaryGive ( this->sendThreadFlushSignal ); semBinaryGive ( this->recvThreadRingBufferSpaceAvailableSignal ); - this->recvPending = true; this->clientCtx ().signalRecvActivity (); } this->unlock (); @@ -563,8 +556,6 @@ tcpiiu::~tcpiiu () this->fullyConstructedFlag = false; - this->cleanShutdown (); - if ( this->channelCount () ) { char hostNameTmp[64]; this->ipToA.hostName ( hostNameTmp, sizeof ( hostNameTmp ) ); @@ -573,14 +564,17 @@ tcpiiu::~tcpiiu () this->disconnectAllChan (); + if ( this->pClaimsPendingIIU ) { + this->pClaimsPendingIIU->disconnectAllChan (); + delete this->pClaimsPendingIIU; + } + + this->cleanShutdown (); + // wait for send and recv threads to exit semBinaryMustTake ( this->sendThreadExitSignal ); semBinaryMustTake ( this->recvThreadExitSignal ); - if ( this->pClaimsPendingIIU ) { - delete this->pClaimsPendingIIU; - } - semBinaryDestroy ( this->sendThreadExitSignal ); semBinaryDestroy ( this->recvThreadExitSignal ); semBinaryDestroy ( this->sendThreadFlushSignal ); @@ -617,8 +611,44 @@ bool tcpiiu::connectionInProgress ( const char *pChannelName, const osiSockAddr return true; } -void tcpiiu::show ( unsigned /* level */ ) const +void tcpiiu::show ( unsigned level ) const { + this->lock (); + char buf[256]; + this->ipToA.hostName ( buf, sizeof ( buf ) ); + printf ( "Virtual circuit to \"%s\" at version %u.%u state %u\n", + buf, CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber, + this->state ); + if ( level > 1u ) { + this->netiiu::show ( level - 1u ); + } + if ( level > 2u ) { + printf ( "\tcurrent data cache pointer = %p current data cache size = %u\n", + this->pCurData, this->curDataMax ); + printf ( "\tcontiguous receive message count=%u, busy detect bool=%u, flow control bool=%u\n", + this->contigRecvMsgCount, this->busyStateDetected, this->flowControlActive ); + } + if ( level > 3u ) { + printf ( "\tvirtual circuit socket identifier %d\n", this->sock ); + printf ( "\tsend thread flush signal:\n" ); + semBinaryShow ( this->sendThreadFlushSignal, level-3u ); + printf ( "\trecv thread buffer space available signal:\n" ); + semBinaryShow ( this->recvThreadRingBufferSpaceAvailableSignal, level-3u ); + printf ( "\tsend thread exit signal:\n" ); + semBinaryShow ( this->sendThreadExitSignal, level-3u ); + printf ( "\trecv thread exit signal:\n" ); + semBinaryShow ( this->recvThreadExitSignal, level-3u ); + printf ( "\tfully constructed bool %u\n", this->fullyConstructedFlag ); + printf ("\techo pending bool = %u\n", this->echoRequestPending ); + printf ("\treceive message pending bool = %u\n", this->recvMessagePending ); + printf ("\tflush pending bool = %u\n", this->flushPending ); + printf ("\treceive message header available bool = %u\n", this->msgHeaderAvailable ); + if ( this->pClaimsPendingIIU ) { + this->pClaimsPendingIIU->show ( level - 3u ); + } + this->bhe.show ( level - 3u ); + } + this->unlock (); } void tcpiiu::echoRequest () @@ -632,7 +662,7 @@ void tcpiiu::echoRequest () */ void tcpiiu::echoRequestMsg () { - if ( CA_V43 ( CA_PROTOCOL_VERSION, this->minor_version_number ) ) { + if ( CA_V43 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ) ) { this->comQueSend::echoRequest (); } else { @@ -671,7 +701,7 @@ void tcpiiu::disableFlowControlMsg () */ void tcpiiu::hostNameSetMsg () { - if ( ! CA_V41 ( CA_PROTOCOL_VERSION, this->minor_version_number ) ) { + if ( ! CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ) ) { return; } @@ -683,7 +713,7 @@ void tcpiiu::hostNameSetMsg () */ void tcpiiu::userNameSetMsg () { - if ( ! CA_V41 ( CA_PROTOCOL_VERSION, this->minor_version_number ) ) { + if ( ! CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ) ) { return; } @@ -736,7 +766,7 @@ void tcpiiu::readNotifyRespAction () * read notify status starting * with CA V4.1 */ - v41 = CA_V41 ( CA_PROTOCOL_VERSION, this->minor_version_number ); + v41 = CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ); if (v41) { status = this->curMsg.m_cid; } @@ -789,7 +819,7 @@ void tcpiiu::eventRespAction () * read notify status starting * with CA V4.1 */ - v41 = CA_V41 ( CA_PROTOCOL_VERSION, this->minor_version_number ); + v41 = CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ); if (v41) { status = this->curMsg.m_cid; } @@ -1065,8 +1095,8 @@ void tcpiiu::processIncomingAndDestroySelfIfDisconnected () if ( this->state == iiu_disconnected ) { this->suicide (); } - else if ( this->recvPending ) { - this->recvPending = false; + else if ( this->recvMessagePending ) { + this->recvMessagePending = false; this->postMsg (); } } diff --git a/src/ca/tcpiiu_IL.h b/src/ca/tcpiiu_IL.h index 92f976eed..55117a17b 100644 --- a/src/ca/tcpiiu_IL.h +++ b/src/ca/tcpiiu_IL.h @@ -62,17 +62,17 @@ inline void tcpiiu::flush () inline bool tcpiiu::ca_v44_ok () const { - return CA_V44 ( CA_PROTOCOL_VERSION, this->minor_version_number ); + return CA_V44 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ); } inline bool tcpiiu::ca_v42_ok () const { - return CA_V42 ( CA_PROTOCOL_VERSION, this->minor_version_number ); + return CA_V42 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ); } inline bool tcpiiu::ca_v41_ok () const { - return CA_V41 ( CA_PROTOCOL_VERSION, this->minor_version_number ); + return CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersionNumber ); } inline bool tcpiiu::alive () const diff --git a/src/ca/udpiiu.cpp b/src/ca/udpiiu.cpp index 3b6a39640..f427ef2af 100644 --- a/src/ca/udpiiu.cpp +++ b/src/ca/udpiiu.cpp @@ -822,4 +822,25 @@ SOCKET udpiiu::getSock () const return this->sock; } +void udpiiu::show ( unsigned level ) const +{ + this->lock (); + printf ( "Datagram IO circuit (and disconnected channel repository)\n"); + if ( level > 1u ) { + this->netiiu::show ( level - 1u ); + } + if ( level > 2u ) { + printf ("\trepeater port %u\n", this->repeaterPort ); + printf ("\tdefault server port %u\n", this->serverPort ); + printChannelAccessAddressList ( &this->dest ); + } + if ( level > 3u ) { + printf ("\tsocket identifier %d\n", this->sock ); + printf ("\tbytes in xmit buffer %u\n", this->nBytesInXmitBuf ); + printf ("\tshut down command bool %u\n", this->shutdownCmd ); + printf ( "\trecv thread exit signal:\n" ); + semBinaryShow ( this->recvThreadExitSignal, level-3u ); + } + this->unlock (); +}