Code

store: Added core support for “metrics” objects.
authorSebastian Harl <sh@tokkee.org>
Sat, 2 Aug 2014 22:07:29 +0000 (00:07 +0200)
committerSebastian Harl <sh@tokkee.org>
Sat, 2 Aug 2014 22:07:29 +0000 (00:07 +0200)
This is going to be used to store information about available metrics (in the
broadest sense). A metric is any kind of queryable value like performance
data.

src/core/store-private.h
src/core/store.c
src/core/store_lookup.c
src/include/core/store.h
t/unit/core/store_test.c

index 3f070678dad16393c5ada4a6f0bf98fa13c861ff..3c23ebbb5ad102cdff7794f285a508d4be14b741 100644 (file)
@@ -78,10 +78,18 @@ typedef struct {
 #define SVC(obj) ((sdb_service_t *)(obj))
 #define CONST_SVC(obj) ((const sdb_service_t *)(obj))
 
+typedef struct {
+       sdb_store_obj_t super;
+
+       sdb_avltree_t *attributes;
+} sdb_metric_t;
+#define METRIC(obj) ((sdb_metric_t *)(obj))
+
 typedef struct {
        sdb_store_obj_t super;
 
        sdb_avltree_t *services;
+       sdb_avltree_t *metrics;
        sdb_avltree_t *attributes;
 } sdb_host_t;
 #define HOST(obj) ((sdb_host_t *)(obj))
index 5a00b6c3cd49a7bba31cb8755bf4bda73f9564f8..7611ec4329e0ff4a03b55795610581edca06db58 100644 (file)
@@ -58,6 +58,7 @@ static pthread_rwlock_t host_lock = PTHREAD_RWLOCK_INITIALIZER;
 
 static sdb_type_t sdb_host_type;
 static sdb_type_t sdb_service_type;
+static sdb_type_t sdb_metric_type;
 static sdb_type_t sdb_attribute_type;
 
 static int
@@ -105,6 +106,9 @@ sdb_host_init(sdb_object_t *obj, va_list ap)
        sobj->services = sdb_avltree_create();
        if (! sobj->services)
                return -1;
+       sobj->metrics = sdb_avltree_create();
+       if (! sobj->metrics)
+               return -1;
        sobj->attributes = sdb_avltree_create();
        if (! sobj->attributes)
                return -1;
@@ -121,6 +125,8 @@ sdb_host_destroy(sdb_object_t *obj)
 
        if (sobj->services)
                sdb_avltree_destroy(sobj->services);
+       if (sobj->metrics)
+               sdb_avltree_destroy(sobj->metrics);
        if (sobj->attributes)
                sdb_avltree_destroy(sobj->attributes);
 } /* sdb_host_destroy */
@@ -154,6 +160,35 @@ sdb_service_destroy(sdb_object_t *obj)
                sdb_avltree_destroy(sobj->attributes);
 } /* sdb_service_destroy */
 
+static int
+sdb_metric_init(sdb_object_t *obj, va_list ap)
+{
+       sdb_metric_t *sobj = METRIC(obj);
+       int ret;
+
+       /* this will consume the first argument (type) of ap */
+       ret = store_obj_init(obj, ap);
+       if (ret)
+               return ret;
+
+       sobj->attributes = sdb_avltree_create();
+       if (! sobj->attributes)
+               return -1;
+       return 0;
+} /* sdb_metric_init */
+
+static void
+sdb_metric_destroy(sdb_object_t *obj)
+{
+       sdb_metric_t *sobj = METRIC(obj);
+       assert(obj);
+
+       store_obj_destroy(obj);
+
+       if (sobj->attributes)
+               sdb_avltree_destroy(sobj->attributes);
+} /* sdb_metric_destroy */
+
 static int
 sdb_attr_init(sdb_object_t *obj, va_list ap)
 {
@@ -194,6 +229,12 @@ static sdb_type_t sdb_service_type = {
        sdb_service_destroy
 };
 
+static sdb_type_t sdb_metric_type = {
+       sizeof(sdb_metric_t),
+       sdb_metric_init,
+       sdb_metric_destroy
+};
+
 static sdb_type_t sdb_attribute_type = {
        sizeof(sdb_attribute_t),
        sdb_attr_init,
@@ -290,7 +331,11 @@ store_obj(sdb_avltree_t *parent_tree, int type, const char *name,
                }
                else {
                        sdb_type_t t;
-                       t = type == SDB_HOST ? sdb_host_type : sdb_service_type;
+                       t = type == SDB_HOST
+                               ? sdb_host_type
+                               : type == SDB_SERVICE
+                                       ? sdb_service_type
+                                       : sdb_metric_type;
                        new = STORE_OBJ(sdb_object_create(name, t, type, last_update));
                }
 
@@ -369,6 +414,8 @@ get_host_children(const char *hostname, int type)
        sdb_object_deref(SDB_OBJ(host));
        if (type == SDB_ATTRIBUTE)
                return host->attributes;
+       else if (type == SDB_METRIC)
+               return host->metrics;
        else
                return host->services;
 } /* get_host_children */
@@ -420,7 +467,9 @@ store_obj_tojson(sdb_avltree_t *tree, int type, sdb_strbuf_t *buf,
 {
        sdb_avltree_iter_t *iter;
 
-       assert((type == SDB_ATTRIBUTE) || (type == SDB_SERVICE));
+       assert((type == SDB_ATTRIBUTE)
+                       || (type == SDB_METRIC)
+                       || (type == SDB_SERVICE));
 
        sdb_strbuf_append(buf, "[");
        iter = sdb_avltree_get_iter(tree);
@@ -457,6 +506,12 @@ store_obj_tojson(sdb_avltree_t *tree, int type, sdb_strbuf_t *buf,
                        store_obj_tojson(SVC(sobj)->attributes, SDB_ATTRIBUTE,
                                        buf, filter, flags);
                }
+               else if ((sobj->type == SDB_METRIC)
+                               && (! (flags & SDB_SKIP_ATTRIBUTES))) {
+                       sdb_strbuf_append(buf, ", \"attributes\": ");
+                       store_obj_tojson(METRIC(sobj)->attributes, SDB_ATTRIBUTE,
+                                       buf, filter, flags);
+               }
                sdb_strbuf_append(buf, "}");
 
                if (sdb_avltree_iter_has_next(iter))
@@ -665,6 +720,11 @@ sdb_store_host_tojson(sdb_store_obj_t *h, sdb_strbuf_t *buf,
                store_obj_tojson(host->attributes, SDB_ATTRIBUTE, buf, filter, flags);
        }
 
+       if (! (flags & SDB_SKIP_METRICS)) {
+               sdb_strbuf_append(buf, ", \"metrics\": ");
+               store_obj_tojson(host->metrics, SDB_METRIC, buf, filter, flags);
+       }
+
        if (! (flags & SDB_SKIP_SERVICES)) {
                sdb_strbuf_append(buf, ", \"services\": ");
                store_obj_tojson(host->services, SDB_SERVICE, buf, filter, flags);
index 98417830f19a52bbf985905d4acfaa2464ca6b7c..c3029c75078db3c0ee6d35b0fcbe602a799f41f6 100644 (file)
@@ -233,6 +233,9 @@ match_name(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
                case SDB_SERVICE:
                        iter = sdb_avltree_get_iter(HOST(obj)->services);
                        break;
+               case SDB_METRIC:
+                       iter = sdb_avltree_get_iter(HOST(obj)->metrics);
+                       break;
                case SDB_ATTRIBUTE:
                        iter = sdb_avltree_get_iter(HOST(obj)->attributes);
                        break;
@@ -953,6 +956,8 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                type = SDB_HOST;
        else if (! strcasecmp(obj_type, "service"))
                type = SDB_SERVICE;
+       else if (! strcasecmp(obj_type, "metric"))
+               type = SDB_METRIC;
        else if (! strcasecmp(obj_type, "attribute"))
                type = SDB_ATTRIBUTE;
        else
index cb7f3e4bbe545e95bf9cd4b8108dbdee52ccfceb..a7d86f529df54f56c4f9328ac6068731f52a28fa 100644 (file)
@@ -46,11 +46,13 @@ extern "C" {
 enum {
        SDB_HOST = 1,
        SDB_SERVICE,
+       SDB_METRIC,
        SDB_ATTRIBUTE,
 };
 #define SDB_STORE_TYPE_TO_NAME(t) \
        (((t) == SDB_HOST) ? "host" \
                : ((t) == SDB_SERVICE) ? "service" \
+               : ((t) == SDB_METRIC) ? "metric" \
                : ((t) == SDB_ATTRIBUTE) ? "attribute" : "unknown")
 
 /*
@@ -400,8 +402,8 @@ sdb_store_inv_matcher(sdb_store_matcher_t *m);
  * of the matcher. Only those objects matching the filter will be considered.
  *
  * Note that the filter is applied to all object types (hosts, service,
- * attribute). Thus, any object-specific matchers are mostly unsuited for this
- * purpose and, if used, may result in unexpected behavior.
+ * metric, attribute). Thus, any object-specific matchers are mostly unsuited
+ * for this purpose and, if used, may result in unexpected behavior.
  *
  * Returns:
  *  - 1 if the object matches
@@ -451,7 +453,8 @@ sdb_store_scan(sdb_store_matcher_t *m, sdb_store_matcher_t *filter,
 enum {
        SDB_SKIP_ATTRIBUTES         = 1 << 0,
        SDB_SKIP_SERVICES           = 1 << 1,
-       SDB_SKIP_SERVICE_ATTRIBUTES = 1 << 2,
+       SDB_SKIP_METRICS            = 1 << 2,
+       SDB_SKIP_SERVICE_ATTRIBUTES = 1 << 3,
 
        SDB_SKIP_ALL                = 0xffff,
 };
index defa6fcfc45d9aaeb021e3ddffdfe9cadd2dc147..fb2c24bf20d596450c36f67e5b7791a96c2b5122 100644 (file)
@@ -359,10 +359,12 @@ START_TEST(test_store_tojson)
                                                        "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                                        "\"update_interval\": \"0s\", \"backends\": []}"
                                        "], "
+                                       "\"metrics\": [], "
                                        "\"services\": []},"
                                "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": [], "
                                        "\"attributes\": [], "
+                                       "\"metrics\": [], "
                                        "\"services\": ["
                                                "{\"name\": \"s1\", "
                                                        "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
@@ -395,18 +397,59 @@ START_TEST(test_store_tojson)
                                                "{\"name\": \"k3\", \"value\": \"v3\", "
                                                        "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                                        "\"update_interval\": \"0s\", \"backends\": []}"
-                                       "]},"
+                                       "], "
+                                       "\"metrics\": []},"
                                "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": [], "
-                                       "\"attributes\": []}"
+                                       "\"attributes\": [], "
+                                       "\"metrics\": []}"
+                       "]}" },
+               { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_METRICS,
+                       "{\"hosts\":["
+                               "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                       "\"update_interval\": \"0s\", \"backends\": [], "
+                                       "\"attributes\": ["
+                                               "{\"name\": \"k1\", \"value\": \"v1\", "
+                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                       "\"update_interval\": \"0s\", \"backends\": []},"
+                                               "{\"name\": \"k2\", \"value\": \"v2\", "
+                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                       "\"update_interval\": \"0s\", \"backends\": []},"
+                                               "{\"name\": \"k3\", \"value\": \"v3\", "
+                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                       "\"update_interval\": \"0s\", \"backends\": []}"
+                                       "], "
+                                       "\"services\": []},"
+                               "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                       "\"update_interval\": \"0s\", \"backends\": [], "
+                                       "\"attributes\": [], "
+                                       "\"services\": ["
+                                               "{\"name\": \"s1\", "
+                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                       "\"update_interval\": \"0s\", \"backends\": [], "
+                                                       "\"attributes\": []},"
+                                               "{\"name\": \"s2\", "
+                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                       "\"update_interval\": \"0s\", \"backends\": [], "
+                                                       "\"attributes\": ["
+                                                               "{\"name\": \"k1\", \"value\": 123, "
+                                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                                       "\"update_interval\": \"0s\", \"backends\": []},"
+                                                               "{\"name\": \"k2\", \"value\": 4711, "
+                                                                       "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+                                                                       "\"update_interval\": \"0s\", \"backends\": []}"
+                                                       "]}"
+                                       "]}"
                        "]}" },
                { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ATTRIBUTES,
                        "{\"hosts\":["
                                "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": [], "
+                                       "\"metrics\": [], "
                                        "\"services\": []},"
                                "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": [], "
+                                       "\"metrics\": [], "
                                        "\"services\": ["
                                                "{\"name\": \"s1\", "
                                                        "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
@@ -416,7 +459,7 @@ START_TEST(test_store_tojson)
                                                        "\"update_interval\": \"0s\", \"backends\": []}"
                                        "]}"
                        "]}" },
-               { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES | SDB_SKIP_ATTRIBUTES,
+               { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ALL,
                        "{\"hosts\":["
                                "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": []},"
@@ -429,6 +472,7 @@ START_TEST(test_store_tojson)
                                "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": [], "
                                        "\"attributes\": [], "
+                                       "\"metrics\": [], "
                                        "\"services\": ["
                                                "{\"name\": \"s2\", "
                                                        "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
@@ -450,6 +494,7 @@ START_TEST(test_store_tojson)
                                                        "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                                        "\"update_interval\": \"0s\", \"backends\": []},"
                                        "], "
+                                       "\"metrics\": [], "
                                        "\"services\": []}"
                        "]}" },
                { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
@@ -458,6 +503,7 @@ START_TEST(test_store_tojson)
                                "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
                                        "\"update_interval\": \"0s\", \"backends\": [], "
                                        "\"attributes\": [], "
+                                       "\"metrics\": [], "
                                        "\"services\": []}"
                        "]}" },
        };
@@ -468,6 +514,7 @@ START_TEST(test_store_tojson)
 
        for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
                sdb_store_matcher_t *filter = NULL;
+               char filter_str[1024];
                int status;
 
                sdb_strbuf_clear(buf);
@@ -489,10 +536,13 @@ START_TEST(test_store_tojson)
                                        "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
                }
 
+               if (sdb_store_matcher_tostring(filter, filter_str, sizeof(filter_str)))
+                       snprintf(filter_str, sizeof(filter_str), "ERR");
+
                status = sdb_store_tojson(buf, filter, golden_data[i].flags);
                fail_unless(status == 0,
-                               "sdb_store_tojson(%x) = %d; expected: 0",
-                               golden_data[i].flags, status);
+                               "sdb_store_tojson(<buf>, %s, %x) = %d; expected: 0",
+                               filter_str, golden_data[i].flags, status);
 
                verify_json_output(buf, golden_data[i].expected, golden_data[i].flags);
                sdb_object_deref(SDB_OBJ(filter));