Strategies for Using the DCE Managed Object Class Library

From EDM2
Jump to: navigation, search

by Theodore Shrader and Gregg Wilson

In his campaigns in northern Virginia, General Robert E. Lee had many strategies, not all of which led to victory. His strategy guide was not fixed of guaranteed. Fortunately, this is not the case with the Managed Object Class Library (MOCL). In your Distributed Computing Environment (DCE) development with the MOCL, a number of firm, battle-tested strategies exist that you can follow to help you win your application campaigns. This article describes some of them.

Strategy #1: Enlisting Proxy Objects

If you already have an existing account defined in the DCE security registry database, you can call the MOCL proxy method to get a handle to it, such as in the following:

pacct = new DCE_Account(ev, cellname, labelid);

If you want to create a new account, you'll need to send the create_object method to the DCE_AccountIM instance manager object.

You don't need to use proxy objects. If you send the lookup_object method to DCE_AccountIM, you will also be able to get a handle back to your specified account. Proxy methods provide you with a quick and easy way to instantiate wrapper objects to pre-existing, physical DCE objects like those in the DCE security registry database.

Proxy methods are also available for the group and organization registry objects (the latter are called policy groups in MOCL), as well as for the many DCE servers, such as the cell directory server and password synchronization server. Because other MOCL objects are not stored in DCE and only exist during the application process, they cannot be created or retrieved with proxy methods. Instance managers, for example, fall under this category.

Strategy #2: Scouting the Environment

Be sure to check your environment variable (ev) after each MOCL call. If a problem occurs in DCE or in one of the many fail-safe checks MOCL implements, you can display the stack of exception messages stored in the environment. They will help you pinpoint the exact cause of the problem.

The following sample code not only checks to see if an exception exists on the stack, but it also checks if the top level exception is of type ExValidationFailed. If so, it increments the validation_errors counter.

if (ev->_major != NO_EXCEPTION) {
  if (!strcmp( somExceptionId(ev), ex_Base_SysAdminException_ExValidationFailed)) {
    validation_errors++;
  }
}

Sometimes the exception revealing the true cause of the error might lie in the middle or at the bottom of the environment exception stack. If MOCL encounters a DCE error, it will place the DCE error message along with the exception, such as ExFailed, on the exception stack. MOCL also can issue another exception and message with a further explanation of the error. For this example, the MOCL exception and message would be at the top of the stack with the DCE exception and message underneath it. The following code is one way you could print all the exception messages from your environment:

error_status_t rc;
ExCursor cursor;

rc = Print_First_Base_SysAdminException(ev,&cursor); 
while (rc==error_status_ok){
  rc=Print_Next_Base_SysAdminException (ev,&cursor);
} 

Another useful technique lies in the use of local environment variables to capture exceptions that you do not want issued in your global environment. The following sample code demonstrates the advantages of a local environment by using it with a call to lookup_object. Because you are trying to find an account, if MOCL issues an exception (such as ExObjNotFound), you might not want it placed in your global environment. For example, you might want to recover from the exception by creating the account object if you can't find it.

Base_MemUtils_Base_FreeUtils *bf=new
Base_MemUtils_Base_FreeUtils(); local_ev=SOM_CreateLocalEnvironment();
pacct = (DCE_SecurityRegistry_DCE_Account*)

void*)pacctim->lookup_object(local_ev, &lt, NULL)); 

if (local_ev->_major != NO_EXCEPTION) {
 if (!strcmp(somExceptionId(ev), ex_Base_SysAdminException_ExObjNotFound)){
   bf - > free_BaseSysAdminException (local_ev);
   // create the account object
 } else {
   // Some other exception that we need to save in the ev.
   // The join call will transfer the exception from the
   // local_ev to the global ev, thus the local_ev does
   // not need to be freed.
   Join_Base_SysAdminException(ev, local_ev); 
   }
 }

SOM_DestroyLocalEnvironment(local_ev);

To prevent memory leaks, you will need to free the exceptions in the local environment as well as destroy your local environment after you've finished using it. The free_BaseSysAdminException method call releases the memory allocated for the exceptions on the environment stack. The SOM_DestroyLocalEnvironment call performs the coup de grace by removing the local environment completely.

Strategy #3: Supplying Object Memory

What may begin as a memory drip can quickly turn into a memory gusher if it stems from an action that your application performs repeatedly. MOCL methods might allocate and return memory objects, sequences, or structures, and your application will need to free these objects after their use.

The MOCL memory structures come in a variety of types. Some are sequences of structures, like SysAdminTypes::ObjectLabelList and others are special

structures, like CosPropertyService::Property. MOCL includes the memory utilities object Base_MemUtils to assist you in freeing the different types of memory allocated by MOCL. The Base_MemUtils .IDL file in your MOCL toolkit and the online publications provide a complete list of the free methods available through this utility object.

You first saw the memory utilities object in our discussion of environments. It's a good idea to just create the memory utilities library object once at the beginning of your program and store it in a global variable or universally accessible object. This can be done right after your call to MOCL_getLibrary where you get a handle to the MOCL library object. You can then free your memory library object at the end of your program--unless you're one of those rebels who lets the system free your global objects at the end of your process.

Retrieving the label of a MOCL object is an action that many applications perform to get both the ID and kind of the object. For an account object, the ID would be the account name, and the kind would be DCE_SecurityRegistry::DCE_Account, which specifies the module and interface name of the account object. The get_Label call allocates memory for those two strings and returns it in the SysAdminTypes::LabelType structure. Your application will need to free this memory, such as through the following code:

SysAdminTypes_LabelType acctlabel;
acctlabel = pacct->_get_label(ev);

if (ev->_major == NO_EXCEPTION) {
   cout << "Account id = " << acctlabel.id << " kind = " <<
       acctlabel.kind << endl;
       bf->free_LabelType(ev, &acctlabel); }

Strategy #4: Vanquishing Complexity with MOCL

As mentioned earlier, with MOCL you can abstract the problems that your application is trying to solve without needing to know the details of DCE API calls. One way MOCL simplifies and routes problems is through its use of fail-safe checks.

An example of such a fail-safe check resides in the membership methods of the DCE_Account object. If you create an account X with a principal X, primary group Y, and primary organization Z and then remove principal X from group Y, whether through a direct DCE API call or using the dcecp command line interface, DCE will automatically delete account X because the principal it was created with no longer has the primary group with which it was associated. If the membership change was unintentional, the behavior could be unexpected--perhaps downright startling.

The DCE_Account remove_membership method protects your DCE application from accidental changes such as these. If your application calls remove_membership and tries to delete the account from the membership list of its primary group, the MOCL method will pass back an ExInvalid exception with a message stating that the account cannot be removed from its primary group.

If your application did want to remove the account from its primary group, as well as delete the account object from DCE, your application could first call the deactivate method on the DCE_Account object. This action would delete the account object from the DCE security registry database, leaving just the principal object. The MOCL DCE_Account object now reverts to an inactive state, which indicates that it is only a principal. Next, your application could call the remove_membership method on the DCE_Account object to remove the principal from the group.

In Review

This article listed several battle-ready strategies that will arm you for successful DCE MOCL development. With these strategies and ones that you've already developed, you're on your way to a victorious campaign in DCE application development.

Note: This article is based on the pre-release version of MOCL included with DCE. The interface may differ in the final release. DCE is included with the IBM Directory and Security Server (DSS) for OS/2 Warp. DSS is one of the IBM Software Servers described in "Go Cross Platform With the Developer Connection," on page 1.

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation