| Solstice Enterprise Manager 4.1 Developing C++ Applications |
Performing Asynchronous Management Operations
A management operation can take a significant length of time to finish, particularly if the operation exchanges a large quantity of data between your application and the network resources it is managing. If your application is blocked while waiting for an operation to finish, the application may appear unresponsive to a user, or may fail to respond quickly enough to important events on your network. Performing asynchronous management operations enables an application to continue with other processing without waiting for the operations to finish.
This chapter explains how to enable applications to perform asynchronous management operations.
- Section 8.1 Asynchronous and Synchronous Operation
- Section 8.2 Specifying Asynchronous Operations
- Section 8.3 Handling Responses From an Asynchronous Operation
- Section 8.4 Verifying and Changing the Status of an Asynchronous Operation
8.1 Asynchronous and Synchronous Operation
Your application can perform a management operation in synchronous or asynchronous mode.
In synchronous mode, all functions within the application wait until the operation is complete before returning. In this way, the thread of control is blocked after a function is called, and the application can make use of the result immediately after the function returns.
In asynchronous mode an application can initiate several concurrent asynchronous operations before receiving any of the results. The results are not guaranteed to be returned in any particular order. Asynchronous mode enables an application to continue with other processing without waiting for a function to return, but does not enable the result to be used immediately.
Note Despite the similarities in terminology, these modes are not related to synchronization.
8.2 Specifying Asynchronous Operations
To enable an application to continue processing while the application is waiting for the result of an operation, call the asynchronous function for the operation. Calling an asynchronous function initiates an operation, but returns program control to your application before the operation finishes.
In the call to an asynchronous function, you can optionally specify a callback function to be run when the asynchronous operation finishes. For more information, see Section 8.3 Handling Responses From an Asynchronous Operation.
An asynchronous function returns an instance of the Waiter class. The function does not return the result of the operation initiated. The Waiter class represents an unfinished asynchronous operation. The instance of Waiter returned enables you to:
- Register a callback function for handling response from managed objects as described in Section 8.3.2 Registering a Callback Function for Handling Responses From Managed Objects
- Verify or change the status of an asynchronous operation as described in Section 8.4 Verifying and Changing the Status of an Asynchronous Operation.
You can choose to perform the following types of operations asynchronously:
- Interactions with the MIS
- Operations on managed objects
- Operations on object collections
In addition, the Album class provides functions for performing asynchronous CMIS operations on object collections.
8.2.1 Interactions With the MIS
The Platform class provides functions for synchronously or asynchronously interacting with the MIS. The names of asynchronous functions are prefixed with start. To specify whether your application interacts with the MIS synchronously or asynchronously, call the appropriate version of the function as listed in TABLE 8-1.
TABLE 8-1 Synchronous and Asynchronous Functions of the Platform Class Connect an application to the MIS connect start_connect Disconnect an application from the MIS disconnect start_disconnect
8.2.2 Asynchronous Operations on Managed Objects
For each management operation that you can perform on a managed object, the Image class provides a function for performing it synchronously or asynchronously. The names of asynchronous functions are prefixed with start. To specify whether a management operation is performed synchronously or asynchronously, call the appropriate version of the function as listed in TABLE 8-2.
8.2.3 Asynchronous Operations on Object Collections
For each management operation that you can perform on an object collection, the Album class provides a function for performing it synchronously or asynchronously. The names of asynchronous functions contain the text start. To specify whether a management operation is performed synchronously or asynchronously, call the appropriate version of the function as listed in TABLE 8-3.
Note The Album class does not provide a function for sending an encoded synchronous action request to an object collection.
8.2.4 Asynchronous CMIS Operations on Object Collections
The Album class provides functions for performing asynchronous management operations defined by the common management information service (CMIS). CMIS is specified in recommendation ITU-T X.710/ISO-9595 Common Management Information Services (CMISE). Use these functions if you want to perform an operation on a subset of the managed objects in an object collection.
You can perform asynchronous management operations on an object collection only if all of the following conditions are met:
- The membership of the object collection is defined by derivation (see Section 6.3.1 Defining the Membership by Derivation).
- The managed objects that you want to perform the operation on are all contained in a subtree of the MIT rooted in the base managed object of the object collection.
- The managed objects in the object collection reside in an agent that supports the common management information protocol (CMIP).
Note The Album class also provides functions for performing management operations that are independent of any particular management protocol or service. However, these functions allow you to perform a management operation only on all managed objects in an object collection, not a subset of them. For more information, refer to Section 6.5 Accessing All Objects in an Object Collection.
The Album class provides functions for performing the CMIS operations listed in TABLE 8-4. For a definition of all CMIS operations, refer to ITU-T X.710/ISO-9595 Common Management Information Services (CMISE).
Performing an asynchronous CMIS operation on an object collection involves:
- Selecting the managed objects to be the subject of a CMIS operation
- Requesting a CMIS operation
8.2.4.1 Selecting the Managed Objects to be the Subject of a CMIS Operation
The derivation string of the Album instance that contains an object collection selects the managed objects that are the subject of a CMIS operation on the object collection.
If you want to select all managed objects in an object collection, leave the derivation string unchanged after you call the derive function of the Album class.
If you want to select a subset of the managed objects in an object collection, reset the derivation string but do not call the derive function of the Album class.
Code for selecting the managed objects to be the subject of a CMIS operation is shown in CODE EXAMPLE 8-1.
In this example, an object collection containing all managed objects except instances of the log class is created. After the membership of this object collection has been defined by derivation, the derivation string is reset to select all second-level subordinates of the system object except instances of the log class. To preserve the membership of the object collection, the derive function of the Album class is not called after the derivation string is reset.
8.2.4.2 Requesting a CMIS Operation
When you have selected the objects to be the subject of a CMIS operation, call one of the functions listed in TABLE 8-5 to request the operation. Additional information on how to call each function listed in TABLE 8-5 is given in the following subsections.
TABLE 8-5 Functions of the Album Class for Requesting CMIS Operations M-GET start_m_get M-SET start_m_set M-ACTION with a text parameter start_m_action M-ACTION with an encoded parameter start_m_action_raw M-DELETE start_m_delete
Requesting an Asynchronous CMIS M-GET Operation
To request an asynchronous CMIS M-GET operation, call the start_m_get function of the Album class.
In the call to start_m_get, specify:
- A list of the attributes you want to get the values of. You must pass the list of attributes to the start_m_get function in an array, even if you want to get only one attribute.
- A callback function to be called when the management operation is complete.
Requesting an Asynchronous CMIS M-SET Operation
To request an asynchronous CMIS M-SET operation, call the start_m_set function of the Album class.
In the call to start_m_set, specify:
- A modification list. The modification lists specifies the attributes you want to set and how you want to set them.
- A callback function to be called when the management operation is complete.
Note The start_m_set function supports only best effort synchronization.
To specify a modification list, create a queue of AttrModifier instances and pass this queue to start_m_set. The AttrModifer class represents a single modification to an attribute of a managed object.
Creating a queue of AttrModifier instances involves:
- Initializing an instance of the Queue class
- For each modification in the modification list:
In the call to the constructor of the AttrModifier class, specify the name of the attribute you want to set.
To specify how you want to set the attribute, call functions of the AttrModifier class as follows:
- To specify the value that you want to set the attribute to, call the set_value function. In the call to set_value, you have to specify an instance of the Morf class that represents the value. For information on the Morf class, refer to Chapter 9.
- To specify how the attribute value is to be modified, call the set_operator function. In the call to set_operator, you have to specify one of the operations listed in TABLE 8-6.
TABLE 8-6 Operations for the set_operator Function REPLACE Replaces the existing value with that specified in the function call. It corresponds to the REPLACE operation in a property list. This is the default operation. ADD Adds the value specified in the function call to the current value of a multi-valued attribute. It corresponds to the ADD operation in a property list. Specify the ADD operation for multi-valued attributes only. If you specify the ADD operation for a single-valued attribute, an exception is thrown. REMOVE Removes the value specified in the function call from the current value of a multi-valued attribute. It corresponds to the REMOVE operation in a property list. Specify the REMOVE operation for multi-valued attributes only. If you specify the REMOVE operation for a single-valued attribute, an exception is thrown. SET_TO_DEFAULT Replaces the existing value with the default value defined in the property list in the ATTRIBUTES construct of the attribute's GDMO specification.
Code for requesting an asynchronous CMIS M-SET operation is shown in CODE EXAMPLE 8-2.
CODE EXAMPLE 8-2 Requesting an Asynchronous CMIS M-SET Operation
... #include <pmi/hi.hh> // High Level PMI #include <queue.hh> // Queue class declaration ...Album nologs_album = Album("All objects except log objects"); ... Queue (AttrModifier) amq; Morf val; AttrModifier * elt1 = new AttrModifier (CDU coordinates); elt1->set_operator (REPLACE); elt1->set_value (&val); amq.enq (elt1); AttrModifier * elt2 = new AttrModifier (CDU highWaterMark); elt2->set_operator (SET_TO_DEFAULT); amq.enq (elt2); nologs_album.start_m_set (amq); ...In this example, a queue named amq of AttrModifier instances is created. The AttrModifier instances in the queue specify that:
- Attribute coordinates is set to the value specified in the instance of Morf named val.
- Attribute highWaterMark is set to its default value.
Requesting an Asynchronous CMIS M-ACTION Operation With a Text Parameter
To request an asynchronous CMIS M-ACTION operation with a text parameter, call the start_m_action function of the Album class.
In the call to start_m_action, specify:
- The name of the action
- An instance of the DataUnit class that contains the parameter associated with the action
- A callback function to be called when the management operation is complete
Note The start_m_action function supports only best effort synchronization.
Requesting an Asynchronous CMIS M-ACTION Operation With an Encoded Parameter
To request an asynchronous CMIS M-ACTION operation with an encoded parameter, call the start_m_action_raw function of the Album class.
In the call to start_m_action_raw, specify:
- The name of the action
- An instance of the Morf class that contains the parameter associated with the action
- A callback function to be called when the management operation is complete
Note The start_m_action_raw function supports only best effort synchronization.
Requesting an Asynchronous CMIS M-DELETE Operation
To request an asynchronous CMIS M-DELETE operation, call the start_m_delete function of the Album class. In the call to start_m_delete, specify a callback function to be called when the management operation is complete.
8.3 Handling Responses From an Asynchronous Operation
An application receives the following types of responses from an asynchronous operation:
- A confirmation that the operation has finished. Some processes in your application may depend on the completion of an asynchronous operation, and must wait until the asynchronous operation has finished. For example, an application that connects asynchronously to an MIS must wait until the connection has been established before attempting to access managed objects in the MIS. Use the confirmation to make your application wait until an asynchronous operation has finished before it starts a process that depends on the completion of the asynchronous operation.
- Responses from managed objects. Each managed object that is the subject of an asynchronous operation sends a response that contains the result of the operation. Handle these responses to process the result of an asynchronous operation, for example by displaying retrieved values or taking alternative courses of action depending on whether the operation succeeds or fails.
Handling responses to asynchronous operations involves:
- Registering a callback function for the completion of an asynchronous operation
- Registering a callback function for handling responses from managed objects
- Writing a callback function
- Scheduling response handling
8.3.1 Registering a Callback Function for the Completion of an Asynchronous Operation
Register a callback to specify the processing that is carried out when an asynchronous operation finishes. Registering a callback associates the callback with an asynchronous operation. The callback is run when your application receives a confirmation that the asynchronous operation has finished.
Registering a callback function for the completion of an asynchronous operation is optional. By default, no callback is registered when you call a function for performing an asynchronous operation.
To register a callback, pass it as a parameter to the asynchronous function. In the asynchronous function call, initialize an instance of the Callback class to represent the callback function.
To initialize an instance of the Callback class, call its constructor in the asynchronous function call. In the call to the constructor of the Callback class, you must specify:
- The name of the callback function.
- A pointer to the data to be passed as an argument to the callback function. You can specify a null pointer if you do not want to pass any data to the callback function.
Code for registering a callback for an asynchronous operation is shown in CODE EXAMPLE 8-3.
CODE EXAMPLE 8-3 Registering a Callback for an Asynchronous Operation
... #include <pmi/hi.hh> // High Level PMI ... Waiter alb_waiter = myAlbum.start_derive( Callback(alb_derived_cb, (Ptr)&cb_info)); ...In this example, the start_derive function of the Album class is called to start the derivation of an Album instance asynchronously. The callback function alb_derived_cb is registered so that it is called when the derivation finishes. A pointer to data contained in the cb_info object is passed to the callback function.
8.3.2 Registering a Callback Function for Handling Responses From Managed Objects
The callback registered in the call to a function for an asynchronous operation is called only once, when the operation is completed. To handle responses from managed objects to an asynchronous function call, you must register a callback specifically for that purpose.
To register a callback for handling responses from managed objects, call the when_resp function on the Waiter instance returned by the asynchronous function call.
In the call to when_resp, specify the callback function for handling responses from managed objects. This callback function is called each time your application receives a response to the asynchronous operation that returned the Waiter instance on which when_resp is called.
Code for registering a callback function to handle responses from managed objects is shown in CODE EXAMPLE 8-4.
CODE EXAMPLE 8-4 Registering a Callback Function for Response Handling
... #include <pmi/hi.hh> // High Level PMI ... Waiter cur; ...if (!(cur=test_album.all_start(DU("topoGetNodeReport"),DU("NULL"),Callback(done_cb, &done)))) { cout << test_album.get_error_string() << endl; exit(9); }if (cur.get_except()) { cout << cur.get_except()->reason() << endl; exit(10); } // subscribe to any future incoming replies cur.when_resp(Callback(asyn_cb,0)); ...In this example, the all_start function of the Album class is called to send an asynchronous action request with a text parameter to all managed objects in an object collection. The when_resp function is called on the Waiter instance returned by the call to all_start. The call to when_resp registers a callback function named asyn_cb. The asyn_cb function is called each time the application receives a response to the asynchronous action from a managed object.
8.3.3 Writing Callback Functions for Asynchronous Operations
Write a callback function to handle each type of asynchronous operation and response you want to process. Each callback function you write must contain the code needed to carry out the processing you require. Writing a callback function involves:
- Defining the signature of the callback function
- Writing code for handling either of the following:
8.3.3.1 Defining the Signature of the Callback Function
The signature of any callback function you write must be in the following format:
void callbackName (Ptr userdata, Ptr calldata)
- callbackName is the name you assign to your callback function.
- userdata is the data passed to the callback by your application.
- calldata is the data passed to the callback by the scheduler that calls the callback function.
Note This format is identical to that required for event-handling callbacks as defined in Section 7.2.2 Writing Callback Functions for Event Handling.
8.3.3.2 Writing Code for Handling a Confirmation That an Asynchronous Operation Has Finished
In the body of your callback function, provide code that you want your application to run when an asynchronous operation finishes. The code you write depends on what you want the callback to do when it is run. If you do not need to process the data that the scheduler passes to the callback function, you can ignore callback's second argument.
An example of a callback for processing a confirmation that an asynchronous operation has finished is given in CODE EXAMPLE 8-5.
CODE EXAMPLE 8-5 Callback for Completion of an Asynchronous Operation
... #include <pmi/hi.hh> // High Level PMI ... void alb_derived_cb(Ptr context_data, Ptr){ callback_data *cb_data = (callback_data *)context_data; char **args_list = cb_data->get_args(); char *g_class = cb_data->get_derivation_class(); fprintf(stdout, "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); fprintf(stdout, "%s: Album Derivation Callback Function\n", args_list[0]); Album alb = cb_data->get_album(); if (!alb) fprintf(stderr, "%s: Error initializing Album in callback\n", args_list[0]);else { fprintf( stdout, "Number of %s instances found: %d\n", g_class, alb.num_images()); } fprintf(stdout, "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); delete cb_data; fprintf(stdout, "\n%s: Program complete, terminating MIS connection\n\n", args_list[0]); MIS_Connected = FALSE; }When this callback is run, it checks for the success of the derivation. If the derivation fails, the callback prints a message stating that the derivation has failed. If the derivation succeeds, the callback prints the number of Image instances in the derived Album instance.
8.3.3.3 Writing Code for Handling Responses From Managed Objects
In the body of your callback function, provide code that you want your application to run when it receives a response from a managed object. The code you write depends on what you want the callback to do when it is run.
Making Correct Use of the Data Passed By the Scheduler
If you intend to register your callback by calling when_resp, you must use the data that the scheduler passes to the callback function to build a CurrentEvent object. This data is a void pointer. It is passed in the second argument of the callback.
If you ignore this data, memory allocated by the scheduler for this data is not freed, leading to a memory leak.
Code that correctly uses the data passed by the scheduler is shown in CODE EXAMPLE 8-6.
CODE EXAMPLE 8-6 Correct Use of Data Passed by the Scheduler
... void cb(Ptr userdata, Ptr calldata){ // do whatever if(calldata){ CurrentEvent ce(calldata); // Do whatever and use and access the information // within the CurrentEvent ce } // do whatever } ...In this example, the data passed by the scheduler is used in the callback to build a CurrentEvent object. The memory allocated by the scheduler for this data is freed, thereby avoiding a memory leak.
Code that does not correctly use the data passed by the scheduler is shown inCODE EXAMPLE 8-7.
CODE EXAMPLE 8-7 Incorrect Use of Data Passed by the Scheduler
... void cb(Ptr userdata,Ptr calldata){ // do whatever but never use calldata to build // a CurrentEvent object. } // or void cb(Ptr userdata){ // do whatever and ignore the second argument } ...In this example, the data passed by the scheduler is ignored, leading to a memory leak.
Extracting Information Contained In a Response From a Managed Object
Extract the information contained in responses that is useful to the user of your application. To extract information contained in a response, call functions of the CurrentEvent class in the body of your callback function.
The information available depends on the response.
Information available from all responses and the functions for extracting the information are given in TABLE 8-7.
TABLE 8-7 Information Available From All Responses A pointer to the response that caused the callback function to be called. This pointer has no meaning outside the scope of the CurrentEvent object that represents the response. get_message The Album instance associated with the response. get_album The Image instance associated with the response. get_image The class of the managed object that sent the response. get_objclass The fully distinguished name (FDN) of the managed object that sent the response. get_objname
Information available only from action replies sent in response to CMIS M-ACTION requests and the functions for extracting the information are given in TABLE 8-8.
TABLE 8-8 Information Available Only From Action Replies The action reply information in encoded form. get_info_raw The name of the action request. get_eventtype
Note The information available from responses is a subset of the information available from event notifications. Functions of the CurrentEvent class that are not listed in TABLE 8-7 and TABLE 8-8 extract meaningful information only from event notifications, not from responses. For more information, refer to Section 7.2.2.2 Extracting Information From an Event Notification.
Example Callback for Handling Responses From Managed Objects
A callback function for handling responses from managed objects is shown in CODE EXAMPLE 8-8.
CODE EXAMPLE 8-8 Callback for Handling Responses From Managed Objects
... #include <pmi/hi.hh> // High Level PMI ... void asyn_cb( Ptr , Ptr calldata){ static int num = 1; cout << "\nExecuting asyn1 callback function for "; cout << num << " times"; cout << endl; cout << "----------------------------------------------" << endl; num++; // Get and print the new attribute value. cout << "During the all_start operation "; cout << endl; if(calldata){ CurrentEvent ce(calldata); cout << "OBJNAME = " << ce.get_objname().chp() << endl; cout << "OBJCLASS = " << ce.get_objclass().chp() << endl; MessagePtr msg = (MessagePtr)ce.get_message(); if(msg->type()==ACTION_RES){ ActionRes* srmsg = (ActionRes*)msg; cout << "OBJCLASS = " << oc2name(srmsg->oc).chp() << endl; cout << "FDN = " << oi2fdn(srmsg->oi).chp() << endl; cout << "ACTION-TYPE = " << endl; (srmsg->action_type).print(stdout); cout << "\n" << endl; cout << "ACTION-REPLY = " << endl; (srmsg->action_reply).print(stdout); cout << "\n" << endl; } Morf mf = ce.get_info_raw(); Asn1Value val = mf.get_value(); if(val){ cout << "info_raw() field of current event ACTION-REPLY = " << endl; val.print(stdout); cout << "\n" << endl; } cout << "eventtype() field of current event ACTION-TYPE = " << ce.get_eventtype().chp() << endl; cout << "Information setting in the current event related Album " << endl; cout << "Derivation rule for the Album " << ce.get_album().get_prop(duNICKNAME).chp() << " is : " << ce.get_album().get_derivation().chp() << endl; cout << "\n" << endl; cout << "Information setting in the current event related Image" << endl; Image im = ce.get_image(); cout << " image name is " << im.get_objname().chp() << endl; cout << " image class is " << im.get_objclass().chp() << endl; cout << " image state is " << im.get_state().chp() << endl; cout << " image last_error is " << im.get_last_error().chp() << endl; if (im.exists()) cout << " image exists " << endl; else cout << " image does not exist " << endl; cout << " attribute(s) and attribute value(s) setting in the image " << endl; Array(DU) attr_names = im.get_attr_names();for (int i=0; i<attr_names.size; i++) { char *name = strdup(attr_names[i].chp()); cout << name; cout << ": "; cout << im.get_str(name).chp() << endl; } cout << "\n" << endl; } }The callback in this example checks a response to determine if the response is an action reply. If the response is an action reply, the following information about the action reply are printed:
- The managed object class of the action reply
- The FDN of the action reply
- The type of action request sent
- The text of the action reply message
For any response, the callback then prints out the following information:
- The nickname of the object collection to which the request was sent
- The derivation string of the object collection to which the request was sent
- The FDN of the managed object that sent the reply
- The managed object class of the managed object that sent the reply
- The state of the managed object that sent the reply
- The last error associated with the managed object that sent the reply
8.3.4 Scheduling Response Handling
An application cannot predict when it will receive a response to an asynchronous operation. Therefore, to process a response to an asynchronous operation, an application must be able to interrupt whatever function is being performed and process the response when it is received. To interrupt the function it is currently performing, an application requires a scheduler. A scheduler retrieves each event from the event queue and calls the function required to process the event correctly.
To schedule response handling, use one of the schedulers that Solstice EM provides:
- sched - For applications without a graphical user interface
- xtsched - For applications with a graphical user interface
Use these schedulers for response handling in the same way that you use them for event handling as explained in:
- Section 7.3.1 Scheduling for Applications Without a Graphical User Interface
- Section 7.3.2 Scheduling for Applications With a Graphical User Interface
When you use the sched scheduler for response handling, you can schedule response handling in either of the following modes, depending on the requirements of your application:
- Nonblocking mode. Schedule response handling in nonblocking mode if you want your application to continue with other operations while an asynchronous operation is outstanding.
- Blocking mode. Schedule response handling in blocking mode if you want your application to carry out some operations only after an asynchronous operation has finished. Blocking mode enables your application to carry out other operations while the asynchronous operation is outstanding.
When you use the xtsched scheduler for response handling, you can schedule response handling in nonblocking mode only.
8.3.4.1 Scheduling Response Handling in Nonblocking Mode
In nonblocking mode, your application continues with other operations while an asynchronous is outstanding.
To schedule response handling in nonblocking mode, activate the scheduler in a loop as shown in CODE EXAMPLE 8-9.
CODE EXAMPLE 8-9 Scheduling Nonblocking Asynchronous Response Handling
... #include <pmi/hi.hh> // High Level PMI ... // Non-Blocking Example (note: boot_cb not shown in this example): Waiter waiter1 = cell_image.start_create(Callback(boot_cb, 0)); waiter1.waitmore(3.0); // Specify 3 sec. timeout for boot operation while (MIS_Connected) dispatch_recursive(TRUE); ...In this example, the dispatch_recursive function of the sched scheduler is called while the application remains connected to an MIS.
8.3.4.2 Scheduling Response Handling in Blocking Mode
In blocking mode, your application carries out some operations only after an asynchronous operation has finished. Blocking mode enables your application to carry out other operations while the asynchronous operation is outstanding.
To schedule response handling in blocking mode, activate the scheduler in a loop only while the asynchronous operation is still outstanding. To test whether the asynchronous operation is still outstanding, call the was_completed function of the Waiter class repeatedly until it returns a value indicating that the operation represented by the Waiter instance has finished.
Outside the loop, call functions for operations that you want to be carried out only after the asynchronous operation has finished.
Inside the loop, call functions for operations you want to be carried out while the asynchronous operation is outstanding. These operations must not block the application.
Code for scheduling response handling in blocking mode is shown in CODE EXAMPLE 8-10.
CODE EXAMPLE 8-10 Scheduling Blocking Asynchronous Response Handling
... #include <pmi/hi.hh> // High Level PMI ... // Blocking Example: Waiter waiter2 = cell_album.all_start_store();while (!waiter2.was_completed){ // Do operations you want to be carried out while the // asynchronous operation is outstanding. These operations // must not block the application. dispatch_recursive(TRUE); } // Continue with operations you want to be carried out only after // the asynchronous operation has finished. ...In this example, attribute values in the MIS for all Image instances in an object collection are updated asynchronously. To ensure that the dispatch_recursive function of the sched scheduler is called only while this operation is still unfinished, it is called in a loop while the was_completed function returns FALSE.
8.3.5 Adding a Callback to the Scheduler Queue
Add a callback to the scheduler queue when you want the callback to be run. Adding a callback to the scheduler queue enables you to specify data that the scheduler passes to your callback when the callback is run.
You only need to add a callback to the scheduler queue if you are implementing an asynchronous function yourself. You do not need to add a callback to the scheduler queue if you are using the asynchronous functions supplied in the Solstice EM APIs.
Adding a callback to the scheduler queue involves:
- Initializing an instance of Waiter by calling an asynchronous function
- Registering the callback by calling the when_resp function on the Waiter instance that you initialized
- Calling the send_resp function on the Waiter instance that you initialized to add the registered callback to the scheduler queue
In the call to send_resp, specify a pointer to the data that the scheduler passes to the callback when the callback is run. Your callback must include code for converting the data into a CurrentEvent instance when the callback is run. If you want to process the data, in your callback, call functions of the CurrentEvent class for processing the data. For more information, refer to Section 8.3.3.3 Writing Code for Handling Responses From Managed Objects.
8.4 Verifying and Changing the Status of an Asynchronous Operation
To verify or change the status of an asynchronous operation, use the instance of the Waiter class returned by the function you called to initiate the asynchronous operation. The instance of Waiter returned enables you verify or change the status of an asynchronous operation by:
- Verifying the result of an asynchronous operation
- Cancelling an asynchronous operation
- Specifying or extending the timeout of an operation
Note The start_create function returns an instance of the Result class, not the Waiter class. Consequently, you cannot check or change the status of an asynchronous operation to add a managed object to the MIS.
8.4.1 Verifying the Result of an Asynchronous Operation
To enable your application to take different actions depending on whether an asynchronous operation succeeds, verify the result of the operation. For example, verify the result of an asynchronous operation to notify the user, or take some other recovery action, if the operation fails.
To verify the result of an asynchronous operation, call the get_except function of the Waiter class.
The get_except function returns one of the following:
- If the operation failed, get_except returns a pointer to an instance of the ExceptionType class. This instance provides information on why the operation failed.
- If the operation succeeded, get_except returns NULL.
The value returned by the get_except function is valid only while the operation is outstanding.
Note The procedure for verifying the result of an asynchronous operations is different from that for asynchronous operations described in Section 4.1.2 Using the get_error_type Function. The get_error_type and get_error_string functions of the Waiter class return information about functions of the Waiter class, not about the operation represented by the instance of Waiter.
To obtain information on why an asynchronous operation failed, call functions of the ExceptionType class as follows:
- To obtain the exception type, call the name function of the ExceptionType class.
- To obtain the reason for the failure, call the reason function of the ExceptionType class.
Code for verifying the result of an asynchronous operation is shown in CODE EXAMPLE 8-11.
CODE EXAMPLE 8-11 Verifying the Result of an Asynchronous Operation
... #include <pmi/hi.hh> // High Level PMI ... // WARNING: get_except() returns a 0 pointer if operation successful. // Following code can also trigger segmentation faults if error occurs // with SEM 3.0. Bottom line: AVOID USE OF ASYNC FUNCTIONALITYif (cell_waiter.get_except()) { fprintf(stderr, "Waiter: Exception: %s, Reason: %s\n", (cell_waiter.get_except())->name(), (cell_waiter.get_except())->reason()); }If the asynchronous operation represented by the instance of Waiter named cell_waiter fails, an error message is written to stderr. The text returned by the calls to the name and reason functions of ExceptionType is incorporated in the message written to stderr.
8.4.2 Cancelling an Asynchronous Operation
Cancel an asynchronous operation that you no longer require to be completed.
To cancel an outstanding asynchronous operation, call the cancel function of the Waiter class.
8.4.3 Changing the Timeout of an Asynchronous Operation
The timeout of an asynchronous operation specifies the maximum length of time an application allows for an asynchronous operation to finish. If an asynchronous operation is not completed within this length of time, the operation is cancelled.
Change the timeout of an asynchronous operation if you want the timeout to change in response to an event. For example, if your application is waiting for several events, change the timeout each time an event is received so that your application only times out if the interval between events exceeds some threshold.
To change the timeout of an asynchronous operation, call the waitmore function of the Waiter class. In the call to the Waitmore function, you have to specify the timeout. The timeout is a typedef double that represents the length of the timeout in seconds.
Code for changing the timeout of an asynchronous operation is given in CODE EXAMPLE 8-12.
CODE EXAMPLE 8-12 Changing the Timeout of an Asynchronous Operation
... #include <pmi/hi.hh> // High Level PMI ... // Nonblocking Example (note: boot_cb not shown in this example): Waiter waiter1 = cell_image.start_create(Callback(boot_cb, 0)); waiter1.waitmore(3.0); // Specify 3 sec. timeout for creation operation ...In this example, the timeout for an asynchronous operation to add a managed object to an MIS is changed to 3.0 seconds.
|
Sun Microsystems, Inc. Copyright information. All rights reserved. |
Doc Set | Contents | Previous | Next | Index |