Research Division EED/Controls Software<P> Release Note 135.0<P> OA and LAL Databases PC User Access

Research Division EED/Controls Software

Release Note 135.0

OA and LAL Databases PC User Access

Julia Kozlovsky

August 23, 1993

Introduction

The Epicure Device Database holds information about devices and provides a way of manipulating and accessing devices for data acquisition. Several sets of routines exist for accessing the database via VAX/VMS. However, accessing the Database with the same routines via the network from PCs is impossible, since due to system differences between PC and VAX, the format of the routines is not compatible. It was therefore decided to keep the OA and LAL database files in an area accessible to the individual PCs via network and to write a set of database accessing routines that are PC-specific. The new db_pc_ routines are the PC equivalent of the db_ routines for the VAX.

Overview

The Device Database is a dual database which has both centralized and distributed elements. The Source database is the master copy which is maintained on a single network node, whereas multiple copies of the OA and LAL databases are distributed to several network nodes. The Optimized Access (OA) and the Look-Aside-List (LAL) databases are derived from the source database. They are optimized by using hash tables for device lookup, storing the database records in contiguous memory and sharing information between devices. The VAX users can get database information by using the Epicure db_, dbsa_, or dbrpt_ services.

In order to be able to access database information via PC, it was necessary to write a PC-specific equivalent of db_ routines, since there are several system-specific differences (disscussed below) which make it impossible to use db_ calls on PCs. OA and LAL database files will be stored in an area accessible to the PCs via network and the users will use db_pc_ routines to access database information in much the same way as they did from the VAX.

PC Specifics

The new db_pc_ routines are implemented in Borland C++ and read the OA and LAL files directly (instead of using the database server like db_ routines do), so they are dependant on the particular features of the system and the software. The effort was made to make the db_pc_ routines as similar to the db_ routines (from the point of view of the user) as possible, but the user must be mindful of several important differences. First, some data structures changed because data types had to be converted: All the data structures for db_pc_ calls are in the following header files:

''dbpcuser.h''
- property and attribute codes; some property and attribute structures and data types;
''oapcdata.h''
- more property and attribute data types;
''dapspc.h''
- DAP structures;
''ftdpc.h''
- FTD structures;
Another difference to note is that device name strings are no longer passed in by descriptors, but as a NULL-terminated string of characters.

Users must also remember that certain properties defined in ''dbpcuser.h'' are not defined for OA and LAL databases:

Querying the database

An application must do the following to retrieve the information from the database via PC:
  1. Open OA and LAL files, verify their version numbers and build dates, reserve memory and read in the hash root for quick data lookup (db_pc_init);
  2. Build a list of database requests (db_pc_add_request_*);
  3. Execute the list: read in the data an keep it in reserved memory (db_pc_process_wait);
  4. Get the data (db_pc_get_data_*);
  5. Free the request list and the memory reserved for returned data (db_pc_free_request_list). Attention: after this routine is called, the data that was retrieved by db_pc_get_data_pointer is wiped out;
  6. When the database session is over, release all the memory reserved for the hash roots (db_pc_completion).
The application must include the .h'' header file which contains the function prototypes for db_pc_ calls.

Note, that such calls as db_pc_name_to_di, db_pc_di_to_name and db_pc_get_dirange do not have to be put on a request list, since they request information and return it all in one shot.

Routines Descriptions

Note: error reporting is handled differently for the db_pc_ routines than for the db_ routines: any file or memory allocation error is reported immediately and the program is interrupted, whereas all other errors are only displayed after calling db_pc_signal_failure(status) or SIGNAL_FAILURE(status). For all calls, status is returned as either 0 (normal) or 1 (error), and only after the status is passed to signal_failure routines, the specific error is reported. The exact error codes are never visible to the user, only a text message is displayed.

status = db_pc_init()
Open the OA and LAL files and verify their versions and build dates, allocate memory and read in the hash root, providing quick data lookup. Possible errors:

status = db_pc_di_to_name(di, name)
Return the name of a device given its device index.

di
- device index. A longword passed by value.
name
- device name. A DB_S_NAME+1-character-long, null-terminated string passed by value.
Possible errors:

status = db_pc_name_to_di(name, di)
Return the index of a device given its name.

name
- device name. A DB_S_NAME+1-character-long, null-terminated string passed by value.
di
- device index. A longword passed by reference.
Possible errors:

status = db_pc_get_dirange(low_di, high_di)
This routine returns the minimum and the maximum DIs in the OA and LAL databases.

low_di
- lowest DI in the OA and LAL databases. A longword passed by reference.
high_di
- highest DI in the OA and LAL databases. A longword passed by reference.
Possible errors:

status = db_pc_add_request_di(di, prop, [attr
, handle)] This routine adds a request to the Database request list for the program. The device is specified by its device index.

di
- device index. A longword passed by value.
prop
- property code (DB_C_PRP_...). Passed by value.
attr
- attribute code (DB_C_ATR..., use DB_C_ATR_NONE or 0 for those properties with no attributes). Passed by value.
handle
- address of a longword to receive the returned identifier to be used with the db_pc_get_data_ routines. Passed by reference.
Possible errors:

status = db_pc_add_request_name(name, prop, [attr
, handle)] This routine adds a request to the Database request list for the program. The device is specified by its name.

name
- device name. A DB_S_NAME+1-character-long, null-terminated string passed by value.
prop
- property code (DB_C_PRP_...). Passed by value.
attr
- attribute code (DB_C_ATR..., use DB_C_ATR_NONE or 0 for those properties with no attributes). Passed by value.
handle
- address of a longword to receive the returned identifier to be used with the db_pc_get_data_ routines. Passed by reference.
Possible errors:

status = db_pc_process_wait()
Call after the request list is completed to process all requests. The routine returns when all the data is read into the internal memory. Possible errors:

status = db_pc_get_data_pointer(handle, datptr, [retlen
)] This routine returns a pointer to the requested data which is located in temporarily allocated memory.

handle
- retrieval identifier from the db_pc_add_request_ routines for the requested data. A longword passed by value.
datptr
- address of a pointer to the data in the internal memory. The pointer itself is passed by reference.
retlen
- actual length of the returned data (in bytes). A longword passed by reference.
Possible errors:

status = db_pc_get_data(handle, [maxlen
, retbuf, [retlen])] This routine copies the requested data location into a user-provided buffer. The user has the responsibility to reserve enough memory.

handle
- retrieval identifier from the db_pc_add_request_ routines for the requested data. A longword passed by value.
maxlen
- size of the buffer (in bytes) for the returned data. A longword passed by value.
retbuf
- the buffer in which the data is to be returned. Passed by reference.
retlen
- actual length of the returned data (in bytes). A longword passed by reference.
Possible errors:

status = db_pc_get_data_length(handle, retlen)
This routine returns the length of the requested data.

handle
- retrieval identifier from the db_pc_add_request_ routines for the requested data. A longword passed by value.
retlen
- actual length of the returned data (in bytes). A longword passed by reference.
Possible errors:

status = db_pc_free_request_list()
Free all of the memory allocated for the requests and the returned data, reset the flags. Possible errors:

status = db_pc_completion()
This routine must be called after the database session is over. Free the memory allocated for the hash roots. Possible errors:

db_pc_signal_failure(status)
If one of the db_pc_ routines has returned an error, report the exact error.

status
- as returned by other db_pc_ calls: 0 (normal) or 1 (error). The exact error codes are hidden, only a text message is displayed.

The Demo Program

This program demonstrates the use of most db_pc_ routines. It gets property and attribute information from two database devices. Note how the data is handled differently depending on the data type.

/* this demo program demonstrates the use of db_pc_ routines */
#include "dbpc.h"       	/* db_pc_ routine decalarations etc. */

main () { int sts; /* status returned from db_pc_ calls */ /* names of two database devices */ char device_name_one[DB_S_NAME+1] = "PE3SEM " char device_name_two[DB_S_NAME+1]; long di_one, di_two = 4199769; /* indexes of two database device */ long lo_di; /* lowest allocated device index */ long hi_di; /* highest allocated device index */ long source_class_handle, addressing_handle, scaling_handle, beamline_handle, dap_handle;/* various request handles */ char source[DB_S_SOURCE_CLASS]; /* device source class */ struct { union { struct DB_ADDRESSING addr; struct DB_SYNTHETIC_ADDR synaddr; }addrs; union dap_u dap; } *addressing; /* holds addressing and dap information */ union { struct DB_ANALOG_SCALING analog; struct DB_ACNET_PDB pdb; } *device_scaling; /* holds scaling information */ struct DB_BEAMLINES *beamline; /* pointer to a beamline structure */ long dap; /* device dap type */ unsigned long ret_lng; /* length of the returned data */

/* open the database files, compare serial numbers, * allocate dynamic memory and read the hash root into it */ sts = db_pc_init(); SIGNAL_FAILURE(sts);

/* for a given device name give device index */ sts = db_pc_name_to_di(device_name_one, &di_one); SIGNAL_FAILURE(sts);

/* for a given device index, give device name */ sts = db_pc_di_to_name(di_two, device_name_two); SIGNAL_FAILURE(sts);

/* build a list of database requests, using two * different types of _add_request_ calls */ sts = db_pc_add_request_di(di_one, DB_C_PRP_READING, DB_C_ATR_SOURCE_CLASS, &source_class_handle); SIGNAL_FAILURE(sts); sts = db_pc_add_request_di(di_one, DB_C_PRP_READING, DB_C_ATR_ADDRESSING, &addressing_handle); SIGNAL_FAILURE(sts); sts = db_pc_add_request_di(di_one, DB_C_PRP_READING, DB_C_ATR_SCALING, &scaling_handle); SIGNAL_FAILURE(sts); sts = db_pc_add_request_name(device_name_two, DB_C_PRP_BEAMLINE, 0, &beamline_handle); SIGNAL_FAILURE(sts); sts = db_pc_add_request_name(device_name_two, DB_C_PRP_DAP_TYPE, 0, &dap_handle); SIGNAL_FAILURE(sts);

/* process the request list */ sts = db_pc_process_wait(); SIGNAL_FAILURE(sts);

/* get the data */ /* note that one could also get source by using the _get_data_pointer call */ sts = db_pc_get_data(source_class_handle, sizeof(source), source, &ret_lng); SIGNAL_FAILURE(sts); /* one could also get the addressing by using the _get_data call */ sts = db_pc_get_data_pointer(addressing_handle, &addressing, &ret_lng); SIGNAL_FAILURE(sts); /* same as above */ sts = db_pc_get_data_pointer(scaling_handle, &device_scaling, &ret_lng); SIGNAL_FAILURE(sts); /* ATTENTION: the beamline structure is of undetermined length, * so it is always necessary to use the _get_data_pointer call */ sts = db_pc_get_data_pointer(beamline_handle, &beamline, &ret_lng); SIGNAL_FAILURE(sts); /* for dap, one could also use the _get_data_pointer call */ sts = db_pc_get_data(dap_handle, sizeof(long), &dap, &ret_lng); SIGNAL_FAILURE(sts);

/* delete the request list, free memory etc. */ sts = db_pc_free_request_list(); SIGNAL_FAILURE(sts);

/* return the current high/low device index values */ sts = db_pc_get_dirange(&lo_di, &hi_di); SIGNAL_FAILURE(sts);

/* The session is over, free memory */ sts = db_pc_completion(); SIGNAL_FAILURE(sts); return(0); }

Security, Privacy, Legal

rwest@fsus04.fnal.gov