Parallels Service and all running virtual machines are constantly monitored for any changes in their state and status. When something important changes, an event of the corresponding type is triggered. A client program can receive the data describing the event and take appropriate action if needed. Events are received asynchronously (it is not possible to receive event-related data on-demand). All possible event types are defined in the PRL_EVENT_TYPE
enumeration. Most of them are triggered automatically when the corresponding action takes place. Some event types are generated in response to client requests and are used to pass the data to the client. For example, the PET_DSP_EVT_HW_CONFIG_CHANGED
event triggers when the host configuration changes, the PET_DSP_EVT_VM_STOPPED
event triggers when one of the virtual machines is stopped, etc. On the other hand, an event of type PET_DSP_EVT_FOUND_LOST_VM_CONFIG
is generated in response to the PrlSrv_StartSearchVms
function call and is used to pass the information about unregistered virtual machines to the client (see Searching for Virtual Machines for more info).
In order to receive an event notification, a client program needs an event handler. An event handler (also called callback) is a function that you have to implement yourself. We've already discussed event handlers and provided code samples in the Asynchronous Functions section. If you haven't read it yet, please do so now. To subscribe to event notifications, you must register your event handler with the Service. This is accomplished using the PrlSrv_RegEventHandler
function. Once this is done, the event handler (callback) function will be called automatically by the background thread every time it receives an event notification from the Service. The code inside the event handler can then handle the event according to the application logic.
The following describes the general steps involved in handling an event in a callback function:
PrlHandle_GetType
function (determines the type of the handle received) and then checking if the handle is of type PHT_EVENT
(not PHT_JOB
).PrlEvent_GetType
function. Check the event type against the PRL_EVENT_TYPE
enumeration. If it is relevant, continue to the next step.PrlEvent_GetIssuerType
or PrlEvent_GetIssuerId
function to find out what part of the system triggered the event. This could be a host, a virtual machine, an I/O service, or a Web service. These are defined in the PRL_EVENT_ISSUER_TYPE
enumeration. PrlEvent_GetServer
function.PHT_EVENT
received by the callback function may include event related data. The data is included in the event object as a list of handles of type PHT_EVENT_PARAMETER
.
You can use the PrlEvent_GetParamsCount
function to determine the number of parameters the event object contains. Some of the events simply inform the client of a change and don't include any data. For example, the virtual machine state change events (started, stopped, suspended, etc.) indicate that a virtual machine has been started, stopped, suspended, and so forth. These events don't produce any data, so no event parameters are included in the event object. The type of the data and the number of parameters depends on the type of the event received. If you know that an event contains data by definition, continue to the next step, if not, skip it.PrlEvent_GetParam
function in each iteration. This function obtains a handle of type PHT_EVENT_PARAMETER
which contains the parameter data. Use the functions of the PHT_EVENT_PARAMETER
handle to process the data as needed. In general, an event parameter contains the following:PrlEvtPrm_GetName
function. This is an internal name and is, most likely, not of any interest to a client application developer.PRL_PARAM_FIELD_DATA_TYPE
enumeration. To retrieve the parameter data type, use the PrlEvtPrm_GetType
function. PHT_EVENT_PARAMETER
handle. For example, a boolean value must be retrieved using the PrlEvtPrm_ToBoolean
function, the string value must be retrieved using the PrlEvtPrm_ToString
function, if a parameter contains a handle, it must be obtained using the PrlEvtPrm_ToHandle
, etc. The meaning of the value is usually different for different event types. For the complete list of PHT_EVENT_PARAMETER
functions, please see the Parallels C API Reference.The following is a simple event handler function that illustrates the implementation of the steps described above. We are not including an example of how to register an event handler here, please see the Asynchronous Functions section for that.
static PRL_RESULT simple_event_handler(PRL_HANDLE hEvent, PRL_VOID_PTR pUserData)
{
PRL_RESULT ret = PRL_ERR_UNINITIALIZED;
PRL_HANDLE_TYPE nHandleType;
// Get the type of the handle recevied.
PrlHandle_GetType(hEvent, &nHandleType);
// If this is a job, release the handle and exit.
// It is up to you if you want to handle jobs and events in
// the same callback function or if you want to do it in
// separate functions. You can have as many event handlers
// registered in your client program as needed.
if (nHandleType == PHT_JOB)
{
PrlHandle_Free(hEvent);
return 0;
}
// If it's not a job, then it is an event (PHT_EVENT).
// Get the type of the event received.
PRL_EVENT_TYPE eventType;
ret = PrlEvent_GetType(hEvent, &eventType);
// Check the type of the event received.
switch (eventType) {
case PET_DSP_EVT_VM_STARTED:
// Handle the event here...
printf("A virtual machine was started. \n");
break;
case PET_DSP_EVT_VM_STOPPED:
// Handle the event here...
printf("A virtual machine was stopped. \n");
break;
case PET_DSP_EVT_VM_CREATED:
// Handle the event here...
printf("A new virtual machine has been created. \n");
break;
case PET_DSP_EVT_VM_SUSPENDED:
// Handle the event here...
printf("A virtual machine has been suspended. \n");
break;
case PET_DSP_EVT_HW_CONFIG_CHANGED:
// Handle the event here...
printf("Parallels Service configuration has been modified. \n");
break;
default:
printf("Unhandled event: %d\n", eventType);
}
}