diff --git a/src/ca/CASG.cpp b/src/ca/CASG.cpp index af3625a2d..5578c32bb 100644 --- a/src/ca/CASG.cpp +++ b/src/ca/CASG.cpp @@ -27,14 +27,18 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "syncGroup.h" #include "oldAccess.h" #include "autoPtrDestroy.h" +#include "cac.h" tsFreeList < struct CASG, 128 > CASG::freeList; epicsMutex CASG::freeListMutex; -CASG::CASG ( cac &cacIn ) : +CASG::CASG ( oldCAC &cacIn ) : client ( cacIn ), magic ( CASG_MAGIC ) { client.installCASG ( *this ); @@ -53,7 +57,7 @@ CASG::~CASG () this->magic = 0; } else { - ca_printf ("cac: attempt to destroy invalid sync group ignored\n"); + this->printf ("cac: attempt to destroy invalid sync group ignored\n"); } } @@ -132,7 +136,7 @@ void CASG::reset () void CASG::show ( unsigned level ) const { - printf ( "Sync Group: id=%u, magic=%u, opPend=%u\n", + ::printf ( "Sync Group: id=%u, magic=%u, opPend=%u\n", this->getId (), this->magic, this->ioList.count () ); if ( level ) { epicsAutoMutex locker ( this->mutex ); @@ -282,3 +286,18 @@ void CASG::operator delete (void *pCadaver, size_t size) CASG::freeList.release ( pCadaver, size ); } +int CASG::printf ( const char *pformat, ... ) +{ + va_list theArgs; + int status; + + va_start ( theArgs, pformat ); + + status = this->client.vPrintf ( pformat, theArgs ); + + va_end ( theArgs ); + + return status; +} + + diff --git a/src/ca/Makefile b/src/ca/Makefile index efc4f8e5a..ef96e0296 100644 --- a/src/ca/Makefile +++ b/src/ca/Makefile @@ -17,7 +17,9 @@ INC += cacIO.h LIBSRCS += cacChannel.cpp LIBSRCS += cacChannelNotify.cpp LIBSRCS += cacNotify.cpp -LIBSRCS += cacDataNotify.cpp +LIBSRCS += cacReadNotify.cpp +LIBSRCS += cacWriteNotify.cpp +LIBSRCS += cacStateNotify.cpp LIBSRCS += cacServiceList.cpp LIBSRCS += access.cpp LIBSRCS += recvProcessThread.cpp @@ -39,6 +41,7 @@ LIBSRCS += cac.cpp LIBSRCS += tcpSendWatchdog.cpp LIBSRCS += tcpRecvWatchdog.cpp LIBSRCS += bhe.cpp +LIBSRCS += oldCAC.cpp LIBSRCS += oldChannelNotify.cpp LIBSRCS += oldSubscription.cpp LIBSRCS += getCallback.cpp diff --git a/src/ca/access.cpp b/src/ca/access.cpp index 2981f2b36..9d43f2058 100644 --- a/src/ca/access.cpp +++ b/src/ca/access.cpp @@ -12,6 +12,9 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + + /* * allocate error message string array * here so I can use sizeof @@ -25,8 +28,6 @@ #include "iocinf.h" #include "oldAccess.h" -#include "cac_IL.h" -#include "baseNMIU_IL.h" #include "autoPtrDestroy.h" epicsThreadPrivateId caClientContextId; @@ -53,7 +54,7 @@ extern "C" void ca_init_client_context ( void * ) /* * fetchClientContext (); */ -int fetchClientContext ( cac **ppcac ) +int fetchClientContext ( oldCAC **ppcac ) { if ( caClientContextId == 0 ) { epicsThreadOnce ( &caClientContextIdOnce, ca_init_client_context, 0 ); @@ -63,14 +64,14 @@ int fetchClientContext ( cac **ppcac ) } int status; - *ppcac = ( cac * ) epicsThreadPrivateGet ( caClientContextId ); + *ppcac = ( oldCAC * ) epicsThreadPrivateGet ( caClientContextId ); if ( *ppcac ) { status = ECA_NORMAL; } else { status = ca_task_initialize (); if ( status == ECA_NORMAL ) { - *ppcac = (cac *) epicsThreadPrivateGet ( caClientContextId ); + *ppcac = (oldCAC *) epicsThreadPrivateGet ( caClientContextId ); if ( ! *ppcac ) { status = ECA_INTERNAL; } @@ -114,9 +115,9 @@ extern "C" int epicsShareAPI ca_task_initialize ( void ) return ca_context_create ( false ); } -extern "C" epicsShareFunc int epicsShareAPI ca_context_create ( int preemptiveCallBackEnable ) +extern "C" int epicsShareAPI ca_context_create ( int preemptiveCallBackEnable ) { - cac *pcac; + oldCAC *pcac; epicsThreadOnce ( &caClientContextIdOnce, ca_init_client_context, 0); @@ -124,12 +125,12 @@ extern "C" epicsShareFunc int epicsShareAPI ca_context_create ( int preemptiveCa return ECA_ALLOCMEM; } - pcac = (cac *) epicsThreadPrivateGet ( caClientContextId ); + pcac = (oldCAC *) epicsThreadPrivateGet ( caClientContextId ); if ( pcac ) { return ECA_NORMAL; } - pcac = new cac ( preemptiveCallBackEnable ? true : false ); + pcac = new oldCAC ( preemptiveCallBackEnable ? true : false ); if ( ! pcac ) { return ECA_ALLOCMEM; } @@ -142,9 +143,9 @@ extern "C" epicsShareFunc int epicsShareAPI ca_context_create ( int preemptiveCa // // ca_register_service () // -epicsShareFunc int epicsShareAPI ca_register_service ( cacService *pService ) +int epicsShareAPI ca_register_service ( cacService *pService ) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -178,12 +179,12 @@ extern "C" int epicsShareAPI ca_modify_user_name ( const char * ) // // ca_context_destroy () // -extern "C" epicsShareFunc int epicsShareAPI ca_context_destroy () +extern "C" int epicsShareAPI ca_context_destroy () { - cac *pcac; + oldCAC *pcac; if ( caClientContextId != NULL ) { - pcac = (cac *) epicsThreadPrivateGet ( caClientContextId ); + pcac = (oldCAC *) epicsThreadPrivateGet ( caClientContextId ); if ( pcac ) { delete pcac; epicsThreadPrivateSet ( caClientContextId, 0 ); @@ -198,7 +199,7 @@ extern "C" epicsShareFunc int epicsShareAPI ca_context_destroy () * * releases all resources alloc to a channel access client */ -extern "C" epicsShareFunc int epicsShareAPI ca_task_exit () +extern "C" int epicsShareAPI ca_task_exit () { return ca_context_destroy (); } @@ -227,7 +228,7 @@ extern "C" int epicsShareAPI ca_search_and_connect ( const char *name_str, chid *chanptr, caCh *conn_func, void *puser ) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -270,7 +271,7 @@ extern "C" int epicsShareAPI ca_clear_channel ( chid pChan ) extern "C" int epicsShareAPI ca_array_get ( chtype type, unsigned long count, chid pChan, void *pValue ) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -510,7 +511,7 @@ extern "C" int epicsShareAPI ca_replace_access_rights_event ( chid pChan, caArh */ extern "C" int epicsShareAPI ca_add_exception_event ( caExceptionHandler *pfunc, void *arg ) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -628,7 +629,7 @@ extern "C" chid epicsShareAPI ca_evid_to_chid ( evid pMon ) */ extern "C" int epicsShareAPI ca_pend_event (ca_real timeout) { - cac *pcac; + oldCAC *pcac; int status = fetchClientContext ( &pcac ); if ( status != ECA_NORMAL ) { return status; @@ -642,7 +643,7 @@ extern "C" int epicsShareAPI ca_pend_event (ca_real timeout) */ extern "C" int epicsShareAPI ca_pend_io (ca_real timeout) { - cac *pcac; + oldCAC *pcac; int status = fetchClientContext ( &pcac ); if ( status != ECA_NORMAL ) { return status; @@ -656,7 +657,7 @@ extern "C" int epicsShareAPI ca_pend_io (ca_real timeout) */ extern "C" int epicsShareAPI ca_flush_io () { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -672,7 +673,7 @@ extern "C" int epicsShareAPI ca_flush_io () */ extern "C" int epicsShareAPI ca_test_io () { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -730,7 +731,7 @@ extern "C" void epicsShareAPI ca_signal_with_file_and_lineno ( long ca_status, extern "C" void epicsShareAPI ca_signal_formated ( long ca_status, const char *pfilenm, int lineno, const char *pFormat, ... ) { - cac *pcac; + oldCAC *pcac; va_list theArgs; static const char *severity[] = { @@ -745,7 +746,7 @@ extern "C" void epicsShareAPI ca_signal_formated ( long ca_status, const char *p }; if ( caClientContextId ) { - pcac = (cac *) epicsThreadPrivateGet ( caClientContextId ); + pcac = (oldCAC *) epicsThreadPrivateGet ( caClientContextId ); } else { pcac = NULL; @@ -794,7 +795,7 @@ extern "C" void epicsShareAPI ca_signal_formated ( long ca_status, const char *p */ extern "C" int epicsShareAPI ca_add_fd_registration (CAFDHANDLER *func, void *arg) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -843,7 +844,7 @@ extern "C" const char * epicsShareAPI ca_version () */ extern "C" int epicsShareAPI ca_replace_printf_handler ( caPrintfFunc *ca_printf_func ) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -854,43 +855,6 @@ extern "C" int epicsShareAPI ca_replace_printf_handler ( caPrintfFunc *ca_printf return ECA_NORMAL; } -/* - * ca_printf() - */ -int ca_printf ( const char *pformat, ... ) -{ - va_list theArgs; - int status; - - va_start ( theArgs, pformat ); - - status = ca_vPrintf ( pformat, theArgs ); - - va_end ( theArgs ); - - return status; -} - -/* - * ca_vPrintf() - */ -int ca_vPrintf ( const char *pformat, va_list args ) -{ - if ( caClientContextId ) { - cac *pcac = (cac *) epicsThreadPrivateGet ( caClientContextId ); - if ( pcac ) { - return pcac->vPrintf ( pformat, args ); - } - else { - return errlogVprintf ( pformat, args ); - } - } - else { - return errlogVprintf ( pformat, args ); - } -} - - /* * ca_field_type() */ @@ -910,7 +874,7 @@ extern "C" unsigned long epicsShareAPI ca_element_count ( chid pChan ) /* * ca_state () */ -extern "C" epicsShareFunc enum channel_state epicsShareAPI ca_state ( chid pChan ) +extern "C" enum channel_state epicsShareAPI ca_state ( chid pChan ) { if ( pChan->connected() ) { return cs_conn; @@ -926,7 +890,7 @@ extern "C" epicsShareFunc enum channel_state epicsShareAPI ca_state ( chid pChan /* * ca_set_puser () */ -extern "C" epicsShareFunc void epicsShareAPI ca_set_puser ( chid pChan, void *puser ) +extern "C" void epicsShareAPI ca_set_puser ( chid pChan, void *puser ) { pChan->setPrivatePointer ( puser ); } @@ -934,7 +898,7 @@ extern "C" epicsShareFunc void epicsShareAPI ca_set_puser ( chid pChan, void *pu /* * ca_get_puser () */ -extern "C" epicsShareFunc void * epicsShareAPI ca_puser ( chid pChan ) +extern "C" void * epicsShareAPI ca_puser ( chid pChan ) { return pChan->privatePointer (); } @@ -942,7 +906,7 @@ extern "C" epicsShareFunc void * epicsShareAPI ca_puser ( chid pChan ) /* * ca_read_access () */ -extern "C" epicsShareFunc unsigned epicsShareAPI ca_read_access ( chid pChan ) +extern "C" unsigned epicsShareAPI ca_read_access ( chid pChan ) { return pChan->accessRights().readPermit(); } @@ -950,7 +914,7 @@ extern "C" epicsShareFunc unsigned epicsShareAPI ca_read_access ( chid pChan ) /* * ca_write_access () */ -extern "C" epicsShareFunc unsigned epicsShareAPI ca_write_access ( chid pChan ) +extern "C" unsigned epicsShareAPI ca_write_access ( chid pChan ) { return pChan->accessRights().writePermit(); } @@ -958,17 +922,17 @@ extern "C" epicsShareFunc unsigned epicsShareAPI ca_write_access ( chid pChan ) /* * ca_name () */ -extern "C" epicsShareFunc const char * epicsShareAPI ca_name ( chid pChan ) +extern "C" const char * epicsShareAPI ca_name ( chid pChan ) { return pChan->pName (); } -extern "C" epicsShareFunc unsigned epicsShareAPI ca_search_attempts ( chid pChan ) +extern "C" unsigned epicsShareAPI ca_search_attempts ( chid pChan ) { return pChan->searchAttempts (); } -extern "C" epicsShareFunc double epicsShareAPI ca_beacon_period ( chid pChan ) +extern "C" double epicsShareAPI ca_beacon_period ( chid pChan ) { return pChan->beaconPeriod (); } @@ -981,7 +945,7 @@ extern "C" epicsShareFunc double epicsShareAPI ca_beacon_period ( chid pChan ) */ extern "C" unsigned epicsShareAPI ca_get_ioc_connection_count () { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -990,16 +954,16 @@ extern "C" unsigned epicsShareAPI ca_get_ioc_connection_count () return pcac->connectionCount (); } -extern "C" epicsShareFunc int epicsShareAPI ca_channel_status ( epicsThreadId /* tid */ ) +extern "C" int epicsShareAPI ca_channel_status ( epicsThreadId /* 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"); + ::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; } -extern "C" epicsShareFunc int epicsShareAPI ca_client_status ( unsigned level ) +extern "C" int epicsShareAPI ca_client_status ( unsigned level ) { - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; @@ -1015,7 +979,7 @@ extern "C" epicsShareFunc int epicsShareAPI ca_client_status ( unsigned level ) * used when an auxillary thread needs to join a CA client context started * by another thread */ -extern "C" epicsShareFunc int epicsShareAPI ca_current_context ( caClientCtx *pCurrentContext ) +extern "C" int epicsShareAPI ca_current_context ( caClientCtx *pCurrentContext ) { if ( caClientContextId ) { void *pCtx = epicsThreadPrivateGet ( caClientContextId ); @@ -1038,11 +1002,11 @@ extern "C" epicsShareFunc int epicsShareAPI ca_current_context ( caClientCtx *pC * used when an auxillary thread needs to join a CA client context started * by another thread */ -extern "C" epicsShareFunc int epicsShareAPI ca_attach_context ( caClientCtx context ) +extern "C" int epicsShareAPI ca_attach_context ( caClientCtx context ) { - cac *pcac; + oldCAC *pcac; - pcac = (cac *) epicsThreadPrivateGet ( caClientContextId ); + pcac = (oldCAC *) epicsThreadPrivateGet ( caClientContextId ); if ( pcac && context != 0 ) { return ECA_ISATTACHED; } diff --git a/src/ca/acctst.c b/src/ca/acctst.c index f8689845b..9ead2aef6 100644 --- a/src/ca/acctst.c +++ b/src/ca/acctst.c @@ -15,16 +15,12 @@ /* * EPICS */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #include "epicsAssert.h" #include "epicsTime.h" #include "envDefs.h" - -/* - * CA - */ -#include "cadef.h" - #include "caDiagnostics.h" +#include "cadef.h" #ifndef min #define min(A,B) ((A)>(B)?(B):(A)) diff --git a/src/ca/addrList.h b/src/ca/addrList.h index 69eb47098..2cf3d6993 100644 --- a/src/ca/addrList.h +++ b/src/ca/addrList.h @@ -1,5 +1,8 @@ +#ifndef addrListh +#define addrListh +#include "shareLib.h" #include "envDefs.h" #ifdef __cplusplus @@ -22,3 +25,4 @@ epicsShareFunc void epicsShareAPI removeDuplicatesAddresses } #endif +#endif addrListh // ifndef addrListh diff --git a/src/ca/autoPtrRecycle_IL.h b/src/ca/autoPtrRecycle.h similarity index 76% rename from src/ca/autoPtrRecycle_IL.h rename to src/ca/autoPtrRecycle.h index 3078f6c98..0f4bf100a 100644 --- a/src/ca/autoPtrRecycle_IL.h +++ b/src/ca/autoPtrRecycle.h @@ -15,8 +15,22 @@ * 505 665 1831 */ -#ifndef autoPtrRecycleILh -#define autoPtrRecycleILh +#ifndef autoPtrRecycleh +#define autoPtrRecycleh + +template < class T > +class autoPtrRecycle { +public: + autoPtrRecycle ( cacRecycle &, T * ); + ~autoPtrRecycle (); + T & operator * () const; + T * operator -> () const; + T * get () const; + T * release (); +private: + T *p; + cacRecycle &r; +}; template < class T > inline autoPtrRecycle::autoPtrRecycle ( cacRecycle &rIn, T *pIn ) : @@ -57,4 +71,4 @@ inline T * autoPtrRecycle::release () return pTmp; } -#endif // #ifdef autoPtrRecycleILh +#endif // #ifdef autoPtrRecycleh diff --git a/src/ca/baseNMIU.cpp b/src/ca/baseNMIU.cpp index c0b2dd9ee..0c6ad4248 100644 --- a/src/ca/baseNMIU.cpp +++ b/src/ca/baseNMIU.cpp @@ -10,9 +10,11 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "nciu_IL.h" -#include "baseNMIU_IL.h" +#include "nciu.h" +#include "netIO.h" baseNMIU::baseNMIU ( nciu &chanIn ) : chan ( chanIn ) @@ -30,7 +32,7 @@ class netSubscription * baseNMIU::isSubscription () void baseNMIU::show ( unsigned /* level */ ) const { - printf ( "CA IO primitive at %p\n", + ::printf ( "CA IO primitive at %p\n", static_cast ( this ) ); } diff --git a/src/ca/bhe.cpp b/src/ca/bhe.cpp index 860c3b3f6..99925b39b 100644 --- a/src/ca/bhe.cpp +++ b/src/ca/bhe.cpp @@ -10,9 +10,14 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "bhe_IL.h" -#include "tcpiiu_IL.h" +#include "virtualCircuit.h" + +#define epicsExportSharedSymbols +#include "bhe.h" +#undef epicsExportSharedSymbols tsFreeList < class bhe, 1024 > bhe::freeList; epicsMutex bhe::freeListMutex; @@ -66,7 +71,7 @@ bool bhe::updatePeriod ( epicsTime programBeginTime ) */ currentPeriod = current - this->timeStamp; if ( this->averagePeriod < 0.0 ) { - ca_real totalRunningTime; + double totalRunningTime; if ( this->piiu ) { this->piiu->beaconAnomalyNotify (); @@ -160,10 +165,10 @@ bool bhe::updatePeriod ( epicsTime programBeginTime ) void bhe::show ( unsigned level ) const { - printf ( "CA beacon hash entry at %p with average period %f\n", + ::printf ( "CA beacon hash entry at %p with average period %f\n", static_cast ( this ), this->averagePeriod ); if ( level > 0u ) { - printf ( "network IO pointer %p\n", + ::printf ( "network IO pointer %p\n", static_cast ( this->piiu ) ); } } diff --git a/src/ca/bhe.h b/src/ca/bhe.h new file mode 100644 index 000000000..b1f034851 --- /dev/null +++ b/src/ca/bhe.h @@ -0,0 +1,100 @@ + +/* + * $Id$ + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * Author: Jeff Hill + */ + +#ifndef bheh +#define bheh + +#include "shareLib.h" + +#include + +#ifdef epicsExportSharedSymbols +# define bhehEpicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +#include "tsSLList.h" +#include "tsFreeList.h" +#include "epicsTime.h" + +#ifdef bhehEpicsExportSharedSymbols +# define epicsExportSharedSymbols +#endif + +#include "inetAddrID.h" + +class tcpiiu; + +class bhe : public tsSLNode < bhe >, public inetAddrID { +public: + epicsShareFunc bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr ); + tcpiiu *getIIU () const; + void bindToIIU ( tcpiiu & ); + epicsShareFunc void destroy (); + epicsShareFunc bool updatePeriod ( epicsTime programBeginTime ); + epicsShareFunc double period () const; + epicsShareFunc void show ( unsigned level) const; + epicsShareFunc void * operator new ( size_t size ); + epicsShareFunc void operator delete ( void *pCadaver, size_t size ); +protected: + epicsShareFunc ~bhe (); // force allocation from freeList +private: + tcpiiu *piiu; + epicsTime timeStamp; + double averagePeriod; + static tsFreeList < class bhe, 1024 > freeList; + static epicsMutex freeListMutex; +}; + +/* + * set average to -1.0 so that when the next beacon + * occurs we can distinguish between: + * o new server + * o existing server's beacon we are seeing + * for the first time shortly after program + * start up + * + * if creating this in response to a search reply + * and not in response to a beacon then + * we set the beacon time stamp to + * zero (so we can correctly compute the period + * between the 1st and 2nd beacons) + */ +inline bhe::bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr ) : + inetAddrID (addr), piiu (0), timeStamp (initialTimeStamp), averagePeriod ( - DBL_MAX ) +{ +# ifdef DEBUG + { + char name[64]; + ipAddrToDottedIP (&addr, name, sizeof(name)); + ::printf ("created beacon entry for %s\n", name); + } +# endif +} + +inline tcpiiu *bhe::getIIU ()const +{ + return this->piiu; +} + +inline void bhe::bindToIIU ( tcpiiu &iiuIn ) +{ + if ( this->piiu != &iiuIn ) { + assert ( this->piiu == 0 ); + this->piiu = &iiuIn; + } +} + +#endif // ifdef bheh + + diff --git a/src/ca/bhe_IL.h b/src/ca/bhe_IL.h deleted file mode 100644 index 5fbdde035..000000000 --- a/src/ca/bhe_IL.h +++ /dev/null @@ -1,54 +0,0 @@ - -/* - * $Id$ - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * Author: Jeff Hill - */ - -#include - -/* - * set average to -1.0 so that when the next beacon - * occurs we can distinguish between: - * o new server - * o existing server's beacon we are seeing - * for the first time shortly after program - * start up - * - * if creating this in response to a search reply - * and not in response to a beacon then - * we set the beacon time stamp to - * zero (so we can correctly compute the period - * between the 1st and 2nd beacons) - */ -inline bhe::bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr ) : - inetAddrID (addr), piiu (0), timeStamp (initialTimeStamp), averagePeriod ( - DBL_MAX ) -{ -# ifdef DEBUG - { - char name[64]; - ipAddrToDottedIP (&addr, name, sizeof(name)); - printf ("created beacon entry for %s\n", name); - } -# endif -} - -inline tcpiiu *bhe::getIIU ()const -{ - return this->piiu; -} - -inline void bhe::bindToIIU ( tcpiiu &iiuIn ) -{ - if ( this->piiu != &iiuIn ) { - assert ( this->piiu == 0 ); - this->piiu = &iiuIn; - } -} - diff --git a/src/ca/caConnTest.cpp b/src/ca/caConnTest.cpp index 8d9a4b5a3..2771fa83e 100644 --- a/src/ca/caConnTest.cpp +++ b/src/ca/caConnTest.cpp @@ -2,8 +2,9 @@ #include #include +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "cadef.h" -#include "epicsAssert.h" #include "epicsTime.h" static unsigned channelCount = 0u; diff --git a/src/ca/caEventRate.cpp b/src/ca/caEventRate.cpp index b0d4487c0..b6924bcaa 100644 --- a/src/ca/caEventRate.cpp +++ b/src/ca/caEventRate.cpp @@ -1,7 +1,4 @@ - -#include "cadef.h" - #include #include diff --git a/src/ca/caRepeater.cpp b/src/ca/caRepeater.cpp index 82364a12f..794adb24c 100644 --- a/src/ca/caRepeater.cpp +++ b/src/ca/caRepeater.cpp @@ -21,15 +21,15 @@ * */ -#include "epicsAssert.h" -#include "shareLib.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -epicsShareFunc void epicsShareAPI ca_repeater (void); +#include "epicsAssert.h" +#include "udpiiu.h" int main() { ca_repeater (); - assert (0); - return (0); + assert ( 0 ); + return ( 0 ); } diff --git a/src/ca/cac.cpp b/src/ca/cac.cpp index e2eacd237..dd1821961 100644 --- a/src/ca/cac.cpp +++ b/src/ca/cac.cpp @@ -10,25 +10,29 @@ * Author: Jeff Hill */ -#include "epicsMemory.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" +#include "epicsMemory.h" #include "osiProcess.h" #include "osiSigPipeIgnore.h" +#include "envdefs.h" #include "iocinf.h" -#include "cac_IL.h" -#include "inetAddrID_IL.h" -#include "bhe_IL.h" -#include "tcpiiu_IL.h" -#include "nciu_IL.h" -#include "comQueSend_IL.h" -#include "recvProcessThread_IL.h" -#include "netiiu_IL.h" -#include "baseNMIU_IL.h" -#include "netWriteNotifyIO_IL.h" -#include "netReadNotifyIO_IL.h" -#include "netSubscription_IL.h" -#include "autoPtrRecycle_IL.h" +#include "cac.h" +#include "inetAddrID.h" +#include "virtualCircuit.h" +#include "netIO.h" +#include "syncGroup.h" +#include "nciu.h" +#include "autoPtrRecycle.h" +#include "searchTimer.h" +#include "repeaterSubscribeTimer.h" + +#define epicsExportSharedSymbols +#include "udpiiu.h" +#include "bhe.h" +#include "net_convert.h" +#undef epicsExportSharedSymbols // TCP protocol jump table const cac::pProtoStubTCP cac::tcpJumpTableCAC [] = @@ -66,17 +70,16 @@ const cac::pProtoStubTCP cac::tcpJumpTableCAC [] = // // cac::cac () // -cac::cac ( bool enablePreemptiveCallbackIn ) : +cac::cac ( cacNotify ¬ifyIn, bool enablePreemptiveCallbackIn ) : ipToAEngine ( "caIPAddrToAsciiEngine" ), chanTable ( 1024 ), ioTable ( 1024 ), sgTable ( 128 ), beaconTable ( 1024 ), - fdRegFunc ( 0 ), - fdRegArg ( 0 ), pudpiiu ( 0 ), pSearchTmr ( 0 ), pRepeaterSubscribeTmr ( 0 ), + notify ( notifyIn ), ioNotifyInProgressId ( 0 ), initializingThreadsPriority ( epicsThreadGetPrioritySelf () ), threadsBlockingOnNotifyCompletion ( 0u ), @@ -99,10 +102,6 @@ cac::cac ( bool enablePreemptiveCallbackIn ) : } } - this->pVPrintfFunc = errlogVprintf; - this->ca_exception_func = ca_default_exception_handler; - this->ca_exception_arg = NULL; - installSigPipeIgnore (); { @@ -127,8 +126,8 @@ cac::cac ( bool enablePreemptiveCallbackIn ) : status = envGetDoubleConfigParam ( &EPICS_CA_CONN_TMO, &this->connTMO ); if ( status ) { this->connTMO = CA_CONN_VERIFY_PERIOD; - ca_printf ( "EPICS \"%s\" double fetch failed\n", EPICS_CA_CONN_TMO.name); - ca_printf ( "Defaulting \"%s\" = %f\n", EPICS_CA_CONN_TMO.name, this->connTMO); + this->printf ( "EPICS \"%s\" double fetch failed\n", EPICS_CA_CONN_TMO.name); + this->printf ( "Defaulting \"%s\" = %f\n", EPICS_CA_CONN_TMO.name, this->connTMO); } this->pTimerQueue = & epicsTimerQueueActive::allocate ( false, abovePriority ); @@ -209,8 +208,8 @@ cac::~cac () } } - if ( ! this->enablePreemptiveCallback && this->fdRegFunc ) { - this->pudpiiu->fdDestroyNotify ( this->fdRegFunc, this->fdRegArg ); + if ( ! this->enablePreemptiveCallback ) { + this->notify.fdWasDestroyed ( this->pudpiiu->getSock() ); } delete this->pudpiiu; delete this->pUserName; @@ -231,56 +230,62 @@ cac::~cac () void cac::processRecvBacklog () { - epicsAutoMutex autoMutex ( this->mutex ); + tsDLList < tcpiiu > deadIIU; + { + epicsAutoMutex autoMutex ( this->mutex ); - tsDLIterBD < tcpiiu > piiu = this->iiuList.firstIter (); - while ( piiu.valid () ) { - tsDLIterBD < tcpiiu > pNext = piiu; - pNext++; + tsDLIterBD < tcpiiu > piiu = this->iiuList.firstIter (); + while ( piiu.valid () ) { + tsDLIterBD < tcpiiu > pNext = piiu; + pNext++; - if ( ! piiu->alive () ) { - assert ( this->pudpiiu && this->pSearchTmr ); + if ( ! piiu->alive () ) { + assert ( this->pudpiiu && this->pSearchTmr ); - bhe *pBHE = piiu->getBHE (); - if ( pBHE ) { - this->beaconTable.remove ( *pBHE ); - pBHE->destroy (); + bhe *pBHE = piiu->getBHE (); + if ( pBHE ) { + this->beaconTable.remove ( *pBHE ); + pBHE->destroy (); + } + + if ( piiu->channelCount () ) { + char hostNameTmp[64]; + piiu->hostName ( hostNameTmp, sizeof ( hostNameTmp ) ); + genLocalExcep ( *this, ECA_DISCONN, hostNameTmp ); + } + + piiu->disconnectAllChan ( *this->pudpiiu ); + + // make certain that: + // 1) this is called from the appropriate thread + // 2) lock is not held while in call back + if ( ! this->enablePreemptiveCallback ) { + epicsAutoMutexRelease autoRelease ( this->mutex ); + this->notify.fdWasDestroyed ( piiu->getSock() ); + } + this->iiuList.remove ( *piiu ); + deadIIU.add ( *piiu ); // postpone destroy and avoid deadlock + } + else { + // make certain that: + // 1) this is called from the appropriate thread + // 2) lock is not held while in call back + if ( piiu->trueOnceOnly() && ! this->enablePreemptiveCallback ) { + epicsAutoMutexRelease autoRelease ( this->mutex ); + this->notify.fdWasCreated ( piiu->getSock() ); + } + piiu->processIncoming (); } - if ( piiu->channelCount () ) { - char hostNameTmp[64]; - piiu->hostName ( hostNameTmp, sizeof ( hostNameTmp ) ); - genLocalExcep ( *this, ECA_DISCONN, hostNameTmp ); - } - - piiu->disconnectAllChan ( *this->pudpiiu ); - - // make certain that: - // 1) this is called from the appropriate thread - // 2) lock is not held while in call back - if ( ! this->enablePreemptiveCallback && this->fdRegFunc ) { - CAFDHANDLER *func = this->fdRegFunc; - void *arg = this->fdRegArg; - epicsAutoMutexRelease autoRelease ( mutex ); - piiu->fdDestroyNotify ( func, arg ); - } - this->iiuList.remove ( *piiu ); + piiu = pNext; + } + } + if ( deadIIU.count() ) { + this->pSearchTmr->resetPeriod ( CA_RECAST_DELAY ); + while ( tcpiiu *piiu = deadIIU.get() ) { piiu->destroy (); - - this->pSearchTmr->resetPeriod ( CA_RECAST_DELAY ); } - else { - // make certain that: - // 1) this is called from the appropriate thread - // 2) lock is not held while in call back - if ( ! this->enablePreemptiveCallback && this->fdRegFunc ) { - piiu->fdCreateNotify ( this->mutex, this->fdRegFunc, this->fdRegArg ); - } - piiu->processIncoming (); - } - - piiu = pNext; - } + } } // @@ -571,20 +576,6 @@ CASG * cac::lookupCASG ( unsigned id ) return psg; } -void cac::exception ( int status, const char *pContext, - const char *pFileName, unsigned lineNo ) -{ - ca_signal_with_file_and_lineno ( status, pContext, pFileName, lineNo ); -} - -void cac::exception ( int status, const char *pContext, - unsigned type, unsigned long count, - const char *pFileName, unsigned lineNo ) -{ - ca_signal_formated ( status, pFileName, lineNo, "%s type=%d count=%ld\n", - pContext, type, count ); -} - void cac::registerService ( cacService &service ) { this->services.registerService ( service ); @@ -634,11 +625,9 @@ bool cac::setupUDP () if ( ! this->pudpiiu ) { return false; } - if ( ! this->enablePreemptiveCallback && this->fdRegFunc ) { - CAFDHANDLER *func = this->fdRegFunc; - void *arg = this->fdRegArg; + if ( ! this->enablePreemptiveCallback ) { epicsAutoMutexRelease autoRelease ( this->mutex ); - this->pudpiiu->fdCreateNotify ( func, arg ); + this->notify.fdWasCreated ( this->pudpiiu->getSock() ); } } @@ -659,13 +648,6 @@ bool cac::setupUDP () return true; } -void cac::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg ) -{ - epicsAutoMutex autoMutex ( this->mutex ); - this->fdRegFunc = pFunc; - this->fdRegArg = pArg; -} - void cac::enableCallbackPreemption () { if ( this->pRecvProcThread ) { @@ -680,52 +662,6 @@ void cac::disableCallbackPreemption () } } -void cac::changeExceptionEvent ( caExceptionHandler *pfunc, void *arg ) -{ - epicsAutoMutex autoMutex ( this->mutex ); - if ( pfunc ) { - this->ca_exception_func = pfunc; - this->ca_exception_arg = arg; - } - else { - this->ca_exception_func = ca_default_exception_handler; - this->ca_exception_arg = NULL; - } -} - -// -// cac::genLocalExcepWFL () -// (generate local exception with file and line number) -// -void cac::genLocalExcepWFL (long stat, const char *ctx, const char *pFile, unsigned lineNo) -{ - struct exception_handler_args args; - caExceptionHandler *pExceptionFunc; - - /* - * NOOP if they disable exceptions - */ - if ( this->ca_exception_func ) { - args.chid = NULL; - args.type = -1; - args.count = 0u; - args.addr = NULL; - args.stat = stat; - args.op = CA_OP_OTHER; - args.ctx = ctx; - args.pFile = pFile; - args.lineNo = lineNo; - - { - epicsAutoMutex autoMutex ( this->mutex ); - pExceptionFunc = this->ca_exception_func; - args.usr = this->ca_exception_arg; - } - - (*pExceptionFunc) (args); - } -} - void cac::repeaterSubscribeConfirmNotify () { if ( this->pRepeaterSubscribeTmr ) { @@ -733,17 +669,6 @@ void cac::repeaterSubscribeConfirmNotify () } } -void cac::replaceErrLogHandler ( caPrintfFunc *ca_printf_func ) -{ - epicsAutoMutex autoMutex ( this->mutex ); - if ( ca_printf_func ) { - this->pVPrintfFunc = ca_printf_func; - } - else { - this->pVPrintfFunc = epicsVprintf; - } -} - bool cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, unsigned typeCode, unsigned long count, unsigned minorVersionNumber, const osiSockAddr &addr ) @@ -771,7 +696,7 @@ bool cac::lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, /* * Ignore duplicate search replies */ - if ( chan->isAttachedToVirtaulCircuit ( addr ) ) { + if ( chan->getPIIU()->isVirtaulCircuit( chan->pName(), addr ) ) { return true; } @@ -906,7 +831,7 @@ void cac::writeRequest ( nciu &chan, unsigned type, unsigned nElem, const void * } cacChannel::ioid cac::writeNotifyRequest ( nciu &chan, unsigned type, unsigned nElem, - const void *pValue, cacNotify ¬ify ) + const void *pValue, cacWriteNotify ¬ify ) { epicsAutoMutex autoMutex ( this->mutex ); autoPtrRecycle < netWriteNotifyIO > pIO ( *this, netWriteNotifyIO::factory ( @@ -924,7 +849,7 @@ cacChannel::ioid cac::writeNotifyRequest ( nciu &chan, unsigned type, unsigned n } } -cacChannel::ioid cac::readNotifyRequest ( nciu &chan, unsigned type, unsigned nElem, cacDataNotify ¬ify ) +cacChannel::ioid cac::readNotifyRequest ( nciu &chan, unsigned type, unsigned nElem, cacReadNotify ¬ify ) { epicsAutoMutex autoMutex ( this->mutex ); autoPtrRecycle < netReadNotifyIO > pIO ( *this, netReadNotifyIO::factory ( @@ -1228,7 +1153,7 @@ void cac::recycleSubscription ( netSubscription &io ) } cacChannel::ioid cac::subscriptionRequest ( nciu &chan, unsigned type, - unsigned long nElem, unsigned mask, cacDataNotify ¬ify ) + unsigned long nElem, unsigned mask, cacStateNotify ¬ify ) { epicsAutoMutex autoMutex ( this->mutex ); autoPtrRecycle < netSubscription > pIO ( *this, netSubscription::factory ( @@ -1459,7 +1384,7 @@ bool cac::badTCPRespAction ( tcpiiu &iiu, const caHdr &hdr, void * /* pMsgBdy */ { char hostName[64]; iiu.hostName ( hostName, sizeof(hostName) ); - ca_printf ( "CAC: Undecipherable TCP message ( bad response type %u ) from %s\n", + this->printf ( "CAC: Undecipherable TCP message ( bad response type %u ) from %s\n", hdr.m_cmmd, hostName ); return false; } diff --git a/src/ca/cac.h b/src/ca/cac.h new file mode 100644 index 000000000..e5761bf1b --- /dev/null +++ b/src/ca/cac.h @@ -0,0 +1,321 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef cach +#define cach + +#include "ipAddrToAsciiAsynchronous.h" +#include "epicsTimer.h" +#include "epicsEvent.h" + +#include "nciu.h" + +#define epicsExportSharedSymbols +#include "bhe.h" +#include "cacIO.h" +#undef epicsExportSharedSymbols + +class ioCounterNet { +public: + ioCounterNet (); + void increment (); + void decrement (); + void decrement ( unsigned seqNumber ); + unsigned sequenceNumber () const; + unsigned currentCount () const; + void cleanUp (); + void show ( unsigned level ) const; + void waitForCompletion ( double delaySec ); +private: + unsigned pndrecvcnt; + unsigned readSeq; + epicsMutex mutex; + epicsEvent ioDone; +}; + +class recvProcessThread : public epicsThreadRunable { +public: + recvProcessThread ( class cac *pcacIn ); + virtual ~recvProcessThread (); + void run (); + void enable (); + void disable (); + void signalActivity (); + bool isCurrentThread () const; + void show ( unsigned level ) const; +private: + // + // The additional complexity associated with + // "processingDone" event and the "processing" flag + // avoid complex locking hierarchy constraints + // and therefore reduces the chance of creating + // a deadlock window during code maintenance. + // + epicsThread thread; + epicsEvent recvActivity; + class cac *pcac; + epicsEvent exit; + epicsEvent processingDone; + mutable epicsMutex mutex; + unsigned enableRefCount; + unsigned blockingForCompletion; + bool processing; + bool shutDown; +}; + +class netWriteNotifyIO; +class netReadNotifyIO; +class netSubscription; + +// used to control access to cac's recycle routines which +// should only be indirectly invoked by CAC when its lock +// is applied +class cacRecycle { +public: + virtual void recycleReadNotifyIO ( netReadNotifyIO &io ) = 0; + virtual void recycleWriteNotifyIO ( netWriteNotifyIO &io ) = 0; + virtual void recycleSubscription ( netSubscription &io ) = 0; +}; + +struct CASG; +class inetAddrID; + +class cac : private cacRecycle +{ +public: + cac ( cacNotify &, bool enablePreemptiveCallback = false ); + virtual ~cac (); + + // beacon management + void beaconNotify ( const inetAddrID &addr ); + void repeaterSubscribeConfirmNotify (); + + // IIU routines + void signalRecvActivity (); + void processRecvBacklog (); + + // outstanding IO count management routines + void incrementOutstandingIO (); + void decrementOutstandingIO (); + void decrementOutstandingIO ( unsigned sequenceNo ); + unsigned sequenceNumberOfOutstandingIO () const; + bool ioComplete () const; + + // IO management + void flushRequest (); + int pendIO ( const double &timeout ); + int pendEvent ( const double &timeout ); + void connectAllIO ( nciu &chan ); + void disconnectAllIO ( nciu &chan ); + void destroyAllIO ( nciu &chan ); + void executeResponse ( tcpiiu &, caHdr &, char *pMshBody ); + void ioCancel ( nciu &chan, const cacChannel::ioid &id ); + void ioShow ( const cacChannel::ioid &id, unsigned level ) const; + + // channel routines + bool connectChannel ( unsigned id ); + void installNetworkChannel ( nciu &, netiiu *&piiu ); + bool lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, + unsigned typeCode, unsigned long count, unsigned minorVersionNumber, + const osiSockAddr & ); + void uninstallChannel ( nciu & ); + cacChannel & createChannel ( const char *name_str, cacChannelNotify &chan ); + void registerService ( cacService &service ); + + // IO request stubs + void writeRequest ( nciu &, unsigned type, + unsigned nElem, const void *pValue ); + cacChannel::ioid writeNotifyRequest ( nciu &, unsigned type, + unsigned nElem, const void *pValue, cacWriteNotify & ); + cacChannel::ioid readNotifyRequest ( nciu &, unsigned type, + unsigned nElem, cacReadNotify & ); + cacChannel::ioid subscriptionRequest ( nciu &, unsigned type, + unsigned long nElem, unsigned mask, cacStateNotify & ); + + // sync group routines + CASG * lookupCASG ( unsigned id ); + void installCASG ( CASG & ); + void uninstallCASG ( CASG & ); + + // exception generation + void exception ( int status, const char *pContext, + const char *pFileName, unsigned lineNo ); + void exception ( int status, const char *pContext, + unsigned type, unsigned long count, + const char *pFileName, unsigned lineNo ); + + // callback preemption control + void enableCallbackPreemption (); + void disableCallbackPreemption (); + + // diagnostics + unsigned connectionCount () const; + void show ( unsigned level ) const; + int printf ( const char *pformat, ... ); + int vPrintf ( const char *pformat, va_list args ); + void ipAddrToAsciiAsynchronousRequestInstall ( ipAddrToAsciiAsynchronous & request ); + + // misc + const char * userNamePointer () const; + unsigned getInitializingThreadsPriority () const; + + epicsMutex & mutexRef (); + +private: + ioCounterNet ioCounter; + ipAddrToAsciiEngine ipToAEngine; + cacServiceList services; + tsDLList iiuList; + chronIntIdResTable + < nciu > chanTable; + chronIntIdResTable + < baseNMIU > ioTable; + chronIntIdResTable + < CASG > sgTable; + resTable + < bhe, inetAddrID > beaconTable; + tsFreeList + < class netReadNotifyIO, 1024 > + freeListReadNotifyIO; + tsFreeList + < class netWriteNotifyIO, 1024 > + freeListWriteNotifyIO; + tsFreeList + < class netSubscription, 1024 > + freeListSubscription; + epicsTime programBeginTime; + double connTMO; + mutable epicsMutex mutex; + epicsEvent notifyCompletionEvent; + epicsTimerQueueActive *pTimerQueue; + char *pUserName; + recvProcessThread *pRecvProcThread; + class udpiiu *pudpiiu; + class searchTimer *pSearchTmr; + class repeaterSubscribeTimer + *pRepeaterSubscribeTmr; + cacNotify ¬ify; + unsigned ioNotifyInProgressId; + unsigned initializingThreadsPriority; + unsigned threadsBlockingOnNotifyCompletion; + bool enablePreemptiveCallback; + bool ioInProgress; + bool setupUDP (); + void flushIfRequired ( nciu & ); // lock must be applied + void recycleReadNotifyIO ( netReadNotifyIO &io ); + void recycleWriteNotifyIO ( netWriteNotifyIO &io ); + void recycleSubscription ( netSubscription &io ); + + bool ioCompletionNotify ( unsigned id, unsigned type, + unsigned long count, const void *pData ); + bool ioExceptionNotify ( unsigned id, + int status, const char *pContext ); + bool ioExceptionNotify ( unsigned id, int status, + const char *pContext, unsigned type, unsigned long count ); + bool ioCompletionNotifyAndDestroy ( unsigned id ); + bool ioCompletionNotifyAndDestroy ( unsigned id, + unsigned type, unsigned long count, const void *pData ); + bool ioExceptionNotifyAndDestroy ( unsigned id, + int status, const char *pContext ); + bool ioExceptionNotifyAndDestroy ( unsigned id, + int status, const char *pContext, unsigned type, unsigned long count ); + + // recv protocol stubs + bool noopAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool echoRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool writeNotifyRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool readNotifyRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool eventRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool readRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool clearChannelRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool exceptionRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool accessRightsRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool claimCIURespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool verifyAndDisconnectChan ( tcpiiu &, const caHdr &, void *pMsgBdy ); + bool badTCPRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); + typedef bool ( cac::*pProtoStubTCP ) ( + tcpiiu &, const caHdr &, void *pMsgBdy ); + static const pProtoStubTCP tcpJumpTableCAC []; +}; + +extern "C" void ca_default_exception_handler ( struct exception_handler_args args ); + +inline const char * cac::userNamePointer () const +{ + return this->pUserName; +} + +inline void cac::ipAddrToAsciiAsynchronousRequestInstall ( ipAddrToAsciiAsynchronous & request ) +{ + request.ioInitiate ( this->ipToAEngine ); +} + +inline unsigned cac::getInitializingThreadsPriority () const +{ + return this->initializingThreadsPriority; +} + +inline void cac::incrementOutstandingIO () +{ + this->ioCounter.increment (); +} + +inline void cac::decrementOutstandingIO () +{ + this->ioCounter.decrement (); +} + +inline void cac::decrementOutstandingIO ( unsigned sequenceNo ) +{ + this->ioCounter.decrement ( sequenceNo ); +} + +inline unsigned cac::sequenceNumberOfOutstandingIO () const +{ + return this->ioCounter.sequenceNumber (); +} + +inline epicsMutex & cac::mutexRef () +{ + return this->mutex; +} + +inline void cac::exception ( int status, const char *pContext, + const char *pFileName, unsigned lineNo ) +{ + this->notify.exception ( status, pContext, pFileName, lineNo ); +} + +inline void cac::exception ( int status, const char *pContext, + unsigned type, unsigned long count, + const char *pFileName, unsigned lineNo ) +{ + this->notify.exception ( status, pContext, type, count, pFileName, lineNo ); +} + +inline int cac::vPrintf ( const char *pformat, va_list args ) +{ + return this->notify.vPrintf ( pformat, args ); +} + +inline bool recvProcessThread::isCurrentThread () const +{ + return this->thread.isCurrentThread (); +} + +#endif // ifdef cach + diff --git a/src/ca/cacChannel.cpp b/src/ca/cacChannel.cpp index c820965f6..88ea8b915 100644 --- a/src/ca/cacChannel.cpp +++ b/src/ca/cacChannel.cpp @@ -13,7 +13,14 @@ #include +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "localHostName.h" + +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols cacChannel::~cacChannel () { diff --git a/src/ca/cacChannelNotify.cpp b/src/ca/cacChannelNotify.cpp index 88028cd56..c455c0136 100644 --- a/src/ca/cacChannelNotify.cpp +++ b/src/ca/cacChannelNotify.cpp @@ -16,28 +16,14 @@ #include "iocinf.h" +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols + cacChannelNotify::~cacChannelNotify () { } -void cacChannelNotify::connectNotify ( cacChannel & ) -{ -} - -void cacChannelNotify::disconnectNotify ( cacChannel & ) -{ -} - -void cacChannelNotify::accessRightsNotify ( cacChannel &, const caAccessRights & ) -{ -} - -void cacChannelNotify::exception ( cacChannel &io, int status, const char *pContext ) -{ - ca_signal_formated ( status, __FILE__, __LINE__, "channel=%s context=\"%s\"\n", - io.pHostName (), pContext ); -} - bool cacChannelNotify::includeFirstConnectInCountOfOutstandingIO () const { return false; diff --git a/src/ca/cacIO.h b/src/ca/cacIO.h index e7662cdef..f80fc8e64 100644 --- a/src/ca/cacIO.h +++ b/src/ca/cacIO.h @@ -15,6 +15,9 @@ * 505 665 1831 */ +#ifndef cacIOh +#define cacIOh + // // Open Issues // ----------- @@ -33,6 +36,8 @@ // // +#include + #include "tsDLList.h" #include "epicsMutex.h" @@ -41,24 +46,35 @@ class cacChannel; // this should not be passing caerr.h status to the exception callback -class epicsShareClass cacNotify { +class epicsShareClass cacWriteNotify { public: - virtual ~cacNotify () = 0; + virtual ~cacWriteNotify () = 0; virtual void completion () = 0; virtual void exception ( int status, const char *pContext ) = 0; }; // 1) this should not be passing caerr.h status to the exception callback -// 2) obviously the data should be passed here using the new data access API -class epicsShareClass cacDataNotify { +// 2) needless-to-say the data should be passed here using the new data access API +class epicsShareClass cacReadNotify { public: - virtual ~cacDataNotify () = 0; + virtual ~cacReadNotify () = 0; virtual void completion ( unsigned type, unsigned long count, const void *pData ) = 0; virtual void exception ( int status, const char *pContext, unsigned type, unsigned long count ) = 0; }; +// 1) this should not be passing caerr.h status to the exception callback +// 2) needless-to-say the data should be passed here using the new data access API +class epicsShareClass cacStateNotify { +public: + virtual ~cacStateNotify () = 0; + virtual void current ( unsigned type, + unsigned long count, const void *pData ) = 0; + virtual void exception ( int status, + const char *pContext, unsigned type, unsigned long count ) = 0; +}; + class caAccessRights { public: caAccessRights ( @@ -83,12 +99,11 @@ private: class epicsShareClass cacChannelNotify { public: virtual ~cacChannelNotify () = 0; -// is it useful to pass the channel IO here ????? - virtual void connectNotify ( cacChannel & ); - virtual void disconnectNotify ( cacChannel & ); - virtual void accessRightsNotify ( cacChannel &, const caAccessRights & ); - virtual void exception ( cacChannel &, int status, const char *pContext ); - // not for public consumption -- can we get rid of this + virtual void connectNotify () = 0; + virtual void disconnectNotify () = 0; + virtual void accessRightsNotify ( const caAccessRights & ) = 0; + virtual void exception ( int status, const char *pContext ) = 0; + // not for public consumption -- can we get rid of this ???? virtual bool includeFirstConnectInCountOfOutstandingIO () const; }; @@ -113,11 +128,11 @@ public: virtual void write ( unsigned type, unsigned long count, const void *pValue ) = 0; virtual ioStatus read ( unsigned type, unsigned long count, - cacDataNotify &, ioid * = 0 ) = 0; + cacReadNotify &, ioid * = 0 ) = 0; virtual ioStatus write ( unsigned type, unsigned long count, - const void *pValue, cacNotify &, ioid * = 0 ) = 0; + const void *pValue, cacWriteNotify &, ioid * = 0 ) = 0; virtual void subscribe ( unsigned type, unsigned long count, - unsigned mask, cacDataNotify &, ioid * = 0 ) = 0; + unsigned mask, cacStateNotify &, ioid * = 0 ) = 0; virtual void ioCancel ( const ioid & ) = 0; virtual void ioShow ( const ioid &, unsigned level ) const = 0; virtual short nativeType () const = 0; @@ -148,6 +163,22 @@ private: cacChannelNotify & callback; }; +class cacNotify { +public: + virtual ~cacNotify () = 0; +// exception mechanism needs to be designed + virtual void exception ( int status, const char *pContext, + const char *pFileName, unsigned lineNo ) = 0; + virtual void exception ( int status, const char *pContext, + unsigned type, unsigned long count, + const char *pFileName, unsigned lineNo ) = 0; +// perhaps this should be phased out in deference to the exception mechanism + virtual int vPrintf ( const char *pformat, va_list args ) = 0; +// this should probably be phased out (its not OS independent) + virtual void fdWasCreated ( int fd ) = 0; + virtual void fdWasDestroyed ( int fd ) = 0; +}; + struct cacService : public tsDLNode < cacService > { public: virtual cacChannel * createChannel ( @@ -229,3 +260,5 @@ inline bool caAccessRights::operatorConfirmationRequest () const { return this->f_operatorConfirmationRequest; } + +#endif // ifndef cacIOh diff --git a/src/ca/cacDataNotify.cpp b/src/ca/cacReadNotify.cpp similarity index 69% rename from src/ca/cacDataNotify.cpp rename to src/ca/cacReadNotify.cpp index 1580df45e..ab0955f8b 100644 --- a/src/ca/cacDataNotify.cpp +++ b/src/ca/cacReadNotify.cpp @@ -12,6 +12,10 @@ #include "iocinf.h" -cacDataNotify::~cacDataNotify () +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols + +cacReadNotify::~cacReadNotify () { } diff --git a/src/ca/cacServiceList.cpp b/src/ca/cacServiceList.cpp index 57312def4..174045ab7 100644 --- a/src/ca/cacServiceList.cpp +++ b/src/ca/cacServiceList.cpp @@ -17,6 +17,10 @@ #include "iocinf.h" +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols + epicsShareDef cacServiceList cacGlobalServiceList; void cacServiceList::registerService ( cacService &service ) diff --git a/src/ca/cacNotify.cpp b/src/ca/cacStateNotify.cpp similarity index 69% rename from src/ca/cacNotify.cpp rename to src/ca/cacStateNotify.cpp index 7dff1b791..f426e6174 100644 --- a/src/ca/cacNotify.cpp +++ b/src/ca/cacStateNotify.cpp @@ -12,6 +12,10 @@ #include "iocinf.h" -cacNotify::~cacNotify () +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols + +cacStateNotify::~cacStateNotify () { } diff --git a/src/ca/cacWriteNotify.cpp b/src/ca/cacWriteNotify.cpp new file mode 100644 index 000000000..dd5e275be --- /dev/null +++ b/src/ca/cacWriteNotify.cpp @@ -0,0 +1,21 @@ + +/* $Id$ + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * Author: Jeff Hill + */ + +#include "iocinf.h" + +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols + +cacWriteNotify::~cacWriteNotify () +{ +} diff --git a/src/ca/cadef.h b/src/ca/cadef.h index 81d26f8f4..25d65908f 100644 --- a/src/ca/cadef.h +++ b/src/ca/cadef.h @@ -16,7 +16,6 @@ #ifndef INCLcadefh #define INCLcadefh - /* * done in two ifdef steps so that we will remain compatible with * traditional C @@ -37,7 +36,17 @@ # endif #endif -#include "epicsThread.h" +#ifdef epicsExportSharedSymbols +# define INCLcadefh_accessh_epicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +# include "epicsThread.h" + +#ifdef INCLcadefh_accessh_epicsExportSharedSymbols +# define epicsExportSharedSymbols +#endif + #include "shareLib.h" #include "caerr.h" #include "db_access.h" @@ -85,7 +94,6 @@ typedef void caArh (); /* The conversion routine to call for each type */ #define VALID_TYPE(TYPE) (((unsigned short)TYPE)<=LAST_BUFFER_TYPE) - /* * Arguments passed to event handlers and get/put call back handlers. * @@ -109,13 +117,12 @@ typedef void caEventCallBackFunc (struct event_handler_args); typedef void caEventCallBackFunc (); #endif /*CAC_ANSI_FUNC_PROTO*/ - epicsShareFunc void epicsShareAPI ca_test_event - ( +( #ifdef CAC_ANSI_FUNC_PROTO struct event_handler_args #endif /*CAC_ANSI_FUNC_PROTO*/ - ); +); /* Format for the arguments to user exception handlers */ struct exception_handler_args { @@ -644,7 +651,7 @@ epicsShareFunc int epicsShareAPI ca_clear_event * timeOut R wait for this delay in seconds */ epicsShareFunc int epicsShareAPI ca_pend_event (ca_real timeOut); -#define ca_poll() ca_pend_event((1e-12)) +#define ca_poll() ca_pend_event( ( 1e-12 ) ) /* * ca_pend_io() @@ -1028,5 +1035,5 @@ ca_sg_array_put(gid, type, 1u, chan, pValue) /* * no additions below this endif */ -#endif /* INCLcadefh */ +#endif /* ifndef INCLcadefh */ diff --git a/src/ca/caerr.h b/src/ca/caerr.h index 973b4a7c4..6ad932689 100644 --- a/src/ca/caerr.h +++ b/src/ca/caerr.h @@ -14,8 +14,18 @@ #ifndef INCLcaerrh #define INCLcaerrh +#ifdef epicsExportSharedSymbols +# define INCLcaerrh_accessh_epicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +# include "epicsTypes.h" + +#ifdef INCLcaerrh_accessh_epicsExportSharedSymbols +# define epicsExportSharedSymbols +#endif + #include "shareLib.h" -#include "epicsTypes.h" /* CA Status Code Definitions */ diff --git a/src/ca/casw.cpp b/src/ca/casw.cpp index 45d5ba655..3ee3ec697 100644 --- a/src/ca/casw.cpp +++ b/src/ca/casw.cpp @@ -12,9 +12,13 @@ #include -#include "iocinf.h" -#include "bhe_IL.h" -#include "inetAddrID_IL.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + +#include "envDefs.h" + +#include "bhe.h" +#include "udpiiu.h" +#include "inetAddrID.h" int main ( int, char ** ) { diff --git a/src/ca/catime.c b/src/ca/catime.c index ae003330e..9124a28c2 100644 --- a/src/ca/catime.c +++ b/src/ca/catime.c @@ -16,10 +16,12 @@ #include #include +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "epicsAssert.h" +#include "epicsTime.h" #include "cadef.h" #include "caProto.h" -#include "epicsTime.h" #include "caDiagnostics.h" diff --git a/src/ca/comBuf.cpp b/src/ca/comBuf.cpp index d87470566..c56b88447 100644 --- a/src/ca/comBuf.cpp +++ b/src/ca/comBuf.cpp @@ -14,8 +14,10 @@ * johill@lanl.gov */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "comBuf_IL.h" +#include "comBuf.h" bool comBuf::flushToWire ( wireSendAdapter &wire ) { diff --git a/src/ca/comBuf_IL.h b/src/ca/comBuf.h similarity index 75% rename from src/ca/comBuf_IL.h rename to src/ca/comBuf.h index 6096f69bb..55205a73b 100644 --- a/src/ca/comBuf_IL.h +++ b/src/ca/comBuf.h @@ -14,13 +14,69 @@ * johill@lanl.gov */ -#ifndef comBuf_ILh -#define comBuf_ILh +#ifndef comBufh +#define comBufh + +#include #include "epicsAssert.h" #include "epicsTypes.h" +#include "tsFreeList.h" +#include "tsDLList.h" #include "osiWireFormat.h" +static const unsigned comBufSize = 0x4000; + +class wireSendAdapter { +public: + virtual unsigned sendBytes ( const void *pBuf, + unsigned nBytesInBuf ) = 0; +}; + +class wireRecvAdapter { +public: + virtual unsigned recvBytes ( void *pBuf, + unsigned nBytesInBuf ) = 0; +}; + +class comBuf : public tsDLNode < comBuf > { +public: + comBuf (); + void destroy (); + unsigned unoccupiedBytes () const; + unsigned occupiedBytes () const; + void compress (); + static unsigned capacityBytes (); + unsigned copyInBytes ( const void *pBuf, unsigned nBytes ); + unsigned copyIn ( comBuf & ); + unsigned copyIn ( const epicsInt8 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsUInt8 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsInt16 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsUInt16 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsInt32 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsUInt32 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsFloat32 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsFloat64 *pValue, unsigned nElem ); + unsigned copyIn ( const epicsOldString *pValue, unsigned nElem ); + bool copyInAllBytes ( const void *pBuf, unsigned nBytes ); + unsigned copyOutBytes ( void *pBuf, unsigned nBytes ); + bool copyOutAllBytes ( void *pBuf, unsigned nBytes ); + unsigned removeBytes ( unsigned nBytes ); + void * operator new ( size_t size ); + void operator delete ( void *pCadaver, size_t size ); + bool flushToWire ( wireSendAdapter & ); + unsigned fillFromWire ( wireRecvAdapter & ); +protected: + ~comBuf (); +private: + unsigned nextWriteIndex; + unsigned nextReadIndex; + unsigned char buf [ comBufSize ]; // optimal for 100 Mb Ethernet LAN MTU + unsigned clipNElem ( unsigned elemSize, unsigned nElem ); + static tsFreeList < class comBuf, 0x20 > freeList; + static epicsMutex freeListMutex; +}; + inline comBuf::comBuf () : nextWriteIndex ( 0u ), nextReadIndex ( 0u ) { } @@ -233,4 +289,4 @@ inline unsigned comBuf::copyIn ( const epicsFloat64 *pValue, unsigned nElem ) return nElem; } -#endif // comBuf_ILh +#endif // comBuf diff --git a/src/ca/comQueRecv.cpp b/src/ca/comQueRecv.cpp index ac503aeaa..2c20b2de9 100644 --- a/src/ca/comQueRecv.cpp +++ b/src/ca/comQueRecv.cpp @@ -14,8 +14,10 @@ * johill@lanl.gov */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "comBuf_IL.h" +#include "virtualCircuit.h" comQueRecv::comQueRecv () { diff --git a/src/ca/comQueSend.cpp b/src/ca/comQueSend.cpp index 7e77be8e0..3e8ff6abf 100644 --- a/src/ca/comQueSend.cpp +++ b/src/ca/comQueSend.cpp @@ -57,8 +57,14 @@ // // +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "comQueSend_IL.h" +#include "virtualCircuit.h" + +#define epicsExportSharedSymbols +#include "db_access.h" // for dbr_short_t etc +#undef epicsExportSharedSymbols tsFreeList < class comBuf, 0x20 > comBuf::freeList; epicsMutex comBuf::freeListMutex; diff --git a/src/ca/comQueSend_IL.h b/src/ca/comQueSend_IL.h deleted file mode 100644 index 0f38196e5..000000000 --- a/src/ca/comQueSend_IL.h +++ /dev/null @@ -1,206 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 2000, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef comQueSend_ILh -#define comQueSend_ILh - -#include - -#include "comBuf_IL.h" - -inline bufferReservoir::~bufferReservoir () -{ - this->drain (); -} - -inline comBuf *bufferReservoir::fetchOneBuffer () -{ - return this->reservedBufs.get (); -} - -inline void bufferReservoir::addOneBuffer () -{ - comBuf *pBuf = new comBuf; - if ( ! pBuf ) { - throw std::bad_alloc(); - } - this->reservedBufs.add ( *pBuf ); -} - -inline unsigned bufferReservoir::nBytes () -{ - return ( this->reservedBufs.count () * comBuf::capacityBytes () ); -} - -inline void bufferReservoir::drain () -{ - comBuf *pBuf; - while ( ( pBuf = this->reservedBufs.get () ) ) { - pBuf->destroy (); - } -} - -inline bool comQueSend::dbr_type_ok ( unsigned type ) -{ - if ( type >= ( sizeof ( this->dbrCopyVector ) / sizeof ( this->dbrCopyVector[0] ) ) ) { - return false; - } - if ( ! this->dbrCopyVector [type] ) { - return false; - } - return true; -} - -// -// 1) This routine does not return status because of the following -// argument. The routine can fail because the wire disconnects or -// because their isnt memory to create a buffer. For the former we -// just discard the message, but do not fail. For the latter we -// shutdown() the connection and discard the rest of the message -// (this eliminates the possibility of message fragments getting -// onto the wire). -// -// 2) Arguments here are a bit verbose until compilers all implement -// member template functions. -// - -template < class T > -inline void comQueSend_copyIn ( unsigned &nBytesPending, - tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, - const T *pVal, unsigned nElem ) -{ - nBytesPending += sizeof ( T ) * nElem; - - comBuf *pComBuf = comBufList.last (); - if ( pComBuf ) { - unsigned nCopied = pComBuf->copyIn ( pVal, nElem ); - if ( nElem > nCopied ) { - comQueSend_copyInWithReservour ( comBufList, reservoir, &pVal[nCopied], - nElem - nCopied ); - } - } - else { - comQueSend_copyInWithReservour ( comBufList, reservoir, pVal, nElem ); - } -} - -template < class T > -void comQueSend_copyInWithReservour ( - tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, - const T *pVal, unsigned nElem ) -{ - unsigned nCopied = 0u; - while ( nElem > nCopied ) { - comBuf *pComBuf = reservoir.fetchOneBuffer (); - // - // This fails only if space was not preallocated. - // See comments at the top of this program on - // why space must always be preallocated. - // - assert ( pComBuf ); - nCopied += pComBuf->copyIn ( &pVal[nCopied], nElem - nCopied ); - comBufList.add ( *pComBuf ); - } -} - -template < class T > -inline void comQueSend_copyIn ( unsigned &nBytesPending, - tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, - const T &val ) -{ - nBytesPending += sizeof ( T ); - - comBuf *pComBuf = comBufList.last (); - if ( pComBuf ) { - if ( pComBuf->copyIn ( &val, 1u ) >= 1u ) { - return; - } - } - - pComBuf = reservoir.fetchOneBuffer (); - // - // This fails only if space was not preallocated. - // See comments at the top of this program on - // space must always be preallocated. - // - assert ( pComBuf ); - pComBuf->copyIn ( &val, 1u ); - comBufList.add ( *pComBuf ); -} - -inline void comQueSend::pushUInt16 ( const ca_uint16_t value ) -{ - comQueSend_copyIn ( this->nBytesPending, - this->bufs, this->reservoir, value ); -} - -inline void comQueSend::pushUInt32 ( const ca_uint32_t value ) -{ - comQueSend_copyIn ( this->nBytesPending, - this->bufs, this->reservoir, value ); -} - -inline void comQueSend::pushFloat32 ( const ca_float32_t value ) -{ - comQueSend_copyIn ( this->nBytesPending, - this->bufs, this->reservoir, value ); -} - -inline void comQueSend::pushString ( const char *pVal, unsigned nElem ) -{ - comQueSend_copyIn ( this->nBytesPending, - this->bufs, this->reservoir, pVal, nElem ); -} - -// it is assumed that dbr_type_ok() was called prior to calling this routine -// to check the type code -inline void comQueSend::push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ) -{ - ( this->*dbrCopyVector [type] ) ( pVal, nElem ); -} - -inline unsigned comQueSend::occupiedBytes () const -{ - return this->nBytesPending; -} - -inline bool comQueSend::flushBlockThreshold ( unsigned nBytesThisMsg ) const -{ - return ( this->nBytesPending + nBytesThisMsg > 16 * comBuf::capacityBytes () ); -} - -inline bool comQueSend::flushEarlyThreshold ( unsigned nBytesThisMsg ) const -{ - return ( this->nBytesPending + nBytesThisMsg > 4 * comBuf::capacityBytes () ); -} - -inline comBuf * comQueSend::popNextComBufToSend () -{ - comBuf *pBuf = this->bufs.get (); - if ( pBuf ) { - unsigned nBytesThisBuf = pBuf->occupiedBytes (); - assert ( this->nBytesPending >= nBytesThisBuf ); - this->nBytesPending -= pBuf->occupiedBytes (); - } - else { - assert ( this->nBytesPending == 0u ); - } - return pBuf; -} - -#endif // comQueSend_ILh - diff --git a/src/ca/convert.cpp b/src/ca/convert.cpp index 83e613797..9cb831aa2 100644 --- a/src/ca/convert.cpp +++ b/src/ca/convert.cpp @@ -14,9 +14,15 @@ * */ -#include +#include -#include "iocinf.h" +#include "osiSock.h" + +#include "iocinf.h" +#include "caProto.h" + +#define epicsExportSharedSymbols +#include "net_convert.h" #if defined(VMS) #include @@ -41,7 +47,6 @@ #define dbr_htons(A) (htons(A)) #define dbr_htonl(A) (htonl(A)) - /* * CVRT_STRING() * @@ -938,7 +943,7 @@ unsigned long num /* number of values */ pDest->status = dbr_ntohs(pSrc->status); pDest->severity = dbr_ntohs(pSrc->severity); - pDest->no_str = dbr_ntohs(pSrc->no_str); + pDest->no_str = dbr_ntohs(pSrc->no_str); memcpy((void *)pDest->strs,(void *)pSrc->strs,sizeof(pSrc->strs)); if (num == 1) /* single value */ @@ -1707,6 +1712,5 @@ epicsShareDef CACVRTFUNC *cac_dbr_cvrt[] = { cvrt_string }; - #endif /* CONVERSION_REQUIRED */ diff --git a/src/ca/db_access.h b/src/ca/db_access.h index 5b3be92b7..1e669b0c2 100644 --- a/src/ca/db_access.h +++ b/src/ca/db_access.h @@ -79,13 +79,22 @@ of this distribution. #ifndef INCLdb_accessh #define INCLdb_accessh - #include -#include "shareLib.h" +#ifdef epicsExportSharedSymbols +# define INCLdb_accessh_epicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + #include "epicsTypes.h" #include "epicsTime.h" +#ifdef INCLdb_accessh_epicsExportSharedSymbols +# define epicsExportSharedSymbols +#endif + +#include "shareLib.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/src/ca/evtime.c b/src/ca/evtime.c index 5b73bc88b..395e53d3f 100644 --- a/src/ca/evtime.c +++ b/src/ca/evtime.c @@ -1,8 +1,9 @@ #include -#include "cadef.h" + #include "dbDefs.h" #include "epicsTime.h" +#include "cadef.h" void event_handler (struct event_handler_args args); int evtime (char *pname); diff --git a/src/ca/getCopy.cpp b/src/ca/getCopy.cpp index 99884d58b..eb473a3d1 100644 --- a/src/ca/getCopy.cpp +++ b/src/ca/getCopy.cpp @@ -15,14 +15,16 @@ * 505 665 1831 */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" #include "oldAccess.h" -#include "cac_IL.h" +#include "cac.h" tsFreeList < class getCopy, 1024 > getCopy::freeList; epicsMutex getCopy::freeListMutex; -getCopy::getCopy ( cac &cacCtxIn, unsigned typeIn, +getCopy::getCopy ( oldCAC &cacCtxIn, unsigned typeIn, unsigned long countIn, void *pValueIn ) : count ( countIn ), cacCtx ( cacCtxIn ), pValue ( pValueIn ), readSeq ( cacCtxIn.sequenceNumberOfOutstandingIO () ), type ( typeIn ) @@ -60,10 +62,10 @@ void getCopy::exception ( void getCopy::show ( unsigned level ) const { int tmpType = static_cast ( this->type ); - printf ( "read copy IO at %p, type %s, element count %lu\n", + ::printf ( "read copy IO at %p, type %s, element count %lu\n", static_cast ( this ), dbf_type_to_text ( tmpType ), this->count ); if ( level > 0u ) { - printf ( "\tsequence number %u, user's storage %p\n", + ::printf ( "\tsequence number %u, user's storage %p\n", this->readSeq, static_cast ( this->pValue ) ); } } diff --git a/src/ca/hostNameCache.cpp b/src/ca/hostNameCache.cpp index 05004578e..41945a09a 100644 --- a/src/ca/hostNameCache.cpp +++ b/src/ca/hostNameCache.cpp @@ -14,7 +14,10 @@ * johill@lanl.gov */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "virtualCircuit.h" tsFreeList < hostNameCache, 16 > hostNameCache::freeList; epicsMutex hostNameCache::freeListMutex; diff --git a/src/ca/inetAddrID_IL.h b/src/ca/inetAddrID.h similarity index 68% rename from src/ca/inetAddrID_IL.h rename to src/ca/inetAddrID.h index 76339996d..6190b5b7b 100644 --- a/src/ca/inetAddrID_IL.h +++ b/src/ca/inetAddrID.h @@ -10,6 +10,23 @@ * Author: Jeff Hill */ +#ifndef inetAddrIDh +#define inetAddrIDh + +#include "resourceLib.h" +#include "osiSock.h" + +class inetAddrID { +public: + inetAddrID ( const struct sockaddr_in &addrIn ); + bool operator == ( const inetAddrID & ) const; + resTableIndex hash ( unsigned nBitsHashIndex ) const; + static unsigned maxIndexBitWidth (); + static unsigned minIndexBitWidth (); +private: + const struct sockaddr_in addr; +}; + inline inetAddrID::inetAddrID ( const struct sockaddr_in &addrIn ) : addr (addrIn) { @@ -43,3 +60,6 @@ inline unsigned inetAddrID::minIndexBitWidth () return 8u; } +#endif // ifdef inetAddrID + + diff --git a/src/ca/ioCounterNet.cpp b/src/ca/ioCounterNet.cpp index 9a7f779d8..d722ea7e8 100644 --- a/src/ca/ioCounterNet.cpp +++ b/src/ca/ioCounterNet.cpp @@ -15,7 +15,16 @@ * 505 665 1831 */ +#include + +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "cac.h" + +#define epicsExportSharedSymbols +#include "caerr.h" // for CA_INTERNAL +#undef epicsExportSharedSymbols ioCounterNet::ioCounterNet () : pndrecvcnt ( 0u ), readSeq ( 0u ) { @@ -111,16 +120,16 @@ void ioCounterNet::decrement ( unsigned seqNumber ) void ioCounterNet::show ( unsigned level ) const { - printf ( "ioCounterNet at %p\n", + ::printf ( "ioCounterNet at %p\n", static_cast ( this ) ); - printf ( "\tthere are %u unsatisfied IO operations blocking ca_pend_io()\n", + ::printf ( "\tthere are %u unsatisfied IO operations blocking ca_pend_io()\n", this->pndrecvcnt ); if ( level > 0u ) { - printf ( "\tthe current read sequence number is %u\n", + ::printf ( "\tthe current read sequence number is %u\n", this->readSeq ); } if ( level > 1u ) { - printf ( "IO done event:\n"); + ::printf ( "IO done event:\n"); this->ioDone.show ( level - 2u ); } } diff --git a/src/ca/iocinf.cpp b/src/ca/iocinf.cpp index 1498c8230..165f872b7 100644 --- a/src/ca/iocinf.cpp +++ b/src/ca/iocinf.cpp @@ -10,10 +10,17 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + +#include "envdefs.h" +#include "epicsAssert.h" #include "locationException.h" -#include "iocinf.h" +#define epicsExportSharedSymbols #include "addrList.h" +#undef epicsExportSharedSymbols + +#include "iocinf.h" /* * getToken() @@ -49,8 +56,8 @@ static char *getToken ( const char **ppString, char *pBuf, unsigned bufSIze ) /* * addAddrToChannelAccessAddressList () */ -epicsShareFunc void epicsShareAPI addAddrToChannelAccessAddressList - (ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port) +extern "C" void epicsShareAPI addAddrToChannelAccessAddressList + ( ELLLIST *pList, const ENV_PARAM *pEnv, unsigned short port ) { osiSockAddrNode *pNewNode; const char *pStr; @@ -67,14 +74,14 @@ epicsShareFunc void epicsShareAPI addAddrToChannelAccessAddressList while ( ( pToken = getToken (&pStr, buf, sizeof (buf) ) ) ) { status = aToIPAddr ( pToken, port, &addr ); if (status<0) { - ca_printf ("%s: Parsing '%s'\n", __FILE__, pEnv->name); - ca_printf ("\tBad internet address or host name: '%s'\n", pToken); + fprintf ( stderr, "%s: Parsing '%s'\n", __FILE__, pEnv->name); + fprintf ( stderr, "\tBad internet address or host name: '%s'\n", pToken); continue; } pNewNode = (osiSockAddrNode *) calloc (1, sizeof(*pNewNode)); if (pNewNode==NULL) { - ca_printf ("addAddrToChannelAccessAddressList(): no memory available for configuration\n"); + fprintf ( stderr, "addAddrToChannelAccessAddressList(): no memory available for configuration\n"); return; } @@ -93,7 +100,7 @@ epicsShareFunc void epicsShareAPI addAddrToChannelAccessAddressList /* * removeDuplicatesAddresses () */ -epicsShareFunc void epicsShareAPI removeDuplicatesAddresses +extern "C" void epicsShareAPI removeDuplicatesAddresses ( ELLLIST *pDestList, ELLLIST *pSrcList ) { osiSockAddrNode *pNode; @@ -113,7 +120,7 @@ epicsShareFunc void epicsShareAPI removeDuplicatesAddresses if ( exorAddr == 0u && pNode->addr.ia.sin_port == pTmpNode->addr.ia.sin_port) { char buf[64]; ipAddrToDottedIP ( &pNode->addr.ia, buf, sizeof (buf) ); - ca_printf ( "Warning: Duplicate EPICS CA Address list entry \"%s\" discarded\n", buf ); + fprintf ( stderr, "Warning: Duplicate EPICS CA Address list entry \"%s\" discarded\n", buf ); free (pNode); pNode = NULL; break; @@ -134,16 +141,16 @@ epicsShareFunc void epicsShareAPI removeDuplicatesAddresses /* * forcePort () */ -static void forcePort (ELLLIST *pList, unsigned short port) +static void forcePort ( ELLLIST *pList, unsigned short port ) { osiSockAddrNode *pNode; - pNode = (osiSockAddrNode *) ellFirst ( pList ); + pNode = ( osiSockAddrNode * ) ellFirst ( pList ); while ( pNode ) { if ( pNode->addr.sa.sa_family == AF_INET ) { pNode->addr.ia.sin_port = htons (port); } - pNode = (osiSockAddrNode *) ellNext ( &pNode->node ); + pNode = ( osiSockAddrNode * ) ellNext ( &pNode->node ); } } @@ -151,7 +158,7 @@ static void forcePort (ELLLIST *pList, unsigned short port) /* * configureChannelAccessAddressList () */ -epicsShareFunc void epicsShareAPI configureChannelAccessAddressList +extern "C" void epicsShareAPI configureChannelAccessAddressList ( ELLLIST *pList, SOCKET sock, unsigned short port ) { ELLLIST tmpList; @@ -219,16 +226,16 @@ epicsShareFunc void epicsShareAPI configureChannelAccessAddressList /* * printChannelAccessAddressList () */ -epicsShareFunc void epicsShareAPI printChannelAccessAddressList ( const ELLLIST *pList ) +extern "C" void epicsShareAPI printChannelAccessAddressList ( const ELLLIST *pList ) { osiSockAddrNode *pNode; - printf ( "Channel Access Address List\n" ); + ::printf ( "Channel Access Address List\n" ); pNode = (osiSockAddrNode *) ellFirst ( pList ); while (pNode) { char buf[64]; ipAddrToA ( &pNode->addr.ia, buf, sizeof ( buf ) ); - printf ( "%s\n", buf ); + ::printf ( "%s\n", buf ); pNode = (osiSockAddrNode *) ellNext ( &pNode->node ); } } diff --git a/src/ca/iocinf.h b/src/ca/iocinf.h index c71b3a7f7..94aef5991 100644 --- a/src/ca/iocinf.h +++ b/src/ca/iocinf.h @@ -17,57 +17,7 @@ #ifndef INCiocinfh #define INCiocinfh -/* - * ANSI C includes - * ---- MULTINET/VMS breaks if we include ANSI time.h here ---- - */ -#include -#include -#include -#include -#include -#include - -#if defined ( epicsExportSharedSymbols ) -# error suspect that libCom was not imported -#endif - -/* - * EPICS includes - */ #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -#include "epicsAssert.h" -#include "bucketLib.h" -#include "envDefs.h" -#include "epicsPrint.h" -#include "epicsTime.h" -#include "tsFreeList.h" -#include "tsDLList.h" -#include "osiSock.h" -#include "epicsEvent.h" -#include "epicsThread.h" -#include "epicsTimer.h" -#include "epicsMutex.h" -#include "resourceLib.h" -#include "localHostName.h" -#include "ipAddrToAsciiAsynchronous.h" - -#if defined ( epicsExportSharedSymbols ) -# error suspect that libCom was not imported -#endif - -/* - * this is defined only after we import from libCom above - */ -#define epicsExportSharedSymbols -#include "cadef.h" -#include "cacIO.h" - -/* - * CA private includes - */ -#include "caProto.h" -#include "net_convert.h" #define NO_PLACEMENT_DELETE @@ -88,329 +38,6 @@ #define MSEC_PER_SEC 1000L #define USEC_PER_SEC 1000000L -/* - * catch when they use really large strings - */ -#define STRING_LIMIT 512 - -static const unsigned comBufSize = 0x4000; - -class wireSendAdapter { -public: - virtual unsigned sendBytes ( const void *pBuf, - unsigned nBytesInBuf ) = 0; -}; - -class wireRecvAdapter { -public: - virtual unsigned recvBytes ( void *pBuf, - unsigned nBytesInBuf ) = 0; -}; - -class comBuf : public tsDLNode < comBuf > { -public: - comBuf (); - void destroy (); - unsigned unoccupiedBytes () const; - unsigned occupiedBytes () const; - void compress (); - static unsigned capacityBytes (); - unsigned copyInBytes ( const void *pBuf, unsigned nBytes ); - unsigned copyIn ( comBuf & ); - unsigned copyIn ( const epicsInt8 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsUInt8 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsInt16 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsUInt16 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsInt32 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsUInt32 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsFloat32 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsFloat64 *pValue, unsigned nElem ); - unsigned copyIn ( const epicsOldString *pValue, unsigned nElem ); - bool copyInAllBytes ( const void *pBuf, unsigned nBytes ); - unsigned copyOutBytes ( void *pBuf, unsigned nBytes ); - bool copyOutAllBytes ( void *pBuf, unsigned nBytes ); - unsigned removeBytes ( unsigned nBytes ); - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); - bool flushToWire ( wireSendAdapter & ); - unsigned fillFromWire ( wireRecvAdapter & ); -protected: - ~comBuf (); -private: - unsigned nextWriteIndex; - unsigned nextReadIndex; - unsigned char buf [ comBufSize ]; // optimal for 100 Mb Ethernet LAN MTU - unsigned clipNElem ( unsigned elemSize, unsigned nElem ); - static tsFreeList < class comBuf, 0x20 > freeList; - static epicsMutex freeListMutex; -}; - -struct msgDescriptor { - const void *pBuf; - unsigned nBytes; -}; - -class bufferReservoir { -public: - ~bufferReservoir (); - void addOneBuffer (); - comBuf *fetchOneBuffer (); - unsigned nBytes (); - void drain (); -private: - tsDLList < comBuf > reservedBufs; -}; - -class comQueSend { -public: - comQueSend ( wireSendAdapter & ); - ~comQueSend (); - void clear (); - void reserveSpace ( unsigned msgSize ); - unsigned occupiedBytes () const; - bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const; - bool flushBlockThreshold ( unsigned nBytesThisMsg ) const; - bool dbr_type_ok ( unsigned type ); - void pushUInt16 ( const ca_uint16_t value ); - void pushUInt32 ( const ca_uint32_t value ); - void pushFloat32 ( const ca_float32_t value ); - void pushString ( const char *pVal, unsigned nElem ); - void push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ); - comBuf * popNextComBufToSend (); -private: - wireSendAdapter & wire; - tsDLList < comBuf > bufs; - bufferReservoir reservoir; - unsigned nBytesPending; - void copy_dbr_string ( const void *pValue, unsigned nElem ); - void copy_dbr_short ( const void *pValue, unsigned nElem ); - void copy_dbr_float ( const void *pValue, unsigned nElem ); - void copy_dbr_char ( const void *pValue, unsigned nElem ); - void copy_dbr_long ( const void *pValue, unsigned nElem ); - void copy_dbr_double ( const void *pValue, unsigned nElem ); - typedef void ( comQueSend::*copyFunc_t ) ( - const void *pValue, unsigned nElem ); - static const copyFunc_t dbrCopyVector [39]; -}; - -static const unsigned maxBytesPendingTCP = 0x4000; - -class comQueRecv { -public: - comQueRecv (); - ~comQueRecv (); - unsigned occupiedBytes () const; - bool copyOutBytes ( void *pBuf, unsigned nBytes ); - void pushLastComBufReceived ( comBuf & ); - void clear (); -private: - tsDLList < comBuf > bufs; -}; - -class caClient { -public: - virtual void exception (int status, const char *pContext, - const char *pFileName, unsigned lineNo) = 0; - virtual void exception (int status, const char *pContext, - unsigned type, unsigned long count, - const char *pFileName, unsigned lineNo) = 0; -}; - -class netiiu; -class tcpiiu; -class baseNMIU; - -class cacPrivateListOfIO { -private: - tsDLList < class baseNMIU > eventq; - friend class cac; -}; - -class nciu : public cacChannel, public tsDLNode < nciu >, - public chronIntIdRes < nciu >, public cacPrivateListOfIO { -public: - nciu ( class cac &, netiiu &, - cacChannelNotify &, const char *pNameIn ); - void connect ( unsigned nativeType, - unsigned long nativeCount, unsigned sid ); - void connect (); - void disconnect ( netiiu &newiiu ); - bool searchMsg ( unsigned short retrySeqNumber, - unsigned &retryNoForThisChannel ); - void createChannelRequest (); - bool isAttachedToVirtaulCircuit ( const osiSockAddr & ); - bool identifierEquivelence ( unsigned idToMatch ); - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); - void resetRetryCount (); - unsigned getRetrySeqNo () const; - void accessRightsStateChange ( const caAccessRights & ); - ca_uint32_t getSID () const; - ca_uint32_t getCID () const; - netiiu * getPIIU (); - cac & getClient (); - void searchReplySetUp ( netiiu &iiu, unsigned sidIn, - unsigned typeIn, unsigned long countIn ); - void show ( unsigned level ) const; - void connectTimeoutNotify (); - const char *pName () const; - unsigned nameLen () const; - const char * pHostName () const; // deprecated - please do not use - unsigned long nativeElementCount () const; - bool connected () const; - bool previouslyConnected () const; -protected: - ~nciu (); // force pool allocation -private: - cac &cacCtx; - caAccessRights accessRightState; - unsigned count; - char *pNameStr; - netiiu *piiu; - ca_uint32_t sid; // server id - unsigned retry; // search retry number - unsigned short retrySeqNo; // search retry seq number - unsigned short nameLength; // channel name length - unsigned short typeCode; - unsigned f_connected:1; - unsigned f_previousConn:1; // T if connected in the past - unsigned f_claimSent:1; - unsigned f_firstConnectDecrementsOutstandingIO:1; - unsigned f_connectTimeOutSeen:1; - void initiateConnect (); - ioStatus read ( unsigned type, unsigned long count, - cacDataNotify &, ioid * ); - void write ( unsigned type, unsigned long count, - const void *pValue ); - ioStatus write ( unsigned type, unsigned long count, - const void *pValue, cacNotify &, ioid * ); - void subscribe ( unsigned type, unsigned long nElem, - unsigned mask, cacDataNotify ¬ify, ioid * ); - void ioCancel ( const ioid & ); - void ioShow ( const ioid &, unsigned level ) const; - short nativeType () const; - caAccessRights accessRights () const; - unsigned searchAttempts () const; - double beaconPeriod () const; - bool ca_v42_ok () const; - void hostName ( char *pBuf, unsigned bufLength ) const; - void notifyStateChangeFirstConnectInCountOfOutstandingIO (); - static void stringVerify ( const char *pStr, const unsigned count ); - static tsFreeList < class nciu, 1024 > freeList; - static epicsMutex freeListMutex; -}; - -class baseNMIU : public tsDLNode < baseNMIU >, - public chronIntIdRes < baseNMIU > { -public: - baseNMIU ( nciu &chan ); - virtual class netSubscription * isSubscription (); - virtual void destroy ( class cacRecycle & ) = 0; // only called by cac - virtual void completion () = 0; - virtual void exception ( int status, const char *pContext ) = 0; - virtual void completion ( unsigned type, - unsigned long count, const void *pData ) = 0; - virtual void exception ( int status, - const char *pContext, unsigned type, unsigned long count ) = 0; - void show ( unsigned level ) const; - ca_uint32_t getID () const; - nciu & channel () const; -protected: - virtual ~baseNMIU () = 0; -// -// perhpas we should not store the channel here and instead fetch it out of the -// notify -// - nciu &chan; -}; - -class netSubscription : public baseNMIU { -public: - static netSubscription * factory ( - tsFreeList < class netSubscription, 1024 > &, - nciu &chan, unsigned type, unsigned long count, - unsigned mask, cacDataNotify ¬ify ); - void show ( unsigned level ) const; - unsigned long getCount () const; - unsigned getType () const; - unsigned getMask () const; - void destroy ( class cacRecycle & ); - void completion (); - void exception ( int status, const char *pContext ); - void completion ( unsigned type, - unsigned long count, const void *pData ); - void exception ( int status, - const char *pContext, unsigned type, unsigned long count ); -protected: - ~netSubscription (); -private: - const unsigned long count; - cacDataNotify ¬ify; - const unsigned type; - const unsigned mask; - netSubscription ( nciu &chan, unsigned type, unsigned long count, - unsigned mask, cacDataNotify ¬ify ); - class netSubscription * isSubscription (); - void * operator new ( size_t, - tsFreeList < class netSubscription, 1024 > & ); -# if ! defined ( NO_PLACEMENT_DELETE ) - void operator delete ( void *, size_t, - tsFreeList < class netSubscription, 1024 > & ); -# endif -}; - -class netReadNotifyIO : public baseNMIU { -public: - static netReadNotifyIO * factory ( - tsFreeList < class netReadNotifyIO, 1024 > &, - nciu &chan, cacDataNotify ¬ify ); - void show ( unsigned level ) const; - void destroy ( class cacRecycle & ); - void completion (); - void exception ( int status, const char *pContext ); - void completion ( unsigned type, - unsigned long count, const void *pData ); - void exception ( int status, - const char *pContext, unsigned type, unsigned long count ); -protected: - ~netReadNotifyIO (); -private: - cacDataNotify ¬ify; - netReadNotifyIO ( nciu &chan, cacDataNotify ¬ify ); - void * operator new ( size_t, - tsFreeList < class netReadNotifyIO, 1024 > & ); -# if ! defined ( NO_PLACEMENT_DELETE ) - void operator delete ( void *, size_t, - tsFreeList < class netReadNotifyIO, 1024 > & ); -# endif -}; - -class netWriteNotifyIO : public baseNMIU { -public: - static netWriteNotifyIO * factory ( - tsFreeList < class netWriteNotifyIO, 1024 > &, - nciu &chan, cacNotify ¬ify ); - void show ( unsigned level ) const; - void destroy ( class cacRecycle & ); - void completion (); - void exception ( int status, const char *pContext ); - void completion ( unsigned type, - unsigned long count, const void *pData ); - void exception ( int status, - const char *pContext, unsigned type, unsigned long count ); -protected: - ~netWriteNotifyIO (); -private: - cacNotify ¬ify; - netWriteNotifyIO ( nciu &chan, cacNotify ¬ify ); - void * operator new ( size_t, - tsFreeList < class netWriteNotifyIO, 1024 > & ); -# if ! defined ( NO_PLACEMENT_DELETE ) - void operator delete ( void *, size_t, - tsFreeList < class netWriteNotifyIO, 1024 > & ); -# endif -}; - /* * these control the duration and period of name resolution * broadcasts @@ -455,350 +82,6 @@ const static double CA_CONN_VERIFY_PERIOD = 30.0; /* (sec) how often to request */ static const unsigned contiguousMsgCountWhichTriggersFlowControl = 10u; -enum iiu_conn_state {iiu_connecting, iiu_connected, iiu_disconnected}; - -class netiiu { -public: - netiiu ( class cac * ); - virtual ~netiiu (); - void show ( unsigned level ) const; - unsigned channelCount () const; - void disconnectAllChan ( netiiu & newiiu ); - void connectTimeoutNotify (); - bool searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisChannel ); - void resetChannelRetryCounts (); - void attachChannel ( nciu &chan ); - void detachChannel ( nciu &chan ); - virtual void hostName (char *pBuf, unsigned bufLength) const; - virtual const char * pHostName () const; // deprecated - please do not use - virtual bool isVirtaulCircuit ( const char *pChannelName, const osiSockAddr &addr ) const; - virtual bool ca_v42_ok () const; - virtual bool ca_v41_ok () const; - virtual bool pushDatagramMsg ( const caHdr &hdr, const void *pExt, ca_uint16_t extsize); - virtual void writeRequest ( nciu &, unsigned type, unsigned nElem, const void *pValue ); - virtual void writeNotifyRequest ( nciu &, netWriteNotifyIO &, unsigned type, unsigned nElem, const void *pValue ); - virtual void readNotifyRequest ( nciu &, netReadNotifyIO &, unsigned type, unsigned nElem ); - virtual void createChannelRequest ( nciu & ); - virtual void connectAllIO ( nciu &chan ); - virtual void disconnectAllIO ( nciu &chan ); - virtual void clearChannelRequest ( nciu & ); - virtual void subscriptionRequest ( nciu &, netSubscription &subscr ); - virtual void subscriptionCancelRequest ( nciu &, netSubscription &subscr ); - virtual double beaconPeriod () const; - virtual void flushRequest (); - virtual bool flushBlockThreshold () const; - virtual void flushRequestIfAboveEarlyThreshold (); - virtual void blockUntilSendBacklogIsReasonable ( epicsMutex & ); -protected: - cac * pCAC () const; -private: - tsDLList < nciu > channelList; - class cac *pClientCtx; - virtual void lastChannelDetachNotify (); -}; - -class limboiiu : public netiiu { -public: - limboiiu (); -}; - -extern limboiiu limboIIU; - -class udpiiu; - -class searchTimer : private epicsTimerNotify { -public: - searchTimer ( udpiiu &iiu, epicsTimerQueue &queue, epicsMutex & ); - virtual ~searchTimer (); - void notifySearchResponse ( unsigned short retrySeqNo ); - void resetPeriod ( double delayToNextTry ); - void show ( unsigned level ) const; -private: - epicsTimer &timer; - epicsMutex &mutex; - udpiiu &iiu; - unsigned framesPerTry; /* # of UDP frames per search try */ - unsigned framesPerTryCongestThresh; /* one half N tries w congest */ - unsigned minRetry; /* min retry number so far */ - unsigned retry; - unsigned searchTriesWithinThisPass; /* num search tries within this pass through the list */ - unsigned searchResponsesWithinThisPass; /* num search resp within this pass through the list */ - unsigned short retrySeqNo; /* search retry seq number */ - unsigned short retrySeqAtPassBegin; /* search retry seq number at beg of pass through list */ - double period; /* period between tries */ - expireStatus expire (); - void setRetryInterval (unsigned retryNo); -}; - -class repeaterSubscribeTimer : private epicsTimerNotify { -public: - repeaterSubscribeTimer (udpiiu &iiu, epicsTimerQueue &queue); - virtual ~repeaterSubscribeTimer (); - void confirmNotify (); - void show (unsigned level) const; -private: - epicsTimer &timer; - udpiiu &iiu; - unsigned attempts; - bool registered; - bool once; - expireStatus expire (); -}; - -extern "C" void cacRecvThreadUDP (void *pParam); - -epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repeaterPort ); -epicsShareFunc void epicsShareAPI caRepeaterRegistrationMessage ( SOCKET sock, unsigned repeaterPort, unsigned attemptNumber ); - -class udpiiu : public netiiu { -public: - udpiiu ( cac &cac ); - virtual ~udpiiu (); - void shutdown (); - void recvMsg (); - void postMsg ( const osiSockAddr &net_addr, - char *pInBuf, unsigned long blockSize ); - void repeaterRegistrationMessage ( unsigned attemptNumber ); - void datagramFlush (); - unsigned getPort () const; - void show ( unsigned level ) const; - bool isCurrentThread () const; - - // exceptions - class noSocket {}; - class noMemory {}; - - void fdCreateNotify ( CAFDHANDLER *func, void *pArg ); - void fdDestroyNotify ( CAFDHANDLER *func, void *pArg ); -private: - char xmitBuf [MAX_UDP_SEND]; - char recvBuf [MAX_UDP_RECV]; - ELLLIST dest; - epicsThreadId recvThreadId; - epicsEventId recvThreadExitSignal; - unsigned nBytesInXmitBuf; - SOCKET sock; - unsigned short repeaterPort; - unsigned short serverPort; - unsigned short localPort; - bool shutdownCmd; - bool sockCloseCompleted; - - bool pushDatagramMsg ( const caHdr &msg, const void *pExt, ca_uint16_t extsize ); - - typedef bool (udpiiu::*pProtoStubUDP) ( const caHdr &, const osiSockAddr & ); - - // UDP protocol dispatch table - static const pProtoStubUDP udpJumpTableCAC[]; - - // UDP protocol stubs - bool noopAction ( const caHdr &, const osiSockAddr & ); - bool badUDPRespAction ( const caHdr &msg, const osiSockAddr &netAddr ); - bool searchRespAction ( const caHdr &msg, const osiSockAddr &net_addr ); - bool exceptionRespAction ( const caHdr &msg, const osiSockAddr &net_addr ); - bool beaconAction ( const caHdr &msg, const osiSockAddr &net_addr ); - bool notHereRespAction ( const caHdr &msg, const osiSockAddr &net_addr ); - bool repeaterAckAction ( const caHdr &msg, const osiSockAddr &net_addr ); - - friend void cacRecvThreadUDP ( void *pParam ); -}; - -class tcpRecvWatchdog : private epicsTimerNotify { -public: - tcpRecvWatchdog ( tcpiiu &, double periodIn, epicsTimerQueue & queueIn ); - virtual ~tcpRecvWatchdog (); - void rescheduleRecvTimer (); - void messageArrivalNotify (); - void beaconArrivalNotify (); - void beaconAnomalyNotify (); - void connectNotify (); - void cancel (); - void show ( unsigned level ) const; -private: - const double period; - epicsTimer &timer; - tcpiiu &iiu; - bool responsePending; - bool beaconAnomaly; - expireStatus expire (); -}; - -class tcpSendWatchdog : private epicsTimerNotify { -public: - tcpSendWatchdog ( tcpiiu &, double periodIn, epicsTimerQueue & queueIn ); - virtual ~tcpSendWatchdog (); - void start (); - void cancel (); -private: - const double period; - epicsTimer &timer; - tcpiiu &iiu; - expireStatus expire (); -}; - -class msgForMultiplyDefinedPV : public ipAddrToAsciiAsynchronous { -public: - msgForMultiplyDefinedPV ( - cac &cacRefIn, const char *pChannelName, const char *pAcc, - const osiSockAddr &rej ); - msgForMultiplyDefinedPV ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine ); - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); -private: - void ioCompletionNotify ( const char *pHostName ); - char acc[64]; - char channel[64]; - cac &cacRef; - - static tsFreeList < class msgForMultiplyDefinedPV, 16 > freeList; - static epicsMutex freeListMutex; -}; - -class hostNameCache : public ipAddrToAsciiAsynchronous { -public: - hostNameCache ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine ); - void destroy (); - void ioCompletionNotify ( const char *pHostName ); - void hostName ( char *pBuf, unsigned bufLength ) const; - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); -protected: - ~hostNameCache (); -private: - bool ioComplete; - char hostNameBuf [128]; - static tsFreeList < class hostNameCache, 16 > freeList; - static epicsMutex freeListMutex; -}; - -extern "C" void cacSendThreadTCP ( void *pParam ); -extern "C" void cacRecvThreadTCP ( void *pParam ); - -class tcpiiu : - public netiiu, public tsDLNode < tcpiiu >, - private wireSendAdapter, private wireRecvAdapter { -public: - tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue ); - ~tcpiiu (); - bool initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, - class bhe &bhe, ipAddrToAsciiEngine &engineIn ); - void connect (); - void processIncoming (); - void destroy (); - void cleanShutdown (); - void forcedShutdown (); - void beaconAnomalyNotify (); - void beaconArrivalNotify (); - - bool fullyConstructed () const; - void flushRequest (); - bool flushBlockThreshold () const; - void flushRequestIfAboveEarlyThreshold (); - void blockUntilSendBacklogIsReasonable ( epicsMutex & ); - virtual void show ( unsigned level ) const; - bool setEchoRequestPending (); - - bool ca_v41_ok () const; - bool ca_v42_ok () const; - bool ca_v44_ok () const; - - void hostName ( char *pBuf, unsigned bufLength ) const; - const char * pHostName () const; // deprecated - please do not use - bool isVirtaulCircuit ( const char *pChannelName, const osiSockAddr &addr ) const; - bool alive () const; - double beaconPeriod () const; - bhe * getBHE () const; - - void fdCreateNotify ( epicsMutex &mutex, CAFDHANDLER *func, void *pArg ); - void fdDestroyNotify ( CAFDHANDLER *func, void *pArg ); -private: - tcpRecvWatchdog recvDog; - tcpSendWatchdog sendDog; - comQueSend sendQue; - comQueRecv recvQue; - osiSockAddr addr; - hostNameCache *pHostNameCache; - caHdr curMsg; - unsigned long curDataMax; - class bhe *pBHE; - char *pCurData; - unsigned minorProtocolVersion; - iiu_conn_state state; - epicsEventId sendThreadFlushSignal; - epicsEventId recvThreadRingBufferSpaceAvailableSignal; - epicsEventId sendThreadExitSignal; - epicsEventId recvThreadExitSignal; - epicsEventId flushBlockSignal; - SOCKET sock; - unsigned contigRecvMsgCount; - unsigned blockingForFlush; - bool fullyConstructedFlag; - bool busyStateDetected; // only modified by the recv thread - bool flowControlActive; // only modified by the send process thread - bool echoRequestPending; - bool msgHeaderAvailable; - bool sockCloseCompleted; - bool fdRegCallbackNeeded; - bool earlyFlush; - - unsigned sendBytes ( const void *pBuf, unsigned nBytesInBuf ); - unsigned recvBytes ( void *pBuf, unsigned nBytesInBuf ); - - friend void cacSendThreadTCP ( void *pParam ); - friend void cacRecvThreadTCP ( void *pParam ); - - void lastChannelDetachNotify (); - - // send protocol stubs - void echoRequest (); - void noopRequest (); - void disableFlowControlRequest (); - void enableFlowControlRequest (); - void hostNameSetRequest (); - void userNameSetRequest (); - void writeRequest ( nciu &, unsigned type, unsigned nElem, const void *pValue ); - void writeNotifyRequest ( nciu &, netWriteNotifyIO &, unsigned type, unsigned nElem, const void *pValue ); - void readNotifyRequest ( nciu &, netReadNotifyIO &, unsigned type, unsigned nElem ); - void createChannelRequest ( nciu & ); - void clearChannelRequest ( nciu & ); - void subscriptionRequest ( nciu &, netSubscription &subscr ); - void subscriptionCancelRequest ( nciu &, netSubscription &subscr ); - - bool flush (); // only to be called by the send thread -}; - -class inetAddrID { -public: - inetAddrID ( const struct sockaddr_in &addrIn ); - bool operator == ( const inetAddrID & ) const; - resTableIndex hash ( unsigned nBitsHashIndex ) const; - static unsigned maxIndexBitWidth (); - static unsigned minIndexBitWidth (); -private: - const struct sockaddr_in addr; -}; - -class bhe : public tsSLNode < bhe >, public inetAddrID { -public: - epicsShareFunc bhe ( const epicsTime &initialTimeStamp, const inetAddrID &addr ); - tcpiiu *getIIU () const; - void bindToIIU ( tcpiiu & ); - epicsShareFunc void destroy (); - epicsShareFunc bool updatePeriod ( epicsTime programBeginTime ); - epicsShareFunc double period () const; - epicsShareFunc void show ( unsigned level) const; - epicsShareFunc void * operator new ( size_t size ); - epicsShareFunc void operator delete ( void *pCadaver, size_t size ); -protected: - epicsShareFunc ~bhe (); // force allocation from freeList -private: - tcpiiu *piiu; - epicsTime timeStamp; - double averagePeriod; - static tsFreeList < class bhe, 1024 > freeList; - static epicsMutex freeListMutex; -}; - class caErrorCode { public: caErrorCode ( int status ) : code ( status ) {}; @@ -806,376 +89,10 @@ private: int code; }; -class recvProcessThread : public epicsThreadRunable { -public: - recvProcessThread ( class cac *pcacIn ); - virtual ~recvProcessThread (); - void run (); - void enable (); - void disable (); - void signalActivity (); - bool isCurrentThread () const; - void show ( unsigned level ) const; -private: - // - // The additional complexity associated with - // "processingDone" event and the "processing" flag - // avoid complex locking hierarchy constraints - // and therefore reduces the chance of creating - // a deadlock window during code maintenance. - // - epicsThread thread; - epicsEvent recvActivity; - class cac *pcac; - epicsEvent exit; - epicsEvent processingDone; - mutable epicsMutex mutex; - unsigned enableRefCount; - unsigned blockingForCompletion; - bool processing; - bool shutDown; -}; - -class sendProcessThread : public epicsThreadRunable { -public: - sendProcessThread ( class cac &cacIn ); - virtual ~sendProcessThread (); - void run (); - void signalActivity (); - epicsThread thread; -private: - epicsEvent sendActivity; - class cac &cacRef; - epicsEvent exit; - bool shutDown; -}; - -static const unsigned CASG_MAGIC = 0xFAB4CAFE; - -// used to control access to CASG's recycle routines which -// should only be indirectly invoked by CASG when its lock -// is applied -class casgRecycle { -public: - virtual void recycleSyncGroupWriteNotify ( class syncGroupWriteNotify &io ) = 0; - virtual void recycleSyncGroupReadNotify ( class syncGroupReadNotify &io ) = 0; -}; - -class syncGroupNotify : public tsDLNode < syncGroupNotify > { -public: - syncGroupNotify ( struct CASG &sgIn, chid ); - virtual void destroy ( casgRecycle & ) = 0; - void show ( unsigned level ) const; -protected: - chid chan; - struct CASG &sg; - const unsigned magic; - cacChannel::ioid id; - bool idIsValid; - virtual ~syncGroupNotify (); -}; - -class syncGroupReadNotify : public syncGroupNotify, public cacDataNotify { -public: - static syncGroupReadNotify * factory ( - tsFreeList < class syncGroupReadNotify, 128 > &, - struct CASG &, chid, unsigned type, - unsigned long count, void *pValueIn ); - void destroy ( casgRecycle & ); - void show ( unsigned level ) const; -protected: - virtual ~syncGroupReadNotify (); -private: - void *pValue; - syncGroupReadNotify ( struct CASG &sgIn, chid, - unsigned type, unsigned long count, void *pValueIn ); - void * operator new ( size_t, - tsFreeList < class syncGroupReadNotify, 128 > & ); -# if ! defined ( NO_PLACEMENT_DELETE ) - void operator delete ( void *, size_t, - tsFreeList < class syncGroupReadNotify, 128 > & ); -# endif - void completion ( - unsigned type, unsigned long count, const void *pData ); - void exception ( - int status, const char *pContext, unsigned type, unsigned long count ); -}; - -class syncGroupWriteNotify : public syncGroupNotify, public cacNotify { -public: - static syncGroupWriteNotify * factory ( - tsFreeList < class syncGroupWriteNotify, 128 > &, - struct CASG &, chid, unsigned type, - unsigned long count, const void *pValueIn ); - void destroy ( casgRecycle & ); - void show ( unsigned level ) const; -protected: - virtual ~syncGroupWriteNotify (); // allocate only from pool -private: - void *pValue; - syncGroupWriteNotify ( struct CASG &, chid, unsigned type, - unsigned long count, const void *pValueIn ); - void * operator new ( size_t, - tsFreeList < class syncGroupWriteNotify, 128 > & ); -# if ! defined ( NO_PLACEMENT_DELETE ) - void operator delete ( void *, size_t, - tsFreeList < class syncGroupWriteNotify, 128 > & ); -# endif - void completion (); - void exception (int status, const char *pContext ); -}; - -struct CASG : public chronIntIdRes < CASG >, private casgRecycle { -public: - CASG (cac &cacIn); - bool ioComplete () const; - void destroy (); - bool verify () const; - int block ( double timeout ); - void reset (); - void show ( unsigned level ) const; - int get ( chid pChan, unsigned type, unsigned long count, void *pValue ); - int put ( chid pChan, unsigned type, unsigned long count, const void *pValue ); - void destroyIO ( syncGroupNotify & ); - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); -protected: - virtual ~CASG (); -private: - tsDLList < syncGroupNotify > ioList; - epicsMutex mutable mutex; - epicsEvent sem; - cac &client; - unsigned magic; - tsFreeList < class syncGroupReadNotify, 128 > freeListReadOP; - tsFreeList < class syncGroupWriteNotify, 128 > freeListWriteOP; - void recycleSyncGroupWriteNotify ( syncGroupWriteNotify &io ); - void recycleSyncGroupReadNotify ( syncGroupReadNotify &io ); - static tsFreeList < struct CASG, 128 > freeList; - static epicsMutex freeListMutex; -}; - -class ioCounterNet { -public: - ioCounterNet (); - void increment (); - void decrement (); - void decrement ( unsigned seqNumber ); - unsigned sequenceNumber () const; - unsigned currentCount () const; - void cleanUp (); - void show ( unsigned level ) const; - void waitForCompletion ( double delaySec ); -private: - unsigned pndrecvcnt; - unsigned readSeq; - epicsMutex mutex; - epicsEvent ioDone; -}; - -// used to control access to cac's recycle routines which -// should only be indirectly invoked by CAC when its lock -// is applied -class cacRecycle { -public: - virtual void recycleReadNotifyIO ( netReadNotifyIO &io ) = 0; - virtual void recycleWriteNotifyIO ( netWriteNotifyIO &io ) = 0; - virtual void recycleSubscription ( netSubscription &io ) = 0; -}; - -template < class T > -class autoPtrRecycle { -public: - autoPtrRecycle ( cacRecycle &, T * ); - ~autoPtrRecycle (); - T & operator * () const; - T * operator -> () const; - T * get () const; - T * release (); -private: - T *p; - cacRecycle &r; -}; - -class cac : public caClient, private cacRecycle -{ -public: - cac ( bool enablePreemptiveCallback = false ); - virtual ~cac (); - - // beacon management - void beaconNotify ( const inetAddrID &addr ); - void repeaterSubscribeConfirmNotify (); - - // IIU routines - void signalRecvActivity (); - void processRecvBacklog (); - - // outstanding IO count management routines - void incrementOutstandingIO (); - void decrementOutstandingIO (); - void decrementOutstandingIO ( unsigned sequenceNo ); - unsigned sequenceNumberOfOutstandingIO () const; - bool ioComplete () const; - - // IO management - void flushRequest (); - int pendIO ( const double &timeout ); - int pendEvent ( const double &timeout ); - void connectAllIO ( nciu &chan ); - void disconnectAllIO ( nciu &chan ); - void destroyAllIO ( nciu &chan ); - void executeResponse ( tcpiiu &, caHdr &, char *pMshBody ); - void ioCancel ( nciu &chan, const cacChannel::ioid &id ); - void ioShow ( const cacChannel::ioid &id, unsigned level ) const; - - // exception routines - void exception ( int status, const char *pContext, - const char *pFileName, unsigned lineNo ); - void exception ( int status, const char *pContext, - unsigned type, unsigned long count, - const char *pFileName, unsigned lineNo ); - void changeExceptionEvent ( caExceptionHandler *pfunc, void *arg ); - void genLocalExcepWFL ( long stat, const char *ctx, const char *pFile, unsigned lineNo ); - - // channel routines - bool connectChannel ( unsigned id ); - void installNetworkChannel ( nciu &, netiiu *&piiu ); - bool lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid, - unsigned typeCode, unsigned long count, unsigned minorVersionNumber, - const osiSockAddr & ); - void uninstallChannel ( nciu & ); - cacChannel & createChannel ( const char *name_str, cacChannelNotify &chan ); - void registerService ( cacService &service ); - - // IO request stubs - void writeRequest ( nciu &, unsigned type, - unsigned nElem, const void *pValue ); - cacChannel::ioid writeNotifyRequest ( nciu &, unsigned type, - unsigned nElem, const void *pValue, cacNotify & ); - cacChannel::ioid readNotifyRequest ( nciu &, unsigned type, - unsigned nElem, cacDataNotify & ); - cacChannel::ioid subscriptionRequest ( nciu &, unsigned type, - unsigned long nElem, unsigned mask, cacDataNotify & ); - - // sync group routines - CASG * lookupCASG ( unsigned id ); - void installCASG ( CASG & ); - void uninstallCASG ( CASG & ); - - // fd call back registration - void registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg ); - - // callback preemption control - void enableCallbackPreemption (); - void disableCallbackPreemption (); - - // diagnostics - unsigned connectionCount () const; - void show ( unsigned level ) const; - int printf ( const char *pformat, ... ); - int vPrintf ( const char *pformat, va_list args ); - void replaceErrLogHandler ( caPrintfFunc *ca_printf_func ); - void ipAddrToAsciiAsynchronousRequestInstall ( ipAddrToAsciiAsynchronous & request ); - - // misc - const char * userNamePointer () const; - unsigned getInitializingThreadsPriority () const; - - epicsMutex & mutexRef (); - -private: - ioCounterNet ioCounter; - ipAddrToAsciiEngine ipToAEngine; - cacServiceList services; - tsDLList iiuList; - chronIntIdResTable - < nciu > chanTable; - chronIntIdResTable - < baseNMIU > ioTable; - chronIntIdResTable - < CASG > sgTable; - resTable - < bhe, inetAddrID > beaconTable; - tsFreeList - < class netReadNotifyIO, 1024 > - freeListReadNotifyIO; - tsFreeList - < class netWriteNotifyIO, 1024 > - freeListWriteNotifyIO; - tsFreeList - < class netSubscription, 1024 > - freeListSubscription; - epicsTime programBeginTime; - double connTMO; - mutable epicsMutex mutex; - epicsEvent notifyCompletionEvent; - epicsTimerQueueActive *pTimerQueue; - caExceptionHandler *ca_exception_func; - void *ca_exception_arg; - caPrintfFunc *pVPrintfFunc; - char *pUserName; - recvProcessThread *pRecvProcThread; - CAFDHANDLER *fdRegFunc; - void *fdRegArg; - udpiiu *pudpiiu; - searchTimer *pSearchTmr; - repeaterSubscribeTimer *pRepeaterSubscribeTmr; - unsigned ioNotifyInProgressId; - unsigned initializingThreadsPriority; - unsigned threadsBlockingOnNotifyCompletion; - bool enablePreemptiveCallback; - bool ioInProgress; - bool setupUDP (); - void flushIfRequired ( nciu & ); // lock must be applied - void recycleReadNotifyIO ( netReadNotifyIO &io ); - void recycleWriteNotifyIO ( netWriteNotifyIO &io ); - void recycleSubscription ( netSubscription &io ); - - bool ioCompletionNotify ( unsigned id, unsigned type, - unsigned long count, const void *pData ); - bool ioExceptionNotify ( unsigned id, - int status, const char *pContext ); - bool ioExceptionNotify ( unsigned id, int status, - const char *pContext, unsigned type, unsigned long count ); - bool ioCompletionNotifyAndDestroy ( unsigned id ); - bool ioCompletionNotifyAndDestroy ( unsigned id, - unsigned type, unsigned long count, const void *pData ); - bool ioExceptionNotifyAndDestroy ( unsigned id, - int status, const char *pContext ); - bool ioExceptionNotifyAndDestroy ( unsigned id, - int status, const char *pContext, unsigned type, unsigned long count ); - - // recv protocol stubs - bool noopAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool echoRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool writeNotifyRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool readNotifyRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool eventRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool readRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool clearChannelRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool exceptionRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool accessRightsRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool claimCIURespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool verifyAndDisconnectChan ( tcpiiu &, const caHdr &, void *pMsgBdy ); - bool badTCPRespAction ( tcpiiu &, const caHdr &, void *pMsgBdy ); - typedef bool ( cac::*pProtoStubTCP ) ( - tcpiiu &, const caHdr &, void *pMsgBdy ); - static const pProtoStubTCP tcpJumpTableCAC []; -}; - /* * CA internal functions */ -int ca_printf ( const char *pformat, ... ); -int ca_vPrintf ( const char *pformat, va_list args ); -epicsShareFunc void epicsShareAPI ca_repeater ( void ); - #define genLocalExcep( CAC, STAT, PCTX ) \ -(CAC).genLocalExcepWFL ( STAT, PCTX, __FILE__, __LINE__ ) - -int fetchClientContext ( cac **ppcac ); -extern "C" void caRepeaterThread ( void *pDummy ); -extern "C" void ca_default_exception_handler ( struct exception_handler_args args ); +(CAC).exception ( STAT, PCTX, __FILE__, __LINE__ ) #endif // ifdef INCiocinfh diff --git a/src/ca/limboiiu.cpp b/src/ca/limboiiu.cpp index 1f2081ddc..e62839469 100644 --- a/src/ca/limboiiu.cpp +++ b/src/ca/limboiiu.cpp @@ -15,7 +15,10 @@ * 505 665 1831 */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "netiiu.h" limboiiu limboIIU; diff --git a/src/ca/localHostName.h b/src/ca/localHostName.h index b679aaa5a..70f4e697e 100644 --- a/src/ca/localHostName.h +++ b/src/ca/localHostName.h @@ -10,6 +10,11 @@ * Author: Jeff Hill */ +#ifndef localHostNameh +#define localHostNameh + +#include + class localHostName { public: localHostName (); @@ -43,3 +48,6 @@ inline const char * localHostName::pointer () const return this->cache; } +#endif // ifndef localHostNameh + + diff --git a/src/ca/msgForMultiplyDefinedPV.cpp b/src/ca/msgForMultiplyDefinedPV.cpp index fa6e6fc39..844e0b10f 100644 --- a/src/ca/msgForMultiplyDefinedPV.cpp +++ b/src/ca/msgForMultiplyDefinedPV.cpp @@ -15,8 +15,15 @@ * 505 665 1831 */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "msgForMultiplyDefinedPV_IL.h" +#include "msgForMultiplyDefinedPV.h" +#include "cac.h" + +#define epicsExportSharedSymbols +#include "caerr.h" // for ECA_DBLCHNL +#undef epicsExportSharedSymbols tsFreeList < class msgForMultiplyDefinedPV, 16 > msgForMultiplyDefinedPV::freeList; epicsMutex msgForMultiplyDefinedPV::freeListMutex; diff --git a/src/ca/msgForMultiplyDefinedPV.h b/src/ca/msgForMultiplyDefinedPV.h new file mode 100644 index 000000000..348511baa --- /dev/null +++ b/src/ca/msgForMultiplyDefinedPV.h @@ -0,0 +1,57 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef msgForMultiplyDefinedPVh +#define msgForMultiplyDefinedPVh + +#include "ipAddrToAsciiAsynchronous.h" +#include "tsFreeList.h" +#include "epicsMutex.h" + +class cac; + +class msgForMultiplyDefinedPV : public ipAddrToAsciiAsynchronous { +public: + msgForMultiplyDefinedPV ( + cac &cacRefIn, const char *pChannelName, const char *pAcc, + const osiSockAddr &rej ); + msgForMultiplyDefinedPV ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine ); + void * operator new ( size_t size ); + void operator delete ( void *pCadaver, size_t size ); +private: + void ioCompletionNotify ( const char *pHostName ); + char acc[64]; + char channel[64]; + cac &cacRef; + static tsFreeList < class msgForMultiplyDefinedPV, 16 > freeList; + static epicsMutex freeListMutex; +}; + +inline void * msgForMultiplyDefinedPV::operator new ( size_t size ) +{ + epicsAutoMutex locker ( msgForMultiplyDefinedPV::freeListMutex ); + return msgForMultiplyDefinedPV::freeList.allocate ( size ); +} + +inline void msgForMultiplyDefinedPV::operator delete ( void *pCadaver, size_t size ) +{ + epicsAutoMutex locker ( msgForMultiplyDefinedPV::freeListMutex ); + msgForMultiplyDefinedPV::freeList.release ( pCadaver, size ); +} + +#endif // ifdef msgForMultiplyDefinedPVh + diff --git a/src/ca/msgForMultiplyDefinedPV_IL.h b/src/ca/msgForMultiplyDefinedPV_IL.h deleted file mode 100644 index e09d3c6ae..000000000 --- a/src/ca/msgForMultiplyDefinedPV_IL.h +++ /dev/null @@ -1,28 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -void * msgForMultiplyDefinedPV::operator new ( size_t size ) -{ - epicsAutoMutex locker ( msgForMultiplyDefinedPV::freeListMutex ); - return msgForMultiplyDefinedPV::freeList.allocate ( size ); -} - -void msgForMultiplyDefinedPV::operator delete ( void *pCadaver, size_t size ) -{ - epicsAutoMutex locker ( msgForMultiplyDefinedPV::freeListMutex ); - msgForMultiplyDefinedPV::freeList.release ( pCadaver, size ); -} diff --git a/src/ca/nciu.cpp b/src/ca/nciu.cpp index ecffc8177..bac541c00 100644 --- a/src/ca/nciu.cpp +++ b/src/ca/nciu.cpp @@ -21,13 +21,17 @@ #include -#include "iocinf.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -#include "nciu_IL.h" -#include "netReadNotifyIO_IL.h" -#include "netWriteNotifyIO_IL.h" -#include "netSubscription_IL.h" -#include "cac_IL.h" +#include "iocinf.h" +#include "netIO.h" +#include "cac.h" + +#define epicsExportSharedSymbols +#include "udpiiu.h" +#include "cadef.h" // for ECA_STRTOBIG and TYPENOTCONN etc +#include "db_access.h" // for INVALID_DB_REQ +#undef epicsExportSharedSymbols tsFreeList < class nciu, 1024 > nciu::freeList; epicsMutex nciu::freeListMutex; @@ -82,14 +86,14 @@ void nciu::connect ( unsigned nativeType, bool v41Ok; if ( ! this->f_claimSent ) { - ca_printf ( + this->cacCtx.printf ( "CAC: Ignored conn resp to chan lacking virtual circuit CID=%u SID=%u?\n", this->getId (), sidIn ); return; } if ( this->f_connected ) { - ca_printf ( + this->cacCtx.printf ( "CAC: Ignored conn resp to conn chan CID=%u SID=%u?\n", this->getId (), sidIn ); return; @@ -127,7 +131,7 @@ void nciu::connect ( unsigned nativeType, // resubscribe for monitors from this channel this->cacCtx.connectAllIO ( *this ); - this->notify().connectNotify ( *this ); + this->notify().connectNotify (); /* * if less than v4.1 then the server will never @@ -136,7 +140,7 @@ void nciu::connect ( unsigned nativeType, * their call back here */ if ( ! v41Ok ) { - this->notify().accessRightsNotify ( *this, this->accessRightState ); + this->notify().accessRightsNotify ( this->accessRightState ); } } @@ -167,8 +171,8 @@ void nciu::disconnect ( netiiu &newiiu ) /* * look for events that have an event cancel in progress */ - this->notify().disconnectNotify ( *this ); - this->notify().accessRightsNotify ( *this, this->accessRightState ); + this->notify().disconnectNotify (); + this->notify().accessRightsNotify ( this->accessRightState ); } this->resetRetryCount (); @@ -223,7 +227,7 @@ void nciu::createChannelRequest () } cacChannel::ioStatus nciu::read ( unsigned type, unsigned long countIn, - cacDataNotify ¬ify, ioid *pId ) + cacReadNotify ¬ify, ioid *pId ) { // // fail out if their arguments are invalid @@ -284,7 +288,7 @@ void nciu::write ( unsigned type, } cacChannel::ioStatus nciu::write ( unsigned type, unsigned long countIn, - const void *pValue, cacNotify ¬ify, ioid *pId ) + const void *pValue, cacWriteNotify ¬ify, ioid *pId ) { if ( ! this->accessRightState.writePermit() ) { throw noWriteAccess(); @@ -306,7 +310,7 @@ cacChannel::ioStatus nciu::write ( unsigned type, unsigned long countIn, } void nciu::subscribe ( unsigned type, unsigned long nElem, - unsigned mask, cacDataNotify ¬ify, ioid *pId ) + unsigned mask, cacStateNotify ¬ify, ioid *pId ) { if ( INVALID_DB_REQ(type) ) { throw badType(); @@ -434,32 +438,32 @@ 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", + ::printf ( "Channel \"%s\", connected to server %s", this->pNameStr, hostNameTmp ); if ( level > 1u ) { int tmpTypeCode = static_cast < int > ( this->typeCode ); - printf ( ", native type %s, native element count %u", + ::printf ( ", native type %s, native element count %u", dbf_type_to_text ( tmpTypeCode ), this->count ); - printf ( ", %sread access, %swrite access", + ::printf ( ", %sread access, %swrite access", this->accessRightState.readPermit() ? "" : "no ", this->accessRightState.writePermit() ? "" : "no "); } - printf ( "\n" ); + ::printf ( "\n" ); } else if ( this->f_previousConn ) { - printf ( "Channel \"%s\" (previously connected to a server)\n", this->pNameStr ); + ::printf ( "Channel \"%s\" (previously connected to a server)\n", this->pNameStr ); } else { - printf ( "Channel \"%s\" (unable to locate server)\n", this->pNameStr ); + ::printf ( "Channel \"%s\" (unable to locate server)\n", this->pNameStr ); } if ( level > 2u ) { - printf ( "\tnetwork IO pointer = %p\n", + ::printf ( "\tnetwork IO pointer = %p\n", static_cast ( this->piiu ) ); - printf ( "\tserver identifier %u\n", this->sid ); - printf ( "\tsearch retry number=%u, search retry sequence number=%u\n", + ::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 ( "\tname length=%u\n", this->nameLength ); } } diff --git a/src/ca/nciu.h b/src/ca/nciu.h new file mode 100644 index 000000000..61374c356 --- /dev/null +++ b/src/ca/nciu.h @@ -0,0 +1,197 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef nciuh +#define nciuh + +#include "resourceLib.h" +#include "tsDLList.h" +#include "tsFreeList.h" +#include "epicsMutex.h" + +#include "caProto.h" + +#define epicsExportSharedSymbols +#include "cacIO.h" +#undef epicsExportSharedSymbols + +class cac; +class netiiu; + +class cacPrivateListOfIO { +private: + tsDLList < class baseNMIU > eventq; + friend class cac; +}; + +class nciu : public cacChannel, public tsDLNode < nciu >, + public chronIntIdRes < nciu >, public cacPrivateListOfIO { +public: + nciu ( cac &, netiiu &, + cacChannelNotify &, const char *pNameIn ); + void connect ( unsigned nativeType, + unsigned long nativeCount, unsigned sid ); + void connect (); + void disconnect ( netiiu &newiiu ); + bool searchMsg ( unsigned short retrySeqNumber, + unsigned &retryNoForThisChannel ); + void createChannelRequest (); + bool identifierEquivelence ( unsigned idToMatch ); + void * operator new ( size_t size ); + void operator delete ( void *pCadaver, size_t size ); + void resetRetryCount (); + unsigned getRetrySeqNo () const; + void accessRightsStateChange ( const caAccessRights & ); + ca_uint32_t getSID () const; + ca_uint32_t getCID () const; + netiiu * getPIIU (); + cac & getClient (); + void searchReplySetUp ( netiiu &iiu, unsigned sidIn, + unsigned typeIn, unsigned long countIn ); + void show ( unsigned level ) const; + void connectTimeoutNotify (); + const char *pName () const; + unsigned nameLen () const; + const char * pHostName () const; // deprecated - please do not use + unsigned long nativeElementCount () const; + bool connected () const; + bool previouslyConnected () const; +protected: + ~nciu (); // force pool allocation +private: + cac &cacCtx; + caAccessRights accessRightState; + unsigned count; + char *pNameStr; + netiiu *piiu; + ca_uint32_t sid; // server id + unsigned retry; // search retry number + unsigned short retrySeqNo; // search retry seq number + unsigned short nameLength; // channel name length + unsigned short typeCode; + unsigned f_connected:1; + unsigned f_previousConn:1; // T if connected in the past + unsigned f_claimSent:1; + unsigned f_firstConnectDecrementsOutstandingIO:1; + unsigned f_connectTimeOutSeen:1; + void initiateConnect (); + ioStatus read ( unsigned type, unsigned long count, + cacReadNotify &, ioid * ); + void write ( unsigned type, unsigned long count, + const void *pValue ); + ioStatus write ( unsigned type, unsigned long count, + const void *pValue, cacWriteNotify &, ioid * ); + void subscribe ( unsigned type, unsigned long nElem, + unsigned mask, cacStateNotify ¬ify, ioid * ); + void ioCancel ( const ioid & ); + void ioShow ( const ioid &, unsigned level ) const; + short nativeType () const; + caAccessRights accessRights () const; + unsigned searchAttempts () const; + double beaconPeriod () const; + bool ca_v42_ok () const; + void hostName ( char *pBuf, unsigned bufLength ) const; + void notifyStateChangeFirstConnectInCountOfOutstandingIO (); + static void stringVerify ( const char *pStr, const unsigned count ); + static tsFreeList < class nciu, 1024 > freeList; + static epicsMutex freeListMutex; +}; + +inline void * nciu::operator new ( size_t size ) +{ + epicsAutoMutex locker ( nciu::freeListMutex ); + return nciu::freeList.allocate ( size ); +} + +inline void nciu::operator delete ( void *pCadaver, size_t size ) +{ + epicsAutoMutex locker ( nciu::freeListMutex ); + nciu::freeList.release ( pCadaver, size ); +} + +inline bool nciu::identifierEquivelence ( unsigned idToMatch ) +{ + return idToMatch == this->id; +} + +inline void nciu::resetRetryCount () +{ + this->retry = 0u; +} + +inline void nciu::accessRightsStateChange ( const caAccessRights &arIn ) +{ + this->accessRightState = arIn; + this->notify().accessRightsNotify ( arIn ); +} + +inline ca_uint32_t nciu::getSID () const +{ + return this->sid; +} + +inline ca_uint32_t nciu::getCID () const +{ + return this->id; +} + +inline unsigned nciu::getRetrySeqNo () const +{ + return this->retrySeqNo; +} + +// this is to only be used by early protocol revisions +inline void nciu::connect () +{ + this->connect ( this->typeCode, this->count, this->sid ); +} + +inline void nciu::searchReplySetUp ( netiiu &iiu, unsigned sidIn, + unsigned typeIn, unsigned long countIn ) +{ + this->piiu = &iiu; + this->typeCode = typeIn; + this->count = countIn; + this->sid = sidIn; +} + +inline bool nciu::connected () const +{ + return this->f_connected; +} + +inline bool nciu::previouslyConnected () const +{ + return this->f_previousConn; +} + +inline netiiu * nciu::getPIIU () +{ + return this->piiu; +} + +inline cac & nciu::getClient () +{ + return this->cacCtx; +} + +inline void nciu::connectTimeoutNotify () +{ + this->f_connectTimeOutSeen = true; +} + +#endif // ifdef nciuh diff --git a/src/ca/nciu_IL.h b/src/ca/nciu_IL.h deleted file mode 100644 index cc2159ba8..000000000 --- a/src/ca/nciu_IL.h +++ /dev/null @@ -1,114 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - - -// -// nciu inline member functions -// - -inline void * nciu::operator new ( size_t size ) -{ - epicsAutoMutex locker ( nciu::freeListMutex ); - return nciu::freeList.allocate ( size ); -} - -inline void nciu::operator delete ( void *pCadaver, size_t size ) -{ - epicsAutoMutex locker ( nciu::freeListMutex ); - nciu::freeList.release ( pCadaver, size ); -} - -inline bool nciu::identifierEquivelence ( unsigned idToMatch ) -{ - return idToMatch == this->id; -} - -inline void nciu::resetRetryCount () -{ - this->retry = 0u; -} - -inline void nciu::accessRightsStateChange ( const caAccessRights &arIn ) -{ - this->accessRightState = arIn; - this->notify().accessRightsNotify ( *this, arIn ); -} - -inline ca_uint32_t nciu::getSID () const -{ - return this->sid; -} - -inline ca_uint32_t nciu::getCID () const -{ - return this->id; -} - -inline unsigned nciu::getRetrySeqNo () const -{ - return this->retrySeqNo; -} - -// this is to only be used by early protocol revisions -inline void nciu::connect () -{ - this->connect ( this->typeCode, this->count, this->sid ); -} - -inline void nciu::searchReplySetUp ( netiiu &iiu, unsigned sidIn, - unsigned typeIn, unsigned long countIn ) -{ - this->piiu = &iiu; - this->typeCode = typeIn; - this->count = countIn; - this->sid = sidIn; -} - -inline bool nciu::connected () const -{ - return this->f_connected; -} - -inline bool nciu::previouslyConnected () const -{ - return this->f_previousConn; -} - -inline bool nciu::isAttachedToVirtaulCircuit ( const osiSockAddr &addrIn ) -{ - return this->piiu->isVirtaulCircuit ( this->pNameStr, addrIn ); -} - -inline netiiu * nciu::getPIIU () -{ - return this->piiu; -} - -inline cac & nciu::getClient () -{ - return this->cacCtx; -} - -inline void nciu::connectTimeoutNotify () -{ - this->f_connectTimeOutSeen = true; -} - - - - - diff --git a/src/ca/netIO.h b/src/ca/netIO.h new file mode 100644 index 000000000..ccc55b19d --- /dev/null +++ b/src/ca/netIO.h @@ -0,0 +1,244 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef netIOh +#define netIOh + +#include "nciu.h" + +class baseNMIU : public tsDLNode < baseNMIU >, + public chronIntIdRes < baseNMIU > { +public: + baseNMIU ( nciu &chan ); + virtual class netSubscription * isSubscription (); + virtual void destroy ( class cacRecycle & ) = 0; // only called by cac + virtual void completion () = 0; + virtual void exception ( int status, const char *pContext ) = 0; + virtual void completion ( unsigned type, + unsigned long count, const void *pData ) = 0; + virtual void exception ( int status, + const char *pContext, unsigned type, unsigned long count ) = 0; + void show ( unsigned level ) const; + ca_uint32_t getID () const; + nciu & channel () const; +protected: + virtual ~baseNMIU () = 0; +// +// perhaps we should not store the channel here and instead fetch it out of the +// notify +// + nciu &chan; +}; + +class netSubscription : public baseNMIU { +public: + static netSubscription * factory ( + tsFreeList < class netSubscription, 1024 > &, + nciu &chan, unsigned type, unsigned long count, + unsigned mask, cacStateNotify ¬ify ); + void show ( unsigned level ) const; + unsigned long getCount () const; + unsigned getType () const; + unsigned getMask () const; + void destroy ( class cacRecycle & ); + void completion (); + void exception ( int status, const char *pContext ); + void completion ( unsigned type, + unsigned long count, const void *pData ); + void exception ( int status, + const char *pContext, unsigned type, unsigned long count ); +protected: + ~netSubscription (); +private: + const unsigned long count; + cacStateNotify ¬ify; + const unsigned type; + const unsigned mask; + netSubscription ( nciu &chan, unsigned type, unsigned long count, + unsigned mask, cacStateNotify ¬ify ); + class netSubscription * isSubscription (); + void * operator new ( size_t, + tsFreeList < class netSubscription, 1024 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class netSubscription, 1024 > & ); +# endif +}; + +class netReadNotifyIO : public baseNMIU { +public: + static netReadNotifyIO * factory ( + tsFreeList < class netReadNotifyIO, 1024 > &, + nciu &chan, cacReadNotify ¬ify ); + void show ( unsigned level ) const; + void destroy ( class cacRecycle & ); + void completion (); + void exception ( int status, const char *pContext ); + void completion ( unsigned type, + unsigned long count, const void *pData ); + void exception ( int status, + const char *pContext, unsigned type, unsigned long count ); +protected: + ~netReadNotifyIO (); +private: + cacReadNotify ¬ify; + netReadNotifyIO ( nciu &chan, cacReadNotify ¬ify ); + void * operator new ( size_t, + tsFreeList < class netReadNotifyIO, 1024 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class netReadNotifyIO, 1024 > & ); +# endif +}; + +class netWriteNotifyIO : public baseNMIU { +public: + static netWriteNotifyIO * factory ( + tsFreeList < class netWriteNotifyIO, 1024 > &, + nciu &chan, cacWriteNotify ¬ify ); + void show ( unsigned level ) const; + void destroy ( class cacRecycle & ); + void completion (); + void exception ( int status, const char *pContext ); + void completion ( unsigned type, + unsigned long count, const void *pData ); + void exception ( int status, + const char *pContext, unsigned type, unsigned long count ); +protected: + ~netWriteNotifyIO (); +private: + cacWriteNotify ¬ify; + netWriteNotifyIO ( nciu &chan, cacWriteNotify ¬ify ); + void * operator new ( size_t, + tsFreeList < class netWriteNotifyIO, 1024 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class netWriteNotifyIO, 1024 > & ); +# endif +}; + +inline ca_uint32_t baseNMIU::getID () const +{ + return this->id; +} + +inline class nciu & baseNMIU::channel () const +{ + return this->chan; +} + +inline netSubscription * netSubscription::factory ( + tsFreeList < class netSubscription, 1024 > &freeList, + nciu &chan, unsigned type, unsigned long count, + unsigned mask, cacStateNotify ¬ify ) +{ + return new ( freeList ) netSubscription ( chan, type, + count, mask, notify ); +} + +inline void * netSubscription::operator new ( size_t size, + tsFreeList < class netSubscription, 1024 > &freeList ) +{ + return freeList.allocate ( size ); +} + +// NOTE: The constructor for netSubscription::netSubscription() currently does +// not throw an exception, but we should eventually have placement delete +// defined for class netSubscription when compilers support this so that +// there is no possibility of a leak if there was an exception in +// a future version of netSubscription::netSubscription() +#if ! defined ( NO_PLACEMENT_DELETE ) +inline void netSubscription::operator delete ( void *pCadaver, size_t size, + tsFreeList < class netSubscription, 1024 > &freeList ) +{ + freeList.release ( pCadaver, size ); +} +#endif + +inline unsigned long netSubscription::getCount () const +{ + unsigned long nativeCount = this->chan.nativeElementCount (); + if ( this->count == 0u || this->count > nativeCount ) { + return nativeCount; + } + else { + return this->count; + } +} + +inline unsigned netSubscription::getType () const +{ + return this->type; +} + +inline unsigned netSubscription::getMask () const +{ + return this->mask; +} + +inline netReadNotifyIO * netReadNotifyIO::factory ( + tsFreeList < class netReadNotifyIO, 1024 > &freeList, + nciu &chan, cacReadNotify ¬ify ) +{ + return new ( freeList ) netReadNotifyIO ( chan, notify ); +} + +inline void * netReadNotifyIO::operator new ( size_t size, + tsFreeList < class netReadNotifyIO, 1024 > &freeList ) +{ + return freeList.allocate ( size ); +} + +// NOTE: The constructor for netReadNotifyIO::netReadNotifyIO() currently does +// not throw an exception, but we should eventually have placement delete +// defined for class netReadNotifyIO when compilers support this so that +// there is no possibility of a leak if there was an exception in +// a future version of netReadNotifyIO::netReadNotifyIO() +#if ! defined ( NO_PLACEMENT_DELETE ) +inline void netReadNotifyIO::operator delete ( void *pCadaver, size_t size, + tsFreeList < class netReadNotifyIO, 1024 > &freeList ) { + freeList.release ( pCadaver, size ); +} +#endif + +inline netWriteNotifyIO * netWriteNotifyIO::factory ( + tsFreeList < class netWriteNotifyIO, 1024 > &freeList, + nciu &chan, cacWriteNotify ¬ify ) +{ + return new ( freeList ) netWriteNotifyIO ( chan, notify ); +} + +inline void * netWriteNotifyIO::operator new ( size_t size, + tsFreeList < class netWriteNotifyIO, 1024 > &freeList ) +{ + return freeList.allocate ( size ); +} + +// NOTE: The constructor for netWriteNotifyIO::netWriteNotifyIO() currently does +// not throw an exception, but we should eventually have placement delete +// defined for class netWriteNotifyIO when compilers support this so that +// there is no possibility of a leak if there was an exception in +// a future version of netWriteNotifyIO::netWriteNotifyIO() +#if ! defined ( NO_PLACEMENT_DELETE ) +inline void netWriteNotifyIO::operator delete ( void *pCadaver, size_t size, + tsFreeList < class netWriteNotifyIO, 1024 > &freeList ) +{ + freeList.release ( pCadaver, size ); +} +#endif + +#endif // ifdef netIOh diff --git a/src/ca/netReadNotifyIO.cpp b/src/ca/netReadNotifyIO.cpp index ca62a9c29..922195c47 100644 --- a/src/ca/netReadNotifyIO.cpp +++ b/src/ca/netReadNotifyIO.cpp @@ -10,12 +10,14 @@ * Author: Jeff Hill */ -#include "iocinf.h" -#include "netReadNotifyIO_IL.h" -#include "nciu_IL.h" -#include "baseNMIU_IL.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -netReadNotifyIO::netReadNotifyIO ( nciu &chan, cacDataNotify ¬ify ) : +#include "iocinf.h" +#include "nciu.h" +#include "netIO.h" +#include "cac.h" + +netReadNotifyIO::netReadNotifyIO ( nciu &chan, cacReadNotify ¬ify ) : baseNMIU ( chan ), notify ( notify ) { } @@ -26,7 +28,7 @@ netReadNotifyIO::~netReadNotifyIO () void netReadNotifyIO::show ( unsigned level ) const { - printf ( "read notify IO at %p\n", + ::printf ( "read notify IO at %p\n", static_cast < const void * > ( this ) ); if ( level > 0u ) { this->baseNMIU::show ( level - 1u ); diff --git a/src/ca/netReadNotifyIO_IL.h b/src/ca/netReadNotifyIO_IL.h deleted file mode 100644 index 2829bfc13..000000000 --- a/src/ca/netReadNotifyIO_IL.h +++ /dev/null @@ -1,46 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef netReadNotifyIO_ILh -#define netReadNotifyIO_ILh - -inline netReadNotifyIO * netReadNotifyIO::factory ( - tsFreeList < class netReadNotifyIO, 1024 > &freeList, - nciu &chan, cacDataNotify ¬ify ) -{ - return new ( freeList ) netReadNotifyIO ( chan, notify ); -} - -inline void * netReadNotifyIO::operator new ( size_t size, - tsFreeList < class netReadNotifyIO, 1024 > &freeList ) -{ - return freeList.allocate ( size ); -} - -// NOTE: The constructor for netReadNotifyIO::netReadNotifyIO() currently does -// not throw an exception, but we should eventually have placement delete -// defined for class netReadNotifyIO when compilers support this so that -// there is no possibility of a leak if there was an exception in -// a future version of netReadNotifyIO::netReadNotifyIO() -#if ! defined ( NO_PLACEMENT_DELETE ) -inline void netReadNotifyIO::operator delete ( void *pCadaver, size_t size, - tsFreeList < class netReadNotifyIO, 1024 > &freeList ) { - freeList.release ( pCadaver, size ); -} -#endif - -#endif // netReadNotifyIO_ILh diff --git a/src/ca/netSubscription.cpp b/src/ca/netSubscription.cpp index fb49583d6..a2577c5ed 100644 --- a/src/ca/netSubscription.cpp +++ b/src/ca/netSubscription.cpp @@ -10,14 +10,20 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "netSubscription_IL.h" -#include "nciu_IL.h" -#include "baseNMIU_IL.h" +#include "nciu.h" +#include "netIO.h" +#include "cac.h" + +#define epicsExportSharedSymbols +#include "db_access.h" // for dbf_type_to_text +#undef epicsExportSharedSymbols netSubscription::netSubscription ( nciu &chan, unsigned typeIn, unsigned long countIn, - unsigned maskIn, cacDataNotify ¬ifyIn ) : + unsigned maskIn, cacStateNotify ¬ifyIn ) : baseNMIU ( chan ), count ( countIn ), notify ( notifyIn ), type ( typeIn ), mask ( maskIn ) { @@ -40,7 +46,7 @@ class netSubscription * netSubscription::isSubscription () void netSubscription::show ( unsigned level ) const { - printf ( "event subscription IO at %p, type %s, element count %lu, mask %u\n", + ::printf ( "event subscription IO at %p, type %s, element count %lu, mask %u\n", static_cast < const void * > ( this ), dbf_type_to_text ( static_cast < int > ( this->type ) ), this->count, this->mask ); @@ -62,7 +68,7 @@ void netSubscription::exception ( int status, const char *pContext ) void netSubscription::completion ( unsigned typeIn, unsigned long countIn, const void *pDataIn ) { - this->notify.completion ( typeIn, countIn, pDataIn ); + this->notify.current ( typeIn, countIn, pDataIn ); } void netSubscription::exception ( int status, diff --git a/src/ca/netSubscription_IL.h b/src/ca/netSubscription_IL.h deleted file mode 100644 index 4235249c8..000000000 --- a/src/ca/netSubscription_IL.h +++ /dev/null @@ -1,72 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef netSubscription_ILh -#define netSubscription_ILh - -inline netSubscription * netSubscription::factory ( - tsFreeList < class netSubscription, 1024 > &freeList, - nciu &chan, unsigned type, unsigned long count, - unsigned mask, cacDataNotify ¬ify ) -{ - return new ( freeList ) netSubscription ( chan, type, - count, mask, notify ); -} - -inline void * netSubscription::operator new ( size_t size, - tsFreeList < class netSubscription, 1024 > &freeList ) -{ - return freeList.allocate ( size ); -} - -// NOTE: The constructor for netSubscription::netSubscription() currently does -// not throw an exception, but we should eventually have placement delete -// defined for class netSubscription when compilers support this so that -// there is no possibility of a leak if there was an exception in -// a future version of netSubscription::netSubscription() -#if ! defined ( NO_PLACEMENT_DELETE ) -inline void netSubscription::operator delete ( void *pCadaver, size_t size, - tsFreeList < class netSubscription, 1024 > &freeList ) -{ - freeList.release ( pCadaver, size ); -} -#endif - -inline unsigned long netSubscription::getCount () const -{ - unsigned long nativeCount = this->chan.nativeElementCount (); - if ( this->count == 0u || this->count > nativeCount ) { - return nativeCount; - } - else { - return this->count; - } -} - -inline unsigned netSubscription::getType () const -{ - return this->type; -} - -inline unsigned netSubscription::getMask () const -{ - return this->mask; -} - -#endif // netSubscription_ILh - - diff --git a/src/ca/netWriteNotifyIO.cpp b/src/ca/netWriteNotifyIO.cpp index cb5d82613..97b9c5c0e 100644 --- a/src/ca/netWriteNotifyIO.cpp +++ b/src/ca/netWriteNotifyIO.cpp @@ -10,12 +10,14 @@ * Author: Jeff Hill */ -#include "iocinf.h" -#include "netWriteNotifyIO_IL.h" -#include "nciu_IL.h" -#include "baseNMIU_IL.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -netWriteNotifyIO::netWriteNotifyIO ( nciu &chan, cacNotify ¬ifyIn ) : +#include "iocinf.h" +#include "nciu.h" +#include "netIO.h" +#include "cac.h" + +netWriteNotifyIO::netWriteNotifyIO ( nciu &chan, cacWriteNotify ¬ifyIn ) : baseNMIU ( chan ), notify ( notifyIn ) { } @@ -26,7 +28,7 @@ netWriteNotifyIO::~netWriteNotifyIO () void netWriteNotifyIO::show ( unsigned level ) const { - printf ( "read write notify IO at %p\n", + ::printf ( "read write notify IO at %p\n", static_cast < const void * > ( this ) ); if ( level > 0u ) { this->baseNMIU::show ( level - 1u ); diff --git a/src/ca/netiiu.cpp b/src/ca/netiiu.cpp index aadc1781e..8d6031190 100644 --- a/src/ca/netiiu.cpp +++ b/src/ca/netiiu.cpp @@ -13,10 +13,12 @@ #include #include +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "netiiu_IL.h" -#include "nciu_IL.h" -#include "baseNMIU_IL.h" +#include "cac.h" +#include "netiiu.h" +#include "netIO.h" netiiu::netiiu ( cac *pClientCtxIn ) : pClientCtx ( pClientCtxIn ) { @@ -28,7 +30,7 @@ netiiu::~netiiu () void netiiu::show ( unsigned level ) const { - printf ( "network IO base class\n" ); + ::printf ( "network IO base class\n" ); if ( level > 1 ) { tsDLIterConstBD < nciu > pChan = this->channelList.firstIter (); while ( pChan.valid () ) { @@ -37,7 +39,7 @@ void netiiu::show ( unsigned level ) const } } if ( level > 2u ) { - printf ( "\tcac pointer %p\n", + ::printf ( "\tcac pointer %p\n", static_cast ( this->pClientCtx ) ); } } @@ -192,3 +194,17 @@ void netiiu::flushRequestIfAboveEarlyThreshold () void netiiu::blockUntilSendBacklogIsReasonable ( epicsMutex & ) { } + +int netiiu::printf ( const char *pformat, ... ) +{ + va_list theArgs; + int status; + + va_start ( theArgs, pformat ); + + status = this->pClientCtx->vPrintf ( pformat, theArgs ); + + va_end ( theArgs ); + + return status; +} diff --git a/src/ca/netiiu.h b/src/ca/netiiu.h new file mode 100644 index 000000000..778bd85fe --- /dev/null +++ b/src/ca/netiiu.h @@ -0,0 +1,105 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef netiiuh +#define netiiuh + +#include "tsDLList.h" + +#include "nciu.h" + +class netWriteNotifyIO; +class netReadNotifyIO; +class netSubscription; +union osiSockAddr; + +class cac; + +class netiiu { +public: + netiiu ( cac * ); + virtual ~netiiu (); + void show ( unsigned level ) const; + unsigned channelCount () const; + void disconnectAllChan ( netiiu & newiiu ); + void connectTimeoutNotify (); + bool searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisChannel ); + void resetChannelRetryCounts (); + void attachChannel ( nciu &chan ); + void detachChannel ( nciu &chan ); + int printf ( const char *pformat, ... ); + virtual void hostName (char *pBuf, unsigned bufLength) const; + virtual const char * pHostName () const; // deprecated - please do not use + virtual bool isVirtaulCircuit ( const char *pChannelName, const osiSockAddr &addr ) const; + virtual bool ca_v42_ok () const; + virtual bool ca_v41_ok () const; + virtual bool pushDatagramMsg ( const caHdr &hdr, const void *pExt, ca_uint16_t extsize); + virtual void writeRequest ( nciu &, unsigned type, unsigned nElem, const void *pValue ); + virtual void writeNotifyRequest ( nciu &, netWriteNotifyIO &, unsigned type, unsigned nElem, const void *pValue ); + virtual void readNotifyRequest ( nciu &, netReadNotifyIO &, unsigned type, unsigned nElem ); + virtual void createChannelRequest ( nciu & ); + virtual void connectAllIO ( nciu &chan ); + virtual void disconnectAllIO ( nciu &chan ); + virtual void clearChannelRequest ( nciu & ); + virtual void subscriptionRequest ( nciu &, netSubscription &subscr ); + virtual void subscriptionCancelRequest ( nciu &, netSubscription &subscr ); + virtual double beaconPeriod () const; + virtual void flushRequest (); + virtual bool flushBlockThreshold () const; + virtual void flushRequestIfAboveEarlyThreshold (); + virtual void blockUntilSendBacklogIsReasonable ( epicsMutex & ); +protected: + cac * pCAC () const; +private: + tsDLList < nciu > channelList; + cac *pClientCtx; + virtual void lastChannelDetachNotify (); +}; + +class limboiiu : public netiiu { +public: + limboiiu (); +}; + +extern limboiiu limboIIU; + +inline cac * netiiu::pCAC () const +{ + return this->pClientCtx; +} + +inline unsigned netiiu::channelCount () const +{ + return this->channelList.count (); +} + +// cac lock must also be applied when calling this +inline void netiiu::attachChannel ( class nciu &chan ) +{ + this->channelList.add ( chan ); +} + +// cac lock must also be applied when calling this +inline void netiiu::detachChannel ( class nciu &chan ) +{ + this->channelList.remove ( chan ); + if ( this->channelList.count () == 0u ) { + this->lastChannelDetachNotify (); + } +} + +#endif // netiiuh diff --git a/src/ca/netiiu_IL.h b/src/ca/netiiu_IL.h deleted file mode 100644 index 24b5acfba..000000000 --- a/src/ca/netiiu_IL.h +++ /dev/null @@ -1,48 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef netiiu_ILh -#define netiiu_ILh - -inline cac * netiiu::pCAC () const -{ - return this->pClientCtx; -} - -inline unsigned netiiu::channelCount () const -{ - return this->channelList.count (); -} - -// cac lock must also be applied when -// calling this -inline void netiiu::attachChannel ( nciu &chan ) -{ - this->channelList.add ( chan ); -} - -// cac lock must also be applied when -// calling this -inline void netiiu::detachChannel ( nciu &chan ) -{ - this->channelList.remove ( chan ); - if ( this->channelList.count () == 0u ) { - this->lastChannelDetachNotify (); - } -} - -#endif // netiiu_ILh diff --git a/src/ca/oldAccess.h b/src/ca/oldAccess.h index a5f016c07..eb2edaf98 100644 --- a/src/ca/oldAccess.h +++ b/src/ca/oldAccess.h @@ -15,9 +15,21 @@ * 505 665 1831 */ +#ifndef oldAccessh +#define oldAccessh + +#include "tsFreeList.h" + +#include "cac.h" + +#define epicsExportSharedSymbols +#include "cacIO.h" +#include "cadef.h" +#undef epicsExportSharedSymbols + struct oldChannelNotify : public cacChannelNotify { public: - oldChannelNotify ( cac &, const char *pName, caCh *pConnCallBackIn, void *pPrivateIn ); + oldChannelNotify ( class oldCAC &, const char *pName, caCh *pConnCallBackIn, void *pPrivateIn ); void destroy (); bool ioAttachOK (); void setPrivatePointer ( void * ); @@ -33,7 +45,7 @@ public: void initiateConnect (); void read ( unsigned type, unsigned long count, - cacDataNotify ¬ify, cacChannel::ioid *pId = 0 ); + cacReadNotify ¬ify, cacChannel::ioid *pId = 0 ); void read ( unsigned type, unsigned long count, void *pValue ); @@ -42,10 +54,10 @@ public: const void *pValue ); void write ( unsigned type, unsigned long count, const void *pValue, - cacNotify &, cacChannel::ioid *pId = 0 ); + cacWriteNotify &, cacChannel::ioid *pId = 0 ); void subscribe ( unsigned type, unsigned long count, unsigned mask, - cacDataNotify &, cacChannel::ioid & ); + cacStateNotify &, cacChannel::ioid & ); void ioCancel ( const cacChannel::ioid & ); void ioShow ( const cacChannel::ioid &, unsigned level ) const; short nativeType () const; @@ -65,17 +77,18 @@ private: caCh *pConnCallBack; void *pPrivate; caArh *pAccessRightsFunc; - void connectNotify ( cacChannel &chan ); - void disconnectNotify ( cacChannel &chan ); - void accessRightsNotify ( cacChannel &chan, const caAccessRights & ); + void connectNotify (); + void disconnectNotify (); + void accessRightsNotify ( const caAccessRights & ); + void exception ( int status, const char *pContext ); bool includeFirstConnectInCountOfOutstandingIO () const; static tsFreeList < struct oldChannelNotify, 1024 > freeList; static epicsMutex freeListMutex; }; -class getCopy : public cacDataNotify { +class getCopy : public cacReadNotify { public: - getCopy ( cac &cacCtx, unsigned type, + getCopy ( oldCAC &cacCtx, unsigned type, unsigned long count, void *pValue ); void destroy (); void show ( unsigned level ) const; @@ -85,7 +98,7 @@ protected: ~getCopy (); // allocate only out of pool private: unsigned long count; - cac &cacCtx; + oldCAC &cacCtx; void *pValue; unsigned readSeq; unsigned type; @@ -97,7 +110,7 @@ private: static epicsMutex freeListMutex; }; -class getCallback : public cacDataNotify { +class getCallback : public cacReadNotify { public: getCallback ( oldChannelNotify &chanIn, caEventCallBackFunc *pFunc, void *pPrivate ); @@ -118,7 +131,7 @@ private: static epicsMutex freeListMutex; }; -class putCallback : public cacNotify { +class putCallback : public cacWriteNotify { public: putCallback ( oldChannelNotify &, caEventCallBackFunc *pFunc, void *pPrivate ); @@ -138,7 +151,7 @@ private: static epicsMutex freeListMutex; }; -struct oldSubscription : public cacDataNotify { +struct oldSubscription : public cacStateNotify { public: oldSubscription ( oldChannelNotify &, @@ -157,7 +170,7 @@ private: caEventCallBackFunc *pFunc; void *pPrivate; bool subscribed; - void completion ( + void current ( unsigned type, unsigned long count, const void *pData ); void exception ( int status, const char *pContext, unsigned type, unsigned long count ); @@ -165,6 +178,53 @@ private: static epicsMutex freeListMutex; }; +class oldCAC : public cacNotify +{ +public: + oldCAC ( bool enablePreemptiveCallback = false ); + virtual ~oldCAC (); + void changeExceptionEvent ( caExceptionHandler *pfunc, void *arg ); + void registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg ); + void replaceErrLogHandler ( caPrintfFunc *ca_printf_func ); + void registerService ( cacService &service ); + cacChannel & createChannel ( const char *name_str, oldChannelNotify &chan ); + void flushRequest (); + int pendIO ( const double &timeout ); + int pendEvent ( const double &timeout ); + bool ioComplete () const; + void show ( unsigned level ) const; + unsigned connectionCount () const; + unsigned sequenceNumberOfOutstandingIO () const; + void incrementOutstandingIO (); + void decrementOutstandingIO ( unsigned sequenceNo ); + void exception ( int status, const char *pContext, + const char *pFileName, unsigned lineNo ); + void exception ( int status, const char *pContext, + unsigned type, unsigned long count, + const char *pFileName, unsigned lineNo ); +// perhaps these should be eliminated in deference to the exception mechanism + int printf ( const char *pformat, ... ); + int vPrintf ( const char *pformat, va_list args ); + CASG * lookupCASG ( unsigned id ); + void installCASG ( CASG & ); + void uninstallCASG ( CASG & ); + void enableCallbackPreemption (); + void disableCallbackPreemption (); +private: + cac & clientCtx; + mutable epicsMutex mutex; + caExceptionHandler *ca_exception_func; + void *ca_exception_arg; + caPrintfFunc *pVPrintfFunc; + CAFDHANDLER *fdRegFunc; + void *fdRegArg; +// this should probably be phased out (its not OS independent) + void fdWasCreated ( int fd ); + void fdWasDestroyed ( int fd ); +}; + +int fetchClientContext ( oldCAC **ppcac ); + inline bool oldChannelNotify::ioAttachOK () { return &this->io ? true : false; @@ -191,7 +251,7 @@ inline void oldChannelNotify::initiateConnect () } inline void oldChannelNotify::read ( unsigned type, unsigned long count, - cacDataNotify ¬ify, cacChannel::ioid *pId ) + cacReadNotify ¬ify, cacChannel::ioid *pId ) { this->io.read ( type, count, notify, pId ); } @@ -203,13 +263,13 @@ inline void oldChannelNotify::write ( unsigned type, } inline void oldChannelNotify::write ( unsigned type, unsigned long count, - const void *pValue, cacNotify ¬ify, cacChannel::ioid *pId ) + const void *pValue, cacWriteNotify ¬ify, cacChannel::ioid *pId ) { this->io.write ( type, count, pValue, notify, pId ); } inline void oldChannelNotify::subscribe ( unsigned type, - unsigned long count, unsigned mask, cacDataNotify ¬ify, + unsigned long count, unsigned mask, cacStateNotify ¬ify, cacChannel::ioid &idOut) { this->io.subscribe ( type, count, mask, notify, &idOut ); @@ -361,3 +421,80 @@ inline void getCallback::operator delete ( void *pCadaver, size_t size ) epicsAutoMutex locker ( getCallback::freeListMutex ); getCallback::freeList.release ( pCadaver, size ); } + +inline void oldCAC::registerService ( cacService &service ) +{ + this->clientCtx.registerService ( service ); +} + +inline cacChannel & oldCAC::createChannel ( const char *name_str, oldChannelNotify &chan ) +{ + return this->clientCtx.createChannel ( name_str, chan ); +} + +inline int oldCAC::pendIO ( const double &timeout ) +{ + return this->clientCtx.pendIO ( timeout ); +} + +inline int oldCAC::pendEvent ( const double &timeout ) +{ + return this->clientCtx.pendEvent ( timeout ); +} + +inline void oldCAC::flushRequest () +{ + this->clientCtx.flushRequest (); +} + +inline bool oldCAC::ioComplete () const +{ + return this->clientCtx.ioComplete (); +} + +inline unsigned oldCAC::connectionCount () const +{ + return this->clientCtx.connectionCount (); +} + +inline unsigned oldCAC::sequenceNumberOfOutstandingIO () const +{ + return this->clientCtx.sequenceNumberOfOutstandingIO (); +} + +inline void oldCAC::incrementOutstandingIO () +{ + this->clientCtx.incrementOutstandingIO (); +} + +inline void oldCAC::decrementOutstandingIO ( unsigned sequenceNo ) +{ + this->clientCtx.decrementOutstandingIO ( sequenceNo ); +} + +inline CASG * oldCAC::lookupCASG ( unsigned id ) +{ + return this->clientCtx.lookupCASG ( id ); +} + +inline void oldCAC::installCASG ( CASG &sg ) +{ + this->clientCtx.installCASG ( sg ); +} + +inline void oldCAC::uninstallCASG ( CASG &sg ) +{ + this->clientCtx.uninstallCASG ( sg ); +} + +inline void oldCAC::enableCallbackPreemption () +{ + this->clientCtx.enableCallbackPreemption (); +} + +inline void oldCAC::disableCallbackPreemption () +{ + this->clientCtx.disableCallbackPreemption (); +} + +#endif // ifndef oldAccessh diff --git a/src/ca/oldCAC.cpp b/src/ca/oldCAC.cpp new file mode 100644 index 000000000..f8aef2401 --- /dev/null +++ b/src/ca/oldCAC.cpp @@ -0,0 +1,178 @@ +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#include "iocinf.h" + +#include "oldAccess.h" + +oldCAC::oldCAC ( bool enablePreemptiveCallback ) : + clientCtx ( * new cac ( *this, enablePreemptiveCallback ) ), + ca_exception_func ( ca_default_exception_handler ), ca_exception_arg ( 0 ), + pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ) +{ + if ( ! & this->clientCtx ) { + throw -1; + } +} + +oldCAC::~oldCAC () +{ + delete & this->clientCtx; +} + +void oldCAC::changeExceptionEvent ( caExceptionHandler *pfunc, void *arg ) +{ + epicsAutoMutex autoMutex ( this->mutex ); + if ( pfunc ) { + this->ca_exception_func = pfunc; + this->ca_exception_arg = arg; + } + else { + this->ca_exception_func = ca_default_exception_handler; + this->ca_exception_arg = NULL; + } +// should block here until releated callback in progress completes +} + +void oldCAC::replaceErrLogHandler ( caPrintfFunc *ca_printf_func ) +{ + epicsAutoMutex autoMutex ( this->mutex ); + if ( ca_printf_func ) { + this->pVPrintfFunc = ca_printf_func; + } + else { + this->pVPrintfFunc = epicsVprintf; + } +// should block here until releated callback in progress completes +} + +void oldCAC::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg ) +{ + epicsAutoMutex autoMutex ( this->mutex ); + this->fdRegFunc = pFunc; + this->fdRegArg = pArg; +// should block here until releated callback in progress completes +} + + +int oldCAC::vPrintf ( const char *pformat, va_list args ) +{ + caPrintfFunc *pFunc; + { + epicsAutoMutex autoMutex ( this->mutex ); + pFunc = this->pVPrintfFunc; + } + if ( pFunc ) { + return ( *pFunc ) ( pformat, args ); + } + else { + return vfprintf ( stderr, pformat, args ); + } +} + +void oldCAC::exception ( int stat, const char *pCtx, const char *pFile, unsigned lineNo ) +{ + this->exception ( stat, pCtx, UINT_MAX, 0, pFile, lineNo ); +} + +void oldCAC::exception ( int stat, const char *ctx, + unsigned type, unsigned long count, + const char *pFile, unsigned lineNo ) +{ + struct exception_handler_args args; + caExceptionHandler *pFunc; + void *pArg; + { + epicsAutoMutex autoMutex ( this->mutex ); + pFunc = this->ca_exception_func; + pArg = this->ca_exception_arg; + } + + // NOOP if they disable exceptions + if ( pFunc ) { + args.chid = NULL; + args.type = type; + args.count = count; + args.addr = NULL; + args.stat = stat; + args.op = CA_OP_OTHER; + args.ctx = ctx; + args.pFile = pFile; + args.lineNo = lineNo; + args.usr = pArg; + ( *pFunc ) ( args ); + } +} + +void oldCAC::fdWasCreated ( int fd ) +{ + CAFDHANDLER *pFunc; + void *pArg; + { + epicsAutoMutex autoMutex ( this->mutex ); + pFunc = this->fdRegFunc; + pArg = this->fdRegArg; + } + if ( pFunc ) { + ( *pFunc ) ( pArg, fd, true ); + } +} + +void oldCAC::fdWasDestroyed ( int fd ) +{ + CAFDHANDLER *pFunc; + void *pArg; + { + epicsAutoMutex autoMutex ( this->mutex ); + pFunc = this->fdRegFunc; + pArg = this->fdRegArg; + } + if ( pFunc ) { + ( *pFunc ) ( pArg, fd, false ); + } +} + +int oldCAC::printf ( const char *pformat, ... ) +{ + va_list theArgs; + int status; + + va_start ( theArgs, pformat ); + + status = this->vPrintf ( pformat, theArgs ); + + va_end ( theArgs ); + + return status; +} + +void oldCAC::show ( unsigned level ) const +{ + ::printf ( "oldCAC at %p\n", + static_cast ( this ) ); + ::printf ( "exception func at %p arg at %p\n", + static_cast ( this->ca_exception_func ), + static_cast ( this->ca_exception_arg ) ); + ::printf ( "printf func at %p\n", + static_cast ( this->pVPrintfFunc ) ); + ::printf ( "fd registration func at %p arg at %p\n", + static_cast ( this->fdRegFunc ), + static_cast ( this->fdRegArg ) ); + if ( level > 0u ) { + this->mutex.show ( level - 1u ); + this->clientCtx.show ( level - 1u ); + } +} \ No newline at end of file diff --git a/src/ca/oldChannelNotify.cpp b/src/ca/oldChannelNotify.cpp index 6b2972f09..59b6e5b8a 100644 --- a/src/ca/oldChannelNotify.cpp +++ b/src/ca/oldChannelNotify.cpp @@ -15,8 +15,11 @@ * 505 665 1831 */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" #include "oldAccess.h" +#include "cac.h" tsFreeList < struct oldChannelNotify, 1024 > oldChannelNotify::freeList; epicsMutex oldChannelNotify::freeListMutex; @@ -29,7 +32,7 @@ extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args ) { } -oldChannelNotify::oldChannelNotify ( cac &cacIn, const char *pName, +oldChannelNotify::oldChannelNotify ( oldCAC &cacIn, const char *pName, caCh *pConnCallBackIn, void *pPrivateIn ) : io ( cacIn.createChannel ( pName, *this ) ), pConnCallBack ( pConnCallBackIn ? pConnCallBackIn : cacNoopConnHandler ), @@ -80,7 +83,7 @@ int oldChannelNotify::replaceAccessRightsEvent ( caArh *pfunc ) return ECA_NORMAL; } -void oldChannelNotify::connectNotify ( cacChannel & ) +void oldChannelNotify::connectNotify () { struct connection_handler_args args; args.chid = this; @@ -88,7 +91,7 @@ void oldChannelNotify::connectNotify ( cacChannel & ) ( *this->pConnCallBack ) ( args ); } -void oldChannelNotify::disconnectNotify ( cacChannel & ) +void oldChannelNotify::disconnectNotify () { struct connection_handler_args args; args.chid = this; @@ -96,7 +99,7 @@ void oldChannelNotify::disconnectNotify ( cacChannel & ) ( *this->pConnCallBack ) ( args ); } -void oldChannelNotify::accessRightsNotify ( cacChannel &, const caAccessRights &ar ) +void oldChannelNotify::accessRightsNotify ( const caAccessRights &ar ) { struct access_rights_handler_args args; args.chid = this; @@ -105,6 +108,11 @@ void oldChannelNotify::accessRightsNotify ( cacChannel &, const caAccessRights & ( *this->pAccessRightsFunc ) ( args ); } +void oldChannelNotify::exception ( int status, const char *pContext ) +{ + ca_signal ( status, pContext ); +} + bool oldChannelNotify::includeFirstConnectInCountOfOutstandingIO () const { return ( this->pConnCallBack == cacNoopConnHandler ); diff --git a/src/ca/oldSubscription.cpp b/src/ca/oldSubscription.cpp index b7d2656da..513c6f331 100644 --- a/src/ca/oldSubscription.cpp +++ b/src/ca/oldSubscription.cpp @@ -21,7 +21,7 @@ oldSubscription::~oldSubscription () this->chan.ioCancel ( this->id ); } -void oldSubscription::completion ( +void oldSubscription::current ( unsigned type, unsigned long count, const void *pData) { struct event_handler_args args; diff --git a/src/ca/recvProcessThread.cpp b/src/ca/recvProcessThread.cpp index 7375103fe..e87652191 100644 --- a/src/ca/recvProcessThread.cpp +++ b/src/ca/recvProcessThread.cpp @@ -16,8 +16,14 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" -#include "cac_IL.h" +#include "cac.h" + +#define epicsExportSharedSymbols +#include "cadef.h" +#undef epicsExportSharedSymbols recvProcessThread::recvProcessThread (cac *pcacIn) : thread ( *this, "CAC-recv-process", @@ -135,24 +141,24 @@ void recvProcessThread::signalActivity () void recvProcessThread::show ( unsigned level ) const { epicsAutoMutex autoMutex ( this->mutex ); - printf ( "CA receive processing thread at %p state=%s\n", + ::printf ( "CA receive processing thread at %p state=%s\n", static_cast ( this ), this->processing ? "busy" : "idle"); if ( level > 0u ) { - printf ( "enable count %u\n", this->enableRefCount ); - printf ( "blocking for completion count %u\n", this->blockingForCompletion ); + ::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", static_cast < void * > ( this->pcac ) ); - printf ( "\tshutdown command boolean %u\n", this->shutDown ); + ::printf ( "\tCA client at %p\n", static_cast < void * > ( this->pcac ) ); + ::printf ( "\tshutdown command boolean %u\n", this->shutDown ); } if ( level > 2u ) { - printf ( "Receive activity event:\n" ); + ::printf ( "Receive activity event:\n" ); this->recvActivity.show ( level - 3u ); - printf ( "exit event:\n" ); + ::printf ( "exit event:\n" ); this->exit.show ( level - 3u ); - printf ( "processing done event:\n" ); + ::printf ( "processing done event:\n" ); this->processingDone.show ( level - 3u ); - printf ( "mutex:\n" ); + ::printf ( "mutex:\n" ); this->mutex.show ( level - 3u ); } } diff --git a/src/ca/recvProcessThread_IL.h b/src/ca/recvProcessThread_IL.h deleted file mode 100644 index fb873bee5..000000000 --- a/src/ca/recvProcessThread_IL.h +++ /dev/null @@ -1,27 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef recvProcessThread_ILh -#define recvProcessThread_ILh - -inline bool recvProcessThread::isCurrentThread () const -{ - return this->thread.isCurrentThread (); -} - -#endif // recvProcessThread_ILh - diff --git a/src/ca/repeater.cpp b/src/ca/repeater.cpp index 3fe3b901c..768488b7b 100644 --- a/src/ca/repeater.cpp +++ b/src/ca/repeater.cpp @@ -54,8 +54,19 @@ * */ -#include "iocinf.h" -#include "taskwd.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + +#include "tsDLList.h" +#include "envdefs.h" +#include "tsFreeList.h" + +#include "iocinf.h" +#include "caProto.h" +#include "taskwd.h" + +#define epicsExportSharedSymbols +#include "udpiiu.h" +#undef epicsExportSharedSymbols /* * one socket per client so we will get the ECONNREFUSED @@ -141,8 +152,7 @@ LOCAL makeSocketReturn makeSocket ( unsigned short port, bool reuseAddr ) (char *) &flag, sizeof (flag) ); if ( status < 0 ) { int errnoCpy = SOCKERRNO; - ca_printf ( - "%s: set socket option failed because \"%s\"\n", + fprintf ( stderr, "%s: set socket option failed because \"%s\"\n", __FILE__, SOCKERRSTR(errnoCpy)); } } @@ -166,7 +176,7 @@ bool repeaterClient::connect () msr = makeSocket ( PORT_ANY, false ); if ( msr.sock == INVALID_SOCKET ) { - ca_printf ( "%s: no client sock because %d=\"%s\"\n", + fprintf ( stderr, "%s: no client sock because %d=\"%s\"\n", __FILE__, msr.errNumber, msr.pErrStr ); return false; } @@ -177,8 +187,7 @@ bool repeaterClient::connect () if ( status < 0 ) { int errnoCpy = SOCKERRNO; - ca_printf ( - "%s: unable to connect client sock because \"%s\"\n", + fprintf ( stderr, "%s: unable to connect client sock because \"%s\"\n", __FILE__, SOCKERRSTR ( errnoCpy ) ); return false; } @@ -204,7 +213,7 @@ bool repeaterClient::sendConfirm () return false; } else { - ca_printf ( "CA Repeater: confirm err was \"%s\"\n", + fprintf ( stderr, "CA Repeater: confirm err was \"%s\"\n", SOCKERRSTR (SOCKERRNO) ); return false; } @@ -297,8 +306,7 @@ bool repeaterClient::verify () * win sock does not set SOCKERRNO when this fails */ if ( msr.errNumber != SOCK_EADDRINUSE ) { - ca_printf ( -"CA Repeater: bind test err was %d=\"%s\"\n", + fprintf ( stderr, "CA Repeater: bind test err was %d=\"%s\"\n", msr.errNumber, msr.pErrStr ); } return true; @@ -375,7 +383,7 @@ LOCAL void register_new_client ( osiSockAddr &from ) if ( ! init ) { msr = makeSocket ( PORT_ANY, true ); if ( msr.sock == INVALID_SOCKET ) { - ca_printf ( "%s: Unable to create repeater bind test socket because %d=\"%s\"\n", + fprintf ( stderr, "%s: Unable to create repeater bind test socket because %d=\"%s\"\n", __FILE__, msr.errNumber, msr.pErrStr ); } else { @@ -425,7 +433,7 @@ LOCAL void register_new_client ( osiSockAddr &from ) else { pNewClient = new repeaterClient ( from ); if ( ! pNewClient ) { - ca_printf ( "%s: no memory for new client\n", __FILE__ ); + fprintf ( stderr, "%s: no memory for new client\n", __FILE__ ); return; } if ( ! pNewClient->connect () ) { @@ -470,9 +478,9 @@ LOCAL void register_new_client ( osiSockAddr &from ) /* - * ca_repeater() + * ca_repeater () */ -void epicsShareAPI ca_repeater () +void ca_repeater () { int size; SOCKET sock; @@ -494,7 +502,7 @@ void epicsShareAPI ca_repeater () debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) ); exit (0); } - ca_printf("%s: Unable to create repeater socket because %d=\"%s\" - fatal\n", + fprintf ( stderr, "%s: Unable to create repeater socket because %d=\"%s\" - fatal\n", __FILE__, msr.errNumber, msr.pErrStr); osiSockRelease (); exit(0); @@ -519,8 +527,8 @@ void epicsShareAPI ca_repeater () continue; } # endif - ca_printf ("CA Repeater: unexpected UDP recv err: %s\n", - SOCKERRSTR(errnoCpy)); + fprintf ( stderr, "CA Repeater: unexpected UDP recv err: %s\n", + SOCKERRSTR (errnoCpy) ); continue; } diff --git a/src/ca/repeaterSubscribeTimer.cpp b/src/ca/repeaterSubscribeTimer.cpp index afe69b631..3f819e998 100644 --- a/src/ca/repeaterSubscribeTimer.cpp +++ b/src/ca/repeaterSubscribeTimer.cpp @@ -12,7 +12,14 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "repeaterSubscribeTimer.h" + +#define epicsExportSharedSymbols +#include "udpiiu.h" +#undef epicsExportSharedSymbols repeaterSubscribeTimer::repeaterSubscribeTimer ( udpiiu &iiuIn, epicsTimerQueue &queueIn ) : timer ( queueIn.createTimer ( *this ) ), iiu ( iiuIn ), @@ -30,9 +37,9 @@ epicsTimerNotify::expireStatus repeaterSubscribeTimer::expire () { static const unsigned nTriesToMsg = 50; if ( this->attempts > nTriesToMsg && ! this->once ) { - ca_printf ( + this->iiu.printf ( "Unable to contact CA repeater after %u tries\n", nTriesToMsg); - ca_printf ( + this->iiu.printf ( "Silence this message by starting a CA repeater daemon\n"); this->once = true; } diff --git a/src/ca/repeaterSubscribeTimer.h b/src/ca/repeaterSubscribeTimer.h new file mode 100644 index 000000000..e2c96c579 --- /dev/null +++ b/src/ca/repeaterSubscribeTimer.h @@ -0,0 +1,40 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef repeaterSubscribeTimerh +#define repeaterSubscribeTimerh + +#include "epicsTimer.h" + +class udpiiu; + +class repeaterSubscribeTimer : private epicsTimerNotify { +public: + repeaterSubscribeTimer ( udpiiu &iiu, epicsTimerQueue &queue ); + virtual ~repeaterSubscribeTimer (); + void confirmNotify (); + void show (unsigned level) const; +private: + epicsTimer &timer; + udpiiu &iiu; + unsigned attempts; + bool registered; + bool once; + expireStatus expire (); +}; + +#endif // ifdef repeaterSubscribeTimerh diff --git a/src/ca/searchTimer.cpp b/src/ca/searchTimer.cpp index efa936359..539d12748 100644 --- a/src/ca/searchTimer.cpp +++ b/src/ca/searchTimer.cpp @@ -10,10 +10,18 @@ * Author: Jeff Hill */ +#include + +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "tsMinMax.h" #include "iocinf.h" -#include "netiiu_IL.h" +#include "searchTimer.h" + +#define epicsExportSharedSymbols +#include "udpiiu.h" +#undef epicsExportSharedSymbols // // searchTimer::searchTimer () diff --git a/src/ca/searchTimer.h b/src/ca/searchTimer.h new file mode 100644 index 000000000..0cfec4d5d --- /dev/null +++ b/src/ca/searchTimer.h @@ -0,0 +1,50 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef searchTimerh +#define searchTimerh + +#include "epicsTimer.h" +#include "epicsMutex.h" + +class udpiiu; + +class searchTimer : private epicsTimerNotify { +public: + searchTimer ( udpiiu &iiu, epicsTimerQueue &queue, epicsMutex & ); + virtual ~searchTimer (); + void notifySearchResponse ( unsigned short retrySeqNo ); + void resetPeriod ( double delayToNextTry ); + void show ( unsigned level ) const; +private: + epicsTimer &timer; + epicsMutex &mutex; + udpiiu &iiu; + unsigned framesPerTry; /* # of UDP frames per search try */ + unsigned framesPerTryCongestThresh; /* one half N tries w congest */ + unsigned minRetry; /* min retry number so far */ + unsigned retry; + unsigned searchTriesWithinThisPass; /* num search tries within this pass through the list */ + unsigned searchResponsesWithinThisPass; /* num search resp within this pass through the list */ + unsigned short retrySeqNo; /* search retry seq number */ + unsigned short retrySeqAtPassBegin; /* search retry seq number at beg of pass through list */ + double period; /* period between tries */ + expireStatus expire (); + void setRetryInterval (unsigned retryNo); +}; + +#endif // ifdef searchTimerh diff --git a/src/ca/syncGroup.h b/src/ca/syncGroup.h new file mode 100644 index 000000000..6848ad6ea --- /dev/null +++ b/src/ca/syncGroup.h @@ -0,0 +1,139 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef syncGrouph +#define syncGrouph + +#include "tsDLList.h" +#include "tsFreeList.h" +#include "resourceLib.h" +#include "epicsEvent.h" + +#define epicsExportSharedSymbols +#include "cadef.h" +#include "cacIO.h" +#undef epicsExportSharedSymbols + +static const unsigned CASG_MAGIC = 0xFAB4CAFE; + +// used to control access to CASG's recycle routines which +// should only be indirectly invoked by CASG when its lock +// is applied +class casgRecycle { +public: + virtual void recycleSyncGroupWriteNotify ( class syncGroupWriteNotify & io ) = 0; + virtual void recycleSyncGroupReadNotify ( class syncGroupReadNotify & io ) = 0; +}; + +class syncGroupNotify : public tsDLNode < syncGroupNotify > { +public: + syncGroupNotify ( struct CASG &sgIn, chid ); + virtual void destroy ( casgRecycle & ) = 0; + void show ( unsigned level ) const; +protected: + chid chan; + struct CASG &sg; + const unsigned magic; + cacChannel::ioid id; + bool idIsValid; + virtual ~syncGroupNotify (); +}; + +class syncGroupReadNotify : public syncGroupNotify, public cacReadNotify { +public: + static syncGroupReadNotify * factory ( + tsFreeList < class syncGroupReadNotify, 128 > &, + struct CASG &, chid, unsigned type, + unsigned long count, void *pValueIn ); + void destroy ( casgRecycle & ); + void show ( unsigned level ) const; +protected: + virtual ~syncGroupReadNotify (); +private: + void *pValue; + syncGroupReadNotify ( struct CASG &sgIn, chid, + unsigned type, unsigned long count, void *pValueIn ); + void * operator new ( size_t, + tsFreeList < class syncGroupReadNotify, 128 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class syncGroupReadNotify, 128 > & ); +# endif + void completion ( + unsigned type, unsigned long count, const void *pData ); + void exception ( + int status, const char *pContext, unsigned type, unsigned long count ); +}; + +class syncGroupWriteNotify : public syncGroupNotify, public cacWriteNotify { +public: + static syncGroupWriteNotify * factory ( + tsFreeList < class syncGroupWriteNotify, 128 > &, + struct CASG &, chid, unsigned type, + unsigned long count, const void *pValueIn ); + void destroy ( casgRecycle & ); + void show ( unsigned level ) const; +protected: + virtual ~syncGroupWriteNotify (); // allocate only from pool +private: + void *pValue; + syncGroupWriteNotify ( struct CASG &, chid, unsigned type, + unsigned long count, const void *pValueIn ); + void * operator new ( size_t, + tsFreeList < class syncGroupWriteNotify, 128 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class syncGroupWriteNotify, 128 > & ); +# endif + void completion (); + void exception (int status, const char *pContext ); +}; + +class oldCAC; + +struct CASG : public chronIntIdRes < CASG >, private casgRecycle { +public: + CASG ( oldCAC &cacIn ); + bool ioComplete () const; + void destroy (); + bool verify () const; + int block ( double timeout ); + void reset (); + void show ( unsigned level ) const; + int get ( chid pChan, unsigned type, unsigned long count, void *pValue ); + int put ( chid pChan, unsigned type, unsigned long count, const void *pValue ); + void destroyIO ( syncGroupNotify & ); + void * operator new ( size_t size ); + void operator delete ( void *pCadaver, size_t size ); + int printf ( const char * pFormat, ... ); +protected: + virtual ~CASG (); +private: + tsDLList < syncGroupNotify > ioList; + epicsMutex mutable mutex; + epicsEvent sem; + oldCAC & client; + unsigned magic; + tsFreeList < class syncGroupReadNotify, 128 > freeListReadOP; + tsFreeList < class syncGroupWriteNotify, 128 > freeListWriteOP; + void recycleSyncGroupWriteNotify ( syncGroupWriteNotify &io ); + void recycleSyncGroupReadNotify ( syncGroupReadNotify &io ); + static tsFreeList < struct CASG, 128 > freeList; + static epicsMutex freeListMutex; +}; + +#endif // ifdef syncGrouph diff --git a/src/ca/syncGroupNotify.cpp b/src/ca/syncGroupNotify.cpp index 6d02bf8ed..ea754be32 100644 --- a/src/ca/syncGroupNotify.cpp +++ b/src/ca/syncGroupNotify.cpp @@ -28,7 +28,10 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "syncGroup.h" #include "oldAccess.h" syncGroupNotify::syncGroupNotify ( CASG &sgIn, chid chanIn ) : @@ -46,7 +49,7 @@ syncGroupNotify::~syncGroupNotify () void syncGroupNotify::show ( unsigned /* level */ ) const { - printf ( "pending sg op: chan=%s magic=%u sg=%p\n", + ::printf ( "pending sg op: chan=%s magic=%u sg=%p\n", this->chan->pName(), this->magic, static_cast ( &this->sg ) ); } diff --git a/src/ca/syncGroupReadNotify.cpp b/src/ca/syncGroupReadNotify.cpp index 4dfb1d853..3415b2efd 100644 --- a/src/ca/syncGroupReadNotify.cpp +++ b/src/ca/syncGroupReadNotify.cpp @@ -28,7 +28,10 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "syncGroup.h" #include "oldAccess.h" syncGroupReadNotify::syncGroupReadNotify ( CASG &sgIn, chid pChan, @@ -62,7 +65,7 @@ void syncGroupReadNotify::completion ( unsigned type, unsigned long count, const void *pData ) { if ( this->magic != CASG_MAGIC ) { - ca_printf ("cac: sync group io_complete(): bad sync grp op magic number?\n"); + this->sg.printf ( "cac: sync group io_complete(): bad sync grp op magic number?\n" ); return; } @@ -90,7 +93,7 @@ void syncGroupReadNotify::exception ( void syncGroupReadNotify::show ( unsigned level ) const { - printf ( "pending sg read op: pVal=%p\n", this->pValue ); + ::printf ( "pending sg read op: pVal=%p\n", this->pValue ); if ( level > 0u ) { this->syncGroupNotify::show ( level - 1u ); } diff --git a/src/ca/syncGroupWriteNotify.cpp b/src/ca/syncGroupWriteNotify.cpp index 26d9c4a7c..89fa4a400 100644 --- a/src/ca/syncGroupWriteNotify.cpp +++ b/src/ca/syncGroupWriteNotify.cpp @@ -28,7 +28,10 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "syncGroup.h" #include "oldAccess.h" syncGroupWriteNotify::syncGroupWriteNotify ( CASG &sgIn, chid pChan, unsigned type, @@ -61,7 +64,7 @@ syncGroupWriteNotify::~syncGroupWriteNotify () void syncGroupWriteNotify::completion () { if ( this->magic != CASG_MAGIC ) { - ca_printf ("cac: sync group io_complete(): bad sync grp op magic number?\n"); + this->sg.printf ( "cac: sync group io_complete(): bad sync grp op magic number?\n" ); return; } @@ -84,7 +87,7 @@ void syncGroupWriteNotify::exception ( void syncGroupWriteNotify::show ( unsigned level ) const { - printf ( "pending write sg op\n" ); + ::printf ( "pending write sg op\n" ); if ( level > 0u ) { this->syncGroupNotify::show ( level - 1u ); } diff --git a/src/ca/syncgrp.cpp b/src/ca/syncgrp.cpp index 8bfa0e4cd..ccd3dc8d4 100644 --- a/src/ca/syncgrp.cpp +++ b/src/ca/syncgrp.cpp @@ -27,16 +27,22 @@ * */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "oldAccess.h" + +#define epicsExportSharedSymbols +#include "syncGroup.h" /* * ca_sg_create() */ -int epicsShareAPI ca_sg_create ( CA_SYNC_GID *pgid ) +extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID *pgid ) { int caStatus; CASG *pcasg; - cac *pcac; + oldCAC *pcac; caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { @@ -56,11 +62,11 @@ int epicsShareAPI ca_sg_create ( CA_SYNC_GID *pgid ) /* * ca_sg_delete() */ -int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid ) +extern "C" int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid ) { int caStatus; CASG *pcasg; - cac *pcac; + oldCAC *pcac; caStatus = fetchClientContext ( &pcac ); if ( caStatus != ECA_NORMAL ) { @@ -80,10 +86,10 @@ int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid ) /* * ca_sg_block () */ -int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeout ) +extern "C" int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeout ) { CASG *pcasg; - cac *pcac; + oldCAC *pcac; int status; status = fetchClientContext (&pcac); @@ -105,10 +111,10 @@ int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeout ) /* * ca_sg_reset */ -int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid ) +extern "C" int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid ) { CASG *pcasg; - cac *pcac; + oldCAC *pcac; int caStatus; caStatus = fetchClientContext (&pcac); @@ -131,10 +137,10 @@ int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid ) /* * ca_sg_stat */ -int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid ) +extern "C" int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid ) { CASG *pcasg; - cac *pcac; + oldCAC *pcac; int caStatus = fetchClientContext (&pcac); if ( caStatus != ECA_NORMAL ) { @@ -143,7 +149,7 @@ int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid ) pcasg = pcac->lookupCASG ( gid ); if ( ! pcasg ) { - printf("Bad Sync Group Id\n"); + ::printf ( "Bad Sync Group Id\n"); return ECA_BADSYNCGRP; } @@ -155,10 +161,10 @@ int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid ) /* * ca_sg_test */ -int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) +extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) { CASG *pcasg; - cac *pcac; + oldCAC *pcac; int caStatus; caStatus = fetchClientContext (&pcac); @@ -182,11 +188,11 @@ int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) /* * ca_sg_array_put() */ -int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype type, +extern "C" int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype type, unsigned long count, chid pChan, const void *pValue ) { CASG *pcasg; - cac *pcac; + oldCAC *pcac; int caStatus; caStatus = fetchClientContext ( &pcac ); @@ -205,11 +211,11 @@ int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype type, /* * ca_sg_array_get() */ -int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid, chtype type, +extern "C" int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid, chtype type, unsigned long count, chid pChan, void *pValue ) { CASG *pcasg; - cac *pcac; + oldCAC *pcac; int caStatus; caStatus = fetchClientContext ( &pcac ); diff --git a/src/ca/tcpRecvWatchdog.cpp b/src/ca/tcpRecvWatchdog.cpp index 3b0859d79..f18a7006f 100644 --- a/src/ca/tcpRecvWatchdog.cpp +++ b/src/ca/tcpRecvWatchdog.cpp @@ -10,7 +10,10 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "virtualCircuit.h" // // the recv watchdog timer is active when this object is created @@ -34,7 +37,7 @@ epicsTimerNotify::expireStatus tcpRecvWatchdog::expire () this->cancel (); char hostName[128]; this->iiu.hostName ( hostName, sizeof (hostName) ); - ca_printf ( "CA server \"%s\" unresponsive after %g inactive sec - disconnecting.\n", + this->iiu.printf ( "CA server \"%s\" unresponsive after %g inactive sec - disconnecting.\n", hostName, this->period ); this->iiu.forcedShutdown (); return noRestart; @@ -89,10 +92,10 @@ void tcpRecvWatchdog::cancel () void tcpRecvWatchdog::show ( unsigned level ) const { - printf ( "Receive virtual circuit watchdog at %p, period %f\n", + ::printf ( "Receive virtual circuit watchdog at %p, period %f\n", static_cast ( this ), this->period ); if ( level > 0u ) { - printf ( "\tresponse pending boolean %u, beacon anomaly boolean %u\n", + ::printf ( "\tresponse pending boolean %u, beacon anomaly boolean %u\n", this->responsePending, this->beaconAnomaly ); } } diff --git a/src/ca/tcpSendWatchdog.cpp b/src/ca/tcpSendWatchdog.cpp index d05db9cd7..cf0098725 100644 --- a/src/ca/tcpSendWatchdog.cpp +++ b/src/ca/tcpSendWatchdog.cpp @@ -10,7 +10,10 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + #include "iocinf.h" +#include "virtualCircuit.h" tcpSendWatchdog::tcpSendWatchdog ( tcpiiu &iiuIn, double periodIn, epicsTimerQueue & queueIn ) : @@ -28,7 +31,7 @@ epicsTimerNotify::expireStatus tcpSendWatchdog::expire () { char hostName[128]; this->iiu.hostName ( hostName, sizeof ( hostName ) ); - ca_printf ( "Request not accepted by CA server %s for %g sec. Disconnecting.\n", + this->iiu.printf ( "Request not accepted by CA server %s for %g sec. Disconnecting.\n", hostName, this->period ); this->iiu.forcedShutdown (); return noRestart; diff --git a/src/ca/tcpiiu.cpp b/src/ca/tcpiiu.cpp index 81acb218e..055c05b74 100644 --- a/src/ca/tcpiiu.cpp +++ b/src/ca/tcpiiu.cpp @@ -11,21 +11,21 @@ * Author: Jeff Hill */ -#include "iocinf.h" +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" -#include "inetAddrID_IL.h" -#include "bhe_IL.h" -#include "tcpiiu_IL.h" -#include "cac_IL.h" -#include "comBuf_IL.h" -#include "comQueSend_IL.h" -#include "netiiu_IL.h" -#include "nciu_IL.h" -#include "baseNMIU_IL.h" -#include "netWriteNotifyIO_IL.h" -#include "netReadNotifyIO_IL.h" -#include "netSubscription_IL.h" +#include "iocinf.h" +#include "virtualCircuit.h" +#include "inetAddrID.h" +#include "cac.h" +#include "netiiu.h" +#include "netIO.h" +#include "msgForMultiplyDefinedPV.h" +#include "localHostName.h" + +#define epicsExportSharedSymbols #include "net_convert.h" +#include "bhe.h" +#undef epicsExportSharedSymbols // nill message alignment pad bytes static const char nillBytes [] = @@ -131,7 +131,7 @@ unsigned tcpiiu::sendBytes ( const void *pBuf, if ( localError != SOCK_EPIPE && localError != SOCK_ECONNRESET && localError != SOCK_ETIMEDOUT && localError != SOCK_ECONNABORTED ) { - ca_printf ("CAC: unexpected TCP send error: %s\n", SOCKERRSTR (localError) ); + this->printf ( "CAC: unexpected TCP send error: %s\n", SOCKERRSTR (localError) ); } this->cleanShutdown (); @@ -181,7 +181,7 @@ unsigned tcpiiu::recvBytes ( void *pBuf, unsigned nBytesInBuf ) { char name[64]; this->hostName ( name, sizeof ( name ) ); - ca_printf ( "Disconnecting from CA server %s because: %s\n", + this->printf ( "Disconnecting from CA server %s because: %s\n", name, SOCKERRSTR ( localErrno ) ); } @@ -317,21 +317,21 @@ tcpiiu::tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue echoRequestPending ( false ), msgHeaderAvailable ( false ), sockCloseCompleted ( false ), - fdRegCallbackNeeded ( true ), + f_trueOnceOnly ( true ), earlyFlush ( false ) { this->addr.sa.sa_family = AF_UNSPEC; this->sendThreadExitSignal = epicsEventCreate ( epicsEventEmpty ); if ( ! this->sendThreadExitSignal ) { - ca_printf ("CA: unable to create CA client send thread exit semaphore\n"); + this->printf ("CA: unable to create CA client send thread exit semaphore\n"); this->fullyConstructedFlag = false; return; } this->recvThreadExitSignal = epicsEventCreate ( epicsEventEmpty ); if ( ! this->recvThreadExitSignal ) { - ca_printf ("CA: unable to create CA client send thread exit semaphore\n"); + this->printf ("CA: unable to create CA client send thread exit semaphore\n"); epicsEventDestroy (this->sendThreadExitSignal); this->fullyConstructedFlag = false; return; @@ -339,7 +339,7 @@ tcpiiu::tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue this->sendThreadFlushSignal = epicsEventCreate ( epicsEventEmpty ); if ( ! this->sendThreadFlushSignal ) { - ca_printf ("CA: unable to create sendThreadFlushSignal object\n"); + this->printf ("CA: unable to create sendThreadFlushSignal object\n"); epicsEventDestroy (this->sendThreadExitSignal); this->fullyConstructedFlag = false; return; @@ -347,7 +347,7 @@ tcpiiu::tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue this->flushBlockSignal = epicsEventCreate ( epicsEventEmpty ); if ( ! this->flushBlockSignal ) { - ca_printf ("CA: unable to create flushBlockSignal object\n"); + this->printf ("CA: unable to create flushBlockSignal object\n"); epicsEventDestroy (this->sendThreadExitSignal); epicsEventDestroy (this->sendThreadFlushSignal); this->fullyConstructedFlag = false; @@ -356,7 +356,7 @@ tcpiiu::tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue this->recvThreadRingBufferSpaceAvailableSignal = epicsEventCreate ( epicsEventEmpty ); if ( ! this->recvThreadRingBufferSpaceAvailableSignal ) { - ca_printf ("CA: unable to create recvThreadRingBufferSpaceAvailableSignal object\n"); + this->printf ("CA: unable to create recvThreadRingBufferSpaceAvailableSignal object\n"); epicsEventDestroy (this->sendThreadExitSignal); epicsEventDestroy (this->sendThreadFlushSignal); epicsEventDestroy (this->flushBlockSignal); @@ -405,7 +405,7 @@ bool tcpiiu::initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, this->sock = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if ( this->sock == INVALID_SOCKET ) { - ca_printf ( "CAC: unable to create virtual circuit because \"%s\"\n", + this->printf ( "CAC: unable to create virtual circuit because \"%s\"\n", SOCKERRSTR ( SOCKERRNO ) ); return false; } @@ -414,7 +414,7 @@ bool tcpiiu::initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, status = setsockopt ( this->sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof ( flag ) ); if ( status < 0 ) { - ca_printf ("CAC: problems setting socket option TCP_NODELAY = \"%s\"\n", + this->printf ("CAC: problems setting socket option TCP_NODELAY = \"%s\"\n", SOCKERRSTR (SOCKERRNO)); } @@ -422,7 +422,7 @@ bool tcpiiu::initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, status = setsockopt ( this->sock , SOL_SOCKET, SO_KEEPALIVE, ( char * ) &flag, sizeof ( flag ) ); if ( status < 0 ) { - ca_printf ( "CAC: problems setting socket option SO_KEEPALIVE = \"%s\"\n", + this->printf ( "CAC: problems setting socket option SO_KEEPALIVE = \"%s\"\n", SOCKERRSTR ( SOCKERRNO ) ); } @@ -438,14 +438,14 @@ bool tcpiiu::initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, status = setsockopt ( this->sock, SOL_SOCKET, SO_SNDBUF, ( char * ) &i, sizeof ( i ) ); if (status < 0) { - ca_printf ("CAC: problems setting socket option SO_SNDBUF = \"%s\"\n", + this->printf ("CAC: problems setting socket option SO_SNDBUF = \"%s\"\n", SOCKERRSTR ( SOCKERRNO ) ); } i = MAX_MSG_SIZE; status = setsockopt ( this->sock, SOL_SOCKET, SO_RCVBUF, ( char * ) &i, sizeof ( i ) ); if ( status < 0 ) { - ca_printf ("CAC: problems setting socket option SO_RCVBUF = \"%s\"\n", + this->printf ("CAC: problems setting socket option SO_RCVBUF = \"%s\"\n", SOCKERRSTR (SOCKERRNO)); } } @@ -461,7 +461,7 @@ bool tcpiiu::initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, tid = epicsThreadCreate ("CAC-TCP-recv", priorityOfRecv, epicsThreadGetStackSize (epicsThreadStackMedium), cacRecvThreadTCP, this); if ( tid == 0 ) { - ca_printf ("CA: unable to create CA client receive thread\n"); + this->printf ("CA: unable to create CA client receive thread\n"); socket_close ( this->sock ); return false; } @@ -516,7 +516,7 @@ void tcpiiu::connect () } else { this->sendDog.cancel (); - ca_printf ( "Unable to connect because %d=\"%s\"\n", + this->printf ( "Unable to connect because %d=\"%s\"\n", errnoCpy, SOCKERRSTR ( errnoCpy ) ); this->cleanShutdown (); return; @@ -699,7 +699,6 @@ tcpiiu::~tcpiiu () this->sendQue.clear (); this->recvQue.clear (); } - this->fdRegCallbackNeeded = true; // wakeup user threads blocking for send backlog to be reduced // and wait for them to stop using this IIU @@ -778,31 +777,31 @@ void tcpiiu::show ( unsigned level ) const strncpy ( buf, "", sizeof ( buf ) ); buf [ sizeof ( buf ) - 1 ] = '\0'; } - printf ( "Virtual circuit to \"%s\" at version %u.%u state %u\n", + ::printf ( "Virtual circuit to \"%s\" at version %u.%u state %u\n", buf, CA_PROTOCOL_VERSION, this->minorProtocolVersion, this->state ); if ( level > 1u ) { this->netiiu::show ( level - 1u ); } if ( level > 2u ) { - printf ( "\tcurrent data cache pointer = %p current data cache size = %lu\n", + ::printf ( "\tcurrent data cache pointer = %p current data cache size = %lu\n", static_cast < void * > ( this->pCurData ), this->curDataMax ); - printf ( "\tcontiguous receive message count=%u, busy detect bool=%u, flow control bool=%u\n", + ::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" ); + ::printf ( "\tvirtual circuit socket identifier %d\n", this->sock ); + ::printf ( "\tsend thread flush signal:\n" ); epicsEventShow ( this->sendThreadFlushSignal, level-3u ); - printf ( "\trecv thread buffer space available signal:\n" ); + ::printf ( "\trecv thread buffer space available signal:\n" ); epicsEventShow ( this->recvThreadRingBufferSpaceAvailableSignal, level-3u ); - printf ( "\tsend thread exit signal:\n" ); + ::printf ( "\tsend thread exit signal:\n" ); epicsEventShow ( this->sendThreadExitSignal, level-3u ); - printf ( "\trecv thread exit signal:\n" ); + ::printf ( "\trecv thread exit signal:\n" ); epicsEventShow ( this->recvThreadExitSignal, level-3u ); - printf ( "\tfully constructed bool %u\n", this->fullyConstructedFlag ); - printf ("\techo pending bool = %u\n", this->echoRequestPending ); - printf ("\treceive message header available bool = %u\n", this->msgHeaderAvailable ); + ::printf ( "\tfully constructed bool %u\n", this->fullyConstructedFlag ); + ::printf ("\techo pending bool = %u\n", this->echoRequestPending ); + ::printf ("\treceive message header available bool = %u\n", this->msgHeaderAvailable ); if ( this->pBHE ) { this->pBHE->show ( level - 3u ); } @@ -1011,7 +1010,7 @@ void tcpiiu::processIncoming () // if ( this->curMsg.m_postsize > ( unsigned ) MAX_TCP ) { this->msgHeaderAvailable = false; - ca_printf ( "CAC: message body was too large ( disconnecting )\n" ); + this->printf ( "CAC: message body was too large ( disconnecting )\n" ); this->cleanShutdown (); return; } @@ -1035,7 +1034,7 @@ void tcpiiu::processIncoming () char *pData = new char [cacheSize]; if ( ! pData ) { - ca_printf ("CAC: not enough memory for message body cache (disconnecting)\n"); + this->printf ("CAC: not enough memory for message body cache (disconnecting)\n"); this->cleanShutdown (); return; } diff --git a/src/ca/tcpiiu_IL.h b/src/ca/tcpiiu_IL.h deleted file mode 100644 index 0384b3c75..000000000 --- a/src/ca/tcpiiu_IL.h +++ /dev/null @@ -1,94 +0,0 @@ - - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -inline bool tcpiiu::fullyConstructed () const -{ - return this->fullyConstructedFlag; -} - -inline void tcpiiu::hostName ( char *pBuf, unsigned bufLength ) const -{ - if ( this->pHostNameCache ) { - this->pHostNameCache->hostName ( pBuf, bufLength ); - } - else { - netiiu::hostName ( pBuf, bufLength ); - } -} - -// deprecated - please dont use - this is _not_ thread safe -inline const char * tcpiiu::pHostName () const -{ - static char nameBuf [128]; - this->hostName ( nameBuf, sizeof ( nameBuf ) ); - return nameBuf; // ouch !! -} - -inline void tcpiiu::flushRequest () -{ - epicsEventSignal ( this->sendThreadFlushSignal ); -} - -inline bool tcpiiu::ca_v44_ok () const -{ - return CA_V44 ( CA_PROTOCOL_VERSION, this->minorProtocolVersion ); -} - -inline bool tcpiiu::ca_v41_ok () const -{ - return CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersion ); -} - -inline bool tcpiiu::alive () const -{ - if ( this->state == iiu_connecting || - this->state == iiu_connected ) { - return true; - } - else { - return false; - } -} - -inline bhe * tcpiiu::getBHE () const -{ - return this->pBHE; -} - -inline void tcpiiu::beaconAnomalyNotify () -{ - this->recvDog.beaconAnomalyNotify (); -} - -inline void tcpiiu::beaconArrivalNotify () -{ - this->recvDog.beaconArrivalNotify (); -} - -inline void tcpiiu::fdCreateNotify ( epicsMutex &mutex, CAFDHANDLER *func, void *pArg ) -{ - if ( this->fdRegCallbackNeeded ) { - epicsAutoMutexRelease autoRelease ( mutex ); - ( *func ) ( pArg, this->sock, true ); - } -} - -inline void tcpiiu::fdDestroyNotify ( CAFDHANDLER *func, void *pArg ) -{ - ( *func ) ( pArg, this->sock, false ); -} diff --git a/src/ca/test_event.cpp b/src/ca/test_event.cpp index 133ece35e..b730adf8b 100644 --- a/src/ca/test_event.cpp +++ b/src/ca/test_event.cpp @@ -3,73 +3,64 @@ * T E S T _ E V E N T . C * Author: Jeffrey O. Hill * simple stub for testing monitors - * - * - * History - * joh 031891 printed type in decimal instead of hex - * joh 072792 better messages - * - * - * - * */ -#include "iocinf.h" +#define epicsExportSharedSymbols +#include "cadef.h" - -void epicsShareAPI ca_test_event(struct event_handler_args args) +extern "C" void epicsShareAPI ca_test_event ( struct event_handler_args args ) { - printf ("CAC: ~~~### in test event for [%s] ###~~~\n", ca_name(args.chid)); - printf ("CAC: User argument\t%p\n", args.usr); - printf ("CAC: Native channel data type\t%d\n", ca_field_type(args.chid)); - printf ("CAC: Monitor data type\t%ld\n", args.type); - printf ("CAC: CA Status \"%s\"\n", ca_message(args.status)); + printf ( "CAC: ~~~### in test event for [%s] ###~~~\n", ca_name(args.chid) ); + printf ( "CAC: User argument\t%p\n", args.usr); + printf ( "CAC: Native channel data type\t%d\n", ca_field_type(args.chid) ); + printf ( "CAC: Monitor data type\t%ld\n", args.type ); + printf ( "CAC: CA Status \"%s\"\n", ca_message(args.status) ); - if(!args.dbr || !(CA_M_SUCCESS&args.status)){ + if ( !args.dbr || !(CA_M_SUCCESS&args.status) ){ return; } - switch(args.type){ + switch ( args.type ) { case DBR_STRING: - printf ("CAC: Value:\t<%s>\n", (const char *)args.dbr); + printf ( "CAC: Value:\t<%s>\n", (const char *) args.dbr ); break; case DBR_CHAR: - printf ("CAC: Value:\t<%d>\n",*(char *)args.dbr); + printf ( "CAC: Value:\t<%d>\n", *(char *) args.dbr ); break; #if DBR_INT != DBR_SHORT case DBR_INT: #endif case DBR_SHORT: case DBR_ENUM: - printf ("CAC: Value:\t<%d>\n",*(short *)args.dbr); + printf ( "CAC: Value:\t<%d>\n", *(short *) args.dbr ); break; case DBR_LONG: - printf ("CAC: Value:\t<%ld>\n",*(long *)args.dbr); + printf ( "CAC: Value:\t<%ld>\n", *(long *)args.dbr ); break; case DBR_FLOAT: - printf ("CAC: Value:\t<%f>\n",*(float *)args.dbr); + printf ( "CAC: Value:\t<%f>\n", *(float *)args.dbr ); break; case DBR_DOUBLE: - printf ("CAC: Value:\t<%f>\n",*(double *)args.dbr); + printf ( "CAC: Value:\t<%f>\n", *(double *)args.dbr ); break; case DBR_STS_STRING: - printf ("CAC: Value:\t<%s>\n",((struct dbr_sts_string *)args.dbr)->value); + printf ( "CAC: Value:\t<%s>\n", ((struct dbr_sts_string *)args.dbr)->value ); break; case DBR_STS_INT: - printf ("CAC: Value:\t<%d>\n",((struct dbr_sts_int *)args.dbr)->value); + printf ( "CAC: Value:\t<%d>\n", ((struct dbr_sts_int *)args.dbr)->value ); break; case DBR_STS_FLOAT: - printf ("CAC: Value:\t<%f>\n",((struct dbr_sts_float *)args.dbr)->value); + printf ( "CAC: Value:\t<%f>\n",((struct dbr_sts_float *)args.dbr)->value ); break; case DBR_STS_ENUM: - printf ("CAC: Value:\t<%d>\n",((struct dbr_sts_enum *)args.dbr)->value); + printf ( "CAC: Value:\t<%d>\n", ((struct dbr_sts_enum *)args.dbr)->value ); break; case DBR_GR_FLOAT: - printf ("CAC: Value:\t<%f>\n",((struct dbr_gr_float *)args.dbr)->value); + printf ( "CAC: Value:\t<%f>\n", ((struct dbr_gr_float *)args.dbr)->value ); break; default: - printf ( "CAC: Sorry test_event does not handle data type %ld yet\n", - args.type); + printf ( "CAC: Sorry test_event does not handle data type %ld yet\n", + args.type ); } } diff --git a/src/ca/udpiiu.cpp b/src/ca/udpiiu.cpp index 3fbb6bab8..e6295c14a 100644 --- a/src/ca/udpiiu.cpp +++ b/src/ca/udpiiu.cpp @@ -10,13 +10,20 @@ * Author: Jeff Hill */ +#define epicsAssertAuthor "Jeff Hill johill@lanl.gov" + +#include "envdefs.h" #include "osiProcess.h" -#include "iocinf.h" +#define epicsExportSharedSymbols #include "addrList.h" -#include "inetAddrID_IL.h" -#include "netiiu_IL.h" -#include "cac_IL.h" +#include "caerr.h" // for ECA_NOSEARCHADDR +#include "udpiiu.h" +#undef epicsExportSharedSymbols + +#include "iocinf.h" +#include "inetAddrID.h" +#include "cac.h" // UDP protocol dispatch table const udpiiu::pProtoStubUDP udpiiu::udpJumpTableCAC [] = @@ -60,7 +67,7 @@ udpiiu::udpiiu ( cac &cac ) : this->sock = socket ( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); if ( this->sock == INVALID_SOCKET ) { - ca_printf ("CAC: unable to create datagram socket because = \"%s\"\n", + this->printf ("CAC: unable to create datagram socket because = \"%s\"\n", SOCKERRSTR (SOCKERRNO)); throwWithLocation ( noSocket () ); } @@ -68,7 +75,7 @@ udpiiu::udpiiu ( cac &cac ) : status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST, (char *) &boolValue, sizeof ( boolValue ) ); if ( status < 0 ) { - ca_printf ("CAC: IP broadcasting enable failed because = \"%s\"\n", + this->printf ("CAC: IP broadcasting enable failed because = \"%s\"\n", SOCKERRSTR ( SOCKERRNO ) ); } @@ -84,7 +91,7 @@ udpiiu::udpiiu ( cac &cac ) : status = setsockopt ( this->sock, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof (size) ); if (status<0) { - ca_printf ("CAC: unable to set socket option SO_RCVBUF because \"%s\"\n", + this->printf ("CAC: unable to set socket option SO_RCVBUF because \"%s\"\n", SOCKERRSTR (SOCKERRNO)); } } @@ -101,7 +108,7 @@ udpiiu::udpiiu ( cac &cac ) : status = bind (this->sock, &addr.sa, sizeof (addr) ); if ( status < 0 ) { socket_close (this->sock); - ca_printf ("CAC: unable to bind to an unconstrained address because = \"%s\"\n", + this->printf ("CAC: unable to bind to an unconstrained address because = \"%s\"\n", SOCKERRSTR (SOCKERRNO)); throwWithLocation ( noSocket () ); } @@ -154,7 +161,7 @@ udpiiu::udpiiu ( cac &cac ) : this->recvThreadId = epicsThreadCreate ( "CAC-UDP", priorityOfRecv, epicsThreadGetStackSize (epicsThreadStackMedium), cacRecvThreadUDP, this ); if ( this->recvThreadId == 0 ) { - ca_printf ("CA: unable to create UDP receive thread\n"); + this->printf ("CA: unable to create UDP receive thread\n"); epicsEventDestroy (this->recvThreadExitSignal); socket_close (this->sock); throwWithLocation ( noMemory () ); @@ -221,7 +228,7 @@ void udpiiu::recvMsg () return; } # endif - ca_printf ( "Unexpected UDP recv error was \"%s\"\n", + this->printf ( "Unexpected UDP recv error was \"%s\"\n", SOCKERRSTR (errnoCpy) ); } else if ( status > 0 ) { @@ -258,7 +265,7 @@ void udpiiu::repeaterRegistrationMessage ( unsigned attemptNumber ) * * register with the repeater */ -epicsShareFunc void epicsShareAPI caRepeaterRegistrationMessage ( +void epicsShareAPI caRepeaterRegistrationMessage ( SOCKET sock, unsigned repeaterPort, unsigned attemptNumber ) { caHdr msg; @@ -339,7 +346,7 @@ epicsShareFunc void epicsShareAPI caRepeaterRegistrationMessage ( if ( errnoCpy != SOCK_EINTR && errnoCpy != SOCK_ECONNREFUSED && errnoCpy != SOCK_ECONNRESET ) { - ca_printf ( "CAC: error sending registration message to CA repeater daemon was \"%s\"\n", + fprintf ( stderr, "error sending registration message to CA repeater daemon was \"%s\"\n", SOCKERRSTR ( errnoCpy ) ); } } @@ -369,7 +376,7 @@ epicsShareFunc void epicsShareAPI caRepeaterRegistrationMessage ( * * 072392 - problem solved by using SO_REUSEADDR */ -epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repeaterPort ) +void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repeaterPort ) { bool installed = false; int status; @@ -378,7 +385,7 @@ epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repea int flag; if ( repeaterPort > 0xffff ) { - ca_printf ( "caStartRepeaterIfNotInstalled () : strange repeater port specified\n"); + fprintf ( stderr, "caStartRepeaterIfNotInstalled () : strange repeater port specified\n" ); return; } @@ -395,7 +402,7 @@ epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repea installed = true; } else { - ca_printf ( "caStartRepeaterIfNotInstalled () : bind failed\n"); + fprintf ( stderr, "caStartRepeaterIfNotInstalled () : bind failed\n" ); } } } @@ -408,7 +415,7 @@ epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repea status = setsockopt ( tmpSock, SOL_SOCKET, SO_REUSEADDR, (char *) &flag, sizeof ( flag ) ); if ( status < 0 ) { - ca_printf ( "caStartRepeaterIfNotInstalled () : set socket option reuseaddr set failed\n"); + fprintf ( stderr, "caStartRepeaterIfNotInstalled () : set socket option reuseaddr set failed\n" ); } socket_close ( tmpSock ); @@ -427,13 +434,13 @@ epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repea epicsThreadId tid; tid = epicsThreadCreate ( "CAC-repeater", epicsThreadPriorityLow, - epicsThreadGetStackSize (epicsThreadStackMedium), caRepeaterThread, 0); + epicsThreadGetStackSize ( epicsThreadStackMedium ), caRepeaterThread, 0); if ( tid == 0 ) { - ca_printf ("caStartRepeaterIfNotInstalled : unable to create CA repeater daemon thread\n"); + fprintf ( stderr, "caStartRepeaterIfNotInstalled : unable to create CA repeater daemon thread\n" ); } } else if ( osptr == osiSpawnDetachedProcessFail ) { - ca_printf ( "caStartRepeaterIfNotInstalled (): unable to start CA repeater daemon detached process\n" ); + fprintf ( stderr, "caStartRepeaterIfNotInstalled (): unable to start CA repeater daemon detached process\n" ); } } } @@ -482,7 +489,7 @@ bool udpiiu::badUDPRespAction ( const caHdr &msg, const osiSockAddr &netAddr ) { char buf[64]; sockAddrToDottedIP ( &netAddr.sa, buf, sizeof ( buf ) ); - ca_printf ( "CAC: undecipherable ( bad msg code %u ) UDP message from %s\n", + this->printf ( "CAC: undecipherable ( bad msg code %u ) UDP message from %s\n", msg.m_cmmd, buf ); return false; } @@ -636,7 +643,7 @@ void udpiiu::postMsg ( const osiSockAddr &net_addr, if ( blockSize < sizeof ( *pCurMsg ) ) { char buf[64]; sockAddrToDottedIP ( &net_addr.sa, buf, sizeof ( buf ) ); - ca_printf ( + this->printf ( "%s: undecipherable (too small) UDP msg from %s ignored\n", __FILE__, buf ); return; @@ -671,7 +678,7 @@ void udpiiu::postMsg ( const osiSockAddr &net_addr, if ( size > blockSize ) { char buf[64]; sockAddrToDottedIP ( &net_addr.sa, buf, sizeof ( buf ) ); - ca_printf ( + this->printf ( "%s: undecipherable (payload too small) UDP msg from %s ignored\n", __FILE__, buf ); return; @@ -691,7 +698,7 @@ void udpiiu::postMsg ( const osiSockAddr &net_addr, if ( ! success ) { char buf[256]; sockAddrToDottedIP ( &net_addr.sa, buf, sizeof ( buf ) ); - ca_printf ( "CAC: undecipherable UDP message from %s\n", buf ); + this->printf ( "CAC: undecipherable UDP message from %s\n", buf ); return; } @@ -753,7 +760,7 @@ void udpiiu::datagramFlush () &pNode->addr.sa, sizeof ( pNode->addr.sa ) ); if ( status != (int) this->nBytesInXmitBuf ) { if ( status >= 0 ) { - ca_printf ( "CAC: UDP sendto () call returned strange xmit count?\n" ); + this->printf ( "CAC: UDP sendto () call returned strange xmit count?\n" ); break; } else { @@ -781,7 +788,7 @@ void udpiiu::datagramFlush () sockAddrToDottedIP ( &pNode->addr.sa, buf, sizeof ( buf ) ); - ca_printf ( + this->printf ( "CAC: error = \"%s\" sending UDP msg to %s\n", SOCKERRSTR ( localErrno ), buf); break; @@ -796,20 +803,20 @@ void udpiiu::datagramFlush () void udpiiu::show ( unsigned level ) const { - printf ( "Datagram IO circuit (and disconnected channel repository)\n"); + ::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 ); + ::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" ); + ::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" ); epicsEventShow ( this->recvThreadExitSignal, level-3u ); } } diff --git a/src/ca/udpiiu.h b/src/ca/udpiiu.h new file mode 100644 index 000000000..d4519d107 --- /dev/null +++ b/src/ca/udpiiu.h @@ -0,0 +1,111 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef udpiiuh +#define udpiiuh + +#ifdef epicsExportSharedSymbols +# define udpiiuh_accessh_epicsExportSharedSymbols +# undef epicsExportSharedSymbols +#endif + +# include "osiSock.h" +# include "epicsThread.h" + +#ifdef udpiiuh_accessh_epicsExportSharedSymbols +# define epicsExportSharedSymbols +#endif + +#include "netiiu.h" + +extern "C" void cacRecvThreadUDP ( void *pParam ); + +epicsShareFunc void epicsShareAPI caStartRepeaterIfNotInstalled ( unsigned repeaterPort ); +epicsShareFunc void epicsShareAPI caRepeaterRegistrationMessage ( SOCKET sock, unsigned repeaterPort, unsigned attemptNumber ); +epicsShareFunc void caRepeaterThread ( void *pDummy ); +epicsShareFunc void ca_repeater ( void ); + +class udpiiu : public netiiu { +public: + udpiiu ( class cac & ); + virtual ~udpiiu (); + void shutdown (); + void recvMsg (); + void postMsg ( const osiSockAddr &net_addr, + char *pInBuf, unsigned long blockSize ); + void repeaterRegistrationMessage ( unsigned attemptNumber ); + void datagramFlush (); + unsigned getPort () const; + void show ( unsigned level ) const; + bool isCurrentThread () const; + + // exceptions + class noSocket {}; + class noMemory {}; + + SOCKET getSock () const; + +private: + char xmitBuf [MAX_UDP_SEND]; + char recvBuf [MAX_UDP_RECV]; + ELLLIST dest; + epicsThreadId recvThreadId; + epicsEventId recvThreadExitSignal; + unsigned nBytesInXmitBuf; + SOCKET sock; + unsigned short repeaterPort; + unsigned short serverPort; + unsigned short localPort; + bool shutdownCmd; + bool sockCloseCompleted; + + bool pushDatagramMsg ( const caHdr &msg, const void *pExt, ca_uint16_t extsize ); + + typedef bool ( udpiiu::*pProtoStubUDP ) ( const caHdr &, const osiSockAddr & ); + + // UDP protocol dispatch table + static const pProtoStubUDP udpJumpTableCAC[]; + + // UDP protocol stubs + bool noopAction ( const caHdr &, const osiSockAddr & ); + bool badUDPRespAction ( const caHdr &msg, const osiSockAddr &netAddr ); + bool searchRespAction ( const caHdr &msg, const osiSockAddr &net_addr ); + bool exceptionRespAction ( const caHdr &msg, const osiSockAddr &net_addr ); + bool beaconAction ( const caHdr &msg, const osiSockAddr &net_addr ); + bool notHereRespAction ( const caHdr &msg, const osiSockAddr &net_addr ); + bool repeaterAckAction ( const caHdr &msg, const osiSockAddr &net_addr ); + + friend void cacRecvThreadUDP ( void *pParam ); +}; + +inline bool udpiiu::isCurrentThread () const +{ + return ( this->recvThreadId == epicsThreadGetIdSelf () ); +} + +inline unsigned udpiiu::getPort () const +{ + return this->localPort; +} + +inline SOCKET udpiiu::getSock () const +{ + return this->sock; +} + +#endif // udpiiuh + diff --git a/src/ca/udpiiu_IL.h b/src/ca/udpiiu_IL.h deleted file mode 100644 index 2fe1137cd..000000000 --- a/src/ca/udpiiu_IL.h +++ /dev/null @@ -1,42 +0,0 @@ - -/* - * $Id$ - * - * - * L O S A L A M O S - * Los Alamos National Laboratory - * Los Alamos, New Mexico 87545 - * - * Copyright, 1986, The Regents of the University of California. - * - * - * Author Jeffrey O. Hill - * johill@lanl.gov - * 505 665 1831 - */ - -#ifndef udpiiu_ILh -#define udpiiu_ILh - -inline bool udpiiu::isCurrentThread () const -{ - return ( this->recvThreadId == epicsThreadGetIdSelf () ); -} - -inline unsigned udpiiu::getPort () const -{ - return this->localPort; -} - -inline void udpiiu::fdCreateNotify ( CAFDHANDLER *func, void *pArg ) -{ - ( *func ) ( pArg, this->sock, true ); -} - -inline void udpiiu::fdDestroyNotify ( CAFDHANDLER *func, void *pArg ) -{ - ( *func ) ( pArg, this->sock, false ); -} - -#endif // udpiiu_ILh - diff --git a/src/ca/virtualCircuit.h b/src/ca/virtualCircuit.h new file mode 100644 index 000000000..220839cc6 --- /dev/null +++ b/src/ca/virtualCircuit.h @@ -0,0 +1,498 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + */ + +#ifndef virtualCircuith +#define virtualCircuith + +#include // needed by comQueueSend + +#include "epicsTimer.h" +#include "ipAddrToAsciiAsynchronous.h" + +#include "comBuf.h" +#include "netiiu.h" + +enum iiu_conn_state {iiu_connecting, iiu_connected, iiu_disconnected}; + +class nciu; +class tcpiiu; + +class bufferReservoir { +public: + ~bufferReservoir (); + void addOneBuffer (); + comBuf *fetchOneBuffer (); + unsigned nBytes (); + void drain (); +private: + tsDLList < comBuf > reservedBufs; +}; + +class comQueSend { +public: + comQueSend ( wireSendAdapter & ); + ~comQueSend (); + void clear (); + void reserveSpace ( unsigned msgSize ); + unsigned occupiedBytes () const; + bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const; + bool flushBlockThreshold ( unsigned nBytesThisMsg ) const; + bool dbr_type_ok ( unsigned type ); + void pushUInt16 ( const ca_uint16_t value ); + void pushUInt32 ( const ca_uint32_t value ); + void pushFloat32 ( const ca_float32_t value ); + void pushString ( const char *pVal, unsigned nElem ); + void push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ); + comBuf * popNextComBufToSend (); +private: + wireSendAdapter & wire; + tsDLList < comBuf > bufs; + bufferReservoir reservoir; + unsigned nBytesPending; + void copy_dbr_string ( const void *pValue, unsigned nElem ); + void copy_dbr_short ( const void *pValue, unsigned nElem ); + void copy_dbr_float ( const void *pValue, unsigned nElem ); + void copy_dbr_char ( const void *pValue, unsigned nElem ); + void copy_dbr_long ( const void *pValue, unsigned nElem ); + void copy_dbr_double ( const void *pValue, unsigned nElem ); + typedef void ( comQueSend::*copyFunc_t ) ( + const void *pValue, unsigned nElem ); + static const copyFunc_t dbrCopyVector [39]; +}; + +static const unsigned maxBytesPendingTCP = 0x4000; + +class comQueRecv { +public: + comQueRecv (); + ~comQueRecv (); + unsigned occupiedBytes () const; + bool copyOutBytes ( void *pBuf, unsigned nBytes ); + void pushLastComBufReceived ( comBuf & ); + void clear (); +private: + tsDLList < comBuf > bufs; +}; + +class tcpRecvWatchdog : private epicsTimerNotify { +public: + tcpRecvWatchdog ( tcpiiu &, double periodIn, epicsTimerQueue & queueIn ); + virtual ~tcpRecvWatchdog (); + void rescheduleRecvTimer (); + void messageArrivalNotify (); + void beaconArrivalNotify (); + void beaconAnomalyNotify (); + void connectNotify (); + void cancel (); + void show ( unsigned level ) const; +private: + const double period; + epicsTimer &timer; + tcpiiu &iiu; + bool responsePending; + bool beaconAnomaly; + expireStatus expire (); +}; + +class tcpSendWatchdog : private epicsTimerNotify { +public: + tcpSendWatchdog ( tcpiiu &, double periodIn, epicsTimerQueue & queueIn ); + virtual ~tcpSendWatchdog (); + void start (); + void cancel (); +private: + const double period; + epicsTimer &timer; + tcpiiu &iiu; + expireStatus expire (); +}; + +class hostNameCache : public ipAddrToAsciiAsynchronous { +public: + hostNameCache ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine ); + void destroy (); + void ioCompletionNotify ( const char *pHostName ); + void hostName ( char *pBuf, unsigned bufLength ) const; + void * operator new ( size_t size ); + void operator delete ( void *pCadaver, size_t size ); +protected: + ~hostNameCache (); +private: + bool ioComplete; + char hostNameBuf [128]; + static tsFreeList < class hostNameCache, 16 > freeList; + static epicsMutex freeListMutex; +}; + +extern "C" void cacSendThreadTCP ( void *pParam ); +extern "C" void cacRecvThreadTCP ( void *pParam ); + +class tcpiiu : + public netiiu, public tsDLNode < tcpiiu >, + private wireSendAdapter, private wireRecvAdapter { +public: + tcpiiu ( cac &cac, double connectionTimeout, epicsTimerQueue &timerQueue ); + ~tcpiiu (); + bool initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion, + class bhe &bhe, ipAddrToAsciiEngine &engineIn ); + void connect (); + void processIncoming (); + void destroy (); + void cleanShutdown (); + void forcedShutdown (); + void beaconAnomalyNotify (); + void beaconArrivalNotify (); + + bool fullyConstructed () const; + void flushRequest (); + bool flushBlockThreshold () const; + void flushRequestIfAboveEarlyThreshold (); + void blockUntilSendBacklogIsReasonable ( epicsMutex & ); + virtual void show ( unsigned level ) const; + bool setEchoRequestPending (); + + bool ca_v41_ok () const; + bool ca_v42_ok () const; + bool ca_v44_ok () const; + + void hostName ( char *pBuf, unsigned bufLength ) const; + const char * pHostName () const; // deprecated - please do not use + bool isVirtaulCircuit ( const char *pChannelName, const osiSockAddr &addr ) const; + bool alive () const; + double beaconPeriod () const; + bhe * getBHE () const; + + SOCKET getSock() const; + bool trueOnceOnly (); + +private: + tcpRecvWatchdog recvDog; + tcpSendWatchdog sendDog; + comQueSend sendQue; + comQueRecv recvQue; + osiSockAddr addr; + hostNameCache *pHostNameCache; + caHdr curMsg; + unsigned long curDataMax; + class bhe *pBHE; + char *pCurData; + unsigned minorProtocolVersion; + iiu_conn_state state; + epicsEventId sendThreadFlushSignal; + epicsEventId recvThreadRingBufferSpaceAvailableSignal; + epicsEventId sendThreadExitSignal; + epicsEventId recvThreadExitSignal; + epicsEventId flushBlockSignal; + SOCKET sock; + unsigned contigRecvMsgCount; + unsigned blockingForFlush; + bool fullyConstructedFlag; + bool busyStateDetected; // only modified by the recv thread + bool flowControlActive; // only modified by the send process thread + bool echoRequestPending; + bool msgHeaderAvailable; + bool sockCloseCompleted; + bool f_trueOnceOnly; + bool earlyFlush; + + unsigned sendBytes ( const void *pBuf, unsigned nBytesInBuf ); + unsigned recvBytes ( void *pBuf, unsigned nBytesInBuf ); + + friend void cacSendThreadTCP ( void *pParam ); + friend void cacRecvThreadTCP ( void *pParam ); + + void lastChannelDetachNotify (); + + // send protocol stubs + void echoRequest (); + void noopRequest (); + void disableFlowControlRequest (); + void enableFlowControlRequest (); + void hostNameSetRequest (); + void userNameSetRequest (); + void writeRequest ( nciu &, unsigned type, unsigned nElem, const void *pValue ); + void writeNotifyRequest ( nciu &, netWriteNotifyIO &, unsigned type, unsigned nElem, const void *pValue ); + void readNotifyRequest ( nciu &, netReadNotifyIO &, unsigned type, unsigned nElem ); + void createChannelRequest ( nciu & ); + void clearChannelRequest ( nciu & ); + void subscriptionRequest ( nciu &, netSubscription &subscr ); + void subscriptionCancelRequest ( nciu &, netSubscription &subscr ); + + bool flush (); // only to be called by the send thread +}; + +inline bufferReservoir::~bufferReservoir () +{ + this->drain (); +} + +inline comBuf *bufferReservoir::fetchOneBuffer () +{ + return this->reservedBufs.get (); +} + +inline void bufferReservoir::addOneBuffer () +{ + comBuf *pBuf = new comBuf; + if ( ! pBuf ) { + throw std::bad_alloc(); + } + this->reservedBufs.add ( *pBuf ); +} + +inline unsigned bufferReservoir::nBytes () +{ + return ( this->reservedBufs.count () * comBuf::capacityBytes () ); +} + +inline void bufferReservoir::drain () +{ + comBuf *pBuf; + while ( ( pBuf = this->reservedBufs.get () ) ) { + pBuf->destroy (); + } +} + +inline bool comQueSend::dbr_type_ok ( unsigned type ) +{ + if ( type >= ( sizeof ( this->dbrCopyVector ) / sizeof ( this->dbrCopyVector[0] ) ) ) { + return false; + } + if ( ! this->dbrCopyVector [type] ) { + return false; + } + return true; +} + +// +// 1) This routine does not return status because of the following +// argument. The routine can fail because the wire disconnects or +// because their isnt memory to create a buffer. For the former we +// just discard the message, but do not fail. For the latter we +// shutdown() the connection and discard the rest of the message +// (this eliminates the possibility of message fragments getting +// onto the wire). +// +// 2) Arguments here are a bit verbose until compilers all implement +// member template functions. +// + +template < class T > +inline void comQueSend_copyIn ( unsigned &nBytesPending, + tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, + const T *pVal, unsigned nElem ) +{ + nBytesPending += sizeof ( T ) * nElem; + + comBuf *pComBuf = comBufList.last (); + if ( pComBuf ) { + unsigned nCopied = pComBuf->copyIn ( pVal, nElem ); + if ( nElem > nCopied ) { + comQueSend_copyInWithReservour ( comBufList, reservoir, &pVal[nCopied], + nElem - nCopied ); + } + } + else { + comQueSend_copyInWithReservour ( comBufList, reservoir, pVal, nElem ); + } +} + +template < class T > +void comQueSend_copyInWithReservour ( + tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, + const T *pVal, unsigned nElem ) +{ + unsigned nCopied = 0u; + while ( nElem > nCopied ) { + comBuf *pComBuf = reservoir.fetchOneBuffer (); + // + // This fails only if space was not preallocated. + // See comments at the top of this program on + // why space must always be preallocated. + // + assert ( pComBuf ); + nCopied += pComBuf->copyIn ( &pVal[nCopied], nElem - nCopied ); + comBufList.add ( *pComBuf ); + } +} + +template < class T > +inline void comQueSend_copyIn ( unsigned &nBytesPending, + tsDLList < comBuf > &comBufList, bufferReservoir &reservoir, + const T &val ) +{ + nBytesPending += sizeof ( T ); + + comBuf *pComBuf = comBufList.last (); + if ( pComBuf ) { + if ( pComBuf->copyIn ( &val, 1u ) >= 1u ) { + return; + } + } + + pComBuf = reservoir.fetchOneBuffer (); + // + // This fails only if space was not preallocated. + // See comments at the top of this program on + // space must always be preallocated. + // + assert ( pComBuf ); + pComBuf->copyIn ( &val, 1u ); + comBufList.add ( *pComBuf ); +} + +inline void comQueSend::pushUInt16 ( const ca_uint16_t value ) +{ + comQueSend_copyIn ( this->nBytesPending, + this->bufs, this->reservoir, value ); +} + +inline void comQueSend::pushUInt32 ( const ca_uint32_t value ) +{ + comQueSend_copyIn ( this->nBytesPending, + this->bufs, this->reservoir, value ); +} + +inline void comQueSend::pushFloat32 ( const ca_float32_t value ) +{ + comQueSend_copyIn ( this->nBytesPending, + this->bufs, this->reservoir, value ); +} + +inline void comQueSend::pushString ( const char *pVal, unsigned nElem ) +{ + comQueSend_copyIn ( this->nBytesPending, + this->bufs, this->reservoir, pVal, nElem ); +} + +// it is assumed that dbr_type_ok() was called prior to calling this routine +// to check the type code +inline void comQueSend::push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ) +{ + ( this->*dbrCopyVector [type] ) ( pVal, nElem ); +} + +inline unsigned comQueSend::occupiedBytes () const +{ + return this->nBytesPending; +} + +inline bool comQueSend::flushBlockThreshold ( unsigned nBytesThisMsg ) const +{ + return ( this->nBytesPending + nBytesThisMsg > 16 * comBuf::capacityBytes () ); +} + +inline bool comQueSend::flushEarlyThreshold ( unsigned nBytesThisMsg ) const +{ + return ( this->nBytesPending + nBytesThisMsg > 4 * comBuf::capacityBytes () ); +} + +inline comBuf * comQueSend::popNextComBufToSend () +{ + comBuf *pBuf = this->bufs.get (); + if ( pBuf ) { + unsigned nBytesThisBuf = pBuf->occupiedBytes (); + assert ( this->nBytesPending >= nBytesThisBuf ); + this->nBytesPending -= pBuf->occupiedBytes (); + } + else { + assert ( this->nBytesPending == 0u ); + } + return pBuf; +} + +inline bool tcpiiu::fullyConstructed () const +{ + return this->fullyConstructedFlag; +} + +inline void tcpiiu::hostName ( char *pBuf, unsigned bufLength ) const +{ + if ( this->pHostNameCache ) { + this->pHostNameCache->hostName ( pBuf, bufLength ); + } + else { + netiiu::hostName ( pBuf, bufLength ); + } +} + +// deprecated - please dont use - this is _not_ thread safe +inline const char * tcpiiu::pHostName () const +{ + static char nameBuf [128]; + this->hostName ( nameBuf, sizeof ( nameBuf ) ); + return nameBuf; // ouch !! +} + +inline void tcpiiu::flushRequest () +{ + epicsEventSignal ( this->sendThreadFlushSignal ); +} + +inline bool tcpiiu::ca_v44_ok () const +{ + return CA_V44 ( CA_PROTOCOL_VERSION, this->minorProtocolVersion ); +} + +inline bool tcpiiu::ca_v41_ok () const +{ + return CA_V41 ( CA_PROTOCOL_VERSION, this->minorProtocolVersion ); +} + +inline bool tcpiiu::alive () const +{ + if ( this->state == iiu_connecting || + this->state == iiu_connected ) { + return true; + } + else { + return false; + } +} + +inline bhe * tcpiiu::getBHE () const +{ + return this->pBHE; +} + +inline void tcpiiu::beaconAnomalyNotify () +{ + this->recvDog.beaconAnomalyNotify (); +} + +inline void tcpiiu::beaconArrivalNotify () +{ + this->recvDog.beaconArrivalNotify (); +} + +inline bool tcpiiu::trueOnceOnly () +{ + if ( this->f_trueOnceOnly ) { + this->f_trueOnceOnly = false; + return true; + } + else { + return false; + } +} + +inline SOCKET tcpiiu::getSock () const +{ + return this->sock; +} + +#endif // ifdef virtualCircuith \ No newline at end of file