db: lock record for db_create_read_log() and dbChannelGetField()

since 27fe3e4468 db_create_read_log()
accesses record fields.

remove now redundant db_create_read_log() calls.
This commit is contained in:
Michael Davidsaver
2023-02-23 11:06:55 -08:00
committed by Andrew Johnson
parent 13d6ca598c
commit 9f788996dc
6 changed files with 37 additions and 55 deletions

View File

@ -635,9 +635,21 @@ long dbChannelGetField(dbChannel *chan, short dbrType, void *pbuffer,
{ {
dbCommon *precord = chan->addr.precord; dbCommon *precord = chan->addr.precord;
long status = 0; long status = 0;
unsigned char local_fl = 0;
dbScanLock(precord); 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); status = dbChannelGet(chan, dbrType, pbuffer, options, nRequest, pfl);
if (local_fl) {
db_delete_field_log(pfl);
}
dbScanUnlock(precord); dbScanUnlock(precord);
return status; return status;
} }

View File

@ -511,6 +511,10 @@ DBCORE_API long dbChannelGet(dbChannel *chan, short type,
* \param[in,out] nRequest Pointer to the element count. * \param[in,out] nRequest Pointer to the element count.
* \param[in] pfl Pointer to a db_field_log or NULL. * \param[in] pfl Pointer to a db_field_log or NULL.
* \returns 0, or an error status value. * \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, DBCORE_API long dbChannelGetField(dbChannel *chan, short type,
void *pbuffer, long *options, long *nRequest, void *pfl); void *pbuffer, long *options, long *nRequest, void *pfl);

View File

@ -202,7 +202,6 @@ void testdbGetFieldEqual(const char* pv, int dbrType, ...)
void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap) void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
{ {
dbChannel *chan = dbChannelCreate(pv); dbChannel *chan = dbChannelCreate(pv);
db_field_log *pfl = NULL;
long nReq = 1; long nReq = 1;
union anybuf pod; union anybuf pod;
long status = S_dbLib_recNotFound; long status = S_dbLib_recNotFound;
@ -212,18 +211,7 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
goto done; goto done;
} }
if(ellCount(&chan->filters)) { status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, NULL);
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);
if (status) { if (status) {
testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status)); testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status));
goto done; goto done;
@ -261,7 +249,6 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
} }
done: done:
db_delete_field_log(pfl);
if(chan) if(chan)
dbChannelDelete(chan); dbChannelDelete(chan);
} }
@ -288,7 +275,6 @@ done:
void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long cnt, const void *pbufraw) void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long cnt, const void *pbufraw)
{ {
dbChannel *chan = dbChannelCreate(pv); dbChannel *chan = dbChannelCreate(pv);
db_field_log *pfl = NULL;
const long vSize = dbValueSize(dbfType); const long vSize = dbValueSize(dbfType);
const long nStore = vSize * nRequest; const long nStore = vSize * nRequest;
long status = S_dbLib_recNotFound; long status = S_dbLib_recNotFound;
@ -300,24 +286,13 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign
goto done; 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); gbuf = gstore = malloc(nStore);
if(!gbuf && nStore!=0) { /* note that malloc(0) is allowed to return NULL on success */ if(!gbuf && nStore!=0) { /* note that malloc(0) is allowed to return NULL on success */
testFail("Allocation failed esize=%ld total=%ld", vSize, nStore); testFail("Allocation failed esize=%ld total=%ld", vSize, nStore);
return; return;
} }
status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, pfl); status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, NULL);
if (status) { if (status) {
testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status); testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status);

View File

@ -148,6 +148,7 @@ int dbChannel_get_count(
long options; long options;
long i; long i;
long zero = 0; long zero = 0;
unsigned char local_fl = 0;
/* The order of the DBR* elements in the "newSt" structures below is /* The order of the DBR* elements in the "newSt" structures below is
* very important and must correspond to the order of processing * very important and must correspond to the order of processing
@ -156,6 +157,16 @@ int dbChannel_get_count(
dbScanLock(dbChannelRecord(chan)); 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) { switch(buffer_type) {
case(oldDBR_STRING): case(oldDBR_STRING):
status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl); status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl);
@ -800,6 +811,8 @@ int dbChannel_get_count(
dbScanUnlock(dbChannelRecord(chan)); dbScanUnlock(dbChannelRecord(chan));
if (local_fl) db_delete_field_log(pfl);
if (status) return -1; if (status) return -1;
return 0; return 0;
} }

View File

@ -493,7 +493,6 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
const int readAccess = asCheckGet ( pciu->asClientPVT ); const int readAccess = asCheckGet ( pciu->asClientPVT );
int status; int status;
int autosize; int autosize;
int local_fl = 0;
long item_count; long item_count;
ca_uint32_t payload_size; ca_uint32_t payload_size;
dbAddr *paddr=&dbch->addr; dbAddr *paddr=&dbch->addr;
@ -535,21 +534,9 @@ static void read_reply ( void *pArg, struct dbChannel *dbch,
return; 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, status = dbChannel_get_count ( dbch, pevext->msg.m_dataType,
pPayload, &item_count, pfl); pPayload, &item_count, pfl);
if (local_fl) db_delete_field_log(pfl);
if ( status < 0 ) { if ( status < 0 ) {
/* Clients recv the status of the operation directly to the /* Clients recv the status of the operation directly to the
* event/put/get callback. (from CA_V41()) * 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; ca_uint32_t payloadSize;
void *pPayload; void *pPayload;
int status; int status;
int local_fl = 0;
db_field_log *pfl = NULL; db_field_log *pfl = NULL;
if ( ! pciu ) { if ( ! pciu ) {
@ -655,21 +641,9 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p
return RSRV_OK; 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, status = dbChannel_get ( pciu->dbch, mp->m_dataType,
pPayload, mp->m_count, pfl ); pPayload, mp->m_count, pfl );
if (local_fl) db_delete_field_log(pfl);
if ( status < 0 ) { if ( status < 0 ) {
send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( pciu->dbch ) ); send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( pciu->dbch ) );
SEND_UNLOCK ( pClient ); SEND_UNLOCK ( pClient );

View File

@ -130,9 +130,11 @@ static void check(short dbr_type) {
off = Offset; req = 10; \ off = Offset; req = 10; \
memset(buf, 0, sizeof(buf)); \ memset(buf, 0, sizeof(buf)); \
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \ (void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
dbScanLock(dbChannelRecord(pch)); \
pfl = db_create_read_log(pch); \ pfl = db_create_read_log(pch); \
testOk(pfl && pfl->type == dbfl_type_ref, "Valid pfl, type = ref"); \ 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); \ testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \ if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
for (i=0; i<Size; i++) \ for (i=0; i<Size; i++) \
@ -174,6 +176,7 @@ static void check(short dbr_type) {
off = Offset; req = 15; \ off = Offset; req = 15; \
memset(buf, 0, sizeof(buf)); \ memset(buf, 0, sizeof(buf)); \
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \ (void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
dbScanLock(dbChannelRecord(pch)); \
pfl = db_create_read_log(pch); \ pfl = db_create_read_log(pch); \
pfl->type = dbfl_type_ref; \ pfl->type = dbfl_type_ref; \
pfl->field_type = DBF_CHAR; \ pfl->field_type = DBF_CHAR; \
@ -181,7 +184,8 @@ static void check(short dbr_type) {
pfl->no_elements = 26; \ pfl->no_elements = 26; \
pfl->dtor = freeArray; \ pfl->dtor = freeArray; \
pfl->u.r.field = epicsStrDup("abcdefghijklmnopqrsstuvwxyz"); \ 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); \ testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \ if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
for (i=0; i<Size; i++) \ for (i=0; i<Size; i++) \