Ingres CL PM
From Ingres Community Wiki
|
Ingres Compatability Library |
General Library Specification PM
Abstract
This is the specification for a General Library facility that provides a simple and general interface for looking up name/value pairs stored in text files. It is used for system configuration and server startup options, and may have other uses.
Revision: 1.0, 30-Jul-94
Document History
- Revision 1.0, 30-Jul-94
- Created from proposal approved on 16-oct-92
- PMhost and PMexpToRegExp added 21-may-93
- Multi-context PM arch approved, details not yet seen. (9-jul-93) See Appendix A.
Specification
Introduction
NOTE: A proposal was in flux at the time the original author of PM left the company. It is included in Appendix A.
The PM ("Parameter Management") routines provide a standard interface for looking up character-string name/value pairs stored in human-readable text files. Furthermore, the parameter name syntax and look-up algorithm supported by the PM functions provide a type of defaulting which is similar to that provided by X-windows. The PM file syntax and semantics (described below) were approved by the Language Review Committee in August, 1992.
Library
GL
Intended Uses
The PM module is intended for use by any INGRES program to look up character strings associated with alpha-numeric names which are stored in text files.
Assumptions
Since the PM function which loads the contents of a PM data file into memory relies on SI, it will cause the calling process to block intermittently while the file is being read. This is probably acceptable for most applications; however the implementor should be aware of this fact and make certain that it is acceptable to block momentarily when the PMload() function is called.
By convention, all PM functions which return pointers to strings will allocate the memory required by those strings internally. Moreover callers of PM functions must not free or modify the contents of such memory explicitly. Rather, PMfree() must be called to free memory allocated by PM.
Prototypes & Concepts
| PM Data File | A human-readable text file recognized by PMload(). A PM data file may contain an arbitrary number of "Resource Specifications". |
| Default Configuration Resource Files | Two specific PM data files which are read by PMload() whenever it is called with a NULL LOCATION argument, named "config.dat" and "protect.dat".
Note that the two files will always be loaded in the order they are named here. When PMload() is called with a NULL LOCATION argument, it will first look for these files in the directory pointed to by the II_CONFIG symbol, if defined. If II_CONFIG isn't defined, PMload() will look for the files in $II_SYSTEM/ingres/files (on in the equivalent VMS directory). By convention, these default configuration resource files will be used to store configuration data used by all INGRES installations which share the same value of II_SYSTEM or II_CONFIG. This usage of "config.dat" and "protect.dat" as the default PM data files for the the PMload() function was approved by the Language Review Committee in August, 1992. |
| Resource Specification | A "Resource Name," followed by an "Assignment Operator," and a "Resource Value." |
| Resource Name | A non-zero number of "Resource Name Components," beginning in the first column of the file. Any line which does not begin in the first column shall be interpreted as the continuation of a multi-line "Resource Value." If more than one name component is present, they must separated by periods ("."). Resource names may not contain whitespace. |
| Resource Name Component | Any "Name String" or a single asterisk ("*"). |
| Name String | A non-zero length string of alpha-numeric characters or underscores ("_"), beginning with an alphabetic character. |
| Assignment Operators | : = |
| Resource Value | One or more "Value Strings" separated by whitespace. A resource value is evaluated by concatenating all value strings which compose it. |
| Value String | Any number of concatenated "Undelimited Value Strings" and "Delimited Value Strings." A value string which consists only of whitespace evaluates to an empty (NULL terminated, zero-length) string. When two delimited value strings are concatenated on the same line, they must be separated by one or more whitespace characters. |
| Undelimited Value String | One or more "Plain Value Strings" (other than the null string) or "Substitution Symbols." Any whitespace characters embedded in undelimited value strings will be ignored. An undelimited value string is evaluated by concatentating its components. |
| Plain Value String | A non-zero length string of printable characters which does not contain newlines or any of the following reserved characters: |
| & " ' \\ $ # | Any whitespace characters contained by plain value strings will be ignored. |
| Substitution Symbol | A resource name enclosed by parentheses and immediately preceded by '$'. Any number of whitespace characters may appear between the resource name and either of the enclosing parentheses (and will be ignored). Substitution symbols are replaced during evaluation with the value of the enclosed resource name. An error will be generated if an undefined symbol is referenced by a substitution symbol, although a resource which is defined as NULL may be referenced. |
| Delimited String | An arbitrary-length string of printable characters which must begin and end with a single quote. Delimited strings may not contain newlines. They are evaluated by discarding the enclosing quotes and applying the following rules from left to right: |
| '' | If a single-quote needs to be included in a delimited string, it must be preceded by a backslash. The backslash/single-quote sequence will evaluate to a single-quote. |
| \ | If a backslash is encountered, it may be followed by a single quote, three octal digits, another backslash, or one of the following characters: 'n', 't', 'r', 'f', or 'b'. The entire sequence will be evaluated using the obvious subset of C string literal semantics. The one exception is the octal sequence \000, which is not allowed, since it would (prematurely) terminate any string containing it. |
| . | Every other character evaluates to itself (with no case conversion). |
| Comment Syntax | Everything following the first '#' on any line of a PM data file (except within delimited value strings) will be treated as a comment (i.e. ignored). |
| Resource Request | A syntactic super-set of resource names which is accepted as an argument by PMdelete(), PMget(), and PMinsert(). The syntactic extensions which define resource requests are: |
| $ | '$' may appear in place of any number of resource name components. Every instance of '$' in a resource request encountered by a function accepting it as an argument will be replaced with the corresponding "Default Resource Name Component" before the request is processed. For components for which there is no default set, each instance of '$' will replaced with '*'. |
| ! | '!' may (only) appear in place of the first (leftmost) resource name component. When '!' is thus encountered by a function which accepts a resource request as an argument, the remaining components of the request (after the '!') will be prepended with all currently set "Default Resource Name Components," separated by periods ("."). The character '*' will be inserted for all intermediate defaults which have not been explicitly set by call(s) to PMsetDefault(). For example, if defaults have been set for the first and fourth resource name components ("foo" and "bar", respectively) any resource request which begins with '!' would be prepended with the string "foo.*.*.bar" before being processed. |
| Resource Expression | The same as a resource request, with the addition of an optional wild card character ('%') in place of any component. |
| Default Resource Name Component | The PMsetDefault() function can be used to set default values for unspecified components of resource requests which are processed by certain PM functions. |
| Unspecified Component of a Resource Request | An instance of '$' or '!' in a resource request. |
| Case-Conversion of Resource Name | All PM resource names are converted to upper case before being loaded into memory or processed in any other way by PM functions. This means, for instance, that any resource name specified in lower or mixed case in a PM data file and loaded with PMload() will be returned in upper case by PMscan(). No case conversion is applied to resource values. |
| Default Configuration Files | Two files named "config.dat" and "protect.dat" (located in $II_SYSTEM/ingres/files or the directory pointed to by $II_CONFIG) will be loaded (in the order named above) by PMload(), if no LOCATION argument is supplied. These files generally contain configuration data which is global to one or more installations. |
| Resource Component Index | An integer which identifies a component of a PM resource name, request or pattern. Resource name component indexes begin with 0 at the leftmost component and increase upward. |
Header File <pm.h>
The header file <pm.h> must be included before any of the PM functions are called. It defines the following:
PM Constants
| PM_FILE_BAD | STATUS returned by PMload() to indicate that a PM data file contains a syntax error. |
| PM_FOUND | STATUS returned by PMinsert() to indicate that the named PM resource could be not be inserted since it already exists. |
| PM_INDEX_BAD | STATUS returned by PMsetDefault() to indicate that an illegal name component index was passed to the function. |
| PM_NOT_FOUND | STATUS returned by several PM functions to indicate that no PM resource could be found to satisfy the requested action. |
| PM_REGEXP_BAD | STATUS returned by PMscan() to indicate that an error occured while trying to parse the regular expression passed to the function. |
PM_SCAN_REC - structure used to stored PMscan() state
The contents of this structure should not be accessed by client code.
typedef struct
{
...
} PM_SCAN_REC;
PM_ERR_FUNC - error processing function called by PMload()
A function of this type must be declared and passed to PMload() by every caller.
typedef void PM_ERR_FUNC( STATUS status, nat nargs, ER_ARGUMENT *args );
Executable Interface
The following functions are provided.
PMdelete - delete a PM resource from memory
Delete a PM resource corresponding to the specified request from the set of resources loaded into memory using PMload() and/or PMinsert(). Calling PMdelete() will not free dynamically allocated memory associated with the deleted resource.
Inputs:
| request | a string containing the PM resource request describing the resource to be deleted. |
Outputs:
| None |
Returns:
| OK | a PM resource was successfully deleted. |
| PM_NOT_FOUND | no PM resource corresponding to the request was found. |
Prototype:
STATUS PMdelete( char *request );
PMexpToRegExp() -- convert resource expression to a regular expression
Returns a pointer to an internally allocated buffer containing an egrep-style regular expression which matches the same set of resources matched by a specified resource expression. The syntax of a resource expression is the same as that of a resource request, with the addition of an optional wild card character ('%') in place of any component. The egrep regular expression returned by PMexpToRegExp() can be used as an input the PMscan() function.
Inputs:
| s | The PM expression to be converted. |
Outputs:
| None. |
Returns:
| An egrep-style regular expression. |
Prototype
char * PMexpToRegExp( char *s )
PMfree - erase previously loaded PM resources and free associated memory
Erase all PM resources previously loaded with PMload() and PMinsert() and free the associated dynamically allocated memory, including all strings allocated and returned by PMget(), PMgetDefault(), and PMscan(). After calling PMfree(), PMinit() must be called (again) before any other PM functions.
Inputs:
| None |
Outputs:
| None |
Returns:
| None |
Prototype:
void PMfree( void );
PMget - get a PM resource matching a resource reques
Return the value of a PM resource which matches the specified resource request. The string which is returned by PMget() is allocated internally and must only be freed by calling PMfree() (which frees all memory allocated by PM functions since the last call to PMinit()). Callers may safely reference any strings returned by this function until PMfree() is called.
Inputs:
| request | a string containing a PM resource request. |
Outputs:
| value | a string containing the value of the matching PM resource. |
Returns:
| OK | a matching PM resource was found. |
| PM_NOT_FOUND | no matching PM resource was found. |
Prototype:
STATUS PMget( char *name, char **value );
PMgetDefault - get a default PM resource name component given its index
Get the default PM name component corresponding to an index. Default resource name component indexes start at the leftmost component (0) and increase upward. Default resource name components can be may by calling PMsetDefault(). The string which is returned by PMgetDefault() is allocated internally and must only be freed by calling PMfree() (which frees all memory allocated by PM functions since the last call to PMinit()). Callers may safely reference any strings returned by this function until PMfree() is called.
Inputs:
| idx | index of a default PM name component. |
Outputs:
| None |
Returns:
| a string containing the specified default name component. | |
| NULL | no default name component set for the specified index. |
Prototype:
char *PMgetDefault( i4 idx );
PMhost() -- return a unique PM host identifier
Returns a pointer to an internally allocated buffer containing a valid resource name component which uniquely identifies the local host with respect to others which may share the same default configuration resource files. Because values which are returned by PMhost() are guaranteed to be syntactically valid resource name components, they may be embedded in resource requests or resource names passed to other PM functions as arguments.
Inputs:
| None. |
Outputs:
| None. |
Returns:
| A unique PM host identifier string. |
Prototype:
char *PMhost( void );
PMinit - initialize the PM data structures
PMinit() must be called prior to any other PM functions.
Inputs:
| None |
Outputs:
| None |
Returns:
| None |
Prototype:
void PMinit( void )
PMinsert - set the value of a PM resource
Add a PM resource corresponding to the specified resource request to the set of resources loaded into memory. An existing resource must be deleted using PMdelete() before it can be reset with PMinsert().
Inputs:
| resource | a string containing a PM resource request. |
| value | a string containing the value of the PM resource. |
Outputs:
| None |
Returns:
| OK | The PM resource was added successfully. |
| PM_FOUND | The PM resource already exists. |
Prototype:
STATUS PMinsert( char *name, char *value );
PMload - load the contents of a PM data file into memory
Load the contents of a PM data file into memory for subsequent look-ups using PMget() and PMscan(). Callers of PMload() must be aware that SI functions are used by PMload() to read files - therefore PMload() will block intermittently while reading the file. PMload() converts all alphabetic characters contained in resource names to upper-case before they are loaded into memory.
PMload() can be called repeatedly to load the contents of several files into the single namespace maintained by PM functions. Namespace clashes are handled by keeping the most recently loaded resource value when a name clash occurs. The resources currently loaded into memory can be erased by calling PMfree(), although this will require PMinit() to be called again before making other PM calls.
Inputs:
| pm_loc | LOCATION containing name of the PM file to be loaded. If pm_loc is NULL, the default configuration files will be used. |
| err_func | Pointer to a caller-declared function which will be called when an error is encountered loading the file. |
Outputs:
| None |
Returns:
| OK | PM file loaded successfully. |
| PM_FILE_BAD | a syntax error was detected in a PM file. |
| other | reportable error status. |
Prototype:
STATUS PMload( LOCATION *pm_loc, PM_ERR_FUNC *err_func );
PMscan - scan a set of PM resources matching a regular expression
Returns the set of PM resources which match an egrep-style regular expression in lexical order, with repeated calls. An initial call to PMscan() must be made to initialize a caller-declared variable used to store state information for the scan and return the first matching resource. Subsequent calls to PMscan() using the same state variable but with a NULL regular expression will return all remaining resources which match the regular expression. Multiple concurrent scans can be made by using a separate state variable for each scan.
Inputs:
| regexp | a string containing an egrep-style regular expression specifying a set of PM resources to be scanned. A new scan will be initiated whenever regexp is not NULL. |
| state | a user-declared state variable maintained by PMscan() which contains state information a scan. state is (re)initialized whenever regexp is not NULL. |
| last | if not NULL, the name of the next resource returned by PMscan() will be lexically larger than the resource name pointed to by last. last is ignored when NULL. |
Outputs:
| name | a string containing the name of the PM resource returned by PMscan(). |
| value | a string containing the value of the PM resource returned by PMscan(). |
Returns:
| OK | a PM resource was returned. |
| PM_END_SCAN | No (more) matching resources found. |
Prototype:
STATUS PMscan( char *regexp,
PM_SCAN_REC *state,
char *last,
char **name,
char **value );
PMsetDefault - set a default PM resource name component
Set the default PM name component corresponding to an index. Default PM resource name component indexes start at the leftmost component (0) and increases upward.
Inputs:
| idx | the index of the default PM name component to set. |
| s | a string containing the default PM name component to set. |
Outputs:
| None |
Returns:
| OK | the default name component was set successfully. |
| PM_INDEX_BAD | an invalid name component index was supplied. |
Prototype:
STATUS PMsetDefault( i4 idx, char *s );
Examples
Using PMload() to load a resource file
/* The following call to PMload() will load the contents of the
** default configuration resource files ($II_CONFIG/config.dat and
** $II_CONFIG/protect.dat). This example passes a null
** PM_ERR_FUNC pointer which means that syntax errors can't be
** fully reported.
*/
switch( PMload( (LOCATION *) NULL, (PM_ERR_FUNC *) NULL ) )
{
case OK:
/* loaded successfully */
break;
case PM_FILE_BAD:
error( "syntax error detected" );
default:
error( "unable to open data file" );
}
Using PMsetDefault() to set defaults
/* All entries in the default configuration resource files ** (maintained by INGRES DBA utilities begin with ** "ii.<hostname>.<program>.", by convention, where <hostname> is ** the string returned by GChostname() and <program> is a unique ** identifier assigned by the Language Review Committee to the ** program or facility which "owns" the parameter. */ char host[ MAX_HOSTNAME + 1 ]; /* Set default name components to simplify the call to PMget() */ PMsetDefault( 0, "ii" ); GChostname( host, sizeof( host ) ); PMsetDefault( 1, host ); PMsetDefault( 2, ERx( "dbms" ) ); PMsetDefault( 3, ERx( "*" ) );
Using PMget() to look up a resource
/* The following pointer is used to return a value from PMget() */
char *value;
/* The following call to PMget(), which uses the leading "!"
** syntax, assumes that defaults have been set with
** PMsetDefault().
*/
if( PMget( "!.connect_limit", &value ) != OK )
error( "parameter not found" );
/* Alternatively, the resource could be named explicitly. */
if( PMget( "ii.beast.dbms.*.connect_limit", &value ) != OK )
error( "parameter not found" );
Using PMscan()
PM_SCAN_REC state;
char *name, *value;
/* This examples uses the egrep regular expression ".*" to specify
** that all resources should be returned - but any egrep regular
** expression will do.
*/
if( PMscan( ".*", &state, NULL, &name, &value ) != OK )
error( "can't initiate PMscan()" );
do {
SIprintf( "%s=%s\\n", name, value );
}
while( PMscan( NULL, &state, NULL, &name, &value ) == OK )
An Uncertain proposal
We don't know what of the following proposal was implemented or is in use. It was architecture approved on 9-Jul-93, but never carried forward in the committee, as the author had left the company.
Topic: PM changes
Date: Wed, 7 Jul 93 11:51:47 PDT From: tyler@beast (Rick Tyler) To: na-cl@beast Subject: (CL #876) 3 PM proposals
1. Change to PMinit()
It is proposed that the return type of PMinit() be change from void to STATUS.
The new prototype for PMinit() will be:
STATUS PMinit( void );
The values returned by PMinit() will be:
| OK | The global PM context was initialized successfully. |
| PM_NO_INIT | PM has already been initialized. |
| PM_NO_MEMORY | Unable to allocate memory. |
2. Multi-context PM prototypes
STATUS PMmDelete( PM_CONTEXT *context, char *request );
char *PMmExpToRegExp( PM_CONTEXT *context, char *s );
void PMmFree( PM_CONTEXT *context );
STATUS PMmGet( PM_CONTEXT *context, char *request, char **value );
char *PMmGetDefault( PM_CONTEXT *context, nat idx );
PM_CONTEXT *PMmInit( void );
STATUS PMmInsert( PM_CONTEXT *context, char *request, char *value );
STATUS PMmLoad( PM_CONTEXT *context, LOCATION *loc, PM_ERR_FUNC
*err_func );
STATUS PMmScan( PM_CONTEXT *context, char *regexp, PM_SCAN_REC *state,
char *last, char **name, char **value );
STATUS PMmSetDefault( PM_CONTEXT *context, i4 idx, char *s );
Explanation
These functions (with the exception of PMmInit) are identical to the single-context versions, except that they require a control block pointer to be passed as an argument.
Instead of a STATUS (which is returned by PMinit), PMmInit() returns a pointer to a PM control block, which is internally allocated and initialized. PMmInit returns NULL if insufficient memory is available.
3. Two new PM functions
- STATUS PMrestrict( char *regexp );
- STATUS PMmRestrict( PM_CONTEXT *context, char *regexp );
Returns:
| OK | Restriction expression registered. |
| PM_NO_INIT | PM context was not initialized. |
| PM_REGEXP_BAD | Regular expression compilation failed. |
These functions may be called prior to PMload() and PMmLoad() in order to restrict the volume of data which gets loaded into memory (i.e. allocated) by PM. These functions will allow clients (such as GCA) to look up values from a well-defined subset of the PM name space, without allocating (potentially) a ton of memory.
A restriction expression which is registered with PMrestrict() or PMmRestrict() will stay in effect for all subsequent PMload() or PMmLoad() calls until a new expression (NULL is ok) is registered.
|
Ingres Compatability Library |
