diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index 1c01da331..4fb25f0bd 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -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 */ diff --git a/src/ioc/db/dbCommon.dbd b/src/ioc/db/dbCommon.dbd index 1b093e6a8..2df9957b8 100644 --- a/src/ioc/db/dbCommon.dbd +++ b/src/ioc/db/dbCommon.dbd @@ -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) diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile index 17941a2bc..e3d4164ff 100644 --- a/src/ioc/db/test/Makefile +++ b/src/ioc/db/test/Makefile @@ -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 diff --git a/src/ioc/db/test/dbStaticTest.c b/src/ioc/db/test/dbStaticTest.c new file mode 100644 index 000000000..b6110162b --- /dev/null +++ b/src/ioc/db/test/dbStaticTest.c @@ -0,0 +1,92 @@ +#include + +#include +#include +#include +#include +#include +#include + +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(); +} + diff --git a/src/ioc/db/test/dbStaticTest.db b/src/ioc/db/test/dbStaticTest.db new file mode 100644 index 000000000..d44592979 --- /dev/null +++ b/src/ioc/db/test/dbStaticTest.db @@ -0,0 +1,4 @@ + +record(x, "testrec") { + info("A", "B") +} diff --git a/src/ioc/db/test/epicsRunDbTests.c b/src/ioc/db/test/epicsRunDbTests.c index 10f10e267..69f6b082e 100644 --- a/src/ioc/db/test/epicsRunDbTests.c +++ b/src/ioc/db/test/epicsRunDbTests.c @@ -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); diff --git a/src/ioc/dbStatic/dbStaticLib.h b/src/ioc/dbStatic/dbStaticLib.h index 1619a9090..23eeba349 100644 --- a/src/ioc/dbStatic/dbStaticLib.h +++ b/src/ioc/dbStatic/dbStaticLib.h @@ -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, diff --git a/src/ioc/dbStatic/dbStaticRun.c b/src/ioc/dbStatic/dbStaticRun.c index f4a9d0709..a08322abf 100644 --- a/src/ioc/dbStatic/dbStaticRun.c +++ b/src/ioc/dbStatic/dbStaticRun.c @@ -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_sizename); + 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) {