Code

store: Provide more verbose messages on errors during scanning.
[sysdb.git] / src / core / store.c
index db8a9d9c5686f7e7c79059fd383c6014ad5329bf..6befce7e5acd8933a3f054336974f8bf32229733 100644 (file)
@@ -919,8 +919,13 @@ sdb_store_get_field(sdb_store_obj_t *obj, int field, sdb_data_t *res)
                        tmp.data.datetime = obj->interval;
                        break;
                case SDB_FIELD_BACKEND:
-                       /* TODO: add support for storing array values in a data object
-                        * for now, fall thru to the error case */
+               {
+                       tmp.type = SDB_TYPE_ARRAY | SDB_TYPE_STRING;
+                       tmp.data.array.length = obj->backends_num;
+                       tmp.data.array.values = obj->backends;
+                       return sdb_data_copy(res, &tmp);
+                       break;
+               }
                default:
                        return -1;
        }
@@ -932,10 +937,11 @@ sdb_store_get_field(sdb_store_obj_t *obj, int field, sdb_data_t *res)
 } /* sdb_store_get_field */
 
 int
-sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res)
+sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res,
+               sdb_store_matcher_t *filter)
 {
        sdb_avltree_t *tree = NULL;
-       sdb_avltree_iter_t *iter = NULL;
+       sdb_store_obj_t *attr;
 
        if ((! obj) || (! name))
                return -1;
@@ -950,23 +956,19 @@ sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res)
        if (! tree)
                return -1;
 
-       iter = sdb_avltree_get_iter(tree);
-       while (sdb_avltree_iter_has_next(iter)) {
-               sdb_object_t *attr = sdb_avltree_iter_get_next(iter);
-
-               if (strcasecmp(SDB_OBJ(attr)->name, name))
-                       continue;
-
-               assert(STORE_OBJ(attr)->type == SDB_ATTRIBUTE);
-               if (res)
-                       sdb_data_copy(res, &ATTR(attr)->value);
-               sdb_avltree_iter_destroy(iter);
-               return 0;
+       attr = STORE_OBJ(sdb_avltree_lookup(tree, name));
+       if (! attr)
+               return -1;
+       if (filter && (! sdb_store_matcher_matches(filter, attr, NULL))) {
+               sdb_object_deref(SDB_OBJ(attr));
+               return -1;
        }
-       sdb_avltree_iter_destroy(iter);
 
-       /* not found */
-       return -1;
+       assert(STORE_OBJ(attr)->type == SDB_ATTRIBUTE);
+       if (res)
+               sdb_data_copy(res, &ATTR(attr)->value);
+       sdb_object_deref(SDB_OBJ(attr));
+       return 0;
 } /* sdb_store_get_attr */
 
 int
@@ -1081,13 +1083,21 @@ sdb_store_tojson(sdb_strbuf_t *buf, sdb_store_matcher_t *filter, 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_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;
        int status = 0;
 
+       if (! cb)
+               return -1;
+
+       if ((type != SDB_HOST) && (type != SDB_SERVICE) && (type != SDB_METRIC)) {
+               sdb_log(SDB_LOG_ERR, "store: Cannot scan objects of type %d", type);
+               return -1;
+       }
+
        pthread_rwlock_rdlock(&host_lock);
 
        host_iter = sdb_avltree_get_iter(hosts);
@@ -1097,20 +1107,52 @@ sdb_store_iterate(sdb_store_iter_cb cb, void *user_data)
        /* 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 (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, filter, user_data)) {
+                                               sdb_log(SDB_LOG_ERR, "store: Callback returned "
+                                                               "an error while scanning");
+                                               status = -1;
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               else if (sdb_store_matcher_matches(m, host, filter)) {
+                       if (cb(host, filter, user_data)) {
+                               sdb_log(SDB_LOG_ERR, "store: Callback returned "
+                                               "an error while scanning");
+                               status = -1;
+                       }
                }
+
+               sdb_avltree_iter_destroy(iter);
+               if (status)
+                       break;
        }
 
        sdb_avltree_iter_destroy(host_iter);
        pthread_rwlock_unlock(&host_lock);
        return status;
-} /* sdb_store_iterate */
+} /* sdb_store_scan */
 
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */