# Getting started with indications

The prerequisite for receiving indications is at least one existing subscription on a CIMOM. It is out of the scope of this document to explain the creation of subscriptions. Please see the corresponding DMTF standards.

The delivery of indications reverses the roles of client and server. The CIMOM acts as HTTP client, the SBLIM CIM Client for Java as an HTTP server. The indication delivery is asynchronous and completely independent from an open client-to-CIMOM connection.

## Setting up an indication listener

The following code snippet illustrates how to set up a simple indication listener.

    /**
     * Starts a indication listener that dumps every received indication to System.out
     * @param port The TCP port to listen on
     * @param ssl Set true if you want to listen on a secure (SSL) socket
     * @return The indication listener instance. Call removeLister() to stop the listener.
     */
    private WBEMListener startIndicationListener(int pPort, boolean pSsl) throws IOException {

      try {
        WBEMListener listener = WBEMListenerFactory.getListener(WBEMClientConstants.PROTOCOL_CIMXML);
        listener.addListener(new IndicationListener() {
          public void indicationOccured(String pIndicationURL, CIMInstance pIndication) {
            System.out.println("Indication received on: " + pIndicationURL + ":");
            System.out.println(pIndication.toString());
          }
        }, pPort, pSsl ? "https" : "http");

        return listener;

        } catch (IOException e) {
          System.err.println("Failed to bind socket to port "+pPort);
          throw e;
        }
      }

This sample will listen for indications on the given socket. Every indication received is dispatched to the single registered `CIMListener` that prints the event details to `stdout`. In a real world application you would replace the `System.out.println()` with your indication processing code.

In order to stop listening and free the socket just call `removeListener(int pPort)`.

The `WBEMListener` is a singleton that keeps a map of socket listeners keyed by port. On multi-homed systems it is possible to bind the listener to a given IP only. The `WBEMListenerSBLIM` class offers an additional signature of `addListener()` that allows you to pass individual configuration properties.

## Implementation Details

When you start an indication listener you start a little HTTP server. This server has to fulfill the usual duties: wait for incoming connections, handle them (also concurrently), parse the request, send a response, create a CIM indication and forward it to the corresponding indication listener from your application.

These duties are handled by four layers, each of which runs in one or more separate threads (compare with picture).

- The outermost layer is the HTTP server. It just listens for incoming connections on the server socket, accepts them and pushes the connection socket in the connection queue.
- The connection dispatcher monitors the connection queue and creates a task for each connection. The tasks are pushed into the task queue.
- The handlers monitor the task queue and execute the task. The task will parse the request, send a response, create a CIM event and push the event into the event queue. The handlers are controlled by a thread pool that creates and destroys them on demand. By default it might create up to 16 handlers and will always keep at least one active.
- The CIM event dispatcher monitors the event queue and forwards the event to the indication listener of the application.

When you subscribe on multiple CIMOMs you have to be able to distinguish which CIMOM is the origin of a particular indication. This is not as easy as it seems since an indication doesn't have sender information. Therefore the common way is to make the destination unique in the subscription. This can be done by either using an individual port per subscription or by using an individual local path per subscription. The first option creates more overhead in the client since we have to start a separate HTTP server for each port. Therefore we recommend using the second option.

## Configuration options

We have five configuration options that allow you to fine tune the indication listener. All of them are coupled together and a wrong setting might harm your ability to receive indications.

- sblim.wbem.listenerHttpTimeout: Sets the socket timeout. CIMOMs that do not send data or keep hanging in between are disconnected after that time. This is a very important setting, because it controls how long a sender might block a handler thread. Increase that value only in a high latency environment.
- sblim.wbem.listenerPoolMaxSize: Sets the maximum number of handlers the thread pool will create on heavy load. It's not recommended to go below two here because that makes the client too vulnerable against a blocked handler.
- sblim.wbem.listenerPoolMinSize: Sets the number of handlers that are kept alive even when we have no load at all. It is recommended to use at least two when the backlog is not zero. Otherwise the client is again too vulnerable against blocked handlers.
- sblim.wbem.listenerBacklog: Sets the number of queued connections that are tolerated before the thread pool will create a new handler. Increasing this setting makes the thread pool more "relaxed" keeping the number of handlers a bit lower and avoiding many handler creations & destructions. You should combine a non-zero setting with a minimal pool size of two or more in order to avoid vulnerability against a blocked handler.
- sblim.wbem.listenerHandlerMaxIdle: Sets the time a handler might be idle before it will be killed by the thread pool. Lower values will make the thread pool more "nervous" closing idle handlers fast. Higher values make it more "relaxed" keeping handlers open and avoiding many handler creations & destructions

### Examples for reasonable combinations:

HTTP timeout | minimum pool size | maximum pool size | backlog | idle timeout | remarks
--- | --- | --- | --- | --- | ---
10s | 2 | 8 | 2 | 30s | Default setting. Will keep number of handlers low & stable. Aggressive HTTP timeout and two handlers always open will keep vulnerability low.
60s | 0 | 8 | 0 | 10s | More dynamic handler allocation. Will destroy all handlers fast when idling and create them without delay on traffic. Allows higher HTTP timeout.
60s | 0 | 8 | 0 | 120s | Similar to default but keeps handler count stable by long idle timeout instead of backlog. Makes it less vulnerable against blocking, but keeps handler open long after traffic peeks. Needs on average more handlers than default.
10s | 0 | 2 | 0 | 10s | Resource saving: maximum of two handlers, aggressive HTTP timeout, short idle timeout. Will keep number of handlers low but is heavily creating & destroying its handlers.

## Reliable Indications

Reliable indication support, as defined by DMTF Indications Profile [DSP1054], is included in the SBLIM CIM Client for Java beginning with version 2.1.9. The gist of reliable indication support is for indications to be delivered to the listener in the order intended by the CIMOM, NOT the order which they arrive at the Client. In other words, if the CIMOM sends indications [#4,#5,#6] but network issues cause them to arrive at the Client as [#5,#6,#4], the Client will deliver them to the listener as [#4,#5,#6].

When reliable indication support is enabled (the default is disabled), the Client is responsible for determining when to dispatch reliable indications, which includes queuing unexpected indications in either a hash table or linked list, caching all indications for the duration of their sequence identifier lifetime, and logging missing, duplicate and out-of-order indications.

A reliable indication must contain both the SequenceContext and SequenceNumber properties, the latter of which is used to deliver indications to the listener in order of increasing value. The sequence identifier lifetime is defined as:

    DeliveryRetryAttempts * DeliveryRetryInterval * 10

where DeliveryRetryAttempts and DeliveryRetryInterval are properties in the CIM_IndicationService instance on the CIMOM dispatching the indications.

There are four configuration options that allow you to control reliable indication handling:

- sblim.wbem.listenerEnableReliableIndications: Enables or disables reliable indication support. If set to true, indications are queued by the Client in a linked list or hash table and delivered in order to the listener . If set to false, indications are passed directly to the listener.
- sblim.wbem.listenerDeliveryRetryAttempts: Sets the default value to use for the CIM_IndicationService DeliveryRetryAttempts property. This value should match the value of the property of the CIM_IndicationService instance on the CIMOM dispatching the indications.
- sblim.wbem.listenerDeliveryRetryInterval: Sets the default value to use for the CIM_IndicationService DeliveryRetryInterval property. This value should match the value of the property of the CIM_IndicationService instance on the CIMOM dispatching the indications.
- sblim.wbem.listenerReliableIndicationHashtableCapacity: Sets the default value to use for the reliable indication handler's initial hash table capacity. A value of 0 indicates use a linked list instead. Linked lists are better suited for a small number of listener destinations per WBEMListener while hash tables are better suited for a large number.

The following code snippet illustrates how to set up a simple indication listener with reliable indication support enabled.

    /**
     * Starts a indication listener that dumps every received indication to System.out
     * @param port The TCP port to listen on
     * @param ssl Set true if you want to listen on a secure (SSL) socket
     * @return The indication listener instance. Call removeLister() to stop the listener.
     */
    private WBEMListener startIndicationListener(int pPort, boolean pSsl) throws IOException {

      try {
        WBEMListener listener = WBEMListenerFactory.getListener(WBEMClientConstants.PROTOCOL_CIMXML);
        // Cast WBEMListener to WBEMListenerSBLIM to get access to the addListener() method that
        // accepts properties - this method is not part of the JSR48 standard, but is a SBLIM addition
        WBEMListenerSBLIM SBLIMlistener = (WBEMListenerSBLIM) listener;

        // Enable reliable indications using 2 retries at intervals of 30 seconds
        Properties props = new Properties();
        props.setProperty("sblim.wbem.listenerEnableReliableIndications", "true");
        props.setProperty("sblim.wbem.listenerDeliveryRetryAttempts", "2");
        props.setProperty("sblim.wbem.listenerDeliveryRetryInterval", "30");

        SBLIMlistener.addListener(new IndicationListener() {
          public void indicationOccured(String pIndicationURL, CIMInstance pIndication) {
            System.out.println("Indication received on: " + pIndicationURL + ":");
            System.out.println(pIndication.toString());
          }
        }, pPort, pSsl ? "https" : "http", null, props);

        return listener;

        } catch (IOException e) {
          System.err.println("Failed to bind socket to port "+pPort);
          throw e;
        }
      }

The properties can also be set in the properties file itself, in which case the code would be identical to the first snippet above. However, that would enable reliable indication support and set the attempts/interval for all listeners whereas this code snippet enables support and sets the attempts/interval for this particular listener only.

NOTE:If reliable indication support is enabled but the CIMOM does not send reliable indications (required properties missing), the indications are passed directly to the listener.