## Storage Management

An object occupies storage. The storage occupied by a public object is allocated by the client, and is, therefore, directly accessible by the client and can be released by the client. The storage occupied by a private object is not accessible by the client and must be managed indirectly by using XOM function calls.

Objects are accessed by an application program via object handles. Object handles are used as input parameters to interface functions by the client and returned as output parameters by the service. The object handle for a public object is simply a pointer to the data structure (an array of descriptors) containing the object OM attributes. The object handle for a private object is a pointer to a data structure that is in private implementation-specific format and therefore inaccessible directly by client.

The client creates a client-generated public object by using normal programming language constructs; for example, static initialization. The client is responsible for managing any storage involved. The service creates service-generated public objects and allocates the necessary storage. The client must destroy service-generated public objects and release the storage by applying the XOM function om_delete( ) to it, as shown in the following code fragment:

/* We can now safely release all the private objects

* and the public objects we no longer need

*/

CHECK_OM_CALL(om_delete(session));

CHECK_OM_CALL(om_delete(result));

CHECK_OM_CALL(om_delete(entry));

CHECK_OM_CALL(om_delete(attributes));

CHECK_DS_CALL(ds_shutdown(workspace));

The service also creates private objects for which it allocates storage that must be managed by the application.

One of the input parameters to the ds_read( ) function call is name. The name parameter is a public object created by the application from a series of nested data structures (RDNs and AVAs) to represent the distinguished name containing Peter Piper. When the application no longer needs the public object, it issues the XDS function call ds_shutdown( ) to release the memory resources associated with the public object. The ds_read( ) call returns the pointer to a private object, result, deposited in the workspace by the service.

The programs goes on to use the XOM function om_get( ) with the input parameter result as a pointer to extract attribute values from the returned private object. The om_get( ) call returns the pointer entry as a service-generated public object to the program so that the attribute values specified in the call can be accessed by it. Once the value is extracted, the application can continue processing; for example, printing a message to a user with some extracted value like a phone number or postal address. The service-generated public object becomes the responsibility of the application program. The program goes on to release the resources allocated by the service by issuing a series of calls to om_delete( ), as shown in the following code fragment from example.h:

/*

* extract the telephone number(s) of "name" from the result

*

* There are 4 stages:

* (1) get the Entry-Information from the Read-Result.

* (2) get the Attributes from the Entry-Information.

* (3) get the list of phone numbers.

* (4) scan the list and print each number.

*/

CHECK_OM_CALL( om_get(result,

OM_EXCLUDE_ALL_BUT_THESE_TYPES

+ OM_EXCLUDE_SUBOBJECTS,

entry_list, OM_FALSE, 0, 0, &entry,

&total_num));

CHECK_OM_CALL( om_get(entry->value.object.object,

OM_EXCLUDE_ALL_BUT_THESE_TYPES

+ OM_EXCLUDE_SUBOBJECTS,

attributes_list, OM_FALSE, 0, 0, &attributes,

&total_num));

CHECK_OM_CALL( om_get(attributes->value.object.object,

OM_EXCLUDE_ALL_BUT_THESE_TYPES

+ OM_EXCLUDE_SUBOBJECTS,

telephone_list, OM_FALSE, 0, 0, &telephones,

&total_num));

/* We can now safely release all the private objects

* and the public objects we no longer need

*/

CHECK_OM_CALL(om_delete(session));

CHECK_OM_CALL(om_delete(result));

CHECK_OM_CALL(om_delete(entry));

CHECK_OM_CALL(om_delete(attributes));

If the client possesses a valid handle (or pointer) for an object, it has access to a private object. If the client does not possess an object handle or the handle is not a valid one, a private object is inaccessible to the client and an error is returned to the calling function. In the preceding code fragment, the handles for the objects stored in entry, attributes, and telephones are the pointers &entry, &attributes, and &telephones, respectively.

##