From ebfd78eb79806777c3de889d75a62665ff78eaca Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 28 Oct 2014 18:17:35 +0100 Subject: [PATCH] store: Let sdb_store_scan() support other object types besides hosts. --- src/core/store.c | 38 ++++++++++++++++--- src/frontend/query.c | 2 +- src/include/core/store.h | 12 +++--- t/unit/core/store_lookup_test.c | 10 ++--- t/unit/core/store_test.c | 66 ++++++++++++++++++++++++++------- 5 files changed, 97 insertions(+), 31 deletions(-) diff --git a/src/core/store.c b/src/core/store.c index 6f525c3..74cbea2 100644 --- a/src/core/store.c +++ b/src/core/store.c @@ -1092,7 +1092,7 @@ sdb_store_tojson(sdb_strbuf_t *buf, sdb_store_matcher_t *filter, int flags) } /* sdb_store_tojson */ int -sdb_store_scan(sdb_store_matcher_t *m, sdb_store_matcher_t *filter, +sdb_store_scan(int type, sdb_store_matcher_t *m, sdb_store_matcher_t *filter, sdb_store_lookup_cb cb, void *user_data) { sdb_avltree_iter_t *host_iter; @@ -1101,6 +1101,9 @@ sdb_store_scan(sdb_store_matcher_t *m, sdb_store_matcher_t *filter, if (! cb) return -1; + if ((type != SDB_HOST) && (type != SDB_SERVICE) && (type != SDB_METRIC)) + return -1; + pthread_rwlock_rdlock(&host_lock); host_iter = sdb_avltree_get_iter(hosts); @@ -1110,16 +1113,41 @@ sdb_store_scan(sdb_store_matcher_t *m, sdb_store_matcher_t *filter, /* has_next returns false if the iterator is NULL */ while (sdb_avltree_iter_has_next(host_iter)) { sdb_store_obj_t *host; + sdb_avltree_iter_t *iter = NULL; host = STORE_OBJ(sdb_avltree_iter_get_next(host_iter)); assert(host); - if (sdb_store_matcher_matches(m, host, filter)) { - if (cb(host, user_data)) { - status = -1; - break; + if (! sdb_store_matcher_matches(filter, host, NULL)) + continue; + + if (type == SDB_SERVICE) + iter = sdb_avltree_get_iter(HOST(host)->services); + else if (type == SDB_METRIC) + iter = sdb_avltree_get_iter(HOST(host)->metrics); + + if (iter) { + while (sdb_avltree_iter_has_next(iter)) { + sdb_store_obj_t *obj; + obj = STORE_OBJ(sdb_avltree_iter_get_next(iter)); + assert(obj); + + if (sdb_store_matcher_matches(m, obj, filter)) { + if (cb(obj, user_data)) { + status = -1; + break; + } + } } } + else if (sdb_store_matcher_matches(m, host, filter)) { + if (cb(host, user_data)) + status = -1; + } + + sdb_avltree_iter_destroy(iter); + if (status) + break; } sdb_avltree_iter_destroy(host_iter); diff --git a/src/frontend/query.c b/src/frontend/query.c index d6bd76a..15e81b8 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -413,7 +413,7 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, int type, * we'd have to filter twice -- once in the scanner and then again in the * serializer. */ data.last_len = sdb_strbuf_len(data.buf); - if (sdb_store_scan(m, /* filter */ NULL, lookup_tojson, &data)) { + if (sdb_store_scan(SDB_HOST, m, /* filter */ NULL, lookup_tojson, &data)) { sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup hosts"); sdb_strbuf_sprintf(conn->errbuf, "Failed to lookup hosts"); sdb_strbuf_destroy(data.buf); diff --git a/src/include/core/store.h b/src/include/core/store.h index 76995d4..3c2231c 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -546,18 +546,18 @@ typedef int (*sdb_store_lookup_cb)(sdb_store_obj_t *obj, void *user_data); /* * sdb_store_scan: - * Look up objects in the store. The specified callback function is called for - * each object in the store matching 'm'. The function performs a full scan of - * all hosts stored in the database. If specified, the filter will be used to - * preselect objects for further evaluation. See the description of - * 'sdb_store_matcher_matches' for details. + * Look up objects of the specified type in the store. The specified callback + * function is called for each object in the store matching 'm'. The function + * performs a full scan of all objects stored in the database. If specified, + * the filter will be used to preselect objects for further evaluation. See + * the description of 'sdb_store_matcher_matches' for details. * * Returns: * - 0 on success * - a negative value else */ int -sdb_store_scan(sdb_store_matcher_t *m, sdb_store_matcher_t *filter, +sdb_store_scan(int type, sdb_store_matcher_t *m, sdb_store_matcher_t *filter, sdb_store_lookup_cb cb, void *user_data); /* diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index 8d15086..c320053 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -587,7 +587,7 @@ START_TEST(test_scan) size_t i; n = 0; - check = sdb_store_scan(/* matcher */ NULL, /* filter */ NULL, + check = sdb_store_scan(SDB_HOST, /* matcher */ NULL, /* filter */ NULL, scan_cb, &n); fail_unless(check == 0, "sdb_store_scan() = %d; expected: 0", check); @@ -610,11 +610,11 @@ START_TEST(test_scan) } n = 0; - sdb_store_scan(m, filter, scan_cb, &n); + sdb_store_scan(SDB_HOST, m, filter, scan_cb, &n); fail_unless(n == golden_data[i].expected, - "sdb_store_scan(matcher{%s}, filter{%s}) found %d hosts; " - "expected: %d", golden_data[i].query, golden_data[i].filter, - n, golden_data[i].expected); + "sdb_store_scan(HOST, matcher{%s}, filter{%s}) " + "found %d hosts; expected: %d", golden_data[i].query, + golden_data[i].filter, n, golden_data[i].expected); sdb_object_deref(SDB_OBJ(filter)); sdb_object_deref(SDB_OBJ(m)); } diff --git a/t/unit/core/store_test.c b/t/unit/core/store_test.c index ecbb39d..d132508 100644 --- a/t/unit/core/store_test.c +++ b/t/unit/core/store_test.c @@ -55,6 +55,7 @@ populate(void) sdb_store_metric("h1", "m1", /* store */ NULL, 2); sdb_store_metric("h1", "m2", /* store */ NULL, 1); + sdb_store_metric("h2", "m1", /* store */ NULL, 1); sdb_store_service("h2", "s1", 1); sdb_store_service("h2", "s2", 2); @@ -483,7 +484,12 @@ START_TEST(test_store_tojson) "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " "\"update_interval\": \"0s\", \"backends\": [], " "\"attributes\": [], " - "\"metrics\": [], " + "\"metrics\": [" + "{\"name\": \"m1\", " + "\"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\", " @@ -534,7 +540,12 @@ START_TEST(test_store_tojson) "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " "\"update_interval\": \"0s\", \"backends\": [], " "\"attributes\": [], " - "\"metrics\": []}" + "\"metrics\": [" + "{\"name\": \"m1\", " + "\"last_update\": \"1970-01-01 00:00:00 +0000\", " + "\"update_interval\": \"0s\", \"backends\": [], " + "\"attributes\": []}" + "]}" "]" }, { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_METRICS, "[" @@ -588,7 +599,11 @@ START_TEST(test_store_tojson) "\"services\": []}," "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", " "\"update_interval\": \"0s\", \"backends\": [], " - "\"metrics\": [], " + "\"metrics\": [" + "{\"name\": \"m1\", " + "\"last_update\": \"1970-01-01 00:00:00 +0000\", " + "\"update_interval\": \"0s\", \"backends\": []}" + "], " "\"services\": [" "{\"name\": \"s1\", " "\"last_update\": \"1970-01-01 00:00:00 +0000\", " @@ -852,7 +867,7 @@ START_TEST(test_interval) END_TEST static int -scan_incr(sdb_store_obj_t *obj, void *user_data) +scan_count(sdb_store_obj_t *obj, void *user_data) { intptr_t *i = user_data; @@ -865,7 +880,7 @@ scan_incr(sdb_store_obj_t *obj, void *user_data) ++(*i); return 0; -} /* scan_incr */ +} /* scan_count */ static int scan_error(sdb_store_obj_t *obj, void *user_data) @@ -889,27 +904,50 @@ START_TEST(test_scan) int check; /* empty store */ - check = sdb_store_scan(/* m, filter = */ NULL, NULL, scan_incr, &i); + check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL, + scan_count, &i); fail_unless(check == -1, - "sdb_store_scan(), empty store = %d; expected: -1", check); + "sdb_store_scan(HOST), empty store = %d; expected: -1", check); fail_unless(i == 0, - "sdb_store_scan called callback %d times; expected: 0", (int)i); + "sdb_store_scan(HOST) called callback %d times; " + "expected: 0", (int)i); populate(); - check = sdb_store_scan(/* m, filter = */ NULL, NULL, scan_incr, &i); + check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL, + scan_count, &i); fail_unless(check == 0, - "sdb_store_scan() = %d; expected: 0", check); + "sdb_store_scan(HOST) = %d; expected: 0", check); fail_unless(i == 2, - "sdb_store_scan called callback %d times; expected: 1", (int)i); + "sdb_store_scan(HOST) called callback %d times; " + "expected: 1", (int)i); i = 0; - check = sdb_store_scan(/* m, filter = */ NULL, NULL, scan_error, &i); + check = sdb_store_scan(SDB_HOST, /* m, filter = */ NULL, NULL, + scan_error, &i); fail_unless(check == -1, - "sdb_store_scan(), error callback = %d; expected: -1", check); + "sdb_store_scan(HOST), error callback = %d; expected: -1", check); fail_unless(i == 1, - "sdb_store_scan called callback %d times " + "sdb_store_scan(HOST) called callback %d times " "(callback returned error); expected: 1", (int)i); + + i = 0; + check = sdb_store_scan(SDB_SERVICE, /* m, filter = */ NULL, NULL, + scan_count, &i); + fail_unless(check == 0, + "sdb_store_scan(SERVICE) = %d; expected: 0", check); + fail_unless(i == 2, + "sdb_store_scan(SERVICE) called callback %d times; " + "expected: 2", (int)i); + + i = 0; + check = sdb_store_scan(SDB_METRIC, /* m, filter = */ NULL, NULL, + scan_count, &i); + fail_unless(check == 0, + "sdb_store_scan(METRIC) = %d; expected: 0", check); + fail_unless(i == 3, + "sdb_store_scan(METRIC) called callback %d times; " + "expected: 3", (int)i); } END_TEST -- 2.30.2