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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -44,65 +44,64 @@
|
||||
|
||||
class dbChannelIO : public cacChannel, public dbContextPrivateListOfIO {
|
||||
public:
|
||||
dbChannelIO (
|
||||
epicsMutex &, cacChannelNotify &,
|
||||
const dbAddr &, dbContext & );
|
||||
void destructor (
|
||||
dbChannelIO (
|
||||
epicsMutex &, cacChannelNotify &,
|
||||
dbChannel *, dbContext & );
|
||||
void destructor (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void destroy (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void callReadNotify (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
void callReadNotify (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
cacReadNotify & notify );
|
||||
void callStateNotify (
|
||||
unsigned type, unsigned long count,
|
||||
void callStateNotify (
|
||||
unsigned type, unsigned long count,
|
||||
const struct db_field_log * pfl, cacStateNotify & notify );
|
||||
void show (
|
||||
void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
unsigned getName (
|
||||
epicsGuard < epicsMutex > &,
|
||||
char * pBuf, unsigned bufLen ) const throw ();
|
||||
const char * pName (
|
||||
epicsGuard < epicsMutex > & ) const throw ();
|
||||
void * operator new ( size_t size,
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & ))
|
||||
protected:
|
||||
~dbChannelIO ();
|
||||
private:
|
||||
epicsMutex & mutex;
|
||||
dbContext & serviceIO;
|
||||
dbAddr addr;
|
||||
epics_auto_ptr < char, eapt_array > pNameStr;
|
||||
dbChannel * dbch;
|
||||
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > & );
|
||||
unsigned requestMessageBytesPending (
|
||||
unsigned requestMessageBytesPending (
|
||||
epicsGuard < epicsMutex > & );
|
||||
void flush (
|
||||
void flush (
|
||||
epicsGuard < epicsMutex > & );
|
||||
ioStatus read (
|
||||
ioStatus read (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, unsigned long count,
|
||||
cacReadNotify &, ioid * );
|
||||
void write (
|
||||
void write (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, unsigned long count,
|
||||
const void * pvalue );
|
||||
ioStatus write (
|
||||
ioStatus write (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, unsigned long count,
|
||||
const void * pvalue, cacWriteNotify &, ioid * );
|
||||
void subscribe (
|
||||
void subscribe (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned type, unsigned long count,
|
||||
unsigned type, unsigned long count,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid * );
|
||||
void ioCancel (
|
||||
void ioCancel (
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & );
|
||||
void ioShow (
|
||||
void ioShow (
|
||||
epicsGuard < epicsMutex > &,
|
||||
const ioid &, unsigned level ) const;
|
||||
short nativeType (
|
||||
@@ -115,18 +114,18 @@ private:
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
inline void dbChannelIO::callReadNotify (
|
||||
epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count,
|
||||
inline void dbChannelIO::callReadNotify (
|
||||
epicsGuard < epicsMutex > & guard, unsigned type, unsigned long count,
|
||||
cacReadNotify & notify )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->serviceIO.callReadNotify ( guard, this->addr, type, count, notify );
|
||||
this->serviceIO.callReadNotify ( guard, this->dbch, type, count, notify );
|
||||
}
|
||||
|
||||
inline void dbChannelIO::callStateNotify ( unsigned type, unsigned long count,
|
||||
inline void dbChannelIO::callStateNotify ( unsigned type, unsigned long count,
|
||||
const struct db_field_log *pfl, cacStateNotify ¬ify )
|
||||
{
|
||||
this->serviceIO.callStateNotify ( this->addr, type, count, pfl, notify );
|
||||
this->serviceIO.callStateNotify ( this->dbch, type, count, pfl, notify );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 & );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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(¤t,&client->time_at_last_send);
|
||||
recv_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_recv);
|
||||
|
||||
printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n",
|
||||
printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n",
|
||||
pproto,
|
||||
clientHostName,
|
||||
client->pHostName ? client->pHostName : "",
|
||||
client->pUserName ? client->pUserName : "",
|
||||
CA_MAJOR_PROTOCOL_REVISION,
|
||||
client->minor_version_number,
|
||||
ellCount(&client->chanList) +
|
||||
ellCount(&client->chanList) +
|
||||
ellCount(&client->chanPendingUpdateARList),
|
||||
client->priority );
|
||||
if ( level >= 1 ) {
|
||||
printf ("\tTask Id=%p, Socket FD=%d\n",
|
||||
(void *) client->tid, client->sock);
|
||||
printf(
|
||||
"\tSecs since last send %6.2f, Secs since last receive %6.2f\n",
|
||||
printf ("\tTask Id=%p, Socket FD=%d\n",
|
||||
(void *) client->tid, client->sock);
|
||||
printf(
|
||||
"\tSecs since last send %6.2f, Secs since last receive %6.2f\n",
|
||||
send_delay, recv_delay);
|
||||
printf(
|
||||
"\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n",
|
||||
printf(
|
||||
"\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n",
|
||||
client->recv.cnt - client->recv.stk,
|
||||
client->send.stk );
|
||||
printf(
|
||||
"\tState=%s%s%s\n",
|
||||
printf(
|
||||
"\tState=%s%s%s\n",
|
||||
state[client->disconnect?1:0],
|
||||
client->send.type == mbtLargeTCP ? " jumbo-send-buf" : "",
|
||||
client->recv.type == mbtLargeTCP ? " jumbo-recv-buf" : "");
|
||||
@@ -428,9 +427,9 @@ static void log_one_client (struct client *client, unsigned level)
|
||||
if ( level >= 2u ) {
|
||||
unsigned bytes_reserved = 0;
|
||||
bytes_reserved += sizeof(struct client);
|
||||
bytes_reserved += countChanListBytes (
|
||||
bytes_reserved += countChanListBytes (
|
||||
client, & client->chanList );
|
||||
bytes_reserved += countChanListBytes (
|
||||
bytes_reserved += countChanListBytes (
|
||||
client, & client->chanPendingUpdateARList );
|
||||
printf( "\t%d bytes allocated\n", bytes_reserved);
|
||||
showChanList ( client, & client->chanList );
|
||||
@@ -485,20 +484,20 @@ void epicsShareAPI casr (unsigned level)
|
||||
printf( "UDP Server:\n" );
|
||||
log_one_client(prsrv_cast_client, level);
|
||||
}
|
||||
|
||||
|
||||
if (level>=2u) {
|
||||
bytes_reserved = 0u;
|
||||
bytes_reserved += sizeof (struct client) *
|
||||
bytes_reserved += sizeof (struct client) *
|
||||
freeListItemsAvail (rsrvClientFreeList);
|
||||
bytes_reserved += sizeof (struct channel_in_use) *
|
||||
freeListItemsAvail (rsrvChanFreeList);
|
||||
bytes_reserved += sizeof(struct event_ext) *
|
||||
freeListItemsAvail (rsrvEventFreeList);
|
||||
bytes_reserved += MAX_TCP *
|
||||
bytes_reserved += MAX_TCP *
|
||||
freeListItemsAvail ( rsrvSmallBufFreeListTCP );
|
||||
bytes_reserved += rsrvSizeofLargeBufTCP *
|
||||
bytes_reserved += rsrvSizeofLargeBufTCP *
|
||||
freeListItemsAvail ( rsrvLargeBufFreeListTCP );
|
||||
bytes_reserved += rsrvSizeOfPutNotify ( 0 ) *
|
||||
bytes_reserved += rsrvSizeOfPutNotify ( 0 ) *
|
||||
freeListItemsAvail ( rsrvPutNotifyFreeList );
|
||||
printf( "There are currently %u bytes on the server's free list\n",
|
||||
(unsigned int) bytes_reserved);
|
||||
@@ -525,7 +524,7 @@ void epicsShareAPI casr (unsigned level)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* destroy_client ()
|
||||
*/
|
||||
void destroy_client ( struct client *client )
|
||||
@@ -533,7 +532,7 @@ void destroy_client ( struct client *client )
|
||||
if ( ! client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( client->tid != 0 ) {
|
||||
taskwdRemove ( client->tid );
|
||||
}
|
||||
@@ -603,12 +602,12 @@ void destroy_client ( struct client *client )
|
||||
|
||||
if ( client->pHostName ) {
|
||||
free ( client->pHostName );
|
||||
}
|
||||
}
|
||||
|
||||
freeListFree ( rsrvClientFreeList, client );
|
||||
}
|
||||
|
||||
static void destroyAllChannels (
|
||||
static void destroyAllChannels (
|
||||
struct client * client, ELLLIST * pList )
|
||||
{
|
||||
if ( !client->chanListLock || !client->eventqLock ) {
|
||||
@@ -651,7 +650,7 @@ static void destroyAllChannels (
|
||||
rsrvChannelCount--;
|
||||
UNLOCK_CLIENTQ;
|
||||
if ( status != S_bucket_success ) {
|
||||
errPrintf ( status, __FILE__, __LINE__,
|
||||
errPrintf ( status, __FILE__, __LINE__,
|
||||
"Bad id=%d at close", pciu->sid);
|
||||
}
|
||||
status = asRemoveClient(&pciu->asClientPVT);
|
||||
@@ -691,7 +690,7 @@ void destroy_tcp_client ( struct client *client )
|
||||
if ( client->evuser ) {
|
||||
db_close_events (client->evuser);
|
||||
}
|
||||
|
||||
|
||||
destroy_client ( client );
|
||||
}
|
||||
|
||||
@@ -710,7 +709,7 @@ struct client * create_client ( SOCKET sock, int proto )
|
||||
spaceAvailOnFreeList = freeListItemsAvail ( rsrvClientFreeList ) > 0
|
||||
&& freeListItemsAvail ( rsrvSmallBufFreeListTCP ) > 0;
|
||||
spaceNeeded = sizeof (struct client) + MAX_TCP;
|
||||
if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) {
|
||||
if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) {
|
||||
epicsSocketDestroy ( sock );
|
||||
epicsPrintf ("CAS: no space in pool for a new client (below max block thresh)\n");
|
||||
return NULL;
|
||||
@@ -721,7 +720,7 @@ struct client * create_client ( SOCKET sock, int proto )
|
||||
epicsSocketDestroy ( sock );
|
||||
epicsPrintf ("CAS: no space in pool for a new client (alloc failed)\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
client->sock = sock;
|
||||
client->proto = proto;
|
||||
@@ -737,8 +736,8 @@ struct client * create_client ( SOCKET sock, int proto )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->pUserName = NULL;
|
||||
client->pHostName = NULL;
|
||||
client->pUserName = NULL;
|
||||
client->pHostName = NULL;
|
||||
ellInit ( & client->chanList );
|
||||
ellInit ( & client->chanPendingUpdateARList );
|
||||
ellInit ( & client->putNotifyQue );
|
||||
@@ -776,7 +775,7 @@ struct client * create_client ( SOCKET sock, int proto )
|
||||
epicsTimeGetCurrent ( &client->time_at_last_recv );
|
||||
client->minor_version_number = CA_UKN_MINOR_VERSION;
|
||||
client->recvBytesToDrain = 0u;
|
||||
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -791,10 +790,10 @@ void casAttachThreadToClient ( struct client *pClient )
|
||||
|
||||
void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size )
|
||||
{
|
||||
if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP
|
||||
if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP
|
||||
&& size <= rsrvSizeofLargeBufTCP ) {
|
||||
int spaceAvailOnFreeList = freeListItemsAvail ( rsrvLargeBufFreeListTCP ) > 0;
|
||||
if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) {
|
||||
if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) {
|
||||
char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP );
|
||||
if ( pNewBuf ) {
|
||||
memcpy ( pNewBuf, pClient->send.buf, pClient->send.stk );
|
||||
@@ -812,7 +811,7 @@ void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size )
|
||||
if ( pClient->recv.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP
|
||||
&& size <= rsrvSizeofLargeBufTCP) {
|
||||
int spaceAvailOnFreeList = freeListItemsAvail ( rsrvLargeBufFreeListTCP ) > 0;
|
||||
if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) {
|
||||
if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) {
|
||||
char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP );
|
||||
if ( pNewBuf ) {
|
||||
assert ( pClient->recv.cnt >= pClient->recv.stk );
|
||||
@@ -849,26 +848,26 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
* see TCP(4P) this seems to make unsolicited single events much
|
||||
* faster. I take care of queue up as load increases.
|
||||
*/
|
||||
status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY,
|
||||
(char *) &intTrue, sizeof (intTrue) );
|
||||
if (status < 0) {
|
||||
errlogPrintf ( "CAS: TCP_NODELAY option set failed\n" );
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* turn on KEEPALIVE so if the client crashes
|
||||
* this task will find out and exit
|
||||
*/
|
||||
status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(char *) &intTrue, sizeof (intTrue) );
|
||||
if ( status < 0 ) {
|
||||
errlogPrintf ( "CAS: SO_KEEPALIVE option set failed\n" );
|
||||
destroy_client ( client );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* some concern that vxWorks will run out of mBuf's
|
||||
* if this change is made
|
||||
@@ -876,8 +875,8 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
* joh 11-10-98
|
||||
*/
|
||||
#if 0
|
||||
/*
|
||||
* set TCP buffer sizes to be synergistic
|
||||
/*
|
||||
* set TCP buffer sizes to be synergistic
|
||||
* with CA internal buffering
|
||||
*/
|
||||
i = MAX_MSG_SIZE;
|
||||
@@ -895,7 +894,7 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
addrSize = sizeof ( client->addr );
|
||||
status = getpeername ( sock, (struct sockaddr *)&client->addr,
|
||||
&addrSize );
|
||||
@@ -928,8 +927,8 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
}
|
||||
}
|
||||
|
||||
status = db_start_events ( client->evuser, "CAS-event",
|
||||
NULL, NULL, priorityOfEvents );
|
||||
status = db_start_events ( client->evuser, "CAS-event",
|
||||
NULL, NULL, priorityOfEvents );
|
||||
if ( status != DB_EVENT_OK ) {
|
||||
errlogPrintf ( "CAS: unable to start the event facility\n" );
|
||||
destroy_tcp_client ( client );
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user