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:

committed by
Andrew Johnson

parent
13d6ca598c
commit
9f788996dc
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 );
|
||||
|
@ -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; i<Size; i++) \
|
||||
@ -174,6 +176,7 @@ static void check(short dbr_type) {
|
||||
off = Offset; req = 15; \
|
||||
memset(buf, 0, sizeof(buf)); \
|
||||
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
|
||||
dbScanLock(dbChannelRecord(pch)); \
|
||||
pfl = db_create_read_log(pch); \
|
||||
pfl->type = 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<Size; i++) \
|
||||
|
Reference in New Issue
Block a user