######################
# Indication manager #
######################
    in short IM

Purpose
~~~~~~~
Indication manager (in short IM) should help in writing indication provider
using CMPI. Main concept is to lessen work you need to do to only define
few callback functions.

Usage
~~~~~
Mainly the user of IM have to write callback functions: IMFilterChecker,
IMEventWatcher.
IM can be used to poll instance. This has to be set upon initialization
and cannot be changed. When not using polling the user have to write also
IMInstGather callback function.
For user are provided the following functions:
im_create_manager, im_destroy_manager, im_verify_filter, im_add_filter,
im_remove_filter, im_start_ind and im_stop_ind.
Following are documentation for functions and callback definitions,
in the following form:
* name of function or callback
C definition
Documentation.

* im_create_manager
IMManager* im_create_manager(IMInstGather gather, IMFilterChecker f_checker,
                             bool polling, IMEventWatcher watcher,
                             IMIndType type, CMPIBroker *broker, IMError *err);
Return newly created reference to IMManager. User should use this reference
only as parameter for functions. User should provide callback functions (see
below), should choose if want to use polling, choose type indications and
provide broker reference. On any error occurance the NULL is returned and
err is set.

* im_destroy_manager
bool im_destroy_manager(IMManager *manager, const CMPIContext *ctx,
                        IMError *err);
Destroy the given manager. User should provide context. Returns true when
everything was correctly done, or false and err is set.

* im_verify_filter
bool im_verify_filter(IMManager *manager, const CMPISelectExp *filter,
                      const CMPIContext *ctx, IMError *err);
Ask manager to verify the given filter. User should provide context. In turn,
the manager calls IMFilterChecker (see below). If filter is accepted true
is returned, otherwise false is returned and err is set.

* im_add_filter
bool im_add_filter(IMManager *manager, CMPISelectExp *filter,
                   const CMPIContext *ctx, IMError *err);
Adds the given filter to the manager. It is logical error to add filter, which
is not verified before. User should provide context. Return true when everything
is correctly done, false otherwise and err is set.

* im_remove_filter
bool im_remove_filter(IMManager *manager, const CMPISelectExp *filter,
                      const CMPIContext *ctx, IMError *err);
Removes the given filter from the manager. Returns true when correctly done,
or false and err is set.

* im_start_ind
bool im_start_ind(IMManager *manager, const CMPIContext *ctx, IMError *err);
Informs the manager to start sending indications. It is recursively calling
IMEventWatcher and IMInstGather (if using polling, the default gather is used).
Returns true if everything started correctly, false otherwise and err is set.
NOTE: Callbacks are called within a thread that can be forcefully interrupted
by the im_stop_ind() call without any chance for cleanup. For that reason, any
dynamically allocated memory will get leaked. Please keep that in mind and use
as much stack memory as possible. If needed, please perform cleanup at the same
place the im_stop_ind() is called. Only one thread is executed within each
indication manager instance, no need for extra thread safety.

* im_stop_ind
bool im_stop_ind(IMManager *manager, const CMPIContext *ctx, IMError *err);
Informs the manager to stop sending indications. Internally this call cancels
the thread function, see the note above. Returns true when everything is done
correctly, false otherwise and err is set.

* IMFilterChecker
typedef bool (*IMFilterChecker) (const CMPISelectExp *filter);
User should define this callback, which is called whenever manager is asked
to verify filter. Function should return true when given filter is allowed,
false otherwise. Filter is passed from im_verify_filter function

* IMEventWatcher
typedef bool (*IMEventWatcher) (void **data);
User should define this callback, which should be blocking. The purpose of this
called is to inform manager that event occured. When the callback returns with
true value the manager is informed that event has occured and will send
indication right after. When the callback returns with false value the manager
is informed that event hasn't occured and will not send indication and will
retart the loop - the callback will be executed again soon.
User can use data to transfer any information from this callback
to IMInstGather.
This is called within a thread and is advised that any blocking call should be
a pthread cancellation point (see pthreads(7)) for easy interruption (see the
note at im_start_ind()).

* IMInstGather
typedef bool (*IMInstGather) (const IMManager *manager, CMPIInstance **old,
                              CMPIInstance **new, void *data);
This callback has to be defined only when not using default polling mechanism.
data are passed from IMEventWatcher and are supposed to help creating instances.
User should create and set instance and/or instances. When type of indications
is IM_IND_CREATION the new instance has to be set. When IM_IND_DELETION the old
instance has to be set. Both when IM_IND_MODIFICATION is used. When the callback
returns true the manager will send the indication and call the callback again.
In other words, the return value means "There is another indication
with instances to be send". When false is returned the manager will send
the last indication and starts another round in the loop.

Cancellation, indications enabling and disabling
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Indications should be enabled or disabled in relation with EnableIndications()
and DisableIndications() CIM class method calls. These are called typically when
subscription is added or removed. Note that enabling or disabling indications
multiple times has no effect.

Polling
~~~~~~~
IM supports basic polling mechanism. When enabled the IM remembers instances
after every IMEventWatcher call and default IMInstGather callback is used.
Which instances are to be polled are determined by the filters, where
the IM looks for the first occurence of ISA predicate in WHERE clause of select
expression. For example we have filter with expression:
SELECT * FROM LMI_SomeIndication WHERE SourceInstance ISA LMI_Account
the manager will be polling instances from LMI_Account class (from the same
namespace as LMI_SomeIndication). Polling is possible on multiple classes.

Known limitations
~~~~~~~~~~~~~~~~~
IM supports only instance indications of the following types:
Creation, Deletion, Modification
and supports only one type per provider.
Settings cannot be changed.

Example
~~~~~~~
Is not provided yet.
