From 98439daa576d4dbc533e9d4b8a5f493926389554 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Wed, 7 Oct 2015 23:45:51 +0200 Subject: [PATCH] Split the memstore module from the store module. --- src/Makefile.am | 16 +- .../{store-private.h => memstore-private.h} | 11 +- src/core/{store.c => memstore.c} | 157 ++++- src/core/{store_exec.c => memstore_exec.c} | 14 +- src/core/{store_expr.c => memstore_expr.c} | 19 +- .../{store_lookup.c => memstore_lookup.c} | 16 +- src/core/{store_query.c => memstore_query.c} | 22 +- src/core/store_json.c | 129 +---- src/include/core/memstore.h | 535 ++++++++++++++++++ src/include/core/store.h | 495 +--------------- src/plugins/store/memory.c | 1 + t/unit/core/store_expr_test.c | 2 +- t/unit/core/store_json_test.c | 1 + t/unit/core/store_lookup_test.c | 2 +- t/unit/core/store_test.c | 2 +- t/unit/frontend/query_test.c | 1 + t/unit/parser/parser_test.c | 4 +- 17 files changed, 738 insertions(+), 689 deletions(-) rename src/core/{store-private.h => memstore-private.h} (96%) rename src/core/{store.c => memstore.c} (86%) rename src/core/{store_exec.c => memstore_exec.c} (94%) rename src/core/{store_expr.c => memstore_expr.c} (95%) rename src/core/{store_lookup.c => memstore_lookup.c} (97%) rename src/core/{store_query.c => memstore_query.c} (92%) create mode 100644 src/include/core/memstore.h diff --git a/src/Makefile.am b/src/Makefile.am index f3bcae1..886cc1a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,16 +72,16 @@ libsysdb_fe_parser_la_CFLAGS = @COVERAGE_CFLAGS@ @PROFILING_CFLAGS@ \ -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\"" libsysdb_la_SOURCES = \ sysdb.c include/sysdb.h \ + core/data.c include/core/data.h \ + core/memstore.c include/core/memstore.h \ + core/memstore-private.h \ + core/memstore_exec.c \ + core/memstore_expr.c \ + core/memstore_lookup.c \ + core/memstore_query.c \ core/object.c include/core/object.h \ core/plugin.c include/core/plugin.h \ - core/store.c include/core/store.h \ - core/store-private.h \ - core/store_exec.c \ - core/store_expr.c \ - core/store_json.c \ - core/store_lookup.c \ - core/store_query.c \ - core/data.c include/core/data.h \ + core/store_json.c include/core/store.h \ core/time.c include/core/time.h \ core/timeseries.c include/core/timeseries.h \ frontend/connection.c include/frontend/connection.h \ diff --git a/src/core/store-private.h b/src/core/memstore-private.h similarity index 96% rename from src/core/store-private.h rename to src/core/memstore-private.h index 2f9d96c..cd0152d 100644 --- a/src/core/store-private.h +++ b/src/core/memstore-private.h @@ -1,5 +1,5 @@ /* - * SysDB - src/core/store-private.h + * SysDB - src/core/memstore-private.h * Copyright (C) 2012-2013 Sebastian 'tokkee' Harl * All rights reserved. * @@ -29,9 +29,10 @@ * private data structures used by the memstore module */ -#ifndef SDB_CORE_STORE_PRIVATE_H -#define SDB_CORE_STORE_PRIVATE_H 1 +#ifndef SDB_CORE_MEMSTORE_PRIVATE_H +#define SDB_CORE_MEMSTORE_PRIVATE_H 1 +#include "core/memstore.h" #include "core/store.h" #include "utils/avltree.h" @@ -153,7 +154,7 @@ struct sdb_memstore_expr { */ /* when adding to this, also update 'MATCHER_SYM' below and 'matchers' in - * store_lookup.c */ + * memstore_lookup.c */ enum { MATCHER_OR, MATCHER_AND, @@ -257,7 +258,7 @@ typedef struct { } /* extern "C" */ #endif -#endif /* ! SDB_CORE_STORE_H */ +#endif /* ! SDB_CORE_MEMSTORE_H */ /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/core/store.c b/src/core/memstore.c similarity index 86% rename from src/core/store.c rename to src/core/memstore.c index 7fc11e1..d886a1f 100644 --- a/src/core/store.c +++ b/src/core/memstore.c @@ -1,5 +1,5 @@ /* - * SysDB - src/core/store.c + * SysDB - src/core/memstore.c * Copyright (C) 2012-2013 Sebastian 'tokkee' Harl * All rights reserved. * @@ -30,7 +30,7 @@ #endif /* HAVE_CONFIG_H */ #include "sysdb.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "core/plugin.h" #include "utils/avltree.h" #include "utils/error.h" @@ -84,7 +84,7 @@ store_init(sdb_object_t *obj, va_list __attribute__((unused)) ap) if ((err = pthread_rwlock_init(&SDB_MEMSTORE(obj)->host_lock, /* attr = */ NULL))) { char errbuf[128]; - sdb_log(SDB_LOG_ERR, "store: Failed to initialize lock: %s", + sdb_log(SDB_LOG_ERR, "memstore: Failed to initialize lock: %s", sdb_strerror(err, errbuf, sizeof(errbuf))); return -1; } @@ -97,7 +97,7 @@ store_destroy(sdb_object_t *obj) int err; if ((err = pthread_rwlock_destroy(&SDB_MEMSTORE(obj)->host_lock))) { char errbuf[128]; - sdb_log(SDB_LOG_ERR, "store: Failed to destroy lock: %s", + sdb_log(SDB_LOG_ERR, "memstore: Failed to destroy lock: %s", sdb_strerror(err, errbuf, sizeof(errbuf))); return; } @@ -353,7 +353,7 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) old = STORE_OBJ(sdb_avltree_lookup(obj->parent_tree, obj->name)); if (old) { if (old->last_update > obj->last_update) { - sdb_log(SDB_LOG_DEBUG, "store: Cannot update %s '%s' - " + sdb_log(SDB_LOG_DEBUG, "memstore: Cannot update %s '%s' - " "value too old (%"PRIsdbTIME" < %"PRIsdbTIME")", SDB_STORE_TYPE_TO_NAME(obj->type), obj->name, obj->last_update, old->last_update); @@ -406,7 +406,7 @@ store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) } else { char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "store: Failed to create %s '%s': %s", + sdb_log(SDB_LOG_ERR, "memstore: Failed to create %s '%s': %s", SDB_STORE_TYPE_TO_NAME(obj->type), obj->name, sdb_strerror(errno, errbuf, sizeof(errbuf))); status = -1; @@ -511,7 +511,7 @@ store_attribute(sdb_store_attribute_t *attr, sdb_object_t *user_data) pthread_rwlock_wrlock(&st->host_lock); host = HOST(sdb_avltree_lookup(st->hosts, hostname)); if (! host) { - sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' - " + sdb_log(SDB_LOG_ERR, "memstore: Failed to store attribute '%s' - " "host '%s' not found", attr->key, hostname); status = -1; } @@ -535,7 +535,7 @@ store_attribute(sdb_store_attribute_t *attr, sdb_object_t *user_data) if (children) { obj.parent = STORE_OBJ(sdb_avltree_lookup(children, attr->parent)); if (! obj.parent) { - sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' - " + sdb_log(SDB_LOG_ERR, "memstore: Failed to store attribute '%s' - " "%s '%s/%s' not found", attr->key, SDB_STORE_TYPE_TO_NAME(attr->parent_type), attr->hostname, attr->parent); @@ -610,7 +610,7 @@ store_service(sdb_store_service_t *service, sdb_object_t *user_data) obj.parent_tree = get_host_children(host, SDB_SERVICE); obj.type = SDB_SERVICE; if (! obj.parent_tree) { - sdb_log(SDB_LOG_ERR, "store: Failed to store service '%s' - " + sdb_log(SDB_LOG_ERR, "memstore: Failed to store service '%s' - " "host '%s' not found", service->name, service->hostname); status = -1; } @@ -649,7 +649,7 @@ store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) obj.parent_tree = get_host_children(host, SDB_METRIC); obj.type = SDB_METRIC; if (! obj.parent_tree) { - sdb_log(SDB_LOG_ERR, "store: Failed to store metric '%s' - " + sdb_log(SDB_LOG_ERR, "memstore: Failed to store metric '%s' - " "host '%s' not found", metric->name, metric->hostname); status = -1; } @@ -679,6 +679,10 @@ sdb_store_writer_t sdb_memstore_writer = { store_host, store_service, store_metric, store_attribute, }; +/* + * store query API + */ + static sdb_object_t * prepare_query(sdb_ast_node_t *ast, sdb_strbuf_t __attribute__((unused)) *errbuf, @@ -707,7 +711,7 @@ sdb_store_reader_t sdb_memstore_reader = { sdb_memstore_t * sdb_memstore_create(void) { - return SDB_MEMSTORE(sdb_object_create("store", store_type)); + return SDB_MEMSTORE(sdb_object_create("memstore", store_type)); } /* sdb_memstore_create */ int @@ -915,7 +919,7 @@ sdb_memstore_scan(sdb_memstore_t *store, int type, 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); + sdb_log(SDB_LOG_ERR, "memstore: Cannot scan objects of type %d", type); return -1; } @@ -948,7 +952,7 @@ sdb_memstore_scan(sdb_memstore_t *store, int type, if (sdb_memstore_matcher_matches(m, obj, filter)) { if (cb(obj, filter, user_data)) { - sdb_log(SDB_LOG_ERR, "store: Callback returned " + sdb_log(SDB_LOG_ERR, "memstore: Callback returned " "an error while scanning"); status = -1; break; @@ -958,7 +962,7 @@ sdb_memstore_scan(sdb_memstore_t *store, int type, } else if (sdb_memstore_matcher_matches(m, host, filter)) { if (cb(host, filter, user_data)) { - sdb_log(SDB_LOG_ERR, "store: Callback returned " + sdb_log(SDB_LOG_ERR, "memstore: Callback returned " "an error while scanning"); status = -1; } @@ -974,5 +978,130 @@ sdb_memstore_scan(sdb_memstore_t *store, int type, return status; } /* sdb_memstore_scan */ +int +sdb_memstore_emit(sdb_memstore_obj_t *obj, sdb_store_writer_t *w, sdb_object_t *wd) +{ + if ((! obj) || (! w)) + return -1; + + switch (obj->type) { + case SDB_HOST: + { + sdb_store_host_t host = { + obj->_name, + obj->last_update, + obj->interval, + (const char * const *)obj->backends, + obj->backends_num, + }; + if (! w->store_host) + return -1; + return w->store_host(&host, wd); + } + case SDB_SERVICE: + { + sdb_store_service_t service = { + obj->parent ? obj->parent->_name : NULL, + obj->_name, + obj->last_update, + obj->interval, + (const char * const *)obj->backends, + obj->backends_num, + }; + if (! w->store_service) + return -1; + return w->store_service(&service, wd); + } + case SDB_METRIC: + { + sdb_store_metric_t metric = { + obj->parent ? obj->parent->_name : NULL, + obj->_name, + { + METRIC(obj)->store.type, + METRIC(obj)->store.id, + }, + obj->last_update, + obj->interval, + (const char * const *)obj->backends, + obj->backends_num, + }; + if (! w->store_metric) + return -1; + return w->store_metric(&metric, wd); + } + case SDB_ATTRIBUTE: + { + sdb_store_attribute_t attr = { + NULL, + obj->parent ? obj->parent->type : 0, + obj->parent ? obj->parent->_name : NULL, + obj->_name, + ATTR(obj)->value, + obj->last_update, + obj->interval, + (const char * const *)obj->backends, + obj->backends_num, + }; + if (obj->parent && (obj->parent->type != SDB_HOST) + && obj->parent->parent) + attr.hostname = obj->parent->parent->_name; + if (! w->store_attribute) + return -1; + return w->store_attribute(&attr, wd); + } + } + + return -1; +} /* sdb_memstore_emit */ + +int +sdb_memstore_emit_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, + sdb_store_writer_t *w, sdb_object_t *wd) +{ + sdb_avltree_t *trees[] = { NULL, NULL, NULL }; + size_t i; + + if (sdb_memstore_emit(obj, w, wd)) + return -1; + + if (obj->type == SDB_HOST) { + trees[0] = HOST(obj)->attributes; + trees[1] = HOST(obj)->metrics; + trees[2] = HOST(obj)->services; + } + else if (obj->type == SDB_SERVICE) + trees[0] = SVC(obj)->attributes; + else if (obj->type == SDB_METRIC) + trees[0] = METRIC(obj)->attributes; + else if (obj->type == SDB_ATTRIBUTE) + return 0; + else + return -1; + + for (i = 0; i < SDB_STATIC_ARRAY_LEN(trees); ++i) { + sdb_avltree_iter_t *iter; + + if (! trees[i]) + continue; + + iter = sdb_avltree_get_iter(trees[i]); + while (sdb_avltree_iter_has_next(iter)) { + sdb_memstore_obj_t *child; + child = STORE_OBJ(sdb_avltree_iter_get_next(iter)); + + if (filter && (! sdb_memstore_matcher_matches(filter, child, NULL))) + continue; + + if (sdb_memstore_emit_full(child, filter, w, wd)) { + sdb_avltree_iter_destroy(iter); + return -1; + } + } + sdb_avltree_iter_destroy(iter); + } + return 0; +} /* sdb_memstore_emit_full */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/core/store_exec.c b/src/core/memstore_exec.c similarity index 94% rename from src/core/store_exec.c rename to src/core/memstore_exec.c index 9b4ea07..802e70c 100644 --- a/src/core/store_exec.c +++ b/src/core/memstore_exec.c @@ -1,5 +1,5 @@ /* - * SysDB - src/core/store_exec.c + * SysDB - src/core/memstore_exec.c * Copyright (C) 2014-2015 Sebastian 'tokkee' Harl * All rights reserved. * @@ -27,7 +27,7 @@ #include "core/object.h" #include "core/plugin.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "frontend/connection.h" #include "parser/ast.h" #include "utils/error.h" @@ -136,7 +136,7 @@ exec_fetch(sdb_memstore_t *store, if (type != SDB_HOST) status = sdb_memstore_emit(obj->parent, w, wd); if (status || sdb_memstore_emit_full(obj, filter, w, wd)) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize " + sdb_log(SDB_LOG_ERR, "memstore: Failed to serialize " "%s %s.%s to JSON", SDB_STORE_TYPE_TO_NAME(type), hostname, name); sdb_strbuf_sprintf(errbuf, "Out of memory"); @@ -156,7 +156,7 @@ exec_list(sdb_memstore_t *store, iter_t iter = { NULL, w, wd }; if (sdb_memstore_scan(store, type, /* m = */ NULL, filter, list_tojson, &iter)) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize " + sdb_log(SDB_LOG_ERR, "memstore: Failed to serialize " "store to JSON"); sdb_strbuf_sprintf(errbuf, "Out of memory"); return -1; @@ -173,7 +173,7 @@ exec_lookup(sdb_memstore_t *store, iter_t iter = { NULL, w, wd }; if (sdb_memstore_scan(store, type, m, filter, lookup_tojson, &iter)) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup %ss", + sdb_log(SDB_LOG_ERR, "memstore: Failed to lookup %ss", SDB_STORE_TYPE_TO_NAME(type)); sdb_strbuf_sprintf(errbuf, "Failed to lookup %ss", SDB_STORE_TYPE_TO_NAME(type)); @@ -196,7 +196,7 @@ sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *q, if (! q) return -1; if (! q->ast) { - sdb_log(SDB_LOG_ERR, "store: Invalid empty query"); + sdb_log(SDB_LOG_ERR, "memstore: Invalid empty query"); return -1; } @@ -216,7 +216,7 @@ sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *q, q->matcher, q->filter); default: - sdb_log(SDB_LOG_ERR, "store: Invalid query of type %s", + sdb_log(SDB_LOG_ERR, "memstore: Invalid query of type %s", SDB_AST_TYPE_TO_STRING(ast)); return -1; } diff --git a/src/core/store_expr.c b/src/core/memstore_expr.c similarity index 95% rename from src/core/store_expr.c rename to src/core/memstore_expr.c index c96b339..8335584 100644 --- a/src/core/store_expr.c +++ b/src/core/memstore_expr.c @@ -1,5 +1,5 @@ /* - * SysDB - src/core/store_expr.c + * SysDB - src/core/memstore_expr.c * Copyright (C) 2014 Sebastian 'tokkee' Harl * All rights reserved. * @@ -26,7 +26,8 @@ */ /* - * This module implements expressions which may be executed in the store. + * This module implements arithmetic and logical expressions for in-memory + * stores. */ #if HAVE_CONFIG_H @@ -34,7 +35,7 @@ #endif /* HAVE_CONFIG_H */ #include "sysdb.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "core/data.h" #include "core/object.h" @@ -133,7 +134,7 @@ sdb_memstore_expr_create(int op, sdb_memstore_expr_t *left, sdb_memstore_expr_t return NULL; if (left->type || right->type) { - e = SDB_MEMSTORE_EXPR(sdb_object_create("store-expr", expr_type, + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-expr", expr_type, op, left, right, NULL)); e->data_type = sdb_data_expr_type(op, left->type, right->type); return e; @@ -142,7 +143,7 @@ sdb_memstore_expr_create(int op, sdb_memstore_expr_t *left, sdb_memstore_expr_t if (sdb_data_expr_eval(op, &left->data, &right->data, &value)) return NULL; - e = SDB_MEMSTORE_EXPR(sdb_object_create("store-constvalue", expr_type, + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-constvalue", expr_type, 0, NULL, NULL, &value)); e->data_type = value.type; return e; @@ -157,7 +158,7 @@ sdb_memstore_expr_typed(int typ, sdb_memstore_expr_t *expr) if ((typ < SDB_HOST) || (SDB_ATTRIBUTE < typ)) return NULL; - e = SDB_MEMSTORE_EXPR(sdb_object_create("store-typedexpr", expr_type, + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-typedexpr", expr_type, TYPED_EXPR, expr, NULL, &value)); e->data_type = expr->data_type; return e; @@ -171,7 +172,7 @@ sdb_memstore_expr_fieldvalue(int field) if ((field < SDB_FIELD_NAME) || (SDB_FIELD_TIMESERIES < field)) return NULL; - e = SDB_MEMSTORE_EXPR(sdb_object_create("store-fieldvalue", expr_type, + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-fieldvalue", expr_type, FIELD_VALUE, NULL, NULL, &value)); e->data_type = SDB_FIELD_TYPE(field); return e; @@ -187,7 +188,7 @@ sdb_memstore_expr_attrvalue(const char *name) if (! value.data.string) return NULL; - expr = SDB_MEMSTORE_EXPR(sdb_object_create("store-attrvalue", expr_type, + expr = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-attrvalue", expr_type, ATTR_VALUE, NULL, NULL, &value)); if (! expr) free(value.data.string); @@ -203,7 +204,7 @@ sdb_memstore_expr_constvalue(const sdb_data_t *value) if (sdb_data_copy(&data, value)) return NULL; - e = SDB_MEMSTORE_EXPR(sdb_object_create("store-constvalue", expr_type, + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-constvalue", expr_type, 0, NULL, NULL, &data)); e->data_type = data.type; return e; diff --git a/src/core/store_lookup.c b/src/core/memstore_lookup.c similarity index 97% rename from src/core/store_lookup.c rename to src/core/memstore_lookup.c index b69e7f9..2752a66 100644 --- a/src/core/store_lookup.c +++ b/src/core/memstore_lookup.c @@ -1,5 +1,5 @@ /* - * SysDB - src/core/store_lookup.c + * SysDB - src/core/memstore_lookup.c * Copyright (C) 2014 Sebastian 'tokkee' Harl * All rights reserved. * @@ -36,7 +36,7 @@ #endif /* HAVE_CONFIG_H */ #include "sysdb.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "core/object.h" #include "utils/error.h" @@ -197,7 +197,7 @@ match_iter(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, iter = sdb_memstore_expr_iter(ITER_M(m)->iter, obj, filter); if (! iter) { - sdb_log(SDB_LOG_WARNING, "store: Invalid iterator"); + sdb_log(SDB_LOG_WARNING, "memstore: Invalid iterator"); return 0; } @@ -333,7 +333,7 @@ typedef int (*matcher_cb)(sdb_memstore_matcher_t *, sdb_memstore_obj_t *, sdb_memstore_matcher_t *); /* this array needs to be indexable by the matcher types; - * -> update the enum in store-private.h when updating this */ + * -> update the enum in memstore-private.h when updating this */ static matcher_cb matchers[] = { match_logical, @@ -516,12 +516,12 @@ sdb_memstore_matcher_t * sdb_memstore_any_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m) { if ((m->type < MATCHER_LT) || (MATCHER_NREGEX < m->type)) { - sdb_log(SDB_LOG_ERR, "store: Invalid ANY -> %s matcher " + sdb_log(SDB_LOG_ERR, "memstore: Invalid ANY -> %s matcher " "(invalid operator)", MATCHER_SYM(m->type)); return NULL; } if (CMP_M(m)->left) { - sdb_log(SDB_LOG_ERR, "store: Invalid ANY %s %s %s matcher " + sdb_log(SDB_LOG_ERR, "memstore: Invalid ANY %s %s %s matcher " "(invalid left operand)", SDB_TYPE_TO_STRING(CMP_M(m)->left->data_type), MATCHER_SYM(m->type), @@ -536,12 +536,12 @@ sdb_memstore_matcher_t * sdb_memstore_all_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m) { if ((m->type < MATCHER_LT) || (MATCHER_NREGEX < m->type)) { - sdb_log(SDB_LOG_ERR, "store: Invalid ALL -> %s matcher " + sdb_log(SDB_LOG_ERR, "memstore: Invalid ALL -> %s matcher " "(invalid operator)", MATCHER_SYM(m->type)); return NULL; } if (CMP_M(m)->left) { - sdb_log(SDB_LOG_ERR, "store: Invalid ALL %s %s %s matcher " + sdb_log(SDB_LOG_ERR, "memstore: Invalid ALL %s %s %s matcher " "(invalid left operand)", SDB_TYPE_TO_STRING(CMP_M(m)->left->data_type), MATCHER_SYM(m->type), diff --git a/src/core/store_query.c b/src/core/memstore_query.c similarity index 92% rename from src/core/store_query.c rename to src/core/memstore_query.c index 341cb16..eb1e82f 100644 --- a/src/core/store_query.c +++ b/src/core/memstore_query.c @@ -1,5 +1,5 @@ /* - * SysDB - src/core/store_query.c + * SysDB - src/core/memstore_query.c * Copyright (C) 2014-2015 Sebastian 'tokkee' Harl * All rights reserved. * @@ -26,7 +26,7 @@ */ #include "core/object.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "parser/ast.h" #include "utils/error.h" @@ -43,14 +43,14 @@ node_to_expr(sdb_ast_node_t *n) int op; if (! n) { - sdb_log(SDB_LOG_ERR, "store: Encountered empty AST expression node"); + sdb_log(SDB_LOG_ERR, "memstore: Encountered empty AST expression node"); return NULL; } switch (n->type) { case SDB_AST_TYPE_OPERATOR: if (! SDB_AST_IS_ARITHMETIC(n)) { - sdb_log(SDB_LOG_ERR, "store: Invalid arithmetic operator of " + sdb_log(SDB_LOG_ERR, "memstore: Invalid arithmetic operator of " "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); return NULL; } @@ -83,7 +83,7 @@ node_to_expr(sdb_ast_node_t *n) break; default: - sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)", + sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); e = NULL; } @@ -188,7 +188,7 @@ cmp_to_matcher(sdb_ast_node_t *n) break; default: - sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)", + sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); m = NULL; } @@ -226,7 +226,7 @@ iter_to_matcher(sdb_ast_node_t *n) break; default: - sdb_log(SDB_LOG_ERR, "store: Invalid iterator node of type %s (%#x)", + sdb_log(SDB_LOG_ERR, "memstore: Invalid iterator node of type %s (%#x)", SDB_AST_OP_TO_STRING(SDB_AST_ITER(n)->kind), SDB_AST_ITER(n)->kind); m = NULL; } @@ -243,14 +243,14 @@ node_to_matcher(sdb_ast_node_t *n) int kind; if (! n) { - sdb_log(SDB_LOG_ERR, "store: Encountered empty AST matcher node"); + sdb_log(SDB_LOG_ERR, "memstore: Encountered empty AST matcher node"); return NULL; } switch (n->type) { case SDB_AST_TYPE_OPERATOR: if (! SDB_AST_IS_LOGICAL(n)) { - sdb_log(SDB_LOG_ERR, "store: Invalid logical operator of " + sdb_log(SDB_LOG_ERR, "memstore: Invalid logical operator of " "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); return NULL; } @@ -265,7 +265,7 @@ node_to_matcher(sdb_ast_node_t *n) return iter_to_matcher(n); } - sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)", + sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); return NULL; } /* node_to_matcher */ @@ -300,7 +300,7 @@ query_init(sdb_object_t *obj, va_list ap) break; default: - sdb_log(SDB_LOG_ERR, "store: Invalid top-level AST node " + sdb_log(SDB_LOG_ERR, "memstore: Invalid top-level AST node " "of type %#x", ast->type); return -1; } diff --git a/src/core/store_json.c b/src/core/store_json.c index b39ff21..9266608 100644 --- a/src/core/store_json.c +++ b/src/core/store_json.c @@ -34,7 +34,7 @@ #endif /* HAVE_CONFIG_H */ #include "sysdb.h" -#include "core/store-private.h" +#include "core/store.h" #include "utils/error.h" #include @@ -379,133 +379,6 @@ sdb_store_json_formatter(sdb_strbuf_t *buf, int type, int flags) buf, type, flags)); } /* sdb_store_json_formatter */ -/* TODO: Move sdb_store_emit* somewhere else. */ - -int -sdb_memstore_emit(sdb_memstore_obj_t *obj, sdb_store_writer_t *w, sdb_object_t *wd) -{ - if ((! obj) || (! w)) - return -1; - - switch (obj->type) { - case SDB_HOST: - { - sdb_store_host_t host = { - obj->_name, - obj->last_update, - obj->interval, - (const char * const *)obj->backends, - obj->backends_num, - }; - if (! w->store_host) - return -1; - return w->store_host(&host, wd); - } - case SDB_SERVICE: - { - sdb_store_service_t service = { - obj->parent ? obj->parent->_name : NULL, - obj->_name, - obj->last_update, - obj->interval, - (const char * const *)obj->backends, - obj->backends_num, - }; - if (! w->store_service) - return -1; - return w->store_service(&service, wd); - } - case SDB_METRIC: - { - sdb_store_metric_t metric = { - obj->parent ? obj->parent->_name : NULL, - obj->_name, - { - METRIC(obj)->store.type, - METRIC(obj)->store.id, - }, - obj->last_update, - obj->interval, - (const char * const *)obj->backends, - obj->backends_num, - }; - if (! w->store_metric) - return -1; - return w->store_metric(&metric, wd); - } - case SDB_ATTRIBUTE: - { - sdb_store_attribute_t attr = { - NULL, - obj->parent ? obj->parent->type : 0, - obj->parent ? obj->parent->_name : NULL, - obj->_name, - ATTR(obj)->value, - obj->last_update, - obj->interval, - (const char * const *)obj->backends, - obj->backends_num, - }; - if (obj->parent && (obj->parent->type != SDB_HOST) - && obj->parent->parent) - attr.hostname = obj->parent->parent->_name; - if (! w->store_attribute) - return -1; - return w->store_attribute(&attr, wd); - } - } - - return -1; -} /* sdb_memstore_emit */ - -int -sdb_memstore_emit_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, - sdb_store_writer_t *w, sdb_object_t *wd) -{ - sdb_avltree_t *trees[] = { NULL, NULL, NULL }; - size_t i; - - if (sdb_memstore_emit(obj, w, wd)) - return -1; - - if (obj->type == SDB_HOST) { - trees[0] = HOST(obj)->attributes; - trees[1] = HOST(obj)->metrics; - trees[2] = HOST(obj)->services; - } - else if (obj->type == SDB_SERVICE) - trees[0] = SVC(obj)->attributes; - else if (obj->type == SDB_METRIC) - trees[0] = METRIC(obj)->attributes; - else if (obj->type == SDB_ATTRIBUTE) - return 0; - else - return -1; - - for (i = 0; i < SDB_STATIC_ARRAY_LEN(trees); ++i) { - sdb_avltree_iter_t *iter; - - if (! trees[i]) - continue; - - iter = sdb_avltree_get_iter(trees[i]); - while (sdb_avltree_iter_has_next(iter)) { - sdb_memstore_obj_t *child; - child = STORE_OBJ(sdb_avltree_iter_get_next(iter)); - - if (filter && (! sdb_memstore_matcher_matches(filter, child, NULL))) - continue; - - if (sdb_memstore_emit_full(child, filter, w, wd)) { - sdb_avltree_iter_destroy(iter); - return -1; - } - } - sdb_avltree_iter_destroy(iter); - } - return 0; -} /* sdb_memstore_emit_full */ - int sdb_store_json_finish(sdb_store_json_formatter_t *f) { diff --git a/src/include/core/memstore.h b/src/include/core/memstore.h new file mode 100644 index 0000000..8590156 --- /dev/null +++ b/src/include/core/memstore.h @@ -0,0 +1,535 @@ +/* + * SysDB - src/include/core/memstore.h + * Copyright (C) 2012-2015 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SDB_CORE_MEMSTORE_H +#define SDB_CORE_MEMSTORE_H 1 + +#include "sysdb.h" +#include "core/object.h" +#include "core/data.h" +#include "core/store.h" +#include "core/time.h" +#include "parser/ast.h" +#include "utils/strbuf.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * sdb_memstore_t represents an in-memory store. It inherits from sdb_object_t + * and may safely be case to a generic object. + */ +struct sdb_memstore; +typedef struct sdb_memstore sdb_memstore_t; +#define SDB_MEMSTORE(obj) ((sdb_memstore_t *)(obj)) + +/* + * sdb_memstore_obj_t represents the super-class of any stored object. It + * inherits from sdb_object_t and may safely be cast to a generic object to + * access its name. + */ +struct sdb_memstore_obj; +typedef struct sdb_memstore_obj sdb_memstore_obj_t; + +/* + * Expressions represent arithmetic expressions based on stored objects and + * their various attributes. + * + * An expression object inherits from sdb_object_t and, thus, may safely be + * cast to a generic object. + */ +struct sdb_memstore_expr; +typedef struct sdb_memstore_expr sdb_memstore_expr_t; +#define SDB_MEMSTORE_EXPR(obj) ((sdb_memstore_expr_t *)(obj)) + +/* + * An expression iterator iterates over the values of an iterable expression. + */ +struct sdb_memstore_expr_iter; +typedef struct sdb_memstore_expr_iter sdb_memstore_expr_iter_t; + +/* + * Store matchers may be used to lookup hosts from the store based on their + * various attributes. Service and attribute matchers are applied to a host's + * services and attributes and evaluate to true if *any* service or attribute + * matches. + * + * A store matcher object inherits from sdb_object_t and, thus, may safely be + * cast to a generic object. + */ +struct sdb_memstore_matcher; +typedef struct sdb_memstore_matcher sdb_memstore_matcher_t; +#define SDB_MEMSTORE_MATCHER(obj) ((sdb_memstore_matcher_t *)(obj)) + +/* + * sdb_memstore_writer: + * A store writer implementation that provides an in-memory object store. It + * expects a store object as its user-data argument. + */ +extern sdb_store_writer_t sdb_memstore_writer; + +/* + * sdb_memstore_reader: + * A store reader implementation that uses an in-memory object store. It + * expects a store object as its user-data argument. + */ +extern sdb_store_reader_t sdb_memstore_reader; + +/* + * sdb_memstore_create: + * Allocate a new in-memory store. + */ +sdb_memstore_t * +sdb_memstore_create(void); + +/* + * sdb_memstore_host, sdb_memstore_service, sdb_memstore_metric, + * sdb_memstore_attribute, sdb_memstore_metric_attr: + * Store an object in the specified store. The hostname is expected to be + * canonical. + */ +int +sdb_memstore_host(sdb_memstore_t *store, const char *name, sdb_time_t last_update); +int +sdb_memstore_service(sdb_memstore_t *store, const char *hostname, const char *name, + sdb_time_t last_update); +int +sdb_memstore_metric(sdb_memstore_t *store, const char *hostname, const char *name, + sdb_metric_store_t *metric_store, sdb_time_t last_update); +int +sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname, + const char *key, const sdb_data_t *value, sdb_time_t last_update); +int +sdb_memstore_service_attr(sdb_memstore_t *store, const char *hostname, + const char *service, const char *key, const sdb_data_t *value, + sdb_time_t last_update); +int +sdb_memstore_metric_attr(sdb_memstore_t *store, const char *hostname, + const char *metric, const char *key, const sdb_data_t *value, + sdb_time_t last_update); + +/* + * sdb_memstore_get_host: + * Query the specified store for a host by its (canonicalized) name. + * + * The function increments the ref count of the host object. The caller needs + * to deref it when no longer using it. + */ +sdb_memstore_obj_t * +sdb_memstore_get_host(sdb_memstore_t *store, const char *name); + +/* + * sdb_memstore_get_child: + * Retrieve a host's child object of the specified type and name. The + * reference count of the child object will be incremented before returning + * it. The caller is responsible for releasing the object once it's no longer + * used. + * + * Returns: + * - the child object on success + * - NULL else + */ +sdb_memstore_obj_t * +sdb_memstore_get_child(sdb_memstore_obj_t *host, int type, const char *name); + +/* + * sdb_memstore_get_field: + * Get the value of a stored object's queryable field. The caller is + * responsible for freeing any dynamically allocated memory possibly stored in + * the returned value. If 'res' is NULL, the function will return whether the + * field exists. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_memstore_get_field(sdb_memstore_obj_t *obj, int field, sdb_data_t *res); + +/* + * sdb_memstore_get_attr: + * Get the value of a stored object's attribute. The caller is responsible for + * freeing any dynamically allocated memory possibly stored in the returned + * value. If 'res' is NULL, the function will return whether the attribute + * exists. If specified, only attributes matching the filter will be + * considered. + * + * Returns: + * - 0 if the attribute exists + * - a negative value else + */ +int +sdb_memstore_get_attr(sdb_memstore_obj_t *obj, const char *name, sdb_data_t *res, + sdb_memstore_matcher_t *filter); + +/* + * Querying a store: + * + * - Query interface: A query is a formal description of an interaction with + * the store. It can be used, both, for read and write access. The query is + * described by its abstract syntax tree (AST). The parser package provides + * means to parse a string (SysQL) representation of the query into an AST. + * + * - Matcher / expression interface: This low-level interface provides direct + * control over how to access the store. It is used by the query + * implementation internally and can only be used for read access. + */ + +/* + * sdb_memstore_query_t: + * A parsed query readily prepared for execution. + */ +struct sdb_memstore_query; +typedef struct sdb_memstore_query sdb_memstore_query_t; + +/* + * sdb_memstore_query_prepare: + * Prepare the query described by 'ast' for execution in a store. + * + * Returns: + * - a store query on success + * - NULL else + */ +sdb_memstore_query_t * +sdb_memstore_query_prepare(sdb_ast_node_t *ast); + +/* + * sdb_memstore_query_prepare_matcher: + * Prepare the logical expression described by 'ast' for execution as a store + * matcher. + * + * Returns: + * - a matcher on success + * - NULL else + */ +sdb_memstore_matcher_t * +sdb_memstore_query_prepare_matcher(sdb_ast_node_t *ast); + +/* + * sdb_memstore_query_execute: + * Execute a previously prepared query in the specified store. The query + * result will be written to 'buf' and any errors to 'errbuf'. + * + * Returns: + * - the result type (to be used by the server reply) + * - a negative value on error + */ +int +sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *m, + sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf); + +/* + * sdb_memstore_expr_create: + * Creates an arithmetic expression implementing the specified operator on the + * specified left and right operand. + * + * Returns: + * - an expression object on success + * - NULL else + */ +sdb_memstore_expr_t * +sdb_memstore_expr_create(int op, + sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); + +/* + * sdb_memstore_expr_typed: + * Creates an expression which evaluates in the context of an object's sibling + * as specified by the given type. + * + * Returns: + * - an expression object on success + * - NULL else + */ +sdb_memstore_expr_t * +sdb_memstore_expr_typed(int typ, sdb_memstore_expr_t *expr); + +/* + * sdb_memstore_expr_fieldvalue: + * Creates an expression which evaluates to the value of the specified + * queryable field of a stored object. + * + * Returns: + * - an expression object on success + * - NULL else + */ +sdb_memstore_expr_t * +sdb_memstore_expr_fieldvalue(int field); + +/* + * sdb_memstore_expr_attrvalue: + * Creates an expression which evaluates to the value of the specified + * attribute of a stored object. Evaluates to a NULL value if the attribute + * does not exist. + * + * Returns: + * - an expression object on success + * - NULL else + */ +sdb_memstore_expr_t * +sdb_memstore_expr_attrvalue(const char *name); + +/* + * sdb_memstore_expr_constvalue: + * Creates an expression which evaluates to the specified constant value. + * + * Returns: + * - an expression object on success + * - NULL else + */ +sdb_memstore_expr_t * +sdb_memstore_expr_constvalue(const sdb_data_t *value); + +/* + * sdb_memstore_expr_eval: + * Evaluate an expression for the specified stored object and stores the + * result in 'res'. The result's value will be allocated dynamically if + * necessary and, thus, should be free'd by the caller (e.g. using + * sdb_data_free_datum). The object may be NULL, in which case the expression + * needs to evaluate to a constant value. If specified, only objects matching + * the filter will be used during the evaluation. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_memstore_expr_eval(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj, + sdb_data_t *res, sdb_memstore_matcher_t *filter); + +/* + * sdb_memstore_expr_iter: + * Iterate over the elements of an iterable expression. sdb_memstore_expr_iter + * returns NULL if the expression is not iterable (for the specified object). + * + * sdb_memstore_expr_iter_get_next returns NULL if there is no next element. + */ +sdb_memstore_expr_iter_t * +sdb_memstore_expr_iter(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter); +void +sdb_memstore_expr_iter_destroy(sdb_memstore_expr_iter_t *iter); + +bool +sdb_memstore_expr_iter_has_next(sdb_memstore_expr_iter_t *iter); +sdb_data_t +sdb_memstore_expr_iter_get_next(sdb_memstore_expr_iter_t *iter); + +/* + * sdb_memstore_dis_matcher: + * Creates a matcher matching the disjunction (logical OR) of two matchers. + */ +sdb_memstore_matcher_t * +sdb_memstore_dis_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right); + +/* + * sdb_memstore_con_matcher: + * Creates a matcher matching the conjunction (logical AND) of two matchers. + */ +sdb_memstore_matcher_t * +sdb_memstore_con_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right); + +/* + * sdb_memstore_inv_matcher: + * Creates a matcher matching the inverse (logical NOT) of a matcher. + */ +sdb_memstore_matcher_t * +sdb_memstore_inv_matcher(sdb_memstore_matcher_t *m); + +/* + * sdb_memstore_any_matcher: + * Creates a matcher iterating over values of the first expression (which has + * to be iterable). It matches if *any* of those elements match 'm'. 'm' has + * to be an ary operation with the left operand unset. + */ +sdb_memstore_matcher_t * +sdb_memstore_any_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m); + +/* + * sdb_memstore_all_matcher: + * Creates a matcher iterating over values of the first expression (which has + * to be iterable). It matches if *all* of those elements match 'm'. 'm' has + * to be an ary operation with the left operand unset. + */ +sdb_memstore_matcher_t * +sdb_memstore_all_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m); + +/* + * sdb_memstore_in_matcher: + * Creates a matcher which matches if the right value evaluates to an array + * value and the left value is included in that array. See sdb_data_inarray + * for more details. + */ +sdb_memstore_matcher_t * +sdb_memstore_in_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); + +/* + * sdb_memstore_lt_matcher, sdb_memstore_le_matcher, sdb_memstore_eq_matcher, + * sdb_memstore_ge_matcher, sdb_memstore_gt_matcher: + * Create conditional matchers comparing the values of two expressions. The + * matcher matches if the left expression compres less than, less or equal + * than, equal to, not equal to, greater or equal than, or greater than the + * right expression. + */ +sdb_memstore_matcher_t * +sdb_memstore_lt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); +sdb_memstore_matcher_t * +sdb_memstore_le_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); +sdb_memstore_matcher_t * +sdb_memstore_eq_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); +sdb_memstore_matcher_t * +sdb_memstore_ne_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); +sdb_memstore_matcher_t * +sdb_memstore_ge_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); +sdb_memstore_matcher_t * +sdb_memstore_gt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); + +/* + * sdb_memstore_regex_matcher: + * Creates a matcher which matches the string value the left expression + * evaluates to against the regular expression the right expression evaluates + * to. The right expression may either be a constant value regular expression + * or string or a dynamic value evaluating to a string. In the latter case, + * the string is compiled to a regex every time the matcher is executed. + */ +sdb_memstore_matcher_t * +sdb_memstore_regex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); + +/* + * sdb_memstore_nregex_matcher: + * Creates a regex matcher just like sdb_memstore_regex_matcher except that it + * matches in case the regular expression does not match. + */ +sdb_memstore_matcher_t * +sdb_memstore_nregex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); + +/* + * sdb_memstore_isnull_matcher: + * Creates a matcher matching NULL values. + */ +sdb_memstore_matcher_t * +sdb_memstore_isnull_matcher(sdb_memstore_expr_t *expr); + +/* + * sdb_memstore_istrue_matcher, sdb_memstore_isfalse_matcher: + * Creates a matcher matching boolean values. + */ +sdb_memstore_matcher_t * +sdb_memstore_istrue_matcher(sdb_memstore_expr_t *expr); +sdb_memstore_matcher_t * +sdb_memstore_isfalse_matcher(sdb_memstore_expr_t *expr); + +/* + * sdb_memstore_matcher_matches: + * Check whether the specified matcher matches the specified store object. If + * specified, the filter will be used to preselect objects for further + * evaluation. It is applied to any object that's used during the evaluation + * of the matcher. Only those objects matching the filter will be considered. + * + * Note that the filter is applied to all object types (hosts, service, + * metric, attribute). Thus, any object-specific matchers are mostly unsuited + * for this purpose and, if used, may result in unexpected behavior. + * + * Returns: + * - 1 if the object matches + * - 0 else + */ +int +sdb_memstore_matcher_matches(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter); + +/* + * sdb_memstore_matcher_op_cb: + * Callback constructing a matcher operator. + */ +typedef sdb_memstore_matcher_t *(*sdb_memstore_matcher_op_cb) + (sdb_memstore_expr_t *, sdb_memstore_expr_t *); + +/* + * sdb_memstore_lookup_cb: + * Lookup callback. It is called for each matching object when looking up data + * in the store passing on the lookup filter and the specified user-data. The + * lookup aborts early if the callback returns non-zero. + */ +typedef int (*sdb_memstore_lookup_cb)(sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter, void *user_data); + +/* + * sdb_memstore_scan: + * Look up objects of the specified type in the specified store. The specified + * callback function is called for each object in the store matching 'm'. The + * function performs a full scan of all stored objects. If specified, the + * filter will be used to preselect objects for further evaluation. See the + * description of 'sdb_memstore_matcher_matches' for details. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_memstore_scan(sdb_memstore_t *store, int type, + sdb_memstore_matcher_t *m, sdb_memstore_matcher_t *filter, + sdb_memstore_lookup_cb cb, void *user_data); + +/* + * sdb_memstore_emit: + * Send a single object to the specified store writer. Attributes or any child + * objects are not included. Use sdb_memstore_emit_full() to emit a full + * (filtered) object. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_memstore_emit(sdb_memstore_obj_t *obj, sdb_store_writer_t *w, sdb_object_t *wd); + +/* + * sdb_memstore_emit_full: + * Send a single object and its attributes and all children to the specified + * store writer. The filter, if specified, is applied to each attribute and + * child object. Only matching objects will be emitted. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_memstore_emit_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, + sdb_store_writer_t *w, sdb_object_t *wd); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ! SDB_CORE_MEMSTORE_H */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/include/core/store.h b/src/include/core/store.h index 03677e8..5f60c8d 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -1,6 +1,6 @@ /* * SysDB - src/include/core/store.h - * Copyright (C) 2012 Sebastian 'tokkee' Harl + * Copyright (C) 2012-2015 Sebastian 'tokkee' Harl * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,11 +32,9 @@ #include "core/object.h" #include "core/data.h" #include "core/time.h" -#include "core/timeseries.h" #include "parser/ast.h" #include "utils/strbuf.h" -#include #include #ifdef __cplusplus @@ -94,22 +92,6 @@ enum { : ((f) == SDB_FIELD_TIMESERIES) ? SDB_TYPE_BOOLEAN \ : -1) -/* - * sdb_memstore_t represents an in-memory store. It inherits from sdb_object_t - * and may safely be case to a generic object. - */ -struct sdb_memstore; -typedef struct sdb_memstore sdb_memstore_t; -#define SDB_MEMSTORE(obj) ((sdb_memstore_t *)(obj)) - -/* - * sdb_memstore_obj_t represents the super-class of any stored object. It - * inherits from sdb_object_t and may safely be cast to a generic object to - * access its name. - */ -struct sdb_memstore_obj; -typedef struct sdb_memstore_obj sdb_memstore_obj_t; - /* * sdb_store_host_t represents the meta-data of a stored host object. */ @@ -180,36 +162,6 @@ typedef struct { } sdb_store_attribute_t; #define SDB_STORE_ATTRIBUTE_INIT { NULL, 0, NULL, NULL, SDB_DATA_INIT, 0, 0, NULL, 0 } -/* - * Expressions represent arithmetic expressions based on stored objects and - * their various attributes. - * - * An expression object inherits from sdb_object_t and, thus, may safely be - * cast to a generic object. - */ -struct sdb_memstore_expr; -typedef struct sdb_memstore_expr sdb_memstore_expr_t; -#define SDB_MEMSTORE_EXPR(obj) ((sdb_memstore_expr_t *)(obj)) - -/* - * An expression iterator iterates over the values of an iterable expression. - */ -struct sdb_memstore_expr_iter; -typedef struct sdb_memstore_expr_iter sdb_memstore_expr_iter_t; - -/* - * Store matchers may be used to lookup hosts from the store based on their - * various attributes. Service and attribute matchers are applied to a host's - * services and attributes and evaluate to true if *any* service or attribute - * matches. - * - * A store matcher object inherits from sdb_object_t and, thus, may safely be - * cast to a generic object. - */ -struct sdb_memstore_matcher; -typedef struct sdb_memstore_matcher sdb_memstore_matcher_t; -#define SDB_MEMSTORE_MATCHER(obj) ((sdb_memstore_matcher_t *)(obj)) - /* * A JSON formatter converts stored objects into the JSON format. * See http://www.ietf.org/rfc/rfc4627.txt @@ -270,13 +222,6 @@ typedef struct { int (*store_attribute)(sdb_store_attribute_t *attr, sdb_object_t *user_data); } sdb_store_writer_t; -/* - * sdb_memstore_writer: - * A store writer implementation that provides an in-memory object store. It - * expects a store object as its user-data argument. - */ -extern sdb_store_writer_t sdb_memstore_writer; - /* * A store reader describes the interface to query a store implementation. */ @@ -300,408 +245,6 @@ typedef struct { sdb_strbuf_t *errbuf, sdb_object_t *user_data); } sdb_store_reader_t; -/* - * sdb_memstore_reader: - * A store reader implementation that uses an in-memory object store. It - * expects a store object as its user-data argument. - */ -extern sdb_store_reader_t sdb_memstore_reader; - -/* - * sdb_memstore_create: - * Allocate a new in-memory store. - */ -sdb_memstore_t * -sdb_memstore_create(void); - -/* - * sdb_memstore_host, sdb_memstore_service, sdb_memstore_metric, - * sdb_memstore_attribute, sdb_memstore_metric_attr: - * Store an object in the specified store. The hostname is expected to be - * canonical. - */ -int -sdb_memstore_host(sdb_memstore_t *store, const char *name, sdb_time_t last_update); -int -sdb_memstore_service(sdb_memstore_t *store, const char *hostname, const char *name, - sdb_time_t last_update); -int -sdb_memstore_metric(sdb_memstore_t *store, const char *hostname, const char *name, - sdb_metric_store_t *metric_store, sdb_time_t last_update); -int -sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname, - const char *key, const sdb_data_t *value, sdb_time_t last_update); -int -sdb_memstore_service_attr(sdb_memstore_t *store, const char *hostname, - const char *service, const char *key, const sdb_data_t *value, - sdb_time_t last_update); -int -sdb_memstore_metric_attr(sdb_memstore_t *store, const char *hostname, - const char *metric, const char *key, const sdb_data_t *value, - sdb_time_t last_update); - -/* - * sdb_memstore_get_host: - * Query the specified store for a host by its (canonicalized) name. - * - * The function increments the ref count of the host object. The caller needs - * to deref it when no longer using it. - */ -sdb_memstore_obj_t * -sdb_memstore_get_host(sdb_memstore_t *store, const char *name); - -/* - * sdb_memstore_get_child: - * Retrieve a host's child object of the specified type and name. The - * reference count of the child object will be incremented before returning - * it. The caller is responsible for releasing the object once it's no longer - * used. - * - * Returns: - * - the child object on success - * - NULL else - */ -sdb_memstore_obj_t * -sdb_memstore_get_child(sdb_memstore_obj_t *host, int type, const char *name); - -/* - * sdb_memstore_get_field: - * Get the value of a stored object's queryable field. The caller is - * responsible for freeing any dynamically allocated memory possibly stored in - * the returned value. If 'res' is NULL, the function will return whether the - * field exists. - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_memstore_get_field(sdb_memstore_obj_t *obj, int field, sdb_data_t *res); - -/* - * sdb_memstore_get_attr: - * Get the value of a stored object's attribute. The caller is responsible for - * freeing any dynamically allocated memory possibly stored in the returned - * value. If 'res' is NULL, the function will return whether the attribute - * exists. If specified, only attributes matching the filter will be - * considered. - * - * Returns: - * - 0 if the attribute exists - * - a negative value else - */ -int -sdb_memstore_get_attr(sdb_memstore_obj_t *obj, const char *name, sdb_data_t *res, - sdb_memstore_matcher_t *filter); - -/* - * Querying a store: - * - * - Query interface: A query is a formal description of an interaction with - * the store. It can be used, both, for read and write access. The query is - * described by its abstract syntax tree (AST). The parser package provides - * means to parse a string (SysQL) representation of the query into an AST. - * - * - Matcher / expression interface: This low-level interface provides direct - * control over how to access the store. It is used by the query - * implementation internally and can only be used for read access. - */ - -/* - * sdb_memstore_query_t: - * A parsed query readily prepared for execution. - */ -struct sdb_memstore_query; -typedef struct sdb_memstore_query sdb_memstore_query_t; - -/* - * sdb_memstore_query_prepare: - * Prepare the query described by 'ast' for execution in a store. - * - * Returns: - * - a store query on success - * - NULL else - */ -sdb_memstore_query_t * -sdb_memstore_query_prepare(sdb_ast_node_t *ast); - -/* - * sdb_memstore_query_prepare_matcher: - * Prepare the logical expression described by 'ast' for execution as a store - * matcher. - * - * Returns: - * - a matcher on success - * - NULL else - */ -sdb_memstore_matcher_t * -sdb_memstore_query_prepare_matcher(sdb_ast_node_t *ast); - -/* - * sdb_memstore_query_execute: - * Execute a previously prepared query in the specified store. The query - * result will be written to 'buf' and any errors to 'errbuf'. - * - * Returns: - * - the result type (to be used by the server reply) - * - a negative value on error - */ -int -sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *m, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf); - -/* - * sdb_memstore_expr_create: - * Creates an arithmetic expression implementing the specified operator on the - * specified left and right operand. - * - * Returns: - * - an expression object on success - * - NULL else - */ -sdb_memstore_expr_t * -sdb_memstore_expr_create(int op, - sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); - -/* - * sdb_memstore_expr_typed: - * Creates an expression which evaluates in the context of an object's sibling - * as specified by the given type. - * - * Returns: - * - an expression object on success - * - NULL else - */ -sdb_memstore_expr_t * -sdb_memstore_expr_typed(int typ, sdb_memstore_expr_t *expr); - -/* - * sdb_memstore_expr_fieldvalue: - * Creates an expression which evaluates to the value of the specified - * queryable field of a stored object. - * - * Returns: - * - an expression object on success - * - NULL else - */ -sdb_memstore_expr_t * -sdb_memstore_expr_fieldvalue(int field); - -/* - * sdb_memstore_expr_attrvalue: - * Creates an expression which evaluates to the value of the specified - * attribute of a stored object. Evaluates to a NULL value if the attribute - * does not exist. - * - * Returns: - * - an expression object on success - * - NULL else - */ -sdb_memstore_expr_t * -sdb_memstore_expr_attrvalue(const char *name); - -/* - * sdb_memstore_expr_constvalue: - * Creates an expression which evaluates to the specified constant value. - * - * Returns: - * - an expression object on success - * - NULL else - */ -sdb_memstore_expr_t * -sdb_memstore_expr_constvalue(const sdb_data_t *value); - -/* - * sdb_memstore_expr_eval: - * Evaluate an expression for the specified stored object and stores the - * result in 'res'. The result's value will be allocated dynamically if - * necessary and, thus, should be free'd by the caller (e.g. using - * sdb_data_free_datum). The object may be NULL, in which case the expression - * needs to evaluate to a constant value. If specified, only objects matching - * the filter will be used during the evaluation. - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_memstore_expr_eval(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj, - sdb_data_t *res, sdb_memstore_matcher_t *filter); - -/* - * sdb_memstore_expr_iter: - * Iterate over the elements of an iterable expression. sdb_memstore_expr_iter - * returns NULL if the expression is not iterable (for the specified object). - * - * sdb_memstore_expr_iter_get_next returns NULL if there is no next element. - */ -sdb_memstore_expr_iter_t * -sdb_memstore_expr_iter(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj, - sdb_memstore_matcher_t *filter); -void -sdb_memstore_expr_iter_destroy(sdb_memstore_expr_iter_t *iter); - -bool -sdb_memstore_expr_iter_has_next(sdb_memstore_expr_iter_t *iter); -sdb_data_t -sdb_memstore_expr_iter_get_next(sdb_memstore_expr_iter_t *iter); - -/* - * sdb_memstore_dis_matcher: - * Creates a matcher matching the disjunction (logical OR) of two matchers. - */ -sdb_memstore_matcher_t * -sdb_memstore_dis_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right); - -/* - * sdb_memstore_con_matcher: - * Creates a matcher matching the conjunction (logical AND) of two matchers. - */ -sdb_memstore_matcher_t * -sdb_memstore_con_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right); - -/* - * sdb_memstore_inv_matcher: - * Creates a matcher matching the inverse (logical NOT) of a matcher. - */ -sdb_memstore_matcher_t * -sdb_memstore_inv_matcher(sdb_memstore_matcher_t *m); - -/* - * sdb_memstore_any_matcher: - * Creates a matcher iterating over values of the first expression (which has - * to be iterable). It matches if *any* of those elements match 'm'. 'm' has - * to be an ary operation with the left operand unset. - */ -sdb_memstore_matcher_t * -sdb_memstore_any_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m); - -/* - * sdb_memstore_all_matcher: - * Creates a matcher iterating over values of the first expression (which has - * to be iterable). It matches if *all* of those elements match 'm'. 'm' has - * to be an ary operation with the left operand unset. - */ -sdb_memstore_matcher_t * -sdb_memstore_all_matcher(sdb_memstore_expr_t *iter, sdb_memstore_matcher_t *m); - -/* - * sdb_memstore_in_matcher: - * Creates a matcher which matches if the right value evaluates to an array - * value and the left value is included in that array. See sdb_data_inarray - * for more details. - */ -sdb_memstore_matcher_t * -sdb_memstore_in_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); - -/* - * sdb_memstore_lt_matcher, sdb_memstore_le_matcher, sdb_memstore_eq_matcher, - * sdb_memstore_ge_matcher, sdb_memstore_gt_matcher: - * Create conditional matchers comparing the values of two expressions. The - * matcher matches if the left expression compres less than, less or equal - * than, equal to, not equal to, greater or equal than, or greater than the - * right expression. - */ -sdb_memstore_matcher_t * -sdb_memstore_lt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); -sdb_memstore_matcher_t * -sdb_memstore_le_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); -sdb_memstore_matcher_t * -sdb_memstore_eq_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); -sdb_memstore_matcher_t * -sdb_memstore_ne_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); -sdb_memstore_matcher_t * -sdb_memstore_ge_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); -sdb_memstore_matcher_t * -sdb_memstore_gt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); - -/* - * sdb_memstore_regex_matcher: - * Creates a matcher which matches the string value the left expression - * evaluates to against the regular expression the right expression evaluates - * to. The right expression may either be a constant value regular expression - * or string or a dynamic value evaluating to a string. In the latter case, - * the string is compiled to a regex every time the matcher is executed. - */ -sdb_memstore_matcher_t * -sdb_memstore_regex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); - -/* - * sdb_memstore_nregex_matcher: - * Creates a regex matcher just like sdb_memstore_regex_matcher except that it - * matches in case the regular expression does not match. - */ -sdb_memstore_matcher_t * -sdb_memstore_nregex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right); - -/* - * sdb_memstore_isnull_matcher: - * Creates a matcher matching NULL values. - */ -sdb_memstore_matcher_t * -sdb_memstore_isnull_matcher(sdb_memstore_expr_t *expr); - -/* - * sdb_memstore_istrue_matcher, sdb_memstore_isfalse_matcher: - * Creates a matcher matching boolean values. - */ -sdb_memstore_matcher_t * -sdb_memstore_istrue_matcher(sdb_memstore_expr_t *expr); -sdb_memstore_matcher_t * -sdb_memstore_isfalse_matcher(sdb_memstore_expr_t *expr); - -/* - * sdb_memstore_matcher_matches: - * Check whether the specified matcher matches the specified store object. If - * specified, the filter will be used to preselect objects for further - * evaluation. It is applied to any object that's used during the evaluation - * of the matcher. Only those objects matching the filter will be considered. - * - * Note that the filter is applied to all object types (hosts, service, - * metric, attribute). Thus, any object-specific matchers are mostly unsuited - * for this purpose and, if used, may result in unexpected behavior. - * - * Returns: - * - 1 if the object matches - * - 0 else - */ -int -sdb_memstore_matcher_matches(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, - sdb_memstore_matcher_t *filter); - -/* - * sdb_memstore_matcher_op_cb: - * Callback constructing a matcher operator. - */ -typedef sdb_memstore_matcher_t *(*sdb_memstore_matcher_op_cb) - (sdb_memstore_expr_t *, sdb_memstore_expr_t *); - -/* - * sdb_memstore_lookup_cb: - * Lookup callback. It is called for each matching object when looking up data - * in the store passing on the lookup filter and the specified user-data. The - * lookup aborts early if the callback returns non-zero. - */ -typedef int (*sdb_memstore_lookup_cb)(sdb_memstore_obj_t *obj, - sdb_memstore_matcher_t *filter, void *user_data); - -/* - * sdb_memstore_scan: - * Look up objects of the specified type in the specified store. The specified - * callback function is called for each object in the store matching 'm'. The - * function performs a full scan of all stored objects. If specified, the - * filter will be used to preselect objects for further evaluation. See the - * description of 'sdb_memstore_matcher_matches' for details. - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_memstore_scan(sdb_memstore_t *store, int type, - sdb_memstore_matcher_t *m, sdb_memstore_matcher_t *filter, - sdb_memstore_lookup_cb cb, void *user_data); - /* * Flags for JSON formatting. */ @@ -717,42 +260,6 @@ enum { sdb_store_json_formatter_t * sdb_store_json_formatter(sdb_strbuf_t *buf, int type, int flags); -/* - * sdb_memstore_emit: - * Serialize a single object to JSON adding it to the string buffer associated - * with the formatter object. The serialized object will not include - * attributes or any child objects. Instead, call the function again for each - * of those objects. All attributes have to be emitted before any other - * children types. Use sdb_memstore_emit_full() to emit a full (filtered) object. - * - * Note that the output might not be valid JSON before calling - * sdb_store_json_finish(). - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_memstore_emit(sdb_memstore_obj_t *obj, sdb_store_writer_t *w, sdb_object_t *wd); - -/* - * sdb_memstore_emit_full: - * Serialize a single object including it's attributes and all children to - * JSON, adding it to the string buffer associated with the formatter object. - * The filter, if specified, is applied to each attribute and child object. - * Only matching objects will be included in the output. - * - * Note that the output might not be valid JSON before calling - * sdb_store_json_finish(). - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_memstore_emit_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, - sdb_store_writer_t *w, sdb_object_t *wd); - /* * sdb_store_json_finish: * Finish the JSON output. This function has to be called once after emiting diff --git a/src/plugins/store/memory.c b/src/plugins/store/memory.c index 67a795b..703696f 100644 --- a/src/plugins/store/memory.c +++ b/src/plugins/store/memory.c @@ -31,6 +31,7 @@ #include "sysdb.h" #include "core/plugin.h" +#include "core/memstore.h" #include "core/store.h" #include "utils/error.h" diff --git a/t/unit/core/store_expr_test.c b/t/unit/core/store_expr_test.c index 04dfc8b..1bf560e 100644 --- a/t/unit/core/store_expr_test.c +++ b/t/unit/core/store_expr_test.c @@ -30,7 +30,7 @@ #endif #include "core/store.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "parser/parser.h" #include "testutils.h" diff --git a/t/unit/core/store_json_test.c b/t/unit/core/store_json_test.c index 40548c0..461c583 100644 --- a/t/unit/core/store_json_test.c +++ b/t/unit/core/store_json_test.c @@ -29,6 +29,7 @@ # include "config.h" #endif +#include "core/memstore.h" #include "core/store.h" #include "testutils.h" diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index ef0900e..0c99ee1 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -31,7 +31,7 @@ #include "core/plugin.h" #include "core/store.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "parser/parser.h" #include "testutils.h" diff --git a/t/unit/core/store_test.c b/t/unit/core/store_test.c index 5299a31..9445c64 100644 --- a/t/unit/core/store_test.c +++ b/t/unit/core/store_test.c @@ -31,7 +31,7 @@ #include "core/plugin.h" #include "core/store.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "testutils.h" #include diff --git a/t/unit/frontend/query_test.c b/t/unit/frontend/query_test.c index d498ea0..52fd58a 100644 --- a/t/unit/frontend/query_test.c +++ b/t/unit/frontend/query_test.c @@ -29,6 +29,7 @@ # include "config.h" #endif +#include "core/memstore.h" #include "core/plugin.h" #include "frontend/connection.h" #include "frontend/connection-private.h" diff --git a/t/unit/parser/parser_test.c b/t/unit/parser/parser_test.c index 83a5845..f6601f1 100644 --- a/t/unit/parser/parser_test.c +++ b/t/unit/parser/parser_test.c @@ -31,7 +31,7 @@ #include "parser/parser.h" #include "core/object.h" -#include "core/store.h" +#include "core/memstore.h" #include "testutils.h" #include @@ -743,7 +743,7 @@ START_TEST(test_parse) /* TODO: this should move into front-end specific tests */ q = sdb_memstore_query_prepare(node); fail_unless(q != NULL, - "sdb_store_query_prepare(AST<%s>) = NULL; expected: ", + "sdb_memstore_query_prepare(AST<%s>) = NULL; expected: ", parse_data[_i].query); sdb_object_deref(SDB_OBJ(node)); -- 2.30.2