Designing SCOadmin object service agents

Example request processors

The Tcl Object Validation Routine will be passed three parameters;

the OSA defined handle associated with this class - forwarded by the class's call to OFBinding(TCL_ADM).

a handle to be passed back to the Server API helper functions to facilitate internal operations

the BMIP request structured in a Tcl keyed list. The BMIP request contains these keys:

Request processor (Tcl)

proc UserRequestProcessor {osaDataString handleId bmipRequest} {

# # get the list of objects we'll be operating on, send them through # a filter, and then get a count of the remaining ones. #

set objectList [keylget bmipRequest objectInstance] set objectList [OFEvaluateFilter $handleId $objectList] set listLength [llength $objectList]

if ($listLength < 1) {

# # If all the objects failed the filter, we need to send a BMIP # response to that effect back to the client. So we set the # objectInstancePtr to NULL and call OFReturnBmipResponse(). #

set bmipResponse $bmipRequest keylset bmipResponse errorParameter {} keylset bmipResponse attributeList {} keylset bmipResponse actionInfo {} keylset bmipResponse linkedId 0 keylset bmipResponse objectInstance {}

OFReturnBmipResponse $handleId $bmipResponse FALSE

return }

# # Step through the remaining object instances so we can operate on # each one and send the BMIP response back to the client that called # us. We will do this non-atomically. # # If we were to do this atomicly we would construct an array to store # all the BMIP responses in. Then we would either send them all in # at once after all the calls to OFEvaluateOperation we completed (if # none of them contained an error), or we would undo the work of the # completed operations and send in one response that contained the # error. #

foreach object $objectList {

# # OFEvaluateOperation() returns a BMIP response, send # this back to the client via OFReturnBmipResponse(). # Make sure to have the last object call the return BMIP # function with a FALSE continue flag, so that we can # inform the client we're done sending data it's way. #

OFEvaluateOperation $handleId $object bmipResponse incr listLength -1 if ($listLength < 1) { set continue FALSE } { set continue TRUE } OFReturnBmipResponse $handleId bmipResponse $continue } }

Request processor (C/C++)

cUserRequestProcessor(errStatus_cl       *errStatusPtr,
                      int                 handleId,
                      bmipRequest_pt      bmipRequestPtr,
                      void               *handle)
     * Generate a list of all the objects to be evaluated
    objectName_pt         *objectList;
    int                    objectCount;
    int                    loop;
    bool_t tclResult = TclListSplit(bmipRequestPtr->objectInstancePtr,
    if (tclResult == FALSE)
        /* If an error is left on the stack when returning, the caller of
         * this function will return a BMIP response based on the BMIP
         * request and the current error stack.

ErrorPush(errStatusPtr, &SCO_OSA_ERR_NO_SUCH_OBJECT_INSTANCE, bmipRequestPtr->objectInstancePtr); return; }

/* Calling OFEvaluateFilter() with a filter and a list of objects will * cause the Object API to run a standard filter (using the OSA provided get * operation) and re-arange the list of objects forwarded to * OFEvaluateFilter() and re-set the value of objectCount to the number * of objects in the list that passed the filter. */ OFEvaluateFilter(errStatusPtr, handleId, bmipRequestPtr->filterPtr, &objectList, &objectCount);

if (objectCount < 1) { /* If all the objects failed the filter, we need to send a BMIP * response to that effect back to the client. So we set the * objectInstancePtr to NULL and call OFReturnBmipResponse(). */ bmipResponse_t *bmipResponsePtr; bmipResponsePtr = OFComposeBmipResponseError(errStatusPtr, bmipRequestPtr);


OFReturnBmipResponse(errStatusPtr, handleId, bmipResponsePtr, FALSE);

/* Calling OFReturnBmipResponse() will also free up bmipResponse_t. */ MemFree(objectList); return; }

/* For each object that passed the filter, have the operation evaluated * upon it and send the BMIP response returned to the client. * * If the OSA were attempting to perform atomic synchronization, then * it would prepair an array of bmipResponse_t pointers and assign each * successful call to OFEvaluateOperation() to a new pointer. Only if * all the objects were evaluated without errors would this validation * code then go ahead and call OFReturnBmipResponse() on each bmipResponse. * If any error occurred, the OSA would have to figure out how to undo the * work it had done during this session so far, and then return the lone * error message. */ for (loop = 0; loop < objectCount; ++loop) { bmipResponse_t *bmipResponsePtr; bmipResponsePtr = OFEvaluateOperation(errStatusPtr, handleId, objectList[loop]); if (ErrorIsOk(errStatusPtr) == FALSE) { /* If we were doing atomic synchronization then we would * want to examine this error, and if needed then undo all * the operations done in this session. Since we are not * doing atomic synchronization, we just let the error * (already incorporated into the current BmipResponse) be * sent back to the client. */ ErrorClear(errStatusPtr); }

/* Only the last object should have the ContinueFlag (parameter 4) * set to FALSE. This tells the client that there are no more BMIP * responses yet to arrive. * * By this same token the validation code should make sure that there * is no error left on the stack after calling the last bmip Response * in, as this error will also be processed and sent to the client. */ OFReturnBmipResponse(errStatusPtr, handleId, bmipResponsePtr, (loop + 1 == objectCount) ? FALSE : TRUE );

if (!(ErrorIsOk(errStatusPtr))) return; }

ckfree(objectList); }

Previous topic: Example helper functions and procedures (Tcl)

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003