diff --git a/modules/database/src/ioc/db/dbChannel.c b/modules/database/src/ioc/db/dbChannel.c index fd682c93e..ad0531580 100644 --- a/modules/database/src/ioc/db/dbChannel.c +++ b/modules/database/src/ioc/db/dbChannel.c @@ -635,9 +635,21 @@ long dbChannelGetField(dbChannel *chan, short dbrType, void *pbuffer, { dbCommon *precord = chan->addr.precord; long status = 0; + unsigned char local_fl = 0; dbScanLock(precord); + if (!pfl && (ellCount(&chan->pre_chain) || ellCount(&chan->post_chain))) { + pfl = db_create_read_log(chan); + if (pfl) { + local_fl = 1; + pfl = dbChannelRunPreChain(chan, pfl); + pfl = dbChannelRunPostChain(chan, pfl); + } + } status = dbChannelGet(chan, dbrType, pbuffer, options, nRequest, pfl); + if (local_fl) { + db_delete_field_log(pfl); + } dbScanUnlock(precord); return status; } diff --git a/modules/database/src/ioc/db/dbChannel.h b/modules/database/src/ioc/db/dbChannel.h index d4cb9e9bc..4bfdd6bc3 100644 --- a/modules/database/src/ioc/db/dbChannel.h +++ b/modules/database/src/ioc/db/dbChannel.h @@ -511,6 +511,10 @@ DBCORE_API long dbChannelGet(dbChannel *chan, short type, * \param[in,out] nRequest Pointer to the element count. * \param[in] pfl Pointer to a db_field_log or NULL. * \returns 0, or an error status value. + * + * \since UNRELEASED If pfl is NULL and chan has filters, db_create_read_log() will be called + * internally to create a temporary db_field_log which is passed to dbChannelGet() + * then deallocated. */ DBCORE_API long dbChannelGetField(dbChannel *chan, short type, void *pbuffer, long *options, long *nRequest, void *pfl); diff --git a/modules/database/src/ioc/db/dbUnitTest.c b/modules/database/src/ioc/db/dbUnitTest.c index 5ac710f48..671763636 100644 --- a/modules/database/src/ioc/db/dbUnitTest.c +++ b/modules/database/src/ioc/db/dbUnitTest.c @@ -202,7 +202,6 @@ void testdbGetFieldEqual(const char* pv, int dbrType, ...) void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap) { dbChannel *chan = dbChannelCreate(pv); - db_field_log *pfl = NULL; long nReq = 1; union anybuf pod; long status = S_dbLib_recNotFound; @@ -212,18 +211,7 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap) goto done; } - if(ellCount(&chan->filters)) { - pfl = db_create_read_log(chan); - if (!pfl) { - testFail("can't db_create_read_log w/ %s", pv); - goto done; - } - - pfl = dbChannelRunPreChain(chan, pfl); - pfl = dbChannelRunPostChain(chan, pfl); - } - - status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, pfl); + status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, NULL); if (status) { testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status)); goto done; @@ -261,7 +249,6 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap) } done: - db_delete_field_log(pfl); if(chan) dbChannelDelete(chan); } @@ -288,7 +275,6 @@ done: void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long cnt, const void *pbufraw) { dbChannel *chan = dbChannelCreate(pv); - db_field_log *pfl = NULL; const long vSize = dbValueSize(dbfType); const long nStore = vSize * nRequest; long status = S_dbLib_recNotFound; @@ -300,24 +286,13 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign goto done; } - if(ellCount(&chan->filters)) { - pfl = db_create_read_log(chan); - if (!pfl) { - testFail("can't db_create_read_log w/ %s", pv); - goto done; - } - - pfl = dbChannelRunPreChain(chan, pfl); - pfl = dbChannelRunPostChain(chan, pfl); - } - gbuf = gstore = malloc(nStore); if(!gbuf && nStore!=0) { /* note that malloc(0) is allowed to return NULL on success */ testFail("Allocation failed esize=%ld total=%ld", vSize, nStore); return; } - status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, pfl); + status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, NULL); if (status) { testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status); diff --git a/modules/database/src/ioc/db/db_access.c b/modules/database/src/ioc/db/db_access.c index 0943315cf..cf83ec8a0 100644 --- a/modules/database/src/ioc/db/db_access.c +++ b/modules/database/src/ioc/db/db_access.c @@ -148,6 +148,7 @@ int dbChannel_get_count( long options; long i; long zero = 0; + unsigned char local_fl = 0; /* The order of the DBR* elements in the "newSt" structures below is * very important and must correspond to the order of processing @@ -156,6 +157,16 @@ int dbChannel_get_count( dbScanLock(dbChannelRecord(chan)); + /* If filters are involved in a read, create field log and run filters */ + if (!pfl && (ellCount(&chan->pre_chain) || ellCount(&chan->post_chain))) { + pfl = db_create_read_log(chan); + if (pfl) { + local_fl = 1; + pfl = dbChannelRunPreChain(chan, pfl); + pfl = dbChannelRunPostChain(chan, pfl); + } + } + switch(buffer_type) { case(oldDBR_STRING): status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl); @@ -800,6 +811,8 @@ int dbChannel_get_count( dbScanUnlock(dbChannelRecord(chan)); + if (local_fl) db_delete_field_log(pfl); + if (status) return -1; return 0; } diff --git a/modules/database/src/ioc/rsrv/camessage.c b/modules/database/src/ioc/rsrv/camessage.c index 81cb36a87..36844d162 100644 --- a/modules/database/src/ioc/rsrv/camessage.c +++ b/modules/database/src/ioc/rsrv/camessage.c @@ -493,7 +493,6 @@ static void read_reply ( void *pArg, struct dbChannel *dbch, const int readAccess = asCheckGet ( pciu->asClientPVT ); int status; int autosize; - int local_fl = 0; long item_count; ca_uint32_t payload_size; dbAddr *paddr=&dbch->addr; @@ -535,21 +534,9 @@ static void read_reply ( void *pArg, struct dbChannel *dbch, return; } - /* If filters are involved in a read, create field log and run filters */ - if (!pfl && (ellCount(&dbch->pre_chain) || ellCount(&dbch->post_chain))) { - pfl = db_create_read_log(dbch); - if (pfl) { - local_fl = 1; - pfl = dbChannelRunPreChain(dbch, pfl); - pfl = dbChannelRunPostChain(dbch, pfl); - } - } - status = dbChannel_get_count ( dbch, pevext->msg.m_dataType, pPayload, &item_count, pfl); - if (local_fl) db_delete_field_log(pfl); - if ( status < 0 ) { /* Clients recv the status of the operation directly to the * event/put/get callback. (from CA_V41()) @@ -616,7 +603,6 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p ca_uint32_t payloadSize; void *pPayload; int status; - int local_fl = 0; db_field_log *pfl = NULL; if ( ! pciu ) { @@ -655,21 +641,9 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p return RSRV_OK; } - /* If filters are involved in a read, create field log and run filters */ - if (ellCount(&pciu->dbch->pre_chain) || ellCount(&pciu->dbch->post_chain)) { - pfl = db_create_read_log(pciu->dbch); - if (pfl) { - local_fl = 1; - pfl = dbChannelRunPreChain(pciu->dbch, pfl); - pfl = dbChannelRunPostChain(pciu->dbch, pfl); - } - } - status = dbChannel_get ( pciu->dbch, mp->m_dataType, pPayload, mp->m_count, pfl ); - if (local_fl) db_delete_field_log(pfl); - if ( status < 0 ) { send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( pciu->dbch ) ); SEND_UNLOCK ( pClient ); diff --git a/modules/database/test/ioc/db/dbChArrTest.cpp b/modules/database/test/ioc/db/dbChArrTest.cpp index 96870d212..1560f72a6 100644 --- a/modules/database/test/ioc/db/dbChArrTest.cpp +++ b/modules/database/test/ioc/db/dbChArrTest.cpp @@ -130,9 +130,11 @@ static void check(short dbr_type) { off = Offset; req = 10; \ memset(buf, 0, sizeof(buf)); \ (void) dbPutField(&offaddr, DBR_LONG, &off, 1); \ + dbScanLock(dbChannelRecord(pch)); \ pfl = db_create_read_log(pch); \ testOk(pfl && pfl->type == dbfl_type_ref, "Valid pfl, type = ref"); \ - testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \ + testOk(!dbChannelGet(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \ + dbScanUnlock(dbChannelRecord(pch)); \ testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \ if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \ for (i=0; itype = dbfl_type_ref; \ pfl->field_type = DBF_CHAR; \ @@ -181,7 +184,8 @@ static void check(short dbr_type) { pfl->no_elements = 26; \ pfl->dtor = freeArray; \ pfl->u.r.field = epicsStrDup("abcdefghijklmnopqrsstuvwxyz"); \ - testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \ + testOk(!dbChannelGet(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \ + dbScanUnlock(dbChannelRecord(pch)); \ testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \ if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \ for (i=0; i