libamxb  4.8.2
Bus Agnostic C API
Data Model Eventing

Functions

int amxb_subscribe (amxb_bus_ctx_t *const ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
 Subscribes for events of a object tree. More...
 
int amxb_unsubscribe (amxb_bus_ctx_t *const ctx, const char *object, amxp_slot_fn_t slot_cb, void *priv)
 Removes an event subscription. More...
 
int amxb_publish (amxb_bus_ctx_t *const ctx, const char *object, const char *name, amxc_var_t *data)
 Publish an event for a specific object. More...
 
int amxb_subscription_new (amxb_subscription_t **subscription, amxb_bus_ctx_t *bus_ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
 Creates a subscription object and subscribes for events of a object tree. More...
 
int amxb_subscription_delete (amxb_subscription_t **subscription)
 Deletes a subscription object and unsubscribe for events of a object tree. More...
 
amxb_subscription_tamxb_subscription_find (amxb_bus_ctx_t *bus_ctx, const char *object, amxp_slot_fn_t slot_cb, void *priv)
 Find an exact subscription. More...
 
amxb_subscription_tamxb_subscription_find_parent (amxb_bus_ctx_t *bus_ctx, const char *object)
 Find a parent subscription. More...
 
amxb_subscription_tamxb_subscription_find_child (amxb_bus_ctx_t *bus_ctx, const char *object)
 Find a child subscription. More...
 
int amxb_wait_for_object (const char *object)
 Checks if an object is available, if not waits for it. More...
 

Detailed Description

Function Documentation

◆ amxb_publish()

int amxb_publish ( amxb_bus_ctx_t *const  ctx,
const char *  object,
const char *  name,
amxc_var_t *  data 
)

Publish an event for a specific object.

This function can only be used when a data model was registered to the provided bus context using amxb_register.

Any event can be published for any object on the condition that the event was added to the data model signal manager.

Parameters
ctxThe bus context (or connection)
objectobject path to the object object paths must end with a "."
nameevent name
dataevent data
Returns
AMXB_STATUS_OK remote function has completed successful

Definition at line 347 of file amxb_ba_subscribe.c.

350  {
351  int retval = -1;
352  amxd_object_t* obj = NULL;
353 
354  when_null(ctx, exit);
355  when_null(ctx->dm, exit);
356  when_null(ctx->bus_ctx, exit);
357  when_str_empty(object, exit);
358  when_str_empty(name, exit);
359 
360  obj = amxd_object_findf(amxd_dm_get_root(ctx->dm), "%s", object);
361 
362  if(obj != NULL) {
363  amxd_object_emit_signal(obj, name, data);
364  retval = amxd_status_ok;
365  } else {
366  retval = amxd_status_object_not_found;
367  }
368 
369 exit:
370  return retval;
371 }
amxd_dm_t * dm
Definition: amxb_types.h:123
void * bus_ctx
Definition: amxb_types.h:122

◆ amxb_subscribe()

int amxb_subscribe ( amxb_bus_ctx_t *const  ctx,
const char *  object,
const char *  expression,
amxp_slot_fn_t  slot_cb,
void *  priv 
)

Subscribes for events of a object tree.

Subscribes for all events matching the given filter on an object (sub)tree.

Using the provided object path, all events matching the given expression, of that object or any of the child objects (instances included) are passed to the callback function.

The subscription can be removed using amxb_unsubscribe.

Parameters
ctxThe bus context (or connection)
objectobject path to the object object paths must end with a "."
expressionan expression used to filter the events
slot_cbcallback function, called for each matching event
privprivate data, passed to the callback function
Returns
AMXB_STATUS_OK remote function has completed successful

Definition at line 205 of file amxb_ba_subscribe.c.

209  {
210  int retval = -1;
211  char* obj_path = NULL;
212  amxc_var_t info;
213  amxd_path_t path;
214  amxb_request_t* req = NULL;
215  amxc_string_t rel_path;
216  amxc_string_t str_expr;
217 
218  amxd_path_init(&path, NULL);
219  amxc_var_init(&info);
220  amxc_string_init(&rel_path, 64);
221  amxc_string_init(&str_expr, 0);
222 
223  when_null(ctx, exit);
224  when_null(ctx->bus_ctx, exit);
225  when_null(object, exit);
226  when_null(slot_cb, exit);
227 
228  amxd_path_setf(&path, true, "%s", object);
229  if((path.type == amxd_path_invalid) ||
230  (path.type == amxd_path_reference) ||
231  (path.type == amxd_path_supported)) {
232  goto exit;
233  }
234  obj_path = amxd_path_get_fixed_part(&path, false);
235 
236  retval = amxb_describe(ctx, obj_path, 0, &info, 5);
237  if(retval == 0) {
238  free(obj_path);
239  amxb_build_path(&info, &path);
240  obj_path = amxd_path_get_fixed_part(&path, false);
241  }
242 
243  when_null(obj_path, exit);
244 
245  amxc_var_set_type(&info, AMXC_VAR_ID_HTABLE);
246  amxc_var_add_key(cstring_t, &info, "expression", expression);
247  req = amxb_async_call(ctx, obj_path, "_subscribe", &info, NULL, NULL);
248  amxb_close_request(&req);
249 
250  if(*obj_path != 0) {
251  obj_path[strlen(obj_path) - 1] = 0;
252  }
253 
254  retval = amxb_build_expression(&str_expr, &path, expression);
255  when_failed(retval, exit);
256  expression = amxc_string_get(&str_expr, 0);
257 
258  if(ctx->dm != NULL) {
259  retval = amxb_subscribe_local_impl(ctx, obj_path, expression, slot_cb, priv);
260  when_true(retval == 0, exit);
261  }
262 
263  retval = amxb_subscribe_be_impl(ctx, obj_path, expression, slot_cb, priv);
264 
265 exit:
266  amxc_string_clean(&str_expr);
267  amxc_string_clean(&rel_path);
268  amxd_path_clean(&path);
269  amxc_var_clean(&info);
270  free(obj_path);
271  return retval;
272 }
static int amxb_subscribe_be_impl(amxb_bus_ctx_t *ctx, const char *path, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
static int amxb_build_expression(amxc_string_t *str_expr, amxd_path_t *obj_path, const char *expression)
static int amxb_subscribe_local_impl(amxb_bus_ctx_t *ctx, const char *path, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
static void amxb_build_path(amxc_var_t *info, amxd_path_t *path)
int amxb_close_request(amxb_request_t **req)
Closes a previously create remote function called context.
int amxb_describe(amxb_bus_ctx_t *const bus_ctx, const char *object, uint32_t flags, amxc_var_t *ret, int timeout)
Describes an object.
amxb_request_t * amxb_async_call(amxb_bus_ctx_t *const bus_ctx, const char *object, const char *method, amxc_var_t *args, amxb_be_done_cb_fn_t done_fn, void *priv)
Invokes a data model function.
A request structure.
Definition: amxb_types.h:138

◆ amxb_subscription_delete()

int amxb_subscription_delete ( amxb_subscription_t **  subscription)

Deletes a subscription object and unsubscribe for events of a object tree.

Unsubscribes for events of an object (sub)tree.

The passes subscription object must be created with amxb_subscription_new

Parameters
subscriptionThe subscription object
Returns
AMXB_STATUS_OK when subscription object was deleted and unsubscribe for events was successful. If unsubscribing for events fail, the subscription object will be deleted

Definition at line 250 of file amxb_subscription.c.

250  {
251  int rv = AMXB_STATUS_OK;
252  amxb_sub_t* sub = NULL;
253 
254  when_null(subscription, exit);
255  when_null(*subscription, exit);
256 
257  sub = amxc_container_of((*subscription), amxb_sub_t, data);
258  rv = amxb_subscription_remove((*subscription));
259 
260  amxc_llist_it_take(&(*subscription)->it);
261  free((*subscription)->object);
262  free(sub);
263 
264  *subscription = NULL;
265 
266 exit:
267  return rv;
268 }
int amxb_subscription_remove(amxb_subscription_t *subscription)
#define AMXB_STATUS_OK
All ok.
Definition: amxb_error.h:86
Definition: amxb_priv.h:64

◆ amxb_subscription_find()

amxb_subscription_t* amxb_subscription_find ( amxb_bus_ctx_t bus_ctx,
const char *  object,
amxp_slot_fn_t  slot_cb,
void *  priv 
)

Find an exact subscription.

Searches in the given bus context for the first matching subscription. A subscription is matching when the object path, the slot_cb and private data is exactly matching .

Parameters
bus_ctxThe bus context (or connection)
objectobject or search path, object paths must end with a "."
slot_cbcallback function, called for each matching event
privprivate data, passed to the callback function
Returns
subscription pointer or NULL if no matching found.

Definition at line 216 of file amxb_subscription.c.

219  {
220  amxb_subscription_t* subscription = NULL;
221 
222  when_str_empty(object, exit);
223  when_null(slot_cb, exit);
224 
225  amxc_llist_iterate(it, (&bus_ctx->client_subs)) {
226  amxb_sub_t* sub = amxc_container_of(it, amxb_sub_t, it);
227  subscription = &sub->data;
228  if((strcmp(subscription->object, object) == 0) &&
229  ( subscription->slot_cb == slot_cb) &&
230  ( subscription->priv == priv)) {
231  break;
232  }
233  subscription = NULL;
234  }
235 
236 exit:
237  return subscription;
238 }
amxc_llist_t client_subs
Definition: amxb_types.h:127
amxp_slot_fn_t slot_cb
Definition: amxb_types.h:159
amxb_subscription_t data
Definition: amxb_priv.h:66
static amxb_bus_ctx_t * bus_ctx
Definition: test_amxb_e2e.c:84

◆ amxb_subscription_find_child()

amxb_subscription_t* amxb_subscription_find_child ( amxb_bus_ctx_t bus_ctx,
const char *  object 
)

Find a child subscription.

A child subscription is a subscription taken on a child object path.

If a search path is given only the fixed part of the path is taken into account.

Parameters
bus_ctxThe bus context (or connection)
objectobject or search path, object paths must end with a "."
Returns
subscription pointer or NULL if no matching found.

Definition at line 245 of file amxb_subscription.c.

246  {
247  return amxb_subscription_find_relation(bus_ctx, object, false);
248 }
static amxb_subscription_t * amxb_subscription_find_relation(amxb_bus_ctx_t *bus_ctx, const char *object, bool parent)

◆ amxb_subscription_find_parent()

amxb_subscription_t* amxb_subscription_find_parent ( amxb_bus_ctx_t bus_ctx,
const char *  object 
)

Find a parent subscription.

A parent subscription is a subscription taken on a parent object path.

If a search path is given only the fixed part of the path is taken into account.

Parameters
bus_ctxThe bus context (or connection)
objectobject or search path, object paths must end with a "."
Returns
subscription pointer or NULL if no matching found.

Definition at line 240 of file amxb_subscription.c.

241  {
242  return amxb_subscription_find_relation(bus_ctx, object, true);
243 }

◆ amxb_subscription_new()

int amxb_subscription_new ( amxb_subscription_t **  subscription,
amxb_bus_ctx_t bus_ctx,
const char *  object,
const char *  expression,
amxp_slot_fn_t  slot_cb,
void *  priv 
)

Creates a subscription object and subscribes for events of a object tree.

Subscribes for all events matching the given filter on an object (sub)tree.

Using the provided object path, all events matching the given expression, of that object or any of the child objects (instances included) are passed to the callback function.

A subscription object amxb_subscription_t is allocated and must be freed using using amxb_subscription_delete.

The allocated subscription object can be stored in a amxc linked list.

Parameters
subscriptionThe new allocated subscription object
bus_ctxThe bus context (or connection)
objectobject or search path, object paths must end with a "."
expressionan expression used to filter the events
slot_cbcallback function, called for each matching event
privprivate data, passed to the callback function
Returns
AMXB_STATUS_OK when subscription object was created and subscribing for events was successful. When failed any other error code can be returned and the subscription object is NULL.

Definition at line 187 of file amxb_subscription.c.

192  {
193  int retval = AMXB_ERROR_UNKNOWN;
194  amxb_sub_t* sub = amxb_sub_alloc(object, slot_cb, priv);
195 
196  when_null(sub, exit);
197  *subscription = &sub->data;
198 
199  retval = amxb_subscribe(bus_ctx,
200  object,
201  expression,
202  (*subscription)->slot_cb,
203  (*subscription)->priv);
204  when_failed(retval, exit);
205  amxc_llist_append(&bus_ctx->client_subs, &sub->it);
206 
207 exit:
208  if((retval != AMXB_STATUS_OK) && (sub != NULL)) {
209  free((*subscription)->object);
210  free(sub);
211  *subscription = NULL;
212  }
213  return retval;
214 }
static amxb_sub_t * amxb_sub_alloc(const char *object, amxp_slot_fn_t slot_cb, void *priv)
#define AMXB_ERROR_UNKNOWN
Unknown error.
Definition: amxb_error.h:80
int amxb_subscribe(amxb_bus_ctx_t *const ctx, const char *object, const char *expression, amxp_slot_fn_t slot_cb, void *priv)
Subscribes for events of a object tree.
amxc_llist_it_t it
Definition: amxb_priv.h:65

◆ amxb_unsubscribe()

int amxb_unsubscribe ( amxb_bus_ctx_t *const  ctx,
const char *  object,
amxp_slot_fn_t  slot_cb,
void *  priv 
)

Removes an event subscription.

When not interested any more in events of a certain object (sub)tree, the subscription can be removed using this function.

To remove a subscription the given object path, callback function and private data pointer must match the one used when the subscription was taken with amxb_subscribe.

Parameters
ctxThe bus context (or connection)
objectobject path to the object object paths must end with a "."
slot_cbcallback function, called for each matching event
privprivate data, passed to the callback function
Returns
AMXB_STATUS_OK remote function has completed successful

Definition at line 274 of file amxb_ba_subscribe.c.

277  {
278  int retval = -1;
279  const amxb_be_funcs_t* fns = NULL;
280  amxb_request_t* req = NULL;
281  amxp_signal_t* signal = NULL;
282  char* obj_path = NULL;
283  amxc_var_t info;
284  amxd_path_t path;
285 
286  amxd_path_init(&path, NULL);
287  amxc_var_init(&info);
288 
289  when_null(ctx, exit);
290  when_null(ctx->bus_ctx, exit);
291  when_str_empty(object, exit);
292 
293  amxd_path_setf(&path, true, "%s", object);
294  if((path.type == amxd_path_invalid) ||
295  (path.type == amxd_path_reference) ||
296  (path.type == amxd_path_supported)) {
297  goto exit;
298  }
299  obj_path = amxd_path_get_fixed_part(&path, false);
300 
301  retval = amxb_describe(ctx, obj_path, 0, &info, 5);
302  if(retval == 0) {
303  free(obj_path);
304  amxb_build_path(&info, &path);
305  obj_path = amxd_path_get_fixed_part(&path, false);
306  }
307 
308  when_null(obj_path, exit);
309 
310  amxc_var_set_type(&info, AMXC_VAR_ID_HTABLE);
311  req = amxb_async_call(ctx, obj_path, "_unsubscribe", &info, NULL, NULL);
312  amxb_close_request(&req);
313 
314  if(*obj_path != 0) {
315  obj_path[strlen(obj_path) - 1] = 0;
316  }
317 
318  retval = -1;
319  signal = amxp_sigmngr_find_signal(&ctx->sigmngr, obj_path);
320  when_null(signal, exit);
321 
322  if(priv == NULL) {
323  amxp_slot_disconnect(&ctx->sigmngr, obj_path, slot_cb);
324  } else {
325  amxp_slot_disconnect_signal_with_priv(&ctx->sigmngr, obj_path, slot_cb, priv);
326  }
327  retval = 0;
328  when_true(amxp_signal_has_slots(signal), exit);
329 
330  fns = ctx->bus_fn;
331  if(amxb_is_valid_be_func(fns, unsubscribe, fns->unsubscribe)) {
332  retval = fns->unsubscribe(ctx->bus_ctx,
333  obj_path);
334  } else {
335  retval = AMXB_STATUS_OK;
336  }
337 
338  amxp_signal_delete(&signal);
339 
340 exit:
341  free(obj_path);
342  amxd_path_clean(&path);
343  amxc_var_clean(&info);
344  return retval;
345 }
#define amxb_is_valid_be_func(ft, member, ptr)
Definition: amxb_priv.h:78
The back-end interface structure.
amxb_be_unsubscribe_fn_t unsubscribe
const amxb_be_funcs_t * bus_fn
Definition: amxb_types.h:121
amxp_signal_mngr_t sigmngr
Definition: amxb_types.h:120

◆ amxb_wait_for_object()

int amxb_wait_for_object ( const char *  object)

Checks if an object is available, if not waits for it.

When all objects are available, the signal "wait:done" is emitted on the global signal manager.

The signal is not defined by default, and must be added to the global signal manager before calling this method. It is also recommended to connect the callback functions (slots) to the signal prior to calling this method.

This function can be called multiple times. If the function is called multiple times before giving back control to the eventloop, the signal "wait:done" is emitted as soon as all objects are available.

Each time the function is called to wait for a new object, a new signal "wait:<OBJECT-PATH>" is created. This signal will be emitted when this object becomes available. However, as this signal does not exist until the moment the function is called, you cannot connect a slot to it beforehand. You can however use amxp_slot_connect_filtered to filter for the specific signal.

It is possible to add new objects to the waiting list. If "wait:done" signal was already emitted a new wait cycle is started.

The wait for object work asynchronously, so it is possible to start other tasks.

Warning
This function works on all open connections on the moment the function is called. The wait for object feature depends on the bus specific implementation. If the used underlying bus system does not support a wait for feature, it is possible that the signal is never emitted.
Parameters
objectobject path
Returns
AMXB_STATUS_OK when successful

Definition at line 105 of file amxb_ba_wait_for.c.

105  {
106  int retval = -1;
107  amxd_path_t path;
108  char* object_path = NULL;
109  amxb_bus_ctx_t* bus_ctx = NULL;
110  amxc_string_t signal_name;
111  amxp_signal_t* signal = NULL;
112 
113  amxd_path_init(&path, NULL);
114  amxc_string_init(&signal_name, 0);
115 
116  when_str_empty(object, exit);
117 
118  amxd_path_setf(&path, true, "%s", object);
119  object_path = amxd_path_get_fixed_part(&path, AMXD_OBJECT_TERMINATE);
120  amxc_string_setf(&signal_name, "wait:%s", object_path);
121 
122  signal = amxp_sigmngr_find_signal(NULL, amxc_string_get(&signal_name, 0));
123  if(signal == NULL) {
124  retval = amxp_signal_new(NULL, &signal, amxc_string_get(&signal_name, 0));
125  when_failed(retval, exit);
126  amxp_slot_connect(NULL, amxc_string_get(&signal_name, 0), NULL,
129  }
130 
131  // When waiting for an object, make sure that the exact full path is matched
132  // remove entry from the cache and check again with full path matching
133  // full path is the fixed part (no wildcard or search parts)
134  amxb_be_cache_remove_path(object_path);
135  bus_ctx = amxb_be_who_has_impl(object_path, true);
136  if(bus_ctx != NULL) {
137  amxp_signal_emit(signal, NULL);
138  retval = 0;
139  } else {
140  retval = amxb_be_for_all_connections(amxb_wait_for_impl, NULL, (void*) object_path);
141  }
142 
143 exit:
144  free(object_path);
145  amxc_string_clean(&signal_name);
146  amxd_path_clean(&path);
147  return retval;
148 }
static int32_t wait_for_objects
static void amxb_wait_object_available(const char *const sig_name, UNUSED const amxc_var_t *const data, UNUSED void *const priv)
static int amxb_wait_for_impl(amxb_bus_ctx_t *bus_ctx, UNUSED const amxc_var_t *args, void *priv)
amxb_bus_ctx_t * amxb_be_who_has_impl(const char *object_path, bool full_match)
int amxb_be_for_all_connections(amxb_be_task_fn_t fn, const amxc_var_t *args, void *priv)
Calls a function on all open connections.
void amxb_be_cache_remove_path(const char *object_path)
Removes an object path and its corresponding bus context from the lookup cache.