aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2017-09-21 11:26:07 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2017-10-09 14:08:32 +0200
commitbb73f5b6fb216b4badb94767558e83e60cf08fd0 (patch)
treed6b66264ea13a780b4426d56b2546ae097040432
parentf2e72e1858d0be1a9cf3c0c4263f0bd81570d0e8 (diff)
afb-evt: prepare futur afb_eventid
Change-Id: Ie4668c2dadbdfbe79bac2c27a1b188edecbcf847 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/afb-api-dbus.c6
-rw-r--r--src/afb-evt.c480
-rw-r--r--src/afb-evt.h42
-rw-r--r--src/afb-hook.c38
-rw-r--r--src/afb-hook.h13
-rw-r--r--src/afb-stub-ws.c6
-rw-r--r--src/afb-trace.c26
7 files changed, 426 insertions, 185 deletions
diff --git a/src/afb-api-dbus.c b/src/afb-api-dbus.c
index d31eda00..69f63ae4 100644
--- a/src/afb-api-dbus.c
+++ b/src/afb-api-dbus.c
@@ -382,7 +382,7 @@ static struct dbus_event *api_dbus_client_event_search(struct api_dbus *api, int
struct dbus_event *ev;
ev = api->client.events;
- while (ev != NULL && (ev->id != id || 0 != strcmp(afb_evt_event_name(ev->event), name)))
+ while (ev != NULL && (ev->id != id || 0 != strcmp(afb_evt_event_fullname(ev->event), name)))
ev = ev->next;
return ev;
@@ -850,7 +850,7 @@ static int dbus_req_subscribe(struct afb_xreq *xreq, struct afb_event event)
rc = afb_evt_add_watch(dreq->listener->listener, event);
sd_bus_message_get_cookie(dreq->message, &msgid);
- afb_api_dbus_server_event_send(dreq->listener->origin, 'S', afb_evt_event_name(event), afb_evt_event_id(event), "", msgid);
+ afb_api_dbus_server_event_send(dreq->listener->origin, 'S', afb_evt_event_fullname(event), afb_evt_event_id(event), "", msgid);
return rc;
}
@@ -861,7 +861,7 @@ static int dbus_req_unsubscribe(struct afb_xreq *xreq, struct afb_event event)
int rc;
sd_bus_message_get_cookie(dreq->message, &msgid);
- afb_api_dbus_server_event_send(dreq->listener->origin, 'U', afb_evt_event_name(event), afb_evt_event_id(event), "", msgid);
+ afb_api_dbus_server_event_send(dreq->listener->origin, 'U', afb_evt_event_fullname(event), afb_evt_event_id(event), "", msgid);
rc = afb_evt_remove_watch(dreq->listener->listener, event);
return rc;
}
diff --git a/src/afb-evt.c b/src/afb-evt.c
index 1c81fd53..2bac0837 100644
--- a/src/afb-evt.c
+++ b/src/afb-evt.c
@@ -60,10 +60,13 @@ struct afb_evt_listener {
/*
* Structure for describing events
*/
-struct afb_evt_event {
+struct afb_evtid {
+
+ /* interface */
+ struct afb_event_itf *itf;
/* next event */
- struct afb_evt_event *next;
+ struct afb_evtid *next;
/* head of the list of listeners watching the event */
struct afb_evt_watch *watchs;
@@ -74,11 +77,14 @@ struct afb_evt_event {
/* hooking */
int hookflags;
+ /* refcount */
+ int refcount;
+
/* mutex of the event */
pthread_mutex_t mutex;
- /* name of the event */
- char name[1];
+ /* fullname of the event */
+ char fullname[1];
};
/*
@@ -86,16 +92,16 @@ struct afb_evt_event {
*/
struct afb_evt_watch {
- /* the event */
- struct afb_evt_event *event;
+ /* the evtid */
+ struct afb_evtid *evtid;
- /* link to the next listener for the same event */
- struct afb_evt_watch *next_by_event;
+ /* link to the next watcher for the same evtid */
+ struct afb_evt_watch *next_by_evtid;
/* the listener */
struct afb_evt_listener *listener;
- /* link to the next event for the same listener */
+ /* link to the next watcher for the same listener */
struct afb_evt_watch *next_by_listener;
/* activity */
@@ -103,17 +109,22 @@ struct afb_evt_watch {
};
/* declare functions */
-static int evt_broadcast(struct afb_evt_event *evt, struct json_object *obj);
-static int evt_push(struct afb_evt_event *evt, struct json_object *obj);
-static void evt_destroy(struct afb_evt_event *evt);
-static const char *evt_name(struct afb_evt_event *evt);
+static void evt_hooked_drop(struct afb_evtid *evtid);
/* the interface for events */
static struct afb_event_itf afb_evt_event_itf = {
- .broadcast = (void*)evt_broadcast,
- .push = (void*)evt_push,
- .drop = (void*)evt_destroy,
- .name = (void*)evt_name
+ .broadcast = (void*)afb_evt_evtid_broadcast,
+ .push = (void*)afb_evt_evtid_push,
+ .drop = (void*)afb_evt_evtid_unref,
+ .name = (void*)afb_evt_evtid_name
+};
+
+/* the interface for events */
+static struct afb_event_itf afb_evt_hooked_event_itf = {
+ .broadcast = (void*)afb_evt_evtid_hooked_broadcast,
+ .push = (void*)afb_evt_evtid_hooked_push,
+ .drop = (void*)evt_hooked_drop,
+ .name = (void*)afb_evt_evtid_hooked_name
};
/* head of the list of listeners */
@@ -122,23 +133,20 @@ static struct afb_evt_listener *listeners = NULL;
/* handling id of events */
static pthread_mutex_t events_mutex = PTHREAD_MUTEX_INITIALIZER;
-static struct afb_evt_event *events = NULL;
+static struct afb_evtid *evtids = NULL;
static int event_id_counter = 0;
static int event_id_wrapped = 0;
/*
* Broadcasts the 'event' of 'id' with its 'obj'
* 'obj' is released (like json_object_put)
- * calls hooks if hookflags isn't 0
* Returns the count of listener having receive the event.
*/
-static int broadcast(const char *event, struct json_object *obj, int id, int hookflags)
+static int broadcast(const char *event, struct json_object *obj, int id)
{
int result;
struct afb_evt_listener *listener;
- if (hookflags & afb_hook_flag_evt_broadcast_before)
- afb_hook_evt_broadcast_before(event, id, obj);
result = 0;
pthread_mutex_lock(&listeners_mutex);
listener = listeners;
@@ -150,20 +158,53 @@ static int broadcast(const char *event, struct json_object *obj, int id, int hoo
listener = listener->next;
}
pthread_mutex_unlock(&listeners_mutex);
+ json_object_put(obj);
+ return result;
+}
+
+/*
+ * Broadcasts the 'event' of 'id' with its 'obj'
+ * 'obj' is released (like json_object_put)
+ * calls hooks if hookflags isn't 0
+ * Returns the count of listener having receive the event.
+ */
+static int hooked_broadcast(const char *event, struct json_object *obj, int id, int hookflags)
+{
+ int result;
+
+ json_object_get(obj);
+
+ if (hookflags & afb_hook_flag_evt_broadcast_before)
+ afb_hook_evt_broadcast_before(event, id, obj);
+
+ result = broadcast(event, obj, id);
+
if (hookflags & afb_hook_flag_evt_broadcast_after)
afb_hook_evt_broadcast_after(event, id, obj, result);
+
json_object_put(obj);
+
return result;
}
/*
- * Broadcasts the event 'evt' with its 'object'
+ * Broadcasts the event 'evtid' with its 'object'
+ * 'object' is released (like json_object_put)
+ * Returns the count of listener that received the event.
+ */
+int afb_evt_evtid_broadcast(struct afb_evtid *evtid, struct json_object *object)
+{
+ return broadcast(evtid->fullname, object, evtid->id);
+}
+
+/*
+ * Broadcasts the event 'evtid' with its 'object'
* 'object' is released (like json_object_put)
* Returns the count of listener that received the event.
*/
-static int evt_broadcast(struct afb_evt_event *evt, struct json_object *object)
+int afb_evt_evtid_hooked_broadcast(struct afb_evtid *evtid, struct json_object *object)
{
- return broadcast(evt->name, object, evt->id, evt->hookflags);
+ return hooked_broadcast(evtid->fullname, object, evtid->id, evtid->hookflags);
}
/*
@@ -173,62 +214,64 @@ static int evt_broadcast(struct afb_evt_event *evt, struct json_object *object)
*/
int afb_evt_broadcast(const char *event, struct json_object *object)
{
- return broadcast(event, object, 0, -1);
+ return hooked_broadcast(event, object, 0, -1);
}
/*
- * Pushes the event 'evt' with 'obj' to its listeners
+ * Pushes the event 'evtid' with 'obj' to its listeners
* 'obj' is released (like json_object_put)
- * calls hooks if hookflags isn't 0
- * Returns the count of listener taht received the event.
+ * Returns the count of listener that received the event.
*/
-static int push(struct afb_evt_event *evt, struct json_object *obj, int hookflags)
+int afb_evt_evtid_push(struct afb_evtid *evtid, struct json_object *obj)
{
int result;
struct afb_evt_watch *watch;
struct afb_evt_listener *listener;
result = 0;
- pthread_mutex_lock(&evt->mutex);
- if (hookflags & afb_hook_flag_evt_push_before)
- afb_hook_evt_push_before(evt->name, evt->id, obj);
- watch = evt->watchs;
+ pthread_mutex_lock(&evtid->mutex);
+ watch = evtid->watchs;
while(watch) {
listener = watch->listener;
assert(listener->itf->push != NULL);
if (watch->activity != 0) {
- listener->itf->push(listener->closure, evt->name, evt->id, json_object_get(obj));
+ listener->itf->push(listener->closure, evtid->fullname, evtid->id, json_object_get(obj));
result++;
}
- watch = watch->next_by_event;
+ watch = watch->next_by_evtid;
}
- if (hookflags & afb_hook_flag_evt_push_after)
- afb_hook_evt_push_after(evt->name, evt->id, obj, result);
- pthread_mutex_unlock(&evt->mutex);
+ pthread_mutex_unlock(&evtid->mutex);
json_object_put(obj);
return result;
}
/*
- * Pushes the event 'evt' with 'obj' to its listeners
+ * Pushes the event 'evtid' with 'obj' to its listeners
* 'obj' is released (like json_object_put)
+ * Emits calls to hooks.
* Returns the count of listener taht received the event.
*/
-static int evt_push(struct afb_evt_event *evt, struct json_object *obj)
+int afb_evt_evtid_hooked_push(struct afb_evtid *evtid, struct json_object *obj)
{
- return push(evt, obj, evt->hookflags);
-}
+ int result;
-/*
- * Returns the name associated to the event 'evt'.
- */
-static const char *evt_name(struct afb_evt_event *evt)
-{
- const char *name = strchr(evt->name, '/');
- name = name ? name + 1 : evt->name;
- if (evt->hookflags & afb_hook_flag_evt_name)
- afb_hook_evt_name(evt->name, evt->id);
- return name;
+ /* lease the object */
+ json_object_get(obj);
+
+ /* hook before push */
+ if (evtid->hookflags & afb_hook_flag_evt_push_before)
+ afb_hook_evt_push_before(evtid->fullname, evtid->id, obj);
+
+ /* push */
+ result = afb_evt_evtid_push(evtid, obj);
+
+ /* hook after push */
+ if (evtid->hookflags & afb_hook_flag_evt_push_after)
+ afb_hook_evt_push_after(evtid->fullname, evtid->id, obj, result);
+
+ /* release the object */
+ json_object_put(obj);
+ return result;
}
/*
@@ -237,20 +280,20 @@ static const char *evt_name(struct afb_evt_event *evt)
static void remove_watch(struct afb_evt_watch *watch)
{
struct afb_evt_watch **prv;
- struct afb_evt_event *evt;
+ struct afb_evtid *evtid;
struct afb_evt_listener *listener;
/* notify listener if needed */
- evt = watch->event;
+ evtid = watch->evtid;
listener = watch->listener;
if (watch->activity != 0 && listener->itf->remove != NULL)
- listener->itf->remove(listener->closure, evt->name, evt->id);
+ listener->itf->remove(listener->closure, evtid->fullname, evtid->id);
/* unlink the watch for its event */
- prv = &evt->watchs;
+ prv = &evtid->watchs;
while(*prv != watch)
- prv = &(*prv)->next_by_event;
- *prv = watch->next_by_event;
+ prv = &(*prv)->next_by_evtid;
+ *prv = watch->next_by_evtid;
/* unlink the watch for its listener */
prv = &listener->watchs;
@@ -263,109 +306,169 @@ static void remove_watch(struct afb_evt_watch *watch)
}
/*
- * Destroys the event 'evt'
+ * Creates an event of name 'fullname' and returns it or NULL on error.
*/
-static void evt_destroy(struct afb_evt_event *evt)
+struct afb_evtid *afb_evt_evtid_create(const char *fullname)
+{
+ size_t len;
+ struct afb_evtid *evtid, *oevt;
+
+ /* allocates the event */
+ len = strlen(fullname);
+ evtid = malloc(len + sizeof * evtid);
+ if (evtid == NULL)
+ goto error;
+
+ /* allocates the id */
+ pthread_mutex_lock(&events_mutex);
+ do {
+ if (++event_id_counter < 0) {
+ event_id_wrapped = 1;
+ event_id_counter = 1024; /* heuristic: small numbers are not destroyed */
+ }
+ if (!event_id_wrapped)
+ break;
+ oevt = evtids;
+ while(oevt != NULL && oevt->id != event_id_counter)
+ oevt = oevt->next;
+ } while (oevt != NULL);
+
+ /* initialize the event */
+ memcpy(evtid->fullname, fullname, len + 1);
+ evtid->next = evtids;
+ evtid->watchs = NULL;
+ evtid->id = event_id_counter;
+ pthread_mutex_init(&evtid->mutex, NULL);
+ evtids = evtid;
+ evtid->hookflags = afb_hook_flags_evt(evtid->fullname);
+ evtid->itf = evtid->hookflags ? &afb_evt_hooked_event_itf : &afb_evt_event_itf;
+ if (evtid->hookflags & afb_hook_flag_evt_create)
+ afb_hook_evt_create(evtid->fullname, evtid->id);
+ pthread_mutex_unlock(&events_mutex);
+
+ /* returns the event */
+ return evtid;
+error:
+ return NULL;
+}
+
+/*
+ * increment the reference count of the event 'evtid'
+ */
+struct afb_evtid *afb_evt_evtid_addref(struct afb_evtid *evtid)
+{
+ __atomic_add_fetch(&evtid->refcount, 1, __ATOMIC_RELAXED);
+ return evtid;
+}
+
+/*
+ * increment the reference count of the event 'evtid'
+ */
+struct afb_evtid *afb_evt_evtid_hooked_addref(struct afb_evtid *evtid)
+{
+ if (evtid->hookflags & afb_hook_flag_evt_addref)
+ afb_hook_evt_addref(evtid->fullname, evtid->id);
+ return afb_evt_evtid_addref(evtid);
+}
+
+/*
+ * decrement the reference count of the event 'evtid'
+ * and destroy it when the count reachs zero
+ */
+void afb_evt_evtid_unref(struct afb_evtid *evtid)
{
int found;
- struct afb_evt_event **prv;
+ struct afb_evtid **prv;
struct afb_evt_listener *listener;
- if (evt != NULL) {
+ if (!__atomic_sub_fetch(&evtid->refcount, 1, __ATOMIC_RELAXED)) {
/* unlinks the event if valid! */
pthread_mutex_lock(&events_mutex);
found = 0;
- prv = &events;
- while (*prv && !(found = (*prv == evt)))
+ prv = &evtids;
+ while (*prv && !(found = (*prv == evtid)))
prv = &(*prv)->next;
if (found)
- *prv = evt->next;
+ *prv = evtid->next;
pthread_mutex_unlock(&events_mutex);
/* destroys the event */
- if (found) {
+ if (!found)
+ ERROR("event not found");
+ else {
/* removes all watchers */
- while(evt->watchs != NULL) {
- listener = evt->watchs->listener;
+ while(evtid->watchs != NULL) {
+ listener = evtid->watchs->listener;
pthread_mutex_lock(&listener->mutex);
- pthread_mutex_lock(&evt->mutex);
- remove_watch(evt->watchs);
- pthread_mutex_unlock(&evt->mutex);
+ pthread_mutex_lock(&evtid->mutex);
+ remove_watch(evtid->watchs);
+ pthread_mutex_unlock(&evtid->mutex);
pthread_mutex_unlock(&listener->mutex);
}
/* hook */
- if (evt->hookflags & afb_hook_flag_evt_drop)
- afb_hook_evt_drop(evt->name, evt->id);
+ if (evtid->hookflags & afb_hook_flag_evt_drop)
+ afb_hook_evt_drop(evtid->fullname, evtid->id);
/* free */
- pthread_mutex_destroy(&evt->mutex);
- free(evt);
+ pthread_mutex_destroy(&evtid->mutex);
+ free(evtid);
}
}
}
/*
- * Creates an event of 'name' and returns it.
- * Returns an event with closure==NULL in case of error.
+ * decrement the reference count of the event 'evtid'
+ * and destroy it when the count reachs zero
*/
-struct afb_event afb_evt_create_event(const char *name)
+void afb_evt_evtid_hooked_unref(struct afb_evtid *evtid)
{
- size_t len;
- struct afb_evt_event *evt, *oevt;
-
- /* allocates the event */
- len = strlen(name);
- evt = malloc(len + sizeof * evt);
- if (evt == NULL)
- goto error;
-
- /* allocates the id */
- pthread_mutex_lock(&events_mutex);
- do {
- if (++event_id_counter < 0) {
- event_id_wrapped = 1;
- event_id_counter = 1024; /* heuristic: small numbers are not destroyed */
- }
- if (!event_id_wrapped)
- break;
- oevt = events;
- while(oevt != NULL && oevt->id != event_id_counter)
- oevt = oevt->next;
- } while (oevt != NULL);
+ if (evtid->hookflags & afb_hook_flag_evt_unref)
+ afb_hook_evt_unref(evtid->fullname, evtid->id);
+ afb_evt_evtid_unref(evtid);
+}
- /* initialize the event */
- memcpy(evt->name, name, len + 1);
- evt->next = events;
- evt->watchs = NULL;
- evt->id = event_id_counter;
- pthread_mutex_init(&evt->mutex, NULL);
- events = evt;
- evt->hookflags = afb_hook_flags_evt(evt->name);
- if (evt->hookflags & afb_hook_flag_evt_create)
- afb_hook_evt_create(evt->name, evt->id);
- pthread_mutex_unlock(&events_mutex);
+static void evt_hooked_drop(struct afb_evtid *evtid)
+{
+ if (evtid->hookflags & afb_hook_flag_evt_drop)
+ afb_hook_evt_drop(evtid->fullname, evtid->id);
+ afb_evt_evtid_unref(evtid);
+}
- /* returns the event */
- return (struct afb_event){ .itf = &afb_evt_event_itf, .closure = evt };
-error:
- return (struct afb_event){ .itf = NULL, .closure = NULL };
+/*
+ * Returns the true name of the 'event'
+ */
+const char *afb_evt_evtid_fullname(struct afb_evtid *evtid)
+{
+ return evtid->fullname;
}
/*
* Returns the name of the 'event'
*/
-const char *afb_evt_event_name(struct afb_event event)
+const char *afb_evt_evtid_name(struct afb_evtid *evtid)
{
- return (event.itf != &afb_evt_event_itf) ? NULL : ((struct afb_evt_event *)event.closure)->name;
+ const char *name = strchr(evtid->fullname, '/');
+ return name ? name + 1 : evtid->fullname;
+}
+
+/*
+ * Returns the name associated to the event 'evtid'.
+ */
+const char *afb_evt_evtid_hooked_name(struct afb_evtid *evtid)
+{
+ const char *result = afb_evt_evtid_name(evtid);
+ if (evtid->hookflags & afb_hook_flag_evt_name)
+ afb_hook_evt_name(evtid->fullname, evtid->id, result);
+ return result;
}
/*
* Returns the id of the 'event'
*/
-int afb_evt_event_id(struct afb_event event)
+int afb_evt_evtid_id(struct afb_evtid *evtid)
{
- return (event.itf != &afb_evt_event_itf) ? 0 : ((struct afb_evt_event *)event.closure)->id;
+ return evtid->id;
}
/*
@@ -421,7 +524,7 @@ struct afb_evt_listener *afb_evt_listener_addref(struct afb_evt_listener *listen
void afb_evt_listener_unref(struct afb_evt_listener *listener)
{
struct afb_evt_listener **prv;
- struct afb_evt_event *evt;
+ struct afb_evtid *evtid;
if (!__atomic_sub_fetch(&listener->refcount, 1, __ATOMIC_RELAXED)) {
@@ -436,10 +539,10 @@ void afb_evt_listener_unref(struct afb_evt_listener *listener)
/* remove the watchers */
pthread_mutex_lock(&listener->mutex);
while (listener->watchs != NULL) {
- evt = listener->watchs->event;
- pthread_mutex_lock(&evt->mutex);
+ evtid = listener->watchs->evtid;
+ pthread_mutex_lock(&evtid->mutex);
remove_watch(listener->watchs);
- pthread_mutex_unlock(&evt->mutex);
+ pthread_mutex_unlock(&evtid->mutex);
}
pthread_mutex_unlock(&listener->mutex);
@@ -450,26 +553,24 @@ void afb_evt_listener_unref(struct afb_evt_listener *listener)
}
/*
- * Makes the 'listener' watching 'event'
+ * Makes the 'listener' watching 'evtid'
* Returns 0 in case of success or else -1.
*/
-int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event)
+int afb_evt_watch_add_evtid(struct afb_evt_listener *listener, struct afb_evtid *evtid)
{
struct afb_evt_watch *watch;
- struct afb_evt_event *evt;
/* check parameter */
- if (event.itf != &afb_evt_event_itf || listener->itf->push == NULL) {
+ if (listener->itf->push == NULL) {
errno = EINVAL;
return -1;
}
/* search the existing watch for the listener */
- evt = event.closure;
pthread_mutex_lock(&listener->mutex);
watch = listener->watchs;
while(watch != NULL) {
- if (watch->event == evt)
+ if (watch->evtid == evtid)
goto found;
watch = watch->next_by_listener;
}
@@ -483,19 +584,19 @@ int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event)
}
/* initialise and link */
- watch->event = evt;
+ watch->evtid = evtid;
watch->activity = 0;
watch->listener = listener;
watch->next_by_listener = listener->watchs;
listener->watchs = watch;
- pthread_mutex_lock(&evt->mutex);
- watch->next_by_event = evt->watchs;
- evt->watchs = watch;
- pthread_mutex_unlock(&evt->mutex);
+ pthread_mutex_lock(&evtid->mutex);
+ watch->next_by_evtid = evtid->watchs;
+ evtid->watchs = watch;
+ pthread_mutex_unlock(&evtid->mutex);
found:
if (watch->activity == 0 && listener->itf->add != NULL)
- listener->itf->add(listener->closure, evt->name, evt->id);
+ listener->itf->add(listener->closure, evtid->fullname, evtid->id);
watch->activity++;
pthread_mutex_unlock(&listener->mutex);
@@ -503,30 +604,22 @@ found:
}
/*
- * Avoids the 'listener' to watch 'event'
+ * Avoids the 'listener' to watch 'evtid'
* Returns 0 in case of success or else -1.
*/
-int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event event)
+int afb_evt_watch_sub_evtid(struct afb_evt_listener *listener, struct afb_evtid *evtid)
{
struct afb_evt_watch *watch;
- struct afb_evt_event *evt;
-
- /* check parameter */
- if (event.itf != &afb_evt_event_itf) {
- errno = EINVAL;
- return -1;
- }
/* search the existing watch */
- evt = event.closure;
pthread_mutex_lock(&listener->mutex);
watch = listener->watchs;
while(watch != NULL) {
- if (watch->event == evt) {
+ if (watch->evtid == evtid) {
if (watch->activity != 0) {
watch->activity--;
if (watch->activity == 0 && listener->itf->remove != NULL)
- listener->itf->remove(listener->closure, evt->name, evt->id);
+ listener->itf->remove(listener->closure, evtid->fullname, evtid->id);
}
pthread_mutex_unlock(&listener->mutex);
return 0;
@@ -543,26 +636,103 @@ int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event eve
*/
void afb_evt_update_hooks()
{
- struct afb_evt_event *evt;
+ struct afb_evtid *evtid;
pthread_mutex_lock(&events_mutex);
- for (evt = events ; evt ; evt = evt->next)
- evt->hookflags = afb_hook_flags_evt(evt->name);
+ for (evtid = evtids ; evtid ; evtid = evtid->next) {
+ evtid->hookflags = afb_hook_flags_evt(evtid->fullname);
+ evtid->itf = evtid->hookflags ? &afb_evt_hooked_event_itf : &afb_evt_event_itf;
+ }
pthread_mutex_unlock(&events_mutex);
}
+struct afb_evtid *afb_evt_to_evtid(struct afb_event event)
+{
+ return (struct afb_evtid*)(event.itf == &afb_evt_hooked_event_itf ? event.closure : NULL);
+}
+
+struct afb_event afb_evt_from_evtid(struct afb_evtid *evtid)
+{
+ return (struct afb_event){ .itf = evtid ? &afb_evt_hooked_event_itf : NULL, .closure = evtid };
+}
+
+/*
+ * Creates an event of 'fullname' and returns it.
+ * Returns an event with closure==NULL in case of error.
+ */
+struct afb_event afb_evt_create_event(const char *fullname)
+{
+ return afb_evt_from_evtid(afb_evt_evtid_create(fullname));
+}
+
+/*
+ * Returns the fullname of the 'event'
+ */
+const char *afb_evt_event_fullname(struct afb_event event)
+{
+ struct afb_evtid *evtid = afb_evt_to_evtid(event);
+ return evtid ? evtid->fullname : NULL;
+}
+
+/*
+ * Returns the id of the 'event'
+ */
+int afb_evt_event_id(struct afb_event event)
+{
+ struct afb_evtid *evtid = afb_evt_to_evtid(event);
+ return evtid ? evtid->id : 0;
+}
+
+/*
+ * Makes the 'listener' watching 'event'
+ * Returns 0 in case of success or else -1.
+ */
+int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event)
+{
+ struct afb_evtid *evtid = afb_evt_to_evtid(event);
+
+ /* check parameter */
+ if (!evtid) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* search the existing watch for the listener */
+ return afb_evt_watch_add_evtid(listener, evtid);
+}
+
+/*
+ * Avoids the 'listener' to watch 'event'
+ * Returns 0 in case of success or else -1.
+ */
+int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event event)
+{
+ struct afb_evtid *evtid = afb_evt_to_evtid(event);
+
+ /* check parameter */
+ if (!evtid) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* search the existing watch */
+ return afb_evt_watch_sub_evtid(listener, evtid);
+}
+
int afb_evt_push(struct afb_event event, struct json_object *object)
{
- if (event.itf == &afb_evt_event_itf)
- return evt_push((struct afb_evt_event *)event.closure, object);
+ struct afb_evtid *evtid = afb_evt_to_evtid(event);
+ if (evtid)
+ return afb_evt_evtid_hooked_push(evtid, object);
json_object_put(object);
return 0;
}
int afb_evt_unhooked_push(struct afb_event event, struct json_object *object)
{
- if (event.itf == &afb_evt_event_itf)
- return push((struct afb_evt_event *)event.closure, object, 0);
+ struct afb_evtid *evtid = afb_evt_to_evtid(event);
+ if (evtid)
+ return afb_evt_evtid_push(evtid, object);
json_object_put(object);
return 0;
}
diff --git a/src/afb-evt.h b/src/afb-evt.h
index 9071b32a..823f8fd0 100644
--- a/src/afb-evt.h
+++ b/src/afb-evt.h
@@ -18,16 +18,17 @@
#pragma once
struct afb_event;
+struct afb_evtid;
struct afb_session;
struct json_object;
struct afb_evt_listener;
struct afb_evt_itf
{
- void (*push)(void *closure, const char *event, int eventid, struct json_object *object);
- void (*broadcast)(void *closure, const char *event, int eventid, struct json_object *object);
- void (*add)(void *closure, const char *event, int eventid);
- void (*remove)(void *closure, const char *event, int eventid);
+ void (*push)(void *closure, const char *event, int evtid, struct json_object *object);
+ void (*broadcast)(void *closure, const char *event, int evtid, struct json_object *object);
+ void (*add)(void *closure, const char *event, int evtid);
+ void (*remove)(void *closure, const char *event, int evtid);
};
extern struct afb_evt_listener *afb_evt_listener_create(const struct afb_evt_itf *itf, void *closure);
@@ -37,8 +38,34 @@ extern int afb_evt_broadcast(const char *event, struct json_object *object);
extern struct afb_evt_listener *afb_evt_listener_addref(struct afb_evt_listener *listener);
extern void afb_evt_listener_unref(struct afb_evt_listener *listener);
-extern struct afb_event afb_evt_create_event(const char *name);
-extern const char *afb_evt_event_name(struct afb_event event);
+extern struct afb_evtid *afb_evt_evtid_create(const char *fullname);
+
+extern struct afb_evtid *afb_evt_evtid_addref(struct afb_evtid *evtid);
+extern struct afb_evtid *afb_evt_evtid_hooked_addref(struct afb_evtid *evtid);
+
+extern void afb_evt_evtid_unref(struct afb_evtid *evtid);
+extern void afb_evt_evtid_hooked_unref(struct afb_evtid *evtid);
+
+extern const char *afb_evt_evtid_fullname(struct afb_evtid *evtid);
+extern int afb_evt_evtid_id(struct afb_evtid *evtid);
+
+extern const char *afb_evt_evtid_name(struct afb_evtid *evtid);
+extern const char *afb_evt_evtid_hooked_name(struct afb_evtid *evtid);
+
+extern int afb_evt_evtid_push(struct afb_evtid *evtid, struct json_object *obj);
+extern int afb_evt_evtid_hooked_push(struct afb_evtid *evtid, struct json_object *obj);
+
+extern int afb_evt_evtid_broadcast(struct afb_evtid *evtid, struct json_object *object);
+extern int afb_evt_evtid_hooked_broadcast(struct afb_evtid *evtid, struct json_object *object);
+
+extern int afb_evt_watch_add_evtid(struct afb_evt_listener *listener, struct afb_evtid *evtid);
+extern int afb_evt_watch_sub_evtid(struct afb_evt_listener *listener, struct afb_evtid *evtid);
+
+extern void afb_evt_update_hooks();
+
+
+extern struct afb_event afb_evt_create_event(const char *fullname);
+extern const char *afb_evt_event_fullname(struct afb_event event);
extern int afb_evt_event_id(struct afb_event event);
extern int afb_evt_push(struct afb_event event, struct json_object *object);
@@ -47,4 +74,5 @@ extern int afb_evt_unhooked_push(struct afb_event event, struct json_object *obj
extern int afb_evt_add_watch(struct afb_evt_listener *listener, struct afb_event event);
extern int afb_evt_remove_watch(struct afb_evt_listener *listener, struct afb_event event);
-extern void afb_evt_update_hooks();
+extern struct afb_evtid *afb_evt_to_evtid(struct afb_event event);
+extern struct afb_event afb_evt_from_evtid(struct afb_evtid *evtid);
diff --git a/src/afb-hook.c b/src/afb-hook.c
index b3a13a7e..09e6062a 100644
--- a/src/afb-hook.c
+++ b/src/afb-hook.c
@@ -283,12 +283,12 @@ static void hook_xreq_session_set_LOA_default_cb(void *closure, const struct afb
static void hook_xreq_subscribe_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event event, int result)
{
- _hook_xreq_(xreq, "subscribe(%s:%d) -> %d", afb_evt_event_name(event), afb_evt_event_id(event), result);
+ _hook_xreq_(xreq, "subscribe(%s:%d) -> %d", afb_evt_event_fullname(event), afb_evt_event_id(event), result);
}
static void hook_xreq_unsubscribe_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, struct afb_event event, int result)
{
- _hook_xreq_(xreq, "unsubscribe(%s:%d) -> %d", afb_evt_event_name(event), afb_evt_event_id(event), result);
+ _hook_xreq_(xreq, "unsubscribe(%s:%d) -> %d", afb_evt_event_fullname(event), afb_evt_event_id(event), result);
}
static void hook_xreq_subcall_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *api, const char *verb, struct json_object *args)
@@ -726,7 +726,7 @@ static void hook_ditf_vverbose_cb(void *closure, const struct afb_hookid *hookid
static void hook_ditf_event_make_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event result)
{
- _hook_ditf_(export, "event_make(%s) -> %s:%d", name, afb_evt_event_name(result), afb_evt_event_id(result));
+ _hook_ditf_(export, "event_make(%s) -> %s:%d", name, afb_evt_event_fullname(result), afb_evt_event_id(result));
}
static void hook_ditf_rootdir_get_fd_cb(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
@@ -1234,9 +1234,9 @@ static void hook_evt_broadcast_after_default_cb(void *closure, const struct afb_
_hook_evt_(evt, id, "broadcast.after(%s) -> %d", json_object_to_json_string(obj), result);
}
-static void hook_evt_name_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+static void hook_evt_name_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id, const char *result)
{
- _hook_evt_(evt, id, "name");
+ _hook_evt_(evt, id, "name -> %s", result);
}
static void hook_evt_drop_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
@@ -1244,6 +1244,16 @@ static void hook_evt_drop_default_cb(void *closure, const struct afb_hookid *hoo
_hook_evt_(evt, id, "drop");
}
+static void hook_evt_addref_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+{
+ _hook_evt_(evt, id, "addref");
+}
+
+static void hook_evt_unref_default_cb(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+{
+ _hook_evt_(evt, id, "unref");
+}
+
static struct afb_hook_evt_itf hook_evt_default_itf = {
.hook_evt_create = hook_evt_create_default_cb,
.hook_evt_push_before = hook_evt_push_before_default_cb,
@@ -1251,7 +1261,9 @@ static struct afb_hook_evt_itf hook_evt_default_itf = {
.hook_evt_broadcast_before = hook_evt_broadcast_before_default_cb,
.hook_evt_broadcast_after = hook_evt_broadcast_after_default_cb,
.hook_evt_name = hook_evt_name_default_cb,
- .hook_evt_drop = hook_evt_drop_default_cb
+ .hook_evt_drop = hook_evt_drop_default_cb,
+ .hook_evt_addref = hook_evt_addref_default_cb,
+ .hook_evt_unref = hook_evt_unref_default_cb
};
/******************************************************************************
@@ -1301,9 +1313,9 @@ int afb_hook_evt_broadcast_after(const char *evt, int id, struct json_object *ob
return result;
}
-void afb_hook_evt_name(const char *evt, int id)
+void afb_hook_evt_name(const char *evt, int id, const char *result)
{
- _HOOK_EVT_(name, evt, id);
+ _HOOK_EVT_(name, evt, id, result);
}
void afb_hook_evt_drop(const char *evt, int id)
@@ -1311,6 +1323,16 @@ void afb_hook_evt_drop(const char *evt, int id)
_HOOK_EVT_(drop, evt, id);
}
+void afb_hook_evt_addref(const char *evt, int id)
+{
+ _HOOK_EVT_(addref, evt, id);
+}
+
+void afb_hook_evt_unref(const char *evt, int id)
+{
+ _HOOK_EVT_(unref, evt, id);
+}
+
/******************************************************************************
* section: hooking services (evt)
*****************************************************************************/
diff --git a/src/afb-hook.h b/src/afb-hook.h
index be4ba54a..9cdca9c7 100644
--- a/src/afb-hook.h
+++ b/src/afb-hook.h
@@ -293,11 +293,14 @@ extern void afb_hook_unref_svc(struct afb_hook_svc *hook);
#define afb_hook_flag_evt_broadcast_after 0x000010
#define afb_hook_flag_evt_name 0x000020
#define afb_hook_flag_evt_drop 0x000040
+#define afb_hook_flag_evt_addref 0x000080
+#define afb_hook_flag_evt_unref 0x000100
#define afb_hook_flags_evt_common (afb_hook_flag_evt_push_before|afb_hook_flag_evt_broadcast_before)
#define afb_hook_flags_evt_extra (afb_hook_flags_evt_common\
|afb_hook_flag_evt_push_after|afb_hook_flag_evt_broadcast_after\
- |afb_hook_flag_evt_create|afb_hook_flag_evt_drop)
+ |afb_hook_flag_evt_create|afb_hook_flag_evt_drop\
+ |afb_hook_flag_evt_addref|afb_hook_flag_evt_unref)
#define afb_hook_flags_evt_all (afb_hook_flags_evt_extra|afb_hook_flag_evt_name)
struct afb_hook_evt_itf {
@@ -306,8 +309,10 @@ struct afb_hook_evt_itf {
void (*hook_evt_push_after)(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj, int result);
void (*hook_evt_broadcast_before)(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj);
void (*hook_evt_broadcast_after)(void *closure, const struct afb_hookid *hookid, const char *evt, int id, struct json_object *obj, int result);
- void (*hook_evt_name)(void *closure, const struct afb_hookid *hookid, const char *evt, int id);
+ void (*hook_evt_name)(void *closure, const struct afb_hookid *hookid, const char *evt, int id, const char *result);
void (*hook_evt_drop)(void *closure, const struct afb_hookid *hookid, const char *evt, int id);
+ void (*hook_evt_addref)(void *closure, const struct afb_hookid *hookid, const char *evt, int id);
+ void (*hook_evt_unref)(void *closure, const struct afb_hookid *hookid, const char *evt, int id);
};
extern void afb_hook_evt_create(const char *evt, int id);
@@ -315,8 +320,10 @@ extern void afb_hook_evt_push_before(const char *evt, int id, struct json_object
extern int afb_hook_evt_push_after(const char *evt, int id, struct json_object *obj, int result);
extern void afb_hook_evt_broadcast_before(const char *evt, int id, struct json_object *obj);
extern int afb_hook_evt_broadcast_after(const char *evt, int id, struct json_object *obj, int result);
-extern void afb_hook_evt_name(const char *evt, int id);
+extern void afb_hook_evt_name(const char *evt, int id, const char *result);
extern void afb_hook_evt_drop(const char *evt, int id);
+extern void afb_hook_evt_addref(const char *evt, int id);
+extern void afb_hook_evt_unref(const char *evt, int id);
extern int afb_hook_flags_evt(const char *name);
extern struct afb_hook_evt *afb_hook_create_evt(const char *pattern, int flags, struct afb_hook_evt_itf *itf, void *closure);
diff --git a/src/afb-stub-ws.c b/src/afb-stub-ws.c
index bdc2c144..9c903247 100644
--- a/src/afb-stub-ws.c
+++ b/src/afb-stub-ws.c
@@ -211,7 +211,7 @@ static int server_req_subscribe_cb(struct afb_xreq *xreq, struct afb_event event
rc = afb_evt_add_watch(wreq->stubws->listener, event);
if (rc >= 0)
- rc = afb_proto_ws_call_subscribe(wreq->call, afb_evt_event_name(event), afb_evt_event_id(event));
+ rc = afb_proto_ws_call_subscribe(wreq->call, afb_evt_event_fullname(event), afb_evt_event_id(event));
if (rc < 0)
ERROR("error while subscribing event");
return rc;
@@ -222,7 +222,7 @@ static int server_req_unsubscribe_cb(struct afb_xreq *xreq, struct afb_event eve
int rc, rc2;
struct server_req *wreq = CONTAINER_OF_XREQ(struct server_req, xreq);
- rc = afb_proto_ws_call_unsubscribe(wreq->call, afb_evt_event_name(event), afb_evt_event_id(event));
+ rc = afb_proto_ws_call_unsubscribe(wreq->call, afb_evt_event_fullname(event), afb_evt_event_id(event));
rc2 = afb_evt_remove_watch(wreq->stubws->listener, event);
if (rc >= 0 && rc2 < 0)
rc = rc2;
@@ -248,7 +248,7 @@ static struct client_event *client_event_search(struct afb_stub_ws *stubws, uint
struct client_event *ev;
ev = stubws->events;
- while (ev != NULL && (ev->eventid != eventid || 0 != strcmp(afb_evt_event_name(ev->event), name)))
+ while (ev != NULL && (ev->eventid != eventid || 0 != strcmp(afb_evt_event_fullname(ev->event), name)))
ev = ev->next;
return ev;
diff --git a/src/afb-trace.c b/src/afb-trace.c
index 5e82274a..0de501a9 100644
--- a/src/afb-trace.c
+++ b/src/afb-trace.c
@@ -365,7 +365,7 @@ static void hook_xreq_subscribe(void *closure, const struct afb_hookid *hookid,
{
hook_xreq(closure, hookid, xreq, "subscribe", "{s{ss si} si}",
"event",
- "name", afb_evt_event_name(event),
+ "name", afb_evt_event_fullname(event),
"id", afb_evt_event_id(event),
"result", result);
}
@@ -374,7 +374,7 @@ static void hook_xreq_unsubscribe(void *closure, const struct afb_hookid *hookid
{
hook_xreq(closure, hookid, xreq, "unsubscribe", "{s{ss? si} si}",
"event",
- "name", afb_evt_event_name(event),
+ "name", afb_evt_event_fullname(event),
"id", afb_evt_event_id(event),
"result", result);
}
@@ -614,7 +614,7 @@ static void hook_ditf_vverbose(void *closure, const struct afb_hookid *hookid, c
static void hook_ditf_event_make(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, const char *name, struct afb_event result)
{
hook_ditf(closure, hookid, export, "event_make", "{ss ss si}",
- "name", name, "event", afb_evt_event_name(result), "id", afb_evt_event_id(result));
+ "name", name, "event", afb_evt_event_fullname(result), "id", afb_evt_event_id(result));
}
static void hook_ditf_rootdir_get_fd(void *closure, const struct afb_hookid *hookid, const struct afb_export *export, int result)
@@ -779,6 +779,7 @@ static struct afb_hook_svc_itf hook_svc_itf = {
/*******************************************************************************/
static struct flag evt_flags[] = { /* must be sorted by names */
+ { "addref", afb_hook_flag_evt_addref },
{ "all", afb_hook_flags_evt_all },
{ "broadcast_after", afb_hook_flag_evt_broadcast_after },
{ "broadcast_before", afb_hook_flag_evt_broadcast_before },
@@ -789,6 +790,7 @@ static struct flag evt_flags[] = { /* must be sorted by names */
{ "name", afb_hook_flag_evt_name },
{ "push_after", afb_hook_flag_evt_push_after },
{ "push_before", afb_hook_flag_evt_push_before },
+ { "unref", afb_hook_flag_evt_unref },
};
/* get the evt value for flag of 'name' */
@@ -835,9 +837,9 @@ static void hook_evt_broadcast_after(void *closure, const struct afb_hookid *hoo
hook_evt(closure, hookid, evt, id, "broadcast_after", "{sO* si}", "data", obj, "result", result);
}
-static void hook_evt_name(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+static void hook_evt_name(void *closure, const struct afb_hookid *hookid, const char *evt, int id, const char *result)
{
- hook_evt(closure, hookid, evt, id, "name", NULL);
+ hook_evt(closure, hookid, evt, id, "name", "{ss}", "result", result);
}
static void hook_evt_drop(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
@@ -845,6 +847,16 @@ static void hook_evt_drop(void *closure, const struct afb_hookid *hookid, const
hook_evt(closure, hookid, evt, id, "drop", NULL);
}
+static void hook_evt_addref(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+{
+ hook_evt(closure, hookid, evt, id, "addref", NULL);
+}
+
+static void hook_evt_unref(void *closure, const struct afb_hookid *hookid, const char *evt, int id)
+{
+ hook_evt(closure, hookid, evt, id, "unref", NULL);
+}
+
static struct afb_hook_evt_itf hook_evt_itf = {
.hook_evt_create = hook_evt_create,
.hook_evt_push_before = hook_evt_push_before,
@@ -852,7 +864,9 @@ static struct afb_hook_evt_itf hook_evt_itf = {
.hook_evt_broadcast_before = hook_evt_broadcast_before,
.hook_evt_broadcast_after = hook_evt_broadcast_after,
.hook_evt_name = hook_evt_name,
- .hook_evt_drop = hook_evt_drop
+ .hook_evt_drop = hook_evt_drop,
+ .hook_evt_addref = hook_evt_addref,
+ .hook_evt_unref = hook_evt_unref
};
/*******************************************************************************/