Static database access provides a simplified interface to a database, i.e. much of the complexity is hidden. All choice fields are accesses via a common type called DCT_MENU. A set of routines are provided to simplify access to link fields. All fields can be accessed as character strings. This interface is called static database access because it can be used to access an uninitialized, as well as an initialized database.
Database Configuration Tools (DCTs) should manipulate an EPICS database only via the static database access interface. An IOC database is created on a Unix system via a database configuration tool and stored in a Unix file with a file extension of ".database". Two routines (dbRead and dbWrite) access a Unix database file. These routines read/write a database file to/from a memory resident EPICS database. All other access routines manipulate the memory resident database.
An include file dbStaticLib.h contains all the definitions needed to use the static database access library. Two structures (DBBASE and DBENTRY) are used to access a database. The fields in these structures should not be accessed directly. They are used by the static database access library to keep state information for the caller.
#include <dbStaticLib.h> DBBASE *pdb; pdb=dbAllocBase();
DBENTRY *pentry; pentry=dbAllocEntry(pdb);Most static access to a database is via a DBENTRY structure. As many structures as desired can be allocated, each associated with a particular database. The user should NEVER access the fields of DBENTRY directly.
Most access routines accept an argument which contains the address of a DBENTRY. Each routine uses this structure to locate the information it needs and gives values to as many fields in this structure as possible. All other fields are set to NULL.
The DCT field types are:
The field type DCT_MENU has an associated set of ASCII strings defining the choices. Routines are available for accessing menu fields. A menu field can also be accessed via the dbGetString, dbPutString, dbVerify, and dbGetRange routines.
The field type DCT_MENUFORM is like DCT_MENU but in addition the field has an associated link field. The information for the link field can be entered via a set of form manipulation fields.
DCT_INLINK (input), DCT_OUTLINK (output), and DCT_FWDLINK (forward) specify that the field is a link structure as defined in dbStaticLib.h. Link fields, which have an associated set of static access routines, are described in more detail in the next subsection. A field that has any of these types can also be accessed via the dbGetString, dbPutString, dbVerify, and dbGetRange routines.
The routines dbGetString, dbPutString, and dbVerify can be used for link fields but should not be used to prompt the user for PV or DEVICE links. They are meant to be used for constant links or to save and restore ASCII versions of the database.
void dbDumpRecords(DBBASE *pdbbase) { DBENTRY *pdbentry; long status; pdbentry = dbAllocEntry(pdbbase); status = dbFirstRecdes(pdbentry); if(status) {printf("No record descriptions\n");return;} while(!status) { printf("record type: %s",dbGetRecdesName (pdbentry)); status = dbFirstRecord(pdbentry); if(status) printf(" No Records\n"); else printf("\n Record: %s\n", dbGetRecordName(pdbentry)); while(!status) { status = dbFirstFielddes(pdbentry,TRUE); if(status) printf(" No Fields\n"); while(!status) { printf(" %s:%s",dbGetFieldName(pdbentry), dbGetString(pdbentry)); status=dbNextFielddes(pdbentry,TRUE); } status = dbNextRecord(pdbentry); } status = dbNextRecdes(pdbentry); } printf("End of all Records\n"); dbFreeEntry(pdbentry); }
DBBASE *dbAllocBase(void); void dbFreeBase(DBBASE *pdbbase); DBENTRY *dbAllocEntry(DBBASE *pdbbase); void dbFreeEntry(DBENTRY *pdbentry); void dbInitEntry(DBBASE *pdbbase,DBENTRY *pdbentry); void dbFinishEntry(DBENTRY *pdbentry); DBENTRY *dbCopyEntry(DBENTRY *pdbentry);These routines allocate and free DBBASE and DBENTRY structures. dbAllocBase allocates and initializes a memory resident database. dbFreebase frees all memory used by the database. Note that it is possible to work with more then one memory resident database at the same time.
The user can allocate and free DBENTRY structures as necessary. Each DBENTRY is, however, tied to a particular database.
The routines dbInitEntry and dbFinishEntry are provided in case the user wants to allocate a DBENTRY structure on the stack.
The routine dbCopyEntry allocates a new entry, via a call to dbAllocEntry, copies the information from the original entry, and returns the result.
long dbRead(DBBASE *pdbbase,FILE *fp); long dbWrite(DBBASE *pdbbase,FILE *fpdctsdr,FILE *fp);dbRead reads a file containing any combination of self defining records and adds the information to the memory resident database. dbWrite writes the memory resident database into a file. dbWrite requires two file pointers. The first is a file containing record description information. The second references the output database file.
Although an arbitrary number of database files can be read each must contain the same set of record descriptions. If any mismatch occurs dbRead will return an error. If dbRead returns a non zero value do not call any of the other routines described in this chapter.
long dbFindRecdes(DBENTRY *pdbentry,char *recdesname); long dbFirstRecdes(DBENTRY *pdbentry); long dbNextRecdes(DBENTRY *pdbentry); char *dbGetRecdesName(DBENTRY *pdbentry); int dbGetNRecdes(DBENTRY *pdbentry); long dbCopyRecdes(DBENTRY *from,DBENTRY *to);These routines manipulate the record description. An EPICS database consists of an arbitrary number of record descriptions. The above routines provide access to the following information:
long dbCreateRecord(DBENTRY *pdbentry,char *precordName); long dbDeleteRecord(DBENTRY *pdbentry); long dbFindRecord(DBENTRY *pdbentry,char *precordName); long dbFirstRecord(DBENTRY *pdbentry); /*first of record type*/ long dbNextRecord(DBENTRY *pdbentry); int dbGetNRecords(DBENTRY *pdbentry); char *dbGetRecordName(DBENTRY *pdbentry); long dbRenameRecord(DBENTRY *pdbentry, char *newname) long dbCopyRecord(DBENTRY *from,DBENTRY *to);These routines are used to create, delete, locate, etc. record instances. Note that other than dbFindRecord all routines assume that one of the record description routines has been used to locate a record type. dbFindRecord also calls dbFindField if the record name includes an extension.
Routines are provided for accessing the following information:
long dbFindField(DBENTRY *pdbentry,char *pfieldName); long dbFirstFielddes(DBENTRY *pdbentry,int dctonly); long dbNextFielddes(DBENTRY *pdbentry,int dctonly); int dbGetFieldType(DBENTRY *pdbentry); int dbGetNFields(DBENTRY *pdbentry,int dctonly); char *dbGetFieldName(DBENTRY *pdbentry); char *dbGetPrompt(DBENTRY *pdbentry); int dbGetPromptGroup(DBENTRY *pdbentry);These routines manipulate the field descriptions for a particular record type. Note that if a record instance has previously been located they also update the location of the field itself.
char *dbGetString(DBENTRY *pdbentry); long dbPutString(DBENTRY *pdbentry,char *pstring); char *dbVerify(DBENTRY *pdbentry,char *pstring); char *dbGetRange(DBENTRY *pdbentry); int dbIsDefaultValue(DBENTRY *pdbentry);These routines are used to get or change field values. They work on all the database field types except DCT_NOACCESS but should NOT be used to prompt the user for information for DCT_MENU, DCT_MENUFORM, or DCT_LINK_xxx fields. dbVerify returns (NULL, a message) if the string is (valid, invalid). Please note that the strings returned are volatile, i.e. the next call to a routines that returns a string will overwrite the value returned by a previous call. Thus it is the caller's responsibility to copy the strings if the value must be kept.
DCT_MENU, DCT_MENUFORM and DCT_LINK_xxx fields can be manipulated via routines described in the following sections. If, however dbGetString and dbPutString are used they do work correctly. For these field types they are intended to be used only for creating and restoring ASCII versions of a database.
char **dbGetChoices(DBENTRY *pdbentry); int dbGetMenuIndex(DBENTRY *pdbentry); long dbPutMenuIndex(DBENTRY *pdbentry,int index); int dbGetNMenuChoices(DBENTRY *pdbentry); long dbCopyMenu(DBENTRY *from,DBENTRY *to);These are the routines that should be used for DCT_MENU and DCT_MENUFORM fields.
int dbAllocForm(DBENTRY *pdbentry) long dbFreeForm(DBENTRY *pdbentry) char **dbGetFormPrompt(DBENTRY *pdbentry) char **dbGetFormValue(DBENTRY *pdbentry) long dbPutForm(DBENTRY *pdbentry, char **value) char **dbVerifyForm(DBENTRY *pdbentry,char **value)dbAllocForm allocates storage needed to manipulate forms. The return value is the number of elements in the form. dbGetFormPrompt returns a pointer to an array of pointers to character strings specifying the prompt string. dbGetFormValue returns the current values. dbPutForm, which can use the same array of values returned by dbGetForm, sets new values. dbVerifyForm can be called to verify user input. It returns NULL if no errors are present. If errors are present it returns a pointer to an array of character strings containing error messages. Lines in error have a message and correct lines have a NULL string. The following is skeleton code showing use of these routines:
char **value; char **prompt; char **error; int n; ... n = dbAllocForm(pdbentry); if(n<=0) {<Error>} prompt = dbGetFormPrompt(pdbentry); value = dbGetFormValue(pdbentry); for(i=0; i<n; i++) { printf("%s (%s) : \n",prompt[i],value[i]); scanf("%s",value[i]); } if(dbPutForm(pdbentry,value)) { error = dbVerifyForm(pdbentry,value); if(error) for(i=0; i<n; i++) { if(error[i]) printf("Error: %s (%s) %s\n", prompt[i], value[i], error[i]); } } dbFreeForm(pdbentry);All value strings are MAX_STRING_SIZE in length.
A set of form calls for a particular DBENTRY, MUST begin with a call to dbAllocForm and end with a call to dbFreeForm. The values returned by dbGetFormPrompt, dbGetFormValue, and dbVerifyForm are valid only between the calls to dbAllocForm and dbFreeForm.
int dbGetNLinks(DBENTRY *pdbentry); long dbGetLinkField(DBENTRY *pdbentry,int index) int dbGetLinkType(DBENTRY *pdbentry);These are routines for manipulating DCT_xxxLINK fields. dbGetNLinks and dbGetLinkField are used to walk through all the link fields of a record. dbGetLinkType returns one of the values: DCT_LINK_CONSTANT, DCT_LINK_FORM, DCT_LINK_PV, or DCT_LINK_DEVICE.
long dbCvtLinkToConstant(DBENTRY *pdbentry); long dbCvtLinkToPvlink(DBENTRY *pdbentry); long dbPutPvlink(DBENTRY *pdbentry,int pp,int ms,char *pvname); long dbGetPvlink(DBENTRY *pdbentry,int *pp,int *ms,char *pvname);These routines should be used for modifying DCT_LINK_CONSTANT or DCT_LINK_PV links. They should not be used for DCT_LINK_FORM or DCT_LINK_DEVICE links, which should be processed via the associated DCT_MENUFORM field described above.
void dbDumpRecords(DBBASE *pdbbase, char *recdesname,int modOnly); void dbDumpPvd(DBBASE *pdbbase); void dbReportDeviceConfig(DBBASE *pdbbase,FILE *report)
atdb <dctsdr> <database>e.g.
atdb default.dctsdr example.database < example.rptThis program. which accepts its input from stdin, creates a new database file and populates it with records defined in the ASCII file. The ASCII file is a file in the old DCT short form format or a file generated by the dbta utility with the -s option.
It should also be noted that instead of terminating records with a ^L (the old short form report), it is also permissible to terminate records with $$end. Thus, in addition to short form reports, the following is valid input to atdb:
PV: <record name> Type: <record type> <field name> <value> ... <as many fields as desired> $$end PV: <record name> Type: <record type> <field name> <value> ... <as many fields as desired> $$endUse dbta, described next, on an existing database without the -s option to see an example.
...
dbta [-v] [-s] <filename>e.g.
dbta -s example.database > newexample.rptThis utility generates an ASCII file from a database file. If -v is specified then all prompt fields are generated, otherwise only fields with non-default values are displayed. If -s is specified, then the generated file can be used as input to the old DCT or to atdb.