Object Data Manager (ODM) is a data manager intended for storing system information. Information is stored and maintained as objects with associated characteristics. You can also use ODM to manage data for application programs.
System data managed by ODM includes:
You can create, add, lock, store, change, get, show, delete, and drop objects and object classes with ODM. ODM commands provide a command line interface to these functions. ODM subroutines access these functions from within an application program.
Some object classes come with the system. These object classes are discussed in the documentation for the specific system products that provide them.
This chapter discusses:
The basic components of ODM are object classes and objects. To manage object classes and objects, you use the ODM commands and subroutines (List of ODM Commands and Subroutines). Specifically, you use the create and add features of these interfaces to build object classes and objects for storage and management of your own data.
object class | A group of objects with the same definition. An object class comprises one or more descriptors (ODM Descriptors). |
object | A member of a defined object class, is an entity that requires storage and management of data |
An object class is conceptually similar to an array of structures, with each object being a structure that is an element of the array. Values are associated with the descriptors of an object when the object is added to an object class. The descriptors of an object and their associated values can be located and changed with ODM facilities.
The following example provides an overview of manipulating object classes and objects.
Example:
class Fictional_Characters { char Story_Star[20]; char Birthday[20]; short Age; char Friend[20]; };
In this example, the Fictional_Characters object class contains four descriptors: Story_Star, Birthday, and Friend, which have a descriptor type of character and a 20-character maximum length; and Age, with a descriptor type of short. To create the object class files required by ODM, you process this file with the odmcreate command or the odm_create_class subroutine.
Fictional_Characters: Story_Star = "Cinderella" Birthday = "Once upon a time" Age = 19 Friend = "mice" Fictional_Characters: Story_Star = "Snow White" Birthday = "Once upon a time" Age = 18 Friend = "Fairy Godmother"
The Fictional_Characters table shows a conceptual picture of the Fictional_Characters object class with the two added objects Cinderella and Snow White.
Story Star (char) | Birthday (char) | Age (short) | Friend (char) |
---|---|---|---|
Cinderella | Once upon a time | 19 | Mice |
Snow White | Once upon a time | 18 | Fairy Godmother |
Retrieved data for 'Story_Star = "Cinderella"' Cinderella: Birthday = Once upon a time Age = 19 Friend = Mice
Cinderella: Birthday = Once upon a time Age = 19 Friend = mice
Attention: Making changes to files that define system object classes and objects can result in system problems. Consult your system administrator before using the /usr/lib/objrepos directory as a storage directory for object classes and objects.
"ODM Object Class and Object Storage" discusses the criteria used at object-class creation time for determining the directory in which to store generated object classes and objects. Most system object classes and objects are stored in the /usr/lib/objrepos directory.
Generate an empty object class by running the odmcreate command with the ASCII file of object class definitions specified as the ClassDescriptionFile input file.
Attention: Making changes to files that define system object classes and objects can result in system problems. Consult your system administrator before using the /usr/lib/objrepos directory as a storage directory for object classes and objects.
"ODM Object Class and Object Storage" discusses the criteria used at object class creation time for determining the directory in which to store generated object classes and objects. Most system object classes and objects are stored in the /usr/lib/objrepos directory.
Add objects to an empty object class by running the odmadd command with the ASCII file of object definitions specified as the InputFile input file.
ODM does not implicitly lock object classes or objects. The coordination of locking and unlocking is the responsibility of the applications accessing the object classes. However, ODM provides the odm_lock and odm_unlock subroutines to control locking and unlocking object classes by application programs.
When the odm_lock subroutine sets the lock flag, it does not disable use of the object class by other processes. If usage collision is a potential problem, an application program should explicitly wait until it is granted a lock on a class before using the class.
Another application cannot acquire a lock on the same path name while a lock is in effect. However, a lock on a directory name does not prevent another application from acquiring a lock on a subdirectory or the files within that directory.
To unlock a locked object class, use an odm_unlock subroutine called with the lock identifier returned by the odm_lock subroutine.
Each object class you create with an odmcreate command or odm_create_class subroutine is stored in a file as a C language definition of an array of structures. Each object you add to the object class with an odmadd command or an odm_add_obj subroutine is stored as a C language structure in the same file.
You determine the directory in which to store this file when you create the object class.
Create an object or object class.
Storage methods vary according to whether commands or subroutines are used to create object classes and objects.
Attention: Making changes to files that define system object classes and objects can result in system problems. Consult your system administrator before using the /usr/lib/objrepos directory as a storage directory for object classes and objects.
When using the odmcreate or odmdrop command to create or drop an object class, specify the directory from which the class definition file will be accessed as follows:
When using the odmdelete, odmadd, odmchange, odmshow, or odmget command to work with classes and objects, specify the directory from which the class definition file will be accessed as follows:
$ export ODMPATH = /usr/lib/objrepos:/tmp/myrepos
The directories in the $ODMPATH are searched only if the directory $ODMDIR does not have the class definition file.
The odm_create_class or odm_add_obj subroutine is used to create object classes and objects:
OR
OR
An Object Data Manager (ODM) descriptor is conceptually similar to a variable with a name and type. When an object class is created, its descriptors are defined like variable names with associated ODM descriptor types. When an object is added to an object class, it gets a copy of all of the descriptors of the object class. Values are also associated with object descriptors already stated.
ODM supports several descriptor types:
terminal descriptor (ODM Terminal Descriptors) | Defines a character or numerical data type |
link descriptor (ODM Link Descriptor) | Defines a relationship between object classes |
method descriptor (ODM Method Descriptor) | Defines an operation or method for an object |
Use the descriptors of an object and their associated values to define criteria for retrieving individual objects from an object class. Format the selection criteria you pass to ODM as defined in ODM Object Searches. Do not use the binary terminal descriptor in search criteria because of its arbitrary length.
Terminal descriptors define the most primitive data types used by ODM. A terminal descriptor is basically a variable defined with an ODM terminal descriptor type. The terminal descriptor types provided by ODM are:
The ODM link descriptor establishes a relationship between an object in an object class and an object in another object class. A link descriptor is a variable defined with the ODM link descriptor type.
For example, the following code can be processed by the ODM create facilities to generate the Friend_Table and Fictional_Characters object classes:
class Friend_Table { char Friend_of[20]; char Friend[20]; }; class Fictional_Characters { char Story_Star[20]; char Birthday[20]; short Age; link Friend_Table Friend_Table Friend_of Friends_of; };
The Fictional_Characters object class uses a link descriptor to make the Friends_of descriptors link to the Friend_Table object class. To resolve the link, the Friends_of descriptor retrieves objects in the Friend_Table object class with matching data in its Friend_of descriptors. The link descriptor in the Fictional_Characters object class defines the class being linked to (Friend_Table), the descriptor being linked to (Friend_of), and the name of the link descriptor (Friends_of) in the Fictional_Characters object class.
The following code could be used to add objects to the Fictional_Characters and Friend_Table object classes:
Fictional_Characters: Story_Star = "Cinderella" Birthday = "Once upon a time" Age = 19 Friends_of = "Cinderella"
Fictional_Characters: Story_Star = "Snow White" Birthday = "Once upon a time" Age = 18 Friends_of = "Snow White"
Friend_Table: Friend_of = "Cinderella" Friend = "Fairy Godmother"
Friend_Table: Friend_of = "Cinderella" Friend = "mice"
Friend_Table: Friend_of = "Snow White" Friend = "Sneezy"
Friend_Table: Friend_of = "Snow White" Friend = "Sleepy"
Friend_Table: Friend_of = "Cinderella" Friend = "Prince"
Friend_Table: Friend_of = "Snow White" Friend = "Happy"
The following tables show a conceptual picture of the Fictional_Characters and Friend_Table object classes, the objects added to the classes, and the link relationship between them.
Story_Star (char) | Birthday (char) | Age (short) | Friends_of (link) |
---|---|---|---|
Cinderella | Once upon a time | 19 | Cinderella |
Snow White | Once upon a time | 18 | Snow White |
Retrieved data for 'Story_Star = "Cinderella" Cinderella: Birthday = Once upon a time Age = 19 Friends_of = Cinderella Friend_of = Cinderella
There is a direct link between the "Friends_of" and "Friend_of" columns of the two tables.
Friend_of (char) | Friend (char) |
---|---|
Cinderella | Fairy Godmother |
Cinderella | mice |
Snow White | Sneezy |
Snow White | Sleepy |
Cinderella | Prince |
Snow White | Happy |
After the Fictional_Characters and Friend_Table object classes are created and the objects are added, the retrieved data for Story_Star = 'Cinderella' would be:
Cinderella: Birthday = Once upon a time Age = 19 Friends_of = Cinderella Friend_of = Cinderella
To see the expanded relationship between the linked object classes, use the odmget command on the Friend_Table object class. The retrieved data for the Friend_of = 'Cinderella' object class would be:
Friend_Table: Friend_Of = "Cinderella" Friend = "Fairy Godmother" Friend_Table: Friend_of = "Cinderella" Friend= "mice" Friend_Table: Friend_of = "Cinderella" Friend = "Prince"
The ODM method descriptor gives the definition of an object class with objects that can have associated methods or operations. A method descriptor is a variable defined with the ODM method descriptor type.
The operation or method descriptor value for an object is a character string that can be any command, program, or shell script run by method invocation. A different method or operation can be defined for each object in an object class. The operations themselves are not part of ODM; they are defined and coded by the application programmer.
The method for an object is called by a call to the odm_run_method subroutine. The invocation of a method is a synchronous event, causing ODM operation to pause until the operation is completed.
For example, the following code can be input to the ODM create facilities to generate the Supporting_Cast_Ratings object class:
class Supporting_Cast_Ratings { char Others[20]; short Dexterity; short Speed; short Strength; method Do_This; };
In the example, the Do_This descriptor is a method descriptor defined for the Supporting_Cast_Ratings object class. The value of the method descriptor can be a string specifying a command, program, or shell script for future invocation by an odm_run_method subroutine.
The following code is an example of how to add objects to the Supporting_Cast_Ratings object class:
Supporting_Cast_Ratings: Others = "Sleepy" Dexterity = 1 Speed = 1 Strength = 3 Do_This = "echo Sleepy has speed of 1"
Supporting_Cast_Ratings: Others = "Fairy Godmother" Dexterity = 10 Speed = 10 Strength = 10 Do_This = "odmget -q "Others='Fairy Godmother'" Supporting_Cast_Ratings"
The Supporting_Cast_Ratings table shows a conceptual picture of the Supporting_Cast_Ratings object class with the Do_This method descriptor and operations associated with individual objects in the class.
Others (char) | Dexterity (short) | Speed (short) | Stength (short) | Do_This (method) |
---|---|---|---|---|
Sleepy | 1 | 1 | 3 | echo Sleepy has speed of 1 |
Fairy Godmother | 10 | 10 | 10 | odmget --q "Others='Fairy Godmother'"Supporting_Cast_Ratings" |
odm_run_method run of Sleepy's method displays (using echo): "Sleepy has speed of 1"
After the Supporting_Cast_Ratings object class is created and the objects are added, an invocation (by the odm_run_method subroutine) of the method defined for Sleepy would cause the echo command to display:
Sleepy has speed of 1
Many ODM routines require that one or more objects in a specified object class be selected for processing. You can include search criteria in the form of qualifiers when you select objects with certain routines.
qualifier | A null-terminated string parameter on ODM subroutine calls that gives the qualification criteria for the objects to retrieve |
The descriptor names and qualification criteria specified by this parameter determine which objects in the object class are selected for later processing. Each qualifier contains one or more predicates connected with logical operators. Each predicate consists of a descriptor name, a comparison operator, and a constant.
A qualifier with three predicates joined by two logical operators follows:
SUPPNO=30 AND (PARTNO>0 AND PARTNO<101)
In this example, the entire string is considered the qualifier. The three predicates are SUPPNO=30, PARTNO>0, and PARTNO<101, and the AND logical operator is used to join the predicates. In the first predicate, SUPPNO is the name of the descriptor in an object, the = (equal sign) is a comparison operator, and 30 is the constant against which the value of the descriptor is compared.
Each predicate specifies a test applied to a descriptor that is defined for each object in the object class. The test is a comparison between the value of the descriptor of an object and the specified constant. The first predicate in the example shows an = (equal to) comparison between the value of a descriptor (SUPPNO) and a constant (30).
The part of the qualifier within parentheses:
PARTNO>0 AND PARTNO<101
contains two predicates joined by the AND logical operator. The PARTNO descriptor is tested for a value greater than 0 in the first predicate, then tested for a value less than 101 in the second predicate. Then the two predicates are logically concatenated to determine a value for that part of the qualifier. For example, if PARTNO is the descriptor name for a part number in a company inventory, then this part of the qualifier defines a selection for all products with part numbers greater than 0 and less than 101.
In another example, the qualifier:
lname='Smith' AND Company.Dept='099' AND Salary<2500
can be used to select everyone (in ODM, every object) with a last name of Smith who is in Department 099 and has a salary less than $2500. Note that the Dept descriptor name is qualified with its Company object class to create a unique descriptor.
In ODM, a descriptor name is not necessarily unique. You can use a descriptor name in more than one object class. When this is the case, you specify the object class name along with the descriptor name in a predicate to create a unique reference to the descriptor.
The following are valid comparison operators:
= | Equal to |
!= | Not equal to |
> | Greater than |
>= | Greater than or equal to |
< | Less than |
<= | Less than or equal to |
LIKE | Similar to; finds patterns in character string data |
Comparisons can be made only between compatible data types.
The LIKE operator enables searching for a pattern within a char descriptor type. For example, the predicate:
NAME LIKE 'ANNE'
defines a search for the value ANNE in the NAME descriptor in each object in the specified object class. In this case, the example is equivalent to:
NAME = 'ANNE'
You can also use the LIKE operator with the following pattern-matching characters and conventions:
NAME LIKE '?A?'
defines a search for any three-character string that has A as a second character in the value of the NAME descriptor of an object. The descriptor values PAM, DAN, and PAT all satisfy this search criterion.
NAME LIKE '*ANNE*'
defines a search for any string that contains the value ANNE in the NAME descriptor of an object. The descriptor values LIZANNE, ANNETTE, and ANNE all satisfy this search criterion.
NAME LIKE '[ST]*'
defines a search for any descriptor value that begins with S or T in the NAME descriptor of an object.
Use a - (minus sign) to specify a range of characters. The predicate example:
NAME LIKE '[AD-GST]*'
defines a search for any descriptor value that begins with any of the characters A, D, E, F, G, S, or T.
NAME LIKE '[!ST]*'
defines a search for any descriptor value except those that begin with S or T in the NAME descriptor of an object.
You can use the pattern-matching characters and conventions in any combination in the string.
The specified constant can be either a numeric constant or a character string constant.
Numeric constants in ODM predicates consist of an optional sign followed by a number (with or without a decimal point), optionally followed by an exponent marked by the letter E or e. If used, the letter E or e must be followed by an exponent that can be signed.
Some valid numeric constants are:
2 2.545 0.5 -2e5 2.11E0 +4.555e-10 4E0 -10 999 +42
The E0 exponent can be used to specify no exponent.
Character string constants must be enclosed in single quotation marks:
'smith' '91'
All character string constants are considered to have a variable length. To represent a single quotation mark inside a string constant, use two single quotation marks. For example:
'DON''T GO'
is interpreted as:
DON'T GO
The AND logical operator can be used with predicates. Use AND or and for the AND logical operator.
The AND logical operator connects two or more predicates. The qualifier example:
predicate1 AND predicate2 AND predicate3
specifies predicate1 logically concatenated with predicate2 followed by the result logically concatenated with predicate3.