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
This commit is contained in:
Michael Davidsaver
2012-04-27 13:21:41 -04:00
parent 56468b684e
commit 8bf53d3c59
22 changed files with 1206 additions and 1745 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
@@ -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)
{

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 <long> (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 <const void *> ( this ), this->addr.precord->name );
printf ("channel at %p attached to local database record %s\n",
static_cast <const void *> ( 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 );

View File

@@ -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 &notify, 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 &notify )
{
this->serviceIO.callStateNotify ( this->addr, type, count, pfl, notify );
this->serviceIO.callStateNotify ( this->dbch, type, count, pfl, notify );
}

View File

@@ -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 <int> ( type ),
int status = dbChannel_get ( dbch, static_cast <int> ( type ),
this->pStateNotifyCache, static_cast <int> ( 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 <const void *> ( 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 <void *> ( 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 );

View File

@@ -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 <int> ( type ),
ptr.get (), static_cast <int> ( count ), 0 );
status = dbChannel_get ( dbch, static_cast <int> ( type ),
ptr.get (), static_cast <long> ( 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 );
}
}

View File

@@ -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
}
}

View File

@@ -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);

View File

@@ -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 <stdlib.h>
#include <stdarg.h>
@@ -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);
}

View File

@@ -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:

View File

@@ -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 <short> ( 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 <const void *> ( 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 );

View File

@@ -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 & );

View File

@@ -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 <const void *> ( 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 <void *> ( &this->chan ) );
}
else {
@@ -161,7 +161,7 @@ void dbSubscriptionIO::show (
}
}
dbSubscriptionIO * dbSubscriptionIO::isSubscription ()
dbSubscriptionIO * dbSubscriptionIO::isSubscription ()
{
return this;
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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; i<count && *pbuffer!=0; i++) {
if(count!=1 && (i%5 == 0)) printf("\n");
printf("%s ",pbuffer);
pbuffer += MAX_STRING_SIZE;
}
break;
case (DBR_SHORT):
case (DBR_ENUM):
{
short *pvalue = (short *)pbuffer;
for (i = 0; i < count; i++,pvalue++){
if(count!=1 && (i%10 == 0)) printf("\n");
printf("%d ",*(short *)pvalue);
}
break;
}
case (DBR_FLOAT):
{
float *pvalue = (float *)pbuffer;
for (i = 0; i < count; i++,pvalue++){
if(count!=1 && (i%10 == 0)) printf("\n");
printf("%6.4f ",*(float *)pvalue);
}
break;
}
case (DBR_CHAR):
{
int value;
if (type <= DBF_STRING || type == DBF_ENUM)
return 0;
for (i = 0; i < count; i++,pbuffer++){
if(count!=1 && (i%10 == 0)) printf("\n");
value = *(unsigned char *)pbuffer;
printf("%d ",value);
}
break;
}
case (DBR_LONG):
{
long *pvalue = (long *)pbuffer;
for (i = 0; i < count; i++,pvalue++){
if(count!=1 && (i%10 == 0)) printf("\n");
printf("%ld ", (unsigned long)*pvalue);
}
break;
}
case (DBR_DOUBLE):
{
double *pvalue = (double *)pbuffer;
for (i = 0; i < count; i++,pvalue++){
if(count!=1 && (i%10 == 0)) printf("\n");
printf("%6.4f ",(float)(*pvalue));
}
break;
}
case (DBR_STS_STRING):
case (DBR_GR_STRING):
case (DBR_CTRL_STRING):
{
struct dbr_sts_string *pvalue
= (struct dbr_sts_string *) pbuffer;
printf("%2d %2d",pvalue->status,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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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 <sys/socket.h>.
@@ -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(&current,&client->time_at_last_send);
recv_delay = epicsTimeDiffInSeconds(&current,&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 );

View File

@@ -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);