WS-Eventing in Openwsman

In an implementation or environment supporting WS-Eveneting there are three actors:

  • Subscriber,
  • Event Source and
  • Event Sink.

The Event Sink subscribes an interest with the Event Source by operation contract, such as Subscribe. Event Source is responsible for controlling the information that Event
Sinks are interested in. The event sink can be the receiving end and the initiator of a subscription, however it is also possible that the subscription comes from a seperate component.

The Event Source can consist of two parts: Subscription Manager and Notification Manager. Subscription manager is responsible for managing a Subscription's
lifetime using operation contracts such as Unsubscribe, Renew and GetStatus while Notification Manager with the notification.

Processing Model of WS-Eventing

In this implementation openwsman acts as an Event Source, which is responsible for receiving a subscription from a subscriber and sending a notification to an event sink. As there are different events created by different applications in the real world, it is important to make this process as general as possible.

The solution is to put the specific eventing production in the plug-in part and intergrate shared WS-Eventing protocol process in the framework of openwsman. That is to say, the framework and plug-in act together to accomplish the process of WS-Eventing. This process model is shown below.

WS-Eveneting Architecture

In this process model, the Subscribe, Unsubscribe and Renew Interfaces act together as the Subscription Manager. The Ack and Pull Interfaces are part of the Notification Manager from the point of view of the event sink.

Subscription Manager

Workflow

When a subscription request is received, if it is a valid request, it will be saved in the subscription repository and in the memory at the same time and a response message will be returned with expiration time(if any) and corresponding subscription identifier. If it is not, an error message will be returned with causes.

Renew request message should include subscripton identifier which is returned by the subscription manager when subscription is made.

Unsubscribe request should include subscription identifier which is returned by the subscription manager when subscription is made.

Subscription Repository

Why is Subscription Repository needed?

There are mainly two reasons:

  • In many occasions, WS-Management working environment is distributed. When the Subscription Manager receives a subscribe request, it has to save this subscription to a Subscription Repository in another physical location, which can also be accessed by the Notification Manager.
  • If there is a subscription repository, the service will recover after restarting without loss of subscribed data.

Goal of implementation

Although we have to decide one kind of repository in our implementation, the implementation should be designed extensible. That is, it should be changed easily if another kind of repository is considered.

Related Data structures

To achieve this goal, callback functions are used. Fuction table of Subscription Repository operations will be registered in the __Soap object when the service finishes loading all plug-ins. The function table should include operations “load all subscriptions”, “get/update/save/delete a specific subscription”. Once the function table is registered, it can be used in the runtime late. If you want to implement a different repository, just change related subscriptions functions.

Related data structures are shown below:

  1. typedef int (*SubscriptionOpInit) (char *, void *);
  2. typedef int (*SubscriptionOpFinalize) (char *, void *);
  3. typedef int (*SubscriptionOpSave) (char *, char *, char *);
  4. typedef int (*SubscriptionOpDelete) (char *, char *);
  5. typedef int (*SubscriptionOpGet)(char *, char *, char *);
  6. typedef int (*SubscriptionOpSearch) (char *, char *);
  7. typedef int (*SubscriptionOpUpdate)(char *, char *, char *);
  8. typedef int (*SubscriptionOpLoad) (char *, list_t *);
  9. struct __SubsRepositoryEntry {
  10. char *strdoc;
  11. char *uuid;
  12. };
  13. typedef struct __SubsRepositoryEntry *SubsRepositoryEntryH;
  14. struct __SubsRepositoryOpSet{
  15. SubscriptionOpLoad load_subscription;
  16. SubscriptionOpGet get_subscription;
  17. SubscriptionOpSave save_subscritption;
  18. SubscriptionOpUpdate update_subscription;
  19. SubscriptionOpDelete delete_subscription;
  20. };

And we also need to add two fields in the __Soap structure:

  1. char *uri_subsRepository; //URI of repository
  2. SubsRepositoryOpSetH subscriptionOpSet; //Function talbe of Subscription Repository

Implementation of Local Subscription Repository

If you want another repository, just change related subscription operations. In this implementation a subscription is saved in a file with the name of UUID returned by the Notification Manager.

Definitions of local Subscription Repository operations:

  1. int LocalSubscriptionOpInit (char * uri_repository, void *opaqueData);
  2. int LocalSubscriptionOpFinalize(char * uri_repository, void *opaqueData);
  3. int LocalSubscriptionOpGet(char * uri_repository, char * uuid, char **subscriptionDoc);
  4. int LocalSubscriptionOpSearch(char * uri_repository, char * uuid);
  5. int LocalSubscriptionOpLoad (char * uri_repository, list_t * subscription_list);
  6. int LocalSubscriptionOpSave (char * uri_repository, char * uuid, char *subscriptionDoc);
  7. int LocalSubscriptionOpUpdate(char * uri_repository, char * uuid, char *expire);
  8. int LocalSubscriptionOpDelete (char * uri_repository, char * uuid);

Function tabre of local Subscription Repository operations:

  1. struct __SubsRepositoryOpSet subscription_repository_op_set = {LocalSubscriptionOpInit, LocalSubscriptionOpFinalize, LocalSubscriptionOpLoad, LocalSubscriptionOpGet, LocalSubscriptionOpSearch, LocalSubscriptionOpSave, LocalSubscriptionOpUpdate, LocalSubscriptionOpDelete};

Event Pool

The Event Pool is responsible for events storage. All events except heatbeats generated by the service are put here before they are sent eventually. Notification Manager gets events from Event Pool, while Plug-in adds events to it.

Event Pool

 

Notification Manager

A Notification defined in WS-Eventing can be a real event produced by the event source or a heartbeat event to be sent in a fixed interval. It is an obvious and reasonable idea to put the two functions in two separate threads. So the notification manager can be designed to consist of the notification manager and the heartbeat threads.

To decrease the memory footprintf, the implementation has a single notification manager thread for all notifications. The thread is created when the service is started. The notification mangager thread works for all notifications. It loops for ever until the service is stopped and detects whether there is an event. If an event is detected, a notification sender thread will be created to send the event to the event sink. The notification sender will quit after the send operation is finished. The notification manager is also responsible for subscriptions. If there is a subscription that is unsubscribed or expired, the notification manager will delete it from the memory. If the subscription is unsubscribed, the subscription data will also be deleted from the repository.

If heartbeat is requested in the “subscribe” message, a heartbeat event will be sent in a fixed interval if there is no event from the event source. The Heartbeat generator is also an independent loop thread strarted when the service launches. It generates all heartbeat events in the system. Like the notification manager thread, if there is a heartbeat event, the heartbeat generator will also create a notification sender to send the event to the event sink.

So the notification manager consists of a notification manager thread, a notification sender and the shared heartbeat generator.

Notification Manager