From 8bf53d3c593c29e357ba98da3046548d6f57473f Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 27 Apr 2012 13:21:41 -0400 Subject: [PATCH] Replaced dbAddr with dbChannel in all CA-server related code * Routines with a db_access interface are named dbChannel_xxx * Using dbch for member variable names in Jeff's code It seems to work! TODO: Make dbChannel use a freelist --- src/ioc/as/asDbLib.c | 34 +- src/ioc/as/asDbLib.h | 10 +- src/ioc/db/dbAccess.c | 112 +--- src/ioc/db/dbAddr.h | 3 - src/ioc/db/dbCAC.h | 68 +- src/ioc/db/dbChannelIO.cpp | 124 ++-- src/ioc/db/dbChannelIO.h | 63 +- src/ioc/db/dbContext.cpp | 149 +++-- src/ioc/db/dbContextReadNotifyCache.cpp | 38 +- src/ioc/db/dbEvent.c | 174 ++--- src/ioc/db/dbEvent.h | 16 +- src/ioc/db/dbNotify.c | 396 ++++++------ src/ioc/db/dbNotify.h | 22 +- src/ioc/db/dbPutNotifyBlocker.cpp | 42 +- src/ioc/db/dbPutNotifyBlocker.h | 28 +- src/ioc/db/dbSubscriptionIO.cpp | 44 +- src/ioc/db/db_access.c | 68 +- src/ioc/db/db_access_routines.h | 18 +- src/ioc/db/db_test.c | 828 +++++------------------- src/ioc/rsrv/camessage.c | 559 ++++++++-------- src/ioc/rsrv/caservertask.c | 125 ++-- src/ioc/rsrv/server.h | 30 +- 22 files changed, 1206 insertions(+), 1745 deletions(-) diff --git a/src/ioc/as/asDbLib.c b/src/ioc/as/asDbLib.c index bf4a85dcc..734b5e8f8 100644 --- a/src/ioc/as/asDbLib.c +++ b/src/ioc/as/asDbLib.c @@ -6,7 +6,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* Author: Marty Kraimer Date: 02-11-94*/ @@ -27,7 +27,7 @@ #include "caeventmask.h" #include "callback.h" #include "dbStaticLib.h" -#include "dbAddr.h" +#include "dbChannel.h" #include "dbAccess.h" #include "db_field_log.h" #include "dbEvent.h" @@ -40,7 +40,7 @@ static char *pacf=NULL; static char *psubstitutions=NULL; static epicsThreadId asInitTheadId=0; static int firstTime = TRUE; - + static long asDbAddRecords(void) { DBENTRY dbentry; @@ -98,7 +98,7 @@ int epicsShareAPI asSetSubstitutions(const char *substitutions) } return(0); } - + static void asSpcAsCallback(struct dbCommon *precord) { asChangeGroup(&precord->asp, precord->asg); @@ -109,7 +109,7 @@ static void asInitCommonOnce(void *arg) int *firstTime = (int *)arg; *firstTime = FALSE; } - + static long asInitCommon(void) { long status; @@ -117,7 +117,7 @@ static long asInitCommon(void) int wasFirstTime = firstTime; static epicsThreadOnceId asInitCommonOnceFlag = EPICS_THREAD_ONCE_INIT; - + epicsThreadOnce(&asInitCommonOnceFlag,asInitCommonOnce,(void *)&firstTime); if(wasFirstTime) { if(!pacf) return(0); /*access security will NEVER be turned on*/ @@ -148,7 +148,7 @@ int epicsShareAPI asInit(void) { return(asInitCommon()); } - + static void wdCallback(void *arg) { ASDBCALLBACK *pcallback = (ASDBCALLBACK *)arg; @@ -195,23 +195,15 @@ int epicsShareAPI asInitAsyn(ASDBCALLBACK *pcallback) } return(0); } - -int epicsShareAPI asDbGetAsl(void *paddress) -{ - DBADDR *paddr = paddress; - dbFldDes *pflddes; - pflddes = paddr->pfldDes; - return((int)pflddes->as_level); +int epicsShareAPI asDbGetAsl(struct dbChannel *chan) +{ + return dbChannelFldDes(chan)->as_level; } -void * epicsShareAPI asDbGetMemberPvt(void *paddress) +void * epicsShareAPI asDbGetMemberPvt(struct dbChannel *chan) { - DBADDR *paddr = paddress; - dbCommon *precord; - - precord = paddr->precord; - return((void *)precord->asp); + return dbChannelRecord(chan)->asp; } static void astacCallback(ASCLIENTPVT clientPvt,asClientStatus status) @@ -259,7 +251,7 @@ int epicsShareAPI astac(const char *pname,const char *user,const char *location) } return(0); } - + static void myMemberCallback(ASMEMBERPVT memPvt,FILE *fp) { dbCommon *precord; diff --git a/src/ioc/as/asDbLib.h b/src/ioc/as/asDbLib.h index f209a9028..b40a8d9df 100644 --- a/src/ioc/as/asDbLib.h +++ b/src/ioc/as/asDbLib.h @@ -5,12 +5,12 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* share/epicsH/dbAsLib.h */ /* $Revision-Id$ */ /* Author: Marty Kraimer Date: 02-23-94*/ - + #ifndef INCdbAsLibh #define INCdbAsLibh @@ -22,6 +22,8 @@ typedef struct { long status; } ASDBCALLBACK; +struct dbChannel; + #ifdef __cplusplus extern "C" { #endif @@ -30,8 +32,8 @@ epicsShareFunc int epicsShareAPI asSetFilename(const char *acf); epicsShareFunc int epicsShareAPI asSetSubstitutions(const char *substitutions); epicsShareFunc int epicsShareAPI asInit(void); epicsShareFunc int epicsShareAPI asInitAsyn(ASDBCALLBACK *pcallback); -epicsShareFunc int epicsShareAPI asDbGetAsl( void *paddr); -epicsShareFunc void * epicsShareAPI asDbGetMemberPvt( void *paddr); +epicsShareFunc int epicsShareAPI asDbGetAsl(struct dbChannel *chan); +epicsShareFunc void * epicsShareAPI asDbGetMemberPvt(struct dbChannel *chan); epicsShareFunc int epicsShareAPI asdbdump(void); epicsShareFunc int epicsShareAPI asdbdumpFP(FILE *fp); epicsShareFunc int epicsShareAPI aspuag(const char *uagname); diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index d1ea856ec..280077149 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -5,7 +5,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* dbAccess.c */ /* $Revision-Id$ */ @@ -15,7 +15,7 @@ * Date: 11-7-90 */ - + #include #include #include @@ -89,7 +89,7 @@ static short mapDBFToDBR[DBF_NTYPES] = { /* The following is to handle SPC_AS */ static SPC_ASCALLBACK spcAsCallback = 0; - + static void inherit_severity(const struct pv_link *ppv_link, dbCommon *pdest, epicsEnum16 stat, epicsEnum16 sevr) { @@ -113,7 +113,7 @@ long epicsShareAPI dbPutSpecial(DBADDR *paddr,int pass) dbCommon *precord = paddr->precord; long status=0; long special=paddr->special; - + prset = dbGetRset(paddr); if(special<100) { /*global processing*/ if((special==SPC_NOMOD) && (pass==0)) { @@ -139,7 +139,7 @@ long epicsShareAPI dbPutSpecial(DBADDR *paddr,int pass) } return(0); } - + static void get_enum_strs(DBADDR *paddr, char **ppbuffer, struct rset *prset,long *options) { @@ -199,7 +199,7 @@ choice_common: *ppbuffer = ((char *)*ppbuffer) + dbr_enumStrs_size; return; } - + static void get_graphics(DBADDR *paddr, char **ppbuffer, struct rset *prset,long *options) { @@ -239,7 +239,7 @@ static void get_graphics(DBADDR *paddr, char **ppbuffer, } return; } - + static void get_control(DBADDR *paddr, char **ppbuffer, struct rset *prset,long *options) { @@ -279,7 +279,7 @@ static void get_control(DBADDR *paddr, char **ppbuffer, } return; } - + static void get_alarm(DBADDR *paddr, char **ppbuffer, struct rset *prset,long *options) { @@ -324,7 +324,7 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer, } return; } - + static void getOptions(DBADDR *paddr,char **poriginal,long *options,void *pflin) { db_field_log *pfl= (db_field_log *)pflin; @@ -352,7 +352,7 @@ static void getOptions(DBADDR *paddr,char **poriginal,long *options,void *pflin) } if( (*options) & DBR_UNITS ) { memset(pbuffer,'\0',dbr_units_size); - if( prset && prset->get_units ){ + if( prset && prset->get_units ){ (*prset->get_units)(paddr, pbuffer); pbuffer[DB_UNITS_SIZE-1] = '\0'; } else { @@ -363,7 +363,7 @@ static void getOptions(DBADDR *paddr,char **poriginal,long *options,void *pflin) if( (*options) & DBR_PRECISION ) { memset(pbuffer, '\0', dbr_precision_size); if((field_type==DBF_FLOAT || field_type==DBF_DOUBLE) - && prset && prset->get_precision ){ + && prset && prset->get_precision ){ (*prset->get_precision)(paddr,pbuffer); } else { *options ^= DBR_PRECISION; /*Turn off DBR_PRECISION*/ @@ -392,7 +392,7 @@ static void getOptions(DBADDR *paddr,char **poriginal,long *options,void *pflin) get_alarm(paddr, &pbuffer, prset, options); *poriginal = pbuffer; } - + struct rset * epicsShareAPI dbGetRset(const struct dbAddr *paddr) { struct dbFldDes *pfldDes = paddr->pfldDes; @@ -462,7 +462,7 @@ int epicsShareAPI dbIsLinkConnected(const struct link *plink) int epicsShareAPI dbGetLinkDBFtype(const struct link *plink) { switch(plink->type) { - case DB_LINK: + case DB_LINK: { DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt; @@ -473,7 +473,7 @@ int epicsShareAPI dbGetLinkDBFtype(const struct link *plink) } return(-1); } - + /* * Process a record if its scan field is passive. * Will notify if processing is complete by callback. @@ -482,7 +482,7 @@ int epicsShareAPI dbGetLinkDBFtype(const struct link *plink) long epicsShareAPI dbScanPassive(dbCommon *pfrom, dbCommon *pto) { long status; - + /* if not passive just return success */ if(pto->scan != 0) return(0); @@ -524,7 +524,7 @@ void epicsShareAPI dbScanFwdLink(struct link *plink) dbCaPutLink(plink,DBR_SHORT,&fwdLinkValue,1); return; } - + /* * Process the record. * 1. Check for breakpoints. @@ -551,7 +551,7 @@ long epicsShareAPI dbProcess(dbCommon *precord) * to dbProcess() corresponding changes will have to * be made in the breakpoint handler. */ - + /* see if there are any stopped records or breakpoints */ if (lset_stack_count != 0) { /* @@ -566,7 +566,7 @@ long epicsShareAPI dbProcess(dbCommon *precord) if (dbBkpt(precord)) goto all_done; } - + /* check for trace processing*/ if (tpro) { if(*ptrace==0) { @@ -650,7 +650,7 @@ all_done: if(callNotifyCompletion && precord->ppn) dbNotifyCompletion(precord); return(status); } - + /* * Fill out a database structure (*paddr) for * a record given by the name "pname." @@ -726,59 +726,7 @@ finish: dbFinishEntry(&dbEntry); return status; } - -/* JOH 10-19-04 */ -static char * dbCopyInNameComponentOfPV ( - char * pBuf, unsigned bufLen, const char * pComponent ) -{ - unsigned compLen = strlen ( pComponent ); - if ( compLen < bufLen ) { - strcpy ( pBuf, pComponent ); - return pBuf + compLen; - } - else { - unsigned reducedSize = bufLen - 1u; - strncpy ( pBuf, pComponent, reducedSize ); - pBuf[reducedSize] = '\0'; - return pBuf + reducedSize; - } -} -/* - * Copies PV name into pBuf of length bufLen - * - * Returns the number of bytes written to pBuf - * not including null termination. - * JOH 10-19-04 - */ -unsigned dbNameOfPV ( - const dbAddr * paddr, char * pBuf, unsigned bufLen ) -{ - dbFldDes * pfldDes = paddr->pfldDes; - char * pBufTmp = pBuf; - if ( bufLen == 0u ) { - return 0u; - } - pBufTmp = dbCopyInNameComponentOfPV ( - pBufTmp, bufLen, paddr->precord->name ); - pBufTmp = dbCopyInNameComponentOfPV ( - pBufTmp, bufLen - ( pBufTmp - pBuf ), "." ); - pBufTmp = dbCopyInNameComponentOfPV ( - pBufTmp, bufLen - ( pBufTmp - pBuf ), pfldDes->name ); - return pBufTmp - pBuf; -} -/* - * Returns the number of bytes in the PV name - * not including null termination. - * JOH 10-19-04 - */ -unsigned dbNameSizeOfPV ( const dbAddr * paddr ) -{ - unsigned recNameLen = strlen ( paddr->precord->name ); - dbFldDes * pfldDes = paddr->pfldDes; - unsigned fieldNameLen = strlen ( pfldDes->name ); - return recNameLen + fieldNameLen + 1; -} - + long epicsShareAPI dbValueSize(short dbr_type) { /* sizes for value associated with each DBR request type */ @@ -826,7 +774,7 @@ int epicsShareAPI dbLoadRecords(const char* file, const char* subs) return dbReadDatabase(&pdbbase, file, 0, subs); } - + long epicsShareAPI dbGetLinkValue(struct link *plink, short dbrType, void *pbuffer, long *poptions, long *pnRequest) { @@ -902,7 +850,7 @@ long epicsShareAPI dbGetLinkValue(struct link *plink, short dbrType, } return status; } - + long epicsShareAPI dbPutLinkValue(struct link *plink, short dbrType, const void *pbuffer, long nRequest) { @@ -941,7 +889,7 @@ long epicsShareAPI dbPutLinkValue(struct link *plink, short dbrType, } return status; } - + long epicsShareAPI dbGetField(DBADDR *paddr,short dbrType, void *pbuffer, long *options, long *nRequest, void *pflin) { @@ -995,7 +943,7 @@ done: dbScanUnlock(precord); return status; } - + long epicsShareAPI dbGet(DBADDR *paddr, short dbrType, void *pbuffer, long *options, long *nRequest, void *pflin) { @@ -1105,7 +1053,7 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType, } return status; } - + devSup* epicsShareAPI dbDTYPtoDevSup(dbRecordType *prdes, int dtyp) { return (devSup *)ellNth(&prdes->devList, dtyp+1); } @@ -1366,7 +1314,7 @@ long epicsShareAPI dbPutField(DBADDR *paddr, short dbrType, dbScanUnlock(precord); return status; } - + static long putAckt(DBADDR *paddr, const unsigned short *pbuffer, long nRequest, long no_elements, long offset) { @@ -1395,7 +1343,7 @@ static long putAcks(DBADDR *paddr, const unsigned short *pbuffer, long nRequest, } return 0; } - + long epicsShareAPI dbPut(DBADDR *paddr, short dbrType, const void *pbuffer, long nRequest) { @@ -1471,7 +1419,7 @@ long epicsShareAPI dbPut(DBADDR *paddr, short dbrType, return status; } - + /* various utility routines */ long epicsShareAPI dbGetControlLimits( const struct link *plink,double *low, double *high) @@ -1516,7 +1464,7 @@ long epicsShareAPI dbGetGraphicLimits( *high = buffer.upper_disp_limit; return(0); } - + long epicsShareAPI dbGetAlarmLimits(const struct link *plink, double *lolo, double *low, double *high, double *hihi) { @@ -1561,7 +1509,7 @@ long epicsShareAPI dbGetPrecision(const struct link *plink,short *precision) *precision = buffer.precision.dp; return(0); } - + long epicsShareAPI dbGetUnits( const struct link *plink,char *units,int unitsSize) { diff --git a/src/ioc/db/dbAddr.h b/src/ioc/db/dbAddr.h index a91bcf76d..2a6e4c0e2 100644 --- a/src/ioc/db/dbAddr.h +++ b/src/ioc/db/dbAddr.h @@ -27,7 +27,4 @@ typedef struct dbAddr { typedef dbAddr DBADDR; -unsigned dbNameOfPV (const dbAddr * paddr, char * pBuf, unsigned bufLen); -unsigned dbNameSizeOfPV (const dbAddr * paddr); - #endif /* dbAddrh */ diff --git a/src/ioc/db/dbCAC.h b/src/ioc/db/dbCAC.h index 3032023dc..8325a7d2d 100644 --- a/src/ioc/db/dbCAC.h +++ b/src/ioc/db/dbCAC.h @@ -5,7 +5,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * $Revision-Id$ @@ -49,7 +49,7 @@ #include "db_access.h" #include "dbNotify.h" #include "dbEvent.h" -#include "dbAddr.h" +#include "dbChannel.h" #include "dbLock.h" #include "dbCommon.h" #include "db_convert.h" @@ -75,25 +75,25 @@ protected: virtual ~dbBaseIO() {} }; -extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr *paddr, +extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbChannel *dbch, int eventsRemaining, struct db_field_log *pfl ); -class dbSubscriptionIO : - public tsDLNode < dbSubscriptionIO >, +class dbSubscriptionIO : + public tsDLNode < dbSubscriptionIO >, public dbBaseIO { public: - dbSubscriptionIO ( + dbSubscriptionIO ( epicsGuard < epicsMutex > &, epicsMutex &, - dbContext &, dbChannelIO &, struct dbAddr &, cacStateNotify &, + dbContext &, dbChannelIO &, struct dbChannel *, cacStateNotify &, unsigned type, unsigned long count, unsigned mask, dbEventCtx ); void destructor ( epicsGuard < epicsMutex > & ); void unsubscribe ( epicsGuard < epicsMutex > & ); void channelDeleteException ( epicsGuard < epicsMutex > & ); void show ( epicsGuard < epicsMutex > &, unsigned level ) const; void show ( unsigned level ) const; - void * operator new ( size_t size, + void * operator new ( size_t size, tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & ); - epicsPlacementDeleteOperator (( void *, + epicsPlacementDeleteOperator (( void *, tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & )) private: epicsMutex & mutex; @@ -104,8 +104,8 @@ private: unsigned type; unsigned id; dbSubscriptionIO * isSubscription (); - friend void dbSubscriptionEventCallback ( - void * pPrivate, struct dbAddr * paddr, + friend void dbSubscriptionEventCallback ( + void * pPrivate, struct dbChannel * dbch, int eventsRemaining, struct db_field_log * pfl ); dbSubscriptionIO ( const dbSubscriptionIO & ); dbSubscriptionIO & operator = ( const dbSubscriptionIO & ); @@ -149,8 +149,8 @@ private: class dbContextReadNotifyCache { public: dbContextReadNotifyCache ( epicsMutex & ); - void callReadNotify ( epicsGuard < epicsMutex > &, - struct dbAddr & addr, unsigned type, unsigned long count, + void callReadNotify ( epicsGuard < epicsMutex > &, + struct dbChannel * dbch, unsigned type, unsigned long count, cacReadNotify & notify ); void show ( epicsGuard < epicsMutex > &, unsigned level ) const; private: @@ -162,29 +162,29 @@ private: class dbContext : public cacContext { public: - dbContext ( epicsMutex & cbMutex, epicsMutex & mutex, + dbContext ( epicsMutex & cbMutex, epicsMutex & mutex, cacContextNotify & notify ); virtual ~dbContext (); void destroyChannel ( epicsGuard < epicsMutex > &, dbChannelIO & ); - void callReadNotify ( epicsGuard < epicsMutex > &, - struct dbAddr & addr, unsigned type, unsigned long count, + void callReadNotify ( epicsGuard < epicsMutex > &, + struct dbChannel * dbch, unsigned type, unsigned long count, cacReadNotify & notify ); - void callStateNotify ( struct dbAddr &addr, unsigned type, unsigned long count, + void callStateNotify ( struct dbChannel * dbch, unsigned type, unsigned long count, const struct db_field_log * pfl, cacStateNotify & notify ); - void subscribe ( + void subscribe ( epicsGuard < epicsMutex > &, - struct dbAddr & addr, dbChannelIO & chan, - unsigned type, unsigned long count, unsigned mask, + struct dbChannel * dbch, dbChannelIO & chan, + unsigned type, unsigned long count, unsigned mask, cacStateNotify & notify, cacChannel::ioid * pId ); - void initiatePutNotify ( - epicsGuard < epicsMutex > &, dbChannelIO &, struct dbAddr &, - unsigned type, unsigned long count, const void * pValue, - cacWriteNotify & notify, cacChannel::ioid * pId ); + void initiatePutNotify ( + epicsGuard < epicsMutex > &, dbChannelIO &, struct dbChannel *, + unsigned type, unsigned long count, const void * pValue, + cacWriteNotify & notify, cacChannel::ioid * pId ); void show ( unsigned level ) const; void showAllIO ( const dbChannelIO & chan, unsigned level ) const; - void destroyAllIO ( + void destroyAllIO ( epicsGuard < epicsMutex > &, dbChannelIO & chan ); - void ioCancel ( epicsGuard < epicsMutex > &, + void ioCancel ( epicsGuard < epicsMutex > &, dbChannelIO & chan, const cacChannel::ioid &id ); void ioShow ( epicsGuard < epicsMutex > &, const cacChannel::ioid & id, unsigned level ) const; @@ -202,11 +202,11 @@ private: epics_auto_ptr < cacContext > pNetContext; char * pStateNotifyCache; - cacChannel & createChannel ( + cacChannel & createChannel ( epicsGuard < epicsMutex > &, - const char * pChannelName, cacChannelNotify &, + const char * pChannelName, cacChannelNotify &, cacChannel::priLev ); - void flush ( + void flush ( epicsGuard < epicsMutex > & ); unsigned circuitCount ( epicsGuard < epicsMutex > & ) const; @@ -214,7 +214,7 @@ private: epicsGuard < epicsMutex > & ) const; unsigned beaconAnomaliesSinceProgramStart ( epicsGuard < epicsMutex > & ) const; - void show ( + void show ( epicsGuard < epicsMutex > &, unsigned level ) const; dbContext ( const dbContext & ); @@ -226,17 +226,17 @@ inline dbContextPrivateListOfIO::dbContextPrivateListOfIO () : { } -inline dbContextPrivateListOfIO::~dbContextPrivateListOfIO () +inline dbContextPrivateListOfIO::~dbContextPrivateListOfIO () { assert ( ! this->pBlocker ); } -inline void dbContext::callReadNotify ( - epicsGuard < epicsMutex > & guard, struct dbAddr &addr, +inline void dbContext::callReadNotify ( + epicsGuard < epicsMutex > & guard, struct dbChannel * dbch, unsigned type, unsigned long count, cacReadNotify & notifyIn ) { guard.assertIdenticalMutex ( this-> mutex ); - this->readNotifyCache.callReadNotify ( guard, addr, type, count, notifyIn ); + this->readNotifyCache.callReadNotify ( guard, dbch, type, count, notifyIn ); } #endif // dbCACh diff --git a/src/ioc/db/dbChannelIO.cpp b/src/ioc/db/dbChannelIO.cpp index c95778abe..9bf9b0d52 100644 --- a/src/ioc/db/dbChannelIO.cpp +++ b/src/ioc/db/dbChannelIO.cpp @@ -4,20 +4,20 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* +/* * $Revision-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 @@ -40,15 +40,12 @@ #include "dbChannelIO.h" #include "dbPutNotifyBlocker.h" -dbChannelIO::dbChannelIO ( - epicsMutex & mutexIn, cacChannelNotify & notify, - const dbAddr & addrIn, dbContext & serviceIO ) : - cacChannel ( notify ), mutex ( mutexIn ), serviceIO ( serviceIO ), - addr ( addrIn ) +dbChannelIO::dbChannelIO ( + epicsMutex & mutexIn, cacChannelNotify & notify, + dbChannel * dbchIn, dbContext & serviceIO ) : + cacChannel ( notify ), mutex ( mutexIn ), serviceIO ( serviceIO ), + dbch ( dbchIn ) { - unsigned bufLen = dbNameSizeOfPV ( & this->addr ) + 1; - this->pNameStr.reset ( new char [ bufLen ] ); - dbNameOfPV ( & this->addr, this->pNameStr.get (), bufLen ); } void dbChannelIO::initiateConnect ( epicsGuard < epicsMutex > & guard ) @@ -57,7 +54,7 @@ void dbChannelIO::initiateConnect ( epicsGuard < epicsMutex > & guard ) this->notify().connectNotify ( guard ); } -dbChannelIO::~dbChannelIO () +dbChannelIO::~dbChannelIO () { } @@ -65,48 +62,49 @@ void dbChannelIO::destructor ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); this->serviceIO.destroyAllIO ( guard, *this ); + dbChannelDelete ( this->dbch ); this->~dbChannelIO (); } -void dbChannelIO::destroy ( +void dbChannelIO::destroy ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); this->serviceIO.destroyChannel ( guard, *this ); - // dont access this pointer after above call because - // object nolonger exists + // don't access this pointer after above call because + // object no longer exists } -cacChannel::ioStatus dbChannelIO::read ( - epicsGuard < epicsMutex > & guard, unsigned type, - unsigned long count, cacReadNotify & notify, ioid * ) +cacChannel::ioStatus dbChannelIO::read ( + epicsGuard < epicsMutex > & guard, unsigned type, + unsigned long count, cacReadNotify & notify, ioid * ) { guard.assertIdenticalMutex ( this->mutex ); - this->serviceIO.callReadNotify ( guard, this->addr, + this->serviceIO.callReadNotify ( guard, this->dbch, type, count, notify ); return iosSynch; } -void dbChannelIO::write ( - epicsGuard < epicsMutex > & guard, unsigned type, +void dbChannelIO::write ( + epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, const void *pValue ) { epicsGuardRelease < epicsMutex > unguard ( guard ); if ( count > LONG_MAX ) { throw outOfBounds(); } - int status = db_put_field ( &this->addr, type, pValue, + int status = dbChannel_put ( this->dbch, type, pValue, static_cast (count) ); if ( status ) { - throw std::logic_error ( + throw std::logic_error ( "db_put_field() completed unsuccessfully" ); } } -cacChannel::ioStatus dbChannelIO::write ( - epicsGuard < epicsMutex > & guard, unsigned type, - unsigned long count, const void * pValue, - cacWriteNotify & notify, ioid * pId ) +cacChannel::ioStatus dbChannelIO::write ( + epicsGuard < epicsMutex > & guard, unsigned type, + unsigned long count, const void * pValue, + cacWriteNotify & notify, ioid * pId ) { guard.assertIdenticalMutex ( this->mutex ); @@ -114,24 +112,24 @@ cacChannel::ioStatus dbChannelIO::write ( throw outOfBounds(); } - this->serviceIO.initiatePutNotify ( - guard, *this, this->addr, + this->serviceIO.initiatePutNotify ( + guard, *this, this->dbch, type, count, pValue, notify, pId ); return iosAsynch; } -void dbChannelIO::subscribe ( - epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, - unsigned mask, cacStateNotify & notify, ioid * pId ) -{ +void dbChannelIO::subscribe ( + epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, + unsigned mask, cacStateNotify & notify, ioid * pId ) +{ guard.assertIdenticalMutex ( this->mutex ); - this->serviceIO.subscribe ( - guard, this->addr, *this, + this->serviceIO.subscribe ( + guard, this->dbch, *this, type, count, mask, notify, pId ); } -void dbChannelIO::ioCancel ( +void dbChannelIO::ioCancel ( epicsGuard < epicsMutex > & mutualExclusionGuard, const ioid & id ) { @@ -139,7 +137,7 @@ void dbChannelIO::ioCancel ( this->serviceIO.ioCancel ( mutualExclusionGuard, *this, id ); } -void dbChannelIO::ioShow ( +void dbChannelIO::ioShow ( epicsGuard < epicsMutex > & guard, const ioid & id, unsigned level ) const { @@ -147,31 +145,35 @@ void dbChannelIO::ioShow ( this->serviceIO.ioShow ( guard, id, level ); } -void dbChannelIO::show ( +void dbChannelIO::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); - printf ("channel at %p attached to local database record %s\n", - static_cast ( this ), this->addr.precord->name ); + printf ("channel at %p attached to local database record %s\n", + static_cast ( this ), + dbChannelRecord ( this->dbch ) -> name ); if ( level > 0u ) { printf ( "\ttype %s, element count %li, field at %p\n", - dbf_type_to_text ( this->addr.dbr_field_type ), this->addr.no_elements, - this->addr.pfield ); - } - if ( level > 1u ) { - this->serviceIO.show ( level - 2u ); - this->serviceIO.showAllIO ( *this, level - 2u ); + dbf_type_to_text ( dbChannelExportType ( this->dbch ) ), + dbChannelElements ( this->dbch ), + dbChannelData ( this->dbch ) ); + if ( level > 1u ) { + dbChannelFilterShow ( this->dbch, level - 2u ); + this->serviceIO.show ( level - 2u ); + this->serviceIO.showAllIO ( *this, level - 2u ); + } } } unsigned long dbChannelIO::nativeElementCount ( - epicsGuard < epicsMutex > & guard ) const + epicsGuard < epicsMutex > & guard ) const { guard.assertIdenticalMutex ( this->mutex ); - if ( this->addr.no_elements >= 0u ) { - return static_cast < unsigned long > ( this->addr.no_elements ); + long elements = dbChannelElements ( this->dbch ); + if ( elements >= 0u ) { + return static_cast < unsigned long > ( elements ); } return 0u; } @@ -181,24 +183,30 @@ const char * dbChannelIO::pName ( epicsGuard < epicsMutex > & guard ) const throw () { guard.assertIdenticalMutex ( this->mutex ); - return this->pNameStr.get (); + return dbChannelName ( this->dbch ); } unsigned dbChannelIO::getName ( epicsGuard < epicsMutex > &, char * pBuf, unsigned bufLen ) const throw () { - return dbNameOfPV ( & this->addr, pBuf, bufLen ); + const char *name = dbChannelName ( this->dbch ); + size_t len = strlen ( name ); + strncpy ( pBuf, name, bufLen ); + if (len < bufLen) + return len; + pBuf[--bufLen] = '\0'; + return bufLen; } short dbChannelIO::nativeType ( - epicsGuard < epicsMutex > & guard ) const + epicsGuard < epicsMutex > & guard ) const { guard.assertIdenticalMutex ( this->mutex ); - return this->addr.dbr_field_type; + return dbChannelExportType( this->dbch ); } -void * dbChannelIO::operator new ( size_t size, +void * dbChannelIO::operator new ( size_t size, tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList ) { return freeList.allocate ( size ); @@ -212,7 +220,7 @@ void * dbChannelIO::operator new ( size_t ) // X aCC 361 } #ifdef CXX_PLACEMENT_DELETE -void dbChannelIO::operator delete ( void *pCadaver, +void dbChannelIO::operator delete ( void *pCadaver, tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList ) { freeList.release ( pCadaver ); diff --git a/src/ioc/db/dbChannelIO.h b/src/ioc/db/dbChannelIO.h index 0473962ba..56cf1f55d 100644 --- a/src/ioc/db/dbChannelIO.h +++ b/src/ioc/db/dbChannelIO.h @@ -5,7 +5,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -44,65 +44,64 @@ class dbChannelIO : public cacChannel, public dbContextPrivateListOfIO { public: - dbChannelIO ( - epicsMutex &, cacChannelNotify &, - const dbAddr &, dbContext & ); - void destructor ( + dbChannelIO ( + epicsMutex &, cacChannelNotify &, + dbChannel *, dbContext & ); + void destructor ( epicsGuard < epicsMutex > & ); void destroy ( epicsGuard < epicsMutex > & mutualExclusionGuard ); - void callReadNotify ( - epicsGuard < epicsMutex > &, - unsigned type, unsigned long count, + void callReadNotify ( + epicsGuard < epicsMutex > &, + unsigned type, unsigned long count, cacReadNotify & notify ); - void callStateNotify ( - unsigned type, unsigned long count, + void callStateNotify ( + unsigned type, unsigned long count, const struct db_field_log * pfl, cacStateNotify & notify ); - void show ( + void show ( epicsGuard < epicsMutex > &, unsigned level ) const; unsigned getName ( epicsGuard < epicsMutex > &, char * pBuf, unsigned bufLen ) const throw (); const char * pName ( epicsGuard < epicsMutex > & ) const throw (); - void * operator new ( size_t size, + void * operator new ( size_t size, tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & ); - epicsPlacementDeleteOperator (( void *, + epicsPlacementDeleteOperator (( void *, tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & )) protected: ~dbChannelIO (); private: epicsMutex & mutex; dbContext & serviceIO; - dbAddr addr; - epics_auto_ptr < char, eapt_array > pNameStr; + dbChannel * dbch; void initiateConnect ( epicsGuard < epicsMutex > & ); - unsigned requestMessageBytesPending ( + unsigned requestMessageBytesPending ( epicsGuard < epicsMutex > & ); - void flush ( + void flush ( epicsGuard < epicsMutex > & ); - ioStatus read ( + ioStatus read ( epicsGuard < epicsMutex > &, - unsigned type, unsigned long count, + unsigned type, unsigned long count, cacReadNotify &, ioid * ); - void write ( + void write ( epicsGuard < epicsMutex > &, - unsigned type, unsigned long count, + unsigned type, unsigned long count, const void * pvalue ); - ioStatus write ( + ioStatus write ( epicsGuard < epicsMutex > &, - unsigned type, unsigned long count, + unsigned type, unsigned long count, const void * pvalue, cacWriteNotify &, ioid * ); - void subscribe ( + void subscribe ( epicsGuard < epicsMutex > &, - unsigned type, unsigned long count, + unsigned type, unsigned long count, unsigned mask, cacStateNotify ¬ify, ioid * ); - void ioCancel ( + void ioCancel ( epicsGuard < epicsMutex > & mutualExclusionGuard, const ioid & ); - void ioShow ( + void ioShow ( epicsGuard < epicsMutex > &, const ioid &, unsigned level ) const; short nativeType ( @@ -115,18 +114,18 @@ private: void operator delete ( void * ); }; -inline void dbChannelIO::callReadNotify ( - epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, +inline void dbChannelIO::callReadNotify ( + epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count, cacReadNotify & notify ) { guard.assertIdenticalMutex ( this->mutex ); - this->serviceIO.callReadNotify ( guard, this->addr, type, count, notify ); + this->serviceIO.callReadNotify ( guard, this->dbch, type, count, notify ); } -inline void dbChannelIO::callStateNotify ( unsigned type, unsigned long count, +inline void dbChannelIO::callStateNotify ( unsigned type, unsigned long count, const struct db_field_log *pfl, cacStateNotify ¬ify ) { - this->serviceIO.callStateNotify ( this->addr, type, count, pfl, notify ); + this->serviceIO.callStateNotify ( this->dbch, type, count, pfl, notify ); } diff --git a/src/ioc/db/dbContext.cpp b/src/ioc/db/dbContext.cpp index 86ebf1997..99f257e7e 100644 --- a/src/ioc/db/dbContext.cpp +++ b/src/ioc/db/dbContext.cpp @@ -4,19 +4,19 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* +/* * $Revision-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 @@ -33,6 +33,7 @@ #include "epicsEvent.h" #include "epicsThread.h" #include "errlog.h" +#include "dbChannel.h" #define epicsExportSharedSymbols #include "db_access_routines.h" @@ -43,20 +44,20 @@ class dbService : public cacService { public: ~dbService () {} - cacContext & contextCreate ( - epicsMutex & mutualExclusion, - epicsMutex & callbackControl, + cacContext & contextCreate ( + epicsMutex & mutualExclusion, + epicsMutex & callbackControl, cacContextNotify & ); }; static dbService dbs; -cacContext & dbService::contextCreate ( - epicsMutex & mutualExclusion, - epicsMutex & callbackControl, +cacContext & dbService::contextCreate ( + epicsMutex & mutualExclusion, + epicsMutex & callbackControl, cacContextNotify & notify ) { - return * new dbContext ( callbackControl, + return * new dbContext ( callbackControl, mutualExclusion, notify ); } @@ -67,9 +68,9 @@ extern "C" void dbServiceIOInit () dbBaseIO::dbBaseIO () {} -dbContext::dbContext ( epicsMutex & cbMutexIn, +dbContext::dbContext ( epicsMutex & cbMutexIn, epicsMutex & mutexIn, cacContextNotify & notifyIn ) : - readNotifyCache ( mutexIn ), ctx ( 0 ), + readNotifyCache ( mutexIn ), ctx ( 0 ), stateNotifyCacheSize ( 0 ), mutex ( mutexIn ), cbMutex ( cbMutexIn ), notify ( notifyIn ), pNetContext ( 0 ), pStateNotifyCache ( 0 ) { @@ -84,41 +85,47 @@ dbContext::~dbContext () } cacChannel & dbContext::createChannel ( // X aCC 361 - epicsGuard < epicsMutex > & guard, const char * pName, + epicsGuard < epicsMutex > & guard, const char * pName, cacChannelNotify & notifyIn, cacChannel::priLev priority ) { guard.assertIdenticalMutex ( this->mutex ); - struct dbAddr addr; - int status; - { - // dont know if the database might call a put callback - // while holding its lock ... - epicsGuardRelease < epicsMutex > unguard ( guard ); - status = db_name_to_addr ( pName, & addr ); - } - if ( status ) { + dbChannel *dbch = dbChannel_create ( pName ); + if ( ! dbch ) { if ( ! this->pNetContext.get() ) { this->pNetContext.reset ( - & this->notify.createNetworkContext ( + & this->notify.createNetworkContext ( this->mutex, this->cbMutex ) ); } return this->pNetContext->createChannel ( guard, pName, notifyIn, priority ); } - else if ( ca_preemtive_callback_is_enabled () ) { - return * new ( this->dbChannelIOFreeList ) - dbChannelIO ( this->mutex, notifyIn, addr, *this ); - } - else { - errlogPrintf ( + + if ( ! ca_preemtive_callback_is_enabled () ) { + dbChannelDelete ( dbch ); + errlogPrintf ( "dbContext: preemptive callback required for direct in\n" "memory interfacing of CA channels to the DB.\n" ); throw cacChannel::unsupportedByService (); } + + long status = dbChannelOpen ( dbch ); + if (status) { + dbChannelDelete ( dbch ); + throw cacChannel::notConnected (); + } + + try { + return * new ( this->dbChannelIOFreeList ) + dbChannelIO ( this->mutex, notifyIn, dbch, *this ); + } + catch (...) { + dbChannelDelete ( dbch ); + throw; + } } -void dbContext::destroyChannel ( +void dbContext::destroyChannel ( epicsGuard < epicsMutex > & guard, dbChannelIO & chan ) { guard.assertIdenticalMutex ( this->mutex ); @@ -134,30 +141,30 @@ void dbContext::destroyChannel ( this->dbChannelIOFreeList.release ( & chan ); } -void dbContext::callStateNotify ( struct dbAddr & addr, - unsigned type, unsigned long count, - const struct db_field_log * pfl, +void dbContext::callStateNotify ( struct dbChannel * dbch, + unsigned type, unsigned long count, + const struct db_field_log * pfl, cacStateNotify & notifyIn ) { unsigned long size = dbr_size_n ( type, count ); if ( type > INT_MAX ) { epicsGuard < epicsMutex > guard ( this->mutex ); - notifyIn.exception ( guard, ECA_BADTYPE, - "type code out of range (high side)", + notifyIn.exception ( guard, ECA_BADTYPE, + "type code out of range (high side)", type, count ); return; } if ( count > INT_MAX ) { epicsGuard < epicsMutex > guard ( this->mutex ); - notifyIn.exception ( guard, ECA_BADCOUNT, + notifyIn.exception ( guard, ECA_BADCOUNT, "element count out of range (high side)", type, count); return; } - // no need to lock this because state notify is + // no need to lock this because state notify is // called from only one event queue consumer thread if ( this->stateNotifyCacheSize < size) { char * pTmp = new char [size]; @@ -166,14 +173,14 @@ void dbContext::callStateNotify ( struct dbAddr & addr, this->stateNotifyCacheSize = size; } void *pvfl = (void *) pfl; - int status = db_get_field ( &addr, static_cast ( type ), + int status = dbChannel_get ( dbch, static_cast ( type ), this->pStateNotifyCache, static_cast ( count ), pvfl ); if ( status ) { epicsGuard < epicsMutex > guard ( this->mutex ); - notifyIn.exception ( guard, ECA_GETFAIL, - "db_get_field() completed unsuccessfuly", type, count ); + notifyIn.exception ( guard, ECA_GETFAIL, + "dbChannel_get() completed unsuccessfully", type, count ); } - else { + else { epicsGuard < epicsMutex > guard ( this->mutex ); notifyIn.current ( guard, type, count, this->pStateNotifyCache ); } @@ -185,10 +192,10 @@ extern "C" void cacAttachClientCtx ( void * pPrivate ) assert ( status == ECA_NORMAL ); } -void dbContext::subscribe ( +void dbContext::subscribe ( epicsGuard < epicsMutex > & guard, - struct dbAddr & addr, dbChannelIO & chan, - unsigned type, unsigned long count, unsigned mask, + struct dbChannel * dbch, dbChannelIO & chan, + unsigned type, unsigned long count, unsigned mask, cacStateNotify & notifyIn, cacChannel::ioid * pId ) { guard.assertIdenticalMutex ( this->mutex ); @@ -214,12 +221,12 @@ void dbContext::subscribe ( unsigned selfPriority = epicsThreadGetPrioritySelf (); unsigned above; - epicsThreadBooleanStatus tbs = + epicsThreadBooleanStatus tbs = epicsThreadLowestPriorityLevelAbove ( selfPriority, &above ); if ( tbs != epicsThreadBooleanStatusSuccess ) { above = selfPriority; } - int status = db_start_events ( tmpctx, "CAC-event", + int status = db_start_events ( tmpctx, "CAC-event", cacAttachClientCtx, ca_current_context (), above ); if ( status ) { db_close_events ( tmpctx ); @@ -227,7 +234,7 @@ void dbContext::subscribe ( } } if ( this->ctx ) { - // another thread tried to simultaneously setup + // another thread tried to simultaneously setup // the event system db_close_events ( tmpctx ); } @@ -237,9 +244,9 @@ void dbContext::subscribe ( } dbSubscriptionIO & subscr = - * new ( this->dbSubscriptionIOFreeList ) - dbSubscriptionIO ( guard, this->mutex, *this, chan, - addr, notifyIn, type, count, mask, this->ctx ); + * new ( this->dbSubscriptionIOFreeList ) + dbSubscriptionIO ( guard, this->mutex, *this, chan, + dbch, notifyIn, type, count, mask, this->ctx ); chan.dbContextPrivateListOfIO::eventq.add ( subscr ); this->ioTable.idAssignAdd ( subscr ); @@ -248,27 +255,27 @@ void dbContext::subscribe ( } } -void dbContext::initiatePutNotify ( +void dbContext::initiatePutNotify ( epicsGuard < epicsMutex > & guard, - dbChannelIO & chan, struct dbAddr & addr, - unsigned type, unsigned long count, const void * pValue, + dbChannelIO & chan, struct dbChannel * dbch, + unsigned type, unsigned long count, const void * pValue, cacWriteNotify & notifyIn, cacChannel::ioid * pId ) { guard.assertIdenticalMutex ( this->mutex ); if ( ! chan.dbContextPrivateListOfIO::pBlocker ) { - chan.dbContextPrivateListOfIO::pBlocker = - new ( this->dbPutNotifyBlockerFreeList ) + chan.dbContextPrivateListOfIO::pBlocker = + new ( this->dbPutNotifyBlockerFreeList ) dbPutNotifyBlocker ( this->mutex ); this->ioTable.idAssignAdd ( *chan.dbContextPrivateListOfIO::pBlocker ); } - chan.dbContextPrivateListOfIO::pBlocker->initiatePutNotify ( - guard, notifyIn, addr, type, count, pValue ); + chan.dbContextPrivateListOfIO::pBlocker->initiatePutNotify ( + guard, notifyIn, dbch, type, count, pValue ); if ( pId ) { *pId = chan.dbContextPrivateListOfIO::pBlocker->getId (); } } -void dbContext::destroyAllIO ( +void dbContext::destroyAllIO ( epicsGuard < epicsMutex > & guard, dbChannelIO & chan ) { guard.assertIdenticalMutex ( this->mutex ); @@ -284,7 +291,7 @@ void dbContext::destroyAllIO ( } while ( ( pIO = tmp.get() ) ) { - // This prevents a db event callback from coming + // This prevents a db event callback from coming // through after the notify IO is deleted pIO->unsubscribe ( guard ); // If they call ioCancel() here it will be ignored @@ -301,8 +308,8 @@ void dbContext::destroyAllIO ( } } -void dbContext::ioCancel ( - epicsGuard < epicsMutex > & guard, dbChannelIO & chan, +void dbContext::ioCancel ( + epicsGuard < epicsMutex > & guard, dbChannelIO & chan, const cacChannel::ioid &id ) { guard.assertIdenticalMutex ( this->mutex ); @@ -325,8 +332,8 @@ void dbContext::ioCancel ( } } -void dbContext::ioShow ( - epicsGuard < epicsMutex > & guard, const cacChannel::ioid &id, +void dbContext::ioShow ( + epicsGuard < epicsMutex > & guard, const cacChannel::ioid &id, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); @@ -339,7 +346,7 @@ void dbContext::ioShow ( void dbContext::showAllIO ( const dbChannelIO & chan, unsigned level ) const { epicsGuard < epicsMutex > guard ( this->mutex ); - tsDLIterConst < dbSubscriptionIO > pItem = + tsDLIterConst < dbSubscriptionIO > pItem = chan.dbContextPrivateListOfIO::eventq.firstIter (); while ( pItem.valid () ) { pItem->show ( guard, level ); @@ -356,14 +363,14 @@ void dbContext::show ( unsigned level ) const this->show ( guard, level ); } -void dbContext::show ( +void dbContext::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); - printf ( "dbContext at %p\n", + printf ( "dbContext at %p\n", static_cast ( this ) ); if ( level > 0u ) { - printf ( "\tevent call back cache location %p, and its size %lu\n", + printf ( "\tevent call back cache location %p, and its size %lu\n", static_cast ( this->pStateNotifyCache ), this->stateNotifyCacheSize ); this->readNotifyCache.show ( guard, level - 1 ); } @@ -375,7 +382,7 @@ void dbContext::show ( } } -void dbContext::flush ( +void dbContext::flush ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); diff --git a/src/ioc/db/dbContextReadNotifyCache.cpp b/src/ioc/db/dbContextReadNotifyCache.cpp index 1d3b8ab1e..f298a63c8 100644 --- a/src/ioc/db/dbContextReadNotifyCache.cpp +++ b/src/ioc/db/dbContextReadNotifyCache.cpp @@ -5,7 +5,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -30,11 +30,11 @@ dbContextReadNotifyCache::dbContextReadNotifyCache ( epicsMutex & mutexIn ) : class privateAutoDestroyPtr { public: - privateAutoDestroyPtr ( + privateAutoDestroyPtr ( dbContextReadNotifyCacheAllocator & allocator, unsigned long size ) : _allocator ( allocator ), _p ( allocator.alloc ( size ) ) {} ~privateAutoDestroyPtr () { _allocator.free ( _p ); } - char * get () const { return _p; } + char * get () const { return _p; } private: dbContextReadNotifyCacheAllocator & _allocator; char * _p; @@ -43,28 +43,28 @@ private: }; // extra effort taken here to not hold the lock when calling the callback -void dbContextReadNotifyCache::callReadNotify ( - epicsGuard < epicsMutex > & guard, struct dbAddr & addr, +void dbContextReadNotifyCache::callReadNotify ( + epicsGuard < epicsMutex > & guard, struct dbChannel * dbch, unsigned type, unsigned long count, cacReadNotify & notify ) { guard.assertIdenticalMutex ( _mutex ); if ( type > INT_MAX ) { - notify.exception ( guard, ECA_BADTYPE, - "type code out of range (high side)", + notify.exception ( guard, ECA_BADTYPE, + "type code out of range (high side)", type, count ); return; } - if ( addr.no_elements < 0 ) { - notify.exception ( guard, ECA_BADCOUNT, + if ( dbChannelElements(dbch) < 0 ) { + notify.exception ( guard, ECA_BADCOUNT, "database has negetive element count", type, count); return; } - if ( count > static_cast < unsigned > ( addr.no_elements ) ) { - notify.exception ( guard, ECA_BADCOUNT, + if ( count > static_cast < unsigned long > ( dbChannelElements(dbch) ) ) { + notify.exception ( guard, ECA_BADCOUNT, "element count out of range (high side)", type, count); return; @@ -75,21 +75,21 @@ void dbContextReadNotifyCache::callReadNotify ( int status; { epicsGuardRelease < epicsMutex > unguard ( guard ); - status = db_get_field ( &addr, static_cast ( type ), - ptr.get (), static_cast ( count ), 0 ); + status = dbChannel_get ( dbch, static_cast ( type ), + ptr.get (), static_cast ( count ), 0 ); } if ( status ) { - notify.exception ( guard, ECA_GETFAIL, + notify.exception ( guard, ECA_GETFAIL, "db_get_field() completed unsuccessfuly", type, count ); } - else { - notify.completion ( + else { + notify.completion ( guard, type, count, ptr.get () ); } } -void dbContextReadNotifyCache::show ( +void dbContextReadNotifyCache::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( _mutex ); @@ -155,8 +155,8 @@ void dbContextReadNotifyCacheAllocator::show ( unsigned level ) const pNext = _pReadNotifyCache->pNext; count++; } - printf ( "\tcount %lu and size %lu\n", - static_cast < unsigned long > ( count ), + printf ( "\tcount %lu and size %lu\n", + static_cast < unsigned long > ( count ), _readNotifyCacheSize ); } } diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index 76f4f1a2c..d53a2e4f2 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -5,13 +5,13 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* dbEvent.c */ /* $Revision-Id$ */ /* routines for scheduling events to lower priority tasks via the RT kernel */ /* - * Author: Jeffrey O. Hill + * Author: Jeffrey O. Hill * Date: 4-1-89 */ @@ -39,6 +39,7 @@ #include "db_field_log.h" #define epicsExportSharedSymbols #include "dbAddr.h" +#include "dbChannel.h" #include "dbLock.h" #include "dbAccessDefs.h" #include "dbEvent.h" @@ -53,7 +54,7 @@ */ struct evSubscrip { ELLNODE node; - struct dbAddr *paddr; + struct dbChannel *chan; EVENTFUNC *user_sub; void *user_arg; struct event_que *ev_que; @@ -80,20 +81,20 @@ struct event_que { unsigned short putix; unsigned short getix; unsigned short quota; /* the number of assigned entries*/ - unsigned short nDuplicates; /* N events duplicated on this q */ + unsigned short nDuplicates; /* N events duplicated on this q */ unsigned short nCanceled; /* the number of canceled entries */ }; struct event_user { struct event_que firstque; /* the first event que */ - + epicsMutexId lock; epicsEventId ppendsem; /* Wait while empty */ epicsEventId pflush_sem; /* wait for flush */ - + EXTRALABORFUNC *extralabor_sub;/* off load to event task */ void *extralabor_arg;/* parameter to above */ - + epicsThreadId taskid; /* event handler task id */ struct evSubscrip *pSuicideEvent; /* event that is deleteing itself */ unsigned queovr; /* event que overflow count */ @@ -134,14 +135,14 @@ static char *EVENT_PEND_NAME = "eventTask"; static struct evSubscrip canceledEvent; -static unsigned short ringSpace ( const struct event_que *pevq ) +static unsigned short ringSpace ( const struct event_que *pevq ) { if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) { if ( pevq->getix > pevq->putix ) { return ( unsigned short ) ( pevq->getix - pevq->putix ); } else { - return ( unsigned short ) ( ( EVENTQUESIZE + pevq->getix ) - pevq->putix ); + return ( unsigned short ) ( ( EVENTQUESIZE + pevq->getix ) - pevq->putix ); } } return 0; @@ -186,7 +187,7 @@ int epicsShareAPI dbel ( const char *pname, unsigned level ) ellCount ( &addr.precord->mlis ) ); while ( pevent ) { - pdbFldDes = pevent->paddr->pfldDes; + pdbFldDes = dbChannelFldDes(pevent->chan); if ( level > 0 ) { printf ( "%4.4s", pdbFldDes->name ); @@ -210,15 +211,15 @@ int epicsShareAPI dbel ( const char *pname, unsigned level ) taskId = ( void * ) pevent->ev_que->evUser->taskid; UNLOCKEVQUE(pevent->ev_que); if ( nEntriesFree == 0u ) { - printf ( ", thread=%p, queue full", + printf ( ", thread=%p, queue full", (void *) taskId ); } else if ( nEntriesFree == EVENTQUESIZE ) { - printf ( ", thread=%p, queue empty", + printf ( ", thread=%p, queue empty", (void *) taskId ); } else { - printf ( ", thread=%p, unused entries=%u", + printf ( ", thread=%p, unused entries=%u", (void *) taskId, nEntriesFree ); } } @@ -245,9 +246,9 @@ int epicsShareAPI dbel ( const char *pname, unsigned level ) } if ( level > 3 ) { - printf ( ", ev %p, ev que %p, ev user %p", - ( void * ) pevent, - ( void * ) pevent->ev_que, + printf ( ", ev %p, ev que %p, ev user %p", + ( void * ) pevent, + ( void * ) pevent->ev_que, ( void * ) pevent->ev_que->evUser ); } @@ -268,32 +269,32 @@ int epicsShareAPI dbel ( const char *pname, unsigned level ) * * Initialize the event facility for this task. Must be called at least once * by each task which uses the db event facility - * + * * returns: ptr to event user block or NULL if memory can't be allocated */ dbEventCtx epicsShareAPI db_init_events (void) { struct event_user * evUser; - + if (!dbevEventUserFreeList) { - freeListInitPvt(&dbevEventUserFreeList, + freeListInitPvt(&dbevEventUserFreeList, sizeof(struct event_user),8); } if (!dbevEventQueueFreeList) { - freeListInitPvt(&dbevEventQueueFreeList, + freeListInitPvt(&dbevEventQueueFreeList, sizeof(struct event_que),8); } if (!dbevEventBlockFreeList) { - freeListInitPvt(&dbevEventBlockFreeList, + freeListInitPvt(&dbevEventBlockFreeList, sizeof(struct evSubscrip),256); } - - evUser = (struct event_user *) + + evUser = (struct event_user *) freeListCalloc(dbevEventUserFreeList); if (!evUser) { return NULL; } - + evUser->firstque.evUser = evUser; evUser->firstque.writelock = epicsMutexCreate(); if (!evUser->firstque.writelock) { @@ -304,7 +305,7 @@ dbEventCtx epicsShareAPI db_init_events (void) if (!evUser->ppendsem) { epicsMutexDestroy (evUser->firstque.writelock); return NULL; - } + } evUser->pflush_sem = epicsEventCreate(epicsEventEmpty); if (!evUser->pflush_sem) { epicsMutexDestroy (evUser->firstque.writelock); @@ -327,7 +328,7 @@ dbEventCtx epicsShareAPI db_init_events (void) /* * DB_CLOSE_EVENTS() - * + * * evUser block and additional event queues * deallocated when the event thread terminates * itself @@ -341,7 +342,7 @@ void epicsShareAPI db_close_events (dbEventCtx ctx) * Exit not forced on event blocks for now - this is left to channel * access and any other tasks using this facility which can find them * more efficiently. - * + * * NOTE: not deleting events before calling this routine could be * hazardous to the system's health. */ @@ -375,7 +376,7 @@ static struct event_que * create_ev_que ( struct event_user * const evUser ) * DB_ADD_EVENT() */ dbEventSubscription epicsShareAPI db_add_event ( - dbEventCtx ctx, struct dbAddr *paddr, + dbEventCtx ctx, struct dbChannel *chan, EVENTFUNC *user_sub, void *user_arg, unsigned select) { struct event_user * const evUser = (struct event_user *) ctx; @@ -430,7 +431,7 @@ dbEventSubscription epicsShareAPI db_add_event ( pevent->nreplace = 0ul; pevent->user_sub = user_sub; pevent->user_arg = user_arg; - pevent->paddr = paddr; + pevent->chan = chan; pevent->select = (unsigned char) select; pevent->pLastLog = NULL; /* not yet in the queue */ pevent->callBackInProgress = FALSE; @@ -442,8 +443,8 @@ dbEventSubscription epicsShareAPI db_add_event ( * communication (for other types they get whatever happens to be * there upon wakeup) */ - if( paddr->no_elements == 1 && - paddr->field_size <= sizeof(union native_value)) { + if( dbChannelElements(chan) == 1 && + dbChannelElementSize(chan) <= sizeof(union native_value)) { pevent->valque = TRUE; } else { @@ -459,8 +460,7 @@ dbEventSubscription epicsShareAPI db_add_event ( void epicsShareAPI db_event_enable (dbEventSubscription es) { struct evSubscrip * const pevent = (struct evSubscrip *) es; - struct dbCommon * const precord = - (struct dbCommon *) pevent->paddr->precord; + struct dbCommon * const precord = dbChannelRecord(pevent->chan); LOCKREC(precord); if ( ! pevent->enabled ) { @@ -476,8 +476,7 @@ void epicsShareAPI db_event_enable (dbEventSubscription es) void epicsShareAPI db_event_disable (dbEventSubscription es) { struct evSubscrip * const pevent = (struct evSubscrip *) es; - struct dbCommon * const precord = - (struct dbCommon *) pevent->paddr->precord; + struct dbCommon * const precord = dbChannelRecord(pevent->chan); LOCKREC(precord); if ( pevent->enabled ) { @@ -491,7 +490,7 @@ void epicsShareAPI db_event_disable (dbEventSubscription es) * event_remove() * event queue lock _must_ be applied */ -static void event_remove ( struct event_que *ev_que, +static void event_remove ( struct event_que *ev_que, unsigned short index, struct evSubscrip *placeHolder ) { struct evSubscrip * const pEvent = ev_que->evque[index]; @@ -511,9 +510,9 @@ static void event_remove ( struct event_que *ev_que, /* * DB_CANCEL_EVENT() * - * This routine does not prevent two threads from deleting + * This routine does not prevent two threads from deleting * the same block at the same time. - * + * */ void epicsShareAPI db_cancel_event (dbEventSubscription es) { @@ -523,7 +522,7 @@ void epicsShareAPI db_cancel_event (dbEventSubscription es) db_event_disable ( es ); /* - * flag the event as canceled by NULLing out the callback handler + * flag the event as canceled by NULLing out the callback handler * * make certain that the event isnt being accessed while * its call back changes @@ -535,14 +534,14 @@ void epicsShareAPI db_cancel_event (dbEventSubscription es) /* * purge this event from the queue * - * Its better to take this approach rather than waiting + * Its better to take this approach rather than waiting * for the event thread to finish removing this event * from the queue because the event thread will not - * process if we are in flow control mode. Since blocking + * process if we are in flow control mode. Since blocking * here will block CA's TCP input queue then a dead lock * would be possible. */ - for ( getix = pevent->ev_que->getix; + for ( getix = pevent->ev_que->getix; pevent->ev_que->evque[getix] != EVENTQEMPTY; ) { if ( pevent->ev_que->evque[getix] == pevent ) { assert ( pevent->ev_que->nCanceled < USHRT_MAX ); @@ -570,7 +569,7 @@ void epicsShareAPI db_cancel_event (dbEventSubscription es) pevent->ev_que->quota -= EVENTENTRIES; UNLOCKEVQUE ( pevent->ev_que ) - + freeListFree ( dbevEventBlockFreeList, pevent ); return; @@ -645,7 +644,7 @@ int epicsShareAPI db_post_extra_labor (dbEventCtx ctx) * NOTE: This assumes that the db scan lock is already applied */ static void db_post_single_event_private (struct evSubscrip *event) -{ +{ struct event_que * const ev_que = event->ev_que; db_field_log * pLog; int firstEventFlag; @@ -661,7 +660,7 @@ static void db_post_single_event_private (struct evSubscrip *event) /* * if we have an event on the queue and we are * not saving the current value (because this is a - * string or an array) then ignore duplicate + * string or an array) then ignore duplicate * events (saving them without the current valuye * serves no purpose) */ @@ -670,8 +669,8 @@ static void db_post_single_event_private (struct evSubscrip *event) return; } - /* - * add to task local event que + /* + * add to task local event que */ /* @@ -680,7 +679,7 @@ static void db_post_single_event_private (struct evSubscrip *event) * then replace the last event on the queue (for this monitor) */ rngSpace = ringSpace ( ev_que ); - if ( event->npend>0u && + if ( event->npend>0u && (ev_que->evUser->flowCtrlMode || rngSpace<=EVENTSPERQUE) ) { /* * replace last event if no space is left @@ -688,7 +687,7 @@ static void db_post_single_event_private (struct evSubscrip *event) pLog = event->pLastLog; event->nreplace++; /* - * the event task has already been notified about + * the event task has already been notified about * this so we dont need to post the semaphore */ firstEventFlag = 0; @@ -705,9 +704,9 @@ static void db_post_single_event_private (struct evSubscrip *event) ev_que->nDuplicates++; } event->npend++; - /* - * if the ring buffer was empty before - * adding this event + /* + * if the ring buffer was empty before + * adding this event */ if (rngSpace==EVENTQUESIZE) { firstEventFlag = 1; @@ -719,38 +718,39 @@ static void db_post_single_event_private (struct evSubscrip *event) } if (pLog && event->valque) { - struct dbCommon *precord = event->paddr->precord; + struct dbChannel *chan = event->chan; + struct dbCommon *precord = dbChannelRecord(chan); pLog->stat = precord->stat; pLog->sevr = precord->sevr; pLog->time = precord->time; /* * use memcpy to avoid a bus error on - * union copy of char in the db at an odd + * union copy of char in the db at an odd * address */ - memcpy( (char *)&pLog->field, - (char *)event->paddr->pfield, - event->paddr->field_size); + memcpy(& pLog->field, + dbChannelData(chan), + dbChannelElementSize(chan)); event->pLastLog = pLog; } UNLOCKEVQUE(ev_que) - /* - * its more efficent to notify the event handler + /* + * its more efficent to notify the event handler * only after the event is ready and the lock * is off in case it runs at a higher priority * than the caller here. */ if (firstEventFlag) { - /* - * notify the event handler + /* + * notify the event handler */ epicsEventSignal(ev_que->evUser->ppendsem); } -} +} /* * DB_POST_EVENTS() @@ -763,22 +763,22 @@ void *pRecord, void *pField, unsigned int caEventMask ) -{ +{ struct dbCommon * const pdbc = (struct dbCommon *)pRecord; struct evSubscrip * event; if (pdbc->mlis.count == 0) return DB_EVENT_OK; /* no monitors set */ LOCKREC(pdbc); - + for (event = (struct evSubscrip *) pdbc->mlis.node.next; event; event = (struct evSubscrip *) event->node.next){ - + /* * Only send event msg if they are waiting on the field which * changed or pval==NULL and waiting on alarms and alarms changed */ - if ( (event->paddr->pfield == (void *)pField || pField==NULL) && + if ( (dbChannelData(event->chan) == (void *)pField || pField==NULL) && (caEventMask & event->select) ) { db_post_single_event_private (event); } @@ -793,9 +793,9 @@ unsigned int caEventMask * DB_POST_SINGLE_EVENT() */ void epicsShareAPI db_post_single_event (dbEventSubscription es) -{ +{ struct evSubscrip * const event = (struct evSubscrip *) es; - struct dbCommon * const precord = event->paddr->precord; + struct dbCommon * const precord = dbChannelRecord(event->chan); dbScanLock (precord); db_post_single_event_private (event); @@ -808,15 +808,15 @@ void epicsShareAPI db_post_single_event (dbEventSubscription es) static int event_read ( struct event_que *ev_que ) { db_field_log *pfl; - void ( *user_sub ) ( void *user_arg, struct dbAddr *paddr, + void ( *user_sub ) ( void *user_arg, struct dbChannel *chan, int eventsRemaining, db_field_log *pfl ); - + /* * evUser ring buffer must be locked for the multiple * threads writing/reading it */ LOCKEVQUE ( ev_que ) - + /* * if in flow control mode drain duplicates and then * suspend processing events until flow control @@ -826,7 +826,7 @@ static int event_read ( struct event_que *ev_que ) UNLOCKEVQUE(ev_que); return DB_EVENT_OK; } - + while ( ev_que->evque[ev_que->getix] != EVENTQEMPTY ) { db_field_log fl = ev_que->valque[ev_que->getix]; struct evSubscrip *event = ev_que->evque[ev_que->getix]; @@ -865,20 +865,20 @@ static int event_read ( struct event_que *ev_que ) * if more events are waiting in the queue * * Must remove the lock here so that we dont deadlock if - * this calls dbGetField() and blocks on the record lock, - * dbPutField() is in progress in another task, it has the - * record lock, and it is calling db_post_events() waiting + * this calls dbGetField() and blocks on the record lock, + * dbPutField() is in progress in another task, it has the + * record lock, and it is calling db_post_events() waiting * for the event queue lock (which this thread now has). */ if ( user_sub ) { /* * This provides a way to test to see if an event is in use - * despite the fact that the event queue does not point to - * it. + * despite the fact that the event queue does not point to + * it. */ event->callBackInProgress = TRUE; UNLOCKEVQUE ( ev_que ) - ( *user_sub ) ( event->user_arg, event->paddr, + ( *user_sub ) ( event->user_arg, event->chan, ev_que->evque[ev_que->getix] != EVENTQEMPTY, pfl ); LOCKEVQUE ( ev_que ) @@ -951,7 +951,7 @@ static void event_task (void *pParm) } evUser->extraLaborBusy = FALSE; - for ( ev_que = &evUser->firstque; ev_que; + for ( ev_que = &evUser->firstque; ev_que; ev_que = ev_que->nextque ) { epicsMutexUnlock ( evUser->lock ); event_read (ev_que); @@ -967,7 +967,7 @@ static void event_task (void *pParm) struct event_que *nextque; ev_que = evUser->firstque.nextque; - while(ev_que){ + while(ev_que){ nextque = ev_que->nextque; epicsMutexDestroy(ev_que->writelock); freeListFree(dbevEventQueueFreeList, ev_que); @@ -990,15 +990,15 @@ static void event_task (void *pParm) * DB_START_EVENTS() */ int epicsShareAPI db_start_events ( - dbEventCtx ctx,const char *taskname, void (*init_func)(void *), + dbEventCtx ctx,const char *taskname, void (*init_func)(void *), void *init_func_arg, unsigned osiPriority ) { struct event_user * const evUser = (struct event_user *) ctx; - + epicsMutexMustLock ( evUser->lock ); - /* - * only one ca_pend_event thread may be + /* + * only one ca_pend_event thread may be * started for each evUser */ if (evUser->taskid) { @@ -1044,7 +1044,7 @@ void epicsShareAPI db_event_flow_ctrl_mode_on (dbEventCtx ctx) epicsMutexMustLock ( evUser->lock ); evUser->flowCtrlMode = TRUE; epicsMutexUnlock ( evUser->lock ); - /* + /* * notify the event handler task */ epicsEventSignal(evUser->ppendsem); @@ -1063,13 +1063,13 @@ void epicsShareAPI db_event_flow_ctrl_mode_off (dbEventCtx ctx) epicsMutexMustLock ( evUser->lock ); evUser->flowCtrlMode = FALSE; epicsMutexUnlock ( evUser->lock ); - /* + /* * notify the event handler task */ epicsEventSignal (evUser->ppendsem); #ifdef DEBUG printf("fc off %lu\n", tickGet()); #endif -} +} diff --git a/src/ioc/db/dbEvent.h b/src/ioc/db/dbEvent.h index db7186849..d93e31594 100644 --- a/src/ioc/db/dbEvent.h +++ b/src/ioc/db/dbEvent.h @@ -5,13 +5,13 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* +/* * $Revision-Id$ * - * Author: Jeff Hill - * Date: 030393 + * Author: Jeff Hill + * Date: 030393 */ #ifndef INCLdbEventh @@ -34,7 +34,7 @@ extern "C" { #endif -struct dbAddr; +struct dbChannel; struct db_field_log; epicsShareFunc int epicsShareAPI db_event_list ( @@ -49,7 +49,7 @@ typedef void * dbEventCtx; typedef void EXTRALABORFUNC (void *extralabor_arg); epicsShareFunc dbEventCtx epicsShareAPI db_init_events (void); epicsShareFunc int epicsShareAPI db_start_events ( - dbEventCtx ctx, const char *taskname, void (*init_func)(void *), + dbEventCtx ctx, const char *taskname, void (*init_func)(void *), void *init_func_arg, unsigned osiPriority ); epicsShareFunc void epicsShareAPI db_close_events (dbEventCtx ctx); epicsShareFunc void epicsShareAPI db_event_flow_ctrl_mode_on (dbEventCtx ctx); @@ -60,12 +60,12 @@ epicsShareFunc void epicsShareAPI db_flush_extra_labor_event (dbEventCtx); epicsShareFunc int epicsShareAPI db_post_extra_labor (dbEventCtx ctx); epicsShareFunc void epicsShareAPI db_event_change_priority ( dbEventCtx ctx, unsigned epicsPriority ); -typedef void EVENTFUNC (void *user_arg, struct dbAddr *paddr, +typedef void EVENTFUNC (void *user_arg, struct dbChannel *chan, int eventsRemaining, struct db_field_log *pfl); typedef void * dbEventSubscription; epicsShareFunc dbEventSubscription epicsShareAPI db_add_event ( - dbEventCtx ctx, struct dbAddr *paddr, + dbEventCtx ctx, struct dbChannel *chan, EVENTFUNC *user_sub, void *user_arg, unsigned select); epicsShareFunc void epicsShareAPI db_cancel_event (dbEventSubscription es); epicsShareFunc void epicsShareAPI db_post_single_event (dbEventSubscription es); diff --git a/src/ioc/db/dbNotify.c b/src/ioc/db/dbNotify.c index 7454129dc..1280291d2 100644 --- a/src/ioc/db/dbNotify.c +++ b/src/ioc/db/dbNotify.c @@ -1,19 +1,19 @@ /*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ + * National Laboratory. + * Copyright (c) 2002 The Regents of the University of California, as + * Operator of Los Alamos National Laboratory. + * EPICS BASE Versions 3.13.7 + * and higher are distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + \*************************************************************************/ /* dbNotify.c */ /* base/src/db $Revision-Id$ */ /* * Author: Marty Kraimer * Date: 03-30-95 * Extracted from dbLink.c -*/ + */ #include #include @@ -36,7 +36,7 @@ #include "dbCommon.h" #define epicsExportSharedSymbols #include "callback.h" -#include "dbAddr.h" +#include "dbChannel.h" #include "dbScan.h" #include "dbLock.h" #include "callback.h" @@ -45,7 +45,7 @@ #include "dbNotify.h" #include "epicsTime.h" #include "cantProceed.h" - + /*putNotify.state values */ typedef enum { putNotifyNotActive, @@ -55,44 +55,44 @@ typedef enum { putNotifyPutInProgress, putNotifyUserCallbackRequested, putNotifyUserCallbackActive -}putNotifyState; +} putNotifyState; /*structure attached to ppnr field of each record*/ typedef struct putNotifyRecord { - ellCheckNode waitNode; - ELLLIST restartList; /*list of putNotifys to restart*/ + ellCheckNode waitNode; + ELLLIST restartList; /*list of putNotifys to restart*/ dbCommon *precord; -}putNotifyRecord; +} putNotifyRecord; #define MAGIC 0xfedc0123 typedef struct putNotifyPvt { - ELLNODE node; /*For free list*/ - long magic; - short state; - CALLBACK callback; - ELLLIST waitList; /*list of records for current putNotify*/ - short cancelWait; - short userCallbackWait; + ELLNODE node; /*For free list*/ + long magic; + short state; + CALLBACK callback; + ELLLIST waitList; /*list of records for current putNotify*/ + short cancelWait; + short userCallbackWait; epicsEventId cancelEvent; epicsEventId userCallbackEvent; -}putNotifyPvt; +} putNotifyPvt; /* putNotify groups can span locksets if links are dynamically modified*/ /* Thus a global lock is taken while putNotify fields are accessed */ typedef struct notifyGlobal { epicsMutexId lock; ELLLIST freeList; -}notifyGlobal; +} notifyGlobal; static notifyGlobal *pnotifyGlobal = 0; - + /*Local routines*/ static void putNotifyInit(putNotify *ppn); static void putNotifyCleanup(putNotify *ppn); static void restartCheck(putNotifyRecord *ppnr); -static void callUser(dbCommon *precord,putNotify *ppn); +static void callUser(dbCommon *precord, putNotify *ppn); static void notifyCallback(CALLBACK *pcallback); -static void putNotifyCommon(putNotify *ppn,dbCommon *precord); +static void putNotifyCommon(putNotify *ppn, dbCommon *precord); #define ellSafeAdd(list,listnode) \ { \ @@ -112,9 +112,9 @@ static void putNotifyInit(putNotify *ppn) { putNotifyPvt *pputNotifyPvt; - pputNotifyPvt = (putNotifyPvt *)ellFirst(&pnotifyGlobal->freeList); - if(pputNotifyPvt) { - ellDelete(&pnotifyGlobal->freeList,&pputNotifyPvt->node); + pputNotifyPvt = (putNotifyPvt *) ellFirst(&pnotifyGlobal->freeList); + if (pputNotifyPvt) { + ellDelete(&pnotifyGlobal->freeList, &pputNotifyPvt->node); } else { pputNotifyPvt = dbCalloc(1,sizeof(putNotifyPvt)); pputNotifyPvt->cancelEvent = epicsEventCreate(epicsEventEmpty); @@ -135,26 +135,26 @@ static void putNotifyInit(putNotify *ppn) static void putNotifyCleanup(putNotify *ppn) { - putNotifyPvt *pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; + putNotifyPvt *pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; pputNotifyPvt->state = putNotifyNotActive; - ellAdd(&pnotifyGlobal->freeList,&pputNotifyPvt->node); + ellAdd(&pnotifyGlobal->freeList, &pputNotifyPvt->node); ppn->pputNotifyPvt = 0; } - + static void restartCheck(putNotifyRecord *ppnr) { dbCommon *precord = ppnr->precord; putNotify *pfirst; putNotifyPvt *pputNotifyPvt; - + assert(precord->ppn); - pfirst = (putNotify *)ellFirst(&ppnr->restartList); - if(!pfirst) { + pfirst = (putNotify *) ellFirst(&ppnr->restartList); + if (!pfirst) { precord->ppn = 0; return; } - pputNotifyPvt = (putNotifyPvt *)pfirst->pputNotifyPvt; + pputNotifyPvt = (putNotifyPvt *) pfirst->pputNotifyPvt; assert(pputNotifyPvt->state==putNotifyWaitForRestart); /* remove pfirst from restartList */ ellSafeDelete(&ppnr->restartList,&pfirst->restartNode); @@ -165,25 +165,25 @@ static void restartCheck(putNotifyRecord *ppnr) callbackRequest(&pputNotifyPvt->callback); } -static void callUser(dbCommon *precord,putNotify *ppn) +static void callUser(dbCommon *precord, putNotify *ppn) { - putNotifyPvt *pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; + putNotifyPvt *pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; epicsMutexUnlock(pnotifyGlobal->lock); dbScanUnlock(precord); (*ppn->userCallback)(ppn); epicsMutexMustLock(pnotifyGlobal->lock); - if(pputNotifyPvt->cancelWait && pputNotifyPvt->userCallbackWait) { + if (pputNotifyPvt->cancelWait && pputNotifyPvt->userCallbackWait) { errlogPrintf("%s putNotify: both cancelWait and userCallbackWait true." - "This is illegal\n",precord->name); + "This is illegal\n", precord->name); pputNotifyPvt->cancelWait = pputNotifyPvt->userCallbackWait = 0; } - if(!pputNotifyPvt->cancelWait && !pputNotifyPvt->userCallbackWait) { + if (!pputNotifyPvt->cancelWait && !pputNotifyPvt->userCallbackWait) { putNotifyCleanup(ppn); - epicsMutexUnlock(pnotifyGlobal->lock); + epicsMutexUnlock(pnotifyGlobal->lock); return; } - if(pputNotifyPvt->cancelWait) { + if (pputNotifyPvt->cancelWait) { pputNotifyPvt->cancelWait = 0; epicsEventSignal(pputNotifyPvt->cancelEvent); epicsMutexUnlock(pnotifyGlobal->lock); @@ -195,38 +195,37 @@ static void callUser(dbCommon *precord,putNotify *ppn) epicsMutexUnlock(pnotifyGlobal->lock); return; } - -static void putNotifyCommon(putNotify *ppn,dbCommon *precord) -{ - long status=0; - dbFldDes *pfldDes = ppn->paddr->pfldDes; - putNotifyPvt *pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - if(precord->ppn && pputNotifyPvt->state!=putNotifyRestartCallbackRequested) - { /*another putNotify owns the record */ - pputNotifyPvt->state = putNotifyWaitForRestart; +static void putNotifyCommon(putNotify *ppn, dbCommon *precord) +{ + long status; + putNotifyPvt *pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + + if (precord->ppn && + pputNotifyPvt->state != putNotifyRestartCallbackRequested) { /*another putNotify owns the record */ + pputNotifyPvt->state = putNotifyWaitForRestart; ellSafeAdd(&precord->ppnr->restartList,&ppn->restartNode); epicsMutexUnlock(pnotifyGlobal->lock); dbScanUnlock(precord); return; - } else if(precord->ppn){ - assert(precord->ppn==ppn); + } else if (precord->ppn) { + assert(precord->ppn == ppn); assert(pputNotifyPvt->state==putNotifyRestartCallbackRequested); } - if(precord->pact) { + if (precord->pact) { precord->ppn = ppn; ellSafeAdd(&pputNotifyPvt->waitList,&precord->ppnr->waitNode); - pputNotifyPvt->state = putNotifyRestartInProgress; + pputNotifyPvt->state = putNotifyRestartInProgress; epicsMutexUnlock(pnotifyGlobal->lock); dbScanUnlock(precord); return; } - status=dbPut(ppn->paddr,ppn->dbrType,ppn->pbuffer,ppn->nRequest); - ppn->status = (status==0) ? putNotifyOK : putNotifyError; + status = dbChannelPut(ppn->chan, ppn->dbrType, ppn->pbuffer, ppn->nRequest); + ppn->status = (status == 0) ? putNotifyOK : putNotifyError; /* Check to see if dbProcess should not be called */ - if(!status /*dont process if dbPut returned error */ - &&((ppn->paddr->pfield==(void *)&precord->proc) /*If PROC call dbProcess*/ - || (pfldDes->process_passive && precord->scan==0))) { + if (!status /*dont process if dbPut returned error */ + && ((dbChannelField(ppn->chan) == (void *) & precord->proc) /*If PROC call dbProcess*/ + || (dbChannelFldDes(ppn->chan)->process_passive && precord->scan == 0))) { precord->ppn = ppn; ellSafeAdd(&pputNotifyPvt->waitList,&precord->ppnr->waitNode); pputNotifyPvt->state = putNotifyPutInProgress; @@ -235,31 +234,31 @@ static void putNotifyCommon(putNotify *ppn,dbCommon *precord) dbScanUnlock(precord); return; } - if(pputNotifyPvt->state==putNotifyRestartCallbackRequested) { + if (pputNotifyPvt->state == putNotifyRestartCallbackRequested) { restartCheck(precord->ppnr); } pputNotifyPvt->state = putNotifyUserCallbackActive; assert(precord->ppn!=ppn); - callUser(precord,ppn); + callUser(precord, ppn); } - + static void notifyCallback(CALLBACK *pcallback) { - putNotify *ppn=NULL; - dbCommon *precord; + putNotify *ppn = NULL; + dbCommon *precord; putNotifyPvt *pputNotifyPvt; callbackGetUser(ppn,pcallback); - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - precord = ppn->paddr->precord; + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + precord = dbChannelRecord(ppn->chan); dbScanLock(precord); epicsMutexMustLock(pnotifyGlobal->lock); assert(precord->ppnr); assert(pputNotifyPvt->state==putNotifyRestartCallbackRequested - || pputNotifyPvt->state==putNotifyUserCallbackRequested); + || pputNotifyPvt->state==putNotifyUserCallbackRequested); assert(ellCount(&pputNotifyPvt->waitList)==0); - if(pputNotifyPvt->cancelWait) { - if(pputNotifyPvt->state==putNotifyRestartCallbackRequested) { + if (pputNotifyPvt->cancelWait) { + if (pputNotifyPvt->state == putNotifyRestartCallbackRequested) { restartCheck(precord->ppnr); } epicsEventSignal(pputNotifyPvt->cancelEvent); @@ -267,58 +266,61 @@ static void notifyCallback(CALLBACK *pcallback) dbScanUnlock(precord); return; } - if(pputNotifyPvt->state==putNotifyRestartCallbackRequested) { - putNotifyCommon(ppn,precord); + if (pputNotifyPvt->state == putNotifyRestartCallbackRequested) { + putNotifyCommon(ppn, precord); return; } /* All done. Clean up and call userCallback */ pputNotifyPvt->state = putNotifyUserCallbackActive; assert(precord->ppn!=ppn); - callUser(precord,ppn); + callUser(precord, ppn); } void epicsShareAPI dbPutNotifyInit(void) { - if(pnotifyGlobal) return; + if (pnotifyGlobal) + return; pnotifyGlobal = dbCalloc(1,sizeof(notifyGlobal)); pnotifyGlobal->lock = epicsMutexMustCreate(); ellInit(&pnotifyGlobal->freeList); } - + void epicsShareAPI dbPutNotify(putNotify *ppn) { - dbCommon *precord = ppn->paddr->precord; - short dbfType = ppn->paddr->field_type; - long status=0; + struct dbChannel *chan = ppn->chan; + dbCommon *precord = dbChannelRecord(chan); + short dbfType = dbChannelFieldType(chan); + long status = 0; putNotifyPvt *pputNotifyPvt; assert(precord); /*check for putField disabled*/ - if(precord->disp) { - if((void *)(&precord->disp) != ppn->paddr->pfield) { - ppn->status = putNotifyPutDisabled; - (*ppn->userCallback)(ppn); - return; + if (precord->disp) { + if (dbChannelField(chan) != (void *) & precord->disp) { + ppn->status = putNotifyPutDisabled; + (*ppn->userCallback)(ppn); + return; } } /* Must handle DBF_XXXLINKs as special case. - * Only dbPutField will change link fields. + * Only dbPutField will change link fields. * Also the record is not processed as a result - */ - if(dbfType>=DBF_INLINK && dbfType<=DBF_FWDLINK) { - status=dbPutField(ppn->paddr,ppn->dbrType,ppn->pbuffer,ppn->nRequest); - ppn->status = (status==0) ? putNotifyOK : putNotifyError; + */ + if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { + status = dbChannelPutField(ppn->chan, ppn->dbrType, ppn->pbuffer, + ppn->nRequest); + ppn->status = (status == 0) ? putNotifyOK : putNotifyError; (*ppn->userCallback)(ppn); return; } dbScanLock(precord); epicsMutexMustLock(pnotifyGlobal->lock); - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - if(pputNotifyPvt && (pputNotifyPvt->magic!=MAGIC)) { + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + if (pputNotifyPvt && (pputNotifyPvt->magic != MAGIC)) { printf("dbPutNotify:pputNotifyPvt was not initialized\n"); pputNotifyPvt = 0; } - if(pputNotifyPvt) { + if (pputNotifyPvt) { assert(pputNotifyPvt->state==putNotifyUserCallbackActive); pputNotifyPvt->userCallbackWait = 1; epicsMutexUnlock(pnotifyGlobal->lock); @@ -328,38 +330,38 @@ void epicsShareAPI dbPutNotify(putNotify *ppn) epicsMutexMustLock(pnotifyGlobal->lock); putNotifyCleanup(ppn); } - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; assert(!pputNotifyPvt); putNotifyInit(ppn); - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - if(!precord->ppnr) {/* make sure record has a putNotifyRecord*/ + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + if (!precord->ppnr) {/* make sure record has a putNotifyRecord*/ precord->ppnr = dbCalloc(1,sizeof(putNotifyRecord)); precord->ppnr->precord = precord; ellInit(&precord->ppnr->restartList); } - putNotifyCommon(ppn,precord); + putNotifyCommon(ppn, precord); } - + void epicsShareAPI dbNotifyCancel(putNotify *ppn) { - dbCommon *precord = ppn->paddr->precord; + dbCommon *precord = dbChannelRecord(ppn->chan); putNotifyState state; putNotifyPvt *pputNotifyPvt; assert(precord); dbScanLock(precord); epicsMutexMustLock(pnotifyGlobal->lock); - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - if(!pputNotifyPvt || pputNotifyPvt->state==putNotifyNotActive) { + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + if (!pputNotifyPvt || pputNotifyPvt->state == putNotifyNotActive) { epicsMutexUnlock(pnotifyGlobal->lock); dbScanUnlock(precord); return; } state = pputNotifyPvt->state; /*If callback is scheduled or active wait for it to complete*/ - if(state==putNotifyUserCallbackRequested - || state==putNotifyRestartCallbackRequested - || state==putNotifyUserCallbackActive) { + if (state == putNotifyUserCallbackRequested || state + == putNotifyRestartCallbackRequested || state + == putNotifyUserCallbackActive) { pputNotifyPvt->cancelWait = 1; epicsMutexUnlock(pnotifyGlobal->lock); dbScanUnlock(precord); @@ -369,24 +371,26 @@ void epicsShareAPI dbNotifyCancel(putNotify *ppn) epicsMutexUnlock(pnotifyGlobal->lock); return; } - switch(state) { - case putNotifyNotActive: break; + switch (state) { + case putNotifyNotActive: + break; case putNotifyWaitForRestart: assert(precord->ppn); assert(precord->ppn!=ppn); - ellSafeDelete(&precord->ppnr->restartList,&ppn->restartNode); + ellSafeDelete(&precord->ppnr->restartList,&ppn->restartNode) + ; break; case putNotifyRestartInProgress: - case putNotifyPutInProgress: - { /*Take all records out of wait list */ - putNotifyRecord *ppnrWait; + case putNotifyPutInProgress: { /*Take all records out of wait list */ + putNotifyRecord *ppnrWait; - while((ppnrWait = (putNotifyRecord *)ellFirst(&pputNotifyPvt->waitList))){ - ellSafeDelete(&pputNotifyPvt->waitList,&ppnrWait->waitNode); - restartCheck(ppnrWait); - } + while ((ppnrWait = (putNotifyRecord *) ellFirst(&pputNotifyPvt->waitList))) { + ellSafeDelete(&pputNotifyPvt->waitList,&ppnrWait->waitNode); + restartCheck(ppnrWait); } - if(precord->ppn==ppn) restartCheck(precord->ppnr); + } + if (precord->ppn == ppn) + restartCheck(precord->ppnr); break; default: printf("dbNotify: illegal state for notifyCallback\n"); @@ -396,29 +400,29 @@ void epicsShareAPI dbNotifyCancel(putNotify *ppn) epicsMutexUnlock(pnotifyGlobal->lock); dbScanUnlock(precord); } - + void epicsShareAPI dbNotifyCompletion(dbCommon *precord) { - putNotify *ppn = precord->ppn; + putNotify *ppn = precord->ppn; putNotifyPvt *pputNotifyPvt; epicsMutexMustLock(pnotifyGlobal->lock); assert(ppn); assert(precord->ppnr); - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - if(pputNotifyPvt->state!=putNotifyRestartInProgress - && pputNotifyPvt->state!=putNotifyPutInProgress) { + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + if (pputNotifyPvt->state != putNotifyRestartInProgress + && pputNotifyPvt->state != putNotifyPutInProgress) { epicsMutexUnlock(pnotifyGlobal->lock); return; } ellSafeDelete(&pputNotifyPvt->waitList,&precord->ppnr->waitNode); - if((ellCount(&pputNotifyPvt->waitList)!=0)) { + if ((ellCount(&pputNotifyPvt->waitList)!=0)) { restartCheck(precord->ppnr); - } else if(pputNotifyPvt->state == putNotifyPutInProgress) { + } else if (pputNotifyPvt->state == putNotifyPutInProgress) { pputNotifyPvt->state = putNotifyUserCallbackRequested; restartCheck(precord->ppnr); callbackRequest(&pputNotifyPvt->callback); - } else if(pputNotifyPvt->state == putNotifyRestartInProgress) { + } else if (pputNotifyPvt->state == putNotifyRestartInProgress) { pputNotifyPvt->state = putNotifyRestartCallbackRequested; callbackRequest(&pputNotifyPvt->callback); } else { @@ -432,142 +436,140 @@ void epicsShareAPI dbNotifyAdd(dbCommon *pfrom, dbCommon *pto) putNotify *ppn = pfrom->ppn; putNotifyPvt *pputNotifyPvt; - if(pto->pact) return; /*if active it will not be processed*/ + if (pto->pact) + return; /*if active it will not be processed*/ epicsMutexMustLock(pnotifyGlobal->lock); - if(!pto->ppnr) {/* make sure record has a putNotifyRecord*/ + if (!pto->ppnr) {/* make sure record has a putNotifyRecord*/ pto->ppnr = dbCalloc(1,sizeof(putNotifyRecord)); pto->ppnr->precord = pto; ellInit(&pto->ppnr->restartList); } assert(ppn); - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - if(!(pto->ppn) - && (pputNotifyPvt->state==putNotifyPutInProgress) - && (pto!=ppn->paddr->precord)) { + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + if (!pto->ppn && + (pputNotifyPvt->state == putNotifyPutInProgress) && + (pto != dbChannelRecord(ppn->chan))) { putNotifyPvt *pputNotifyPvt; pto->ppn = pfrom->ppn; - pputNotifyPvt = (putNotifyPvt *)pfrom->ppn->pputNotifyPvt; + pputNotifyPvt = (putNotifyPvt *) pfrom->ppn->pputNotifyPvt; ellSafeAdd(&pputNotifyPvt->waitList,&pto->ppnr->waitNode); } epicsMutexUnlock(pnotifyGlobal->lock); } - + typedef struct tpnInfo { epicsEventId callbackDone; - putNotify *ppn; -}tpnInfo; + putNotify *ppn; +} tpnInfo; static void dbtpnCallback(putNotify *ppn) { putNotifyStatus status = ppn->status; - tpnInfo *ptpnInfo = (tpnInfo *)ppn->usrPvt; + tpnInfo *ptpnInfo = (tpnInfo *) ppn->usrPvt; + const char *pname = dbChannelRecord(ppn->chan)->name; - if(status==0) - printf("dbtpnCallback: success record=%s\n",ppn->paddr->precord->name); + if (status == 0) + printf("dbtpnCallback: success record=%s\n", pname); else - printf("%s dbtpnCallback putNotify.status %d\n",ppn->paddr->precord->name,(int)status); + printf("%s dbtpnCallback putNotify.status %d\n", + pname, (int) status); epicsEventSignal(ptpnInfo->callbackDone); } static void tpnThread(void *pvt) { - tpnInfo *ptpnInfo = (tpnInfo *)pvt; - putNotify *ppn = (putNotify *)ptpnInfo->ppn; + tpnInfo *ptpnInfo = (tpnInfo *) pvt; + putNotify *ppn = (putNotify *) ptpnInfo->ppn; dbPutNotify(ppn); epicsEventWait(ptpnInfo->callbackDone); dbNotifyCancel(ppn); epicsEventDestroy(ptpnInfo->callbackDone); - free((void *)ppn->paddr); + free(ppn->pbuffer); + dbChannelDelete(ppn->chan); free(ppn); free(ptpnInfo); } -long epicsShareAPI dbtpn(char *pname,char *pvalue) +long epicsShareAPI dbtpn(char *pname, char *pvalue) { - long status; - tpnInfo *ptpnInfo; - DBADDR *pdbaddr=NULL; - putNotify *ppn=NULL; - char *psavevalue; - int len; + struct dbChannel *chan; + tpnInfo *ptpnInfo; + putNotify *ppn; + char *pbuffer; - len = strlen(pvalue); - /*allocate space for value immediately following DBADDR*/ - pdbaddr = dbCalloc(1,sizeof(DBADDR) + len+1); - psavevalue = (char *)(pdbaddr + 1); - strcpy(psavevalue,pvalue); - status = dbNameToAddr(pname,pdbaddr); - if(status) { - errMessage(status, "dbtpn: dbNameToAddr"); - free((void *)pdbaddr); - return(-1); + pbuffer = strdup(pvalue); + chan = dbChannelCreate(pname); + if (!chan) { + printf("dbtpn: No such channel"); + return -1; } - ppn = dbCalloc(1,sizeof(putNotify)); - ppn->paddr = pdbaddr; - ppn->pbuffer = psavevalue; + + ppn = dbCalloc(1, sizeof(putNotify)); + ppn->chan = chan; + ppn->pbuffer = pbuffer; ppn->nRequest = 1; ppn->dbrType = DBR_STRING; ppn->userCallback = dbtpnCallback; - ptpnInfo = dbCalloc(1,sizeof(tpnInfo)); + ptpnInfo = dbCalloc(1, sizeof(tpnInfo)); ptpnInfo->ppn = ppn; ptpnInfo->callbackDone = epicsEventCreate(epicsEventEmpty); ppn->usrPvt = ptpnInfo; - epicsThreadCreate("dbtpn",epicsThreadPriorityHigh, - epicsThreadGetStackSize(epicsThreadStackMedium), - tpnThread,ptpnInfo); - return(0); + epicsThreadCreate("dbtpn", epicsThreadPriorityHigh, + epicsThreadGetStackSize(epicsThreadStackMedium), tpnThread, ptpnInfo); + return 0; } - + int epicsShareAPI dbNotifyDump(void) { epicsMutexLockStatus lockStatus; dbRecordType *pdbRecordType; dbRecordNode *pdbRecordNode; - dbCommon *precord; - putNotify *ppn; - putNotify *ppnRestart; + dbCommon *precord; + putNotify *ppn; + putNotify *ppnRestart; putNotifyRecord *ppnrWait; int itry; - - - for(itry=0; itry<100; itry++) { + + for (itry = 0; itry < 100; itry++) { lockStatus = epicsMutexTryLock(pnotifyGlobal->lock); - if(lockStatus==epicsMutexLockOK) break; + if (lockStatus == epicsMutexLockOK) + break; epicsThreadSleep(.05); } - for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); - pdbRecordType; - pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { - for (pdbRecordNode=(dbRecordNode *)ellFirst(&pdbRecordType->recList); - pdbRecordNode; - pdbRecordNode = (dbRecordNode *)ellNext(&pdbRecordNode->node)) { + for (pdbRecordType = (dbRecordType *) ellFirst(&pdbbase->recordTypeList); pdbRecordType; pdbRecordType + = (dbRecordType *) ellNext(&pdbRecordType->node)) { + for (pdbRecordNode = (dbRecordNode *) ellFirst(&pdbRecordType->recList); pdbRecordNode; pdbRecordNode + = (dbRecordNode *) ellNext(&pdbRecordNode->node)) { putNotifyPvt *pputNotifyPvt; precord = pdbRecordNode->precord; - if (!precord->name[0] || - pdbRecordNode->flags & DBRN_FLAGS_ISALIAS) + if (!precord->name[0] || pdbRecordNode->flags & DBRN_FLAGS_ISALIAS) + continue; + if (!precord->ppn) + continue; + if (!precord->ppnr) + continue; + if (dbChannelRecord(precord->ppn->chan) != precord) continue; - if(!precord->ppn) continue; - if(!precord->ppnr) continue; - if(precord->ppn->paddr->precord != precord) continue; ppn = precord->ppn; - pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt; - printf("%s state %d ppn %p\n waitList\n", - precord->name,pputNotifyPvt->state,(void*)ppn); - ppnrWait = (putNotifyRecord *)ellFirst(&pputNotifyPvt->waitList); - while(ppnrWait) { - printf(" %s pact %d\n", - ppnrWait->precord->name,ppnrWait->precord->pact); - ppnrWait = (putNotifyRecord *)ellNext(&ppnrWait->waitNode.node); + pputNotifyPvt = (putNotifyPvt *) ppn->pputNotifyPvt; + printf("%s state %d ppn %p\n waitList\n", precord->name, + pputNotifyPvt->state, (void*) ppn); + ppnrWait = (putNotifyRecord *) ellFirst(&pputNotifyPvt->waitList); + while (ppnrWait) { + printf(" %s pact %d\n", ppnrWait->precord->name, + ppnrWait->precord->pact); + ppnrWait = (putNotifyRecord *) ellNext(&ppnrWait->waitNode.node); } printf(" restartList\n"); - ppnRestart = (putNotify *)ellFirst(&precord->ppnr->restartList); - while(ppnRestart) { - printf(" %p\n", (void *)ppnRestart); - ppnRestart = (putNotify *)ellNext(&ppnRestart->restartNode.node); + ppnRestart = (putNotify *) ellFirst(&precord->ppnr->restartList); + while (ppnRestart) { + printf(" %p\n", (void *) ppnRestart); + ppnRestart = (putNotify *) ellNext(&ppnRestart->restartNode.node); } } } - if(lockStatus==epicsMutexLockOK) epicsMutexUnlock(pnotifyGlobal->lock); - return(0); + if (lockStatus == epicsMutexLockOK) + epicsMutexUnlock(pnotifyGlobal->lock); + return (0); } diff --git a/src/ioc/db/dbNotify.h b/src/ioc/db/dbNotify.h index 5c57c0d90..b7ab1460f 100644 --- a/src/ioc/db/dbNotify.h +++ b/src/ioc/db/dbNotify.h @@ -5,7 +5,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* dbNotify.h */ @@ -18,12 +18,12 @@ #include "callback.h" #ifdef __cplusplus - /* for brain dead C++ compilers */ - struct dbCommon; - struct putNotify; extern "C" { #endif - + +struct dbCommon; +struct putNotify; + typedef struct ellCheckNode{ ELLNODE node; int isOnList; @@ -40,7 +40,7 @@ typedef struct putNotify{ ellCheckNode restartNode; /*The following members MUST be set by user*/ void (*userCallback)(struct putNotify *); - struct dbAddr *paddr; /*dbAddr set by dbNameToAddr*/ + struct dbChannel *chan; /*dbChannel*/ void *pbuffer; /*address of data*/ long nRequest; /*number of elements to be written*/ short dbrType; /*database request type*/ @@ -55,7 +55,7 @@ typedef struct putNotify{ epicsShareFunc void epicsShareAPI dbPutNotify(putNotify *pputNotify); epicsShareFunc void epicsShareAPI dbNotifyCancel(putNotify *pputNotify); -/*dbPutNotifyMapType convience function for old database access*/ +/*dbPutNotifyMapType convenience function for old database access*/ epicsShareFunc int epicsShareAPI dbPutNotifyMapType (putNotify *ppn, short oldtype); /* dbPutNotifyInit called by iocInit */ @@ -70,9 +70,9 @@ epicsShareFunc void epicsShareAPI dbNotifyCompletion(struct dbCommon *precord); /* dbtpn is test routine for put notify */ epicsShareFunc long epicsShareAPI dbtpn(char *recordname,char *value); -/* dbNotifyDump is an INVASIVE debug utility. Dont use this needlessly*/ +/* dbNotifyDump is an INVASIVE debug utility. Don't use this needlessly*/ epicsShareFunc int epicsShareAPI dbNotifyDump(void); - + /* This module provides code to handle put notify. If a put causes a record to * be processed, then a user supplied callback is called when that record * and all records processed because of that record complete processing. @@ -87,8 +87,8 @@ epicsShareFunc int epicsShareAPI dbNotifyDump(void); * * After dbPutNotify is called it may not called for the same putNotify * until the putCallback is complete. The use can call dbNotifyCancel - * to cancel the operation. - * + * to cancel the operation. + * * The user callback is called when the operation is completed. * * The other global routines (dbNotifyAdd and dbNotifyCompletion) are called by: diff --git a/src/ioc/db/dbPutNotifyBlocker.cpp b/src/ioc/db/dbPutNotifyBlocker.cpp index e91234b67..7acebdbd5 100644 --- a/src/ioc/db/dbPutNotifyBlocker.cpp +++ b/src/ioc/db/dbPutNotifyBlocker.cpp @@ -5,21 +5,21 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* +/* * $Revision-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: + * + * + * Author: * Jeffrey O. Hill * johill@lanl.gov * 505 665 1831 @@ -47,7 +47,7 @@ #include "dbPutNotifyBlocker.h" dbPutNotifyBlocker::dbPutNotifyBlocker ( epicsMutex & mutexIn ) : - mutex ( mutexIn ), pNotify ( 0 ), + mutex ( mutexIn ), pNotify ( 0 ), maxValueSize ( sizeof ( this->dbrScalarValue ) ) { memset ( & this->pn, '\0', sizeof ( this->pn ) ); @@ -55,7 +55,7 @@ dbPutNotifyBlocker::dbPutNotifyBlocker ( epicsMutex & mutexIn ) : this->pn.pbuffer = & this->dbrScalarValue; } -dbPutNotifyBlocker::~dbPutNotifyBlocker () +dbPutNotifyBlocker::~dbPutNotifyBlocker () { } @@ -70,7 +70,7 @@ void dbPutNotifyBlocker::destructor ( epicsGuard < epicsMutex > & guard ) this->~dbPutNotifyBlocker (); } -void dbPutNotifyBlocker::cancel ( +void dbPutNotifyBlocker::cancel ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); @@ -82,7 +82,7 @@ void dbPutNotifyBlocker::cancel ( this->block.signal (); } -void dbPutNotifyBlocker::expandValueBuf ( +void dbPutNotifyBlocker::expandValueBuf ( epicsGuard < epicsMutex > & guard, unsigned long newSize ) { guard.assertIdenticalMutex ( this->mutex ); @@ -127,9 +127,9 @@ extern "C" void putNotifyCompletion ( putNotify *ppn ) } } -void dbPutNotifyBlocker::initiatePutNotify ( - epicsGuard < epicsMutex > & guard, cacWriteNotify & notify, - struct dbAddr & addr, unsigned type, unsigned long count, +void dbPutNotifyBlocker::initiatePutNotify ( + epicsGuard < epicsMutex > & guard, cacWriteNotify & notify, + struct dbChannel * dbch, unsigned type, unsigned long count, const void * pValue ) { guard. assertIdenticalMutex ( this->mutex ); @@ -163,7 +163,7 @@ void dbPutNotifyBlocker::initiatePutNotify ( throw cacChannel::badType(); } - int status = dbPutNotifyMapType ( + int status = dbPutNotifyMapType ( &this->pn, static_cast ( type ) ); if ( status ) { this->pNotify = 0; @@ -171,7 +171,7 @@ void dbPutNotifyBlocker::initiatePutNotify ( } this->pn.nRequest = static_cast < unsigned > ( count ); - this->pn.paddr = &addr; + this->pn.chan = dbch; this->pn.userCallback = putNotifyCompletion; this->pn.usrPvt = this; @@ -191,22 +191,22 @@ void dbPutNotifyBlocker::show ( unsigned level ) const this->show ( guard, level ); } -void dbPutNotifyBlocker::show ( +void dbPutNotifyBlocker::show ( epicsGuard < epicsMutex > &, unsigned level ) const { - printf ( "put notify blocker at %p\n", + printf ( "put notify blocker at %p\n", static_cast ( this ) ); if ( level > 0u ) { this->block.show ( level - 1u ); } } -dbSubscriptionIO * dbPutNotifyBlocker::isSubscription () +dbSubscriptionIO * dbPutNotifyBlocker::isSubscription () { return 0; } -void * dbPutNotifyBlocker::operator new ( size_t size, +void * dbPutNotifyBlocker::operator new ( size_t size, tsFreeList < dbPutNotifyBlocker, 64, epicsMutexNOOP > & freeList ) { return freeList.allocate ( size ); @@ -220,7 +220,7 @@ void * dbPutNotifyBlocker::operator new ( size_t ) // X aCC 361 } #ifdef CXX_PLACEMENT_DELETE -void dbPutNotifyBlocker::operator delete ( void *pCadaver, +void dbPutNotifyBlocker::operator delete ( void *pCadaver, tsFreeList < dbPutNotifyBlocker, 64, epicsMutexNOOP > & freeList ) { freeList.release ( pCadaver ); diff --git a/src/ioc/db/dbPutNotifyBlocker.h b/src/ioc/db/dbPutNotifyBlocker.h index da2cc9fcb..bca0d715b 100644 --- a/src/ioc/db/dbPutNotifyBlocker.h +++ b/src/ioc/db/dbPutNotifyBlocker.h @@ -5,20 +5,20 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* +/* * $Revision-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 @@ -43,24 +43,24 @@ class dbPutNotifyBlocker : public dbBaseIO { public: dbPutNotifyBlocker ( epicsMutex & ); void destructor ( epicsGuard < epicsMutex > & ); - void initiatePutNotify ( epicsGuard < epicsMutex > &, - cacWriteNotify &, struct dbAddr &, + void initiatePutNotify ( epicsGuard < epicsMutex > &, + cacWriteNotify &, struct dbChannel *, unsigned type, unsigned long count, const void * pValue ); void cancel ( epicsGuard < epicsMutex > & ); void show ( epicsGuard < epicsMutex > &, unsigned level ) const; void show ( unsigned level ) const; - void * operator new ( size_t size, + void * operator new ( size_t size, tsFreeList < dbPutNotifyBlocker, 64, epicsMutexNOOP > & ); - epicsPlacementDeleteOperator (( void *, + epicsPlacementDeleteOperator (( void *, tsFreeList < dbPutNotifyBlocker, 64, epicsMutexNOOP > & )) private: putNotify pn; // - // Include a union of all scalar types + // Include a union of all scalar types // including fixed length strings so - // that in many cases we can avoid + // that in many cases we can avoid // allocating another buffer - // + // union { dbr_string_t strval; dbr_short_t shrtval; @@ -76,7 +76,7 @@ private: cacWriteNotify * pNotify; unsigned long maxValueSize; dbSubscriptionIO * isSubscription (); - void expandValueBuf ( + void expandValueBuf ( epicsGuard < epicsMutex > &, unsigned long newSize ); friend void putNotifyCompletion ( putNotify * ppn ); dbPutNotifyBlocker ( const dbPutNotifyBlocker & ); diff --git a/src/ioc/db/dbSubscriptionIO.cpp b/src/ioc/db/dbSubscriptionIO.cpp index 4fd190d3f..a53fd0086 100644 --- a/src/ioc/db/dbSubscriptionIO.cpp +++ b/src/ioc/db/dbSubscriptionIO.cpp @@ -4,20 +4,20 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ -/* +/* * $Revision-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 @@ -41,18 +41,18 @@ #include "dbChannelIO.h" #include "db_access_routines.h" -dbSubscriptionIO::dbSubscriptionIO ( +dbSubscriptionIO::dbSubscriptionIO ( epicsGuard < epicsMutex > & guard, epicsMutex & mutexIn, - dbContext &, dbChannelIO & chanIO, - dbAddr & addr, cacStateNotify & notifyIn, unsigned typeIn, + dbContext &, dbChannelIO & chanIO, + dbChannel * dbch, cacStateNotify & notifyIn, unsigned typeIn, unsigned long countIn, unsigned maskIn, dbEventCtx ctx ) : - mutex ( mutexIn ), count ( countIn ), notify ( notifyIn ), + mutex ( mutexIn ), count ( countIn ), notify ( notifyIn ), chan ( chanIO ), es ( 0 ), type ( typeIn ), id ( 0u ) { guard.assertIdenticalMutex ( this->mutex ); { epicsGuardRelease < epicsMutex > unguard ( guard ); - this->es = db_add_event ( ctx, & addr, + this->es = db_add_event ( ctx, dbch, dbSubscriptionEventCallback, (void *) this, maskIn ); if ( this->es == 0 ) { throw std::bad_alloc(); @@ -62,7 +62,7 @@ dbSubscriptionIO::dbSubscriptionIO ( } } -dbSubscriptionIO::~dbSubscriptionIO () +dbSubscriptionIO::~dbSubscriptionIO () { } @@ -72,7 +72,7 @@ void dbSubscriptionIO::destructor ( epicsGuard < epicsMutex > & guard ) this->~dbSubscriptionIO (); } -void dbSubscriptionIO::unsubscribe ( +void dbSubscriptionIO::unsubscribe ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); @@ -86,11 +86,11 @@ void dbSubscriptionIO::unsubscribe ( } } -void dbSubscriptionIO::channelDeleteException ( +void dbSubscriptionIO::channelDeleteException ( epicsGuard < epicsMutex > & guard ) { guard.assertIdenticalMutex ( this->mutex ); - this->notify.exception ( guard, ECA_CHANDESTROY, + this->notify.exception ( guard, ECA_CHANDESTROY, this->chan.pName(guard), this->type, this->count ); } @@ -112,21 +112,21 @@ void dbSubscriptionIO::operator delete ( void * ) __FILE__, __LINE__ ); } -void * dbSubscriptionIO::operator new ( size_t size, +void * dbSubscriptionIO::operator new ( size_t size, tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & freeList ) { return freeList.allocate ( size ); } #ifdef CXX_PLACEMENT_DELETE -void dbSubscriptionIO::operator delete ( void * pCadaver, +void dbSubscriptionIO::operator delete ( void * pCadaver, tsFreeList < dbSubscriptionIO, 256, epicsMutexNOOP > & freeList ) { freeList.release ( pCadaver ); } #endif -extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbAddr * /* paddr */, +extern "C" void dbSubscriptionEventCallback ( void *pPrivate, struct dbChannel * /* dbch */, int /* eventsRemaining */, struct db_field_log *pfl ) { dbSubscriptionIO * pIO = static_cast < dbSubscriptionIO * > ( pPrivate ); @@ -139,19 +139,19 @@ void dbSubscriptionIO::show ( unsigned level ) const this->show ( guard, level ); } -void dbSubscriptionIO::show ( +void dbSubscriptionIO::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); - printf ( "Data base subscription IO at %p\n", + printf ( "Data base subscription IO at %p\n", static_cast ( this ) ); if ( level > 0u ) { short tmpType; if ( this->type < SHRT_MAX ) { tmpType = static_cast < short > ( this->type ); printf ( "\ttype %s, count %lu, channel at %p\n", - dbf_type_to_text ( tmpType ), this->count, + dbf_type_to_text ( tmpType ), this->count, static_cast ( &this->chan ) ); } else { @@ -161,7 +161,7 @@ void dbSubscriptionIO::show ( } } -dbSubscriptionIO * dbSubscriptionIO::isSubscription () +dbSubscriptionIO * dbSubscriptionIO::isSubscription () { return this; } diff --git a/src/ioc/db/db_access.c b/src/ioc/db/db_access.c index 5596f1a0e..479d501fa 100644 --- a/src/ioc/db/db_access.c +++ b/src/ioc/db/db_access.c @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* $Revision-Id$ */ @@ -24,6 +24,7 @@ #include "epicsConvert.h" #include "dbDefs.h" +#include "dbChannel.h" #include "errlog.h" #include "ellLib.h" #include "epicsTime.h" @@ -42,10 +43,6 @@ #include "dbEvent.h" #include "db_access_routines.h" -#ifndef NULL -#define NULL 0 -#endif - #define oldDBF_STRING 0 #define oldDBF_INT 1 @@ -108,46 +105,26 @@ extern unsigned short dbDBRnewToDBRold[DBR_ENUM+1]; typedef char DBSTRING[MAX_STRING_SIZE]; -#ifndef MAX_STRING_SIZE -#define MAX_STRING_SIZE 40 -#endif - -/* - * DB_PROCESS - * - * process database records - */ -void db_process(struct dbAddr *paddr) +struct dbChannel * dbChannel_create(const char *pname) { - long status = dbProcess(paddr->precord); - - if (status) errMessage(status, "db_process failed"); -} - -/* - * DB_NAME_TO_ADDR - */ -int epicsShareAPI db_name_to_addr(const char *pname, struct dbAddr *paddr) -{ - long status; + dbChannel *chan = dbChannelCreate(pname); short ftype; - status = dbNameToAddr(pname, paddr); - if (!status) { - ftype = paddr->dbr_field_type; - if (INVALID_DB_REQ(ftype)) { - errlogPrintf("%s dbNameToAddr failed\n", pname); - return -2; - } - paddr->dbr_field_type = dbDBRnewToDBRold[ftype]; - return 0; + if (!chan) + return NULL; + + ftype = chan->addr.dbr_field_type; + if (INVALID_DB_REQ(ftype)) { + dbChannelDelete(chan); + return NULL; } - else - return -1; + + chan->addr.dbr_field_type = dbDBRnewToDBRold[ftype]; + return chan; } - -int epicsShareAPI db_get_field(struct dbAddr *paddr, - int buffer_type, void *pbuffer, int no_elements, void *pfl) + +int dbChannel_get(struct dbChannel *chan, + int buffer_type, void *pbuffer, long no_elements, void *pfl) { long nRequest = no_elements; int result = db_get_field_and_count( @@ -825,15 +802,14 @@ int epicsShareAPI db_get_field_and_count( if (status) return -1; return 0; } - -/* DB_PUT_FIELD put a field and convert it to the desired type */ -int epicsShareAPI db_put_field(struct dbAddr *paddr, int src_type, - const void *psrc, int no_elements) +int dbChannel_put(struct dbChannel *chan, int src_type, + const void *psrc, long no_elements) { + dbAddr *paddr = & chan->addr; long status; - switch(src_type) { + switch (src_type) { case(oldDBR_STRING): status = dbPutField(paddr, DBR_STRING, psrc, no_elements); break; @@ -993,7 +969,7 @@ int epicsShareAPI db_put_field(struct dbAddr *paddr, int src_type, return 0; } - + epicsShareFunc int epicsShareAPI dbPutNotifyMapType (putNotify *ppn, short oldtype) { switch(oldtype) { diff --git a/src/ioc/db/db_access_routines.h b/src/ioc/db/db_access_routines.h index a1f445c6f..efe20b95c 100644 --- a/src/ioc/db/db_access_routines.h +++ b/src/ioc/db/db_access_routines.h @@ -5,7 +5,7 @@ * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* base/include/db_access_routines.h */ @@ -22,23 +22,19 @@ extern "C" { #endif #include "shareLib.h" -#include "dbAddr.h" epicsShareExtern struct dbBase *pdbbase; epicsShareExtern volatile int interruptAccept; /* - * old db access API - * (included here because these routines use dbAccess.h and their - * prototypes must also be included in db_access.h) + * Adaptors for db_access users */ -epicsShareFunc int epicsShareAPI db_name_to_addr( - const char *pname, DBADDR *paddr); -epicsShareFunc int epicsShareAPI db_put_field( - DBADDR *paddr, int src_type,const void *psrc, int no_elements); -epicsShareFunc int epicsShareAPI db_get_field( - DBADDR *paddr, int dest_type,void *pdest, int no_elements, void *pfl); +epicsShareFunc struct dbChannel * dbChannel_create(const char *pname); +epicsShareFunc int dbChannel_get(struct dbChannel *chan, + int buffer_type, void *pbuffer, long no_elements, void *pfl); +epicsShareFunc int dbChannel_put(struct dbChannel *chan, int src_type, + const void *psrc, long no_elements); epicsShareFunc int epicsShareAPI db_get_field_and_count( struct dbAddr *paddr, int buffer_type, void *pbuffer, long *nRequest, void *pfl); diff --git a/src/ioc/db/db_test.c b/src/ioc/db/db_test.c index 0ad5ad2e2..57c325907 100644 --- a/src/ioc/db/db_test.c +++ b/src/ioc/db/db_test.c @@ -1,12 +1,12 @@ /*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne -* National Laboratory. -* Copyright (c) 2002 The Regents of the University of California, as -* Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ + * National Laboratory. + * Copyright (c) 2002 The Regents of the University of California, as + * Operator of Los Alamos National Laboratory. + * EPICS BASE Versions 3.13.7 + * and higher are distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + \*************************************************************************/ /* share/src/db @(#)db_test.c 1.10 2/3/94 */ /* database access subroutines */ /* @@ -23,706 +23,230 @@ #include "cadef.h" #include "epicsStdioRedirect.h" #define epicsExportSharedSymbols +#include "dbChannel.h" #include "db_access_routines.h" #include "dbNotify.h" #include "db_test.h" #include "dbCommon.h" - #define MAX_ELEMS 10 -int epicsShareAPI gft(char *pname) + +int gft(char *pname) { - char tgf_buffer[MAX_ELEMS*MAX_STRING_SIZE+sizeof(struct dbr_ctrl_double)]; - struct dbAddr addr; - struct dbAddr *paddr = &addr; - short number_elements; - int i; - int status; + char tgf_buffer[MAX_ELEMS*MAX_STRING_SIZE + sizeof(struct dbr_ctrl_double)]; + struct dbChannel *chan; + struct dbCommon *precord; + long elements; + short type; + int i; - if (pname==0 || ((*pname < ' ') || (*pname > 'z'))) { - printf("\nusage \"pv name\"\n"); - return(1); - } - /* convert name to database address */ - status=db_name_to_addr(pname,&addr); - if(status) { - printf("db_name_to_addr failed\n"); - return(1); - } - printf(" Record Name: %s\n",pname); - printf("Record Address: 0x%p\n",(void *)addr.precord); - printf(" Field Type: %d\n",addr.dbr_field_type); - printf(" Field Address: 0x%p\n",addr.pfield); - printf(" Field Size: %d\n",addr.field_size); - printf(" No Elements: %ld\n",addr.no_elements); - number_elements = - ((addr.no_elements > MAX_ELEMS)?MAX_ELEMS:addr.no_elements); + chan = dbChannel_create(pname); + if (!chan) { + printf("Channel couldn't be created\n"); + return 1; + } - for(i=0; i<=LAST_BUFFER_TYPE; i++) { - if(addr.dbr_field_type==0) { - if( (i!=DBR_STRING) - && (i!=DBR_STS_STRING) - && (i!=DBR_TIME_STRING) - && (i!=DBR_GR_STRING) - && (i!=DBR_CTRL_STRING)) continue; - } - if(db_get_field(paddr,i,tgf_buffer,number_elements,NULL)<0) - printf("\t%s Failed\n",dbr_text[i]); - else - ca_dump_dbr (i,number_elements,tgf_buffer); - } - return(0); + precord = dbChannelRecord(chan); + elements = dbChannelElements(chan); + type = dbChannelExportType(chan); + + printf(" Record Name: %s\n", precord->name); + printf("Record Address: 0x%p\n", precord); + printf(" Export Type: %d\n", type); + printf(" Field Address: 0x%p\n", dbChannelData(chan)); + printf(" Field Size: %d\n", dbChannelElementSize(chan)); + printf(" No Elements: %ld\n", elements); + + if (elements > MAX_ELEMS) + elements = MAX_ELEMS; + + for (i = 0; i <= LAST_BUFFER_TYPE; i++) { + if (type == 0) { + if ((i != DBR_STRING) && (i != DBR_STS_STRING) && + (i != DBR_TIME_STRING) && (i != DBR_GR_STRING) && + (i != DBR_CTRL_STRING)) + continue; + } + if (dbChannel_get(chan, i, tgf_buffer, elements, NULL) < 0) + printf("\t%s Failed\n", dbr_text[i]); + else + ca_dump_dbr(i, elements, tgf_buffer); + } + + dbChannelDelete(chan); + return 0; } - + /* * TPF * Test put field */ -int epicsShareAPI pft(char *pname,char *pvalue) +int epicsShareAPI pft(char *pname, char *pvalue) { - struct dbAddr addr; - struct dbAddr *paddr = &addr; - char buffer[500]; - short shortvalue; - long longvalue; - float floatvalue; - unsigned char charvalue; - double doublevalue; - int status; + struct dbChannel *chan; + struct dbCommon *precord; + long elements; + short type; + char buffer[500]; + short shortvalue; + long longvalue; + float floatvalue; + unsigned char charvalue; + double doublevalue; - if (pname==0 || pvalue==0 - || ((*pname < ' ') || (*pname > 'z')) - || ((*pvalue < ' ') || (*pvalue > 'z'))){ - printf("\nusage \"pv name\",\"value\"\n"); - return(1); - } + chan = dbChannel_create(pname); + if (!chan) { + printf("Channel couldn't be created\n"); + return 1; + } - /* convert name to database address */ + precord = dbChannelRecord(chan); + elements = dbChannelElements(chan); + type = dbChannelExportType(chan); - /* convert name to database address */ - status=db_name_to_addr(pname,&addr); - if(status) { - printf("db_name_to_addr failed\n"); - return(1); - } - printf(" Record Name: %s\n",pname); - printf("Record Address: 0x%p\n",(void *)addr.precord); - printf(" Field Type: %d\n",addr.dbr_field_type); - printf(" Field Address: 0x%p\n",addr.pfield); - printf(" Field Size: %d\n",addr.field_size); - printf(" No Elements: %ld\n",addr.no_elements); - if (db_put_field(paddr,DBR_STRING,pvalue,1) < 0) printf("\n\t failed "); - if (db_get_field(paddr,DBR_STRING,buffer,1,NULL) < 0) printf("\n\tfailed"); - else ca_dump_dbr(DBR_STRING,1,buffer); - if(addr.dbr_field_type<=DBF_STRING || addr.dbr_field_type==DBF_ENUM) - return(0); - if(sscanf(pvalue,"%hd",&shortvalue)==1) { - if (db_put_field(paddr,DBR_SHORT,&shortvalue,1) < 0) - printf("\n\t SHORT failed "); - if (db_get_field(paddr,DBR_SHORT,buffer,1,NULL) < 0) - printf("\n\t SHORT GET failed"); - else ca_dump_dbr(DBR_SHORT,1,buffer); - } - if(sscanf(pvalue,"%ld",&longvalue)==1) { - if (db_put_field(paddr,DBR_LONG,&longvalue,1) < 0) - printf("\n\t LONG failed "); - if (db_get_field(paddr,DBR_LONG,buffer,1,NULL) < 0) - printf("\n\t LONG GET failed"); - else ca_dump_dbr(DBR_LONG,1,buffer); - } - if(epicsScanFloat(pvalue, &floatvalue)==1) { - if (db_put_field(paddr,DBR_FLOAT,&floatvalue,1) < 0) - printf("\n\t FLOAT failed "); - if (db_get_field(paddr,DBR_FLOAT,buffer,1,NULL) < 0) - printf("\n\t FLOAT GET failed"); - else ca_dump_dbr(DBR_FLOAT,1,buffer); - } - if(epicsScanFloat(pvalue, &floatvalue)==1) { - doublevalue=floatvalue; - if (db_put_field(paddr,DBR_DOUBLE,&doublevalue,1) < 0) - printf("\n\t DOUBLE failed "); - if (db_get_field(paddr,DBR_DOUBLE,buffer,1,NULL) < 0) - printf("\n\t DOUBLE GET failed"); - else ca_dump_dbr(DBR_DOUBLE,1,buffer); - } - if(sscanf(pvalue,"%hd",&shortvalue)==1) { - charvalue=(unsigned char)shortvalue; - if (db_put_field(paddr,DBR_CHAR,&charvalue,1) < 0) - printf("\n\t CHAR failed "); - if (db_get_field(paddr,DBR_CHAR,buffer,1,NULL) < 0) - printf("\n\t CHAR GET failed"); - else ca_dump_dbr(DBR_CHAR,1,buffer); - } - if(sscanf(pvalue,"%hd",&shortvalue)==1) { - if (db_put_field(paddr,DBR_ENUM,&shortvalue,1) < 0) - printf("\n\t ENUM failed "); - if (db_get_field(paddr,DBR_ENUM,buffer,1,NULL) < 0) - printf("\n\t ENUM GET failed"); - else ca_dump_dbr(DBR_ENUM,1,buffer); - } - printf("\n"); - return(0); -} + printf(" Record Name: %s\n", precord->name); + printf("Record Address: 0x%p\n", precord); + printf(" Export Type: %d\n", type); + printf(" Field Address: 0x%p\n", dbChannelData(chan)); + printf(" Field Size: %d\n", dbChannelElementSize(chan)); + printf(" No Elements: %ld\n", elements); -#if 0 -/* - * PRINT_RETURNED - * - * print out the values in a database access interface structure - */ -static void print_returned(type,count,pbuffer) - short type; - char *pbuffer; - short count; -{ - short i; + if (dbChannel_put(chan, DBR_STRING,pvalue, 1) < 0) + printf("\n\t failed "); + if (dbChannel_get(chan, DBR_STRING,buffer, 1, NULL) < 0) + printf("\n\tfailed"); + else + ca_dump_dbr(DBR_STRING,1, buffer); - printf("%s\t",dbr_text[type]); - switch(type){ - case (DBR_STRING): - for(i=0; istatus,pvalue->severity); - printf("\tValue: %s",pvalue->value); - break; - } - case (DBR_STS_ENUM): - case (DBR_STS_SHORT): - { - struct dbr_sts_short *pvalue - = (struct dbr_sts_short *)pbuffer; - short *pshort = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pshort++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*pshort); - } - break; - } - case (DBR_STS_FLOAT): - { - struct dbr_sts_float *pvalue - = (struct dbr_sts_float *)pbuffer; - float *pfloat = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pfloat++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",*pfloat); - } - break; - } - case (DBR_STS_CHAR): - { - struct dbr_sts_char *pvalue - = (struct dbr_sts_char *)pbuffer; - unsigned char *pchar = &pvalue->value; - short value; - - printf("%2d %2d",pvalue->status,pvalue->severity); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pchar++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - value=*pchar; - printf("%d ",value); - } - break; - } - case (DBR_STS_LONG): - { - struct dbr_sts_long *pvalue - = (struct dbr_sts_long *)pbuffer; - dbr_long_t *plong = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,plong++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*plong); - } - break; - } - case (DBR_STS_DOUBLE): - { - struct dbr_sts_double *pvalue - = (struct dbr_sts_double *)pbuffer; - double *pdouble = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pdouble++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",(float)(*pdouble)); - } - break; - } - case (DBR_TIME_STRING): - { - struct dbr_time_string *pvalue - = (struct dbr_time_string *) pbuffer; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf("\tTimeStamp: %u %u", - pvalue->stamp.secPastEpoch, pvalue->stamp.nsec); - printf("\tValue: "); - printf("%s",pvalue->value); - break; - } - case (DBR_TIME_SHORT): - case (DBR_TIME_ENUM): - { - struct dbr_time_short *pvalue - = (struct dbr_time_short *)pbuffer; - short *pshort = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf("\tTimeStamp: %u %u", - pvalue->stamp.secPastEpoch, pvalue->stamp.nsec); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pshort++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*pshort); - } - break; - } - case (DBR_TIME_FLOAT): - { - struct dbr_time_float *pvalue - = (struct dbr_time_float *)pbuffer; - float *pfloat = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf("\tTimeStamp: %u %u", - pvalue->stamp.secPastEpoch, pvalue->stamp.nsec); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pfloat++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",*pfloat); - } - break; - } - case (DBR_TIME_CHAR): - { - struct dbr_time_char *pvalue - = (struct dbr_time_char *)pbuffer; - unsigned char *pchar = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf("\tTimeStamp: %u %u", - pvalue->stamp.secPastEpoch, pvalue->stamp.nsec); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pchar++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",(short)(*pchar)); - } - break; - } - case (DBR_TIME_LONG): - { - struct dbr_time_long *pvalue - = (struct dbr_time_long *)pbuffer; - dbr_long_t *plong = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf("\tTimeStamp: %u %u", - pvalue->stamp.secPastEpoch, pvalue->stamp.nsec); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,plong++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*plong); - } - break; - } - case (DBR_TIME_DOUBLE): - { - struct dbr_time_double *pvalue - = (struct dbr_time_double *)pbuffer; - double *pdouble = &pvalue->value; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf("\tTimeStamp: %u %u", - pvalue->stamp.secPastEpoch, pvalue->stamp.nsec); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pdouble++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",(float)(*pdouble)); - } - break; - } - case (DBR_GR_SHORT): - { - struct dbr_gr_short *pvalue - = (struct dbr_gr_short *)pbuffer; - short *pshort = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf("\n\t%8d %8d %8d %8d %8d %8d", - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pshort++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*pshort); - } - break; - } - case (DBR_GR_FLOAT): - { - struct dbr_gr_float *pvalue - = (struct dbr_gr_float *)pbuffer; - float *pfloat = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf(" %3d\n\t%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f", - pvalue->precision, - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pfloat++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",*pfloat); - } - break; - } - case (DBR_GR_ENUM): - case (DBR_CTRL_ENUM): - { - struct dbr_gr_enum *pvalue - = (struct dbr_gr_enum *)pbuffer; - printf("%2d %2d",pvalue->status, - pvalue->severity); - printf("\tValue: %d",pvalue->value); - if(pvalue->no_str>0) { - printf("\n\t%3d",pvalue->no_str); - for (i = 0; i < pvalue->no_str; i++) - printf("\n\t%.26s",pvalue->strs[i]); - } - break; - } - case (DBR_GR_CHAR): - { - struct dbr_gr_char *pvalue - = (struct dbr_gr_char *)pbuffer; - unsigned char *pchar = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf("\n\t%8d %8d %8d %8d %8d %8d", - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pchar++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",(short)(*pchar)); - } - break; - } - case (DBR_GR_LONG): - { - struct dbr_gr_long *pvalue - = (struct dbr_gr_long *)pbuffer; - dbr_long_t *plong = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf("\n\t%8d %8d %8d %8d %8d %8d", - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,plong++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*plong); - } - break; - } - case (DBR_GR_DOUBLE): - { - struct dbr_gr_double *pvalue - = (struct dbr_gr_double *)pbuffer; - double *pdouble = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf(" %3d\n\t%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f", - pvalue->precision, - (float)(pvalue->upper_disp_limit), - (float)(pvalue->lower_disp_limit), - (float)(pvalue->upper_alarm_limit), - (float)(pvalue->upper_warning_limit), - (float)(pvalue->lower_warning_limit), - (float)(pvalue->lower_alarm_limit)); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pdouble++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",(float)(*pdouble)); - } - break; - } - case (DBR_CTRL_SHORT): - { - struct dbr_ctrl_short *pvalue - = (struct dbr_ctrl_short *)pbuffer; - short *pshort = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf("\n\t%8d %8d %8d %8d %8d %8d", - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - printf(" %8d %8d", - pvalue->upper_ctrl_limit,pvalue->lower_ctrl_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pshort++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*pshort); - } - break; - } - case (DBR_CTRL_FLOAT): - { - struct dbr_ctrl_float *pvalue - = (struct dbr_ctrl_float *)pbuffer; - float *pfloat = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf(" %3d\n\t%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f", - pvalue->precision, - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - printf(" %8.3f %8.3f", - pvalue->upper_ctrl_limit,pvalue->lower_ctrl_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pfloat++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.4f ",*pfloat); - } - break; - } - case (DBR_CTRL_CHAR): - { - struct dbr_ctrl_char *pvalue - = (struct dbr_ctrl_char *)pbuffer; - unsigned char *pchar = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf("\n\t%8d %8d %8d %8d %8d %8d", - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - printf(" %8d %8d", - pvalue->upper_ctrl_limit,pvalue->lower_ctrl_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pchar++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%4d ",(short)(*pchar)); - } - break; - } - case (DBR_CTRL_LONG): - { - struct dbr_ctrl_long *pvalue - = (struct dbr_ctrl_long *)pbuffer; - dbr_long_t *plong = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf("\n\t%8d %8d %8d %8d %8d %8d", - pvalue->upper_disp_limit,pvalue->lower_disp_limit, - pvalue->upper_alarm_limit,pvalue->upper_warning_limit, - pvalue->lower_warning_limit,pvalue->lower_alarm_limit); - printf(" %8d %8d", - pvalue->upper_ctrl_limit,pvalue->lower_ctrl_limit); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,plong++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%d ",*plong); - } - break; - } - case (DBR_CTRL_DOUBLE): - { - struct dbr_ctrl_double *pvalue - = (struct dbr_ctrl_double *)pbuffer; - double *pdouble = &pvalue->value; - printf("%2d %2d %.8s",pvalue->status,pvalue->severity, - pvalue->units); - printf(" %3d\n\t%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f", - pvalue->precision, - (float)(pvalue->upper_disp_limit), - (float)(pvalue->lower_disp_limit), - (float)(pvalue->upper_alarm_limit), - (float)(pvalue->upper_warning_limit), - (float)(pvalue->lower_warning_limit), - (float)(pvalue->lower_alarm_limit)); - printf(" %8.3f %8.3f", - (float)(pvalue->upper_ctrl_limit), - (float)(pvalue->lower_ctrl_limit)); - if(count==1) printf("\tValue: "); - for (i = 0; i < count; i++,pdouble++){ - if(count!=1 && (i%10 == 0)) printf("\n"); - printf("%6.6f ",(float)(*pdouble)); - } - break; - } - case (DBR_STSACK_STRING): - { - struct dbr_stsack_string *pvalue - = (struct dbr_stsack_string *)pbuffer; - printf("%2d %2d",pvalue->status,pvalue->severity); - printf(" %2d %2d",pvalue->ackt,pvalue->acks); - printf(" %s",pvalue->value); - break; - } - case (DBR_CLASS_NAME): - { - printf(" %s",(char *)pbuffer); - break; - } + if (sscanf(pvalue, "%hd", &shortvalue) == 1) { + if (dbChannel_put(chan, DBR_SHORT,&shortvalue, 1) < 0) + printf("\n\t SHORT failed "); + if (dbChannel_get(chan, DBR_SHORT,buffer, 1, NULL) < 0) + printf("\n\t SHORT GET failed"); + else + ca_dump_dbr(DBR_SHORT,1, buffer); + } + if (sscanf(pvalue, "%ld", &longvalue) == 1) { + if (dbChannel_put(chan, DBR_LONG,&longvalue, 1) < 0) + printf("\n\t LONG failed "); + if (dbChannel_get(chan, DBR_LONG,buffer, 1, NULL) < 0) + printf("\n\t LONG GET failed"); + else + ca_dump_dbr(DBR_LONG,1, buffer); + } + if (epicsScanFloat(pvalue, &floatvalue) == 1) { + if (dbChannel_put(chan, DBR_FLOAT,&floatvalue, 1) < 0) + printf("\n\t FLOAT failed "); + if (dbChannel_get(chan, DBR_FLOAT,buffer, 1, NULL) < 0) + printf("\n\t FLOAT GET failed"); + else + ca_dump_dbr(DBR_FLOAT,1, buffer); + } + if (epicsScanFloat(pvalue, &floatvalue) == 1) { + doublevalue = floatvalue; + if (dbChannel_put(chan, DBR_DOUBLE,&doublevalue, 1) < 0) + printf("\n\t DOUBLE failed "); + if (dbChannel_get(chan, DBR_DOUBLE,buffer, 1, NULL) < 0) + printf("\n\t DOUBLE GET failed"); + else + ca_dump_dbr(DBR_DOUBLE,1, buffer); + } + if (sscanf(pvalue, "%hd", &shortvalue) == 1) { + charvalue = (unsigned char) shortvalue; + if (dbChannel_put(chan, DBR_CHAR,&charvalue, 1) < 0) + printf("\n\t CHAR failed "); + if (dbChannel_get(chan, DBR_CHAR,buffer, 1, NULL) < 0) + printf("\n\t CHAR GET failed"); + else + ca_dump_dbr(DBR_CHAR,1, buffer); + } + if (sscanf(pvalue, "%hd", &shortvalue) == 1) { + if (dbChannel_put(chan, DBR_ENUM,&shortvalue, 1) < 0) + printf("\n\t ENUM failed "); + if (dbChannel_get(chan, DBR_ENUM,buffer, 1, NULL) < 0) + printf("\n\t ENUM GET failed"); + else + ca_dump_dbr(DBR_ENUM,1, buffer); } printf("\n"); + return (0); } -#endif - + + typedef struct tpnInfo { epicsEventId callbackDone; - putNotify *ppn; -}tpnInfo; + putNotify *ppn; + struct dbChannel *chan; +} tpnInfo; static void tpnCallback(putNotify *ppn) { - struct dbAddr *pdbaddr = (struct dbAddr *)ppn->paddr; - tpnInfo *ptpnInfo = (tpnInfo *)ppn->usrPvt; + tpnInfo *ptpnInfo = (tpnInfo *) ppn->usrPvt; putNotifyStatus status = ppn->status; - char *pname = pdbaddr->precord->name; + const char *pname = dbChannelRecord(ppn->chan)->name; - if(status==0) - printf("tpnCallback: success record=%s\n",pname); + if (status == 0) + printf("tpnCallback: success record=%s\n", pname); else - printf("%s tpnCallback status = %d\n",pname,status); + printf("%s tpnCallback status = %d\n", pname, status); epicsEventSignal(ptpnInfo->callbackDone); } static void tpnThread(void *pvt) { - tpnInfo *ptpnInfo = (tpnInfo *)pvt; - putNotify *ppn = (putNotify *)ptpnInfo->ppn; + tpnInfo *ptpnInfo = (tpnInfo *) pvt; + putNotify *ppn = (putNotify *) ptpnInfo->ppn; dbPutNotify(ppn); epicsEventWait(ptpnInfo->callbackDone); dbNotifyCancel(ppn); epicsEventDestroy(ptpnInfo->callbackDone); - free((void *)ppn->paddr); + free(ppn->pbuffer); + dbChannelDelete(ppn->chan); free(ppn); free(ptpnInfo); } - -int epicsShareAPI tpn(char *pname,char *pvalue) +int epicsShareAPI tpn(char *pname, char *pvalue) { - long status; - tpnInfo *ptpnInfo; - struct dbAddr *pdbaddr=NULL; - putNotify *ppn=NULL; - char *psavevalue; - int len; + struct dbChannel *chan; + tpnInfo *ptpnInfo; + putNotify *ppn; + char *pbuffer; - if (pname==0 || pvalue==0 - || ((*pname < ' ') || (*pname > 'z')) - || ((*pvalue < ' ') || (*pvalue > 'z'))){ - printf("\nusage \"pv name\",\"value\"\n"); - return(1); + chan = dbChannel_create(pname); + if (!chan) { + printf("Channel couldn't be created\n"); + return 1; } - len = strlen(pvalue); - /*allocate space for value immediately following DBADDR*/ - pdbaddr = calloc(1,sizeof(struct dbAddr) + len+1); - if(!pdbaddr) { - printf("calloc failed\n"); - return(-1); + + pbuffer = strdup(pvalue); + ppn = calloc(1, sizeof(putNotify)); + if (!ppn) { + printf("calloc failed\n"); + return -1; } - psavevalue = (char *)(pdbaddr + 1); - strcpy(psavevalue,pvalue); - status = db_name_to_addr(pname,pdbaddr); - if(status) { - printf("db_name_to_addr failed\n"); - free((void *)pdbaddr); - return(-1); - } - ppn = calloc(1,sizeof(putNotify)); - if(!pdbaddr) { - printf("calloc failed\n"); - return(-1); - } - ppn->paddr = pdbaddr; - ppn->pbuffer = psavevalue; + ppn->chan = chan; + ppn->pbuffer = pbuffer; ppn->nRequest = 1; - if(dbPutNotifyMapType(ppn,DBR_STRING)) { - printf("dbPutNotifyMapType failed\n"); - printf("calloc failed\n"); - return(-1); + if (dbPutNotifyMapType(ppn, DBR_STRING)) { + printf("dbPutNotifyMapType failed\n"); + printf("calloc failed\n"); + return -1; } ppn->userCallback = tpnCallback; - ptpnInfo = calloc(1,sizeof(tpnInfo)); - if(!ptpnInfo) { - printf("calloc failed\n"); - return(-1); + ptpnInfo = calloc(1, sizeof(tpnInfo)); + if (!ptpnInfo) { + printf("calloc failed\n"); + return -1; } ptpnInfo->ppn = ppn; ptpnInfo->callbackDone = epicsEventCreate(epicsEventEmpty); ppn->usrPvt = ptpnInfo; - epicsThreadCreate("tpn",epicsThreadPriorityHigh, - epicsThreadGetStackSize(epicsThreadStackMedium), - tpnThread,ptpnInfo); - return(0); + epicsThreadCreate("tpn", epicsThreadPriorityHigh, + epicsThreadGetStackSize(epicsThreadStackMedium), tpnThread, ptpnInfo); + return 0; } diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 09015f667..f51b81c5e 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -45,7 +45,7 @@ #include "rsrv.h" #include "server.h" -#define RECORD_NAME(PADDR) ((PADDR)->precord->name) +#define RECORD_NAME(CHAN) (dbChannelRecord(CHAN)->name) static EVENTFUNC read_reply; @@ -60,9 +60,9 @@ typedef struct rsrv_put_notify { putNotify dbPutNotify; caHdrLargeArray msg; /* - * Include a union of all scalar types + * Include a union of all scalar types * including fixed length strings so - * that in many cases we can avoid + * that in many cases we can avoid * allocating another buffer and only * use an rsrv_put_notify from its * free list. @@ -173,8 +173,8 @@ va_list args /* * allocate plenty of space for a sprintf() buffer */ - localStatus = cas_copy_in_header ( client, - CA_PROTO_ERROR, maxDiagLen, 0, 0, cid, status, + localStatus = cas_copy_in_header ( client, + CA_PROTO_ERROR, maxDiagLen, 0, 0, cid, status, ( void * ) &pReqOut ); if ( localStatus != ECA_NORMAL ) { errlogPrintf ( "caserver: Unable to deliver err msg \"%s\" to client because \"%s\"\n", @@ -187,7 +187,7 @@ va_list args * copy back the request protocol * (in network byte order) */ - if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) && + if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) && CA_V49( client->minor_version_number ) ) { ca_uint32_t *pLW = ( ca_uint32_t * ) ( pReqOut + 1 ); pReqOut->m_cmmd = htons ( curp->m_cmmd ); @@ -222,7 +222,7 @@ va_list args size += (ca_uint32_t) (diagLen + 1u); } else { - errlogPrintf ( + errlogPrintf ( "caserver: vsend_err: epicsVsnprintf detected " "error message truncation, pFormat = \"%s\"\n", pformat ); @@ -282,9 +282,9 @@ static void log_header ( "CAS: Request from %s => cmmd=%d cid=0x%x type=%d count=%d postsize=%u\n", hostName, mp->m_cmmd, mp->m_cid, mp->m_dataType, mp->m_count, mp->m_postsize); - epicsPrintf ( -"CAS: Request from %s => available=0x%x \tN=%u paddr=%p\n", - hostName, mp->m_available, mnum, (pciu?(void *)&pciu->addr:NULL)); + epicsPrintf ( +"CAS: Request from %s => available=0x%x \tN=%u dbch=%p\n", + hostName, mp->m_available, mnum, (pciu?(void *)&pciu->dbch:NULL)); if (mp->m_cmmd==CA_PROTO_WRITE && mp->m_dataType==DBF_STRING && pPayLoad ) { epicsPrintf ( @@ -297,7 +297,7 @@ static void log_header ( * logBadIdWithFileAndLineno() */ static void logBadIdWithFileAndLineno( -struct client *client, +struct client *client, caHdrLargeArray *mp, const void *pPayload, char *pFileName, @@ -314,10 +314,10 @@ unsigned lineno /* * bad_udp_cmd_action() */ -static int bad_udp_cmd_action ( caHdrLargeArray *mp, +static int bad_udp_cmd_action ( caHdrLargeArray *mp, void *pPayload, struct client *pClient ) { - log_header ("invalid (damaged?) request code from UDP", + log_header ("invalid (damaged?) request code from UDP", pClient, mp, pPayload, 0); return RSRV_ERROR; } @@ -325,13 +325,13 @@ static int bad_udp_cmd_action ( caHdrLargeArray *mp, /* * udp_echo_action() */ -static int udp_echo_action ( caHdrLargeArray *mp, +static int udp_echo_action ( caHdrLargeArray *mp, void *pPayload, struct client *pClient ) { char *pPayloadOut; int status; SEND_LOCK ( pClient ); - status = cas_copy_in_header ( pClient, mp->m_cmmd, mp->m_postsize, + status = cas_copy_in_header ( pClient, mp->m_cmmd, mp->m_postsize, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, ( void * ) &pPayloadOut ); if ( status == ECA_NORMAL ) { @@ -345,13 +345,13 @@ static int udp_echo_action ( caHdrLargeArray *mp, /* * bad_tcp_cmd_action() */ -static int bad_tcp_cmd_action ( caHdrLargeArray *mp, void *pPayload, +static int bad_tcp_cmd_action ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { const char *pCtx = "invalid (damaged?) request code from TCP"; log_header ( pCtx, client, mp, pPayload, 0 ); - /* + /* * by default, clients dont recover * from this */ @@ -365,7 +365,7 @@ static int bad_tcp_cmd_action ( caHdrLargeArray *mp, void *pPayload, /* * tcp_version_action() */ -static int tcp_version_action ( caHdrLargeArray *mp, void *pPayload, +static int tcp_version_action ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { double tmp; @@ -406,13 +406,13 @@ static int tcp_version_action ( caHdrLargeArray *mp, void *pPayload, /* * tcp_echo_action() */ -static int tcp_echo_action ( caHdrLargeArray *mp, +static int tcp_echo_action ( caHdrLargeArray *mp, void *pPayload, struct client *pClient ) { char *pPayloadOut; int status; SEND_LOCK ( pClient ); - status = cas_copy_in_header ( pClient, mp->m_cmmd, mp->m_postsize, + status = cas_copy_in_header ( pClient, mp->m_cmmd, mp->m_postsize, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, ( void * ) &pPayloadOut ); if ( status == ECA_NORMAL ) { @@ -426,7 +426,7 @@ static int tcp_echo_action ( caHdrLargeArray *mp, /* * events_on_action () */ -static int events_on_action ( caHdrLargeArray *mp, +static int events_on_action ( caHdrLargeArray *mp, void *pPayload, struct client *pClient ) { db_event_flow_ctrl_mode_off ( pClient->evuser ); @@ -436,7 +436,7 @@ static int events_on_action ( caHdrLargeArray *mp, /* * events_off_action () */ -static int events_off_action ( caHdrLargeArray *mp, +static int events_off_action ( caHdrLargeArray *mp, void *pPayload, struct client *pClient ) { db_event_flow_ctrl_mode_on ( pClient->evuser ); @@ -462,8 +462,8 @@ static void no_read_access_event ( struct client *pClient, * on failure to pre v41 clients */ if ( ! CA_V41 ( pClient->minor_version_number ) ) { - send_err ( &pevext->msg, ECA_GETFAIL, pClient, - RECORD_NAME ( &pevext->pciu->addr ) ); + send_err ( &pevext->msg, ECA_GETFAIL, pClient, + RECORD_NAME ( pevext->pciu->dbch ) ); return; } @@ -473,30 +473,30 @@ static void no_read_access_event ( struct client *pClient, * event/put/get callback. * * Fetched value is zerod in case they - * use it even when the status indicates + * use it even when the status indicates * failure. * * The m_cid field in the protocol * header is abused to carry the status */ - status = cas_copy_in_header ( pClient, pevext->msg.m_cmmd, pevext->size, - pevext->msg.m_dataType, pevext->msg.m_count, ECA_NORDACCESS, + status = cas_copy_in_header ( pClient, pevext->msg.m_cmmd, pevext->size, + pevext->msg.m_dataType, pevext->msg.m_count, ECA_NORDACCESS, pevext->msg.m_available, ( void * ) &pPayloadOut ); if ( status == ECA_NORMAL ) { memset ( pPayloadOut, 0, pevext->size ); cas_commit_msg ( pClient, pevext->size ); } else { - send_err ( &pevext->msg, status, pClient, + send_err ( &pevext->msg, status, pClient, "server unable to load read access denied response into protocol buffer PV=\"%s max bytes=%u\"", - RECORD_NAME ( &pevext->pciu->addr ), rsrvSizeofLargeBufTCP ); + RECORD_NAME ( pevext->pciu->dbch ), rsrvSizeofLargeBufTCP ); } } /* * read_reply() */ -static void read_reply ( void *pArg, struct dbAddr *paddr, +static void read_reply ( void *pArg, struct dbChannel *dbch, int eventsRemaining, db_field_log *pfl ) { ca_uint32_t cid; @@ -513,7 +513,7 @@ static void read_reply ( void *pArg, struct dbAddr *paddr, SEND_LOCK ( pClient ); - /* + /* * New clients recv the status of the * operation directly to the * event/put/get callback. @@ -543,7 +543,7 @@ static void read_reply ( void *pArg, struct dbAddr *paddr, pevext->msg.m_dataType, item_count, cid, pevext->msg.m_available, &pPayload ); if ( status != ECA_NORMAL ) { - send_err ( &pevext->msg, status, pClient, + send_err ( &pevext->msg, status, pClient, "server unable to load read (or subscription update) response " "into protocol buffer PV=\"%s\" max bytes=%u", RECORD_NAME ( paddr ), rsrvSizeofLargeBufTCP ); @@ -564,19 +564,19 @@ static void read_reply ( void *pArg, struct dbAddr *paddr, return; } - status = db_get_field_and_count( - paddr, pevext->msg.m_dataType, pPayload, &item_count, pfl); + status = dbChannel_get_count ( dbch, pevext->msg.m_dataType, + pPayload, &item_count, pfl); if ( status < 0 ) { /* * I cant wait to redesign this protocol from scratch! */ if ( ! v41 ) { /* - * old client & plain get + * old client & plain get * continue to return an exception * on failure */ - send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( paddr ) ); + send_err ( &pevext->msg, ECA_GETFAIL, pClient, RECORD_NAME ( dbch ) ); } else { /* New clients recv the status of the operation directly to the @@ -598,8 +598,8 @@ static void read_reply ( void *pArg, struct dbAddr *paddr, } } else { - int cacStatus = caNetConvert ( - pevext->msg.m_dataType, pPayload, pPayload, + int cacStatus = caNetConvert ( + pevext->msg.m_dataType, pPayload, pPayload, TRUE /* host -> net format */, item_count ); if ( cacStatus == ECA_NORMAL ) { ca_uint32_t data_size = @@ -655,18 +655,18 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p SEND_LOCK ( pClient ); if ( INVALID_DB_REQ ( mp->m_dataType ) ) { - send_err ( mp, ECA_BADTYPE, pClient, RECORD_NAME ( &pciu->addr ) ); + send_err ( mp, ECA_BADTYPE, pClient, RECORD_NAME ( pciu->dbch ) ); SEND_UNLOCK ( pClient ); return RSRV_ERROR; } payloadSize = dbr_size_n ( mp->m_dataType, mp->m_count ); - status = cas_copy_in_header ( pClient, mp->m_cmmd, payloadSize, + status = cas_copy_in_header ( pClient, mp->m_cmmd, payloadSize, mp->m_dataType, mp->m_count, pciu->cid, mp->m_available, &pPayload ); if ( status != ECA_NORMAL ) { - send_err ( mp, status, pClient, + send_err ( mp, status, pClient, "server unable to load read response into protocol buffer PV=\"%s\" max bytes=%u", - RECORD_NAME ( &pciu->addr ), rsrvSizeofLargeBufTCP ); + RECORD_NAME ( pciu->dbch ), rsrvSizeofLargeBufTCP ); SEND_UNLOCK ( pClient ); return RSRV_OK; } @@ -682,25 +682,25 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p else{ status = ECA_GETFAIL; } - send_err ( mp, status, - pClient, RECORD_NAME ( &pciu->addr ) ); + send_err ( mp, status, + pClient, RECORD_NAME ( pciu->dbch ) ); SEND_UNLOCK ( pClient ); return RSRV_OK; } - status = db_get_field ( &pciu->addr, mp->m_dataType, + status = dbChannel_get ( pciu->dbch, mp->m_dataType, pPayload, mp->m_count, 0 ); if ( status < 0 ) { - send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( &pciu->addr ) ); + send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( pciu->dbch ) ); SEND_UNLOCK ( pClient ); return RSRV_OK; } - status = caNetConvert ( - mp->m_dataType, pPayload, pPayload, + status = caNetConvert ( + mp->m_dataType, pPayload, pPayload, TRUE /* host -> net format */, mp->m_count ); if ( status != ECA_NORMAL ) { - send_err ( mp, status, pClient, RECORD_NAME ( &pciu->addr ) ); + send_err ( mp, status, pClient, RECORD_NAME ( pciu->dbch ) ); SEND_UNLOCK ( pClient ); return RSRV_OK; } @@ -717,7 +717,7 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p } else { pStr[payloadSize-1] = '\0'; - errlogPrintf ( + errlogPrintf ( "caserver: read_action: detected DBR_STRING w/o nill termination " "in response from db_get_field, pPayload = \"%s\"\n", pStr ); @@ -754,11 +754,11 @@ static int read_notify_action ( caHdrLargeArray *mp, void *pPayload, struct clie * favor of the standard db event calling * mechanism- routine(userarg, paddr). See * events added above. - * + * * Hold argument set true so the send message * buffer is not flushed once each call. */ - read_reply ( &evext, &pciu->addr, TRUE, NULL ); + read_reply ( &evext, pciu->dbch, TRUE, NULL ); return RSRV_OK; } @@ -766,7 +766,7 @@ static int read_notify_action ( caHdrLargeArray *mp, void *pPayload, struct clie /* * write_action() */ -static int write_action ( caHdrLargeArray *mp, +static int write_action ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { struct channel_in_use *pciu; @@ -791,25 +791,25 @@ static int write_action ( caHdrLargeArray *mp, } SEND_LOCK(client); send_err( - mp, - status, - client, - RECORD_NAME(&pciu->addr)); + mp, + status, + client, + RECORD_NAME ( pciu->dbch )); SEND_UNLOCK(client); return RSRV_OK; } - status = caNetConvert ( - mp->m_dataType, pPayload, pPayload, + status = caNetConvert ( + mp->m_dataType, pPayload, pPayload, FALSE /* net -> host format */, mp->m_count ); if ( status != ECA_NORMAL ) { log_header ("invalid data type", client, mp, pPayload, 0); SEND_LOCK(client); send_err( - mp, - status, - client, - RECORD_NAME(&pciu->addr)); + mp, + status, + client, + RECORD_NAME ( pciu->dbch )); SEND_UNLOCK(client); return RSRV_ERROR; } @@ -817,10 +817,10 @@ static int write_action ( caHdrLargeArray *mp, asWritePvt = asTrapWriteBefore ( pciu->asClientPVT, pciu->client->pUserName ? pciu->client->pUserName : "", pciu->client->pHostName ? pciu->client->pHostName : "", - (void *) &pciu->addr ); + pciu->dbch ); - dbStatus = db_put_field( - &pciu->addr, + dbStatus = dbChannel_put( + pciu->dbch, mp->m_dataType, pPayload, mp->m_count); @@ -830,10 +830,10 @@ static int write_action ( caHdrLargeArray *mp, if (dbStatus < 0) { SEND_LOCK(client); send_err( - mp, - ECA_PUTFAIL, - client, - RECORD_NAME(&pciu->addr)); + mp, + ECA_PUTFAIL, + client, + RECORD_NAME ( pciu->dbch )); SEND_UNLOCK(client); } @@ -852,8 +852,8 @@ static int host_name_action ( caHdrLargeArray *mp, void *pPayload, int chanCount; epicsMutexMustLock ( client->chanListLock ); - chanCount = - ellCount ( &client->chanList ) + + chanCount = + ellCount ( &client->chanList ) + ellCount ( &client->chanPendingUpdateARList ); epicsMutexUnlock( client->chanListLock ); @@ -872,13 +872,13 @@ static int host_name_action ( caHdrLargeArray *mp, void *pPayload, pName = (char *) pPayload; size = strlen(pName)+1; if (size > 512) { - log_header ( "bad (very long) host name", + log_header ( "bad (very long) host name", client, mp, pPayload, 0 ); SEND_LOCK(client); send_err( - mp, - ECA_INTERNAL, - client, + mp, + ECA_INTERNAL, + client, "bad (very long) host name"); SEND_UNLOCK(client); return RSRV_ERROR; @@ -889,7 +889,7 @@ static int host_name_action ( caHdrLargeArray *mp, void *pPayload, */ pMalloc = malloc(size); if(!pMalloc){ - log_header ( "no space in pool for new host name", + log_header ( "no space in pool for new host name", client, mp, pPayload, 0 ); SEND_LOCK(client); send_err( @@ -901,8 +901,8 @@ static int host_name_action ( caHdrLargeArray *mp, void *pPayload, return RSRV_ERROR; } strncpy( - pMalloc, - pName, + pMalloc, + pName, size-1); pMalloc[size-1]='\0'; @@ -912,13 +912,13 @@ static int host_name_action ( caHdrLargeArray *mp, void *pPayload, free ( pName ); } - DLOG (2, ( "CAS: host_name_action for \"%s\"\n", + DLOG (2, ( "CAS: host_name_action for \"%s\"\n", client->pHostName ? client->pHostName : "" ) ); return RSRV_OK; } - + /* * client_name_action() */ @@ -931,8 +931,8 @@ static int client_name_action ( caHdrLargeArray *mp, void *pPayload, int chanCount; epicsMutexMustLock ( client->chanListLock ); - chanCount = - ellCount ( &client->chanList ) + + chanCount = + ellCount ( &client->chanList ) + ellCount ( &client->chanPendingUpdateARList ); epicsMutexUnlock( client->chanListLock ); @@ -951,13 +951,13 @@ static int client_name_action ( caHdrLargeArray *mp, void *pPayload, pName = (char *) pPayload; size = strlen(pName)+1; if (size > 512) { - log_header ("a very long user name was specified", + log_header ("a very long user name was specified", client, mp, pPayload, 0); SEND_LOCK(client); send_err( - mp, - ECA_INTERNAL, - client, + mp, + ECA_INTERNAL, + client, "a very long user name was specified"); SEND_UNLOCK(client); return RSRV_ERROR; @@ -968,7 +968,7 @@ static int client_name_action ( caHdrLargeArray *mp, void *pPayload, */ pMalloc = malloc(size); if(!pMalloc){ - log_header ("no memory for new user name", + log_header ("no memory for new user name", client, mp, pPayload, 0); SEND_LOCK(client); send_err( @@ -980,8 +980,8 @@ static int client_name_action ( caHdrLargeArray *mp, void *pPayload, return RSRV_ERROR; } strncpy( - pMalloc, - pName, + pMalloc, + pName, size-1); pMalloc[size-1]='\0'; @@ -999,7 +999,7 @@ static int client_name_action ( caHdrLargeArray *mp, void *pPayload, */ static struct channel_in_use *casCreateChannel ( struct client *client, -struct dbAddr *pAddr, +struct dbChannel *dbch, unsigned cid ) { @@ -1009,14 +1009,14 @@ unsigned cid int status; /* get block off free list if possible */ - pchannel = (struct channel_in_use *) + pchannel = (struct channel_in_use *) freeListCalloc(rsrvChanFreeList); if (!pchannel) { return NULL; } ellInit(&pchannel->eventq); epicsTimeGetCurrent(&pchannel->time_at_creation); - pchannel->addr = *pAddr; + pchannel->dbch = dbch; pchannel->client = client; /* * bypass read only warning @@ -1046,8 +1046,8 @@ unsigned cid * Verify that this id is not in use */ status = bucketAddItemUnsignedId ( - pCaBucket, - &pchannel->sid, + pCaBucket, + &pchannel->sid, pchannel); } while (status == S_bucket_idInUse); @@ -1116,7 +1116,7 @@ static void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type) epicsMutexUnlock ( pclient->chanListLock ); /* - * Update all event call backs + * Update all event call backs */ epicsMutexMustLock(pclient->eventqLock); for (pevext = (struct event_ext *) ellFirst(&pciu->eventq); @@ -1175,8 +1175,8 @@ static void access_rights_reply ( struct channel_in_use * pciu ) } SEND_LOCK ( pciu->client ); - status = cas_copy_in_header ( - pciu->client, CA_PROTO_ACCESS_RIGHTS, 0, + status = cas_copy_in_header ( + pciu->client, CA_PROTO_ACCESS_RIGHTS, 0, 0, 0, pciu->cid, ar, 0 ); /* * OK to just ignore the request if the connection drops @@ -1197,26 +1197,28 @@ static void claim_ciu_reply ( struct channel_in_use * pciu ) if ( v42 ) { int status; ca_uint32_t nElem; + long dbElem; SEND_LOCK ( pciu->client ); - if ( pciu->addr.no_elements < 0 ) { + dbElem = dbChannelElements(pciu->dbch); + if ( dbElem < 0 ) { nElem = 0; } else { if ( ! CA_V49 ( pciu->client->minor_version_number ) ) { - if ( pciu->addr.no_elements >= 0xffff ) { + if ( dbElem >= 0xffff ) { nElem = 0xfffe; } else { - nElem = (ca_uint32_t) pciu->addr.no_elements; + nElem = (ca_uint32_t) dbElem; } } else { - nElem = (ca_uint32_t) pciu->addr.no_elements; + nElem = (ca_uint32_t) dbElem; } } - status = cas_copy_in_header ( + status = cas_copy_in_header ( pciu->client, CA_PROTO_CREATE_CHAN, 0u, - pciu->addr.dbr_field_type, nElem, pciu->cid, + dbChannelExportType(pciu->dbch), nElem, pciu->cid, pciu->sid, NULL ); if ( status == ECA_NORMAL ) { cas_commit_msg ( pciu->client, 0u ); @@ -1228,7 +1230,7 @@ static void claim_ciu_reply ( struct channel_in_use * pciu ) /* * claim_ciu_action() */ -static int claim_ciu_action ( caHdrLargeArray *mp, +static int claim_ciu_action ( caHdrLargeArray *mp, void *pPayload, client *client ) { int status; @@ -1243,47 +1245,48 @@ static int claim_ciu_action ( caHdrLargeArray *mp, client->minor_version_number = mp->m_available; if (CA_V44(client->minor_version_number)) { - struct dbAddr tmp_addr; + struct dbChannel *dbch; char *pName = (char *) pPayload; /* * check the sanity of the message */ if (mp->m_postsize<=1) { - log_header ( "empty PV name in UDP search request?", + log_header ( "empty PV name in UDP search request?", client, mp, pPayload, 0 ); return RSRV_OK; } pName[mp->m_postsize-1] = '\0'; - status = db_name_to_addr (pName, &tmp_addr); - if (status) { + dbch = dbChannel_create (pName); + if (!dbch) { return RSRV_OK; } - DLOG ( 2, ("CAS: claim_ciu_action found '%s', type %d, count %d\n", - pName, tmp_addr.dbr_field_type, tmp_addr.no_elements) ); - + DLOG ( 2, ("CAS: claim_ciu_action found '%s', type %d, count %d\n", + pName, dbChannelExportType(dbch), dbChannelElements(dbch)) ); + pciu = casCreateChannel ( - client, - &tmp_addr, + client, + dbch, mp->m_cid); if (!pciu) { - log_header ("no memory to create new channel", + log_header ("no memory to create new channel", client, mp, pPayload, 0); SEND_LOCK(client); - send_err(mp, - ECA_ALLOCMEM, - client, - RECORD_NAME(&tmp_addr)); + send_err(mp, + ECA_ALLOCMEM, + client, + RECORD_NAME(dbch)); SEND_UNLOCK(client); + dbChannelDelete(dbch); return RSRV_ERROR; } } else { epicsMutexMustLock(prsrv_cast_client->chanListLock); /* - * clients which dont claim their + * clients which dont claim their * channel in use block prior to * timeout must reconnect */ @@ -1302,8 +1305,8 @@ static int claim_ciu_action ( caHdrLargeArray *mp, return RSRV_ERROR; } - /* - * duplicate claim message are unacceptable + /* + * duplicate claim message are unacceptable * (so we disconnect the client) */ if (pciu->client!=prsrv_cast_client) { @@ -1327,7 +1330,7 @@ static int claim_ciu_action ( caHdrLargeArray *mp, * who is claiming it */ ellDelete( - &prsrv_cast_client->chanList, + &prsrv_cast_client->chanList, &pciu->node); epicsMutexUnlock(prsrv_cast_client->chanListLock); @@ -1343,12 +1346,12 @@ static int claim_ciu_action ( caHdrLargeArray *mp, */ status = asAddClient( &pciu->asClientPVT, - asDbGetMemberPvt(&pciu->addr), - asDbGetAsl(&pciu->addr), + asDbGetMemberPvt(pciu->dbch), + asDbGetAsl(pciu->dbch), client->pUserName ? client->pUserName : "", - client->pHostName ? client->pHostName : ""); + client->pHostName ? client->pHostName : ""); if(status != 0 && status != S_asLib_asNotActive){ - log_header ("No room for security table", + log_header ("No room for security table", client, mp, pPayload, 0); SEND_LOCK(client); send_err(mp, ECA_ALLOCMEM, client, "No room for security table"); @@ -1357,7 +1360,7 @@ static int claim_ciu_action ( caHdrLargeArray *mp, } /* - * store ptr to channel in use block + * store ptr to channel in use block * in access security private */ asPutClientPvt(pciu->asClientPVT, pciu); @@ -1366,7 +1369,7 @@ static int claim_ciu_action ( caHdrLargeArray *mp, * register for asynch updates of access rights changes */ status = asRegisterClientCallback( - pciu->asClientPVT, + pciu->asClientPVT, casAccessRightsCB); if ( status == S_asLib_asNotActive ) { epicsMutexMustLock ( client->chanListLock ); @@ -1378,10 +1381,10 @@ static int claim_ciu_action ( caHdrLargeArray *mp, claim_ciu_reply ( pciu ); } else if (status!=0) { - log_header ("No room for access security state change subscription", + log_header ("No room for access security state change subscription", client, mp, pPayload, 0); SEND_LOCK(client); - send_err(mp, ECA_ALLOCMEM, client, + send_err(mp, ECA_ALLOCMEM, client, "No room for access security state change subscription"); SEND_UNLOCK(client); return RSRV_ERROR; @@ -1429,7 +1432,7 @@ static void write_notify_call_back(putNotify *ppn) db_post_extra_labor(pClient->evuser); } -/* +/* * write_notify_reply() * (called by the CA server event task via the extra labor interface) */ @@ -1477,18 +1480,18 @@ static void write_notify_reply ( struct client * pClient ) asTrapWriteAfter ( asWritePvtTmp ); /* - * the channel id field is being abused to carry + * the channel id field is being abused to carry * status here */ SEND_LOCK(pClient); - localStatus = cas_copy_in_header ( - pClient, CA_PROTO_WRITE_NOTIFY, - 0u, msgtmp.m_dataType, msgtmp.m_count, status, + localStatus = cas_copy_in_header ( + pClient, CA_PROTO_WRITE_NOTIFY, + 0u, msgtmp.m_dataType, msgtmp.m_count, status, msgtmp.m_available, 0 ); if ( localStatus != ECA_NORMAL ) { /* * inability to aquire buffer space - * Indicates corruption + * Indicates corruption */ errlogPrintf("CA server corrupted - put call back(s) discarded\n"); SEND_UNLOCK ( pClient ); @@ -1511,11 +1514,11 @@ static void write_notify_reply ( struct client * pClient ) */ static void sendAllUpdateAS ( struct client *client ) { - struct channel_in_use *pciu; + struct channel_in_use *pciu; epicsMutexMustLock ( client->chanListLock ); - pciu = ( struct channel_in_use * ) + pciu = ( struct channel_in_use * ) ellGet ( & client->chanPendingUpdateARList ); while ( pciu ) { if ( pciu->state == rsrvCS_pendConnectRespUpdatePendAR ) { @@ -1531,14 +1534,14 @@ static void sendAllUpdateAS ( struct client *client ) } pciu->state = rsrvCS_inService; ellAdd ( & client->chanList, & pciu->node ); - pciu = ( struct channel_in_use * ) + pciu = ( struct channel_in_use * ) ellGet ( & client->chanPendingUpdateARList ); } epicsMutexUnlock( client->chanListLock ); } -/* +/* * rsrv_extra_labor() * (called by the CA server event task via the extra labor interface) */ @@ -1562,8 +1565,8 @@ static void putNotifyErrorReply ( struct client *client, caHdrLargeArray *mp, in * the cid field abused to contain status * during put cb replies */ - status = cas_copy_in_header ( client, CA_PROTO_WRITE_NOTIFY, - 0u, mp->m_dataType, mp->m_count, statusCA, + status = cas_copy_in_header ( client, CA_PROTO_WRITE_NOTIFY, + 0u, mp->m_dataType, mp->m_count, statusCA, mp->m_available, 0 ); if ( status != ECA_NORMAL ) { SEND_UNLOCK ( client ); @@ -1578,28 +1581,28 @@ static void putNotifyErrorReply ( struct client *client, caHdrLargeArray *mp, in void initializePutNotifyFreeList (void) { if ( ! rsrvPutNotifyFreeList ) { - freeListInitPvt ( &rsrvPutNotifyFreeList, + freeListInitPvt ( &rsrvPutNotifyFreeList, sizeof(struct rsrv_put_notify), 512 ); assert ( rsrvPutNotifyFreeList ); } } -static struct rsrv_put_notify * +static struct rsrv_put_notify * rsrvAllocPutNotify ( struct channel_in_use * pciu ) { struct rsrv_put_notify *pNotify; - + if ( rsrvPutNotifyFreeList ) { pNotify = (RSRVPUTNOTIFY *) freeListCalloc ( rsrvPutNotifyFreeList ); if ( pNotify ) { - pNotify->dbPutNotify.pbuffer = + pNotify->dbPutNotify.pbuffer = &pNotify->dbrScalarValue; - pNotify->valueSize = + pNotify->valueSize = sizeof (pNotify->dbrScalarValue); pNotify->dbPutNotify.usrPvt = pciu; - pNotify->dbPutNotify.paddr = &pciu->addr; - pNotify->dbPutNotify.userCallback = + pNotify->dbPutNotify.chan = pciu->dbch; + pNotify->dbPutNotify.userCallback = write_notify_call_back; } } @@ -1609,18 +1612,18 @@ static struct rsrv_put_notify * return pNotify; } -static int rsrvExpandPutNotify ( +static int rsrvExpandPutNotify ( struct rsrv_put_notify * pNotify, unsigned sizeNeeded ) { int booleanStatus; - + if ( sizeNeeded > pNotify->valueSize ) { /* - * try to use the union embeded in the free list - * item, but allocate a random sized block if they + * try to use the union embeded in the free list + * item, but allocate a random sized block if they * writing a vector. */ - if ( pNotify->valueSize > + if ( pNotify->valueSize > sizeof (pNotify->dbrScalarValue) ) { free ( pNotify->dbPutNotify.pbuffer ); } @@ -1633,9 +1636,9 @@ static int rsrvExpandPutNotify ( /* * revert back to the embedded union */ - pNotify->dbPutNotify.pbuffer = + pNotify->dbPutNotify.pbuffer = &pNotify->dbrScalarValue; - pNotify->valueSize = + pNotify->valueSize = sizeof (pNotify->dbrScalarValue); booleanStatus = FALSE; } @@ -1643,7 +1646,7 @@ static int rsrvExpandPutNotify ( else { booleanStatus = TRUE; } - + return booleanStatus; } @@ -1651,7 +1654,7 @@ unsigned rsrvSizeOfPutNotify ( struct rsrv_put_notify *pNotify ) { unsigned size = sizeof ( *pNotify ); if ( pNotify ) { - if ( pNotify->valueSize > + if ( pNotify->valueSize > sizeof ( pNotify->dbrScalarValue ) ) { size += pNotify->valueSize; } @@ -1659,7 +1662,7 @@ unsigned rsrvSizeOfPutNotify ( struct rsrv_put_notify *pNotify ) return size; } -void rsrvFreePutNotify ( client *pClient, +void rsrvFreePutNotify ( client *pClient, struct rsrv_put_notify *pNotify ) { if ( pNotify ) { @@ -1671,16 +1674,16 @@ void rsrvFreePutNotify ( client *pClient, epicsMutexUnlock ( pClient->putNotifyLock ); /* - * if any possiblity that the put notify is + * if any possiblity that the put notify is * outstanding then cancel it */ if ( busyTmp ) { dbNotifyCancel ( &pNotify->dbPutNotify ); - } + } epicsMutexMustLock ( pClient->putNotifyLock ); if ( pNotify->onExtraLaborQueue ) { - ellDelete ( &pClient->putNotifyQue, + ellDelete ( &pClient->putNotifyQue, &pNotify->node ); } busyTmp = pNotify->busy; @@ -1692,7 +1695,7 @@ void rsrvFreePutNotify ( client *pClient, asTrapWriteAfter ( asWritePvtTmp ); } - if ( pNotify->valueSize > + if ( pNotify->valueSize > sizeof(pNotify->dbrScalarValue) ) { free ( pNotify->dbPutNotify.pbuffer ); } @@ -1703,7 +1706,7 @@ void rsrvFreePutNotify ( client *pClient, /* * write_notify_action() */ -static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, +static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { unsigned size; @@ -1732,7 +1735,7 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, if ( pciu->pPutNotify ) { /* - * serialize concurrent put notifies + * serialize concurrent put notifies */ epicsMutexMustLock(client->putNotifyLock); while(pciu->pPutNotify->busy){ @@ -1757,7 +1760,7 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, busyTmp = pciu->pPutNotify->busy; if ( busyTmp ) { if ( pciu->pPutNotify->onExtraLaborQueue ) { - ellDelete ( &client->putNotifyQue, + ellDelete ( &client->putNotifyQue, &pciu->pPutNotify->node ); } pciu->pPutNotify->busy = FALSE; @@ -1765,9 +1768,9 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, pciu->pPutNotify->asWritePvt = 0; } epicsMutexUnlock(client->putNotifyLock); - + if ( busyTmp ) { - log_header("put call back time out", client, + log_header("put call back time out", client, &pciu->pPutNotify->msg, pciu->pPutNotify->dbPutNotify.pbuffer, 0); asTrapWriteAfter ( asWritePvtTmp ); putNotifyErrorReply (client, &pciu->pPutNotify->msg, ECA_PUTCBINPROG); @@ -1784,15 +1787,15 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, * send error and go to next request * if there isnt enough memory left */ - log_header ( "no memory to initiate put notify", + log_header ( "no memory to initiate put notify", client, mp, pPayload, 0 ); putNotifyErrorReply (client, mp, ECA_ALLOCMEM); return RSRV_ERROR; } } - + if ( ! rsrvExpandPutNotify ( pciu->pPutNotify, size ) ) { - log_header ( "no memory to initiate vector put notify", + log_header ( "no memory to initiate vector put notify", client, mp, pPayload, 0 ); putNotifyErrorReply ( client, mp, ECA_ALLOCMEM ); return RSRV_ERROR; @@ -1803,8 +1806,8 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, pciu->pPutNotify->msg = *mp; pciu->pPutNotify->dbPutNotify.nRequest = mp->m_count; - status = caNetConvert ( - mp->m_dataType, pPayload, pciu->pPutNotify->dbPutNotify.pbuffer, + status = caNetConvert ( + mp->m_dataType, pPayload, pciu->pPutNotify->dbPutNotify.pbuffer, FALSE /* net -> host format */, mp->m_count ); if ( status != ECA_NORMAL ) { log_header ("invalid data type", client, mp, pPayload, 0); @@ -1819,11 +1822,11 @@ static int write_notify_action ( caHdrLargeArray *mp, void *pPayload, return RSRV_OK; } - pciu->pPutNotify->asWritePvt = asTrapWriteBefore ( + pciu->pPutNotify->asWritePvt = asTrapWriteBefore ( pciu->asClientPVT, pciu->client->pUserName ? pciu->client->pUserName : "", pciu->client->pHostName ? pciu->client->pHostName : "", - (void *) &pciu->addr ); + pciu->dbch ); dbPutNotify(&pciu->pPutNotify->dbPutNotify); @@ -1849,10 +1852,10 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client } /* - * stop further use of server if memory becomes scarse + * stop further use of server if memory becomes scarce */ spaceAvailOnFreeList = freeListItemsAvail ( rsrvEventFreeList ) > 0; - if ( osiSufficentSpaceInPool(sizeof(*pevext)) || spaceAvailOnFreeList ) { + if ( osiSufficentSpaceInPool(sizeof(*pevext)) || spaceAvailOnFreeList ) { pevext = (struct event_ext *) freeListCalloc (rsrvEventFreeList); } else { @@ -1860,14 +1863,14 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client } if (!pevext) { - log_header ("no memory to add subscription", + log_header ("no memory to add subscription", client, mp, pPayload, 0); SEND_LOCK(client); send_err( mp, - ECA_ALLOCMEM, - client, - RECORD_NAME(&pciu->addr)); + ECA_ALLOCMEM, + client, + RECORD_NAME(pciu->dbch)); SEND_UNLOCK(client); return RSRV_ERROR; } @@ -1881,15 +1884,15 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client ellAdd( &pciu->eventq, &pevext->node); epicsMutexUnlock(client->eventqLock); - pevext->pdbev = db_add_event (client->evuser, &pciu->addr, + pevext->pdbev = db_add_event (client->evuser, pciu->dbch, read_reply, pevext, pevext->mask); if (pevext->pdbev == NULL) { - log_header ("no memory to add subscription to db", + log_header ("no memory to add subscription to db", client, mp, pPayload, 0); SEND_LOCK(client); - send_err (mp, ECA_ALLOCMEM, client, - "subscription install into record %s failed", - RECORD_NAME(&pciu->addr)); + send_err (mp, ECA_ALLOCMEM, client, + "subscription install into record %s failed", + RECORD_NAME(pciu->dbch)); SEND_UNLOCK(client); return RSRV_ERROR; } @@ -1903,7 +1906,7 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client * of the socket would block. This prevents * a application program initiated deadlock. * - * However when I am reconnecting I reissue + * However when I am reconnecting I reissue * the monitors and I could get deadlocked. * The client is blocked sending and the server * task for the client is blocked sending in @@ -1914,7 +1917,7 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client * post_single_event() below instead of calling * read_reply() in this module. This is a complete * fix since a monitor setup is the only request - * soliciting a reply in the client which is + * soliciting a reply in the client which is * issued from inside of service.c (from inside * of the part of the ca client which services * messages sent by the server). @@ -1940,13 +1943,13 @@ static int event_add_action (caHdrLargeArray *mp, void *pPayload, struct client /* * clear_channel_reply() */ -static int clear_channel_reply ( caHdrLargeArray *mp, +static int clear_channel_reply ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { struct event_ext *pevext; struct channel_in_use *pciu; int status; - + /* * * Verify the channel @@ -1957,43 +1960,43 @@ static int clear_channel_reply ( caHdrLargeArray *mp, logBadId ( client, mp, pPayload ); return RSRV_ERROR; } - + rsrvFreePutNotify ( client, pciu->pPutNotify ); - + while (TRUE){ epicsMutexMustLock(client->eventqLock); pevext = (struct event_ext *) ellGet(&pciu->eventq); epicsMutexUnlock(client->eventqLock); - + if(!pevext){ break; } - + if (pevext->pdbev) { db_cancel_event (pevext->pdbev); } freeListFree(rsrvEventFreeList, pevext); } - + db_flush_extra_labor_event ( client->evuser ); - + /* * send delete confirmed message */ SEND_LOCK(client); - status = cas_copy_in_header ( client, CA_PROTO_CLEAR_CHANNEL, - 0u, mp->m_dataType, mp->m_count, mp->m_cid, + status = cas_copy_in_header ( client, CA_PROTO_CLEAR_CHANNEL, + 0u, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, NULL ); if ( status != ECA_NORMAL ) { SEND_UNLOCK(client); return RSRV_ERROR; } - + cas_commit_msg ( client, 0u ); SEND_UNLOCK(client); - + epicsMutexMustLock ( client->chanListLock ); - if ( pciu->state == rsrvCS_inService || + if ( pciu->state == rsrvCS_inService || pciu->state == rsrvCS_pendConnectResp ) { ellDelete ( &client->chanList, &pciu->node ); } @@ -2004,22 +2007,22 @@ static int clear_channel_reply ( caHdrLargeArray *mp, else { epicsMutexUnlock( client->chanListLock ); SEND_LOCK(client); - send_err(mp, ECA_INTERNAL, client, + send_err(mp, ECA_INTERNAL, client, "channel was in strange state or corrupted during cleanup"); SEND_UNLOCK(client); return RSRV_ERROR; } epicsMutexUnlock( client->chanListLock ); - + /* * remove from access control list */ status = asRemoveClient(&pciu->asClientPVT); if(status != 0 && status != S_asLib_asNotActive){ - errMessage(status, RECORD_NAME(&pciu->addr)); + errMessage(status, RECORD_NAME(pciu->dbch)); return RSRV_ERROR; } - + LOCK_CLIENTQ; status = bucketRemoveItemUnsignedId (pCaBucket, &pciu->sid); if(status != S_bucket_success){ @@ -2031,11 +2034,12 @@ static int clear_channel_reply ( caHdrLargeArray *mp, rsrvChannelCount--; UNLOCK_CLIENTQ; + dbChannelDelete(pciu->dbch); freeListFree(rsrvChanFreeList, pciu); - + return RSRV_OK; } - + /* * * event_cancel_reply() @@ -2049,7 +2053,7 @@ static int event_cancel_reply ( caHdrLargeArray *mp, void *pPayload, struct clie struct channel_in_use *pciu; struct event_ext *pevext; int status; - + /* * * Verify the channel @@ -2060,7 +2064,7 @@ static int event_cancel_reply ( caHdrLargeArray *mp, void *pPayload, struct clie logBadId ( client, mp, pPayload ); return RSRV_ERROR; } - + /* * search events on this channel for a match * (there are usually very few monitors per channel) @@ -2068,38 +2072,38 @@ static int event_cancel_reply ( caHdrLargeArray *mp, void *pPayload, struct clie epicsMutexMustLock(client->eventqLock); for (pevext = (struct event_ext *) ellFirst(&pciu->eventq); pevext; pevext = (struct event_ext *) ellNext(&pevext->node)){ - + if (pevext->msg.m_available == mp->m_available) { ellDelete(&pciu->eventq, &pevext->node); break; } } epicsMutexUnlock(client->eventqLock); - + /* - * Not Found- return an exception event + * Not Found- return an exception event */ if(!pevext){ SEND_LOCK(client); - send_err(mp, ECA_BADMONID, client, RECORD_NAME(&pciu->addr)); + send_err(mp, ECA_BADMONID, client, RECORD_NAME(pciu->dbch)); SEND_UNLOCK(client); return RSRV_ERROR; } - + /* * cancel monitor activity in progress */ if (pevext->pdbev) { db_cancel_event (pevext->pdbev); } - + /* * send delete confirmed message */ SEND_LOCK(client); - status = cas_copy_in_header ( client, pevext->msg.m_cmmd, - 0u, pevext->msg.m_dataType, pevext->msg.m_count, pevext->msg.m_cid, + status = cas_copy_in_header ( client, pevext->msg.m_cmmd, + 0u, pevext->msg.m_dataType, pevext->msg.m_count, pevext->msg.m_cid, pevext->msg.m_available, NULL ); if ( status != ECA_NORMAL ) { SEND_UNLOCK(client); @@ -2107,7 +2111,7 @@ static int event_cancel_reply ( caHdrLargeArray *mp, void *pPayload, struct clie } cas_commit_msg ( client, 0 ); SEND_UNLOCK(client); - + freeListFree (rsrvEventFreeList, pevext); return RSRV_OK; @@ -2120,8 +2124,8 @@ static int read_sync_reply ( caHdrLargeArray *mp, void *pPayload, struct client { int status; SEND_LOCK(client); - status = cas_copy_in_header ( client, mp->m_cmmd, - 0u, mp->m_dataType, mp->m_count, mp->m_cid, + status = cas_copy_in_header ( client, mp->m_cmmd, + 0u, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, NULL ); if ( status != ECA_NORMAL ) { SEND_UNLOCK(client); @@ -2132,17 +2136,17 @@ static int read_sync_reply ( caHdrLargeArray *mp, void *pPayload, struct client return RSRV_OK; } -/* +/* * search_fail_reply() * - * Only when requested by the client + * Only when requested by the client * send search failed reply */ static void search_fail_reply ( caHdrLargeArray *mp, void *pPayload, struct client *client) { int status; SEND_LOCK ( client ); - status = cas_copy_in_header ( client, CA_PROTO_NOT_FOUND, + status = cas_copy_in_header ( client, CA_PROTO_NOT_FOUND, 0u, mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, NULL ); if ( status != ECA_NORMAL ) { SEND_UNLOCK ( client ); @@ -2180,16 +2184,16 @@ int rsrv_version_reply ( struct client *client ) SEND_LOCK ( client ); /* * sequence number is specified zero when we copy in the - * header because we dont know it until we receive a datagram + * header because we dont know it until we receive a datagram * from the client */ - status = cas_copy_in_header ( client, CA_PROTO_VERSION, - 0, 0, CA_MINOR_PROTOCOL_REVISION, + status = cas_copy_in_header ( client, CA_PROTO_VERSION, + 0, 0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 ); if ( status != ECA_NORMAL ) { SEND_UNLOCK ( client ); return RSRV_ERROR; - } + } cas_commit_msg ( client, 0 ); SEND_UNLOCK ( client ); return RSRV_OK; @@ -2200,7 +2204,6 @@ int rsrv_version_reply ( struct client *client ) */ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client *client ) { - struct dbAddr tmp_addr; ca_uint16_t *pMinorVersion; char *pName = (char *) pPayload; int status; @@ -2215,35 +2218,34 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client * check the sanity of the message */ if (mp->m_postsize<=1) { - log_header ("empty PV name in UDP search request?", + log_header ("empty PV name in UDP search request?", client, mp, pPayload, 0); return RSRV_OK; } pName[mp->m_postsize-1] = '\0'; - + /* Exit quickly if channel not on this node */ - status = db_name_to_addr (pName, &tmp_addr); - if (status) { + if (dbChannelTest(pName)) { DLOG ( 2, ( "CAS: Lookup for channel \"%s\" failed\n", pPayLoad ) ); if (mp->m_dataType == DOREPLY) search_fail_reply ( mp, pPayload, client ); return RSRV_OK; } - + /* - * stop further use of server if memory becomes scarse + * stop further use of server if memory becomes scarce */ spaceAvailOnFreeList = freeListItemsAvail ( rsrvChanFreeList ) > 0 && freeListItemsAvail ( rsrvEventFreeList ) > reasonableMonitorSpace; - spaceNeeded = sizeof (struct channel_in_use) + + spaceNeeded = sizeof (struct channel_in_use) + reasonableMonitorSpace * sizeof (struct event_ext); - if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) { + if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) { SEND_LOCK(client); send_err ( mp, ECA_ALLOCMEM, client, "Server memory exhausted" ); SEND_UNLOCK(client); return RSRV_OK; } - + /* * starting with V4.4 the count field is used (abused) * to store the minor version number of the client. @@ -2259,49 +2261,58 @@ static int search_reply_udp ( caHdrLargeArray *mp, void *pPayload, struct client type = ca_server_port; } else { + struct dbChannel *dbch; struct channel_in_use *pchannel; - - pchannel = casCreateChannel ( client, &tmp_addr, mp->m_cid ); + + dbch = dbChannel_create(pName); + if (!dbch) { + DLOG ( 2, ( "CAS: dbChannel Test of \"%s\" OK but Create failed\n", pName ) ); + if (mp->m_dataType == DOREPLY) + search_fail_reply ( mp, pPayload, client ); + return RSRV_OK; + } + pchannel = casCreateChannel ( client, dbch, mp->m_cid ); if (!pchannel) { SEND_LOCK(client); - send_err ( mp, ECA_ALLOCMEM, client, - RECORD_NAME ( &tmp_addr ) ); + send_err ( mp, ECA_ALLOCMEM, client, + RECORD_NAME ( dbch ) ); SEND_UNLOCK ( client ); + dbChannelDelete(dbch); return RSRV_OK; } sid = pchannel->sid; - if ( tmp_addr.no_elements < 0 ) { + if ( dbChannelElements(dbch) < 0 ) { count = 0; } - else if ( tmp_addr.no_elements > 0xffff ) { + else if ( dbChannelElements(dbch) > 0xffff ) { count = 0xfffe; } else { - count = (ca_uint16_t) tmp_addr.no_elements; + count = (ca_uint16_t) dbChannelElements(dbch); } - type = (ca_uint16_t) tmp_addr.dbr_field_type; + type = (ca_uint16_t) dbChannelExportType(dbch); } - + SEND_LOCK ( client ); - status = cas_copy_in_header ( client, CA_PROTO_SEARCH, - sizeof(*pMinorVersion), type, count, - sid, mp->m_available, + status = cas_copy_in_header ( client, CA_PROTO_SEARCH, + sizeof(*pMinorVersion), type, count, + sid, mp->m_available, ( void * ) &pMinorVersion ); if ( status != ECA_NORMAL ) { SEND_UNLOCK ( client ); return RSRV_ERROR; } - + /* * Starting with CA V4.1 the minor version number * is appended to the end of each search reply. - * This value is ignored by earlier clients. + * This value is ignored by earlier clients. */ *pMinorVersion = htons ( CA_MINOR_PROTOCOL_REVISION ); - + cas_commit_msg ( client, sizeof ( *pMinorVersion ) ); SEND_UNLOCK ( client ); - + return RSRV_OK; } @@ -2370,7 +2381,7 @@ typedef int (*pProtoStubTCP) (caHdrLargeArray *mp, void *pPayload, struct client /* * TCP protocol jump table */ -static const pProtoStubTCP tcpJumpTable[] = +static const pProtoStubTCP tcpJumpTable[] = { tcp_version_action, event_add_action, @@ -2406,7 +2417,7 @@ static const pProtoStubTCP tcpJumpTable[] = * UDP protocol jump table */ typedef int (*pProtoStubUDP) (caHdrLargeArray *mp, void *pPayload, struct client *client); -static const pProtoStubUDP udpJumpTable[] = +static const pProtoStubUDP udpJumpTable[] = { udp_version_action, bad_udp_cmd_action, @@ -2447,7 +2458,7 @@ int camessage ( struct client *client ) unsigned msgsize; unsigned bytes_left; int status = RSRV_ERROR; - + if ( ! pCaBucket ) { pCaBucket = bucketCreate(CAS_HASH_TABLE_SIZE); if(!pCaBucket){ @@ -2467,11 +2478,11 @@ int camessage ( struct client *client ) client->recvBytesToDrain = 0u; } } - + DLOG ( 2, ( "CAS: Parsing %d(decimal) bytes\n", recv->cnt ) ); - + while ( 1 ) - { + { caHdrLargeArray msg; caHdr *mp; void *pBody; @@ -2482,7 +2493,7 @@ int camessage ( struct client *client ) status = RSRV_OK; break; } - + mp = (caHdr *) &client->recv.buf[client->recv.stk]; msg.m_cmmd = ntohs ( mp->m_cmmd ); msg.m_postsize = ntohs ( mp->m_postsize ); @@ -2508,13 +2519,13 @@ int camessage ( struct client *client ) } /* - * disconnect clients that dont send 8 byte + * disconnect clients that dont send 8 byte * aligned payloads */ if ( msgsize & 0x7 ) { - send_err ( &msg, ECA_INTERNAL, client, + send_err ( &msg, ECA_INTERNAL, client, "CAS: Missaligned protocol rejected" ); - log_header ( "CAS: Missaligned protocol rejected", + log_header ( "CAS: Missaligned protocol rejected", client, &msg, 0, nmsg ); status = RSRV_ERROR; break; @@ -2529,10 +2540,10 @@ int camessage ( struct client *client ) if ( msgsize > client->recv.maxstk ) { casExpandRecvBuffer ( client, msgsize ); if ( msgsize > client->recv.maxstk ) { - send_err ( &msg, ECA_TOLARGE, client, + send_err ( &msg, ECA_TOLARGE, client, "CAS: Server unable to load large request message. Max bytes=%lu", rsrvSizeofLargeBufTCP ); - log_header ( "CAS: server unable to load large request message", + log_header ( "CAS: server unable to load large request message", client, &msg, 0, nmsg ); assert ( client->recv.cnt <= client->recv.maxstk ); assert ( msgsize >= bytes_left ); @@ -2550,12 +2561,12 @@ int camessage ( struct client *client ) status = RSRV_OK; break; } - + nmsg++; - + if ( CASDEBUG > 2 ) log_header (NULL, client, &msg, pBody, nmsg); - + if ( client == prsrv_cast_client ) { if ( msg.m_cmmd < NELEMENTS ( udpJumpTable ) ) { status = ( *udpJumpTable[msg.m_cmmd] )( &msg, pBody, client ); @@ -2581,10 +2592,10 @@ int camessage ( struct client *client ) return bad_tcp_cmd_action ( &msg, pBody, client ); } } - + client->recv.stk += msgsize; } - + return status; } @@ -2595,8 +2606,8 @@ int rsrvCheckPut (const struct channel_in_use *pciu) { /* * SPC_NOMOD fields are always unwritable - */ - if (pciu->addr.special==SPC_NOMOD) { + */ + if (dbChannelSpecial(pciu->dbch) == SPC_NOMOD) { return 0; } else { diff --git a/src/ioc/rsrv/caservertask.c b/src/ioc/rsrv/caservertask.c index 21bcba9f4..5554d9ad7 100644 --- a/src/ioc/rsrv/caservertask.c +++ b/src/ioc/rsrv/caservertask.c @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -33,7 +33,6 @@ #include "freeList.h" #include "errlog.h" #include "db_field_log.h" -#include "dbAddr.h" #include "dbEvent.h" #include "dbCommon.h" #include "epicsStdioRedirect.h" @@ -73,22 +72,22 @@ static void req_server (void *pParm) epicsSignalInstallSigPipeIgnore (); taskwdInsert ( epicsThreadGetIdSelf (), NULL, NULL ); - + rsrvCurrentClient = epicsThreadPrivateCreate (); if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { - ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, + ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } else { - ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, + ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) { epicsSocketDestroy ( IOC_sock ); } - + /* * Open the socket. Use ARPA Internet address format and stream * sockets. Format described in . @@ -103,7 +102,7 @@ static void req_server (void *pParm) /* Zero the sock_addr structure */ memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) ); serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); + serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); serverAddr.sin_port = htons ( ca_server_port ); /* get server's Internet address */ @@ -116,12 +115,12 @@ static void req_server (void *pParm) * work correctly) */ serverAddr.sin_port = ntohs (0); - status = bind ( IOC_sock, + status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); } if ( status < 0 ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf ( "CAS: Socket bind error was \"%s\"\n", sockErrBuf ); @@ -134,13 +133,13 @@ static void req_server (void *pParm) } addrSize = ( osiSocklen_t ) sizeof ( serverAddr ); - status = getsockname ( IOC_sock, + status = getsockname ( IOC_sock, (struct sockaddr *)&serverAddr, &addrSize); if ( status ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( "CAS: getsockname() error %s\n", + errlogPrintf ( "CAS: getsockname() error %s\n", sockErrBuf ); epicsThreadSuspendSelf (); } @@ -149,7 +148,7 @@ static void req_server (void *pParm) if ( portChange ) { errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n"); - errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", + errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", ca_server_port ); errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n"); errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" ); @@ -192,13 +191,13 @@ static void req_server (void *pParm) clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen ); if ( clientSock == INVALID_SOCKET ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf("CAS: Client accept error was \"%s\"\n", sockErrBuf ); epicsThreadSleep(15.0); continue; - } + } else { epicsThreadId id; struct client *pClient; @@ -282,14 +281,14 @@ int rsrv_init (void) castcp_ctl = ctlPause; /* - * go down two levels so that we are below + * go down two levels so that we are below * the TCP and event threads started on behalf * of individual clients */ - tbs = epicsThreadHighestPriorityLevelBelow ( + tbs = epicsThreadHighestPriorityLevelBelow ( epicsThreadPriorityCAServerLow, &priorityOfConnectDaemon ); if ( tbs == epicsThreadBooleanStatusSuccess ) { - tbs = epicsThreadHighestPriorityLevelBelow ( + tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfConnectDaemon, &priorityOfConnectDaemon ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfConnectDaemon = epicsThreadPriorityCAServerLow; @@ -330,7 +329,7 @@ int rsrv_pause (void) return RSRV_OK; } -static unsigned countChanListBytes ( +static unsigned countChanListBytes ( struct client *client, ELLLIST * pList ) { struct channel_in_use * pciu; @@ -349,7 +348,7 @@ static unsigned countChanListBytes ( return bytes_reserved; } -static void showChanList ( +static void showChanList ( struct client * client, ELLLIST * pList ) { unsigned i = 0u; @@ -357,8 +356,8 @@ static void showChanList ( epicsMutexMustLock ( client->chanListLock ); pciu = (struct channel_in_use *) pList->node.next; while ( pciu ){ - printf( "\t%s(%d%c%c)", - pciu->addr.precord->name, + printf( "\t%s(%d%c%c)", + dbChannelRecord(pciu->dbch)->name, ellCount ( &pciu->eventq ), asCheckGet ( pciu->asClientPVT ) ? 'r': '-', rsrvCheckPut ( pciu ) ? 'w': '-' ); @@ -398,28 +397,28 @@ static void log_one_client (struct client *client, unsigned level) send_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_send); recv_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_recv); - printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n", + printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n", pproto, clientHostName, client->pHostName ? client->pHostName : "", client->pUserName ? client->pUserName : "", CA_MAJOR_PROTOCOL_REVISION, client->minor_version_number, - ellCount(&client->chanList) + + ellCount(&client->chanList) + ellCount(&client->chanPendingUpdateARList), client->priority ); if ( level >= 1 ) { - printf ("\tTask Id=%p, Socket FD=%d\n", - (void *) client->tid, client->sock); - printf( - "\tSecs since last send %6.2f, Secs since last receive %6.2f\n", + printf ("\tTask Id=%p, Socket FD=%d\n", + (void *) client->tid, client->sock); + printf( + "\tSecs since last send %6.2f, Secs since last receive %6.2f\n", send_delay, recv_delay); - printf( - "\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n", + printf( + "\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n", client->recv.cnt - client->recv.stk, client->send.stk ); - printf( - "\tState=%s%s%s\n", + printf( + "\tState=%s%s%s\n", state[client->disconnect?1:0], client->send.type == mbtLargeTCP ? " jumbo-send-buf" : "", client->recv.type == mbtLargeTCP ? " jumbo-recv-buf" : ""); @@ -428,9 +427,9 @@ static void log_one_client (struct client *client, unsigned level) if ( level >= 2u ) { unsigned bytes_reserved = 0; bytes_reserved += sizeof(struct client); - bytes_reserved += countChanListBytes ( + bytes_reserved += countChanListBytes ( client, & client->chanList ); - bytes_reserved += countChanListBytes ( + bytes_reserved += countChanListBytes ( client, & client->chanPendingUpdateARList ); printf( "\t%d bytes allocated\n", bytes_reserved); showChanList ( client, & client->chanList ); @@ -485,20 +484,20 @@ void epicsShareAPI casr (unsigned level) printf( "UDP Server:\n" ); log_one_client(prsrv_cast_client, level); } - + if (level>=2u) { bytes_reserved = 0u; - bytes_reserved += sizeof (struct client) * + bytes_reserved += sizeof (struct client) * freeListItemsAvail (rsrvClientFreeList); bytes_reserved += sizeof (struct channel_in_use) * freeListItemsAvail (rsrvChanFreeList); bytes_reserved += sizeof(struct event_ext) * freeListItemsAvail (rsrvEventFreeList); - bytes_reserved += MAX_TCP * + bytes_reserved += MAX_TCP * freeListItemsAvail ( rsrvSmallBufFreeListTCP ); - bytes_reserved += rsrvSizeofLargeBufTCP * + bytes_reserved += rsrvSizeofLargeBufTCP * freeListItemsAvail ( rsrvLargeBufFreeListTCP ); - bytes_reserved += rsrvSizeOfPutNotify ( 0 ) * + bytes_reserved += rsrvSizeOfPutNotify ( 0 ) * freeListItemsAvail ( rsrvPutNotifyFreeList ); printf( "There are currently %u bytes on the server's free list\n", (unsigned int) bytes_reserved); @@ -525,7 +524,7 @@ void epicsShareAPI casr (unsigned level) } } -/* +/* * destroy_client () */ void destroy_client ( struct client *client ) @@ -533,7 +532,7 @@ void destroy_client ( struct client *client ) if ( ! client ) { return; } - + if ( client->tid != 0 ) { taskwdRemove ( client->tid ); } @@ -603,12 +602,12 @@ void destroy_client ( struct client *client ) if ( client->pHostName ) { free ( client->pHostName ); - } + } freeListFree ( rsrvClientFreeList, client ); } -static void destroyAllChannels ( +static void destroyAllChannels ( struct client * client, ELLLIST * pList ) { if ( !client->chanListLock || !client->eventqLock ) { @@ -651,7 +650,7 @@ static void destroyAllChannels ( rsrvChannelCount--; UNLOCK_CLIENTQ; if ( status != S_bucket_success ) { - errPrintf ( status, __FILE__, __LINE__, + errPrintf ( status, __FILE__, __LINE__, "Bad id=%d at close", pciu->sid); } status = asRemoveClient(&pciu->asClientPVT); @@ -691,7 +690,7 @@ void destroy_tcp_client ( struct client *client ) if ( client->evuser ) { db_close_events (client->evuser); } - + destroy_client ( client ); } @@ -710,7 +709,7 @@ struct client * create_client ( SOCKET sock, int proto ) spaceAvailOnFreeList = freeListItemsAvail ( rsrvClientFreeList ) > 0 && freeListItemsAvail ( rsrvSmallBufFreeListTCP ) > 0; spaceNeeded = sizeof (struct client) + MAX_TCP; - if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) { + if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) { epicsSocketDestroy ( sock ); epicsPrintf ("CAS: no space in pool for a new client (below max block thresh)\n"); return NULL; @@ -721,7 +720,7 @@ struct client * create_client ( SOCKET sock, int proto ) epicsSocketDestroy ( sock ); epicsPrintf ("CAS: no space in pool for a new client (alloc failed)\n"); return NULL; - } + } client->sock = sock; client->proto = proto; @@ -737,8 +736,8 @@ struct client * create_client ( SOCKET sock, int proto ) return NULL; } - client->pUserName = NULL; - client->pHostName = NULL; + client->pUserName = NULL; + client->pHostName = NULL; ellInit ( & client->chanList ); ellInit ( & client->chanPendingUpdateARList ); ellInit ( & client->putNotifyQue ); @@ -776,7 +775,7 @@ struct client * create_client ( SOCKET sock, int proto ) epicsTimeGetCurrent ( &client->time_at_last_recv ); client->minor_version_number = CA_UKN_MINOR_VERSION; client->recvBytesToDrain = 0u; - + return client; } @@ -791,10 +790,10 @@ void casAttachThreadToClient ( struct client *pClient ) void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size ) { - if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP + if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP && size <= rsrvSizeofLargeBufTCP ) { int spaceAvailOnFreeList = freeListItemsAvail ( rsrvLargeBufFreeListTCP ) > 0; - if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { + if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP ); if ( pNewBuf ) { memcpy ( pNewBuf, pClient->send.buf, pClient->send.stk ); @@ -812,7 +811,7 @@ void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size ) if ( pClient->recv.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP && size <= rsrvSizeofLargeBufTCP) { int spaceAvailOnFreeList = freeListItemsAvail ( rsrvLargeBufFreeListTCP ) > 0; - if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { + if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP ); if ( pNewBuf ) { assert ( pClient->recv.cnt >= pClient->recv.stk ); @@ -849,26 +848,26 @@ struct client *create_tcp_client ( SOCKET sock ) * see TCP(4P) this seems to make unsolicited single events much * faster. I take care of queue up as load increases. */ - status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY, + status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY, (char *) &intTrue, sizeof (intTrue) ); if (status < 0) { errlogPrintf ( "CAS: TCP_NODELAY option set failed\n" ); destroy_client ( client ); return NULL; } - - /* + + /* * turn on KEEPALIVE so if the client crashes * this task will find out and exit */ - status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE, + status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &intTrue, sizeof (intTrue) ); if ( status < 0 ) { errlogPrintf ( "CAS: SO_KEEPALIVE option set failed\n" ); destroy_client ( client ); return NULL; } - + /* * some concern that vxWorks will run out of mBuf's * if this change is made @@ -876,8 +875,8 @@ struct client *create_tcp_client ( SOCKET sock ) * joh 11-10-98 */ #if 0 - /* - * set TCP buffer sizes to be synergistic + /* + * set TCP buffer sizes to be synergistic * with CA internal buffering */ i = MAX_MSG_SIZE; @@ -895,7 +894,7 @@ struct client *create_tcp_client ( SOCKET sock ) return NULL; } #endif - + addrSize = sizeof ( client->addr ); status = getpeername ( sock, (struct sockaddr *)&client->addr, &addrSize ); @@ -928,8 +927,8 @@ struct client *create_tcp_client ( SOCKET sock ) } } - status = db_start_events ( client->evuser, "CAS-event", - NULL, NULL, priorityOfEvents ); + status = db_start_events ( client->evuser, "CAS-event", + NULL, NULL, priorityOfEvents ); if ( status != DB_EVENT_OK ) { errlogPrintf ( "CAS: unable to start the event facility\n" ); destroy_tcp_client ( client ); diff --git a/src/ioc/rsrv/server.h b/src/ioc/rsrv/server.h index 6d1dfc38f..b1a6c7b24 100644 --- a/src/ioc/rsrv/server.h +++ b/src/ioc/rsrv/server.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -25,7 +25,7 @@ #include "epicsEvent.h" #include "bucketLib.h" #include "asLib.h" -#include "dbAddr.h" +#include "dbChannel.h" #include "dbNotify.h" #define CA_MINOR_PROTOCOL_REVISION 13 #include "caProto.h" @@ -64,7 +64,7 @@ struct message_buffer { char *buf; unsigned stk; unsigned maxstk; - unsigned cnt; + unsigned cnt; enum messageBufferType type; }; @@ -98,16 +98,16 @@ typedef struct client { char disconnect; /* disconnect detected */ } client; -enum rsrvChanState { +enum rsrvChanState { rsrvCS_invalid, rsrvCS_pendConnectResp, rsrvCS_inService, rsrvCS_pendConnectRespUpdatePendAR, - rsrvCS_inServiceUpdatePendAR + rsrvCS_inServiceUpdatePendAR }; /* - * per channel structure + * per channel structure * (stored in chanList or chanPendingUpdateARList off of a client block) */ struct channel_in_use { @@ -118,7 +118,7 @@ struct channel_in_use { const unsigned cid; /* client id */ const unsigned sid; /* server id */ epicsTimeStamp time_at_creation; /* for UDP timeout */ - struct dbAddr addr; + struct dbChannel *dbch; ASCLIENTPVT asClientPVT; enum rsrvChanState state; }; @@ -156,7 +156,7 @@ enum ctl {ctlRun, ctlPause, ctlExit}; # define DLOG(LEVEL,ARGSINPAREN) \ if (CASDEBUG > LEVEL) errlogPrintf ARGSINPAREN #else -# define DLOG(LEVEL,ARGSINPAREN) +# define DLOG(LEVEL,ARGSINPAREN) #endif GLBLTYPE int CASDEBUG; @@ -168,13 +168,13 @@ GLBLTYPE ELLLIST beaconAddrList; GLBLTYPE epicsMutexId clientQlock; GLBLTYPE struct client *prsrv_cast_client; GLBLTYPE BUCKET *pCaBucket; -GLBLTYPE void *rsrvClientFreeList; +GLBLTYPE void *rsrvClientFreeList; GLBLTYPE void *rsrvChanFreeList; GLBLTYPE void *rsrvEventFreeList; -GLBLTYPE void *rsrvSmallBufFreeListTCP; -GLBLTYPE void *rsrvLargeBufFreeListTCP; +GLBLTYPE void *rsrvSmallBufFreeListTCP; +GLBLTYPE void *rsrvLargeBufFreeListTCP; GLBLTYPE unsigned rsrvSizeofLargeBufTCP; -GLBLTYPE void *rsrvPutNotifyFreeList; +GLBLTYPE void *rsrvPutNotifyFreeList; GLBLTYPE unsigned rsrvChannelCount; GLBLTYPE epicsEventId casudp_startStopEvent; @@ -207,7 +207,7 @@ int camessage ( struct client *client ); void rsrv_extra_labor ( void * pArg ); int rsrvCheckPut ( const struct channel_in_use *pciu ); int rsrv_version_reply ( struct client *client ); -void rsrvFreePutNotify ( struct client *pClient, +void rsrvFreePutNotify ( struct client *pClient, struct rsrv_put_notify *pNotify ); void initializePutNotifyFreeList (void); unsigned rsrvSizeOfPutNotify ( struct rsrv_put_notify *pNotify ); @@ -221,9 +221,9 @@ void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size ); * outgoing protocol maintenance */ void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size ); -int cas_copy_in_header ( +int cas_copy_in_header ( struct client *pClient, ca_uint16_t response, ca_uint32_t payloadSize, - ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, + ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, ca_uint32_t responseSpecific, void **pPayload ); void cas_set_header_cid ( struct client *pClient, ca_uint32_t ); void cas_set_header_count (struct client *pClient, ca_uint32_t count);