From 56468b684e70ec0d6a2b895d42527a0d2551e0e2 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 27 Apr 2012 13:21:41 -0400 Subject: [PATCH] Extended functionality of dbChannel code: * Deleted the chan->magic member and associated checks. * Moved rset->cvt_dbaddr() call into dbChannelCreate() * Added many accessor routines * Renamed dbChannelReport() to dbChannelShow() and added dbChannelFilterShow() --- src/ioc/db/dbChannel.c | 140 ++++++++++++++++++++++---------- src/ioc/db/dbChannel.h | 32 +++++--- src/ioc/db/test/dbChannelTest.c | 2 +- 3 files changed, 119 insertions(+), 55 deletions(-) diff --git a/src/ioc/db/dbChannel.c b/src/ioc/db/dbChannel.c index f9a995a6a..97fe9ec91 100644 --- a/src/ioc/db/dbChannel.c +++ b/src/ioc/db/dbChannel.c @@ -10,6 +10,7 @@ #include "cantProceed.h" #include "dbChannel.h" +#include "dbCommon.h" #include "dbBase.h" #include "link.h" #include "dbAccessDefs.h" @@ -292,21 +293,21 @@ static long pvNameLookup(DBENTRY *pdbe, const char **ppname) return status; } -long dbChannelTest(const char *pname) +long dbChannelTest(const char *name) { DBENTRY dbEntry; long status; - if (!pname || !*pname || !pdbbase) + if (!name || !*name || !pdbbase) return S_db_notFound; - status = pvNameLookup(&dbEntry, &pname); + status = pvNameLookup(&dbEntry, &name); if (status) goto finish; /* Test field modifiers */ - while (*pname) { - switch (*pname) { + while (*name) { + switch (*name) { case '$': switch (dbEntry.pflddes->field_type) { case DBF_STRING: @@ -320,13 +321,13 @@ long dbChannelTest(const char *pname) } break; case '{': - status = json_validate(pname); + status = json_validate(name); goto finish; default: status = S_dbLib_fieldNotFound; goto finish; } - pname++; + name++; } finish: @@ -356,17 +357,16 @@ static short mapDBFToDBR[DBF_NTYPES] = dbChannel * dbChannelCreate(const char *name) { + const char *pname = name; DBENTRY dbEntry; dbChannel *chan = NULL; DBADDR *paddr; dbFldDes *pflddes; - const char *pname; long status; short dbfType; if (!name || !*name || !pdbbase) return NULL; - pname = name; status = pvNameLookup(&dbEntry, &pname); if (status) @@ -374,7 +374,6 @@ dbChannel * dbChannelCreate(const char *name) // FIXME: Use free-list chan = (dbChannel *) callocMustSucceed(1, sizeof(*chan), "dbChannelCreate"); - chan->magic = DBCHANNEL_MAGIC; chan->name = strdup(name); // FIXME? ellInit(&chan->filters); @@ -421,36 +420,30 @@ dbChannel * dbChannelCreate(const char *name) pname++; } -finish: - dbFinishEntry(&dbEntry); - if (status && chan) { - dbChannelDelete(chan); - chan = NULL; - } - return chan; -} - -long dbChannelOpen(dbChannel *chan) -{ - DBADDR *paddr; - chFilter *filter; - long status = 0; - - if (chan->magic != DBCHANNEL_MAGIC) - return S_db_notInit; - - paddr = &chan->addr; if (paddr->special == SPC_DBADDR) { struct rset *prset = dbGetRset(paddr); /* Let record type modify the dbAddr */ if (prset && prset->cvt_dbaddr) { status = prset->cvt_dbaddr(paddr); - if (status) - return status; + if (status) goto finish; } } +finish: + if (status && chan) { + dbChannelDelete(chan); + chan = NULL; + } + dbFinishEntry(&dbEntry); + return chan; +} + +long dbChannelOpen(dbChannel *chan) +{ + chFilter *filter; + long status = 0; + filter = (chFilter *) ellFirst(&chan->filters); while (filter) { status = filter->fif->channel_open(filter); @@ -461,19 +454,81 @@ long dbChannelOpen(dbChannel *chan) return status; } -void dbChannelReport(dbChannel *chan, int level) +const char * dbChannelName(dbChannel *chan) { - chFilter *filter; + return chan->name; +} - if (chan->magic != DBCHANNEL_MAGIC) - return; +struct dbCommon * dbChannelRecord(dbChannel *chan) +{ + return chan->addr.precord; +} - printf("Channel '%s': %d filter(s)\n", chan->name, - ellCount(&chan->filters)); +struct dbFldDes * dbChannelFldDes(dbChannel *chan) +{ + return chan->addr.pfldDes; +} - filter = (chFilter *) ellFirst(&chan->filters); +long dbChannelElements(dbChannel *chan) +{ + return chan->addr.no_elements; +} + +short dbChannelFieldType(dbChannel *chan) +{ + return chan->addr.field_type; +} + +short dbChannelExportType(dbChannel *chan) +{ + return chan->addr.dbr_field_type; +} + +short dbChannelElementSize(dbChannel *chan) +{ + return chan->addr.field_size; +} + +short dbChannelSpecial(dbChannel *chan) +{ + return chan->addr.special; +} + +void * dbChannelData(dbChannel *chan) +{ + void * pdata = chan->addr.pfield; + /* FIXME: offer to filters? */ + return pdata; +} + +long dbChannelPut(dbChannel *chan, short type, const void *pbuffer, long nRequest) +{ + /* FIXME: offer to filters? */ + return dbPut(&chan->addr, type, pbuffer, nRequest); +} + +long dbChannelPutField(dbChannel *chan, short type, const void *pbuffer, long nRequest) +{ + /* FIXME: offer to filters? */ + return dbPutField(&chan->addr, type, pbuffer, nRequest); +} + +void dbChannelShow(dbChannel *chan, int level) +{ + printf(" dbChannel name: %s\n", chan->name); + /* FIXME: show field_type name */ + printf(" field_type %d, %ld element(s), %d filter(s)", + chan->addr.field_type, + chan->addr.no_elements, ellCount(&chan->filters)); + if (level > 0) + dbChannelFilterShow(chan, level - 1); +} + +void dbChannelFilterShow(dbChannel *chan, int level) +{ + chFilter *filter = (chFilter *) ellFirst(&chan->filters); while (filter) { - filter->fif->channel_report(filter, level); + filter->fif->channel_report(filter, level - 1); filter = (chFilter *) ellNext(&filter->node); } } @@ -482,20 +537,17 @@ long dbChannelDelete(dbChannel *chan) { chFilter *filter; - if (chan->magic != DBCHANNEL_MAGIC) - return S_db_notInit; - while ((filter = (chFilter *) ellGet(&chan->filters))) { filter->fif->channel_close(filter); free(filter); } - free(chan->name); // FIXME? - chan->magic = 0; + free((char *) chan->name); // FIXME: Use free-list free(chan); // FIXME: Use free-list return 0; } + /* FIXME: Do these belong in a different file? */ void dbRegisterFilter(const char *name, const chFilterIf *fif) diff --git a/src/ioc/db/dbChannel.h b/src/ioc/db/dbChannel.h index 740165b17..3c5d2e2b3 100644 --- a/src/ioc/db/dbChannel.h +++ b/src/ioc/db/dbChannel.h @@ -16,16 +16,11 @@ #include "shareLib.h" #ifdef __cplusplus -// extern "C" { +extern "C" { #endif -#define DBCHANNEL_MAGIC 0xdbc4a9e1 - -#define S_db_notInit (M_dbAccess|21) /*dbChannel not initialized*/ - /* A dbChannel points to a record field, and can have multiple filters */ typedef struct dbChannel { - epicsUInt32 magic; const char *name; dbAddr addr; ELLLIST filters; @@ -74,7 +69,7 @@ typedef struct chFilterIf { /* Channel operations: */ long (* channel_open)(chFilter *filter); void (* channel_report)(chFilter *filter, int level); - /* FIXME: More routines here ... */ + /* FIXME: More filter routines here ... */ void (* channel_close)(chFilter *filter); } chFilterIf; @@ -86,10 +81,27 @@ struct chFilter { void *puser; }; -epicsShareFunc long dbChannelTest(const char *pname); -epicsShareFunc dbChannel * dbChannelCreate(const char *pname); +struct dbCommon; +struct dbFldDes; + +epicsShareFunc long dbChannelTest(const char *name); +epicsShareFunc dbChannel * dbChannelCreate(const char *name); epicsShareFunc long dbChannelOpen(dbChannel *chan); -epicsShareFunc void dbChannelReport(dbChannel *chan, int level); +epicsShareFunc const char * dbChannelName(dbChannel *chan); +epicsShareFunc struct dbCommon * dbChannelRecord(dbChannel *chan); +epicsShareFunc struct dbFldDes * dbChannelFldDes(dbChannel *chan); +epicsShareFunc long dbChannelElements(dbChannel *chan); +epicsShareFunc short dbChannelFieldType(dbChannel *chan); +epicsShareFunc short dbChannelExportType(dbChannel *chan); +epicsShareFunc short dbChannelElementSize(dbChannel *chan); +epicsShareFunc short dbChannelSpecial(dbChannel *chan); +epicsShareFunc void * dbChannelData(dbChannel *chan); +epicsShareFunc long dbChannelPut(dbChannel *chan, short type, + const void *pbuffer, long nRequest); +epicsShareFunc long dbChannelPutField(dbChannel *chan, short type, + const void *pbuffer, long nRequest); +epicsShareFunc void dbChannelShow(dbChannel *chan, int level); +epicsShareFunc void dbChannelFilterShow(dbChannel *chan, int level); epicsShareFunc long dbChannelDelete(dbChannel *chan); epicsShareFunc void dbRegisterFilter(const char *key, const chFilterIf *fif); diff --git a/src/ioc/db/test/dbChannelTest.c b/src/ioc/db/test/dbChannelTest.c index 9a8245f55..58db707c5 100644 --- a/src/ioc/db/test/dbChannelTest.c +++ b/src/ioc/db/test/dbChannelTest.c @@ -185,7 +185,7 @@ MAIN(dbChannelTest) testOk1(!!(pch = dbChannelCreate("x.{\"scalar\":null}"))); e = e_report; - dbChannelReport(pch, 0); + dbChannelShow(pch, 0); e = e_close; testOk1(!dbChannelDelete(pch));