Code

store: Let sdb_store_scan() support other object types besides hosts.
authorSebastian Harl <sh@tokkee.org>
Tue, 28 Oct 2014 17:17:35 +0000 (18:17 +0100)
committerSebastian Harl <sh@tokkee.org>
Tue, 28 Oct 2014 17:17:35 +0000 (18:17 +0100)
src/core/store.c
src/frontend/query.c
src/include/core/store.h
t/unit/core/store_lookup_test.c
t/unit/core/store_test.c

index 6f525c31462ed74e0d4256b889373cdcc38b4ee7..74cbea2703bdd727aca9011de1861a29b587d58f 100644 (file)
@@ -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);
index d6bd76a95ebb3c23ba06c291f324215233801ff2..15e81b8f06613fcf6deb469ea92fe3d376df49d2 100644 (file)
@@ -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);
index 76995d40a11452c8bc46881349a323eab88f33ab..3c2231c31bcb0c488d782805f390f1e1866cd0f1 100644 (file)
@@ -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);
 
 /*
index 8d1508641d1a59515f67f8ec516900483f44d970..c32005393a90cb730ad9204696bc8978fb0490e7 100644 (file)
@@ -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));
        }
index ecbb39d93b601ebe4f2da1891f4779d379bbf368..d132508537a76789ca3e9effe2240473ff8f5e88 100644 (file)
@@ -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