Solstice Enterprise Manager 4.1 Developing C++ Applications | ![]() ![]() ![]() ![]() ![]() |
Writing Management Protocol Adaptors (MPAs)
The Solstice EM MIS (Management Information Server) is responsible for maintaining the MIT (Management Information Tree) and ensuring that all activity within the MIT is transparent to an application. This transparency allows applications to make requests for information in a normalized fashion without regard for object location or communications protocol. The MIS resolves the request and routes it to an appropriate entity that is capable of making the correct protocol request. These entities are called protocol adaptors. Adaptors exist to map information into the MIT maintained by the MIS. The Management Protocol Adaptors (MPAs) shipped with Solstice EM exist as separate processes from the MIS. Three such adaptors are shipped with Solstice EM: the SNMP MPA, the RPC MPA, the CMIP MPA, and the JDMK MPA. These adaptors provide the protocol translation into the SNMP, RPC, CMIP, and JDMK domains respectively.
This chapter explains how to write MPAs.
- Section 11.1 Review of MIS Architecture
- Section 11.2 Initializing Management Protocol Adaptors and Protocol Driver Modules
- Section 11.3 Routing Messages
- Section 11.4 MPA/PDM Request Management
- Section 11.5 Timer Management
- Section 11.6 File Descriptor Management
- Section 11.7 Notifications
- Section 11.8 Sample MPA/PDM Source Code
- Section 11.9 Developing an Adaptor
11.1 Review of MIS Architecture
The MIS has a modular architecture. Modules are connected by Service Access Points (SAPs). These SAPs provide an asynchronous bi-directional message pipe interface. The core of MIS is the Message Routing Module (MRM) which routes messages to the appropriate modules. New modules can be added to the MIS by attaching a SAP from the new module to the MRM. Each SAP has a unique address which is registered with the MRM when it is attached.
New adaptors are introduced to the system by creating a new SAP to the MRM. (For MPA, no new SAP needs to be created. All MPAs are routed by the same MPA SAP.)
The figure bellow illustrates some of the modules within the MIS.
FIGURE 11-1 MIS Architecture
![]()
The shaded components in FIGURE 11-1 illustrate how users can add new adaptors to communicate to a proprietary device X. The two choices are clearly indicated, MPA or PDM.
All requests are initially sent to the Message Routing Module (MRM). The MRM uses configuration information maintained in the MIT to determine where to satisfy the request. Local requests are sent to the OAM. Remote requests are directed to the appropriate adaptor that has registered to handle that remote portion of the MIT.
Note Both the MPA and the PDM use SAP to communicate to the MRM. There is very little difference between a MPA and a PDM once the SAP has been created. They both receive identical messages through the same interface.
11.2 Initializing Management Protocol Adaptors and Protocol Driver Modules
This section describes how Management Protocol Adaptors and Protocol Driver Modules are initialized.
11.2.1 Services Access Points (SAPs)
SAPs provide an asynchronous message passing service. The message set is based on the set of CMIP Protocol Data Units (PDUs). The complete set of messages that can be passed over a SAP is defined in message.hh.
All SAP's are C++ class instances derived from the C++ MessageSAP class defined in message.hh. This class defines the interfaces that allow messages to be sent and received over SAP pairs. An initialized SAP consists of a coupled pair of MessageSAP instances.
Note SAP will now be used to refer to an initialized SAP pair.
Once a SAP has been initialized, the following functions may be performed:
This set of functions provides the following message services:
The interface is defined to be asynchronous. This is achieved using callbacks. Callbacks are a C++ class that consist of a static function pointer and user data. The user data is passed as a parameter to the callback function when the function is invoked.
Example 1
The following example from the fdn_register function in samp_utils.cc illustrates a CONFIRMED request message.
Note A callback is created with a static function called pdm_receive_resp as the callback function pointer. The callback data is the SAP instance pointer. The send function includes the callback recv_cb in the send arguments.
When the MIS completes the request, the pdm_receive_resp function is called with two parameters. The first parameter is the SAP and the second is a response handle which is used to receive the message response.
Example 2
The following example excerpt is from the msgio.cc module and illustrates the pdm_receive_resp function.
SAPs are initialized by creating SAP pairs. When a SAP pair is created, the init_kernel_msg_sap function is used. The init_kernel_msg_sap function is a utility function which couples two SAPs. Once the SAPs have been coupled, the local SAP must have two callback functions initialized: the receive request callback and the detached callback.
The receive request callback handler is the handler which is invoked when message requests are sent to the SAP. The detach callback handler is invoked when the remote SAP is deleted.
11.2.2 Initializing a Management Protocol Adaptor
Initializing a Management Protocol Adaptor involves:
- Creating the listen port and request SAP
- Connecting to the MIS and using extract raw SAP
- Locking the application discriminator
11.2.2.1 Creating the Listen Port and Request SAP
The MIS to MPA communication is a form of CMIP over TCP/IP. The MIS creates and manages associations to an MPA on a per request basis. If an association is not used for a period of time the association is released. If an association is already established it will be reused for subsequent requests. Each request has a request identifier which allows for multiple requests to be outstanding at any one time. To facilitate demand based association establishment, the MPA must allocate an IP listen port. An IP listen port is where the MPA listens for association requests from the MIS.
The utility function init_mpa creates both a SAP and a listen port.
- init_mpa(portnum, &p_sap);
where portnumber is a port number for an IP socket, and p_sap is the address of a pointer to a MessageSAP data type.
11.2.2.2 Connecting to the MIS and Using get_raw_sap
Because the underlying transport mechanism for this SAP might not be active (that is, an underlying association is not established), another SAP must be created to send event reports to the MIS. This other SAP is allocated by creating a platform instance which is connected to the MIS. This platform instance gives access to an ApplMessageSAP. This SAP is based on another MessageSAP implementation. Because the implementation is derived from MessageSAP, the ApplMessageSAP can be used as a MessageSAP. This is possible through C++ inheritance and virtual function mechanisms.
Example
The following code example illustrates how to create a SAP that sends event reports to the MIS and initialize the resultant SAP to receive requests and disconnects.
Once the platform instance has been created, the get_raw_sap method returns the SAP which can be used for sending event reports to the MIS.
11.2.2.3 Locking the Application Discriminator
This step must be completed to allow for proper operation of the MPA. It is most important, as locking the application discriminator has direct impact on system performance. Every platform instance creates an application object instance within the MIS as long as the platform instance is instantiated. Each application object instance contains a discriminator which forwards all platform notifications to the connected application. The MPA typically does not require this feature.
To disable event forwarding, the application instance discriminator must be locked.
Example
The following example excerpt from the samp_main.cc module in the samples directory illustrates this locking mechanism.
11.2.3 Initializing a Protocol Driver Module
Protocol Driver Modules are shared libraries that are loaded at MIS start-up time. The MIS looks in the $EM_HOME/config/EM_shared_libs file for a list of libraries to load. Once it finds an entry in that file, it uses the dlopen() system call to load that library. Once the library is loaded, the MIS looks for an instance of the DynLoader class that matches the name of the loaded library. Once the Dynloader instance has been located, the entry point is invoked with a D_LOAD command.
Note The second parameter of the instance of the declared DynLoader must match the name of the shared library. See dyn_lib.cc for an example.
Initializing a Protocol Driver Module involves:
- Creating a kernel message SAP pair
- Registering the SAP with the Fully Distinguished Name (FDN) table
11.2.3.1 Creating a Kernel Message SAP
A kernel message SAP pair is created using the init_kern_msg_sap function.
extern Result init_kernel_msg_sap ( Address , MessageSAP ** );This utility function creates a pair of coupled kernel message SAPs. It returns to the caller a pointer to a local MessageSAP and initializes the remote SAP to be attached to the MRM at the SAP Address supplied. This Address must be the same as the Address supplied in the FDN table configuration step. See the section on "Example of Timer Initialization" for more information on Address Format.
Each request (message) contains a destination address field dest. The MRM searches in its list of attached SAPs for an address match. When the destination address of a request matches a registered SAP, the request is routed over that SAP.
Note The destination field component is completed by the lookup code within the MIS.
11.2.3.2 Registering an FDN Table Entry
The utility function fdn_register in samp_utils.cc illustrates how to add an entry to the FDN table.
Result fdn_register(MessageSAP *, int, Asn1Value &);The fdn_register function creates a table entry which specifies a mapping between a fully distinguished name (FDN) and a specific address. It takes three parameters to create a table entry:
- A SAP over which to send the addfdn ACTION request
- An integer which specifies the SAP TAG (unique identifier for a SAP)
- An encoded distinguished name
Example
The following example from dyn_libs.cc illustrates the creation of a table entry:
See Section11.3.2 MPA and PDM Addresses" for information on using EM_config. See Section11.3.1.1 Address Classes" for more information on the AC_PRIMITIVE class.
11.3 Routing Messages
11.3.1 How Messages are Routed to the Adaptors
The MIS contains a table which is analogous to the NFS mount table that the UNIX kernel maintains. The table is a complete mapping of the remote MIT. The MRM searches this table for complete or partial matches of the Distinguished Name (DN) for every request. If there is a match, the MRM stores the address information found in the FDN table entry in the destination field of the message and forwards the message to the SAP that matches that address.
To route a message to an adaptor the FDN table must previously have been updated with the DN or DNs that the adaptor is responsible for and an address for the adaptor's SAP.
The FDN table is updated by two action requests: emAddFdnEntry and emRemoveFdnEntry. These action requests are defined in the em.gdmo document. The fdn_register function uses these actions to update the FDN table. The CMIP Configuration utility (em_cmipconfig) uses the same actions to achieve the same purpose.
The FDN table entry has two components: the DN and the Address. The address component is based on the address C++ class defined in address.hh. An address has three components:
- class, type of Address
- tag, particular instance of a particular class
- value, data associated with that address class
11.3.1.1 Address Classes
Four address classes are defined:
- AC_DEFAULT
- Implies default routing based on type, for example, an event report is always routed to the EMM.
- AC_APP
- Is the address class for SAPs that are attached to applications. Each PMI application results in an Application SAP being created. The address class of each application SAP is AC_APP.
- AC_DIR_SERVICE
- Is reserved for directory service management.
- AC_PRIMITIVE
- Is the address class for PDMs and MPAs
11.3.1.2 AC_PRIMITIVE Address Tags (SAP number)
Each Address class uses the tag value to uniquely identify SAP instances. For the purposes of developing PDMs or MPAs, familiarity with AC_PRIMITIVE tags is critical.
The following is a list of the well known AC_PRIMITIVE tags:
Note The tags listed above are the well known AC_PRIMITIVE tags that are in use by the MIS system. Providers of new PDMs must choose a value outside this range.
11.3.1.3 Address Data (aval)
The data field of an address can be used for any purpose. It is a DataUnit which is of variable length. Of particular interest is the aval syntax for the AT_PRIM_CMIP_PRES_ADDR tagged AC_PRIMITIVE class. This contains a complete Presentation Address using the following syntax:
length byte, Presentation Selector,
length byte Session Selector,
length byte, Transport Selector,
count byte (number of Network Selectors),
length byte, Network Selector.....This is a series of octets, one octet of length followed by value octets. A length value of -1 (255) indicates a null selector.
11.3.2 MPA and PDM Addresses
11.3.2.1 PDM Addresses
A PDM Address is defined to have the following values
- class, AC_PRIMITIVE
- tag, user specified tag, an integer value outside of the range of the well defined set listed above
- value, Data Portion is user definable
Example
The following example from dyn_lib.cc serves as an illustration:
Note A convention exists to ensure that user-supplied PDMs use conflicting PDM SAP numbers. This convention is illustrated above. The convention consists of specifying the PDM number in the $RUNTIME/conf/EM-config file which can be extracted using the GETENV macro.
11.3.2.2 MPA Addresses
MPAs have one more level of indirection than PDMs. The additional level allows the MPA to be a separate process that can be run anywhere in the TCP/IP domain. The MPA addresses are defined as:
- class, AC_PRIMITVE
- tag, AT_PRIM_MPA_ADDR.
The developer need not worry about configuring an MPA Address programmatically since the Address for an MPA is configured using the em_cmipconfig utility. The em_cmipconfig utility creates an address where the aval portion contains all the relevant configuration information. The MIS extracts this information and presents it to the MPA using the remote_oi and remote fields of the message request sent to the MPA request routine.
The following fields need to be configured for a custom MPA:
- Entity Name
- Custom MPA: The port and hostname fields must be completed.
- Session Selector
- Network SAP: The Network address of the entity containing the real object should be included.
- FDN
Note If the Presentation address of the remote entity has a null session selector, the session selector must be configured with some default value (for example, "MPA").
The example MPA supplied used the following configuration:
Entity Name : { 1 2 3 4 5 1 }
Custom MPA port : 5597
Custom MPA host : "carla" Session Selector : "Test"
Network SAP : carla:5597
FDN : /pdmId=string:"testMPA"Once the em_cmipconfig configuration has been completed, the MRM attempts to match entries against what has been configured in the FDN table using em_cmipconfig.
Requests for multiple entities can be directed to a custom MPA. The sample source supplied only supports one entity /pdmId="testMPA". A custom MPA can be created to support multiple entities.
The CMIP MPA provided with the MIS is an example of an MPA that is capable of supporting multiple entities. Each CMIP agent in the MIS' management domain is viewed as an entity. For each CMIP agent to be managed, the user must run em_cmipconfig specifying the agent parameters, in particular, the agent's presentation address.
11.3.2.3 Message remote_oi and remote Fields
The values in the remote_oi and remote fields are one of the specific differences between an MPA and a PDM.
The MPA can make explicit use of these fields. The remote_oi contains the DN of the CMIP table entry that was used to route the request to the MPA. The last RDN of this DN can be used to find the AE-Title (Application Entity Table). The remote field contains whatever was configured for that entity's presentation address. This information is what the CMIP MPA uses to establish an association with a remote entity. The aval portion of the remote field contains a string of the format:
"{ Pres, Sess, Tsel, Net }"This is an ASCII representation of the remote entities presentation address as configured using em_cmipconfig. See Section 11.3.1.3 Address Data (aval) for more information.
Note A PDM can not make use of the remote_oi or the remote field.
Multiple FDN table entries can be stored which point to a single MPA or PDM. This storage mechanism can be used as a persistent configuration store for each entity supported by the MPA/PDM. This mechanism, in conjunction with the remote_oi and remote fields, allows for easy multiplexing to the real object information.
11.3.3 FDN Table Configuration Options
There are multiple ways to configure the MIS to route messages to adaptors. In deciding which configuration to use, it is important to implement a model view that is appropriate for the problem being solved. Common sense can be a good start. For example, it would not be appropriate to add thousands of entries to the FDN table when the MPA could easily implement an efficient proprietary lookup based on the DN.
To help clarify the process, the following options are examined:
- MPA supporting two remote objects
- PDM supporting two remote objects
These examples are used to indicate the various options open to the developer.
Note These examples are not the only options and are used for illustrative purposes only.
11.3.3.1 MPA Supporting Two Remote Objects
Two possible strategies for adding entries to the FDN table are:
- Two entries can be added to the FDN table using em_cmipconfig with two different entity names specified.
- Two entries can be added to the FDN table using em_cmipconfig with only one entity name specified.
The second case illustrates how em_cmipconfig allows one entity to support multiple objects. It is assumed that the remote entity that supports these objects is identically addressed, that is, the objects live at the same presentation address.
11.3.3.2 PDM Supporting Two Remote Objects
Two possible strategies for adding entries to the FDN table are:
- Two entries can be added to the FDN table with an identical PDM address.
- Two entries can be added to the FDN table with identical class and tag values in the address with different data value in the address value field.
The first case assumes that the DN is decoded in the request and that the request is routed to the appropriate agent entity.
The second case allows the data that is configured in the value (aval) portion of the dest field of the message to be used for achieving multiplexing to the remote agent entity.
11.3.4 Source and Destination Fields in the Message
All messages contain src and dest fields. These fields are C++ instances of Address and are very important for message routing.
Note The src field must be completed for all CONFIRMED requests.
The MPA/PDM developer must complete the src address if responses are expected. The src field is the same address used when creating the SAP and when specifying the address component of the FDN table registry entry.
The dest field is only important if you wish to explicitly route the message.
Caution Because explicit routing is used for passing messages between applications, it should be used carefully.
11.4 MPA/PDM Request Management
The MIS has been designed to be a multi-user server and can handle multiple requests transparently and asynchronously. The SAP interface has been designed to make this asynchronous style of programming easier.
In FIGURE 11-2, a scenario is illustrated that is typical of a real world environment.
![]()
FIGURE 11-2 Potential Real World Configuration
Application1 makes continuous requests to the local MIT. These requests can be satisfied immediately.
Application2 makes requests to A1 and A2. These agents are at the remote end of very slow links. The architecture must support the scheduling of responses to requests that could take a long time to complete. The design and implementation should also handle cases where requests overlap. If appropriate, multiple overlapping requests should be queued and serviced with a single response.
The MPA/PDM module serving A1 and A2 schedules its responses. It achieves this by using the underlying PMI scheduling services.
The transport mechanism used by the MPA/PDM is normally hidden behind a UNIX file descriptor. The MPA/PDM developer needs to use the underlying scheduling services to interface to the file descriptor. This scheduling service makes use of the underlying poll (select) system call to determine the following:
- Whether data is available at the file descriptor
- Whether data can be written to the file descriptor
- Whether there is an underlying exception on the file descriptor
To satisfy remote requests, the MPA/PDM code typically opens a file descriptor to the agent. As requests are made to the agent, they are written to the file descriptor. The MPA/PDM code then schedules a callback for whenever data becomes available at the file descriptor. When the data is completely transferred, the MPA/PDM sends a response back to the MIS.
At a high level, the steps can be broken down as shown in TABLE 11-2.:
Note Because all requests have unique identifiers, it is easy to match responses to requests.
11.4.1 Asynchronous Request Code Specifics
When managing asynchronous requests, familiarity with some of the underlying C++ classes that facilitate asynchronous request management is critical. The most important C++ class is the Callback class. This is used by all of the asynchronous interfaces. There is also a C++ programming style that must be understood. The proposed C++ model is that a C++ class must be built with a class implementation with the following characteristics:
- Original request information, particularly the request id, the src, and dest fields must be stored.
- A static member function must exist that can be used as a callback handler.
- A variable must exist than can be used to count the number of callbacks expected.
- Class instances must be easily found by the request identifier so that CANCEL GET requests can be serviced in a timely manner.
- Responses must be queued for synchronous requests.
These characteristics determine what can be called a pending request class. This type of class encompasses the functionality required for responding to requests asynchronously.
Example
The following example excerpt from a class called pdm_pend_req in samp_inc.hh illustrates some key elements associated with asynchronous requests:
The pdm_pend_req class has the following characteristics:
- Maintains a copy of the original request and request id
- Has a callback counter
- Can be queued
- Can be hashed based on a MessId type
- Has an asynchronous interface to a start_req routine
- Has a callback to be used for invoking operation completions
The function of this class is to remember original request information, to start requests, and to ensure that a final response is sent if required. Requests are completed when there are no more callbacks pending, that is, cbs_pending == 0.
The req_mngt.cc module supplied in the samples directory illustrates all of these key concepts. The req_mngt.cc starts requests, counts the callbacks, and releases resources that are no longer required.
11.4.2 Validating Requests
Each request can be validated. The extent of the validation is dependent on the implementor and the specifics of the implementation. In some cases, it will make no sense to validate requests since much of the intelligence to validate is on the remote agent. The CMIP MPA supplied does little more than store request identifiers and forward the requests to the CMIP agent. The sample source, which is supplied, does some validation for illustrative purposes.
The typical items that can be validated up front are object class and operation types. For illustrations of typical items than can be validated, see the code in msgio.cc particularly pdm_verify_oc and pdm_verify_dn.
11.4.3 Matching Requests to Responses
Every request is identified with an identifier. To send a response to a particular request, set the response message id to the request Id. For completeness the src and dest fields must be completed also.
Example
The following example excerpt from msgio.cc send_resp. rmp is a pointer to a response message. msg is a pointer to the original request.
rmp->id = msg->id;
rmp->source = msg->dest;
rmp->dest = msg->source;
rmp->qos = msg->qos;11.5 Timer Management
The following timer management services are available to the developer:
- Create and delete a timer
- Start a timer
- Stop a timer
Timers are very useful in the MPA/PDM environment. In particular, they are needed to implement time out strategies. Every request requires a response. In the real world, there are occasions when devices do not respond. The timer facilities are useful to set a timeout callback which can send an TIMED_OUT response to the MIS in these types of situations.
Note MPAs cannot use TIMED_OUT, DEST_UNREACH or NO_SUCH_DEST messages. PDMs may use these message to signify errors. For error conditions like these, the MPA should return a PROC_FALL message with a Probable Cause specific error which is defined by the implementor.
Timers can also be used to check on device status. If the device status has changed, the MPA/PDM can emit an attribute change notification. Applications can then be written to wait for these notifications and to operate on an event driven basis. Asynchronous applications (applications that do not POLL or that are event driven) have a positive impact on overall system performance.
The MPA/PDM developer should always attempt to use a notification based mechanism to communicate with applications. Timers can be used to schedule these specific notifications. Using GDMO, any type of notification can be designed. Once the GDMO syntax has been loaded into the metadata repository (MDR), the MPA/PDM can emit the notification based on the behavior defined in the GDMO.
11.5.1 Timer Management Interface
The timer interface consist of a set of functions which allow the scheduling of callback handlers based on criteria specified in instances of a timer C++ class. These timer instances specify the following:
- A callback handler
- An interval specifying expiration time before the handler is invoked
- A reload interval value load after the original interval expires
Note These timers are not suitable for real time solutions.
The class definition for timer is defined in sched.hh and is listed below as well as the interface functions to the scheduler.
The four functions detailed above provide the interface to the scheduler for enabling and disabling callbacks based on time. The user can choose a purge interface suitable for the implementation.
11.5.1.1 Example of Timer Initialization
The following example excerpt start_timer from rusagobj.cc uses the post_timer scheduling function to start a timer. The timer that is passed to post_timer is an instance of the C++ class timer.
The timer constructor takes three parameters
- Timer intervals
- Timer reload interval value
- Callback to be executed
All interval values are specified in milliseconds. The timer instance created above is based on a variable, timerval, stored in the rusageobj instance. This value is in seconds and is converted to milliseconds by multiplying by 1000. The implementation requires that the timer be continuous so a reload value identical to the initial interval is passed for the reload parameter. The callback parameter is passed containing pdmrusage_timer as the function to be called and the rusageobj instance pointer is passed as the Callback user data.
Note The implementation of post_timer makes a copy of the timer and Callback parameters passed. It is okay to use timers and Callbacks that get destructed.
11.5.2 Stopping a Timer
Timers are stopped or purged using the purge_timer, purge_timer_handler or purge_timer_data utility functions. The stop_timer method in rusageobj.cc, listed below uses the purge_timer_handler function to cancel the pdmrusage_timer callback when it is no longer needed, that is, when the runtime attribute is set to 0.
void stop_timer() {
purge_timer_handler((CallbackHandler) pdmrusage_timer);
timer_posted = FALSE;
}purge_timer_handler searches the list of active timers for any timer that has a callback handler equal to the value passed. It then purges any timers matching from the timer queue.
Note It is important to remember if timers have been posted. A common error is that users forget to purge timers. The callback then tries to use data that has been deallocated.
11.6 File Descriptor Management
The normal mechanism of communicating outside of a UNIX process is through a UNIX file descriptor. The services provided by the scheduler to interface to file descriptors are important to understand because most MPA/PDMs use file descriptors to communicate with remote devices.
11.6.1 Asynchronous File I/O
It is important that the MPA/PDM never blocks (makes a system call that does not return immediately). The underlying UNIX File I/O system allows file descriptors to be opened or created in NON-BLOCKING modes. It is most important that any file descriptors be opened in a non-blocking mode.
The most important aspect of non-blocking file I/O is that some operations may not complete. The code must handle properly partial reads/writes. By using the underlying operating poll system call (select on BSD systems), the scheduler facilitates non-blocking I/O by providing a set of utility functions to allow for callbacks when particular events happen at a file descriptor. These are based on the standard UNIX set:
- Data can be read
- Data can be written
- Error or exception
Whenever a user expects to read from a file descriptor the user should use post_fd_read_callback. If data needs to be scheduled to be written, the user should use post_fd_write_callback. To handle error cases there should be a handler for exceptions. This handler can be set using post_fd_except_callback.
Callback handlers as discussed above are static functions that are invoked when the event they have been scheduled to service occurs. The file management functions are passed the file descriptor they are managing as parameter two. Parameter one is the data specified when the CallBack was created. Oftentimes parameter one is a pointer to a C++ instance that contains the file descriptor and any status associated with it.
The complete set of function prototypes as defined in sched.hh are listed below:
Note File descriptor callbacks should be purged if the instance associated with the callback is deleted.
11.6.2 Example of a Read Callback Implementation
The example below is taken from the unixobj.cc sample source code. There are two items of importance:
- Scheduling the callback
- Callback execution
11.6.2.1 Scheduling the Callback
The following example is taken from the unxobj.cc start_get_req routine. Once the pipe has been successfully opened, the code creates a callback and schedules the callback function execution when there is data available from the pipe. The read callback handler is scheduled using the post_fd_read_callback routine.
The following should be noted:
- The FPTR (fp) is converted to a file descriptor using fileno. (See the man pages for more information.)
- The callback which is created is initialized to have a function pointer sh_fetch_input and a data pointer of this. (This is C++ this for instance being operated on).
// Set up to get called back when Data is
// available from the pipe.
Callback rd_cb((CallbackHandler)sh_fetch_input, this);
post_fd_read_callback(fileno(fp),rd_cb);The routine sh_fetch_input is invoked wherever there is data available at the file descriptor fileno(fp).
11.6.2.2 Callback Execution
The code below is excerpted from unixobj.cc sh_fetch_input.
The sh_fetch_input routine does the following:
- Uses parameter one as a pdmunixOi pointer since that is what was defined as the user data parameter when the callback was scheduled.
- Accesses the file descriptor from the instance pointer where it was stored.
- Allocates a temporary dataunit to store the data read.
- Reads the data until there is no more data (for example, EOF). When that happens, it calls the get_complete method of the pdmunixOi C++ instance.
- If there is more data, it reposts the callback having first saved the data read in sh_data. The dataunit catenate is used to add any new data to the end of the old data.
Example
This is a very complete example of a read callback handler since it remembers state information (data just read) and reschedules itself.
Note The callback must be rescheduled if more data is to be read. A common error is the omissions of reposting the callback when the data transfer has not been completed.
11.7 Notifications
Notifications are based on the OSI Management Event Reporting function. All notifications are instances of the CMIP Event Report Request. They contain:
- Object Instance
- Object Class
- Event Time
- Event Type
- Event Information
The ASN.1 syntax for a notification is defined in x711.asn and is listed below:
Note The event information field is an ASN.1 any defined by value, which is defined by the Event Type field. To generate a notification, the eventInfo must first be constructed according to the syntax defined for that specific notification.
Notifications can be confirmed or unconfirmed. Typically notifications are unconfirmed.
Notifications are generated based on the behavior of the object class being modeled. The standard notification set includes ObjectCreation, ObjectDeletion, and attributeValueChange notifications. New notification types can be defined that are specific to the model being presented to the applications. These new notification types and syntaxes must be loaded into the MDR using the em_gdmo and em_asn1 utilities.
11.7.1 Creating a Notification
- Allocating an event report request message
- Filling in the message fields
- Sending the completed messages to the MIS
These steps are illustrated in the pdm_issue_notif routine in msgio.cc. Excerpts from that routine are used in the following subsections.
11.7.1.1 Allocating an Event Report Message
Messages are allocated using the new_message function. An example of how they are allocated follows:
11.7.1.2 Filling in the Event Report Message Fields
The time and info fields are optional and only need to be competed if the syntax demands that they be completed. All other fields must be filled in. Each of the fields require an encoded Asn1Value:
mp->mode = UNCONFIRMED;
mp->oc = oc;
mp->oi = oi; TRYRES(event.encode_oid(TAG_CONT(6), event_type));
mp->event_type = event;
mp->event_info = info;
getGeneralizedTime(mp->event_time);Each field has a specific encoding. This must be adhered to as defined by the definition of an EventReport. See the "Notifications" section for information on syntax. The object class field needs to be encoded TAG CONTEXT 0. The OI needs to be defined according to the specific encoding rules for ObjectInstance. See the x711.asn1 documentation for more information about ObjectInstance.
11.7.1.3 Sending a Notification
All messages are sent to the MIS over an initialized SAP.
Unconfirmed event report request messages are sent using the send function. Confirmed event report requests also use the send function, however, it needs the asynchronous version.
SendResult send(MessagePtr mp, const Callback &cb, MTime cd block_time)The MIS forwards all event report requests to the Event Distribution System (EDS) where it is discriminated (filtered). The notification is then forwarded to applications that have registered for it.
This routine accepts an already encoded Info parameter. For a complex example of encoding an eventInfo structure, see pdm_make_attr_chginfo in samp_utils.cc.
11.8 Sample MPA/PDM Source Code
The source code example provided is meant for illustrative and educational purposes. Much of the example code would not be used by a standard MPA/PDM. The sample source provides additional Logical Object Services that would normally be provided in the remote agent. To avoid dependencies on a specific remote agent, simple Logical Object Services are included in the sample source.
Note All of the sample source code should be studied in detail.
11.8.1 Files and Configuration
The sample source and the GDMO and ASN.1 files are included in the mpa_samples directory. There is also a set of netperl scripts which can be used to illustrate the functionality of the MPA/PDM.
Note The GDMO and ASN.1 files must be loaded before any of the example code is used.
The MPA/PDM sample source consists of the files listed in TABLE 11-3.
The makefile can be used to generate two files, testmpa and testpdm.so. The testmpa file is an executable and testpdm.so is a shared library.
11.8.1.1 Sample MPA Configuration: testmpa
Testmpa is an executable that binds to 5597 on whatever machine it is run on. It manages a logical MIT that begins at /pdmId="testMPA". em_cmipconfig must be run to address this MPA. The MPA has a DN of /pdmId="testMPA"; it is a CUSTOM MPA that lives at a default port of 5597. You can choose whatever machine name that is needed. Be sure to include a session selector of "test" when using em_cmipconfg.
Note The port number can be overridden by using the environment variable TEST_MPA_DEFAULT_PORT. Make sure that this port is entered in em_cmipconfig when configuring the MPA.
11.8.1.2 Sample PDM Configuration: testpdm.so
Testpdm.so is a shared library that can be loaded at platform start-up time. To load testpdm.so, edit $EM_HOME/config/EM_shared_libs. There are two methods for loading testpdm.so:
- Provide a complete pathname in the file.
- To do so, include the complete pathname of the shared library in EM_shared_libs, e.g. "/opt/ger/pdmsrc/testpdm.so".
- Provide the library name if the library will be placed in $EM_HOME/lib.
- To do so, include the libname and place the shared library in $EM_HOME/lib.
The PDM manages a logical MIT that begins at /pdmId="testPDM", it configures itself to be attached to the MRM at an AC_PRIMITIVE SAP type with a SAP number of 64.
Note PDM SAP numbers can be chosen by the implementor.
To allow for multiple PDMs to exist, this SAP number should be configurable and readable from a file. By convention and default, SAP tag numbers are stored in /var/opt/SUNWconn/em/conf/EM-config. The format is Name : Value. For example:
TEST_PDM_SAP : 64could be added to the file. This entry can be read using GETENV("TEST_PDM_SAP"). See the source example in dyn_lib.cc.
11.9 Developing an Adaptor
Developing an adaptor involves:
- Defining the management information model
- Designing and implementing the request management interface
- Designing and implementing the protocol code
11.9.1 Defining the Management Information Model
The information model presented to the MIS must be defined in GDMO. If the
existing agent already has some GDMO definitions, the task may be easier. In some cases, the existing GDMO definitions may not be adequately abstracted and therefore, will not be suitable. If the existing GDMO model does not provide a sufficient level of abstraction, new definitions should be defined. The GDMO model defined should make every attempt to fully abstract the management problem being solved.For example, in a case where a device has 5000 ports, the following activities could be defined:
- The device could be defined as one single object with a set of attributes and ACTIONS that could be used to access the ports.
- Each port could be defined as an object with multiple attributes.
The model chosen is dependent on the problem being solved. In most cases, the more abstract models can provide for less complex development and better performance for the most common operations. Models can also be optimized to enhance the solution.
The preferred solution in the above scenario would be the single object view. This view would be less complex to implement and require less code. Since there is only one logical object to manage, the overhead in maintaining a logical tree would be minimal and the performance may be better. If the object was defined properly, the applications using the model would also be simpler. They would not have to incur the overhead of managing thousands of objects.
There are no specific rules that can be applied here. Common sense and a clear understanding of the real problem and specific solution required by the customer are the best guides.
11.9.2 The Request Management Interface
As outlined in the sample source, the interface to the MIS must be completely asynchronous. The interface code must be capable of managing multiple outstanding requests. In addition, it must have minimal impact on the overall system performance. This is critical in the case of the PDM. The request interface can be modeled on the sample source and the msgio.cc and req_mngt.cc modules can provide the basis for any adaptor.
11.9.3 The Protocol Code
Each device or remote entity must support some type of remote access. Often there are existing libraries that have already implemented a suitable protocol interface to the devices which are to be managed. These interfaces should be reused as much as possible. The most important consideration when reusing existing protocol stack code is that there be no underlying interface element that could block. All code must be asynchronous. When only synchronous interfaces are provided, a layer needs to be built that provides the asynchronous interface.
Sun Microsystems, Inc. Copyright information. All rights reserved. |
Doc Set | Contents | Previous | Next | Index |