ioc/dbStatic: add dbInitEntryFromChannel()

Constant time population of a DBENTRY from
a valid dbAddr.
This commit is contained in:
Michael Davidsaver
2017-04-28 18:23:30 -04:00
parent f716b1b26a
commit 78a7ad168e
8 changed files with 138 additions and 1 deletions

View File

@@ -682,6 +682,19 @@ finish:
return status;
}
void dbInitEntryFromChannel(struct dbAddr *paddr, DBENTRY *pdbentry)
{
struct dbCommon *prec = paddr->precord;
pdbentry->pdbbase = pdbbase;
pdbentry->precordType = prec->rdes;
pdbentry->precnode = prec->rnde;
pdbentry->pflddes = paddr->pfldDes;
pdbentry->pinfonode = NULL;
pdbentry->pfield = paddr->pfield;
pdbentry->indfield = -1; /* invalid */
pdbentry->message = NULL;
}
long dbValueSize(short dbr_type)
{
/* sizes for value associated with each DBR request type */

View File

@@ -217,6 +217,12 @@
interest(4)
extra("struct dbRecordType *rdes")
}
field(RNDE,DBF_NOACCESS) {
prompt("Address of dbRecordNode")
special(SPC_NOMOD)
interest(4)
extra("struct dbRecordNode *rnde")
}
field(LSET,DBF_NOACCESS) {
prompt("Lock Set")
special(SPC_NOMOD)

View File

@@ -159,6 +159,13 @@ testHarness_SRCS += dbPutGetTest.c
TESTFILES += ../dbPutGetTest.db
TESTS += testPutGetTest
TESTPROD_HOST += dbStaticTest
dbStaticTest_SRCS += dbStaticTest.c
dbStaticTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
testHarness_SRCS += dbStaticTest.c
TESTFILES += ../dbStaticTest.db
TESTS += dbStaticTest
# This runs all the test programs in a known working order:
testHarness_SRCS += epicsRunDbTests.c

View File

@@ -0,0 +1,92 @@
#include <string.h>
#include <errlog.h>
#include <dbAccess.h>
#include <dbStaticLib.h>
#include <dbStaticPvt.h>
#include <dbUnitTest.h>
#include <testMain.h>
static void testEntry(void)
{
DBENTRY entry;
testDiag("testEntry");
dbInitEntry(pdbbase, &entry);
testOk1(dbFindRecord(&entry, "testrec.VAL")==0);
testOk1(entry.precordType && strcmp(entry.precordType->name, "x")==0);
testOk1(entry.precnode && strcmp(((dbCommon*)entry.precnode->precord)->name, "testrec")==0);
testOk1(entry.pflddes && strcmp(entry.pflddes->name, "VAL")==0);
testOk1(dbFindInfo(&entry, "A")==0 && strcmp(dbGetInfoString(&entry), "B")==0);
dbFinishEntry(&entry);
}
static void testAddr2Entry(void)
{
DBENTRY entry, entry2;
dbAddr addr;
testDiag("testAddr2Entry");
memset(&entry, 0, sizeof(entry));
memset(&entry2, 0, sizeof(entry2));
dbInitEntry(pdbbase, &entry);
if(dbFindRecord(&entry, "testrec.VAL")!=0)
testAbort("no entry for testrec.VAL");
if(dbNameToAddr("testrec.VAL", &addr))
testAbort("no addr for testrec.VAL");
dbInitEntryFromChannel(&addr, &entry2);
testOk1(entry.pdbbase==entry2.pdbbase);
testOk1(entry.precordType==entry2.precordType);
testOk1(entry.pflddes==entry2.pflddes);
testOk1(entry.precnode==entry2.precnode);
testOk1(entry.pfield==entry2.pfield);
testOk1(entry2.indfield==-1);
testOk1(!entry2.pinfonode);
testOk1(!entry2.message);
/* no way to look this up, so not set */
entry.indfield = -1;
testOk1(memcmp(&entry, &entry2, sizeof(entry))==0);
dbFinishEntry(&entry);
}
void dbTestIoc_registerRecordDeviceDriver(struct dbBase *);
MAIN(dbStaticTest)
{
testPlan(19);
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
dbTestIoc_registerRecordDeviceDriver(pdbbase);
testdbReadDatabase("dbStaticTest.db", NULL, NULL);
testEntry();
eltc(0);
testIocInitOk();
eltc(1);
testEntry();
testAddr2Entry();
testIocShutdownOk();
testdbCleanup();
return testDone();
}

View File

@@ -0,0 +1,4 @@
record(x, "testrec") {
info("A", "B")
}

View File

@@ -26,6 +26,7 @@ int dbScanTest(void);
int scanIoTest(void);
int dbLockTest(void);
int dbPutLinkTest(void);
int dbStaticTest(void);
int dbCaLinkTest(void);
int testDbChannel(void);
int chfPluginTest(void);
@@ -46,6 +47,7 @@ void epicsRunDbTests(void)
runTest(scanIoTest);
runTest(dbLockTest);
runTest(dbPutLinkTest);
runTest(dbStaticTest);
runTest(dbCaLinkTest);
runTest(testDbChannel);
runTest(arrShorthandTest);

View File

@@ -56,7 +56,9 @@ typedef struct{
char *message;
short indfield;
} DBENTRY;
struct dbAddr;
/*dbDumpFldDes is obsolete. It is only provided for compatibility*/
#define dbDumpFldDes dbDumpField
@@ -67,6 +69,11 @@ epicsShareFunc DBENTRY * dbAllocEntry(DBBASE *pdbbase);
epicsShareFunc void dbFreeEntry(DBENTRY *pdbentry);
epicsShareFunc void dbInitEntry(DBBASE *pdbbase,
DBENTRY *pdbentry);
/** Initialize DBENTRY from a valid dbAddr*.
* Constant time equivalent of dbInitEntry() then dbFindRecord()
* except that DBENTRY::indfield is not set
*/
epicsShareFunc void dbInitEntryFromChannel(struct dbAddr *paddr, DBENTRY *pdbentry);
epicsShareFunc void dbFinishEntry(DBENTRY *pdbentry);
epicsShareFunc DBENTRY * dbCopyEntry(DBENTRY *pdbentry);
epicsShareFunc void dbCopyEntryContents(DBENTRY *pfrom,

View File

@@ -79,8 +79,14 @@ long dbAllocRecord(DBENTRY *pdbentry,const char *precordName)
epicsPrintf("dbAllocRecord(%s) with %s rec_size = 0\n",
precordName, pdbRecordType->name);
return(S_dbLib_noRecSup);
} else if(pdbRecordType->rec_size<sizeof(*precord)) {
printf("\t*** Recordtype %s must include \"dbCommon.dbd\"\n", pdbRecordType->name);
epicsPrintf("dbAllocRecord(%s) with %s rec_size = %d\n",
precordName, pdbRecordType->name, pdbRecordType->rec_size);
return(S_dbLib_noRecSup);
}
precord = dbCalloc(1, pdbRecordType->rec_size);
precord->rnde = precnode;
precnode->precord = precord;
pflddes = pdbRecordType->papFldDes[0];
if(!pflddes) {