previous next

Chapter 9: Monitor Plug-in

RealServer plug-ins can monitor resources in the RealServer Property Registry, which is a dynamic repository for a variety of server and client properties. These properties include such values as the number of clients currently connected, the total bandwidth being utilized, and a comprehensive set of statistics for each of these clients. A monitor plug-in can monitor any registry property, receiving notification when RealServer updates the property. Monitor plug-ins can also add their own properties to the registry and receive notifications when those properties change.

Additional Information
For a detailed description of the RealServer Property Registry, including descriptions of the various server, client, and session properties, see "Appendix F: RealServer Property Registry".

Monitor Plug-in

Monitor plug-ins do not need to be standalone modules. Any server-side plug-in can implement the monitoring features described in this section. A file format plug-in, for example, can check the registry for customized configuration parameters.

Additional Information
For information on receiving system error messages, See "Chapter 15: Status Codes and Errors".

Interfaces

A monitor plug-in implements the following interfaces:

The monitor plug-in uses the following interfaces:

Coding a Monitor Plug-In

The following sections explain how RealServer and a monitor plug-in use the RealSystem interfaces. The sample code included with this SDK illustrates many of these features. You can use the sample code as a starting point for building your own plug-in. Refer to the RealSystem SDK header files for more information on function variables and return values.

Note
The order of function calls listed in the following sections provides a generalized explanation and is for illustrative purposes only. Because RealSystem is asynchronous, your plug-in must be able to handle any call made to it while it is processing data or waiting for a response from another object. Do not code your plug-in so that it expects a specific sequence of events to occur as it interacts with RealServer.

Starting Up

When RealServer starts up, it loads each monitor plug-in:

  1. RealServer calls RMACreateInstance to create an instance of the monitor plug-in. See "Creating a Plug-In Instance" for more on this method.

  2. RealServer calls IRMAPlugin::GetPluginInfo, which returns descriptive information used by the RealSystem client. A plug-in used only for monitoring can return NULL for all descriptive values except pDescription, which should be Monitor. Set bLoadMultiple to FALSE to open the monitor plug-in in the RealServer process.

  3. RealServer calls IRMAPlugin::InitPlugin, passing the monitor plug-in a pointer to the RealServer context. Within IRMAPlugin::InitPlugin, the plug-in peforms any necessary initialization, minimally doing the following:

    1. With the RealServer context pointer, the plug-in stores a reference to IRMACommonClassFactory so that it can create RealSystem objects.

    2. The plug-in uses IRMACommonClassFactory::CreateInstance to get an IRMAPNRegistry interface.

    3. The plug-in uses IRMAPNRegistry::CreatePropWatch to create an IRMAPropWatch interface. This interface lets the monitor plug-in set watch points on properties.

    4. Using IRMAPropWatch::Init, the plug-in initializes the property watch interface with the response interface, IRMAPropWatchResponse, which is the monitor plug-in itself. Through the response interface's methods, RealServer notifies the plug-in of additions, modifications, and deletions to the watched properties.

  4. With the registry initialized, the plug-in can set watches through IRMAPropWatch (see "Watching Properties") or IRMAScheduler (see "Using the Scheduler"). The sample code uses a method called CExampleMonitor::SetWatches, but you can use any other method name. The plug-in methods are called when watches are triggered or, if a callback has been put into the Scheduler, whenever the time slice expires.

Watching Properties

The RealServer implementation of monitoring enables monitor plug-ins to watch desired resources much as a debugger does. You can set watches on composites or any other type of property, but there is a subtle difference between the two. For composite properties, RealServer sends notification only when one of the following happens:

For all other properties, RealServer sends notification on one of the following:

Use IRMAPropWatch::SetWatchOnRoot to watch for additions or deletions of properties at the registry's root level. To set watches on specific properties, use one of these methods:

When RealServer adds, modifies, or deletes the watched property, it notifies the plug-in through the IRMAPropWatchResponse::AddedProp, IRMAPropWatchResponse::ModifiedProp, and IRMAPropWatchResponse::DeletedProp methods. This notification includes the watched property's ID value, its datatype, and the ID of its parent property. The plug-in can then query the registry for the property's new value.

Note
From the time the IRMAPropWatch::SetWatchxxx method is called until the time the watch is actually set on the property, if any new properties are added under the composite property about to be watched, notification for these new properties is not sent back to the plug-in.

Keep in mind the following when setting watches:

Using the Scheduler

From the system context pointer it receives during initialization, a plug-in can use IUnknown::QueryInterface to obtain the IRMAScheduler interface. The plug-in then creates an IRMACallback interface and enters it into the Scheduler using one of these methods:

The Scheduler then calls IRMACallback::Func after the specified time slice has elapsed. See the monitor plug-in sample code for an example of one way to do this.

Modifying the Monitor Plug-in Sample Code

The RealSystem SDK includes two monitor plug-in samples: an intermediate sample and an advanced sample.

Intermediate Sample

The RealSystem SDK includes source code for a sample monitor plug-in you can use as a template:

Modify the sample code as follows.

  1. Make copies of the sample files.

  2. Specify copyright and URL information for your plug-in in the CExampleMonitor::GetPluginInfo method.

    Note
    Do not change the pDescription attribute. It must be Monitor.

  3. Replace the following methods with the user interface for your monitor:
    
    CExampleMonitor::PrepareCounter 
    
    
    CExampleMonitor::UpdateCounter
    

  4. Modify the CExampleMonitor::SetWatches method to specify the properties you want to monitor.

  5. Modify the following methods to process the notifications as the watched properties are added, modified, and deleted:
    
    CExampleMonitor::AddedProp 
    
    
    CExampleMonitor::ModifiedProp 
    
    
    CExampleMonitor::DeletedProp 
    

    Tip
    Limit the amount of processing within methods to prevent slowing down RealServer.

Advanced Sample

The sample samples/advanced/expksink/expksink.cpp is an example of a live packet sink plug-in that uses monitoring. It sets a watch on the registry's LiveConnections composite key so that it will receive notifications about new live connections. It then examines the headers and packets sent to the server from the live source. The plug-in can use this information for many purposes, including logging statistics about the live content or archiving the live streams to disk. See the source file for instructions on how the plug-in works.

Examples

Example 1: Adding a Simple Property to the Registry

The following example shows how to add an IntRef property. It demonstrates how the property creator can change its value using a simple "C"-style dereference:


// creator
int* int_val = new int;

*int_val = 99;
...
UINT32 iref_id = m_registry->AddIntRef("mystats.foobar", int_val);
...
/*
modifying the variable pointed to by int_val automatically reflects
in the registry because it is the same address.
*/
(*int_val)++;
...
// accessor -- some other user
INT32 i_val = 0;
m_registry->GetIntByName("mystats.foobar", i_val);
...

Example 2: Adding Statistics to the Registry

This next example adds registry statistics that show how many clients are connected per hour and how many packets are lost per hour.


char *str[] = { "mystats",
"mystats.num_player_per_hour",
"mystats.packets_lost_per_hour"
};

// add the COMPOSITE under which our INTEGER Props will go
mystats_id = m_pRegistry-AddComp(str[0]);
npph_id = m_pRegistry-AddInt(str[1], num_plyrs_per_hr);
plph_id = m_pRegistry-AddInt(str[2], pckts_lost_per_hr);
...

if (m_pRegistry->SetIntById(npph_id, num_plyrs_per_hr) != PNR_OK)
{
// error reporting here...
}

This code adds the composite property mystats to the registry. This property contains the two string properties mystats.num_player_per_hour and mystats.packets_lost_per_hour. To retrieve the values of the properties you can do either of the following:


int int_val = 0;
if (m_pRegistry->GetIntByName(str[1], int_val) != PNR_OK)
{
// do some error checking here
}

or:


int int_val = 0;
if (m_pRegistry->GetIntById(npph_id, int_val) != PNR_OK)
{
// do some error checking here
}

For a string, retrieve the value as follows:


IRMABuffer* str_val = 0;
if (m_pRegistry->GetStrByName(prop_name, str_val) != PNR_OK)
{
// error checking here
}
// after you are done with the buffer RELEASE it
str_val-Release();

Note
When retrieving string values, make sure that you pass in a pointer to an IRMABuffer that has not been created. RealServer returns a created buffer with the string value in it. Be sure to use IUnknown::Release to release the buffer after using it.

To get the unique ID value of a property, pass the property name to the IRMAPNRegistry::GetId method. If the property does not exist, the method returns 0 (zero) as the ID.


Copyright © 2000 RealNetworks
For technical support, please contact supportsdk@real.com.
This file last updated on 05/17/00 at 12:50:19.
previous next