Ingres CL Architecture
From Ingres Community Wiki
|
Ingres Compatability Library |
Contents |
CL and GL Interface Architecture
The CL and GL have a consistent format for interfaces. This section discusses a hypothetical FC facility.
Include Files
All code using parts of the CL and GL must include the file <compat.h> before any other CL headers. This header is documented in a following chapter.
Each of the facilities within the CL exports at least one header describing its interface. For facility FC, this is usually <fc.h>. Some facilities export additional include files; these are documented in the chapter that describes the facility. You must include the header files for a facility before using any of the functions, data types, or constants it defines.
The <fc.h> file actually lives in the GL header directories. It will include <fccl.h> which is owned by the different CL providers. The single <fc.h> file make all the public function declarations, ensuring a consistant interface across all CL implementations. There are methods for handling things that might be functions on some systems and macros on others. You can look at the existing headers in the GL for details.
These exported facility include files will define all function declarations, type or structure definitions, symbolic constants, and the return codes needed to use the facility. Any function interface within the CL may be a macro defined in the appropriate facility header.
Multiple Inclusion: Mainline code is forbidden to do nested includes. It may be necessary for CL headers to include other files, including other CL headers. In these cases, some CL headers will need to be protected from multiple inclusion. For instance, client code using SIprintf must include <si.h>, but it does not need to include <lo.h> since it it not using any of the SI interfaces that use LOCATION s. It may be necessary for <si.h> to include <lo.h> on its own in this circumstance. Since the client code might include <si.h> before including <lo.h>, it is necessary for <lo.h> to be protected from multiple inclusion.
Constants
Constants should be prefixed by the facility code:
# define FC_MAX_STUFF 10
Structures
Data structures should be prefixed by the facility code. Members within a structure should have a common prefix to show the structure to which they belong.
typedef struct FC_MYSTRUCT
{
char ms_stuff[ FC_MAX_STUFF ];
nat ms_morestuff;
} FC_MYSTRUCT;
Executable Interfaces
Unless otherwise specified, any executable interface in the CL may be implemented as a true function, an object-like macro, or a function-like macro. An object-like macro is one that does not take parentheses; a function-like macro has parentheses and may take arguments.
A legal CL implementation could map all executable interface names with object-like macros in the facility include file, even if they ultimately resolved to true functions.
/* <fc.h> */
# define FCfunc IIFCfunc
This is one way to reduce the pollution of the user application namespace without rewriting code. It does require that all clients include the facility header, or the link will fail with an undefined symbol "FCfunc".
Most calls to the CL have the same general form:
STATUS
FCfunc( in1, in2, inout1, inout2, out1, out2, errdesc )
nat in1;
nat in2;
MYSTRUCT *inout1;
MYSTRUCT *inout2;
MYSTRUCT *out1;
MYSTRUCT *out2;
CL_ERR_DESC *errdesc;
The arguments to a function are always, from left to right, inputs, input-outputs, and outputs. A CL_ERR_DESC should usually be the last parameter to a function. Most functions return a variable of the STATUS type. On successful completion, the return value will be OK. OK is guaranteed to have the value zero. Mainline code may check for other STATUS values documented for the function. Any function may return other STATUS values that are unknown to the mainline representing error values. If the status is not OK, and the function has a CL_ERR_DESC argument, then the error descriptor will be filled in with additional information about the error.
Exceptions to this general form are:
Routines that predate this convention (circa 1983).
Functions such as MEreqmem where it is convenient to be able to put the output into a register variable, or necessary to immediately coerce the output pointer with a cast. Neither is possible with by-reference output parameters
Variable argument functions, when it is convenient to get all the output parameters (such as the error descriptor) before starting to walk the stack.
Functions that "can't fail," such as STcopy.
Notes on Data Types
A complete specification of general types available to CL users is in the chapter on <compat.h>. In moving towards a more portable CL specification, the use of i2 and i4 types has been restricted to storing database objects. Use nat and longnat wherever possible; nat's are used to represent at least a 16-bit integer and longnat's are assumed to represent at least 32-bit integers. Some CL routines (MEcopy for one) still take u_i2 parameters. This is an unfortunate historical occurrence; new interfaces may not be specified in this way.
CL Specification Format
The general outline of a CL specification document is as follows. Optional sections are in brackets. The <xx.h> section is a new requirement with the 6.3 specification.
Chapter 1 - Document History
Version of the document, date, changes made
Chapter 2 - Specification
2.1 Introduction
2.1.n [Description]
2.1.n [Intended Uses]
2.1.n [Assumptions]
2.1.n [Definitions/Concepts]
2.2 <xx.h> - include file
2.2.n [Data structures]
2.2.n [Types]
2.2.n [Constants]
2.3 Executable Interface
(in alphabetical order)
2.3.n [Function/Macro]
Description
Inputs
Outputs
Returns
[Exceptions]
[Side Effects]
Prototype | Definition
Examples
Facility Examples
[Chapter 3 - Examples]
[More extensive examples]
Index
Introduction
overview of the facility.
[Description]
a short explanation of what the facility provides. This contains a description of the function supported by the facility as a whole.
[Intended Uses]
summarizes the uses this facility is intended for. In all cases, it should summarize the uses within Ingres that the facility was built for. Also, any uses that should be excluded are given here (e.g. DI should only be used by the DBMS).
[Assumptions]
summarizes and highlights the model-of-the-world assumed by this abstraction. The section is designed to enhance the understanding of how a client can (must) use the facility and how an implementor must build the system. It will not always be clear whether information belongs in the Assumptions or Definitions/Concepts section; err on the side of redundancy and restating the obvious. Some examples:
"This facility assumes that strings are terminated with a single byte NULL terminator, referred to as EOS."
"The CL assumes that all bytes are 8-bit quantities. Therefore, this CL may only be implemented on 8-bit byte machines."
"The user of DI cannot assume that upon return from DIwrite the pages are on the disk. To insure a page hits the disk DIforce must be invoked."
"The file abstraction SR is built upon must allow the file to be extended in an 'unlimited' fashion. SR files can be created, through SRopen, without any disk space allocated to them."
"This facility must support variable length IO, i.e. multiple physical blocks can be handled as a single logical request as long as the logical request is a multiple of the physical block size."
[Definitions/Concepts]
describe the key concepts of the abstraction. The concepts and definitions given here are used to explain the workings of the facility and also to provide language to use in the interface section. This substantially overlaps the following section describing the facility include file. Given a choice, define things in the include file section rather than here.
"<xx.h>"
describes the required contents of the include file associated with the facility. The presence of this section was added with Ingres 6.3, subsuming much of what used to be in the ``Definitions/Concepts. It may include optional subsections as necessary for clarification. Each significant data structure should be in its own subsection so it shows up in the table of contents.
[Data Structures]
describes data structures exported by the facility.
[Types]
describes types exported by the facility.
[Constants]
describes constants exported by the facility
Executable Interface
describes the callable interfaces of the facility in alphabetical order. These may either be functions or macros. Each interface description consists of a number of mandatory, and some optional elements.
Description
explains what the interface does.
Inputs
lists the input variables and the meanings of their contents when the invocation is made. Unless specifically allowed in the specification, handing a NULL as a pointer argument will result in unspecified behavior, meaning an access violation or a segmentation violation might result, and the function need not attempt to protect itself.
Outputs
list the variables used as outputs and the meanings of their values on exit.
Returns
describes what values are returned by the function. For functions that return STATUS , only values that clients should or must consider should be documented. The standard language is OK or other system specific error status.
[Exceptions]
is an optional section that lists exceptions that are required to be raised under specific conditions that are also described.
[Side Effects]
is an optional section that explains any side effects of invoking the interface.
Prototype or Definition
shows the details of the interface, either as an ANSI-style prototype (preferred), or as the beginning of a K&R C style function definition.
Examples
shows how the interface is expected to be used; required for all new interfaces.
Facility Examples
should provide correct examples of calls to the interfaces. It is useful to show common sequences, particularly those involving interactions with other facilities, for instance the use of LO before SIopen.
Writing code using the Compatibility Library
Your compilation environment will need to be set up so you can get the documented CL headers with angle bracket include statements, and provide an object library to link with. All Ingres code must comply with the Ingres Coding Standards, a separate document.
As noted above, you must include <compat.h> before including anything else, and you must include the facility header for any CL facility you use. For example, you should not use MEcopy without including <me.h> because MEcopy may be defined as a macro.
All callers should check the return codes of functions returning STATUS, and the return domain of functions returning values. It is very poor coding practice to ignore return values. If a return value is being ignored, it must be explicitly thrown away with a _VOID_ cast.
Client code can only check for explicitly documented return values. Since CL routines may return other STATUS codes, the only thing mainline may do at that point is hand the value to ERlookup for decoding. (ERreport is an obsolete way of doing the same thing.)
|
Ingres Compatability Library |
