allow to load the same alias multiple times (unless dbRecordsOnceOnly is set)
This commit is contained in:
@ -32,6 +32,13 @@ not propagate AMSG, either.
|
||||
Channel Access links do not propagate AMSG, regardless of the MSS attribute,
|
||||
because the message is not available over Channel Access.
|
||||
|
||||
### Allow to load the same alias multiple times
|
||||
|
||||
Aliases can now be defined multiple times as long as they still refer to the
|
||||
same record, unless the shell variable dbRecordsOnceOnly is set.
|
||||
This allows to load database files multiple times, even if they contain
|
||||
alias definitions.
|
||||
|
||||
### DBE_PROPERTY event rate changed
|
||||
|
||||
Updating property fields now only post DBE_PROPERTY events if the
|
||||
|
@ -1263,24 +1263,50 @@ static void dbRecordInfo(char *name, char *value)
|
||||
}
|
||||
}
|
||||
|
||||
static long createAlias(DBENTRY *pdbentry, const char *alias)
|
||||
{
|
||||
DBENTRY tempEntry;
|
||||
long status;
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
|
||||
if (precnode->aliasedRecnode) precnode = precnode->aliasedRecnode;
|
||||
dbInitEntry(pdbentry->pdbbase, &tempEntry);
|
||||
status = dbFindRecord(&tempEntry, alias);
|
||||
if (status == 0) {
|
||||
if (tempEntry.precnode->aliasedRecnode != precnode) {
|
||||
if (tempEntry.precnode->aliasedRecnode)
|
||||
fprintf(stderr, ERL_ERROR ": Alias \"%s\" for \"%s\": name already used by an alias for \"%s\"\n",
|
||||
alias, dbGetRecordName(pdbentry),
|
||||
tempEntry.precnode->aliasedRecnode->recordname);
|
||||
else
|
||||
fprintf(stderr, ERL_ERROR ": Alias \"%s\" for \"%s\": name already used by a record\n",
|
||||
alias, dbGetRecordName(pdbentry));
|
||||
status = S_dbLib_recExists;
|
||||
} else if (dbRecordsOnceOnly) {
|
||||
fprintf(stderr, ERL_ERROR ": Alias \"%s\" already defined and dbRecordsOnceOnly set.\n",
|
||||
alias);
|
||||
status = S_dbLib_recExists;
|
||||
}
|
||||
} else {
|
||||
status = dbCreateAlias(pdbentry, alias);
|
||||
}
|
||||
dbFinishEntry(&tempEntry);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dbRecordAlias(char *name)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if(dbRecordNameValidate(name))
|
||||
return;
|
||||
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbCreateAlias(pdbentry, name);
|
||||
if (status) {
|
||||
fprintf(stderr, "Can't create alias \"%s\" for \"%s\"\n",
|
||||
name, dbGetRecordName(pdbentry));
|
||||
|
||||
if (createAlias(pdbentry, name) != 0) {
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1298,9 +1324,7 @@ static void dbAlias(char *name, char *alias)
|
||||
alias, name);
|
||||
yyerror(NULL);
|
||||
}
|
||||
else if (dbCreateAlias(pdbEntry, alias)) {
|
||||
fprintf(stderr, "Can't create alias \"%s\" referring to \"%s\"\n",
|
||||
alias, name);
|
||||
else if (createAlias(pdbEntry, alias) != 0) {
|
||||
yyerror(NULL);
|
||||
}
|
||||
dbFinishEntry(pdbEntry);
|
||||
|
@ -36,6 +36,7 @@ dbTestIoc_DBD += xLink.dbd
|
||||
dbTestIoc_DBD += devx.dbd
|
||||
dbTestIoc_DBD += jlinkz.dbd
|
||||
dbTestIoc_DBD += dbLinkdset.dbd
|
||||
dbTestIoc_DBD += dbCore.dbd
|
||||
TESTFILES += $(COMMON_DIR)/dbTestIoc.dbd ../xRecord.db
|
||||
|
||||
testHarness_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
|
||||
@ -183,6 +184,11 @@ testHarness_SRCS += dbStaticTest.c
|
||||
TESTFILES += ../dbStaticTest.db
|
||||
TESTFILES += ../dbStaticTestAlias1.db
|
||||
TESTFILES += ../dbStaticTestAlias2.db
|
||||
TESTFILES += ../dbStaticTestAliasAgain1.db
|
||||
TESTFILES += ../dbStaticTestAliasAgain2.db
|
||||
TESTFILES += ../dbStaticTestAliasAgain3.db
|
||||
TESTFILES += ../dbStaticTestAliasAgainError1.db
|
||||
TESTFILES += ../dbStaticTestAliasAgainError2.db
|
||||
TESTFILES += ../dbStaticTestRemove.db
|
||||
TESTS += dbStaticTest
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <dbUnitTest.h>
|
||||
#include <testMain.h>
|
||||
#include <epicsString.h>
|
||||
#include <iocsh.h>
|
||||
|
||||
|
||||
static void testEntryRemoved(const char *pv)
|
||||
@ -321,16 +322,19 @@ static void testDbVerify(const char *record)
|
||||
dbFinishEntry(&entry);
|
||||
}
|
||||
|
||||
static void testWrongAliasRecord(const char *filename)
|
||||
static void testReadDatabase(const char *filename, int expectToFail)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
long status;
|
||||
dbPath(pdbbase,"." OSI_PATH_LIST_SEPARATOR "..");
|
||||
dbOpenFile(pdbbase, filename, &fp);
|
||||
if(!fp) {
|
||||
testAbort("Unable to read %s", filename);
|
||||
testAbort("Unable to open %s", filename);
|
||||
}
|
||||
testOk(dbReadDatabaseFP(&pdbbase, fp, NULL, NULL) != 0,
|
||||
"Wrong alias record in %s is expected to fail", filename);
|
||||
status = dbReadDatabaseFP(&pdbbase, fp, NULL, NULL);
|
||||
testOk(!status == !expectToFail,
|
||||
"Reading %s%s", filename,
|
||||
expectToFail ? " is expected to fail" : "");
|
||||
}
|
||||
|
||||
void dbTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
@ -341,7 +345,7 @@ MAIN(dbStaticTest)
|
||||
char *ldirDup;
|
||||
FILE *fp = NULL;
|
||||
|
||||
testPlan(340);
|
||||
testPlan(350);
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
|
||||
@ -370,8 +374,21 @@ MAIN(dbStaticTest)
|
||||
}
|
||||
free(ldirDup);
|
||||
|
||||
testWrongAliasRecord("dbStaticTestAlias1.db");
|
||||
testWrongAliasRecord("dbStaticTestAlias2.db");
|
||||
testReadDatabase("dbStaticTestAlias1.db", 1);
|
||||
testReadDatabase("dbStaticTestAlias2.db", 1);
|
||||
|
||||
/* Test re-defining aliases */
|
||||
testReadDatabase("dbStaticTestAliasAgain1.db", 0);
|
||||
testReadDatabase("dbStaticTestAliasAgain1.db", 0);
|
||||
testReadDatabase("dbStaticTestAliasAgain2.db", 0);
|
||||
testReadDatabase("dbStaticTestAliasAgain2.db", 0);
|
||||
testReadDatabase("dbStaticTestAliasAgain3.db", 0);
|
||||
testReadDatabase("dbStaticTestAliasAgain3.db", 0);
|
||||
testReadDatabase("dbStaticTestAliasAgainError1.db", 1);
|
||||
testReadDatabase("dbStaticTestAliasAgainError2.db", 1);
|
||||
iocshCmd("var dbRecordsOnceOnly 1");
|
||||
testReadDatabase("dbStaticTestAliasAgain2.db", 1);
|
||||
testReadDatabase("dbStaticTestAliasAgain3.db", 1);
|
||||
|
||||
testEntry("testrec.VAL");
|
||||
testEntry("testalias.VAL");
|
||||
|
4
modules/database/test/ioc/db/dbStaticTestAliasAgain1.db
Normal file
4
modules/database/test/ioc/db/dbStaticTestAliasAgain1.db
Normal file
@ -0,0 +1,4 @@
|
||||
# Test re-load alias in record
|
||||
record(x, "testrecAgain") {
|
||||
alias("testaliasAgain1")
|
||||
}
|
2
modules/database/test/ioc/db/dbStaticTestAliasAgain2.db
Normal file
2
modules/database/test/ioc/db/dbStaticTestAliasAgain2.db
Normal file
@ -0,0 +1,2 @@
|
||||
# Test re-load alias for record
|
||||
alias("testrecAgain", "testaliasAgain2")
|
2
modules/database/test/ioc/db/dbStaticTestAliasAgain3.db
Normal file
2
modules/database/test/ioc/db/dbStaticTestAliasAgain3.db
Normal file
@ -0,0 +1,2 @@
|
||||
# Test re-load alias for alias
|
||||
alias("testaliasAgain2", "testaliasAgain3")
|
@ -0,0 +1,2 @@
|
||||
# ERROR: alias using name of exising alias for different record
|
||||
alias("testrec", "testaliasAgain1")
|
@ -0,0 +1,2 @@
|
||||
# ERROR: alias using name of exising record fails
|
||||
alias("testrecAgain", "testrec")
|
Reference in New Issue
Block a user