Generic callback support
authorHenning Rogge <hrogge@googlemail.com>
Tue, 8 Feb 2011 11:30:31 +0000 (12:30 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Tue, 8 Feb 2011 11:30:31 +0000 (12:30 +0100)
src/olsr_callbacks.c [new file with mode: 0644]
src/olsr_callbacks.h [new file with mode: 0644]
src/olsr_cfg_data.c
src/olsr_cfg_data.h

diff --git a/src/olsr_callbacks.c b/src/olsr_callbacks.c
new file mode 100644 (file)
index 0000000..674e69b
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * olsr_callback.c
+ *
+ *  Created on: Feb 8, 2011
+ *      Author: henning
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "common/list.h"
+#include "common/avl.h"
+#include "common/avl_olsr_comp.h"
+#include "olsr_logging.h"
+#include "olsr_callbacks.h"
+
+static const char *unknown_key(void *);
+
+struct avl_tree callback_provider_tree;
+
+void
+olsr_callback_init(void) {
+  avl_init(&callback_provider_tree, avl_comp_strcasecmp, false, NULL);
+}
+
+void
+olsr_callback_cleanup(void) {
+  struct olsr_callback_provider *prv, *iterator;
+
+  OLSR_FOR_ALL_CALLBACK_PROVIDERS(prv, iterator) {
+    olsr_callback_prv_destroy(prv);
+  }
+}
+
+int
+olsr_callback_prv_create(struct olsr_callback_provider *prv, const char *name) {
+  if (avl_find(&callback_provider_tree, name) != NULL) {
+    OLSR_WARN(LOG_CALLBACK, "Provider '%s' already exists\n", name);
+    return 1;
+  }
+
+  OLSR_DEBUG(LOG_CALLBACK, "Create callback provider '%s'\n", name);
+  memset(prv, 0, sizeof(*prv));
+
+  prv->node.key = strdup(name);
+  prv->name = prv->node.key;
+  avl_insert(&callback_provider_tree, &prv->node);
+
+  prv->getKey = unknown_key;
+  list_init_head(&prv->callbacks);
+  return 0;
+}
+
+void
+olsr_callback_prv_destroy(struct olsr_callback_provider *prv) {
+  struct olsr_callback_consumer *cons, *iterator;
+
+  OLSR_DEBUG(LOG_CALLBACK, "Destroying callback provider '%s' (object count %u)\n",
+      prv->name, prv->obj_count);
+
+  OLSR_FOR_ALL_CALLBACK_CONSUMERS(prv, cons, iterator) {
+    olsr_callback_cons_unregister(cons);
+  }
+
+  avl_delete(&callback_provider_tree, &prv->node);
+  free(prv->name);
+  prv->name = NULL;
+}
+
+struct olsr_callback_provider *
+olsr_callback_cons_register(const char *prv_name, const char *cons_name,
+    struct olsr_callback_consumer *cons) {
+  struct olsr_callback_provider *prv;
+
+  prv = avl_find_element(&callback_provider_tree, prv_name, prv, node);
+  if (prv == NULL) {
+    OLSR_WARN(LOG_CALLBACK, "Could not find callback provider '%s'\n", prv_name);
+    return NULL;
+  }
+
+  OLSR_DEBUG(LOG_CALLBACK, "Register callback '%s' with provider '%s'\n",
+      cons_name, prv_name);
+  cons->provider = prv;
+  cons->name = strdup(cons_name);
+  list_add_tail(&prv->callbacks, &cons->node);
+  return prv;
+}
+
+void
+olsr_callback_cons_unregister(struct olsr_callback_consumer *cons) {
+  if (cons->node.next != NULL && cons->node.prev) {
+    OLSR_DEBUG(LOG_CALLBACK, "Unregister callback '%s' with provider '%s'\n",
+        cons->name, cons->provider->name);
+
+    list_remove(&cons->node);
+    free (cons->name);
+    cons->name = NULL;
+    cons->provider = NULL;
+  }
+}
+
+void
+olsr_callback_add_object(struct olsr_callback_provider *prv, void *obj) {
+  struct olsr_callback_consumer *cons, *iterator;
+
+  prv->obj_count++;
+  OLSR_DEBUG(LOG_CALLBACK, "Adding object %s (%u) to callback '%s'\n",
+      prv->getKey(obj), prv->obj_count, prv->name);
+
+  OLSR_FOR_ALL_CALLBACK_CONSUMERS(prv, cons, iterator) {
+    OLSR_DEBUG(LOG_CALLBACK, "Calling '%s' add callback\n", cons->name);
+    cons->add(obj);
+  }
+}
+
+void
+olsr_callback_change_object(struct olsr_callback_provider *prv, void *obj) {
+  struct olsr_callback_consumer *cons, *iterator;
+
+  OLSR_DEBUG(LOG_CALLBACK, "Changing object %s (%u) of callback '%s'\n",
+      prv->getKey(obj), prv->obj_count, prv->name);
+
+  OLSR_FOR_ALL_CALLBACK_CONSUMERS(prv, cons, iterator) {
+    OLSR_DEBUG(LOG_CALLBACK, "Calling '%s' change callback\n", cons->name);
+    cons->change(obj);
+  }
+}
+
+void
+olsr_callback_remove_object(struct olsr_callback_provider *prv, void *obj) {
+  struct olsr_callback_consumer *cons, *iterator;
+
+  OLSR_DEBUG(LOG_CALLBACK, "Removing object %s (%u) from callback '%s'\n",
+      prv->getKey(obj), prv->obj_count, prv->name);
+
+  OLSR_FOR_ALL_CALLBACK_CONSUMERS(prv, cons, iterator) {
+    OLSR_DEBUG(LOG_CALLBACK, "Calling '%s' remove callback\n", cons->name);
+    cons->remove(obj);
+  }
+  prv->obj_count--;
+}
+
+static const char *
+unknown_key(void *obj) {
+  static char buffer[32];
+
+  snprintf(buffer, sizeof(buffer), "0x%zx", (size_t)obj);
+  return buffer;
+}
diff --git a/src/olsr_callbacks.h b/src/olsr_callbacks.h
new file mode 100644 (file)
index 0000000..a219422
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * olsr_callbacks.h
+ *
+ *  Created on: Feb 8, 2011
+ *      Author: henning
+ */
+
+#ifndef OLSR_CALLBACKS_H_
+#define OLSR_CALLBACKS_H_
+
+#include "common/list.h"
+#include "common/avl.h"
+#include "defs.h"
+
+struct olsr_callback_provider {
+  struct avl_node node;
+  char *name;
+
+  struct list_entity callbacks;
+  uint32_t obj_count;
+
+  const char *(*getKey)(void *);
+};
+
+struct olsr_callback_consumer {
+  struct list_entity node;
+  struct olsr_callback_provider *provider;
+  char *name;
+
+  void (*add)(void *);
+  void (*change)(void *);
+  void (*remove)(void *);
+};
+
+void olsr_callback_init(void);
+void olsr_callback_cleanup(void);
+
+int EXPORT(olsr_callback_prv_create)(struct olsr_callback_provider *, const char *);
+void EXPORT(olsr_callback_prv_destroy)(struct olsr_callback_provider *);
+
+struct olsr_callback_provider *EXPORT(olsr_callback_cons_register)(
+    const char *, const char *, struct olsr_callback_consumer *);
+void EXPORT(olsr_callback_cons_unregister)(struct olsr_callback_consumer *);
+
+void EXPORT(olsr_callback_add_object)(struct olsr_callback_provider *, void *);
+void EXPORT(olsr_callback_change_object)(struct olsr_callback_provider *, void *);
+void EXPORT(olsr_callback_remove_object)(struct olsr_callback_provider *, void *);
+
+#define OLSR_FOR_ALL_CALLBACK_PROVIDERS(provider, iterator) avl_for_each_element_safe(&callback_provider_tree, provider, node, iterator)
+#define OLSR_FOR_ALL_CALLBACK_CONSUMERS(provider, consumer, iterator) list_for_each_element_safe(&provider->callbacks, consumer, node, iterator)
+
+extern struct avl_tree EXPORT(callback_provider_tree);
+#endif /* OLSR_CALLBACKS_H_ */
index 327d728..885f405 100644 (file)
@@ -75,7 +75,8 @@ const char *LOG_SOURCE_NAMES[] = {
   "comport",
   "apm",
   "rtnetlink",
-  "tunnel"
+  "tunnel",
+  "callback"
 };
 
 const char *LOG_SEVERITY_NAMES[] = {
index 1141e52..1976661 100644 (file)
@@ -74,6 +74,7 @@ enum log_source {
   LOG_APM,                             //!< LOG_APM
   LOG_RTNETLINK,                       //!< LOG_RTNETLINK
   LOG_TUNNEL,                          //!< LOG_TUNNEL
+  LOG_CALLBACK,                        //!< LOG_CALLBACK
 
   /* this one must be the last of the enums ! */
   LOG_SOURCE_COUNT                     //!< LOG_SOURCE_COUNT