Code

plugin/store: Added support for "cname" plugins.
authorSebastian Harl <sh@tokkee.org>
Sat, 20 Jul 2013 00:08:27 +0000 (17:08 -0700)
committerSebastian Harl <sh@tokkee.org>
Sat, 20 Jul 2013 00:08:27 +0000 (17:08 -0700)
This type of plugins may be used to canonicalize hostnames. Before storing a
new hosts, all registered cname callbacks will be used to translate the
specified hostname before actually storing it.

src/core/plugin.c
src/core/store.c
src/include/core/plugin.h

index c248d37eff6c15f9abce00d3d0b53b0b636a580e..4dbea70109a49f13c6484b863d798ed79e582da9 100644 (file)
@@ -98,6 +98,7 @@ static _Bool            plugin_ctx_key_initialized = 0;
 static sdb_llist_t      *config_list = NULL;
 static sdb_llist_t      *init_list = NULL;
 static sdb_llist_t      *collector_list = NULL;
+static sdb_llist_t      *cname_list = NULL;
 static sdb_llist_t      *shutdown_list = NULL;
 static sdb_llist_t      *log_list = NULL;
 
@@ -415,6 +416,14 @@ sdb_plugin_register_log(const char *name, sdb_plugin_log_cb callback,
                        user_data);
 } /* sdb_plugin_register_log */
 
+int
+sdb_plugin_register_cname(const char *name, sdb_plugin_cname_cb callback,
+               sdb_object_t *user_data)
+{
+       return sdb_plugin_add_callback(&cname_list, "cname", name, callback,
+                       user_data);
+} /* sdb_plugin_register_cname */
+
 int
 sdb_plugin_register_collector(const char *name, sdb_plugin_collector_cb callback,
                const sdb_time_t *interval, sdb_object_t *user_data)
@@ -656,6 +665,37 @@ sdb_plugin_collector_loop(sdb_plugin_loop_t *loop)
        return 0;
 } /* sdb_plugin_read_loop */
 
+char *
+sdb_plugin_cname(char *hostname)
+{
+       sdb_llist_iter_t *iter;
+
+       if (! hostname)
+               return NULL;
+
+       if (! cname_list)
+               return hostname;
+
+       iter = sdb_llist_get_iter(cname_list);
+       while (sdb_llist_iter_has_next(iter)) {
+               sdb_plugin_cname_cb callback;
+               char *cname;
+
+               sdb_object_t *obj = sdb_llist_iter_get_next(iter);
+               assert(obj);
+
+               callback = SDB_PLUGIN_CB(obj)->cb_callback;
+               cname = callback(hostname, SDB_PLUGIN_CB(obj)->cb_user_data);
+               if (cname) {
+                       free(hostname);
+                       hostname = cname;
+               }
+               /* else: don't change hostname */
+       }
+       sdb_llist_iter_destroy(iter);
+       return hostname;
+} /* sdb_plugin_cname */
+
 int
 sdb_plugin_log(int prio, const char *msg)
 {
index c66b5236a95b82869d19b532237a0ed0e4832aef..64e9f64064c50956b6afe56ed4dc35f5d9e5b72b 100644 (file)
@@ -28,6 +28,7 @@
 #include "sysdb.h"
 #include "core/store.h"
 #include "core/error.h"
+#include "core/plugin.h"
 #include "utils/llist.h"
 
 #include <assert.h>
@@ -233,13 +234,22 @@ sdb_host_create(const char *name)
 int
 sdb_store_host(const sdb_host_t *host)
 {
+       char *cname;
+
        sdb_time_t last_update;
        sdb_host_t *old;
+
        int status = 0;
 
        if ((! host) || (! SDB_CONST_OBJ(host)->name))
                return -1;
 
+       cname = sdb_plugin_cname(strdup(SDB_CONST_OBJ(host)->name));
+       if (! cname) {
+               sdb_log(SDB_LOG_ERR, "store: strdup failed");
+               return -1;
+       }
+
        last_update = host->_last_update;
        if (last_update <= 0)
                last_update = sdb_gettime();
@@ -253,14 +263,13 @@ sdb_store_host(const sdb_host_t *host)
                }
        }
 
-       old = SDB_HOST(sdb_llist_search_by_name(host_list,
-                               SDB_CONST_OBJ(host)->name));
+       old = SDB_HOST(sdb_llist_search_by_name(host_list, cname));
 
        if (old) {
                if (old->_last_update > last_update) {
                        sdb_log(SDB_LOG_DEBUG, "store: Cannot update host '%s' - "
                                        "value too old (%"PRIscTIME" < %"PRIscTIME")",
-                                       SDB_CONST_OBJ(host)->name, last_update, old->_last_update);
+                                       cname, last_update, old->_last_update);
                        /* don't report an error; the host may be updated by multiple
                         * backends */
                        status = 1;
@@ -279,11 +288,14 @@ sdb_store_host(const sdb_host_t *host)
                        return -1;
                }
 
+               free(SDB_OBJ(new)->name);
+               SDB_OBJ(new)->name = cname;
+
                if (! new->attributes) {
                        if (! (new->attributes = sdb_llist_create())) {
                                char errbuf[1024];
                                sdb_log(SDB_LOG_ERR, "store: Failed to initialize "
-                                               "host object '%s': %s", SDB_CONST_OBJ(host)->name,
+                                               "host object '%s': %s", SDB_OBJ(new)->name,
                                                sdb_strerror(errno, errbuf, sizeof(errbuf)));
                                sdb_object_deref(SDB_OBJ(new));
                                pthread_rwlock_unlock(&host_lock);
@@ -295,7 +307,7 @@ sdb_store_host(const sdb_host_t *host)
                        if (! (new->services = sdb_llist_create())) {
                                char errbuf[1024];
                                sdb_log(SDB_LOG_ERR, "store: Failed to initialize "
-                                               "host object '%s': %s", SDB_CONST_OBJ(host)->name,
+                                               "host object '%s': %s", SDB_OBJ(new)->name,
                                                sdb_strerror(errno, errbuf, sizeof(errbuf)));
                                sdb_object_deref(SDB_OBJ(new));
                                pthread_rwlock_unlock(&host_lock);
index bef5e0b4ccb35251f261ff8af4defe54b898d2bf..446c8672ff890edd7a3180047ba7897677410b03 100644 (file)
@@ -87,12 +87,16 @@ int
 sdb_plugin_set_info(sdb_plugin_info_t *info, int type, ...);
 
 /*
- * plugin callback functions
+ * plugin callback functions:
+ * See the description of the respective register function for what arguments
+ * the callbacks expect.
  */
 
 typedef int (*sdb_plugin_config_cb)(oconfig_item_t *ci);
 typedef int (*sdb_plugin_init_cb)(sdb_object_t *user_data);
 typedef int (*sdb_plugin_collector_cb)(sdb_object_t *user_data);
+typedef char *(*sdb_plugin_cname_cb)(const char *name,
+               sdb_object_t *user_data);
 typedef int (*sdb_plugin_shutdown_cb)(sdb_object_t *user_data);
 typedef int (*sdb_plugin_log_cb)(int prio, const char *msg,
                sdb_object_t *user_data);
@@ -161,6 +165,25 @@ sdb_plugin_register_collector(const char *name,
                sdb_plugin_collector_cb callback,
                const sdb_time_t *interval, sdb_object_t *user_data);
 
+/*
+ * sdb_plugin_register_cname:
+ * Register a "cname" (canonicalize name) function. This type of function is
+ * called whenever a host is stored. It accepts the hostname and returns a
+ * canonicalized hostname which will then be used to actually store the host.
+ * If multiple such callbacks are registered, each one of them will be called
+ * in the order they have been registered, each one receiving the result of
+ * the previous callback. If the function returns NULL, the original hostname
+ * is not changed. Any other value has to be dynamically allocated. It will be
+ * freed later on by the core.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a negative value else
+ */
+int
+sdb_plugin_register_cname(const char *name, sdb_plugin_cname_cb callback,
+               sdb_object_t *user_data);
+
 /*
  * sdb_plugin_register_shutdown:
  * Register a "shutdown" function to be called after stopping all update
@@ -234,6 +257,16 @@ sdb_plugin_init_all(void);
 int
 sdb_plugin_collector_loop(sdb_plugin_loop_t *loop);
 
+/*
+ * sdb_plugin_cname:
+ * Returns the canonicalized hostname. The given hostname argument has to
+ * point to dynamically allocated memory and might be freed by the function.
+ * The return value will also be dynamically allocated (but it might be
+ * unchanged) and has to be freed by the caller.
+ */
+char *
+sdb_plugin_cname(char *hostname);
+
 /*
  * sdb_plugin_log:
  * Log the specified message using all registered log callbacks. The message