dbEvent.h

Internal publish/subscribe mechanism of process database. Direct usage is discouraged in favor of derived interfaces, principally local and remote PVA/CA.

Since

7.0.8.1 New usage is recommended to define the USE_TYPED_DBEVENT C macro to select typed arguments of some calls as opposed to void pointers.

Objects

  • Event context (dbEventCtx)

  • Event subscription (dbEventSubscription)

  • Channel (dbChannel)

  • Event / field log (db_field_log)

Lifecycle

Usage is tied to the lifetime of the process database. Either through IOC lifecycle callback hooks. or Unit testing of record processing . db_init_events() must not be called before initHookAfterInitDatabase or testIocInitOk(). db_close_events() must be called after initHookBeforeFree or testIocShutdownOk().

Subscriptions associated with an Event Context must be deallocated before that Context is deallocated.

Concurrency

Each Event Context has an associated worker thread on which subscription callbacks are invoked. Some API functions implicitly synchronize with that worker thread as noted. The “extra labor” functions may be used to explicitly synchronize with this thread.

Note

testMonitorCreate() and friends are provided to easy handling of subscriptions in unit tests.

Defines

DB_EVENT_OK
DB_EVENT_ERROR

Typedefs

typedef void *dbEventSubscription
typedef void *dbEventCtx
typedef void EXTRALABORFUNC(void *extralabor_arg)
typedef void EVENTFUNC(void *user_arg, struct dbChannel *chan, int eventsRemaining, struct db_field_log *pfl)

Subscription event callback.

An event callback is expected to call dbChannelGetField() or take equivalent action. eg. explicitly lock the record and call dbChannelGet().

Callee must not delete the db_field_log.

Since

7.0.5,

pfl->mask 
may be used to detect which condition(s) triggered this event.

Param user_arg:

private argument passed to db_add_event()

Param chan:

dbChannel passed to db_add_event()

Param eventsRemaining:

Approximate number of events remaining in queued. Not exact. Use is discouraged.

Param pfl:

db_field_log of this event.

Functions

int db_event_list(const char *name, unsigned level)
int dbel(const char *name, unsigned level)
int db_post_events(void *pRecord, void *pField, unsigned caEventMask)
dbEventCtx db_init_events(void)

Allocate event reception context.

On success, call db_start_events(), and then eventually db_close_events().

Returns:

NULL on error

Pre:

Call after initHookAfterInitDatabase and before initHookBeforeFree.

int db_start_events(dbEventCtx ctx, const char *taskname, void (*init_func)(void*), void *init_func_arg, unsigned osiPriority)

Start listener thread.

Basic lifecycle:

dbEventCtx ctxt = db_init_events();
assert(ctxt);
int ret = db_start_events(ctxt, "mymodule", NULL, NULL, 0);
assert(ret==DB_EVENT_OK);
... create and close subscriptions
db_close_events(ctxt);

Flow control initially disabled, so events can be delivered.

Parameters:
  • ctx – Context

  • taskname – Thread name

  • init_func – If not NULL, call from the newly created listener thread

  • init_func_arg – Argument to init_func

  • osiPriority – Thread priority. See epicsThreadOpts::priority

Returns:

DB_EVENT_OK Success. DB_EVENT_ERROR, failed to create new thread.

void db_close_events(dbEventCtx ctx)

Stop and deallocate event reception context.

Parameters:

ctx – Context

Pre:

Call after initHookAfterInitDatabase and before initHookBeforeFree.

Pre:

All dbEventSubscription must first be deallocated by db_cancel_event().

Post:

Joins event listener thread.

void db_event_flow_ctrl_mode_on(dbEventCtx ctx)

Enable flow control, pause event delivery.

Parameters:

ctx – Context

void db_event_flow_ctrl_mode_off(dbEventCtx ctx)

Disable flow control, resume event delivery.

Parameters:

ctx – Context

int db_add_extra_labor_event(dbEventCtx ctx, EXTRALABORFUNC *func, void *arg)

Setup/Clear extra labor callback.

Does not queue callback. See db_post_extra_labor().

Parameters:
  • ctx – Context

  • func – Extra labor callback, may be NULL to clear previously set callback.

  • arg – Argument to func

Returns:

DB_EVENT_OK, always succeeds.

void db_flush_extra_labor_event(dbEventCtx)

Wait for extra labor callback.

To ensure completion, call should arrange that db_post_extra_labor() will not be called again.

Pre:

Do not call from event listener thread.

Post:

extra labor queued flag is unchanged

int db_post_extra_labor(dbEventCtx ctx)

Queue extra labor callback event.

Sets an internal queued flag, which still be set from a previous call.

Parameters:

ctx – Context

Returns:

DB_EVENT_OK, always succeeds.

void db_event_change_priority(dbEventCtx ctx, unsigned epicsPriority)

Change event listener thread priority.

Parameters:
dbEventSubscription db_add_event(dbEventCtx ctx, struct dbChannel *chan, EVENTFUNC *user_sub, void *user_arg, unsigned select)

Create subscription to channel.

Creates a new subscription to the specified dbChannel. Callbacks will be delivered on the listener thread of the provided Context.

Creation does not queue any events. Follow with a call to db_post_single_event() to queue an initial event.

Subscription is initially disabled. Call db_event_enable();

Basic lifecycle:

static
void mycb(void *priv, struct dbChannel *chan, int eventsRemaining, struct db_field_log *pfl) {
    (void)eventsRemaining; // use not recommended

    // dbChannelGetField() locks record.
    // May read value and meta-data from event (db_field_log).
    long ret = dbChannelGetField(chan, ..., pfl);
}
void someaction() {
    dbEventCtx ctx = ...; // previously created
    dbChannel *chan = ...;
    void *priv = ...;

    dbEventSubscription sub = db_add_event(ctx, chan, mycb, priv, DBE_VALUE|DBE_ALARM);
    assert(sub);
    db_cancel_event(sub);
}
Parameters:
  • ctx – Context

  • chan – Channel

  • user_sub – Event callback

  • user_arg – Private argument

  • select – Bit mask of DBE_VALUE and others. See caeventmask.h

Returns:

NULL on error. On success, later call db_cancel_event()

void db_cancel_event(dbEventSubscription es)

Deallocate subscription.

Synchronizes with Event Context worker thread to wait for a concurrent callback to complete.

Parameters:

es – Subscription. Must not be NULL.

void db_post_single_event(dbEventSubscription es)

Immediately attempt to queue an event with the present value.

Locks record and runs pre-chain of any server-side filters. Such a filter may drop the new event (a well designed filter should not drop the first event).

Parameters:

es – Subscription

void db_event_enable(dbEventSubscription es)

Enable subscription callback delivery.

Parameters:

es – Subscription

void db_event_disable(dbEventSubscription es)

Disable subscription callback delivery.

Does not synchronize with listener thread, pending callbacks may be delivered. Use extra-labor mechanism and db_flush_extra_labor_event() to synchronize.

Parameters:

es – Subscription

struct db_field_log *db_create_event_log(struct evSubscrip *pevent)

Allocate subscription update event.

Parameters:

pevent – Subscription

Returns:

NULL on allocation failure.

struct db_field_log *db_create_read_log(struct dbChannel *chan)

Allocate “read” event.

Used by PVA or CA “GET” operations when polling the current value of a Channel.

Parameters:

pevent – Subscription

Returns:

NULL on allocation failure.

void db_delete_field_log(struct db_field_log *pfl)

db_delete_field_log

Parameters:

pfl – event structure. May be NULL (no-op).

int db_available_logs(void)