From dd74510898e5a480fc18a1acad7aa4196f732efe Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sat, 16 Aug 2014 12:08:16 +0200 Subject: [PATCH] store: Store "data-store" information alongside metrics. A metric data-store describes how to access data (e.g. time-series) of a metric. --- src/core/store-private.h | 4 +++ src/core/store.c | 44 +++++++++++++++++++++++++++++-- src/include/core/store.h | 12 ++++++++- t/integration/mock_plugin.c | 28 +++++++++++++------- t/unit/core/store_lookup_test.c | 4 +-- t/unit/core/store_test.c | 46 +++++++++++++++++++++------------ 6 files changed, 108 insertions(+), 30 deletions(-) diff --git a/src/core/store-private.h b/src/core/store-private.h index 3c23ebb..6dc68c0 100644 --- a/src/core/store-private.h +++ b/src/core/store-private.h @@ -82,6 +82,10 @@ typedef struct { sdb_store_obj_t super; sdb_avltree_t *attributes; + struct { + char *type; + char *id; + } store; } sdb_metric_t; #define METRIC(obj) ((sdb_metric_t *)(obj)) diff --git a/src/core/store.c b/src/core/store.c index 44e696c..2565eca 100644 --- a/src/core/store.c +++ b/src/core/store.c @@ -174,6 +174,8 @@ sdb_metric_init(sdb_object_t *obj, va_list ap) sobj->attributes = sdb_avltree_create(); if (! sobj->attributes) return -1; + + sobj->store.type = sobj->store.id = NULL; return 0; } /* sdb_metric_init */ @@ -187,6 +189,11 @@ sdb_metric_destroy(sdb_object_t *obj) if (sobj->attributes) sdb_avltree_destroy(sobj->attributes); + + if (sobj->store.type) + free(sobj->store.type); + if (sobj->store.id) + free(sobj->store.id); } /* sdb_metric_destroy */ static int @@ -678,14 +685,19 @@ sdb_store_service_attr(const char *hostname, const char *service, int sdb_store_metric(const char *hostname, const char *name, - sdb_time_t last_update) + sdb_metric_store_t *store, sdb_time_t last_update) { + sdb_store_obj_t *obj = NULL; + sdb_metric_t *metric; + sdb_avltree_t *metrics; int status = 0; if ((! hostname) || (! name)) return -1; + if (store && ((! store->type) || (! store->id))) + return -1; pthread_rwlock_wrlock(&host_lock); metrics = get_host_children(hostname, SDB_METRIC); @@ -696,7 +708,35 @@ sdb_store_metric(const char *hostname, const char *name, } if (! status) - status = store_obj(metrics, SDB_METRIC, name, last_update, NULL); + status = store_obj(metrics, SDB_METRIC, name, last_update, &obj); + + if (status || (! store)) { + pthread_rwlock_unlock(&host_lock); + return status; + } + + assert(obj); + metric = METRIC(obj); + + if ((! metric->store.type) || strcasecmp(metric->store.type, store->type)) { + if (metric->store.type) + free(metric->store.type); + metric->store.type = strdup(store->type); + } + if ((! metric->store.id) || strcasecmp(metric->store.id, store->id)) { + if (metric->store.id) + free(metric->store.id); + metric->store.id = strdup(store->id); + } + + if ((! metric->store.type) || (! metric->store.id)) { + if (metric->store.type) + free(metric->store.type); + if (metric->store.id) + free(metric->store.id); + metric->store.type = metric->store.id = NULL; + status = -1; + } pthread_rwlock_unlock(&host_lock); return status; } /* sdb_store_metric */ diff --git a/src/include/core/store.h b/src/include/core/store.h index 169d112..2d3d707 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -174,6 +174,14 @@ int sdb_store_service_attr(const char *hostname, const char *service, const char *key, const sdb_data_t *value, sdb_time_t last_update); +/* + * A metric store describes how to access a metric's data. + */ +typedef struct { + const char *type; + const char *id; +} sdb_metric_store_t; + /* * sdb_store_metric: * Add/update a metric in the store. If the metric, identified by its name, @@ -183,6 +191,8 @@ sdb_store_service_attr(const char *hostname, const char *service, * memory required for storing the entry will be allocated an managed by the * store itself. * + * If specified, the metric store describes where to access the metric's data. + * * Returns: * - 0 on success * - a positive value if the new entry is older than the currently stored @@ -191,7 +201,7 @@ sdb_store_service_attr(const char *hostname, const char *service, */ int sdb_store_metric(const char *hostname, const char *name, - sdb_time_t last_update); + sdb_metric_store_t *store, sdb_time_t last_update); /* * sdb_store_metric_attr: diff --git a/t/integration/mock_plugin.c b/t/integration/mock_plugin.c index 8c16194..1fb59fc 100644 --- a/t/integration/mock_plugin.c +++ b/t/integration/mock_plugin.c @@ -54,15 +54,24 @@ static const char *hostnames[] = { static struct { const char *hostname; const char *metric; + sdb_metric_store_t store; } metrics[] = { - { "some.host.name", "foo/bar/qux" }, - { "some.host.name", "foo/bar/baz" }, - { "some.host.name", "foo2/bar/qux" }, - { "some.host.name", "foo2/bar/baz" }, - { "other.host.name", "foo/bar/qux" }, - { "other.host.name", "foo/bar/baz" }, - { "other.host.name", "foo2/bar/qux" }, - { "other.host.name", "foo2/bar/baz" }, + { "some.host.name", "foo/bar/qux", + { "dummy", "/var/lib/collectd/rrd/foo/bar/qux.rrd" } }, + { "some.host.name", "foo/bar/baz", + { "dummy", "/var/lib/collectd/rrd/foo/bar/baz.rrd" } }, + { "some.host.name", "foo2/bar/qux", + { "dummy", "/var/lib/collectd/rrd/foo2/bar/qux.rrd" } }, + { "some.host.name", "foo2/bar/baz", + { "dummy", "/var/lib/collectd/rrd/foo2/bar/baz.rrd" } }, + { "other.host.name", "foo/bar/qux", + { "dummy", "/var/lib/collectd/rrd/foo/bar/qux.rrd" } }, + { "other.host.name", "foo/bar/baz", + { "dummy", "/var/lib/collectd/rrd/foo/bar/baz.rrd" } }, + { "other.host.name", "foo2/bar/qux", + { "dummy", "/var/lib/collectd/rrd/foo2/bar/qux.rrd" } }, + { "other.host.name", "foo2/bar/baz", + { "dummy", "/var/lib/collectd/rrd/foo2/bar/baz.rrd" } }, }; static struct { @@ -152,7 +161,8 @@ mock_collect(sdb_object_t *user_data) } for (i = 0; i < SDB_STATIC_ARRAY_LEN(metrics); ++i) { if ((check = sdb_store_metric(metrics[i].hostname, - metrics[i].metric, sdb_gettime()))) { + metrics[i].metric, &metrics[i].store, + sdb_gettime()))) { sdb_log(SDB_LOG_ERR, "mock::plugin: Failed to store metric: " "status %d", check); exit(1); diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index d1dc82f..b356fa0 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -77,9 +77,9 @@ populate(void) for (i = 0; i < SDB_STATIC_ARRAY_LEN(metrics); ++i) { int status = sdb_store_metric(metrics[i].host, - metrics[i].metric, 1); + metrics[i].metric, /* store */ NULL, 1); fail_unless(status == 0, - "sdb_store_metric(%s, %s, 1) = %d; expected: 0", + "sdb_store_metric(%s, %s, NULL, 1) = %d; expected: 0", metrics[i].host, metrics[i].metric, status); } diff --git a/t/unit/core/store_test.c b/t/unit/core/store_test.c index c056ac7..e8c77c7 100644 --- a/t/unit/core/store_test.c +++ b/t/unit/core/store_test.c @@ -53,8 +53,8 @@ populate(void) sdb_store_attribute("h1", "k2", &datum, 1); sdb_store_attribute("h1", "k3", &datum, 2); - sdb_store_metric("h1", "m1", 2); - sdb_store_metric("h1", "m2", 1); + sdb_store_metric("h1", "m1", /* store */ NULL, 2); + sdb_store_metric("h1", "m2", /* store */ NULL, 1); sdb_store_service("h2", "s1", 1); sdb_store_service("h2", "s2", 2); @@ -228,20 +228,32 @@ END_TEST START_TEST(test_store_metric) { + sdb_metric_store_t store1 = { "dummy-type1", "dummy-id1" }; + sdb_metric_store_t store2 = { "dummy-type2", "dummy-id2" }; + struct { const char *host; const char *metric; + sdb_metric_store_t *store; sdb_time_t last_update; int expected; } golden_data[] = { - { "k", "m", 1, -1 }, - { "k", "m", 1, -1 }, /* retry to ensure the host is not created */ - { "l", "m1", 1, 0 }, - { "l", "m1", 2, 0 }, - { "l", "m1", 2, 1 }, - { "l", "m2", 1, 0 }, - { "m", "m", 1, 0 }, - { "m", "m", 1, 1 }, + { "k", "m", NULL, 1, -1 }, + { "k", "m", NULL, 1, -1 }, /* retry to ensure the host is not created */ + { "k", "m", &store1, 1, -1 }, + { "l", "m1", NULL, 1, 0 }, + { "l", "m1", &store1, 2, 0 }, + { "l", "m1", &store1, 3, 0 }, + { "l", "m1", NULL, 3, 1 }, + { "l", "m2", &store1, 1, 0 }, + { "l", "m2", &store2, 2, 0 }, + { "l", "m2", NULL, 3, 0 }, + { "m", "m", &store1, 1, 0 }, + { "m", "m", NULL, 2, 0 }, + { "m", "m", NULL, 2, 1 }, + { "m", "m", &store1, 3, 0 }, + { "m", "m", &store2, 4, 0 }, + { "m", "m", NULL, 5, 0 }, }; size_t i; @@ -252,11 +264,13 @@ START_TEST(test_store_metric) int status; status = sdb_store_metric(golden_data[i].host, - golden_data[i].metric, golden_data[i].last_update); + golden_data[i].metric, golden_data[i].store, + golden_data[i].last_update); fail_unless(status == golden_data[i].expected, - "sdb_store_metric(%s, %s, %d) = %d; expected: %d", + "sdb_store_metric(%s, %s, %p, %d) = %d; expected: %d", golden_data[i].host, golden_data[i].metric, - golden_data[i].last_update, status, golden_data[i].expected); + golden_data[i].store, golden_data[i].last_update, + status, golden_data[i].expected); } } END_TEST @@ -290,9 +304,9 @@ START_TEST(test_store_metric_attr) sdb_store_host("m", 1); sdb_store_host("l", 1); - sdb_store_metric("m", "m1", 1); - sdb_store_metric("l", "m1", 1); - sdb_store_metric("l", "m2", 1); + sdb_store_metric("m", "m1", NULL, 1); + sdb_store_metric("l", "m1", NULL, 1); + sdb_store_metric("l", "m2", NULL, 1); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { int status; -- 2.30.2