Code

store: Added sdb_store_iterate().
authorSebastian Harl <sh@tokkee.org>
Tue, 1 Apr 2014 19:34:23 +0000 (21:34 +0200)
committerSebastian Harl <sh@tokkee.org>
Tue, 1 Apr 2014 19:34:23 +0000 (21:34 +0200)
This function iterates over all (host, for now) objects in the store and calls
a user-specified callback for each.

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

index 47ba0356933453d4aa0c061daf23a6d3ad4a727c..b2fb0f602837f62128e09c849b00dde84f1389c0 100644 (file)
@@ -525,7 +525,6 @@ sdb_store_host_tojson(sdb_store_base_t *h, sdb_strbuf_t *buf, int flags)
        return 0;
 } /* sdb_store_host_tojson */
 
-/* TODO: actually support hierarchical data */
 int
 sdb_store_tojson(sdb_strbuf_t *buf, int flags)
 {
@@ -562,5 +561,34 @@ sdb_store_tojson(sdb_strbuf_t *buf, int flags)
        return 0;
 } /* sdb_store_tojson */
 
+/* TODO: actually support hierarchical data */
+int
+sdb_store_iterate(sdb_store_iter_cb cb, void *user_data)
+{
+       sdb_llist_iter_t *host_iter;
+       int status = 0;
+
+       pthread_rwlock_rdlock(&obj_lock);
+
+       host_iter = sdb_llist_get_iter(obj_list);
+       if (! host_iter)
+               status = -1;
+
+       /* has_next returns false if the iterator is NULL */
+       while (sdb_llist_iter_has_next(host_iter)) {
+               sdb_store_base_t *host = STORE_BASE(sdb_llist_iter_get_next(host_iter));
+               assert(host);
+
+               if (cb(host, user_data)) {
+                       status = -1;
+                       break;
+               }
+       }
+
+       sdb_llist_iter_destroy(host_iter);
+       pthread_rwlock_unlock(&obj_lock);
+       return status;
+} /* sdb_store_iterate */
+
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */
 
index 80975087227882a4810fbc9790a15c017b2ba2db..a149b1d714d3b245c36fad7c626d5dd40d564653 100644 (file)
@@ -230,6 +230,24 @@ sdb_store_tojson(sdb_strbuf_t *buf, int flags);
 int
 sdb_store_host_tojson(sdb_store_base_t *host, sdb_strbuf_t *buf, int flags);
 
+/*
+ * sdb_store_iter_cb:
+ * Store iterator callback. Iteration stops if the callback returns non-zero.
+ */
+typedef int (*sdb_store_iter_cb)(sdb_store_base_t *obj, void *user_data);
+
+/*
+ * sdb_store_iterate:
+ * Iterate the entire store, calling the specified callback for each object.
+ * The user_data pointer is passed on to each call of the callback.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a negative value else
+ */
+int
+sdb_store_iterate(sdb_store_iter_cb cb, void *user_data);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 8d484b671efb7b48e436a09907c7f0d6602d8a27..d0ef5a910cbc7e5c15c32fb93ff58d8b85ee5bce 100644 (file)
 #include <check.h>
 #include <string.h>
 
+static void
+populate(void)
+{
+       sdb_data_t datum;
+
+       sdb_store_host("h1", 1);
+       sdb_store_host("h2", 1);
+
+       datum.type = SDB_TYPE_STRING;
+       datum.data.string = "v1";
+       sdb_store_attribute("h1", "k1", &datum, 1);
+       datum.data.string = "v2";
+       sdb_store_attribute("h1", "k2", &datum, 1);
+       datum.data.string = "v3";
+       sdb_store_attribute("h1", "k3", &datum, 1);
+
+       sdb_store_service("h2", "s1", 1);
+       sdb_store_service("h2", "s2", 1);
+} /* populate */
+
 START_TEST(test_store_host)
 {
        struct {
@@ -249,7 +269,6 @@ verify_json_output(sdb_strbuf_t *buf, const char *expected, int flags)
 START_TEST(test_store_tojson)
 {
        sdb_strbuf_t *buf;
-       sdb_data_t datum;
        size_t i;
 
        struct {
@@ -299,21 +318,9 @@ START_TEST(test_store_tojson)
                        "]}" },
        };
 
-       sdb_store_host("h1", 1);
-       sdb_store_host("h2", 1);
-
-       datum.type = SDB_TYPE_STRING;
-       datum.data.string = "v1";
-       sdb_store_attribute("h1", "k1", &datum, 1);
-       datum.data.string = "v2";
-       sdb_store_attribute("h1", "k2", &datum, 1);
-       datum.data.string = "v3";
-       sdb_store_attribute("h1", "k3", &datum, 1);
-
-       sdb_store_service("h2", "s1", 1);
-       sdb_store_service("h2", "s2", 1);
-
        buf = sdb_strbuf_create(0);
+       fail_unless(buf != NULL, "INTERNAL ERROR: failed to create string buffer");
+       populate();
 
        for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
                int status;
@@ -331,6 +338,68 @@ START_TEST(test_store_tojson)
 }
 END_TEST
 
+static int
+iter_incr(sdb_store_base_t *obj, void *user_data)
+{
+       intptr_t *i = user_data;
+
+       fail_unless(obj != NULL,
+                       "sdb_store_iterate callback received NULL obj; expected: "
+                       "<store base obj>");
+       fail_unless(i != NULL,
+                       "sdb_store_iterate callback received NULL user_data; "
+                       "expected: <pointer to data>");
+
+       ++(*i);
+       return 0;
+} /* iter_incr */
+
+static int
+iter_error(sdb_store_base_t *obj, void *user_data)
+{
+       intptr_t *i = user_data;
+
+       fail_unless(obj != NULL,
+                       "sdb_store_iterate callback received NULL obj; expected: "
+                       "<store base obj>");
+       fail_unless(i != NULL,
+                       "sdb_store_iterate callback received NULL user_data; "
+                       "expected: <pointer to data>");
+
+       ++(*i);
+       return -1;
+} /* iter_error */
+
+START_TEST(test_iterate)
+{
+       intptr_t i = 0;
+       int check;
+
+       /* empty store */
+       check = sdb_store_iterate(iter_incr, &i);
+       fail_unless(check == -1,
+                       "sdb_store_iterate(), empty store = %d; expected: -1", check);
+       fail_unless(i == 0,
+                       "sdb_store_iterate called callback %d times; expected: 0", (int)i);
+
+       populate();
+
+       check = sdb_store_iterate(iter_incr, &i);
+       fail_unless(check == 0,
+                       "sdb_store_iterate() = %d; expected: 0", check);
+       fail_unless(i == 2,
+                       "sdb_store_iterate called callback %d times; expected: 1", (int)i);
+
+       i = 0;
+       check = sdb_store_iterate(iter_error, &i);
+       fail_unless(check == -1,
+                       "sdb_store_iterate(), error callback = %d; expected: -1", check);
+       fail_unless(i == 1,
+                       "sdb_store_iterate called callback %d times "
+                       "(callback returned error); expected: 1", (int)i);
+}
+END_TEST
+
 Suite *
 core_store_suite(void)
 {
@@ -343,6 +412,7 @@ core_store_suite(void)
        tcase_add_test(tc, test_store_get_host);
        tcase_add_test(tc, test_store_attr);
        tcase_add_test(tc, test_store_service);
+       tcase_add_test(tc, test_iterate);
        tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);
        suite_add_tcase(s, tc);