VIX API Concepts : Event Models

Event Models

The Vix API provides the flexibility to handle events in different ways, depending on the needs of the client. The "event pump" mechanism allows you to process asynchronous operations in single-threaded clients. This section discusses both ways to manage asynchronous operations.

Multi-Threaded Event Model

The multi-threaded event model is the default model for Vix clients. Its use is described in detail in the section above calledCallback Functions. This model is the easiest to use, if your client code is thread-safe.

Using this model, the Vix library creates worker threads as needed to process asynchronous operations in parallel. Callback functions are invoked on the worker threads under the control of the Vix library.

Single-Threaded Event Model

Using the single-threaded model, all asynchronous processing and all event reporting is deferred until the thread callsVix_PumpEvents(). Each call to Vix_PumpEvents() does more work on an asynchronous operation. At appropriate times during the operation, control is transferred to the callback routine, if one was specified in the call to the asynchronous function that began the operation.

The single-threaded event model is useful for clients that are not thread safe, or that depend on libraries that are not thread-safe. All processing is done in a single thread. You have to write extra code for a polling loop, but you need not be concerned with synchronizing multiple threads.

Using the Event Pump

To use the event pump:

  1. Connect to the host with a flag indicating that events are to be triggered by Vix_PumpEvents() and received by a callback function on the same thread. Otherwise, events are reported asynchronously and callback functions are invoked on a pool of Vix worker threads.

    The flag is a value of VIX_HOSTOPTION_USE_EVENT_PUMP passed in the options parameter to theVixHost_Connect() function.

    Example 2-15.
    VixHandle hostHandle = VIX_INVALID_HANDLE;
    VixHandle jobHandle = VIX_INVALID_HANDLE;
    VixError err;
     
    jobHandle = VixHost_Connect(VIX_API_VERSION,
                                VIX_SERVICEPROVIDER_VMWARE_WORKSTATION,
                                NULL, // hostName
                                0, // hostPort
                                NULL, // userName
                                NULL, // password,
                                VIX_HOSTOPTION_USE_EVENT_PUMP, // options
                                VIX_INVALID_HANDLE, // propertyListHandle
                                NULL, // callbackProc
                                NULL); // clientData
    err = VixJob_Wait(jobHandle,
                      VIX_PROPERTY_JOB_RESULT_HANDLE,
                      &hostHandle,
                      VIX_PROPERTY_NONE);
    if (VIX_OK != err) {
       // Handle the error...
       goto abort;
    }
  2. Call Vix_PumpEvents() at appropriate times to advance processing of the asynchronous operation.
    Vix_PumpEvents(hostHandle, VIX_PUMPEVENTOPTION_NONE);

    If your application is multithreaded, you can call this function from a separate thread. You can never call VixJob_Wait()on the same thread that also calls Vix_PumpEvents(). However, you can call Vix_PumpEvents() on one thread andVixJob_Wait() on another thread.

  3. Check the results of the asynchronous operation, either by polling or by callback. The polling method is explained inPolling for Completion in a Single-Threaded Client. The callback method is explained in Using a Callback Function in a Single-Threaded Client.

Polling for Completion in a Single-Threaded Client

Single-threaded clients must share the thread between the main logic of the program and the processing that takes place as a result of calling an asynchronous function. In a single-threaded client, the processing can only take place during a call toVix_PumpEvents().

That fact implies that the single-threaded client cannot call VixJob_Wait(). In a multi-threaded client, a call to VixJob_Wait()returns when the asynchronous operation is completed by another thread. However, in a single-threaded client, VixJob_Wait()never returns because there is no processing happening on any thread during the call to VixJob_Wait().

One solution is to poll for completion using VixJob_CheckCompletion() instead of calling VixJob_Wait(). You alternate pumping with polling, as in the following example.

  1. Example 2-16.
// Function to poll for completion.
// Returns TRUE if successful; otherwise returns FALSE.
Bool CheckCompletion(VixHandle hostHandle,
                     VixHandle jobHandle,
                     int timeOut)
{
   Bool completed = FALSE;
   VixError err = VIX_OK;
   int secondCount = 0;
 
   while (!completed && secondCount < timeOut) {
      Vix_PumpEvents(hostHandle, VIX_PUMPEVENTOPTION_NONE);
      
      err = VixJob_CheckCompletion(jobHandle, &completed);
      if (VIX_OK != err) {
         return FALSE;
      }
      
      secondCount++;
      sleep(1);
   }
   
   if ((!completed) && (secondCount == ONE_MINUTE)) {
      return FALSE;
   }
   
   return TRUE;
}
 
// Part of virtual machine processing below.
VixError err = VIX_OK;
VixHandle jobHandle = VIX_INVALID_HANDLE;
VixPowerState powerState = 0;
 
// Suspend the virtual machine.
jobHandle = VixVM_Suspend(vmHandle,
                          0, // powerOnOptions,
                          VIX_INVALID_HANDLE, // propertyListHandle,
                          NULL, // callbackProc,
                          NULL); // clientData
 
// The powerState may be VIX_POWERSTATE_SUSPENDING for a few seconds.
// Wait for completion.
if (CheckCompletion(hostHandle, jobHandle, 30)) {
   // Now the powerState should be ready.
   err = Vix_GetProperties(vmHandle,
                           VIX_PROPERTY_VM_POWER_STATE,
                           &powerState,
                           VIX_PROPERTY_NONE);
   if (VIX_OK != err) {
      // Handle the error...
      goto abort;
   }
} // CheckCompletion

Using a Callback Function in a Single-Threaded Client

Single-threaded clients also have the option to use callback functions that handle completion. Because the callback has to share the single thread, it cannot happen asynchronously. As with the polling method of completion described in Polling for Completion in a Single-Threaded Client, the client cannot call VixJob_Wait().

In the single-threaded client, processing takes place only during calls to Vix_PumpEvents(). Each call does more work on the operation. If a callback was specified in the call to the asynchronous function that began the operation, the Vix library invokes the callback function during one of the calls to Vix_PumpEvents().

The code to use this method looks like the following example. The main function initiates a host connection operation (specifying a callback function) and then enters a loop to pump events. When the operation has completed, the callback function returns a handle to the host (or an invalid value in case of failure).

  1. Example 2-17.
Bool handleCallbackDone = FALSE;
 
void handleCallback(VixHandle jobHandle,
                    VixEventType eventType,
                    VixHandle moreEventInfo,
                    void *clientData)
{
   /*
    * This function is invoked on completion of an asynchronous operation.
    * If the operation succeeded, this function returns a handle
    * that resulted from the asynchronous operation.
    */
   VixError err;
   VixError asyncErr;
   VixHandle resultHandle = VIX_INVALID_HANDLE;
 
   /*
    * Ignore progress callbacks. Check only for final signal.
   */
   if (VIX_EVENTTYPE_JOB_COMPLETED != eventType) {
      return;
   }
 
   err = Vix_GetProperties(jobHandle,
                           VIX_PROPERTY_JOB_RESULT_HANDLE,
                           &resultHandle,
                           VIX_PROPERTY_JOB_RESULT_ERROR_CODE,
                           &asyncErr,
                           VIX_PROPERTY_NONE);
   if (VIX_OK != err) {
      // Failed to get properties. Bail.
      *clientData = VIX_INVALID_HANDLE;
      handleCallbackDone = TRUE;
      return;
   }
 
   if (VIX_OK == asyncErr) {
      *clientData = (void) resultHandle;
   } else {
      // The asynchronous operation failed. Bail.
      *clientData = VIX_INVALID_HANDLE;
   }
   
   handleCallbackDone = TRUE;
} // end handleCallback
 
int main()
{
   VixHandle hostHandle = VIX_INVALID_HANDLE;
   VixHandle jobHandle = VIX_INVALID_HANDLE;
   char *contextData = "Hello, Vix";
 
   jobHandle = VixHost_Connect(VIX_API_VERSION,
                               VIX_SERVICEPROVIDER_VMWARE_VI_SERVER,
                               "https://server2.example.com/sdk", // hostName
                               0, // hostPort
                               "root", // username
                               "secretpw", // password
                               VIX_HOSTOPTION_USE_EVENT_PUMP, // options
                               VIX_INVALID_HANDLE, // propertyListHandle
                               handleCallback,
                               (void *) &hostHandle);
 
   // Release handle, if not using it.
   Vix_ReleaseHandle(jobHandle);
   jobHandle = VIX_INVALID_HANDLE;
 
   // Pump events and wait for callback.
   handleCallbackDone = FALSE;
   while (!handleCallbackDone) {
      Vix_PumpEvents();
   }
   
   if (VIX_INVALID_HANDLE == hostHandle) {
      printf(":-(\n");
   } else {
      printf(":-)\n");
   }
} // end main
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值