Code

store: Introduced service attributes.
authorSebastian Harl <sh@tokkee.org>
Fri, 4 Jul 2014 18:38:52 +0000 (20:38 +0200)
committerSebastian Harl <sh@tokkee.org>
Fri, 4 Jul 2014 18:38:52 +0000 (20:38 +0200)
src/core/store.c
src/include/core/store.h
t/unit/core/store_test.c

index fc2a7f472d6dbdc0fb7111c2096cbfde38741d6f..323ed778b7c52fa76c8d492447781b2920695995 100644 (file)
@@ -248,6 +248,9 @@ store_obj(sdb_llist_t *parent_list, int type, const char *name,
 
        assert(parent_list);
 
+       if (last_update <= 0)
+               last_update = sdb_gettime();
+
        old = STORE_OBJ(sdb_llist_search_by_name(parent_list, name));
        if (old) {
                if (old->last_update >= last_update) {
@@ -313,52 +316,52 @@ store_obj(sdb_llist_t *parent_list, int type, const char *name,
        return status;
 } /* store_obj */
 
-/* The host_lock has to be acquired before calling this function. */
 static int
-store_host_obj(const char *hostname, int type, const char *name,
-               sdb_time_t last_update, sdb_store_obj_t **updated_obj)
+store_attr(sdb_llist_t *attributes, const char *key, const sdb_data_t *value,
+               sdb_time_t last_update)
 {
-       char *cname = NULL;
-       sdb_host_t *host;
-       sdb_llist_t *parent_list;
+       sdb_store_obj_t *attr = NULL;
+       int status;
 
-       int status = 0;
+       status = store_obj(attributes, SDB_ATTRIBUTE, key, last_update, &attr);
+       if (status < 0)
+               return status;
 
-       if (last_update <= 0)
-               last_update = sdb_gettime();
+       assert(attr);
+       if (sdb_data_copy(&ATTR(attr)->value, value))
+               return -1;
+       return status;
+} /* store_attr */
+
+/* The host_lock has to be acquired before calling this function. */
+static sdb_llist_t *
+get_host_children(const char *hostname, int type)
+{
+       char *cname = NULL;
+       sdb_host_t *host;
 
        assert(hostname);
        assert((type == SDB_SERVICE) || (type == SDB_ATTRIBUTE));
 
        if (! host_list)
-               return -1;
+               return NULL;
 
        cname = sdb_plugin_cname(strdup(hostname));
        if (! cname) {
                sdb_log(SDB_LOG_ERR, "store: strdup failed");
-               return -1;
+               return NULL;
        }
 
        host = lookup_host(cname);
-       if (! host) {
-               sdb_log(SDB_LOG_ERR, "store: Failed to store %s '%s' - "
-                               "host '%s' not found", SDB_STORE_TYPE_TO_NAME(type),
-                               name, hostname);
-               free(cname);
-               return -1;
-       }
+       free(cname);
+       if (! host)
+               return NULL;
 
        if (type == SDB_ATTRIBUTE)
-               parent_list = host->attributes;
+               return host->attributes;
        else
-               parent_list = host->services;
-
-       status = store_obj(parent_list, type, name,
-                       last_update, updated_obj);
-
-       free(cname);
-       return status;
-} /* store_host_obj */
+               return host->services;
+} /* get_host_children */
 
 /*
  * store_common_tojson serializes common object attributes to JSON.
@@ -464,9 +467,6 @@ sdb_store_host(const char *name, sdb_time_t last_update)
        if (! name)
                return -1;
 
-       if (last_update <= 0)
-               last_update = sdb_gettime();
-
        cname = sdb_plugin_cname(strdup(name));
        if (! cname) {
                sdb_log(SDB_LOG_ERR, "store: strdup failed");
@@ -519,23 +519,23 @@ sdb_store_attribute(const char *hostname,
                const char *key, const sdb_data_t *value,
                sdb_time_t last_update)
 {
-       int status;
-
-       sdb_store_obj_t *updated_attr = NULL;
+       sdb_llist_t *attrs;
+       int status = 0;
 
        if ((! hostname) || (! key))
                return -1;
 
        pthread_rwlock_wrlock(&host_lock);
-       status = store_host_obj(hostname, SDB_ATTRIBUTE, key, last_update,
-                       &updated_attr);
-
-       if (status >= 0) {
-               assert(updated_attr);
-               if (sdb_data_copy(&ATTR(updated_attr)->value, value))
-                       status = -1;
+       attrs = get_host_children(hostname, SDB_ATTRIBUTE);
+       if (! attrs) {
+               sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' - "
+                               "host '%s' not found", key, hostname);
+               status = -1;
        }
 
+       if (! status)
+               status = store_attr(attrs, key, value, last_update);
+
        pthread_rwlock_unlock(&host_lock);
        return status;
 } /* sdb_store_attribute */
@@ -544,17 +544,62 @@ int
 sdb_store_service(const char *hostname, const char *name,
                sdb_time_t last_update)
 {
-       int status;
+       sdb_llist_t *services;
+
+       int status = 0;
 
        if ((! hostname) || (! name))
                return -1;
 
        pthread_rwlock_wrlock(&host_lock);
-       status = store_host_obj(hostname, SDB_SERVICE, name, last_update, NULL);
+       services = get_host_children(hostname, SDB_SERVICE);
+       if (! services) {
+               sdb_log(SDB_LOG_ERR, "store: Failed to store service '%s' - "
+                               "host '%s' not found", name, hostname);
+               status = -1;
+       }
+
+       if (! status)
+               status = store_obj(services, SDB_SERVICE, name, last_update, NULL);
        pthread_rwlock_unlock(&host_lock);
        return status;
 } /* sdb_store_service */
 
+int
+sdb_store_service_attr(const char *hostname, const char *service,
+               const char *key, const sdb_data_t *value, sdb_time_t last_update)
+{
+       sdb_llist_t *services;
+       sdb_service_t *svc;
+       int status = 0;
+
+       if ((! hostname) || (! service) || (! key))
+               return -1;
+
+       pthread_rwlock_wrlock(&host_lock);
+       services = get_host_children(hostname, SDB_SERVICE);
+       if (! services) {
+               sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' "
+                               "for service '%s' - host '%ss' not found",
+                               key, service, hostname);
+               pthread_rwlock_unlock(&host_lock);
+               return -1;
+       }
+
+       svc = SVC(sdb_llist_search_by_name(services, service));
+       if (! svc) {
+               sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' - "
+                               "service '%s/%s' not found", key, hostname, service);
+               status = -1;
+       }
+
+       if (! status)
+               status = store_attr(svc->attributes, key, value, last_update);
+
+       pthread_rwlock_unlock(&host_lock);
+       return status;
+} /* sdb_store_service_attr */
+
 int
 sdb_store_host_tojson(sdb_store_obj_t *h, sdb_strbuf_t *buf, int flags)
 {
index e273e7ca1aedb59702de8014c9efeb2c7ba7ffd9..1d64c4b7bee0a0f2d3944272521f3c74a85bc472 100644 (file)
@@ -141,6 +141,24 @@ int
 sdb_store_service(const char *hostname, const char *name,
                sdb_time_t last_update);
 
+/*
+ * sdb_store_service_attr:
+ * Add/update a service's attribute in the store. If the attribute, identified
+ * by its key, already exists for the specified service, it will be updated to
+ * the specified value. If the references service (for the specified host)
+ * does not exist, an error will be reported. Any memory required for storing
+ * the entry will be allocated and managed by the store itself.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a positive value if the new entry is older than the currently stored
+ *    entry (in this case, no update will happen)
+ *  - a negative value on error
+ */
+int
+sdb_store_service_attr(const char *hostname, const char *service,
+               const char *key, const sdb_data_t *value, sdb_time_t last_update);
+
 /*
  * Conditionals may be used to lookup hosts from the store based on a
  * conditional expression.
index 0a022e430508276e80563c7b37fc2fb494f6e511..6715a5b0868a49714b3a9e3664ff586e6455166c 100644 (file)
@@ -240,6 +240,54 @@ START_TEST(test_store_service)
 }
 END_TEST
 
+START_TEST(test_store_service_attr)
+{
+       struct {
+               const char *host;
+               const char *svc;
+               const char *attr;
+               const sdb_data_t value;
+               sdb_time_t  last_update;
+               int expected;
+       } golden_data[] = {
+               { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+               /* retry, it should still fail */
+               { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+               { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+               /* retry, it should still fail */
+               { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+               { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
+               { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
+               { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2,  0 },
+               { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
+               { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  1 },
+               { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
+               { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1,  0 },
+       };
+
+       size_t i;
+
+       sdb_store_host("m", 1);
+       sdb_store_host("l", 1);
+       sdb_store_service("m", "s1", 1);
+       sdb_store_service("l", "s1", 1);
+       sdb_store_service("l", "s2", 1);
+
+       for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+               int status;
+
+               status = sdb_store_service_attr(golden_data[i].host,
+                               golden_data[i].svc, golden_data[i].attr,
+                               &golden_data[i].value, golden_data[i].last_update);
+               fail_unless(status == golden_data[i].expected,
+                               "sdb_store_service_attr(%s, %s, %s, %d, %d) = %d; "
+                               "expected: %d", golden_data[i].host, golden_data[i].svc,
+                               golden_data[i].attr, golden_data[i].value.data.integer,
+                               golden_data[i].last_update, status, golden_data[i].expected);
+       }
+}
+END_TEST
+
 static void
 verify_json_output(sdb_strbuf_t *buf, const char *expected, int flags)
 {
@@ -497,6 +545,7 @@ core_store_suite(void)
        tcase_add_test(tc, test_store_get_host);
        tcase_add_test(tc, test_store_attr);
        tcase_add_test(tc, test_store_service);
+       tcase_add_test(tc, test_store_service_attr);
        tcase_add_test(tc, test_interval);
        tcase_add_test(tc, test_iterate);
        tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);