Code

store: Added sdb_store_get_child().
authorSebastian Harl <sh@tokkee.org>
Mon, 3 Nov 2014 18:35:34 +0000 (19:35 +0100)
committerSebastian Harl <sh@tokkee.org>
Mon, 3 Nov 2014 18:35:34 +0000 (19:35 +0100)
This function may be used to retrieve a host's child object (service, metric,
attribute) by it's name.

src/core/store.c
src/include/core/store.h
t/unit/core/store_test.c

index b2062831c7447cff2feeea535e9ee325e45e70b1..d6ad01fedd354da89efaa9bac27c6b44921cd180 100644 (file)
@@ -426,8 +426,9 @@ store_attr(sdb_store_obj_t *parent, sdb_avltree_t *attributes,
 static sdb_avltree_t *
 get_host_children(sdb_host_t *host, int type)
 {
-       assert((type == SDB_SERVICE) || (type == SDB_METRIC)
-                       || (type == SDB_ATTRIBUTE));
+       if ((type != SDB_SERVICE) && (type != SDB_METRIC)
+                       && (type != SDB_ATTRIBUTE))
+               return NULL;
 
        if (! host)
                return NULL;
@@ -762,6 +763,20 @@ sdb_store_metric_attr(const char *hostname, const char *metric,
        return status;
 } /* sdb_store_metric_attr */
 
+sdb_store_obj_t *
+sdb_store_get_child(sdb_store_obj_t *host, int type, const char *name)
+{
+       sdb_avltree_t *children;
+
+       if ((! host) || (host->type != SDB_HOST) || (! name))
+               return NULL;
+
+       children = get_host_children(HOST(host), type);
+       if (! children)
+               return NULL;
+       return STORE_OBJ(sdb_avltree_lookup(children, name));
+} /* sdb_store_get_child */
+
 int
 sdb_store_fetch_timeseries(const char *hostname, const char *metric,
                sdb_timeseries_opts_t *opts, sdb_strbuf_t *buf)
index 9bb75948d76e76c759568dda46860b67f179ade7..b84fc72720d2fa5938b5121650d22ef0dc554683 100644 (file)
@@ -216,6 +216,20 @@ 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_store_get_child:
+ * Retrieve a host's child object of the specified type and name. The
+ * reference count of the child object will be incremented before returning
+ * it. The caller is responsible for releasing the object once it's no longer
+ * used.
+ *
+ * Returns:
+ *  - the child object on success
+ *  - NULL else
+ */
+sdb_store_obj_t *
+sdb_store_get_child(sdb_store_obj_t *host, int type, const char *name);
+
 /*
  * A metric store describes how to access a metric's data.
  */
index ab3087acbc2cbe2101f1c877737048273e1c19b2..262f681de1ba8a7b69ca846ba20525b60cf67820 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <check.h>
 #include <string.h>
+#include <strings.h>
 
 static void
 populate(void)
@@ -501,6 +502,95 @@ START_TEST(test_get_field)
 }
 END_TEST
 
+START_TEST(test_get_child)
+{
+       struct {
+               const char *host;
+               const char *name;
+               int type;
+               int expected;
+       } golden_data[] = {
+               { "h1", NULL, SDB_HOST,       0 },
+               { "h1", NULL, SDB_SERVICE,   -1 },
+               { "h1", NULL, SDB_METRIC,    -1 },
+               { "h1", NULL, SDB_ATTRIBUTE, -1 },
+               { "h2", NULL, SDB_HOST,       0 },
+               { "h2", NULL, SDB_SERVICE,   -1 },
+               { "h2", NULL, SDB_METRIC,    -1 },
+               { "h2", NULL, SDB_ATTRIBUTE, -1 },
+               { "h3", NULL, SDB_HOST,      -1 },
+               { "h1", "k1", SDB_ATTRIBUTE,  0 },
+               { "h1", "x1", SDB_ATTRIBUTE, -1 },
+               { "h2", "k1", SDB_ATTRIBUTE, -1 },
+               { "h1", "k1", SDB_SERVICE,   -1 },
+               { "h1", "k1", SDB_METRIC,    -1 },
+               { "h1", "s1", SDB_SERVICE,   -1 },
+               { "h2", "s1", SDB_SERVICE,    0 },
+               { "h1", "m2", SDB_METRIC,     0 },
+               { "h2", "m2", SDB_METRIC,    -1 },
+       };
+
+       size_t i;
+
+       populate();
+
+       for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+               sdb_store_obj_t *obj;
+               const char *expected_name = golden_data[i].host;
+
+               obj = sdb_store_get_host(golden_data[i].host);
+               if (golden_data[i].expected && (golden_data[i].type == SDB_HOST))
+                       fail_unless(obj == NULL,
+                                       "sdb_store_get_host(%s) = %p; expected: NULL",
+                                       golden_data[i].host, obj);
+               else
+                       fail_unless(obj != NULL,
+                                       "sdb_store_get_host(%s) = NULL; expected: <host>",
+                                       golden_data[i].host);
+
+               if (golden_data[i].type != SDB_HOST) {
+                       sdb_store_obj_t *tmp;
+
+                       expected_name = golden_data[i].name;
+
+                       tmp = sdb_store_get_child(obj,
+                                       golden_data[i].type, golden_data[i].name);
+                       if (golden_data[i].expected)
+                               fail_unless(tmp == NULL,
+                                               "sdb_store_get_child(<%s>, %s, %s) = %p; "
+                                               "expected: NULL", golden_data[i].host,
+                                               SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
+                                               golden_data[i].name, tmp);
+                       else
+                               fail_unless(tmp != NULL,
+                                               "sdb_store_get_child(<%s>, %s, %s) = NULL; "
+                                               "expected: <obj>", golden_data[i].host,
+                                               SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
+                                               golden_data[i].name);
+
+                       sdb_object_deref(SDB_OBJ(obj));
+                       obj = tmp;
+               }
+
+               if (golden_data[i].expected)
+                       continue;
+
+               fail_unless(obj->type == golden_data[i].type,
+                               "sdb_store_get_<%s>(%s, %s) returned object of type %d; "
+                               "expected: %d", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
+                               golden_data[i].host, golden_data[i].name, obj->type,
+                               golden_data[i].type);
+               fail_unless(! strcasecmp(SDB_OBJ(obj)->name, expected_name),
+                               "sdb_store_get_<%s>(%s, %s) returned object named '%s'; "
+                               "expected: '%s'", SDB_STORE_TYPE_TO_NAME(golden_data[i].type),
+                               golden_data[i].host, golden_data[i].name, SDB_OBJ(obj)->name,
+                               expected_name);
+
+               sdb_object_deref(SDB_OBJ(obj));
+       }
+}
+END_TEST
+
 START_TEST(test_interval)
 {
        sdb_store_obj_t *host;
@@ -663,6 +753,7 @@ core_store_suite(void)
        tcase_add_test(tc, test_store_service);
        tcase_add_test(tc, test_store_service_attr);
        tcase_add_test(tc, test_get_field);
+       tcase_add_test(tc, test_get_child);
        tcase_add_test(tc, test_interval);
        tcase_add_test(tc, test_scan);
        tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);