From: Sebastian Harl Date: Tue, 13 Oct 2015 19:30:13 +0000 (+0200) Subject: Merged branch 'master' of git://git.tokkee.org/sysdb. X-Git-Tag: sysdb-0.8.0~10 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=25bba5d07cafb9f1169d687bffb742dae6f77a8e;hp=78ea02850cbffccb0df63d77cd4e42238137e63f Merged branch 'master' of git://git.tokkee.org/sysdb. --- 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/memstore-private.h b/src/core/memstore-private.h new file mode 100644 index 0000000..cd0152d --- /dev/null +++ b/src/core/memstore-private.h @@ -0,0 +1,264 @@ +/* + * SysDB - src/core/memstore-private.h + * Copyright (C) 2012-2013 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. + */ + +/* + * private data structures used by the memstore module + */ + +#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" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * core types + */ + +struct sdb_memstore_obj { + sdb_object_t super; +#define _name super.name + + /* object type */ + int type; + + /* common meta information */ + sdb_time_t last_update; + sdb_time_t interval; /* moving average */ + char **backends; + size_t backends_num; + sdb_memstore_obj_t *parent; +}; +#define STORE_OBJ(obj) ((sdb_memstore_obj_t *)(obj)) +#define STORE_CONST_OBJ(obj) ((const sdb_memstore_obj_t *)(obj)) + +typedef struct { + sdb_memstore_obj_t super; + + sdb_data_t value; +} attr_t; +#define ATTR(obj) ((attr_t *)(obj)) +#define CONST_ATTR(obj) ((const attr_t *)(obj)) + +typedef struct { + sdb_memstore_obj_t super; + + sdb_avltree_t *attributes; +} service_t; +#define SVC(obj) ((service_t *)(obj)) +#define CONST_SVC(obj) ((const service_t *)(obj)) + +typedef struct { + sdb_memstore_obj_t super; + + sdb_avltree_t *attributes; + struct { + char *type; + char *id; + } store; +} metric_t; +#define METRIC(obj) ((metric_t *)(obj)) + +typedef struct { + sdb_memstore_obj_t super; + + sdb_avltree_t *services; + sdb_avltree_t *metrics; + sdb_avltree_t *attributes; +} host_t; +#define HOST(obj) ((host_t *)(obj)) +#define CONST_HOST(obj) ((const host_t *)(obj)) + +/* shortcuts for accessing service/host attributes */ +#define _last_update super.last_update +#define _interval super.interval + +/* + * querying + */ + +struct sdb_memstore_query { + sdb_object_t super; + sdb_ast_node_t *ast; + sdb_memstore_matcher_t *matcher; + sdb_memstore_matcher_t *filter; +}; +#define QUERY(m) ((sdb_memstore_query_t *)(m)) + +/* + * expressions + */ + +enum { + TYPED_EXPR = -3, /* obj type stored in data.data.integer */ + ATTR_VALUE = -2, /* attr name stored in data.data.string */ + FIELD_VALUE = -1, /* field type stored in data.data.integer */ + /* 0: const value (stored in data) */ + /* >0: operator id */ +}; + +struct sdb_memstore_expr { + sdb_object_t super; + + int type; /* see above */ + int data_type; + + sdb_memstore_expr_t *left; + sdb_memstore_expr_t *right; + + sdb_data_t data; +}; +#define CONST_EXPR(v) { SDB_OBJECT_INIT, 0, (v).type, NULL, NULL, (v) } +#define EXPR_TO_STRING(e) \ + (((e)->type == TYPED_EXPR) ? "" \ + : ((e)->type == ATTR_VALUE) ? "attribute" \ + : ((e)->type == FIELD_VALUE) ? SDB_FIELD_TO_NAME((e)->data.data.integer) \ + : ((e)->type == 0) ? "" \ + : ((e)->type > 0) ? SDB_DATA_OP_TO_STRING((e)->type) \ + : "") + +/* + * matchers + */ + +/* when adding to this, also update 'MATCHER_SYM' below and 'matchers' in + * memstore_lookup.c */ +enum { + MATCHER_OR, + MATCHER_AND, + MATCHER_NOT, + MATCHER_ANY, + MATCHER_ALL, + MATCHER_IN, + + /* unary operators */ + MATCHER_ISNULL, + MATCHER_ISTRUE, + MATCHER_ISFALSE, + + /* ary operators */ + MATCHER_LT, + MATCHER_LE, + MATCHER_EQ, + MATCHER_NE, + MATCHER_GE, + MATCHER_GT, + MATCHER_REGEX, + MATCHER_NREGEX, + + /* a generic query */ + MATCHER_QUERY, +}; + +#define MATCHER_SYM(t) \ + (((t) == MATCHER_OR) ? "OR" \ + : ((t) == MATCHER_AND) ? "AND" \ + : ((t) == MATCHER_NOT) ? "NOT" \ + : ((t) == MATCHER_ANY) ? "ANY" \ + : ((t) == MATCHER_ALL) ? "ALL" \ + : ((t) == MATCHER_IN) ? "IN" \ + : ((t) == MATCHER_ISNULL) ? "IS NULL" \ + : ((t) == MATCHER_ISTRUE) ? "IS TRUE" \ + : ((t) == MATCHER_ISFALSE) ? "IS FALSE" \ + : ((t) == MATCHER_LT) ? "<" \ + : ((t) == MATCHER_LE) ? "<=" \ + : ((t) == MATCHER_EQ) ? "=" \ + : ((t) == MATCHER_NE) ? "!=" \ + : ((t) == MATCHER_GE) ? ">=" \ + : ((t) == MATCHER_GT) ? ">" \ + : ((t) == MATCHER_REGEX) ? "=~" \ + : ((t) == MATCHER_NREGEX) ? "!~" \ + : ((t) == MATCHER_QUERY) ? "QUERY" \ + : "UNKNOWN") + +/* matcher base type */ +struct sdb_memstore_matcher { + sdb_object_t super; + /* type of the matcher */ + int type; +}; +#define M(m) ((sdb_memstore_matcher_t *)(m)) + +/* infix operator matcher */ +typedef struct { + sdb_memstore_matcher_t super; + + /* left and right hand operands */ + sdb_memstore_matcher_t *left; + sdb_memstore_matcher_t *right; +} op_matcher_t; +#define OP_M(m) ((op_matcher_t *)(m)) + +/* unary operator matcher */ +typedef struct { + sdb_memstore_matcher_t super; + + /* operand */ + sdb_memstore_matcher_t *op; +} uop_matcher_t; +#define UOP_M(m) ((uop_matcher_t *)(m)) + +/* iter matcher */ +typedef struct { + sdb_memstore_matcher_t super; + sdb_memstore_expr_t *iter; + sdb_memstore_matcher_t *m; +} iter_matcher_t; +#define ITER_M(m) ((iter_matcher_t *)(m)) + +/* compare operator matcher */ +typedef struct { + sdb_memstore_matcher_t super; + + /* left and right hand expressions */ + sdb_memstore_expr_t *left; + sdb_memstore_expr_t *right; +} cmp_matcher_t; +#define CMP_M(m) ((cmp_matcher_t *)(m)) + +typedef struct { + sdb_memstore_matcher_t super; + sdb_memstore_expr_t *expr; +} unary_matcher_t; +#define UNARY_M(m) ((unary_matcher_t *)(m)) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ! SDB_CORE_MEMSTORE_H */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/core/memstore.c b/src/core/memstore.c new file mode 100644 index 0000000..2449827 --- /dev/null +++ b/src/core/memstore.c @@ -0,0 +1,1085 @@ +/* + * SysDB - src/core/memstore.c + * Copyright (C) 2012-2013 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. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "sysdb.h" +#include "core/memstore-private.h" +#include "core/plugin.h" +#include "utils/avltree.h" +#include "utils/error.h" + +#include + +#include + +#include +#include +#include + +#include + +/* + * private types + */ + +struct sdb_memstore { + sdb_object_t super; + + /* hosts are the top-level entries and + * reference everything else */ + sdb_avltree_t *hosts; + pthread_rwlock_t host_lock; +}; + +/* internal representation of a to-be-stored object */ +typedef struct { + sdb_memstore_obj_t *parent; + sdb_avltree_t *parent_tree; + int type; + const char *name; + sdb_time_t last_update; + sdb_time_t interval; + const char * const *backends; + size_t backends_num; +} store_obj_t; +#define STORE_OBJ_INIT { NULL, NULL, 0, NULL, 0, 0, NULL, 0 } + +static sdb_type_t host_type; +static sdb_type_t service_type; +static sdb_type_t metric_type; +static sdb_type_t attribute_type; + +static int +store_init(sdb_object_t *obj, va_list __attribute__((unused)) ap) +{ + int err; + if (! (SDB_MEMSTORE(obj)->hosts = sdb_avltree_create())) + return -1; + if ((err = pthread_rwlock_init(&SDB_MEMSTORE(obj)->host_lock, + /* attr = */ NULL))) { + char errbuf[128]; + sdb_log(SDB_LOG_ERR, "memstore: Failed to initialize lock: %s", + sdb_strerror(err, errbuf, sizeof(errbuf))); + return -1; + } + return 0; +} /* store_init */ + +static void +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, "memstore: Failed to destroy lock: %s", + sdb_strerror(err, errbuf, sizeof(errbuf))); + return; + } + sdb_avltree_destroy(SDB_MEMSTORE(obj)->hosts); + SDB_MEMSTORE(obj)->hosts = NULL; +} /* store_destroy */ + +static int +store_obj_init(sdb_object_t *obj, va_list ap) +{ + sdb_memstore_obj_t *sobj = STORE_OBJ(obj); + sobj->type = va_arg(ap, int); + return 0; +} /* store_obj_init */ + +static void +store_obj_destroy(sdb_object_t *obj) +{ + sdb_memstore_obj_t *sobj = STORE_OBJ(obj); + size_t i; + + for (i = 0; i < sobj->backends_num; ++i) + free(sobj->backends[i]); + free(sobj->backends); + sobj->backends = NULL; + sobj->backends_num = 0; + + // We don't currently keep an extra reference for parent objects to + // avoid circular self-references which are not handled correctly by + // the ref-count base management layer. + //sdb_object_deref(SDB_OBJ(sobj->parent)); +} /* store_obj_destroy */ + +static int +host_init(sdb_object_t *obj, va_list ap) +{ + host_t *sobj = HOST(obj); + int ret; + + /* this will consume the first argument (type) of ap */ + ret = store_obj_init(obj, ap); + if (ret) + return ret; + + sobj->services = sdb_avltree_create(); + if (! sobj->services) + return -1; + sobj->metrics = sdb_avltree_create(); + if (! sobj->metrics) + return -1; + sobj->attributes = sdb_avltree_create(); + if (! sobj->attributes) + return -1; + return 0; +} /* host_init */ + +static void +host_destroy(sdb_object_t *obj) +{ + host_t *sobj = HOST(obj); + assert(obj); + + store_obj_destroy(obj); + + if (sobj->services) + sdb_avltree_destroy(sobj->services); + if (sobj->metrics) + sdb_avltree_destroy(sobj->metrics); + if (sobj->attributes) + sdb_avltree_destroy(sobj->attributes); +} /* host_destroy */ + +static int +service_init(sdb_object_t *obj, va_list ap) +{ + service_t *sobj = SVC(obj); + int ret; + + /* this will consume the first argument (type) of ap */ + ret = store_obj_init(obj, ap); + if (ret) + return ret; + + sobj->attributes = sdb_avltree_create(); + if (! sobj->attributes) + return -1; + return 0; +} /* service_init */ + +static void +service_destroy(sdb_object_t *obj) +{ + service_t *sobj = SVC(obj); + assert(obj); + + store_obj_destroy(obj); + + if (sobj->attributes) + sdb_avltree_destroy(sobj->attributes); +} /* service_destroy */ + +static int +metric_init(sdb_object_t *obj, va_list ap) +{ + metric_t *sobj = METRIC(obj); + int ret; + + /* this will consume the first argument (type) of ap */ + ret = store_obj_init(obj, ap); + if (ret) + return ret; + + sobj->attributes = sdb_avltree_create(); + if (! sobj->attributes) + return -1; + + sobj->store.type = sobj->store.id = NULL; + return 0; +} /* metric_init */ + +static void +metric_destroy(sdb_object_t *obj) +{ + metric_t *sobj = METRIC(obj); + assert(obj); + + store_obj_destroy(obj); + + if (sobj->attributes) + sdb_avltree_destroy(sobj->attributes); + + if (sobj->store.type) + free(sobj->store.type); + if (sobj->store.id) + free(sobj->store.id); +} /* metric_destroy */ + +static int +attr_init(sdb_object_t *obj, va_list ap) +{ + const sdb_data_t *value; + int ret; + + /* this will consume the first argument (type) of ap */ + ret = store_obj_init(obj, ap); + if (ret) + return ret; + value = va_arg(ap, const sdb_data_t *); + + if (value) + if (sdb_data_copy(&ATTR(obj)->value, value)) + return -1; + return 0; +} /* attr_init */ + +static void +attr_destroy(sdb_object_t *obj) +{ + assert(obj); + + store_obj_destroy(obj); + sdb_data_free_datum(&ATTR(obj)->value); +} /* attr_destroy */ + +static sdb_type_t store_type = { + /* size = */ sizeof(sdb_memstore_t), + /* init = */ store_init, + /* destroy = */ store_destroy, +}; + +static sdb_type_t host_type = { + /* size = */ sizeof(host_t), + /* init = */ host_init, + /* destroy = */ host_destroy +}; + +static sdb_type_t service_type = { + /* size = */ sizeof(service_t), + /* init = */ service_init, + /* destroy = */ service_destroy +}; + +static sdb_type_t metric_type = { + /* size = */ sizeof(metric_t), + /* init = */ metric_init, + /* destroy = */ metric_destroy +}; + +static sdb_type_t attribute_type = { + /* size = */ sizeof(attr_t), + /* init = */ attr_init, + /* destroy = */ attr_destroy +}; + +/* + * private helper functions + */ + +static int +record_backends(sdb_memstore_obj_t *obj, + const char * const *backends, size_t backends_num) +{ + char **tmp; + size_t i; + + for (i = 0; i < backends_num; i++) { + bool found = 0; + size_t j; + + for (j = 0; j < obj->backends_num; ++j) { + if (!strcasecmp(obj->backends[j], backends[i])) { + found = 1; + break; + } + } + if (found) + continue; + + tmp = realloc(obj->backends, + (obj->backends_num + 1) * sizeof(*obj->backends)); + if (! tmp) + return -1; + + obj->backends = tmp; + obj->backends[obj->backends_num] = strdup(backends[i]); + if (! obj->backends[obj->backends_num]) + return -1; + + ++obj->backends_num; + } + return 0; +} /* record_backends */ + +static int +store_obj(store_obj_t *obj, sdb_memstore_obj_t **updated_obj) +{ + sdb_memstore_obj_t *old, *new; + int status = 0; + + assert(obj->parent_tree); + + old = STORE_OBJ(sdb_avltree_lookup(obj->parent_tree, obj->name)); + if (old) { + new = old; + sdb_object_deref(SDB_OBJ(old)); + } + else { + if (obj->type == SDB_ATTRIBUTE) { + /* the value will be updated by the caller */ + new = STORE_OBJ(sdb_object_create(obj->name, attribute_type, + obj->type, NULL)); + } + else { + sdb_type_t t; + t = obj->type == SDB_HOST + ? host_type + : obj->type == SDB_SERVICE + ? service_type + : metric_type; + new = STORE_OBJ(sdb_object_create(obj->name, t, obj->type)); + } + + if (new) { + status = sdb_avltree_insert(obj->parent_tree, SDB_OBJ(new)); + + /* pass control to the tree or destroy in case of an error */ + sdb_object_deref(SDB_OBJ(new)); + } + else { + char errbuf[1024]; + 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; + } + } + + if (status < 0) + return status; + assert(new); + + new->last_update = obj->last_update; + new->interval = obj->interval; + + if (new->parent != obj->parent) { + // Avoid circular self-references which are not handled + // correctly by the ref-count based management layer. + //sdb_object_deref(SDB_OBJ(new->parent)); + //sdb_object_ref(SDB_OBJ(obj->parent)); + new->parent = obj->parent; + } + + if (updated_obj) + *updated_obj = new; + + if (record_backends(new, obj->backends, obj->backends_num)) + return -1; + return status; +} /* store_obj */ + +static int +store_metric_store(metric_t *metric, sdb_store_metric_t *m) +{ + char *type = metric->store.type; + char *id = metric->store.id; + + if ((! metric->store.type) || strcasecmp(metric->store.type, m->store.type)) { + if (! (type = strdup(m->store.type))) + return -1; + } + if ((! metric->store.id) || strcasecmp(metric->store.id, m->store.id)) { + if (! (id = strdup(m->store.id))) { + if (type != metric->store.type) + free(type); + return -1; + } + } + + if (type != metric->store.type) { + if (metric->store.type) + free(metric->store.type); + metric->store.type = type; + } + if (id != metric->store.id) { + if (metric->store.id) + free(metric->store.id); + metric->store.id = id; + } + return 0; +} /* store_metric_store */ + +/* The store's host_lock has to be acquired before calling this function. */ +static sdb_avltree_t * +get_host_children(host_t *host, int type) +{ + if ((type != SDB_SERVICE) && (type != SDB_METRIC) + && (type != SDB_ATTRIBUTE)) + return NULL; + + if (! host) + return NULL; + + if (type == SDB_ATTRIBUTE) + return host->attributes; + else if (type == SDB_METRIC) + return host->metrics; + else + return host->services; +} /* get_host_children */ + +static sdb_avltree_t * +get_obj_attrs(sdb_memstore_obj_t *obj) +{ + if (obj->type == SDB_HOST) + return HOST(obj)->attributes; + else if (obj->type == SDB_SERVICE) + return SVC(obj)->attributes; + else if (obj->type == SDB_METRIC) + return METRIC(obj)->attributes; + return NULL; +} /* get_obj_attrs */ + +/* + * store writer API + */ + +static int +store_attribute(sdb_store_attribute_t *attr, sdb_object_t *user_data) +{ + sdb_memstore_t *st = SDB_MEMSTORE(user_data); + store_obj_t obj = STORE_OBJ_INIT; + sdb_memstore_obj_t *new = NULL; + const char *hostname; + host_t *host; + + sdb_avltree_t *children = NULL; + int status = 0; + + if ((! attr) || (! attr->parent) || (! attr->key)) + return -1; + + hostname = attr->hostname; + if (attr->parent_type == SDB_HOST) + hostname = attr->parent; + if (! hostname) + return -1; + + pthread_rwlock_wrlock(&st->host_lock); + host = HOST(sdb_avltree_lookup(st->hosts, hostname)); + if (! host) { + sdb_log(SDB_LOG_ERR, "memstore: Failed to store attribute '%s' - " + "host '%s' not found", attr->key, hostname); + status = -1; + } + + switch (attr->parent_type) { + case SDB_HOST: + obj.parent = STORE_OBJ(host); + obj.parent_tree = get_host_children(host, SDB_ATTRIBUTE); + break; + case SDB_SERVICE: + case SDB_METRIC: + children = get_host_children(host, attr->parent_type); + break; + default: + status = -1; + break; + } + + if (children) { + obj.parent = STORE_OBJ(sdb_avltree_lookup(children, attr->parent)); + if (! obj.parent) { + 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); + status = -1; + } + else + obj.parent_tree = attr->parent_type == SDB_SERVICE + ? SVC(obj.parent)->attributes + : METRIC(obj.parent)->attributes; + } + + obj.type = SDB_ATTRIBUTE; + obj.name = attr->key; + obj.last_update = attr->last_update; + obj.interval = attr->interval; + obj.backends = attr->backends; + obj.backends_num = attr->backends_num; + if (! status) + status = store_obj(&obj, &new); + + if (! status) { + assert(new); + /* update the value if it changed */ + if (sdb_data_cmp(&ATTR(new)->value, &attr->value)) + if (sdb_data_copy(&ATTR(new)->value, &attr->value)) + status = -1; + } + + if (obj.parent != STORE_OBJ(host)) + sdb_object_deref(SDB_OBJ(obj.parent)); + sdb_object_deref(SDB_OBJ(host)); + pthread_rwlock_unlock(&st->host_lock); + + return status; +} /* store_attribute */ + +static int +store_host(sdb_store_host_t *host, sdb_object_t *user_data) +{ + sdb_memstore_t *st = SDB_MEMSTORE(user_data); + store_obj_t obj = { NULL, st->hosts, SDB_HOST, NULL, 0, 0, NULL, 0 }; + int status = 0; + + if ((! host) || (! host->name)) + return -1; + + obj.name = host->name; + obj.last_update = host->last_update; + obj.interval = host->interval; + obj.backends = host->backends; + obj.backends_num = host->backends_num; + pthread_rwlock_wrlock(&st->host_lock); + status = store_obj(&obj, NULL); + pthread_rwlock_unlock(&st->host_lock); + + return status; +} /* store_host */ + +static int +store_service(sdb_store_service_t *service, sdb_object_t *user_data) +{ + sdb_memstore_t *st = SDB_MEMSTORE(user_data); + store_obj_t obj = STORE_OBJ_INIT; + host_t *host; + + int status = 0; + + if ((! service) || (! service->hostname) || (! service->name)) + return -1; + + pthread_rwlock_wrlock(&st->host_lock); + host = HOST(sdb_avltree_lookup(st->hosts, service->hostname)); + obj.parent = STORE_OBJ(host); + obj.parent_tree = get_host_children(host, SDB_SERVICE); + obj.type = SDB_SERVICE; + if (! obj.parent_tree) { + sdb_log(SDB_LOG_ERR, "memstore: Failed to store service '%s' - " + "host '%s' not found", service->name, service->hostname); + status = -1; + } + + obj.name = service->name; + obj.last_update = service->last_update; + obj.interval = service->interval; + obj.backends = service->backends; + obj.backends_num = service->backends_num; + if (! status) + status = store_obj(&obj, NULL); + + sdb_object_deref(SDB_OBJ(host)); + pthread_rwlock_unlock(&st->host_lock); + return status; +} /* store_service */ + +static int +store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) +{ + sdb_memstore_t *st = SDB_MEMSTORE(user_data); + store_obj_t obj = STORE_OBJ_INIT; + sdb_memstore_obj_t *new = NULL; + host_t *host; + + int status = 0; + + if ((! metric) || (! metric->hostname) || (! metric->name)) + return -1; + + if ((metric->store.type != NULL) != (metric->store.id != NULL)) + return -1; + + pthread_rwlock_wrlock(&st->host_lock); + host = HOST(sdb_avltree_lookup(st->hosts, metric->hostname)); + obj.parent = STORE_OBJ(host); + obj.parent_tree = get_host_children(host, SDB_METRIC); + obj.type = SDB_METRIC; + if (! obj.parent_tree) { + sdb_log(SDB_LOG_ERR, "memstore: Failed to store metric '%s' - " + "host '%s' not found", metric->name, metric->hostname); + status = -1; + } + + obj.name = metric->name; + obj.last_update = metric->last_update; + obj.interval = metric->interval; + obj.backends = metric->backends; + obj.backends_num = metric->backends_num; + if (! status) + status = store_obj(&obj, &new); + sdb_object_deref(SDB_OBJ(host)); + + if (status) { + pthread_rwlock_unlock(&st->host_lock); + return status; + } + + assert(new); + if (metric->store.type && metric->store.id) + if (store_metric_store(METRIC(new), metric)) + status = -1; + pthread_rwlock_unlock(&st->host_lock); + return status; +} /* store_metric */ + +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, + sdb_object_t __attribute__((unused)) *user_data) +{ + return SDB_OBJ(sdb_memstore_query_prepare(ast)); +} /* prepare_query */ + +static int +execute_query(sdb_object_t *q, + sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, + sdb_object_t *user_data) +{ + return sdb_memstore_query_execute(SDB_MEMSTORE(user_data), + QUERY(q), w, wd, errbuf); +} /* execute_query */ + +sdb_store_reader_t sdb_memstore_reader = { + prepare_query, execute_query, +}; + +/* + * public API + */ + +sdb_memstore_t * +sdb_memstore_create(void) +{ + return SDB_MEMSTORE(sdb_object_create("memstore", store_type)); +} /* sdb_memstore_create */ + +int +sdb_memstore_host(sdb_memstore_t *store, const char *name, + sdb_time_t last_update, sdb_time_t interval) +{ + sdb_store_host_t host = { + name, last_update, interval, NULL, 0, + }; + return store_host(&host, SDB_OBJ(store)); +} /* sdb_memstore_host */ + +int +sdb_memstore_service(sdb_memstore_t *store, const char *hostname, const char *name, + sdb_time_t last_update, sdb_time_t interval) +{ + sdb_store_service_t service = { + hostname, name, last_update, interval, NULL, 0, + }; + return store_service(&service, SDB_OBJ(store)); +} /* sdb_memstore_service */ + +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, sdb_time_t interval) +{ + sdb_store_metric_t metric = { + hostname, name, { NULL, NULL }, last_update, interval, NULL, 0, + }; + if (metric_store) { + metric.store.type = metric_store->type; + metric.store.id = metric_store->id; + } + return store_metric(&metric, SDB_OBJ(store)); +} /* sdb_memstore_metric */ + +int +sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname, + const char *key, const sdb_data_t *value, + sdb_time_t last_update, sdb_time_t interval) +{ + sdb_store_attribute_t attr = { + NULL, SDB_HOST, hostname, key, SDB_DATA_INIT, + last_update, interval, NULL, 0, + }; + if (value) { + attr.value = *value; + } + return store_attribute(&attr, SDB_OBJ(store)); +} /* sdb_memstore_attribute */ + +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, sdb_time_t interval) +{ + sdb_store_attribute_t attr = { + hostname, SDB_SERVICE, service, key, SDB_DATA_INIT, + last_update, interval, NULL, 0, + }; + if (value) { + attr.value = *value; + } + return store_attribute(&attr, SDB_OBJ(store)); +} /* sdb_memstore_service_attr */ + +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_time_t interval) +{ + sdb_store_attribute_t attr = { + hostname, SDB_METRIC, metric, key, SDB_DATA_INIT, + last_update, interval, NULL, 0, + }; + if (value) { + attr.value = *value; + } + return store_attribute(&attr, SDB_OBJ(store)); +} /* sdb_memstore_metric_attr */ + +sdb_memstore_obj_t * +sdb_memstore_get_host(sdb_memstore_t *store, const char *name) +{ + host_t *host; + + if ((! store) || (! name)) + return NULL; + + host = HOST(sdb_avltree_lookup(store->hosts, name)); + if (! host) + return NULL; + + return STORE_OBJ(host); +} /* sdb_memstore_get_host */ + +sdb_memstore_obj_t * +sdb_memstore_get_child(sdb_memstore_obj_t *obj, int type, const char *name) +{ + sdb_avltree_t *children = NULL; + + if ((! obj) || (! name)) + return NULL; + + if (type & SDB_ATTRIBUTE) + children = get_obj_attrs(obj); + else if (obj->type == SDB_HOST) + children = get_host_children(HOST(obj), type); + if (! children) + return NULL; + return STORE_OBJ(sdb_avltree_lookup(children, name)); +} /* sdb_memstore_get_child */ + +int +sdb_memstore_get_field(sdb_memstore_obj_t *obj, int field, sdb_data_t *res) +{ + sdb_data_t tmp; + + if (! obj) + return -1; + + switch (field) { + case SDB_FIELD_NAME: + tmp.type = SDB_TYPE_STRING; + tmp.data.string = strdup(SDB_OBJ(obj)->name); + if (! tmp.data.string) + return -1; + break; + case SDB_FIELD_LAST_UPDATE: + tmp.type = SDB_TYPE_DATETIME; + tmp.data.datetime = obj->last_update; + break; + case SDB_FIELD_AGE: + tmp.type = SDB_TYPE_DATETIME; + tmp.data.datetime = sdb_gettime() - obj->last_update; + break; + case SDB_FIELD_INTERVAL: + tmp.type = SDB_TYPE_DATETIME; + tmp.data.datetime = obj->interval; + break; + case SDB_FIELD_BACKEND: + if (! res) + return 0; + 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); + case SDB_FIELD_VALUE: + if (obj->type != SDB_ATTRIBUTE) + return -1; + if (! res) + return 0; + return sdb_data_copy(res, &ATTR(obj)->value); + case SDB_FIELD_TIMESERIES: + if (obj->type != SDB_METRIC) + return -1; + tmp.type = SDB_TYPE_BOOLEAN; + tmp.data.boolean = METRIC(obj)->store.type != NULL; + default: + return -1; + } + if (res) + *res = tmp; + else + sdb_data_free_datum(&tmp); + return 0; +} /* sdb_memstore_get_field */ + +int +sdb_memstore_get_attr(sdb_memstore_obj_t *obj, const char *name, sdb_data_t *res, + sdb_memstore_matcher_t *filter) +{ + sdb_memstore_obj_t *attr; + + if ((! obj) || (! name)) + return -1; + + attr = STORE_OBJ(sdb_avltree_lookup(get_obj_attrs(obj), name)); + if (! attr) + return -1; + if (filter && (! sdb_memstore_matcher_matches(filter, attr, NULL))) { + sdb_object_deref(SDB_OBJ(attr)); + 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_memstore_get_attr */ + +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_avltree_iter_t *host_iter = NULL; + int status = 0; + + if ((! store) || (! cb)) + return -1; + + if ((type != SDB_HOST) && (type != SDB_SERVICE) && (type != SDB_METRIC)) { + sdb_log(SDB_LOG_ERR, "memstore: Cannot scan objects of type %d", type); + return -1; + } + + pthread_rwlock_rdlock(&store->host_lock); + host_iter = sdb_avltree_get_iter(store->hosts); + if (! host_iter) + status = -1; + + /* has_next returns false if the iterator is NULL */ + while (sdb_avltree_iter_has_next(host_iter)) { + sdb_memstore_obj_t *host; + sdb_avltree_iter_t *iter = NULL; + + host = STORE_OBJ(sdb_avltree_iter_get_next(host_iter)); + assert(host); + + if (! sdb_memstore_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_memstore_obj_t *obj; + obj = STORE_OBJ(sdb_avltree_iter_get_next(iter)); + assert(obj); + + if (sdb_memstore_matcher_matches(m, obj, filter)) { + if (cb(obj, filter, user_data)) { + sdb_log(SDB_LOG_ERR, "memstore: Callback returned " + "an error while scanning"); + status = -1; + break; + } + } + } + } + else if (sdb_memstore_matcher_matches(m, host, filter)) { + if (cb(host, filter, user_data)) { + sdb_log(SDB_LOG_ERR, "memstore: 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(&store->host_lock); + 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/memstore_exec.c b/src/core/memstore_exec.c new file mode 100644 index 0000000..a489a66 --- /dev/null +++ b/src/core/memstore_exec.c @@ -0,0 +1,240 @@ +/* + * SysDB - src/core/memstore_exec.c + * Copyright (C) 2014-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. + */ + +#include "core/object.h" +#include "core/plugin.h" +#include "core/memstore-private.h" +#include "frontend/connection.h" +#include "parser/ast.h" +#include "utils/error.h" + +#include + +#include +#include +#include + +/* + * private helper functions + */ + +typedef struct { + sdb_memstore_obj_t *current_host; + + sdb_store_writer_t *w; + sdb_object_t *wd; +} iter_t; + +static int +maybe_emit_host(iter_t *iter, sdb_memstore_obj_t *obj) +{ + if ((obj->type == SDB_HOST) || (obj->type == SDB_ATTRIBUTE)) + return 0; + if (iter->current_host == obj->parent) + return 0; + iter->current_host = obj->parent; + return sdb_memstore_emit(obj->parent, iter->w, iter->wd); +} /* maybe_emit_host */ + +static int +list_tojson(sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t __attribute__((unused)) *filter, + void *user_data) +{ + iter_t *iter = user_data; + maybe_emit_host(iter, obj); + return sdb_memstore_emit(obj, iter->w, iter->wd); +} /* list_tojson */ + +static int +lookup_tojson(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, + void *user_data) +{ + iter_t *iter = user_data; + maybe_emit_host(iter, obj); + return sdb_memstore_emit_full(obj, filter, iter->w, iter->wd); +} /* lookup_tojson */ + +/* + * query implementations + */ + +static int +exec_fetch(sdb_memstore_t *store, + sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, + int type, const char *hostname, int parent_type, const char *parent, + const char *name, bool full, sdb_memstore_matcher_t *filter) +{ + sdb_memstore_obj_t *host, *p = NULL, *obj; + int status = 0; + + if (type == SDB_HOST) + hostname = name; + + host = sdb_memstore_get_host(store, hostname); + if ((! host) + || (filter && (! sdb_memstore_matcher_matches(filter, host, NULL)))) { + sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s: " + "host %s not found", SDB_STORE_TYPE_TO_NAME(type), + name, hostname); + sdb_object_deref(SDB_OBJ(host)); + return -1; + } + obj = host; + if (type != SDB_HOST) { + if (parent) { + p = sdb_memstore_get_child(obj, parent_type, parent); + if ((! p) || (filter + && (! sdb_memstore_matcher_matches(filter, p, NULL)))) { + sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s.%s.%s: " + "%s not found", SDB_STORE_TYPE_TO_NAME(type), + hostname, parent, name, parent); + status = -1; + } + obj = p; + } + if (! status) { + obj = sdb_memstore_get_child(obj, type, name); + if ((! obj) || (filter + && (! sdb_memstore_matcher_matches(filter, obj, NULL)))) { + sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s.%s: " + "%s not found", SDB_STORE_TYPE_TO_NAME(type), + hostname, name, name); + status = -1; + } + } + } + + if (! status) { + if (type != SDB_HOST) + status = sdb_memstore_emit(host, w, wd); + if ((! status) && parent) + status = sdb_memstore_emit(p, w, wd); + if (! status) { + if (full) + status = sdb_memstore_emit_full(obj, filter, w, wd); + else + status = sdb_memstore_emit(obj, w, wd); + } + if (status) { + 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"); + status = -1; + } + } + + if (host != obj) + sdb_object_deref(SDB_OBJ(host)); + if (p != obj) + sdb_object_deref(SDB_OBJ(p)); + sdb_object_deref(SDB_OBJ(obj)); + + if (status) + return status; + return SDB_CONNECTION_DATA; +} /* exec_fetch */ + +static int +exec_list(sdb_memstore_t *store, + sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, + int type, sdb_memstore_matcher_t *filter) +{ + iter_t iter = { NULL, w, wd }; + + if (sdb_memstore_scan(store, type, /* m = */ NULL, filter, list_tojson, &iter)) { + sdb_log(SDB_LOG_ERR, "memstore: Failed to serialize " + "store to JSON"); + sdb_strbuf_sprintf(errbuf, "Out of memory"); + return -1; + } + + return SDB_CONNECTION_DATA; +} /* exec_list */ + +static int +exec_lookup(sdb_memstore_t *store, + sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, + int type, sdb_memstore_matcher_t *m, sdb_memstore_matcher_t *filter) +{ + iter_t iter = { NULL, w, wd }; + + if (sdb_memstore_scan(store, type, m, filter, lookup_tojson, &iter)) { + 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)); + return -1; + } + + return SDB_CONNECTION_DATA; +} /* exec_lookup */ + +/* + * public API + */ + +int +sdb_memstore_query_execute(sdb_memstore_t *store, sdb_memstore_query_t *q, + sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf) +{ + sdb_ast_node_t *ast; + + if (! q) + return -1; + if (! q->ast) { + sdb_log(SDB_LOG_ERR, "memstore: Invalid empty query"); + return -1; + } + + ast = q->ast; + switch (ast->type) { + case SDB_AST_TYPE_FETCH: + return exec_fetch(store, w, wd, errbuf, + SDB_AST_FETCH(ast)->obj_type, SDB_AST_FETCH(ast)->hostname, + SDB_AST_FETCH(ast)->parent_type, SDB_AST_FETCH(ast)->parent, + SDB_AST_FETCH(ast)->name, SDB_AST_FETCH(ast)->full, q->filter); + + case SDB_AST_TYPE_LIST: + return exec_list(store, w, wd, errbuf, SDB_AST_LIST(ast)->obj_type, + q->filter); + + case SDB_AST_TYPE_LOOKUP: + return exec_lookup(store, w, wd, errbuf, SDB_AST_LOOKUP(ast)->obj_type, + q->matcher, q->filter); + + default: + sdb_log(SDB_LOG_ERR, "memstore: Invalid query of type %s", + SDB_AST_TYPE_TO_STRING(ast)); + return -1; + } + + return 0; +} /* sdb_memstore_query_execute */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/core/memstore_expr.c b/src/core/memstore_expr.c new file mode 100644 index 0000000..8335584 --- /dev/null +++ b/src/core/memstore_expr.c @@ -0,0 +1,464 @@ +/* + * SysDB - src/core/memstore_expr.c + * Copyright (C) 2014 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. + */ + +/* + * This module implements arithmetic and logical expressions for in-memory + * stores. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "sysdb.h" +#include "core/memstore-private.h" +#include "core/data.h" +#include "core/object.h" + +#include +#include +#include +#include + +/* + * private data types + */ + +/* iterate through either a list of child nodes or arrays */ +struct sdb_memstore_expr_iter { + sdb_memstore_obj_t *obj; + sdb_memstore_expr_t *expr; + + sdb_avltree_iter_t *tree; + + sdb_data_t array; + size_t array_idx; + bool free_array; + + sdb_memstore_matcher_t *filter; +}; + +/* + * private types + */ + +static int +expr_init(sdb_object_t *obj, va_list ap) +{ + int type = va_arg(ap, int); + sdb_memstore_expr_t *left = va_arg(ap, sdb_memstore_expr_t *); + sdb_memstore_expr_t *right = va_arg(ap, sdb_memstore_expr_t *); + const sdb_data_t *value = va_arg(ap, const sdb_data_t *); + + sdb_memstore_expr_t *expr = SDB_MEMSTORE_EXPR(obj); + + if (type <= 0) { + if (! value) + return -1; + if ((type == TYPED_EXPR) && (! left)) + return -1; + } else { + if (value) + return -1; + if ((! left) || (! right)) + return -1; + } + + if (value) + expr->data = *value; + + sdb_object_ref(SDB_OBJ(left)); + sdb_object_ref(SDB_OBJ(right)); + + expr->type = type; + expr->left = left; + expr->right = right; + + /* unknown for now */ + expr->data_type = -1; + return 0; +} /* expr_init */ + +static void +expr_destroy(sdb_object_t *obj) +{ + sdb_memstore_expr_t *expr = SDB_MEMSTORE_EXPR(obj); + sdb_object_deref(SDB_OBJ(expr->left)); + sdb_object_deref(SDB_OBJ(expr->right)); + + if (expr->data.type) + sdb_data_free_datum(&expr->data); +} /* expr_destroy */ + +static sdb_type_t expr_type = { + /* size = */ sizeof(sdb_memstore_expr_t), + /* init = */ expr_init, + /* destroy = */ expr_destroy, +}; + +/* + * public API + */ + +sdb_memstore_expr_t * +sdb_memstore_expr_create(int op, sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + sdb_data_t value = SDB_DATA_INIT; + sdb_memstore_expr_t *e; + + if ((op < 0) || (SDB_DATA_CONCAT < op) || (! left) || (! right)) + return NULL; + + if (left->type || right->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; + } + /* else: both expressions are constant values; evaluate now */ + + if (sdb_data_expr_eval(op, &left->data, &right->data, &value)) + return NULL; + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-constvalue", expr_type, + 0, NULL, NULL, &value)); + e->data_type = value.type; + return e; +} /* sdb_memstore_expr_create */ + +sdb_memstore_expr_t * +sdb_memstore_expr_typed(int typ, sdb_memstore_expr_t *expr) +{ + sdb_data_t value = { SDB_TYPE_INTEGER, { .integer = typ } }; + sdb_memstore_expr_t *e; + + if ((typ < SDB_HOST) || (SDB_ATTRIBUTE < typ)) + return NULL; + + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-typedexpr", expr_type, + TYPED_EXPR, expr, NULL, &value)); + e->data_type = expr->data_type; + return e; +} /* sdb_memstore_expr_typed */ + +sdb_memstore_expr_t * +sdb_memstore_expr_fieldvalue(int field) +{ + sdb_data_t value = { SDB_TYPE_INTEGER, { .integer = field } }; + sdb_memstore_expr_t *e; + + if ((field < SDB_FIELD_NAME) || (SDB_FIELD_TIMESERIES < field)) + return NULL; + 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; +} /* sdb_memstore_expr_fieldvalue */ + +sdb_memstore_expr_t * +sdb_memstore_expr_attrvalue(const char *name) +{ + sdb_data_t value = { SDB_TYPE_STRING, { .string = NULL} }; + sdb_memstore_expr_t *expr; + + value.data.string = strdup(name); + if (! value.data.string) + return NULL; + + expr = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-attrvalue", expr_type, + ATTR_VALUE, NULL, NULL, &value)); + if (! expr) + free(value.data.string); + expr->data_type = -1; + return expr; +} /* sdb_memstore_expr_attrvalue */ + +sdb_memstore_expr_t * +sdb_memstore_expr_constvalue(const sdb_data_t *value) +{ + sdb_data_t data = SDB_DATA_INIT; + sdb_memstore_expr_t *e; + + if (sdb_data_copy(&data, value)) + return NULL; + e = SDB_MEMSTORE_EXPR(sdb_object_create("memstore-constvalue", expr_type, + 0, NULL, NULL, &data)); + e->data_type = data.type; + return e; +} /* sdb_memstore_expr_constvalue */ + +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_data_t v1 = SDB_DATA_INIT, v2 = SDB_DATA_INIT; + int status = 0; + + if ((! expr) || (! res)) + return -1; + + if (filter && obj && (! sdb_memstore_matcher_matches(filter, obj, NULL))) + obj = NULL; /* this object does not exist */ + + if (! expr->type) + return sdb_data_copy(res, &expr->data); + else if (expr->type == FIELD_VALUE) + return sdb_memstore_get_field(obj, (int)expr->data.data.integer, res); + else if (expr->type == ATTR_VALUE) { + status = sdb_memstore_get_attr(obj, expr->data.data.string, res, filter); + if ((status < 0) && obj) { + /* attribute does not exist => NULL */ + status = 0; + res->type = SDB_TYPE_STRING; + res->data.string = NULL; + } + return status; + } + else if (expr->type == TYPED_EXPR) { + int typ = (int)expr->data.data.integer; + if (typ != obj->type) { + /* we support self-references and { service, metric } -> host */ + if ((typ != SDB_HOST) + || ((obj->type != SDB_SERVICE) + && (obj->type != SDB_METRIC))) + return -1; + obj = obj->parent; + } + return sdb_memstore_expr_eval(expr->left, obj, res, filter); + } + + if (sdb_memstore_expr_eval(expr->left, obj, &v1, filter)) + return -1; + if (sdb_memstore_expr_eval(expr->right, obj, &v2, filter)) { + sdb_data_free_datum(&v1); + return -1; + } + + if (sdb_data_expr_eval(expr->type, &v1, &v2, res)) + status = -1; + sdb_data_free_datum(&v1); + sdb_data_free_datum(&v2); + return status; +} /* sdb_memstore_expr_eval */ + +sdb_memstore_expr_iter_t * +sdb_memstore_expr_iter(sdb_memstore_expr_t *expr, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + sdb_memstore_expr_iter_t *iter; + sdb_avltree_iter_t *tree = NULL; + sdb_data_t array = SDB_DATA_INIT; + bool free_array = 0; + + if (! expr) + return NULL; + + while (expr->type == TYPED_EXPR) { + int type = (int)expr->data.data.integer; + + if (obj->type == type) { + /* self reference */ + } + else if ((type == SDB_HOST) + && ((obj->type == SDB_SERVICE) + || (obj->type == SDB_METRIC))) { + /* reference to parent host */ + obj = obj->parent; + } + else + break; + expr = expr->left; + } + + if (expr->type == TYPED_EXPR) { + if (! obj) + return NULL; + if (obj->type == SDB_HOST) { + if (expr->data.data.integer == SDB_SERVICE) + tree = sdb_avltree_get_iter(HOST(obj)->services); + else if (expr->data.data.integer == SDB_METRIC) + tree = sdb_avltree_get_iter(HOST(obj)->metrics); + else if (expr->data.data.integer == SDB_ATTRIBUTE) + tree = sdb_avltree_get_iter(HOST(obj)->attributes); + } + else if (obj->type == SDB_SERVICE) { + if (expr->data.data.integer == SDB_ATTRIBUTE) + tree = sdb_avltree_get_iter(SVC(obj)->attributes); + } + else if (obj->type == SDB_METRIC) { + if (expr->data.data.integer == SDB_ATTRIBUTE) + tree = sdb_avltree_get_iter(METRIC(obj)->attributes); + } + } + else if (expr->type == FIELD_VALUE) { + if (! obj) + return NULL; + if (expr->data.data.integer == SDB_FIELD_BACKEND) { + /* while scanning the store, we hold a read lock, so it's safe to + * access the data without copying */ + array.type = SDB_TYPE_ARRAY | SDB_TYPE_STRING; + array.data.array.length = obj->backends_num; + array.data.array.values = obj->backends; + } + } + else if (! expr->type) { + if (expr->data.type & SDB_TYPE_ARRAY) + array = expr->data; + } + else { + sdb_data_t value = SDB_DATA_INIT; + if (sdb_memstore_expr_eval(expr, obj, &value, filter)) + return NULL; + if (! (value.type & SDB_TYPE_ARRAY)) { + sdb_data_free_datum(&value); + return NULL; + } + array = value; + free_array = 1; + } + + if ((! tree) && (array.type == SDB_TYPE_NULL)) + return NULL; + + iter = calloc(1, sizeof(*iter)); + if (! iter) { + if (free_array) + sdb_data_free_datum(&array); + return NULL; + } + + sdb_object_ref(SDB_OBJ(obj)); + sdb_object_ref(SDB_OBJ(expr)); + sdb_object_ref(SDB_OBJ(filter)); + + iter->obj = obj; + iter->expr = expr; + iter->tree = tree; + iter->array = array; + iter->free_array = free_array; + iter->filter = filter; + return iter; +} /* sdb_memstore_expr_iter */ + +void +sdb_memstore_expr_iter_destroy(sdb_memstore_expr_iter_t *iter) +{ + sdb_data_t null = SDB_DATA_INIT; + + if (! iter) + return; + + if (iter->tree) + sdb_avltree_iter_destroy(iter->tree); + iter->tree = NULL; + + if (iter->free_array) + sdb_data_free_datum(&iter->array); + iter->array = null; + iter->array_idx = 0; + + sdb_object_deref(SDB_OBJ(iter->obj)); + sdb_object_deref(SDB_OBJ(iter->expr)); + sdb_object_deref(SDB_OBJ(iter->filter)); + free(iter); +} /* sdb_memstore_expr_iter_destroy */ + +bool +sdb_memstore_expr_iter_has_next(sdb_memstore_expr_iter_t *iter) +{ + if (! iter) + return 0; + + if (iter->tree) { + /* this function may be called before get_next, + * so we'll have to apply filters here as well */ + if (iter->filter) { + sdb_memstore_obj_t *child; + while ((child = STORE_OBJ(sdb_avltree_iter_peek_next(iter->tree)))) { + if (sdb_memstore_matcher_matches(iter->filter, child, NULL)) + break; + (void)sdb_avltree_iter_get_next(iter->tree); + } + } + + return sdb_avltree_iter_has_next(iter->tree); + } + + return iter->array_idx < iter->array.data.array.length; +} /* sdb_memstore_expr_iter_has_next */ + +sdb_data_t +sdb_memstore_expr_iter_get_next(sdb_memstore_expr_iter_t *iter) +{ + sdb_data_t null = SDB_DATA_INIT; + sdb_data_t ret = SDB_DATA_INIT; + sdb_data_t tmp = SDB_DATA_INIT; + + if (! iter) + return null; + + if (iter->tree) { + sdb_memstore_obj_t *child; + + while (42) { + child = STORE_OBJ(sdb_avltree_iter_get_next(iter->tree)); + if (! child) + break; + if (iter->filter + && (! sdb_memstore_matcher_matches(iter->filter, child, NULL))) + continue; + + if (sdb_memstore_expr_eval(iter->expr, child, &ret, iter->filter)) + return null; + break; + } + + /* Skip over any filtered objects */ + if (iter->filter) { + while ((child = STORE_OBJ(sdb_avltree_iter_peek_next(iter->tree)))) { + if (sdb_memstore_matcher_matches(iter->filter, child, NULL)) + break; + (void)sdb_avltree_iter_get_next(iter->tree); + } + } + + return ret; + } + + if (iter->array_idx >= iter->array.data.array.length) + return null; + + ++iter->array_idx; + if (sdb_data_array_get(&iter->array, iter->array_idx - 1, &ret)) + return null; + if (sdb_data_copy(&tmp, &ret)) + return null; + ret = tmp; + return ret; +} /* sdb_memstore_expr_iter_get_next */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/core/memstore_lookup.c b/src/core/memstore_lookup.c new file mode 100644 index 0000000..2752a66 --- /dev/null +++ b/src/core/memstore_lookup.c @@ -0,0 +1,694 @@ +/* + * SysDB - src/core/memstore_lookup.c + * Copyright (C) 2014 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. + */ + +/* + * This module implements operators which may be used to select contents of + * the store by matching various attributes of the stored objects. For now, a + * simple full table scan is supported only. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "sysdb.h" +#include "core/memstore-private.h" +#include "core/object.h" +#include "utils/error.h" + +#include + +#include +#include + +#include +#include + +#include + +static int +expr_eval2(sdb_memstore_expr_t *e1, sdb_data_t *v1, + sdb_memstore_expr_t *e2, sdb_data_t *v2, + sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter) +{ + if (e1->type) { + if (sdb_memstore_expr_eval(e1, obj, v1, filter)) + return -1; + } + else + *v1 = e1->data; + if (e2->type) { + if (sdb_memstore_expr_eval(e2, obj, v2, filter)) { + if (e1->type) + sdb_data_free_datum(v1); + return -1; + } + } + else + *v2 = e2->data; + return 0; +} /* expr_eval2 */ + +static void +expr_free_datum2(sdb_memstore_expr_t *e1, sdb_data_t *v1, + sdb_memstore_expr_t *e2, sdb_data_t *v2) +{ + if (e1->type) + sdb_data_free_datum(v1); + if (e2->type) + sdb_data_free_datum(v2); +} /* expr_free_datum2 */ + +/* + * matcher implementations + */ + +/* + * cmp_expr: + * Compare two values using the specified matcher operator. If strcmp_fallback + * is enabled, compare the string values in case of a type mismatch. + */ +static int +match_cmp_value(int op, sdb_data_t *v1, sdb_data_t *v2, bool strcmp_fallback) +{ + int status; + + if (sdb_data_isnull(v1) || (sdb_data_isnull(v2))) + status = INT_MAX; + else if (v1->type == v2->type) + status = sdb_data_cmp(v1, v2); + else if (! strcmp_fallback) + status = INT_MAX; + else + status = sdb_data_strcmp(v1, v2); + + if (status == INT_MAX) + return 0; + switch (op) { + case MATCHER_LT: return status < 0; + case MATCHER_LE: return status <= 0; + case MATCHER_EQ: return status == 0; + case MATCHER_NE: return status != 0; + case MATCHER_GE: return status >= 0; + case MATCHER_GT: return status > 0; + } + return 0; +} /* match_cmp_value */ + +static int +match_regex_value(int op, sdb_data_t *v, sdb_data_t *re) +{ + char value[sdb_data_strlen(v) + 1]; + int status = 0; + + assert((op == MATCHER_REGEX) + || (op == MATCHER_NREGEX)); + + if (sdb_data_isnull(v) || sdb_data_isnull(re)) + return 0; + + if (re->type == SDB_TYPE_STRING) { + sdb_data_t tmp = SDB_DATA_INIT; + + if (sdb_data_parse(re->data.string, SDB_TYPE_REGEX, &tmp)) + return 0; + + sdb_data_free_datum(re); + *re = tmp; + } + else if (re->type != SDB_TYPE_REGEX) + return 0; + + if (! sdb_data_format(v, value, sizeof(value), SDB_UNQUOTED)) + status = 0; + else if (! regexec(&re->data.re.regex, value, 0, NULL, 0)) + status = 1; + + if (op == MATCHER_NREGEX) + return !status; + return status; +} /* match_regex_value */ + +static int +match_logical(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + int status; + + assert((m->type == MATCHER_AND) || (m->type == MATCHER_OR)); + assert(OP_M(m)->left && OP_M(m)->right); + + status = sdb_memstore_matcher_matches(OP_M(m)->left, obj, filter); + + /* lazy evaluation */ + if ((! status) && (m->type == MATCHER_AND)) + return status; + else if (status && (m->type == MATCHER_OR)) + return status; + + return sdb_memstore_matcher_matches(OP_M(m)->right, obj, filter); +} /* match_logical */ + +static int +match_uop(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + assert(m->type == MATCHER_NOT); + assert(UOP_M(m)->op); + + return !sdb_memstore_matcher_matches(UOP_M(m)->op, obj, filter); +} /* match_uop */ + +/* iterate: ANY/ALL */ +static int +match_iter(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + sdb_memstore_expr_iter_t *iter = NULL; + int status; + int all = (int)(m->type == MATCHER_ALL); + + assert((m->type == MATCHER_ANY) || (m->type == MATCHER_ALL)); + assert((! CMP_M(ITER_M(m)->m)->left) && CMP_M(ITER_M(m)->m)->right); + + iter = sdb_memstore_expr_iter(ITER_M(m)->iter, obj, filter); + if (! iter) { + sdb_log(SDB_LOG_WARNING, "memstore: Invalid iterator"); + return 0; + } + + status = all; + while (sdb_memstore_expr_iter_has_next(iter)) { + sdb_data_t v = sdb_memstore_expr_iter_get_next(iter); + sdb_memstore_expr_t expr = CONST_EXPR(v); + bool matches; + + CMP_M(ITER_M(m)->m)->left = &expr; + matches = sdb_memstore_matcher_matches(ITER_M(m)->m, obj, filter); + CMP_M(ITER_M(m)->m)->left = NULL; + sdb_data_free_datum(&v); + + if (matches) { + if (! all) { + status = 1; + break; + } + } else if (all) { + status = 0; + break; + } + } + sdb_memstore_expr_iter_destroy(iter); + return status; +} /* match_iter */ + +static int +match_cmp(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + sdb_memstore_expr_t *e1 = CMP_M(m)->left; + sdb_memstore_expr_t *e2 = CMP_M(m)->right; + sdb_data_t v1 = SDB_DATA_INIT, v2 = SDB_DATA_INIT; + int status; + + assert((m->type == MATCHER_LT) + || (m->type == MATCHER_LE) + || (m->type == MATCHER_EQ) + || (m->type == MATCHER_NE) + || (m->type == MATCHER_GE) + || (m->type == MATCHER_GT)); + assert(e1 && e2); + + if (expr_eval2(e1, &v1, e2, &v2, obj, filter)) + return 0; + + status = match_cmp_value(m->type, &v1, &v2, + (e1->data_type) < 0 || (e2->data_type < 0)); + + expr_free_datum2(e1, &v1, e2, &v2); + return status; +} /* match_cmp */ + +static int +match_in(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + sdb_data_t value = SDB_DATA_INIT, array = SDB_DATA_INIT; + int status = 1; + + assert(m->type == MATCHER_IN); + assert(CMP_M(m)->left && CMP_M(m)->right); + + if (expr_eval2(CMP_M(m)->left, &value, + CMP_M(m)->right, &array, obj, filter)) + status = 0; + + if (status) + status = sdb_data_inarray(&value, &array); + + expr_free_datum2(CMP_M(m)->left, &value, CMP_M(m)->right, &array); + return status; +} /* match_in */ + +static int +match_regex(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + sdb_data_t regex = SDB_DATA_INIT, v = SDB_DATA_INIT; + int status = 0; + + assert((m->type == MATCHER_REGEX) + || (m->type == MATCHER_NREGEX)); + assert(CMP_M(m)->left && CMP_M(m)->right); + + if (expr_eval2(CMP_M(m)->left, &v, CMP_M(m)->right, ®ex, obj, filter)) + return 0; + + status = match_regex_value(m->type, &v, ®ex); + + expr_free_datum2(CMP_M(m)->left, &v, CMP_M(m)->right, ®ex); + return status; +} /* match_regex */ + +static int +match_unary(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + sdb_data_t v = SDB_DATA_INIT; + int status; + + assert((m->type == MATCHER_ISNULL) + || (m->type == MATCHER_ISTRUE) + || (m->type == MATCHER_ISFALSE)); + + if (UNARY_M(m)->expr->type) { + /* TODO: this might hide real errors; + * improve error reporting and propagation */ + if (sdb_memstore_expr_eval(UNARY_M(m)->expr, obj, &v, filter)) + return 1; + } + else + v = UNARY_M(m)->expr->data; + + if (m->type == MATCHER_ISNULL) + status = sdb_data_isnull(&v) ? 1 : 0; + else { /* ISTRUE or ISFALSE */ + if ((v.type == SDB_TYPE_BOOLEAN) + && (v.data.boolean == (m->type == MATCHER_ISTRUE))) + status = 1; + else + status = 0; + } + + if (UNARY_M(m)->expr->type) + sdb_data_free_datum(&v); + return status; +} /* match_unary */ + +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 memstore-private.h when updating this */ +static matcher_cb +matchers[] = { + match_logical, + match_logical, + match_uop, + match_iter, + match_iter, + match_in, + + /* unary operators */ + match_unary, + match_unary, + match_unary, + + /* ary operators */ + match_cmp, + match_cmp, + match_cmp, + match_cmp, + match_cmp, + match_cmp, + match_regex, + match_regex, + + NULL, /* QUERY */ +}; + +/* + * private matcher types + */ + +static int +op_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + if ((M(obj)->type != MATCHER_OR) && (M(obj)->type != MATCHER_AND)) + return -1; + + OP_M(obj)->left = va_arg(ap, sdb_memstore_matcher_t *); + sdb_object_ref(SDB_OBJ(OP_M(obj)->left)); + OP_M(obj)->right = va_arg(ap, sdb_memstore_matcher_t *); + sdb_object_ref(SDB_OBJ(OP_M(obj)->right)); + + if ((! OP_M(obj)->left) || (! OP_M(obj)->right)) + return -1; + return 0; +} /* op_matcher_init */ + +static void +op_matcher_destroy(sdb_object_t *obj) +{ + if (OP_M(obj)->left) + sdb_object_deref(SDB_OBJ(OP_M(obj)->left)); + if (OP_M(obj)->right) + sdb_object_deref(SDB_OBJ(OP_M(obj)->right)); +} /* op_matcher_destroy */ + +static int +iter_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + ITER_M(obj)->iter = va_arg(ap, sdb_memstore_expr_t *); + ITER_M(obj)->m = va_arg(ap, sdb_memstore_matcher_t *); + + sdb_object_ref(SDB_OBJ(ITER_M(obj)->iter)); + sdb_object_ref(SDB_OBJ(ITER_M(obj)->m)); + + if ((! ITER_M(obj)->iter) || (! ITER_M(obj)->m)) + return -1; + return 0; +} /* iter_matcher_init */ + +static void +iter_matcher_destroy(sdb_object_t *obj) +{ + sdb_object_deref(SDB_OBJ(ITER_M(obj)->iter)); + sdb_object_deref(SDB_OBJ(ITER_M(obj)->m)); +} /* iter_matcher_destroy */ + +static int +cmp_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + + CMP_M(obj)->left = va_arg(ap, sdb_memstore_expr_t *); + sdb_object_ref(SDB_OBJ(CMP_M(obj)->left)); + CMP_M(obj)->right = va_arg(ap, sdb_memstore_expr_t *); + sdb_object_ref(SDB_OBJ(CMP_M(obj)->right)); + + if (! CMP_M(obj)->right) + return -1; + return 0; +} /* cmp_matcher_init */ + +static void +cmp_matcher_destroy(sdb_object_t *obj) +{ + sdb_object_deref(SDB_OBJ(CMP_M(obj)->left)); + sdb_object_deref(SDB_OBJ(CMP_M(obj)->right)); +} /* cmp_matcher_destroy */ + +static int +uop_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + if (M(obj)->type != MATCHER_NOT) + return -1; + + UOP_M(obj)->op = va_arg(ap, sdb_memstore_matcher_t *); + sdb_object_ref(SDB_OBJ(UOP_M(obj)->op)); + + if (! UOP_M(obj)->op) + return -1; + return 0; +} /* uop_matcher_init */ + +static void +uop_matcher_destroy(sdb_object_t *obj) +{ + if (UOP_M(obj)->op) + sdb_object_deref(SDB_OBJ(UOP_M(obj)->op)); +} /* uop_matcher_destroy */ + +static int +unary_matcher_init(sdb_object_t *obj, va_list ap) +{ + M(obj)->type = va_arg(ap, int); + if ((M(obj)->type != MATCHER_ISNULL) + && (M(obj)->type != MATCHER_ISTRUE) + && (M(obj)->type != MATCHER_ISFALSE)) + return -1; + + UNARY_M(obj)->expr = va_arg(ap, sdb_memstore_expr_t *); + sdb_object_ref(SDB_OBJ(UNARY_M(obj)->expr)); + return 0; +} /* unary_matcher_init */ + +static void +unary_matcher_destroy(sdb_object_t *obj) +{ + sdb_object_deref(SDB_OBJ(UNARY_M(obj)->expr)); + UNARY_M(obj)->expr = NULL; +} /* unary_matcher_destroy */ + +static sdb_type_t op_type = { + /* size = */ sizeof(op_matcher_t), + /* init = */ op_matcher_init, + /* destroy = */ op_matcher_destroy, +}; + +static sdb_type_t uop_type = { + /* size = */ sizeof(uop_matcher_t), + /* init = */ uop_matcher_init, + /* destroy = */ uop_matcher_destroy, +}; + +static sdb_type_t iter_type = { + /* size = */ sizeof(iter_matcher_t), + /* init = */ iter_matcher_init, + /* destroy = */ iter_matcher_destroy, +}; + +static sdb_type_t cmp_type = { + /* size = */ sizeof(cmp_matcher_t), + /* init = */ cmp_matcher_init, + /* destroy = */ cmp_matcher_destroy, +}; + +static sdb_type_t unary_type = { + /* size = */ sizeof(unary_matcher_t), + /* init = */ unary_matcher_init, + /* destroy = */ unary_matcher_destroy, +}; + +/* + * public API + */ + +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, "memstore: Invalid ANY -> %s matcher " + "(invalid operator)", MATCHER_SYM(m->type)); + return NULL; + } + if (CMP_M(m)->left) { + 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), + SDB_TYPE_TO_STRING(CMP_M(m)->right->data_type)); + return NULL; + } + return M(sdb_object_create("any-matcher", iter_type, + MATCHER_ANY, iter, m)); +} /* sdb_memstore_any_matcher */ + +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, "memstore: Invalid ALL -> %s matcher " + "(invalid operator)", MATCHER_SYM(m->type)); + return NULL; + } + if (CMP_M(m)->left) { + 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), + SDB_TYPE_TO_STRING(CMP_M(m)->right->data_type)); + return NULL; + } + return M(sdb_object_create("all-matcher", iter_type, + MATCHER_ALL, iter, m)); +} /* sdb_memstore_all_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_lt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("lt-matcher", cmp_type, + MATCHER_LT, left, right)); +} /* sdb_memstore_lt_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_le_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("le-matcher", cmp_type, + MATCHER_LE, left, right)); +} /* sdb_memstore_le_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_eq_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("eq-matcher", cmp_type, + MATCHER_EQ, left, right)); +} /* sdb_memstore_eq_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_ne_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("ne-matcher", cmp_type, + MATCHER_NE, left, right)); +} /* sdb_memstore_ne_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_ge_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("ge-matcher", cmp_type, + MATCHER_GE, left, right)); +} /* sdb_memstore_ge_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_gt_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("gt-matcher", cmp_type, + MATCHER_GT, left, right)); +} /* sdb_memstore_gt_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_in_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + return M(sdb_object_create("in-matcher", cmp_type, + MATCHER_IN, left, right)); +} /* sdb_memstore_in_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_regex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + if (! right->type) { + if ((right->data.type != SDB_TYPE_STRING) + && (right->data.type != SDB_TYPE_REGEX)) + return NULL; + + if (right->data.type == SDB_TYPE_STRING) { + char *raw = right->data.data.string; + if (sdb_data_parse(raw, SDB_TYPE_REGEX, &right->data)) + return NULL; + free(raw); + } + } + return M(sdb_object_create("regex-matcher", cmp_type, + MATCHER_REGEX, left, right)); +} /* sdb_memstore_regex_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_nregex_matcher(sdb_memstore_expr_t *left, sdb_memstore_expr_t *right) +{ + sdb_memstore_matcher_t *m = sdb_memstore_regex_matcher(left, right); + if (! m) + return NULL; + m->type = MATCHER_NREGEX; + return m; +} /* sdb_memstore_nregex_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_isnull_matcher(sdb_memstore_expr_t *expr) +{ + return M(sdb_object_create("isnull-matcher", unary_type, + MATCHER_ISNULL, expr)); +} /* sdb_memstore_isnull_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_istrue_matcher(sdb_memstore_expr_t *expr) +{ + return M(sdb_object_create("istrue-matcher", unary_type, + MATCHER_ISTRUE, expr)); +} /* sdb_memstore_istrue_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_isfalse_matcher(sdb_memstore_expr_t *expr) +{ + return M(sdb_object_create("isfalse-matcher", unary_type, + MATCHER_ISFALSE, expr)); +} /* sdb_memstore_isfalse_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_dis_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right) +{ + return M(sdb_object_create("dis-matcher", op_type, MATCHER_OR, + left, right)); +} /* sdb_memstore_dis_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_con_matcher(sdb_memstore_matcher_t *left, sdb_memstore_matcher_t *right) +{ + return M(sdb_object_create("con-matcher", op_type, MATCHER_AND, + left, right)); +} /* sdb_memstore_con_matcher */ + +sdb_memstore_matcher_t * +sdb_memstore_inv_matcher(sdb_memstore_matcher_t *m) +{ + return M(sdb_object_create("inv-matcher", uop_type, MATCHER_NOT, m)); +} /* sdb_memstore_inv_matcher */ + +int +sdb_memstore_matcher_matches(sdb_memstore_matcher_t *m, sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t *filter) +{ + if (filter && (! sdb_memstore_matcher_matches(filter, obj, NULL))) + return 0; + + /* "NULL" always matches */ + if ((! m) || (! obj)) + return 1; + + if ((m->type < 0) || ((size_t)m->type >= SDB_STATIC_ARRAY_LEN(matchers))) + return 0; + + if (! matchers[m->type]) + return 0; + return matchers[m->type](m, obj, filter); +} /* sdb_memstore_matcher_matches */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/core/memstore_query.c b/src/core/memstore_query.c new file mode 100644 index 0000000..eb1e82f --- /dev/null +++ b/src/core/memstore_query.c @@ -0,0 +1,354 @@ +/* + * SysDB - src/core/memstore_query.c + * Copyright (C) 2014-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. + */ + +#include "core/object.h" +#include "core/memstore-private.h" +#include "parser/ast.h" +#include "utils/error.h" + +#include + +static sdb_memstore_matcher_t * +node_to_matcher(sdb_ast_node_t *n); + +static sdb_memstore_expr_t * +node_to_expr(sdb_ast_node_t *n) +{ + sdb_memstore_expr_t *left = NULL, *right = NULL; + sdb_memstore_expr_t *e; + int op; + + if (! n) { + 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, "memstore: Invalid arithmetic operator of " + "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); + return NULL; + } + + left = node_to_expr(SDB_AST_OP(n)->left); + if (! left) + return NULL; + right = node_to_expr(SDB_AST_OP(n)->right); + if (! right) { + sdb_object_deref(SDB_OBJ(left)); + return NULL; + } + op = SDB_AST_OP_TO_DATA_OP(SDB_AST_OP(n)->kind); + e = sdb_memstore_expr_create(op, left, right); + break; + + case SDB_AST_TYPE_CONST: + return sdb_memstore_expr_constvalue(&SDB_AST_CONST(n)->value); + + case SDB_AST_TYPE_VALUE: + if (SDB_AST_VALUE(n)->type == SDB_ATTRIBUTE) + return sdb_memstore_expr_attrvalue(SDB_AST_VALUE(n)->name); + return sdb_memstore_expr_fieldvalue(SDB_AST_VALUE(n)->type); + + case SDB_AST_TYPE_TYPED: + right = node_to_expr(SDB_AST_TYPED(n)->expr); + if (! right) + return NULL; + e = sdb_memstore_expr_typed(SDB_AST_TYPED(n)->type, right); + break; + + default: + sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)", + SDB_AST_TYPE_TO_STRING(n), n->type); + e = NULL; + } + + /* expressions take a reference */ + sdb_object_deref(SDB_OBJ(left)); + sdb_object_deref(SDB_OBJ(right)); + return e; +} /* node_to_expr */ + +static sdb_memstore_matcher_t * +logical_to_matcher(sdb_ast_node_t *n) +{ + sdb_memstore_matcher_t *left = NULL, *right; + sdb_memstore_matcher_t *m; + + if (SDB_AST_OP(n)->left) { + left = node_to_matcher(SDB_AST_OP(n)->left); + if (! left) + return NULL; + } + right = node_to_matcher(SDB_AST_OP(n)->right); + if (! right) { + sdb_object_deref(SDB_OBJ(left)); + return NULL; + } + + switch (SDB_AST_OP(n)->kind) { + case SDB_AST_AND: + m = sdb_memstore_con_matcher(left, right); + break; + case SDB_AST_OR: + m = sdb_memstore_dis_matcher(left, right); + break; + case SDB_AST_NOT: + m = sdb_memstore_inv_matcher(right); + break; + + default: + m = NULL; + } + + /* matchers take a reference */ + sdb_object_deref(SDB_OBJ(left)); + sdb_object_deref(SDB_OBJ(right)); + return m; +} /* logical_to_matcher */ + +static sdb_memstore_matcher_t * +cmp_to_matcher(sdb_ast_node_t *n) +{ + sdb_memstore_expr_t *left = NULL, *right; + sdb_memstore_matcher_t *m; + + if (SDB_AST_OP(n)->left) { + left = node_to_expr(SDB_AST_OP(n)->left); + if (! left) + return NULL; + } + right = node_to_expr(SDB_AST_OP(n)->right); + if (! right) { + sdb_object_deref(SDB_OBJ(left)); + return NULL; + } + + switch (SDB_AST_OP(n)->kind) { + case SDB_AST_LT: + m = sdb_memstore_lt_matcher(left, right); + break; + case SDB_AST_LE: + m = sdb_memstore_le_matcher(left, right); + break; + case SDB_AST_EQ: + m = sdb_memstore_eq_matcher(left, right); + break; + case SDB_AST_NE: + m = sdb_memstore_ne_matcher(left, right); + break; + case SDB_AST_GE: + m = sdb_memstore_ge_matcher(left, right); + break; + case SDB_AST_GT: + m = sdb_memstore_gt_matcher(left, right); + break; + case SDB_AST_REGEX: + m = sdb_memstore_regex_matcher(left, right); + break; + case SDB_AST_NREGEX: + m = sdb_memstore_nregex_matcher(left, right); + break; + case SDB_AST_ISNULL: + m = sdb_memstore_isnull_matcher(right); + break; + case SDB_AST_ISTRUE: + m = sdb_memstore_istrue_matcher(right); + break; + case SDB_AST_ISFALSE: + m = sdb_memstore_isfalse_matcher(right); + break; + case SDB_AST_IN: + m = sdb_memstore_in_matcher(left, right); + break; + + default: + sdb_log(SDB_LOG_ERR, "memstore: Invalid matcher node of type %s (%#x)", + SDB_AST_TYPE_TO_STRING(n), n->type); + m = NULL; + } + + /* matchers take a reference */ + sdb_object_deref(SDB_OBJ(left)); + sdb_object_deref(SDB_OBJ(right)); + return m; +} /* cmp_to_matcher */ + +static sdb_memstore_matcher_t * +iter_to_matcher(sdb_ast_node_t *n) +{ + sdb_memstore_expr_t *iter; + sdb_memstore_matcher_t *expr, *m; + + assert((SDB_AST_ITER(n)->expr->type == SDB_AST_TYPE_OPERATOR) + && (! SDB_AST_OP(SDB_AST_ITER(n)->expr)->left)); + + iter = node_to_expr(SDB_AST_ITER(n)->iter); + if (! iter) + return NULL; + expr = cmp_to_matcher(SDB_AST_ITER(n)->expr); + if (! expr) { + sdb_object_deref(SDB_OBJ(iter)); + return NULL; + } + + switch (SDB_AST_ITER(n)->kind) { + case SDB_AST_ALL: + m = sdb_memstore_all_matcher(iter, expr); + break; + case SDB_AST_ANY: + m = sdb_memstore_any_matcher(iter, expr); + break; + + default: + 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; + } + + /* matchers take a reference */ + sdb_object_deref(SDB_OBJ(iter)); + sdb_object_deref(SDB_OBJ(expr)); + return m; +} /* iter_to_matcher */ + +static sdb_memstore_matcher_t * +node_to_matcher(sdb_ast_node_t *n) +{ + int kind; + + if (! n) { + 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, "memstore: Invalid logical operator of " + "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); + return NULL; + } + + kind = SDB_AST_OP(n)->kind; + if ((kind == SDB_AST_AND) || (kind == SDB_AST_OR) || (kind == SDB_AST_NOT)) + return logical_to_matcher(n); + else + return cmp_to_matcher(n); + + case SDB_AST_TYPE_ITERATOR: + return iter_to_matcher(n); + } + + 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 */ + +/* + * query type + */ + +static int +query_init(sdb_object_t *obj, va_list ap) +{ + sdb_ast_node_t *ast = va_arg(ap, sdb_ast_node_t *); + sdb_ast_node_t *matcher = NULL, *filter = NULL; + + QUERY(obj)->ast = ast; + sdb_object_ref(SDB_OBJ(ast)); + + switch (ast->type) { + case SDB_AST_TYPE_FETCH: + filter = SDB_AST_FETCH(ast)->filter; + break; + case SDB_AST_TYPE_LIST: + filter = SDB_AST_LIST(ast)->filter; + break; + case SDB_AST_TYPE_LOOKUP: + matcher = SDB_AST_LOOKUP(ast)->matcher; + filter = SDB_AST_LOOKUP(ast)->filter; + break; + case SDB_AST_TYPE_STORE: + case SDB_AST_TYPE_TIMESERIES: + /* nothing to do */ + break; + + default: + sdb_log(SDB_LOG_ERR, "memstore: Invalid top-level AST node " + "of type %#x", ast->type); + return -1; + } + + if (matcher) { + QUERY(obj)->matcher = node_to_matcher(matcher); + if (! QUERY(obj)->matcher) + return -1; + } + if (filter) { + QUERY(obj)->filter = node_to_matcher(filter); + if (! QUERY(obj)->filter) + return -1; + } + + return 0; +} /* query_init */ + +static void +query_destroy(sdb_object_t *obj) +{ + sdb_object_deref(SDB_OBJ(QUERY(obj)->ast)); + sdb_object_deref(SDB_OBJ(QUERY(obj)->matcher)); + sdb_object_deref(SDB_OBJ(QUERY(obj)->filter)); +} /* query_destroy */ + +static sdb_type_t query_type = { + /* size = */ sizeof(sdb_memstore_query_t), + /* init = */ query_init, + /* destroy = */ query_destroy, +}; + +/* + * public API + */ + +sdb_memstore_query_t * +sdb_memstore_query_prepare(sdb_ast_node_t *ast) +{ + if (! ast) + return NULL; + return QUERY(sdb_object_create(SDB_AST_TYPE_TO_STRING(ast), query_type, ast)); +} /* sdb_memstore_query_prepare */ + +sdb_memstore_matcher_t * +sdb_memstore_query_prepare_matcher(sdb_ast_node_t *ast) +{ + return node_to_matcher(ast); +} /* sdb_memstore_query_prepare_matcher */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/core/plugin.c b/src/core/plugin.c index 728e20c..76b0b1e 100644 --- a/src/core/plugin.c +++ b/src/core/plugin.c @@ -661,6 +661,111 @@ plugin_add_callback(sdb_llist_t **list, const char *type, return 0; } /* plugin_add_callback */ +/* + * object meta-data + */ + +typedef struct { + int obj_type; + sdb_time_t last_update; + sdb_time_t interval; +} interval_fetcher_t; + +static int +interval_fetcher_host(sdb_store_host_t *host, sdb_object_t *user_data) +{ + interval_fetcher_t *lu = SDB_OBJ_WRAPPER(user_data)->data; + lu->obj_type = SDB_HOST; + lu->last_update = host->last_update; + return 0; +} /* interval_fetcher_host */ + +static int +interval_fetcher_service(sdb_store_service_t *svc, sdb_object_t *user_data) +{ + interval_fetcher_t *lu = SDB_OBJ_WRAPPER(user_data)->data; + lu->obj_type = SDB_SERVICE; + lu->last_update = svc->last_update; + return 0; +} /* interval_fetcher_service */ + +static int +interval_fetcher_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) +{ + interval_fetcher_t *lu = SDB_OBJ_WRAPPER(user_data)->data; + lu->obj_type = SDB_METRIC; + lu->last_update = metric->last_update; + return 0; +} /* interval_fetcher_metric */ + +static int +interval_fetcher_attr(sdb_store_attribute_t *attr, sdb_object_t *user_data) +{ + interval_fetcher_t *lu = SDB_OBJ_WRAPPER(user_data)->data; + lu->obj_type = SDB_ATTRIBUTE; + lu->last_update = attr->last_update; + return 0; +} /* interval_fetcher_attr */ + +static sdb_store_writer_t interval_fetcher = { + interval_fetcher_host, interval_fetcher_service, + interval_fetcher_metric, interval_fetcher_attr, +}; + +static int +get_interval(int obj_type, const char *hostname, + int parent_type, const char *parent, const char *name, + sdb_time_t last_update, sdb_time_t *interval_out) +{ + sdb_ast_fetch_t fetch = SDB_AST_FETCH_INIT; + char hn[hostname ? strlen(hostname) + 1 : 1]; + char pn[parent ? strlen(parent) + 1 : 1]; + char n[strlen(name) + 1]; + int status; + + interval_fetcher_t lu = { 0, 0, 0 }; + sdb_object_wrapper_t obj = SDB_OBJECT_WRAPPER_STATIC(&lu); + sdb_time_t interval; + + assert(name); + + if (hostname) + strncpy(hn, hostname, sizeof(hn)); + if (parent) + strncpy(pn, parent, sizeof(pn)); + strncpy(n, name, sizeof(n)); + + fetch.obj_type = obj_type; + fetch.hostname = hostname ? hn : NULL; + fetch.parent_type = parent_type; + fetch.parent = parent ? pn : NULL; + fetch.name = n; + + status = sdb_plugin_query(SDB_AST_NODE(&fetch), + &interval_fetcher, SDB_OBJ(&obj), NULL); + if ((status < 0) || (lu.obj_type != obj_type) || (lu.last_update == 0)) { + *interval_out = 0; + return 0; + } + + if (lu.last_update >= last_update) { + if (lu.last_update > last_update) + sdb_log(SDB_LOG_DEBUG, "memstore: Cannot update %s '%s' - " + "value too old (%"PRIsdbTIME" < %"PRIsdbTIME")", + SDB_STORE_TYPE_TO_NAME(obj_type), name, + lu.last_update, last_update); + *interval_out = lu.interval; + return 1; + } + + interval = last_update - lu.last_update; + if (lu.interval && interval) + interval = (sdb_time_t)((0.9 * (double)lu.interval) + + (0.1 * (double)interval)); + *interval_out = interval; + return 0; +} /* get_interval */ + static void get_backend(char **backends, size_t *backends_num) { @@ -1508,7 +1613,12 @@ sdb_plugin_store_host(const char *name, sdb_time_t last_update) } host.name = cname; - host.last_update = last_update; + host.last_update = last_update ? last_update : sdb_gettime(); + if (get_interval(SDB_HOST, NULL, -1, NULL, cname, + host.last_update, &host.interval)) { + free(cname); + return 1; + } host.backends = (const char * const *)backends; get_backend(backends, &host.backends_num); @@ -1556,7 +1666,12 @@ sdb_plugin_store_service(const char *hostname, const char *name, service.hostname = cname; service.name = name; - service.last_update = last_update; + service.last_update = last_update ? last_update : sdb_gettime(); + if (get_interval(SDB_SERVICE, cname, -1, NULL, name, + service.last_update, &service.interval)) { + free(cname); + return 1; + } service.backends = (const char * const *)backends; get_backend(backends, &service.backends_num); @@ -1576,7 +1691,7 @@ sdb_plugin_store_service(const char *hostname, const char *name, d.type = SDB_TYPE_STRING; d.data.string = cname; if (sdb_plugin_store_service_attribute(cname, name, - "hostname", &d, last_update)) + "hostname", &d, service.last_update)) status = -1; } @@ -1621,7 +1736,12 @@ sdb_plugin_store_metric(const char *hostname, const char *name, metric.store.type = store->type; metric.store.id = store->id; } - metric.last_update = last_update; + metric.last_update = last_update ? last_update : sdb_gettime(); + if (get_interval(SDB_METRIC, cname, -1, NULL, name, + metric.last_update, &metric.interval)) { + free(cname); + return 1; + } metric.backends = (const char * const *)backends; get_backend(backends, &metric.backends_num); @@ -1641,7 +1761,7 @@ sdb_plugin_store_metric(const char *hostname, const char *name, d.type = SDB_TYPE_STRING; d.data.string = cname; if (sdb_plugin_store_metric_attribute(cname, name, - "hostname", &d, last_update)) + "hostname", &d, metric.last_update)) status = -1; } @@ -1679,7 +1799,12 @@ sdb_plugin_store_attribute(const char *hostname, const char *key, attr.parent = cname; attr.key = key; attr.value = *value; - attr.last_update = last_update; + attr.last_update = last_update ? last_update : sdb_gettime(); + if (get_interval(SDB_ATTRIBUTE, cname, -1, NULL, key, + attr.last_update, &attr.interval)) { + free(cname); + return 1; + } attr.backends = (const char * const *)backends; get_backend(backends, &attr.backends_num); @@ -1728,7 +1853,12 @@ sdb_plugin_store_service_attribute(const char *hostname, const char *service, attr.parent = service; attr.key = key; attr.value = *value; - attr.last_update = last_update; + attr.last_update = last_update ? last_update : sdb_gettime(); + if (get_interval(SDB_ATTRIBUTE, cname, SDB_SERVICE, service, key, + attr.last_update, &attr.interval)) { + free(cname); + return 1; + } attr.backends = (const char * const *)backends; get_backend(backends, &attr.backends_num); @@ -1777,7 +1907,12 @@ sdb_plugin_store_metric_attribute(const char *hostname, const char *metric, attr.parent = metric; attr.key = key; attr.value = *value; - attr.last_update = last_update; + attr.last_update = last_update ? last_update : sdb_gettime(); + if (get_interval(SDB_ATTRIBUTE, cname, SDB_METRIC, metric, key, + attr.last_update, &attr.interval)) { + free(cname); + return 1; + } attr.backends = (const char * const *)backends; get_backend(backends, &attr.backends_num); diff --git a/src/core/store-private.h b/src/core/store-private.h deleted file mode 100644 index e851487..0000000 --- a/src/core/store-private.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * SysDB - src/core/store-private.h - * Copyright (C) 2012-2013 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. - */ - -/* - * private data structures used by the store module - */ - -#ifndef SDB_CORE_STORE_PRIVATE_H -#define SDB_CORE_STORE_PRIVATE_H 1 - -#include "core/store.h" -#include "utils/avltree.h" - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * core types - */ - -struct sdb_store_obj { - sdb_object_t super; -#define _name super.name - - /* object type */ - int type; - - /* common meta information */ - sdb_time_t last_update; - sdb_time_t interval; /* moving average */ - char **backends; - size_t backends_num; - sdb_store_obj_t *parent; -}; -#define STORE_OBJ(obj) ((sdb_store_obj_t *)(obj)) -#define STORE_CONST_OBJ(obj) ((const sdb_store_obj_t *)(obj)) - -typedef struct { - sdb_store_obj_t super; - - sdb_data_t value; -} attr_t; -#define ATTR(obj) ((attr_t *)(obj)) -#define CONST_ATTR(obj) ((const attr_t *)(obj)) - -typedef struct { - sdb_store_obj_t super; - - sdb_avltree_t *attributes; -} service_t; -#define SVC(obj) ((service_t *)(obj)) -#define CONST_SVC(obj) ((const service_t *)(obj)) - -typedef struct { - sdb_store_obj_t super; - - sdb_avltree_t *attributes; - struct { - char *type; - char *id; - } store; -} sdb_metric_t; -#define METRIC(obj) ((sdb_metric_t *)(obj)) - -typedef struct { - sdb_store_obj_t super; - - sdb_avltree_t *services; - sdb_avltree_t *metrics; - sdb_avltree_t *attributes; -} host_t; -#define HOST(obj) ((host_t *)(obj)) -#define CONST_HOST(obj) ((const host_t *)(obj)) - -/* shortcuts for accessing service/host attributes */ -#define _last_update super.last_update -#define _interval super.interval - -/* - * querying - */ - -struct sdb_store_query { - sdb_object_t super; - sdb_ast_node_t *ast; - sdb_store_matcher_t *matcher; - sdb_store_matcher_t *filter; -}; -#define QUERY(m) ((sdb_store_query_t *)(m)) - -/* - * expressions - */ - -enum { - TYPED_EXPR = -3, /* obj type stored in data.data.integer */ - ATTR_VALUE = -2, /* attr name stored in data.data.string */ - FIELD_VALUE = -1, /* field type stored in data.data.integer */ - /* 0: const value (stored in data) */ - /* >0: operator id */ -}; - -struct sdb_store_expr { - sdb_object_t super; - - int type; /* see above */ - int data_type; - - sdb_store_expr_t *left; - sdb_store_expr_t *right; - - sdb_data_t data; -}; -#define CONST_EXPR(v) { SDB_OBJECT_INIT, 0, (v).type, NULL, NULL, (v) } -#define EXPR_TO_STRING(e) \ - (((e)->type == TYPED_EXPR) ? "" \ - : ((e)->type == ATTR_VALUE) ? "attribute" \ - : ((e)->type == FIELD_VALUE) ? SDB_FIELD_TO_NAME((e)->data.data.integer) \ - : ((e)->type == 0) ? "" \ - : ((e)->type > 0) ? SDB_DATA_OP_TO_STRING((e)->type) \ - : "") - -/* - * matchers - */ - -/* when adding to this, also update 'MATCHER_SYM' below and 'matchers' in - * store_lookup.c */ -enum { - MATCHER_OR, - MATCHER_AND, - MATCHER_NOT, - MATCHER_ANY, - MATCHER_ALL, - MATCHER_IN, - - /* unary operators */ - MATCHER_ISNULL, - MATCHER_ISTRUE, - MATCHER_ISFALSE, - - /* ary operators */ - MATCHER_LT, - MATCHER_LE, - MATCHER_EQ, - MATCHER_NE, - MATCHER_GE, - MATCHER_GT, - MATCHER_REGEX, - MATCHER_NREGEX, - - /* a generic query */ - MATCHER_QUERY, -}; - -#define MATCHER_SYM(t) \ - (((t) == MATCHER_OR) ? "OR" \ - : ((t) == MATCHER_AND) ? "AND" \ - : ((t) == MATCHER_NOT) ? "NOT" \ - : ((t) == MATCHER_ANY) ? "ANY" \ - : ((t) == MATCHER_ALL) ? "ALL" \ - : ((t) == MATCHER_IN) ? "IN" \ - : ((t) == MATCHER_ISNULL) ? "IS NULL" \ - : ((t) == MATCHER_ISTRUE) ? "IS TRUE" \ - : ((t) == MATCHER_ISFALSE) ? "IS FALSE" \ - : ((t) == MATCHER_LT) ? "<" \ - : ((t) == MATCHER_LE) ? "<=" \ - : ((t) == MATCHER_EQ) ? "=" \ - : ((t) == MATCHER_NE) ? "!=" \ - : ((t) == MATCHER_GE) ? ">=" \ - : ((t) == MATCHER_GT) ? ">" \ - : ((t) == MATCHER_REGEX) ? "=~" \ - : ((t) == MATCHER_NREGEX) ? "!~" \ - : ((t) == MATCHER_QUERY) ? "QUERY" \ - : "UNKNOWN") - -/* matcher base type */ -struct sdb_store_matcher { - sdb_object_t super; - /* type of the matcher */ - int type; -}; -#define M(m) ((sdb_store_matcher_t *)(m)) - -/* infix operator matcher */ -typedef struct { - sdb_store_matcher_t super; - - /* left and right hand operands */ - sdb_store_matcher_t *left; - sdb_store_matcher_t *right; -} op_matcher_t; -#define OP_M(m) ((op_matcher_t *)(m)) - -/* unary operator matcher */ -typedef struct { - sdb_store_matcher_t super; - - /* operand */ - sdb_store_matcher_t *op; -} uop_matcher_t; -#define UOP_M(m) ((uop_matcher_t *)(m)) - -/* iter matcher */ -typedef struct { - sdb_store_matcher_t super; - sdb_store_expr_t *iter; - sdb_store_matcher_t *m; -} iter_matcher_t; -#define ITER_M(m) ((iter_matcher_t *)(m)) - -/* compare operator matcher */ -typedef struct { - sdb_store_matcher_t super; - - /* left and right hand expressions */ - sdb_store_expr_t *left; - sdb_store_expr_t *right; -} cmp_matcher_t; -#define CMP_M(m) ((cmp_matcher_t *)(m)) - -typedef struct { - sdb_store_matcher_t super; - sdb_store_expr_t *expr; -} unary_matcher_t; -#define UNARY_M(m) ((unary_matcher_t *)(m)) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* ! SDB_CORE_STORE_H */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/core/store.c b/src/core/store.c deleted file mode 100644 index fa72955..0000000 --- a/src/core/store.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * SysDB - src/core/store.c - * Copyright (C) 2012-2013 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. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include "sysdb.h" -#include "core/store-private.h" -#include "core/plugin.h" -#include "utils/avltree.h" -#include "utils/error.h" - -#include - -#include - -#include -#include -#include - -#include - -/* - * private types - */ - -struct sdb_store { - sdb_object_t super; - - /* hosts are the top-level entries and - * reference everything else */ - sdb_avltree_t *hosts; - pthread_rwlock_t host_lock; -}; - -/* internal representation of a to-be-stored object */ -typedef struct { - sdb_store_obj_t *parent; - sdb_avltree_t *parent_tree; - int type; - const char *name; - sdb_time_t last_update; - const char * const *backends; - size_t backends_num; -} store_obj_t; -#define STORE_OBJ_INIT { NULL, NULL, 0, NULL, 0, NULL, 0 } - -static sdb_type_t host_type; -static sdb_type_t service_type; -static sdb_type_t metric_type; -static sdb_type_t attribute_type; - -static int -store_init(sdb_object_t *obj, va_list __attribute__((unused)) ap) -{ - int err; - if (! (SDB_STORE(obj)->hosts = sdb_avltree_create())) - return -1; - if ((err = pthread_rwlock_init(&SDB_STORE(obj)->host_lock, - /* attr = */ NULL))) { - char errbuf[128]; - sdb_log(SDB_LOG_ERR, "store: Failed to initialize lock: %s", - sdb_strerror(err, errbuf, sizeof(errbuf))); - return -1; - } - return 0; -} /* store_init */ - -static void -store_destroy(sdb_object_t *obj) -{ - int err; - if ((err = pthread_rwlock_destroy(&SDB_STORE(obj)->host_lock))) { - char errbuf[128]; - sdb_log(SDB_LOG_ERR, "store: Failed to destroy lock: %s", - sdb_strerror(err, errbuf, sizeof(errbuf))); - return; - } - sdb_avltree_destroy(SDB_STORE(obj)->hosts); - SDB_STORE(obj)->hosts = NULL; -} /* store_destroy */ - -static int -store_obj_init(sdb_object_t *obj, va_list ap) -{ - sdb_store_obj_t *sobj = STORE_OBJ(obj); - - sobj->type = va_arg(ap, int); - - sobj->last_update = va_arg(ap, sdb_time_t); - sobj->interval = 0; - sobj->backends = NULL; - sobj->backends_num = 0; - sobj->parent = NULL; - return 0; -} /* store_obj_init */ - -static void -store_obj_destroy(sdb_object_t *obj) -{ - sdb_store_obj_t *sobj = STORE_OBJ(obj); - size_t i; - - for (i = 0; i < sobj->backends_num; ++i) - free(sobj->backends[i]); - free(sobj->backends); - sobj->backends = NULL; - sobj->backends_num = 0; - - // We don't currently keep an extra reference for parent objects to - // avoid circular self-references which are not handled correctly by - // the ref-count base management layer. - //sdb_object_deref(SDB_OBJ(sobj->parent)); -} /* store_obj_destroy */ - -static int -host_init(sdb_object_t *obj, va_list ap) -{ - host_t *sobj = HOST(obj); - int ret; - - /* this will consume the first argument (type) of ap */ - ret = store_obj_init(obj, ap); - if (ret) - return ret; - - sobj->services = sdb_avltree_create(); - if (! sobj->services) - return -1; - sobj->metrics = sdb_avltree_create(); - if (! sobj->metrics) - return -1; - sobj->attributes = sdb_avltree_create(); - if (! sobj->attributes) - return -1; - return 0; -} /* host_init */ - -static void -host_destroy(sdb_object_t *obj) -{ - host_t *sobj = HOST(obj); - assert(obj); - - store_obj_destroy(obj); - - if (sobj->services) - sdb_avltree_destroy(sobj->services); - if (sobj->metrics) - sdb_avltree_destroy(sobj->metrics); - if (sobj->attributes) - sdb_avltree_destroy(sobj->attributes); -} /* host_destroy */ - -static int -service_init(sdb_object_t *obj, va_list ap) -{ - service_t *sobj = SVC(obj); - int ret; - - /* this will consume the first argument (type) of ap */ - ret = store_obj_init(obj, ap); - if (ret) - return ret; - - sobj->attributes = sdb_avltree_create(); - if (! sobj->attributes) - return -1; - return 0; -} /* service_init */ - -static void -service_destroy(sdb_object_t *obj) -{ - service_t *sobj = SVC(obj); - assert(obj); - - store_obj_destroy(obj); - - if (sobj->attributes) - sdb_avltree_destroy(sobj->attributes); -} /* service_destroy */ - -static int -metric_init(sdb_object_t *obj, va_list ap) -{ - sdb_metric_t *sobj = METRIC(obj); - int ret; - - /* this will consume the first argument (type) of ap */ - ret = store_obj_init(obj, ap); - if (ret) - return ret; - - sobj->attributes = sdb_avltree_create(); - if (! sobj->attributes) - return -1; - - sobj->store.type = sobj->store.id = NULL; - return 0; -} /* metric_init */ - -static void -metric_destroy(sdb_object_t *obj) -{ - sdb_metric_t *sobj = METRIC(obj); - assert(obj); - - store_obj_destroy(obj); - - if (sobj->attributes) - sdb_avltree_destroy(sobj->attributes); - - if (sobj->store.type) - free(sobj->store.type); - if (sobj->store.id) - free(sobj->store.id); -} /* metric_destroy */ - -static int -attr_init(sdb_object_t *obj, va_list ap) -{ - const sdb_data_t *value; - int ret; - - /* this will consume the first two arguments - * (type and last_update) of ap */ - ret = store_obj_init(obj, ap); - if (ret) - return ret; - value = va_arg(ap, const sdb_data_t *); - - if (value) - if (sdb_data_copy(&ATTR(obj)->value, value)) - return -1; - return 0; -} /* attr_init */ - -static void -attr_destroy(sdb_object_t *obj) -{ - assert(obj); - - store_obj_destroy(obj); - sdb_data_free_datum(&ATTR(obj)->value); -} /* attr_destroy */ - -static sdb_type_t store_type = { - /* size = */ sizeof(sdb_store_t), - /* init = */ store_init, - /* destroy = */ store_destroy, -}; - -static sdb_type_t host_type = { - /* size = */ sizeof(host_t), - /* init = */ host_init, - /* destroy = */ host_destroy -}; - -static sdb_type_t service_type = { - /* size = */ sizeof(service_t), - /* init = */ service_init, - /* destroy = */ service_destroy -}; - -static sdb_type_t metric_type = { - /* size = */ sizeof(sdb_metric_t), - /* init = */ metric_init, - /* destroy = */ metric_destroy -}; - -static sdb_type_t attribute_type = { - /* size = */ sizeof(attr_t), - /* init = */ attr_init, - /* destroy = */ attr_destroy -}; - -/* - * private helper functions - */ - -static int -record_backends(sdb_store_obj_t *obj, - const char * const *backends, size_t backends_num) -{ - char **tmp; - size_t i; - - for (i = 0; i < backends_num; i++) { - bool found = 0; - size_t j; - - for (j = 0; j < obj->backends_num; ++j) { - if (!strcasecmp(obj->backends[j], backends[i])) { - found = 1; - break; - } - } - if (found) - continue; - - tmp = realloc(obj->backends, - (obj->backends_num + 1) * sizeof(*obj->backends)); - if (! tmp) - return -1; - - obj->backends = tmp; - obj->backends[obj->backends_num] = strdup(backends[i]); - if (! obj->backends[obj->backends_num]) - return -1; - - ++obj->backends_num; - } - return 0; -} /* record_backends */ - -static int -store_obj(store_obj_t *obj, sdb_store_obj_t **updated_obj) -{ - sdb_store_obj_t *old, *new; - int status = 0; - - assert(obj->parent_tree); - - if (obj->last_update <= 0) - obj->last_update = sdb_gettime(); - - 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' - " - "value too old (%"PRIsdbTIME" < %"PRIsdbTIME")", - SDB_STORE_TYPE_TO_NAME(obj->type), obj->name, - obj->last_update, old->last_update); - /* don't report an error; the object may be updated by multiple - * backends */ - status = 1; - } - else if (old->last_update == obj->last_update) { - /* don't report an error and also don't even log this to avoid - * excessive noise on high sampling frequencies */ - status = 1; - } - else { - sdb_time_t interval = obj->last_update - old->last_update; - old->last_update = obj->last_update; - if (interval) { - if (old->interval) - old->interval = (sdb_time_t)((0.9 * (double)old->interval) - + (0.1 * (double)interval)); - else - old->interval = interval; - } - } - - new = old; - sdb_object_deref(SDB_OBJ(old)); - } - else { - if (obj->type == SDB_ATTRIBUTE) { - /* the value will be updated by the caller */ - new = STORE_OBJ(sdb_object_create(obj->name, attribute_type, - obj->type, obj->last_update, NULL)); - } - else { - sdb_type_t t; - t = obj->type == SDB_HOST - ? host_type - : obj->type == SDB_SERVICE - ? service_type - : metric_type; - new = STORE_OBJ(sdb_object_create(obj->name, t, - obj->type, obj->last_update)); - } - - if (new) { - status = sdb_avltree_insert(obj->parent_tree, SDB_OBJ(new)); - - /* pass control to the tree or destroy in case of an error */ - sdb_object_deref(SDB_OBJ(new)); - } - else { - char errbuf[1024]; - sdb_log(SDB_LOG_ERR, "store: Failed to create %s '%s': %s", - SDB_STORE_TYPE_TO_NAME(obj->type), obj->name, - sdb_strerror(errno, errbuf, sizeof(errbuf))); - status = -1; - } - } - - if (status < 0) - return status; - assert(new); - - if (new->parent != obj->parent) { - // Avoid circular self-references which are not handled - // correctly by the ref-count based management layer. - //sdb_object_deref(SDB_OBJ(new->parent)); - //sdb_object_ref(SDB_OBJ(obj->parent)); - new->parent = obj->parent; - } - - if (updated_obj) - *updated_obj = new; - - if (record_backends(new, obj->backends, obj->backends_num)) - return -1; - return status; -} /* store_obj */ - -static int -store_metric_store(sdb_metric_t *metric, sdb_store_metric_t *m) -{ - char *type = metric->store.type; - char *id = metric->store.id; - - if ((! metric->store.type) || strcasecmp(metric->store.type, m->store.type)) { - if (! (type = strdup(m->store.type))) - return -1; - } - if ((! metric->store.id) || strcasecmp(metric->store.id, m->store.id)) { - if (! (id = strdup(m->store.id))) { - if (type != metric->store.type) - free(type); - return -1; - } - } - - if (type != metric->store.type) { - if (metric->store.type) - free(metric->store.type); - metric->store.type = type; - } - if (id != metric->store.id) { - if (metric->store.id) - free(metric->store.id); - metric->store.id = id; - } - return 0; -} /* store_metric_store */ - -/* The store's host_lock has to be acquired before calling this function. */ -static sdb_avltree_t * -get_host_children(host_t *host, int type) -{ - if ((type != SDB_SERVICE) && (type != SDB_METRIC) - && (type != SDB_ATTRIBUTE)) - return NULL; - - if (! host) - return NULL; - - if (type == SDB_ATTRIBUTE) - return host->attributes; - else if (type == SDB_METRIC) - return host->metrics; - else - return host->services; -} /* get_host_children */ - -/* - * store writer API - */ - -static int -store_attribute(sdb_store_attribute_t *attr, sdb_object_t *user_data) -{ - sdb_store_t *st = SDB_STORE(user_data); - store_obj_t obj = STORE_OBJ_INIT; - sdb_store_obj_t *new = NULL; - const char *hostname; - host_t *host; - - sdb_avltree_t *children = NULL; - int status = 0; - - if ((! attr) || (! attr->parent) || (! attr->key)) - return -1; - - hostname = attr->hostname; - if (attr->parent_type == SDB_HOST) - hostname = attr->parent; - if (! hostname) - return -1; - - 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' - " - "host '%s' not found", attr->key, hostname); - status = -1; - } - - switch (attr->parent_type) { - case SDB_HOST: - obj.parent = STORE_OBJ(host); - obj.parent_tree = get_host_children(host, SDB_ATTRIBUTE); - break; - case SDB_SERVICE: - children = get_host_children(host, SDB_SERVICE); - break; - case SDB_METRIC: - children = get_host_children(host, SDB_METRIC); - break; - default: - status = -1; - break; - } - - 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' - " - "%s '%s/%s' not found", attr->key, - SDB_STORE_TYPE_TO_NAME(attr->parent_type), - attr->hostname, attr->parent); - status = -1; - } - else - obj.parent_tree = attr->parent_type == SDB_SERVICE - ? SVC(obj.parent)->attributes - : METRIC(obj.parent)->attributes; - } - - obj.type = SDB_ATTRIBUTE; - obj.name = attr->key; - obj.last_update = attr->last_update; - obj.backends = attr->backends; - obj.backends_num = attr->backends_num; - if (! status) - status = store_obj(&obj, &new); - - if (! status) { - assert(new); - /* update the value if it changed */ - if (sdb_data_cmp(&ATTR(new)->value, &attr->value)) - if (sdb_data_copy(&ATTR(new)->value, &attr->value)) - status = -1; - } - - if (obj.parent != STORE_OBJ(host)) - sdb_object_deref(SDB_OBJ(obj.parent)); - sdb_object_deref(SDB_OBJ(host)); - pthread_rwlock_unlock(&st->host_lock); - - return status; -} /* store_attribute */ - -static int -store_host(sdb_store_host_t *host, sdb_object_t *user_data) -{ - sdb_store_t *st = SDB_STORE(user_data); - store_obj_t obj = { NULL, st->hosts, SDB_HOST, NULL, 0, NULL, 0 }; - int status = 0; - - if ((! host) || (! host->name)) - return -1; - - obj.name = host->name; - obj.last_update = host->last_update; - obj.backends = host->backends; - obj.backends_num = host->backends_num; - pthread_rwlock_wrlock(&st->host_lock); - status = store_obj(&obj, NULL); - pthread_rwlock_unlock(&st->host_lock); - - return status; -} /* store_host */ - -static int -store_service(sdb_store_service_t *service, sdb_object_t *user_data) -{ - sdb_store_t *st = SDB_STORE(user_data); - store_obj_t obj = STORE_OBJ_INIT; - host_t *host; - - int status = 0; - - if ((! service) || (! service->hostname) || (! service->name)) - return -1; - - pthread_rwlock_wrlock(&st->host_lock); - host = HOST(sdb_avltree_lookup(st->hosts, service->hostname)); - obj.parent = STORE_OBJ(host); - 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' - " - "host '%s' not found", service->name, service->hostname); - status = -1; - } - - obj.name = service->name; - obj.last_update = service->last_update; - obj.backends = service->backends; - obj.backends_num = service->backends_num; - if (! status) - status = store_obj(&obj, NULL); - - sdb_object_deref(SDB_OBJ(host)); - pthread_rwlock_unlock(&st->host_lock); - return status; -} /* store_service */ - -static int -store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) -{ - sdb_store_t *st = SDB_STORE(user_data); - store_obj_t obj = STORE_OBJ_INIT; - sdb_store_obj_t *new = NULL; - host_t *host; - - int status = 0; - - if ((! metric) || (! metric->hostname) || (! metric->name)) - return -1; - - if ((metric->store.type != NULL) != (metric->store.id != NULL)) - return -1; - - pthread_rwlock_wrlock(&st->host_lock); - host = HOST(sdb_avltree_lookup(st->hosts, metric->hostname)); - obj.parent = STORE_OBJ(host); - 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' - " - "host '%s' not found", metric->name, metric->hostname); - status = -1; - } - - obj.name = metric->name; - obj.last_update = metric->last_update; - obj.backends = metric->backends; - obj.backends_num = metric->backends_num; - if (! status) - status = store_obj(&obj, &new); - sdb_object_deref(SDB_OBJ(host)); - - if (status) { - pthread_rwlock_unlock(&st->host_lock); - return status; - } - - assert(new); - if (metric->store.type && metric->store.id) - if (store_metric_store(METRIC(new), metric)) - status = -1; - pthread_rwlock_unlock(&st->host_lock); - return status; -} /* store_metric */ - -sdb_store_writer_t sdb_store_writer = { - store_host, store_service, store_metric, store_attribute, -}; - -static sdb_object_t * -prepare_query(sdb_ast_node_t *ast, - sdb_strbuf_t __attribute__((unused)) *errbuf, - sdb_object_t __attribute__((unused)) *user_data) -{ - return SDB_OBJ(sdb_store_query_prepare(ast)); -} /* prepare_query */ - -static int -execute_query(sdb_object_t *q, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, - sdb_object_t *user_data) -{ - return sdb_store_query_execute(SDB_STORE(user_data), - QUERY(q), w, wd, errbuf); -} /* execute_query */ - -sdb_store_reader_t sdb_store_reader = { - prepare_query, execute_query, -}; - -/* - * public API - */ - -sdb_store_t * -sdb_store_create(void) -{ - return SDB_STORE(sdb_object_create("store", store_type)); -} /* sdb_store_create */ - -int -sdb_store_host(sdb_store_t *store, const char *name, sdb_time_t last_update) -{ - sdb_store_host_t host = { - name, last_update, 0, NULL, 0, - }; - return store_host(&host, SDB_OBJ(store)); -} /* sdb_store_host */ - -int -sdb_store_service(sdb_store_t *store, const char *hostname, const char *name, - sdb_time_t last_update) -{ - sdb_store_service_t service = { - hostname, name, last_update, 0, NULL, 0, - }; - return store_service(&service, SDB_OBJ(store)); -} /* sdb_store_service */ - -int -sdb_store_metric(sdb_store_t *store, const char *hostname, const char *name, - sdb_metric_store_t *metric_store, sdb_time_t last_update) -{ - sdb_store_metric_t metric = { - hostname, name, { NULL, NULL }, last_update, 0, NULL, 0, - }; - if (metric_store) { - metric.store.type = metric_store->type; - metric.store.id = metric_store->id; - } - return store_metric(&metric, SDB_OBJ(store)); -} /* sdb_store_metric */ - -int -sdb_store_attribute(sdb_store_t *store, const char *hostname, - const char *key, const sdb_data_t *value, sdb_time_t last_update) -{ - sdb_store_attribute_t attr = { - NULL, SDB_HOST, hostname, key, SDB_DATA_INIT, last_update, 0, NULL, 0, - }; - if (value) { - attr.value = *value; - } - return store_attribute(&attr, SDB_OBJ(store)); -} /* sdb_store_attribute */ - -int -sdb_store_service_attr(sdb_store_t *store, const char *hostname, - const char *service, const char *key, const sdb_data_t *value, - sdb_time_t last_update) -{ - sdb_store_attribute_t attr = { - hostname, SDB_SERVICE, service, key, SDB_DATA_INIT, last_update, 0, NULL, 0, - }; - if (value) { - attr.value = *value; - } - return store_attribute(&attr, SDB_OBJ(store)); -} /* sdb_store_service_attr */ - -int -sdb_store_metric_attr(sdb_store_t *store, const char *hostname, - const char *metric, const char *key, const sdb_data_t *value, - sdb_time_t last_update) -{ - sdb_store_attribute_t attr = { - hostname, SDB_METRIC, metric, key, SDB_DATA_INIT, last_update, 0, NULL, 0, - }; - if (value) { - attr.value = *value; - } - return store_attribute(&attr, SDB_OBJ(store)); -} /* sdb_store_metric_attr */ - -sdb_store_obj_t * -sdb_store_get_host(sdb_store_t *store, const char *name) -{ - host_t *host; - - if ((! store) || (! name)) - return NULL; - - host = HOST(sdb_avltree_lookup(store->hosts, name)); - if (! host) - return NULL; - - return STORE_OBJ(host); -} /* sdb_store_get_host */ - -sdb_store_obj_t * -sdb_store_get_child(sdb_store_obj_t *host, int type, const char *name) -{ - sdb_avltree_t *children; - - if ((! host) || (host->type != SDB_HOST) || (! name)) - return NULL; - - children = get_host_children(HOST(host), type); - if (! children) - return NULL; - return STORE_OBJ(sdb_avltree_lookup(children, name)); -} /* sdb_store_get_child */ - -int -sdb_store_get_field(sdb_store_obj_t *obj, int field, sdb_data_t *res) -{ - sdb_data_t tmp; - - if (! obj) - return -1; - - switch (field) { - case SDB_FIELD_NAME: - tmp.type = SDB_TYPE_STRING; - tmp.data.string = strdup(SDB_OBJ(obj)->name); - if (! tmp.data.string) - return -1; - break; - case SDB_FIELD_LAST_UPDATE: - tmp.type = SDB_TYPE_DATETIME; - tmp.data.datetime = obj->last_update; - break; - case SDB_FIELD_AGE: - tmp.type = SDB_TYPE_DATETIME; - tmp.data.datetime = sdb_gettime() - obj->last_update; - break; - case SDB_FIELD_INTERVAL: - tmp.type = SDB_TYPE_DATETIME; - tmp.data.datetime = obj->interval; - break; - case SDB_FIELD_BACKEND: - if (! res) - return 0; - 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); - case SDB_FIELD_VALUE: - if (obj->type != SDB_ATTRIBUTE) - return -1; - if (! res) - return 0; - return sdb_data_copy(res, &ATTR(obj)->value); - case SDB_FIELD_TIMESERIES: - if (obj->type != SDB_METRIC) - return -1; - tmp.type = SDB_TYPE_BOOLEAN; - tmp.data.boolean = METRIC(obj)->store.type != NULL; - default: - return -1; - } - if (res) - *res = tmp; - else - sdb_data_free_datum(&tmp); - return 0; -} /* sdb_store_get_field */ - -int -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_store_obj_t *attr; - - if ((! obj) || (! name)) - return -1; - - if (obj->type == SDB_HOST) - tree = HOST(obj)->attributes; - else if (obj->type == SDB_SERVICE) - tree = SVC(obj)->attributes; - else if (obj->type == SDB_METRIC) - tree = METRIC(obj)->attributes; - - if (! tree) - return -1; - - 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; - } - - 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 -sdb_store_scan(sdb_store_t *store, 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 = NULL; - int status = 0; - - if ((! store) || (! 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(&store->host_lock); - host_iter = sdb_avltree_get_iter(store->hosts); - if (! host_iter) - status = -1; - - /* 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(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(&store->host_lock); - return status; -} /* sdb_store_scan */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/core/store_exec.c b/src/core/store_exec.c deleted file mode 100644 index d4e3088..0000000 --- a/src/core/store_exec.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * SysDB - src/core/store_exec.c - * Copyright (C) 2014-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. - */ - -#include "core/object.h" -#include "core/plugin.h" -#include "core/store-private.h" -#include "frontend/connection.h" -#include "parser/ast.h" -#include "utils/error.h" - -#include - -#include -#include -#include - -/* - * private helper functions - */ - -typedef struct { - sdb_store_obj_t *current_host; - - sdb_store_writer_t *w; - sdb_object_t *wd; -} iter_t; - -static int -maybe_emit_host(iter_t *iter, sdb_store_obj_t *obj) -{ - if ((obj->type == SDB_HOST) || (obj->type == SDB_ATTRIBUTE)) - return 0; - if (iter->current_host == obj->parent) - return 0; - iter->current_host = obj->parent; - return sdb_store_emit(obj->parent, iter->w, iter->wd); -} /* maybe_emit_host */ - -static int -list_tojson(sdb_store_obj_t *obj, - sdb_store_matcher_t __attribute__((unused)) *filter, - void *user_data) -{ - iter_t *iter = user_data; - maybe_emit_host(iter, obj); - return sdb_store_emit(obj, iter->w, iter->wd); -} /* list_tojson */ - -static int -lookup_tojson(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, - void *user_data) -{ - iter_t *iter = user_data; - maybe_emit_host(iter, obj); - return sdb_store_emit_full(obj, filter, iter->w, iter->wd); -} /* lookup_tojson */ - -/* - * query implementations - */ - -static int -exec_fetch(sdb_store_t *store, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, - int type, const char *hostname, const char *name, - sdb_store_matcher_t *filter) -{ - sdb_store_obj_t *host; - sdb_store_obj_t *obj; - - int status = 0; - - if ((! name) || ((type == SDB_HOST) && hostname) - || ((type != SDB_HOST) && (! hostname))) { - /* This is a programming error, not something the client did wrong */ - sdb_strbuf_sprintf(errbuf, "INTERNAL ERROR: invalid " - "arguments to FETCH(%s, %s, %s)", - SDB_STORE_TYPE_TO_NAME(type), hostname, name); - return -1; - } - if (type == SDB_HOST) - hostname = name; - - host = sdb_store_get_host(store, hostname); - if ((! host) - || (filter && (! sdb_store_matcher_matches(filter, host, NULL)))) { - sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s: " - "host %s not found", SDB_STORE_TYPE_TO_NAME(type), - name, hostname); - sdb_object_deref(SDB_OBJ(host)); - return -1; - } - if (type == SDB_HOST) { - obj = host; - } - else { - obj = sdb_store_get_child(host, type, name); - if ((! obj) - || (filter && (! sdb_store_matcher_matches(filter, obj, NULL)))) { - sdb_strbuf_sprintf(errbuf, "Failed to fetch %s %s.%s: " - "%s not found", SDB_STORE_TYPE_TO_NAME(type), - hostname, name, name); - if (obj) - sdb_object_deref(SDB_OBJ(obj)); - sdb_object_deref(SDB_OBJ(host)); - return -1; - } - sdb_object_deref(SDB_OBJ(host)); - } - host = NULL; - - if (type != SDB_HOST) - status = sdb_store_emit(obj->parent, w, wd); - if (status || sdb_store_emit_full(obj, filter, w, wd)) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize " - "%s %s.%s to JSON", SDB_STORE_TYPE_TO_NAME(type), - hostname, name); - sdb_strbuf_sprintf(errbuf, "Out of memory"); - sdb_object_deref(SDB_OBJ(obj)); - return -1; - } - - sdb_object_deref(SDB_OBJ(obj)); - return SDB_CONNECTION_DATA; -} /* exec_fetch */ - -static int -exec_list(sdb_store_t *store, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, - int type, sdb_store_matcher_t *filter) -{ - iter_t iter = { NULL, w, wd }; - - if (sdb_store_scan(store, type, /* m = */ NULL, filter, list_tojson, &iter)) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize " - "store to JSON"); - sdb_strbuf_sprintf(errbuf, "Out of memory"); - return -1; - } - - return SDB_CONNECTION_DATA; -} /* exec_list */ - -static int -exec_lookup(sdb_store_t *store, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf, - int type, sdb_store_matcher_t *m, sdb_store_matcher_t *filter) -{ - iter_t iter = { NULL, w, wd }; - - if (sdb_store_scan(store, type, m, filter, lookup_tojson, &iter)) { - sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup %ss", - SDB_STORE_TYPE_TO_NAME(type)); - sdb_strbuf_sprintf(errbuf, "Failed to lookup %ss", - SDB_STORE_TYPE_TO_NAME(type)); - return -1; - } - - return SDB_CONNECTION_DATA; -} /* exec_lookup */ - -/* - * public API - */ - -int -sdb_store_query_execute(sdb_store_t *store, sdb_store_query_t *q, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf) -{ - sdb_ast_node_t *ast; - - if (! q) - return -1; - if (! q->ast) { - sdb_log(SDB_LOG_ERR, "store: Invalid empty query"); - return -1; - } - - ast = q->ast; - switch (ast->type) { - case SDB_AST_TYPE_FETCH: - return exec_fetch(store, w, wd, errbuf, SDB_AST_FETCH(ast)->obj_type, - SDB_AST_FETCH(ast)->hostname, SDB_AST_FETCH(ast)->name, - q->filter); - - case SDB_AST_TYPE_LIST: - return exec_list(store, w, wd, errbuf, SDB_AST_LIST(ast)->obj_type, - q->filter); - - case SDB_AST_TYPE_LOOKUP: - return exec_lookup(store, w, wd, errbuf, SDB_AST_LOOKUP(ast)->obj_type, - q->matcher, q->filter); - - default: - sdb_log(SDB_LOG_ERR, "store: Invalid query of type %s", - SDB_AST_TYPE_TO_STRING(ast)); - return -1; - } - - return 0; -} /* sdb_store_query_execute */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/core/store_expr.c b/src/core/store_expr.c deleted file mode 100644 index 6405002..0000000 --- a/src/core/store_expr.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * SysDB - src/core/store_expr.c - * Copyright (C) 2014 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. - */ - -/* - * This module implements expressions which may be executed in the store. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include "sysdb.h" -#include "core/store-private.h" -#include "core/data.h" -#include "core/object.h" - -#include -#include -#include -#include - -/* - * private data types - */ - -/* iterate through either a list of child nodes or arrays */ -struct sdb_store_expr_iter { - sdb_store_obj_t *obj; - sdb_store_expr_t *expr; - - sdb_avltree_iter_t *tree; - - sdb_data_t array; - size_t array_idx; - bool free_array; - - sdb_store_matcher_t *filter; -}; - -/* - * private types - */ - -static int -expr_init(sdb_object_t *obj, va_list ap) -{ - int type = va_arg(ap, int); - sdb_store_expr_t *left = va_arg(ap, sdb_store_expr_t *); - sdb_store_expr_t *right = va_arg(ap, sdb_store_expr_t *); - const sdb_data_t *value = va_arg(ap, const sdb_data_t *); - - sdb_store_expr_t *expr = SDB_STORE_EXPR(obj); - - if (type <= 0) { - if (! value) - return -1; - if ((type == TYPED_EXPR) && (! left)) - return -1; - } else { - if (value) - return -1; - if ((! left) || (! right)) - return -1; - } - - if (value) - expr->data = *value; - - sdb_object_ref(SDB_OBJ(left)); - sdb_object_ref(SDB_OBJ(right)); - - expr->type = type; - expr->left = left; - expr->right = right; - - /* unknown for now */ - expr->data_type = -1; - return 0; -} /* expr_init */ - -static void -expr_destroy(sdb_object_t *obj) -{ - sdb_store_expr_t *expr = SDB_STORE_EXPR(obj); - sdb_object_deref(SDB_OBJ(expr->left)); - sdb_object_deref(SDB_OBJ(expr->right)); - - if (expr->data.type) - sdb_data_free_datum(&expr->data); -} /* expr_destroy */ - -static sdb_type_t expr_type = { - /* size = */ sizeof(sdb_store_expr_t), - /* init = */ expr_init, - /* destroy = */ expr_destroy, -}; - -/* - * public API - */ - -sdb_store_expr_t * -sdb_store_expr_create(int op, sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - sdb_data_t value = SDB_DATA_INIT; - sdb_store_expr_t *e; - - if ((op < 0) || (SDB_DATA_CONCAT < op) || (! left) || (! right)) - return NULL; - - if (left->type || right->type) { - e = SDB_STORE_EXPR(sdb_object_create("store-expr", expr_type, - op, left, right, NULL)); - e->data_type = sdb_data_expr_type(op, left->type, right->type); - return e; - } - /* else: both expressions are constant values; evaluate now */ - - if (sdb_data_expr_eval(op, &left->data, &right->data, &value)) - return NULL; - e = SDB_STORE_EXPR(sdb_object_create("store-constvalue", expr_type, - 0, NULL, NULL, &value)); - e->data_type = value.type; - return e; -} /* sdb_store_expr_create */ - -sdb_store_expr_t * -sdb_store_expr_typed(int typ, sdb_store_expr_t *expr) -{ - sdb_data_t value = { SDB_TYPE_INTEGER, { .integer = typ } }; - sdb_store_expr_t *e; - - if ((typ < SDB_HOST) || (SDB_ATTRIBUTE < typ)) - return NULL; - - e = SDB_STORE_EXPR(sdb_object_create("store-typedexpr", expr_type, - TYPED_EXPR, expr, NULL, &value)); - e->data_type = expr->data_type; - return e; -} /* sdb_store_expr_typed */ - -sdb_store_expr_t * -sdb_store_expr_fieldvalue(int field) -{ - sdb_data_t value = { SDB_TYPE_INTEGER, { .integer = field } }; - sdb_store_expr_t *e; - - if ((field < SDB_FIELD_NAME) || (SDB_FIELD_TIMESERIES < field)) - return NULL; - e = SDB_STORE_EXPR(sdb_object_create("store-fieldvalue", expr_type, - FIELD_VALUE, NULL, NULL, &value)); - e->data_type = SDB_FIELD_TYPE(field); - return e; -} /* sdb_store_expr_fieldvalue */ - -sdb_store_expr_t * -sdb_store_expr_attrvalue(const char *name) -{ - sdb_data_t value = { SDB_TYPE_STRING, { .string = NULL} }; - sdb_store_expr_t *expr; - - value.data.string = strdup(name); - if (! value.data.string) - return NULL; - - expr = SDB_STORE_EXPR(sdb_object_create("store-attrvalue", expr_type, - ATTR_VALUE, NULL, NULL, &value)); - if (! expr) - free(value.data.string); - expr->data_type = -1; - return expr; -} /* sdb_store_expr_attrvalue */ - -sdb_store_expr_t * -sdb_store_expr_constvalue(const sdb_data_t *value) -{ - sdb_data_t data = SDB_DATA_INIT; - sdb_store_expr_t *e; - - if (sdb_data_copy(&data, value)) - return NULL; - e = SDB_STORE_EXPR(sdb_object_create("store-constvalue", expr_type, - 0, NULL, NULL, &data)); - e->data_type = data.type; - return e; -} /* sdb_store_expr_constvalue */ - -int -sdb_store_expr_eval(sdb_store_expr_t *expr, sdb_store_obj_t *obj, - sdb_data_t *res, sdb_store_matcher_t *filter) -{ - sdb_data_t v1 = SDB_DATA_INIT, v2 = SDB_DATA_INIT; - int status = 0; - - if ((! expr) || (! res)) - return -1; - - if (filter && obj && (! sdb_store_matcher_matches(filter, obj, NULL))) - obj = NULL; /* this object does not exist */ - - if (! expr->type) - return sdb_data_copy(res, &expr->data); - else if (expr->type == FIELD_VALUE) - return sdb_store_get_field(obj, (int)expr->data.data.integer, res); - else if (expr->type == ATTR_VALUE) { - status = sdb_store_get_attr(obj, expr->data.data.string, res, filter); - if ((status < 0) && obj) { - /* attribute does not exist => NULL */ - status = 0; - res->type = SDB_TYPE_STRING; - res->data.string = NULL; - } - return status; - } - else if (expr->type == TYPED_EXPR) { - int typ = (int)expr->data.data.integer; - if (typ != obj->type) { - /* we support self-references and { service, metric } -> host */ - if ((typ != SDB_HOST) - || ((obj->type != SDB_SERVICE) - && (obj->type != SDB_METRIC))) - return -1; - obj = obj->parent; - } - return sdb_store_expr_eval(expr->left, obj, res, filter); - } - - if (sdb_store_expr_eval(expr->left, obj, &v1, filter)) - return -1; - if (sdb_store_expr_eval(expr->right, obj, &v2, filter)) { - sdb_data_free_datum(&v1); - return -1; - } - - if (sdb_data_expr_eval(expr->type, &v1, &v2, res)) - status = -1; - sdb_data_free_datum(&v1); - sdb_data_free_datum(&v2); - return status; -} /* sdb_store_expr_eval */ - -sdb_store_expr_iter_t * -sdb_store_expr_iter(sdb_store_expr_t *expr, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - sdb_store_expr_iter_t *iter; - sdb_avltree_iter_t *tree = NULL; - sdb_data_t array = SDB_DATA_INIT; - bool free_array = 0; - - if (! expr) - return NULL; - - while (expr->type == TYPED_EXPR) { - int type = (int)expr->data.data.integer; - - if (obj->type == type) { - /* self reference */ - } - else if ((type == SDB_HOST) - && ((obj->type == SDB_SERVICE) - || (obj->type == SDB_METRIC))) { - /* reference to parent host */ - obj = obj->parent; - } - else - break; - expr = expr->left; - } - - if (expr->type == TYPED_EXPR) { - if (! obj) - return NULL; - if (obj->type == SDB_HOST) { - if (expr->data.data.integer == SDB_SERVICE) - tree = sdb_avltree_get_iter(HOST(obj)->services); - else if (expr->data.data.integer == SDB_METRIC) - tree = sdb_avltree_get_iter(HOST(obj)->metrics); - else if (expr->data.data.integer == SDB_ATTRIBUTE) - tree = sdb_avltree_get_iter(HOST(obj)->attributes); - } - else if (obj->type == SDB_SERVICE) { - if (expr->data.data.integer == SDB_ATTRIBUTE) - tree = sdb_avltree_get_iter(SVC(obj)->attributes); - } - else if (obj->type == SDB_METRIC) { - if (expr->data.data.integer == SDB_ATTRIBUTE) - tree = sdb_avltree_get_iter(METRIC(obj)->attributes); - } - } - else if (expr->type == FIELD_VALUE) { - if (! obj) - return NULL; - if (expr->data.data.integer == SDB_FIELD_BACKEND) { - /* while scanning the store, we hold a read lock, so it's safe to - * access the data without copying */ - array.type = SDB_TYPE_ARRAY | SDB_TYPE_STRING; - array.data.array.length = obj->backends_num; - array.data.array.values = obj->backends; - } - } - else if (! expr->type) { - if (expr->data.type & SDB_TYPE_ARRAY) - array = expr->data; - } - else { - sdb_data_t value = SDB_DATA_INIT; - if (sdb_store_expr_eval(expr, obj, &value, filter)) - return NULL; - if (! (value.type & SDB_TYPE_ARRAY)) { - sdb_data_free_datum(&value); - return NULL; - } - array = value; - free_array = 1; - } - - if ((! tree) && (array.type == SDB_TYPE_NULL)) - return NULL; - - iter = calloc(1, sizeof(*iter)); - if (! iter) { - if (free_array) - sdb_data_free_datum(&array); - return NULL; - } - - sdb_object_ref(SDB_OBJ(obj)); - sdb_object_ref(SDB_OBJ(expr)); - sdb_object_ref(SDB_OBJ(filter)); - - iter->obj = obj; - iter->expr = expr; - iter->tree = tree; - iter->array = array; - iter->free_array = free_array; - iter->filter = filter; - return iter; -} /* sdb_store_expr_iter */ - -void -sdb_store_expr_iter_destroy(sdb_store_expr_iter_t *iter) -{ - sdb_data_t null = SDB_DATA_INIT; - - if (! iter) - return; - - if (iter->tree) - sdb_avltree_iter_destroy(iter->tree); - iter->tree = NULL; - - if (iter->free_array) - sdb_data_free_datum(&iter->array); - iter->array = null; - iter->array_idx = 0; - - sdb_object_deref(SDB_OBJ(iter->obj)); - sdb_object_deref(SDB_OBJ(iter->expr)); - sdb_object_deref(SDB_OBJ(iter->filter)); - free(iter); -} /* sdb_store_expr_iter_destroy */ - -bool -sdb_store_expr_iter_has_next(sdb_store_expr_iter_t *iter) -{ - if (! iter) - return 0; - - if (iter->tree) { - /* this function may be called before get_next, - * so we'll have to apply filters here as well */ - if (iter->filter) { - sdb_store_obj_t *child; - while ((child = STORE_OBJ(sdb_avltree_iter_peek_next(iter->tree)))) { - if (sdb_store_matcher_matches(iter->filter, child, NULL)) - break; - (void)sdb_avltree_iter_get_next(iter->tree); - } - } - - return sdb_avltree_iter_has_next(iter->tree); - } - - return iter->array_idx < iter->array.data.array.length; -} /* sdb_store_expr_iter_has_next */ - -sdb_data_t -sdb_store_expr_iter_get_next(sdb_store_expr_iter_t *iter) -{ - sdb_data_t null = SDB_DATA_INIT; - sdb_data_t ret = SDB_DATA_INIT; - sdb_data_t tmp = SDB_DATA_INIT; - - if (! iter) - return null; - - if (iter->tree) { - sdb_store_obj_t *child; - - while (42) { - child = STORE_OBJ(sdb_avltree_iter_get_next(iter->tree)); - if (! child) - break; - if (iter->filter - && (! sdb_store_matcher_matches(iter->filter, child, NULL))) - continue; - - if (sdb_store_expr_eval(iter->expr, child, &ret, iter->filter)) - return null; - break; - } - - /* Skip over any filtered objects */ - if (iter->filter) { - while ((child = STORE_OBJ(sdb_avltree_iter_peek_next(iter->tree)))) { - if (sdb_store_matcher_matches(iter->filter, child, NULL)) - break; - (void)sdb_avltree_iter_get_next(iter->tree); - } - } - - return ret; - } - - if (iter->array_idx >= iter->array.data.array.length) - return null; - - ++iter->array_idx; - if (sdb_data_array_get(&iter->array, iter->array_idx - 1, &ret)) - return null; - if (sdb_data_copy(&tmp, &ret)) - return null; - ret = tmp; - return ret; -} /* sdb_store_expr_iter_get_next */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/core/store_json.c b/src/core/store_json.c index 961e54c..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_store_emit(sdb_store_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_store_emit */ - -int -sdb_store_emit_full(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, - sdb_store_writer_t *w, sdb_object_t *wd) -{ - sdb_avltree_t *trees[] = { NULL, NULL, NULL }; - size_t i; - - if (sdb_store_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_store_obj_t *child; - child = STORE_OBJ(sdb_avltree_iter_get_next(iter)); - - if (filter && (! sdb_store_matcher_matches(filter, child, NULL))) - continue; - - if (sdb_store_emit_full(child, filter, w, wd)) { - sdb_avltree_iter_destroy(iter); - return -1; - } - } - sdb_avltree_iter_destroy(iter); - } - return 0; -} /* sdb_store_emit_full */ - int sdb_store_json_finish(sdb_store_json_formatter_t *f) { diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c deleted file mode 100644 index 06151a8..0000000 --- a/src/core/store_lookup.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * SysDB - src/core/store_lookup.c - * Copyright (C) 2014 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. - */ - -/* - * This module implements operators which may be used to select contents of - * the store by matching various attributes of the stored objects. For now, a - * simple full table scan is supported only. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include "sysdb.h" -#include "core/store-private.h" -#include "core/object.h" -#include "utils/error.h" - -#include - -#include -#include - -#include -#include - -#include - -static int -expr_eval2(sdb_store_expr_t *e1, sdb_data_t *v1, - sdb_store_expr_t *e2, sdb_data_t *v2, - sdb_store_obj_t *obj, sdb_store_matcher_t *filter) -{ - if (e1->type) { - if (sdb_store_expr_eval(e1, obj, v1, filter)) - return -1; - } - else - *v1 = e1->data; - if (e2->type) { - if (sdb_store_expr_eval(e2, obj, v2, filter)) { - if (e1->type) - sdb_data_free_datum(v1); - return -1; - } - } - else - *v2 = e2->data; - return 0; -} /* expr_eval2 */ - -static void -expr_free_datum2(sdb_store_expr_t *e1, sdb_data_t *v1, - sdb_store_expr_t *e2, sdb_data_t *v2) -{ - if (e1->type) - sdb_data_free_datum(v1); - if (e2->type) - sdb_data_free_datum(v2); -} /* expr_free_datum2 */ - -/* - * matcher implementations - */ - -/* - * cmp_expr: - * Compare two values using the specified matcher operator. If strcmp_fallback - * is enabled, compare the string values in case of a type mismatch. - */ -static int -match_cmp_value(int op, sdb_data_t *v1, sdb_data_t *v2, bool strcmp_fallback) -{ - int status; - - if (sdb_data_isnull(v1) || (sdb_data_isnull(v2))) - status = INT_MAX; - else if (v1->type == v2->type) - status = sdb_data_cmp(v1, v2); - else if (! strcmp_fallback) - status = INT_MAX; - else - status = sdb_data_strcmp(v1, v2); - - if (status == INT_MAX) - return 0; - switch (op) { - case MATCHER_LT: return status < 0; - case MATCHER_LE: return status <= 0; - case MATCHER_EQ: return status == 0; - case MATCHER_NE: return status != 0; - case MATCHER_GE: return status >= 0; - case MATCHER_GT: return status > 0; - } - return 0; -} /* match_cmp_value */ - -static int -match_regex_value(int op, sdb_data_t *v, sdb_data_t *re) -{ - char value[sdb_data_strlen(v) + 1]; - int status = 0; - - assert((op == MATCHER_REGEX) - || (op == MATCHER_NREGEX)); - - if (sdb_data_isnull(v) || sdb_data_isnull(re)) - return 0; - - if (re->type == SDB_TYPE_STRING) { - sdb_data_t tmp = SDB_DATA_INIT; - - if (sdb_data_parse(re->data.string, SDB_TYPE_REGEX, &tmp)) - return 0; - - sdb_data_free_datum(re); - *re = tmp; - } - else if (re->type != SDB_TYPE_REGEX) - return 0; - - if (! sdb_data_format(v, value, sizeof(value), SDB_UNQUOTED)) - status = 0; - else if (! regexec(&re->data.re.regex, value, 0, NULL, 0)) - status = 1; - - if (op == MATCHER_NREGEX) - return !status; - return status; -} /* match_regex_value */ - -static int -match_logical(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - int status; - - assert((m->type == MATCHER_AND) || (m->type == MATCHER_OR)); - assert(OP_M(m)->left && OP_M(m)->right); - - status = sdb_store_matcher_matches(OP_M(m)->left, obj, filter); - - /* lazy evaluation */ - if ((! status) && (m->type == MATCHER_AND)) - return status; - else if (status && (m->type == MATCHER_OR)) - return status; - - return sdb_store_matcher_matches(OP_M(m)->right, obj, filter); -} /* match_logical */ - -static int -match_uop(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - assert(m->type == MATCHER_NOT); - assert(UOP_M(m)->op); - - return !sdb_store_matcher_matches(UOP_M(m)->op, obj, filter); -} /* match_uop */ - -/* iterate: ANY/ALL */ -static int -match_iter(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - sdb_store_expr_iter_t *iter = NULL; - int status; - int all = (int)(m->type == MATCHER_ALL); - - assert((m->type == MATCHER_ANY) || (m->type == MATCHER_ALL)); - assert((! CMP_M(ITER_M(m)->m)->left) && CMP_M(ITER_M(m)->m)->right); - - iter = sdb_store_expr_iter(ITER_M(m)->iter, obj, filter); - if (! iter) { - sdb_log(SDB_LOG_WARNING, "store: Invalid iterator"); - return 0; - } - - status = all; - while (sdb_store_expr_iter_has_next(iter)) { - sdb_data_t v = sdb_store_expr_iter_get_next(iter); - sdb_store_expr_t expr = CONST_EXPR(v); - bool matches; - - CMP_M(ITER_M(m)->m)->left = &expr; - matches = sdb_store_matcher_matches(ITER_M(m)->m, obj, filter); - CMP_M(ITER_M(m)->m)->left = NULL; - sdb_data_free_datum(&v); - - if (matches) { - if (! all) { - status = 1; - break; - } - } else if (all) { - status = 0; - break; - } - } - sdb_store_expr_iter_destroy(iter); - return status; -} /* match_iter */ - -static int -match_cmp(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - sdb_store_expr_t *e1 = CMP_M(m)->left; - sdb_store_expr_t *e2 = CMP_M(m)->right; - sdb_data_t v1 = SDB_DATA_INIT, v2 = SDB_DATA_INIT; - int status; - - assert((m->type == MATCHER_LT) - || (m->type == MATCHER_LE) - || (m->type == MATCHER_EQ) - || (m->type == MATCHER_NE) - || (m->type == MATCHER_GE) - || (m->type == MATCHER_GT)); - assert(e1 && e2); - - if (expr_eval2(e1, &v1, e2, &v2, obj, filter)) - return 0; - - status = match_cmp_value(m->type, &v1, &v2, - (e1->data_type) < 0 || (e2->data_type < 0)); - - expr_free_datum2(e1, &v1, e2, &v2); - return status; -} /* match_cmp */ - -static int -match_in(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - sdb_data_t value = SDB_DATA_INIT, array = SDB_DATA_INIT; - int status = 1; - - assert(m->type == MATCHER_IN); - assert(CMP_M(m)->left && CMP_M(m)->right); - - if (expr_eval2(CMP_M(m)->left, &value, - CMP_M(m)->right, &array, obj, filter)) - status = 0; - - if (status) - status = sdb_data_inarray(&value, &array); - - expr_free_datum2(CMP_M(m)->left, &value, CMP_M(m)->right, &array); - return status; -} /* match_in */ - -static int -match_regex(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - sdb_data_t regex = SDB_DATA_INIT, v = SDB_DATA_INIT; - int status = 0; - - assert((m->type == MATCHER_REGEX) - || (m->type == MATCHER_NREGEX)); - assert(CMP_M(m)->left && CMP_M(m)->right); - - if (expr_eval2(CMP_M(m)->left, &v, CMP_M(m)->right, ®ex, obj, filter)) - return 0; - - status = match_regex_value(m->type, &v, ®ex); - - expr_free_datum2(CMP_M(m)->left, &v, CMP_M(m)->right, ®ex); - return status; -} /* match_regex */ - -static int -match_unary(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - sdb_data_t v = SDB_DATA_INIT; - int status; - - assert((m->type == MATCHER_ISNULL) - || (m->type == MATCHER_ISTRUE) - || (m->type == MATCHER_ISFALSE)); - - if (UNARY_M(m)->expr->type) { - /* TODO: this might hide real errors; - * improve error reporting and propagation */ - if (sdb_store_expr_eval(UNARY_M(m)->expr, obj, &v, filter)) - return 1; - } - else - v = UNARY_M(m)->expr->data; - - if (m->type == MATCHER_ISNULL) - status = sdb_data_isnull(&v) ? 1 : 0; - else { /* ISTRUE or ISFALSE */ - if ((v.type == SDB_TYPE_BOOLEAN) - && (v.data.boolean == (m->type == MATCHER_ISTRUE))) - status = 1; - else - status = 0; - } - - if (UNARY_M(m)->expr->type) - sdb_data_free_datum(&v); - return status; -} /* match_unary */ - -typedef int (*matcher_cb)(sdb_store_matcher_t *, sdb_store_obj_t *, - sdb_store_matcher_t *); - -/* this array needs to be indexable by the matcher types; - * -> update the enum in store-private.h when updating this */ -static matcher_cb -matchers[] = { - match_logical, - match_logical, - match_uop, - match_iter, - match_iter, - match_in, - - /* unary operators */ - match_unary, - match_unary, - match_unary, - - /* ary operators */ - match_cmp, - match_cmp, - match_cmp, - match_cmp, - match_cmp, - match_cmp, - match_regex, - match_regex, - - NULL, /* QUERY */ -}; - -/* - * private matcher types - */ - -static int -op_matcher_init(sdb_object_t *obj, va_list ap) -{ - M(obj)->type = va_arg(ap, int); - if ((M(obj)->type != MATCHER_OR) && (M(obj)->type != MATCHER_AND)) - return -1; - - OP_M(obj)->left = va_arg(ap, sdb_store_matcher_t *); - sdb_object_ref(SDB_OBJ(OP_M(obj)->left)); - OP_M(obj)->right = va_arg(ap, sdb_store_matcher_t *); - sdb_object_ref(SDB_OBJ(OP_M(obj)->right)); - - if ((! OP_M(obj)->left) || (! OP_M(obj)->right)) - return -1; - return 0; -} /* op_matcher_init */ - -static void -op_matcher_destroy(sdb_object_t *obj) -{ - if (OP_M(obj)->left) - sdb_object_deref(SDB_OBJ(OP_M(obj)->left)); - if (OP_M(obj)->right) - sdb_object_deref(SDB_OBJ(OP_M(obj)->right)); -} /* op_matcher_destroy */ - -static int -iter_matcher_init(sdb_object_t *obj, va_list ap) -{ - M(obj)->type = va_arg(ap, int); - ITER_M(obj)->iter = va_arg(ap, sdb_store_expr_t *); - ITER_M(obj)->m = va_arg(ap, sdb_store_matcher_t *); - - sdb_object_ref(SDB_OBJ(ITER_M(obj)->iter)); - sdb_object_ref(SDB_OBJ(ITER_M(obj)->m)); - - if ((! ITER_M(obj)->iter) || (! ITER_M(obj)->m)) - return -1; - return 0; -} /* iter_matcher_init */ - -static void -iter_matcher_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(ITER_M(obj)->iter)); - sdb_object_deref(SDB_OBJ(ITER_M(obj)->m)); -} /* iter_matcher_destroy */ - -static int -cmp_matcher_init(sdb_object_t *obj, va_list ap) -{ - M(obj)->type = va_arg(ap, int); - - CMP_M(obj)->left = va_arg(ap, sdb_store_expr_t *); - sdb_object_ref(SDB_OBJ(CMP_M(obj)->left)); - CMP_M(obj)->right = va_arg(ap, sdb_store_expr_t *); - sdb_object_ref(SDB_OBJ(CMP_M(obj)->right)); - - if (! CMP_M(obj)->right) - return -1; - return 0; -} /* cmp_matcher_init */ - -static void -cmp_matcher_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(CMP_M(obj)->left)); - sdb_object_deref(SDB_OBJ(CMP_M(obj)->right)); -} /* cmp_matcher_destroy */ - -static int -uop_matcher_init(sdb_object_t *obj, va_list ap) -{ - M(obj)->type = va_arg(ap, int); - if (M(obj)->type != MATCHER_NOT) - return -1; - - UOP_M(obj)->op = va_arg(ap, sdb_store_matcher_t *); - sdb_object_ref(SDB_OBJ(UOP_M(obj)->op)); - - if (! UOP_M(obj)->op) - return -1; - return 0; -} /* uop_matcher_init */ - -static void -uop_matcher_destroy(sdb_object_t *obj) -{ - if (UOP_M(obj)->op) - sdb_object_deref(SDB_OBJ(UOP_M(obj)->op)); -} /* uop_matcher_destroy */ - -static int -unary_matcher_init(sdb_object_t *obj, va_list ap) -{ - M(obj)->type = va_arg(ap, int); - if ((M(obj)->type != MATCHER_ISNULL) - && (M(obj)->type != MATCHER_ISTRUE) - && (M(obj)->type != MATCHER_ISFALSE)) - return -1; - - UNARY_M(obj)->expr = va_arg(ap, sdb_store_expr_t *); - sdb_object_ref(SDB_OBJ(UNARY_M(obj)->expr)); - return 0; -} /* unary_matcher_init */ - -static void -unary_matcher_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(UNARY_M(obj)->expr)); - UNARY_M(obj)->expr = NULL; -} /* unary_matcher_destroy */ - -static sdb_type_t op_type = { - /* size = */ sizeof(op_matcher_t), - /* init = */ op_matcher_init, - /* destroy = */ op_matcher_destroy, -}; - -static sdb_type_t uop_type = { - /* size = */ sizeof(uop_matcher_t), - /* init = */ uop_matcher_init, - /* destroy = */ uop_matcher_destroy, -}; - -static sdb_type_t iter_type = { - /* size = */ sizeof(iter_matcher_t), - /* init = */ iter_matcher_init, - /* destroy = */ iter_matcher_destroy, -}; - -static sdb_type_t cmp_type = { - /* size = */ sizeof(cmp_matcher_t), - /* init = */ cmp_matcher_init, - /* destroy = */ cmp_matcher_destroy, -}; - -static sdb_type_t unary_type = { - /* size = */ sizeof(unary_matcher_t), - /* init = */ unary_matcher_init, - /* destroy = */ unary_matcher_destroy, -}; - -/* - * public API - */ - -sdb_store_matcher_t * -sdb_store_any_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m) -{ - if ((m->type < MATCHER_LT) || (MATCHER_NREGEX < m->type)) { - sdb_log(SDB_LOG_ERR, "store: 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 " - "(invalid left operand)", - SDB_TYPE_TO_STRING(CMP_M(m)->left->data_type), - MATCHER_SYM(m->type), - SDB_TYPE_TO_STRING(CMP_M(m)->right->data_type)); - return NULL; - } - return M(sdb_object_create("any-matcher", iter_type, - MATCHER_ANY, iter, m)); -} /* sdb_store_any_matcher */ - -sdb_store_matcher_t * -sdb_store_all_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m) -{ - if ((m->type < MATCHER_LT) || (MATCHER_NREGEX < m->type)) { - sdb_log(SDB_LOG_ERR, "store: 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 " - "(invalid left operand)", - SDB_TYPE_TO_STRING(CMP_M(m)->left->data_type), - MATCHER_SYM(m->type), - SDB_TYPE_TO_STRING(CMP_M(m)->right->data_type)); - return NULL; - } - return M(sdb_object_create("all-matcher", iter_type, - MATCHER_ALL, iter, m)); -} /* sdb_store_all_matcher */ - -sdb_store_matcher_t * -sdb_store_lt_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("lt-matcher", cmp_type, - MATCHER_LT, left, right)); -} /* sdb_store_lt_matcher */ - -sdb_store_matcher_t * -sdb_store_le_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("le-matcher", cmp_type, - MATCHER_LE, left, right)); -} /* sdb_store_le_matcher */ - -sdb_store_matcher_t * -sdb_store_eq_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("eq-matcher", cmp_type, - MATCHER_EQ, left, right)); -} /* sdb_store_eq_matcher */ - -sdb_store_matcher_t * -sdb_store_ne_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("ne-matcher", cmp_type, - MATCHER_NE, left, right)); -} /* sdb_store_ne_matcher */ - -sdb_store_matcher_t * -sdb_store_ge_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("ge-matcher", cmp_type, - MATCHER_GE, left, right)); -} /* sdb_store_ge_matcher */ - -sdb_store_matcher_t * -sdb_store_gt_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("gt-matcher", cmp_type, - MATCHER_GT, left, right)); -} /* sdb_store_gt_matcher */ - -sdb_store_matcher_t * -sdb_store_in_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - return M(sdb_object_create("in-matcher", cmp_type, - MATCHER_IN, left, right)); -} /* sdb_store_in_matcher */ - -sdb_store_matcher_t * -sdb_store_regex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - if (! right->type) { - if ((right->data.type != SDB_TYPE_STRING) - && (right->data.type != SDB_TYPE_REGEX)) - return NULL; - - if (right->data.type == SDB_TYPE_STRING) { - char *raw = right->data.data.string; - if (sdb_data_parse(raw, SDB_TYPE_REGEX, &right->data)) - return NULL; - free(raw); - } - } - return M(sdb_object_create("regex-matcher", cmp_type, - MATCHER_REGEX, left, right)); -} /* sdb_store_regex_matcher */ - -sdb_store_matcher_t * -sdb_store_nregex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right) -{ - sdb_store_matcher_t *m = sdb_store_regex_matcher(left, right); - if (! m) - return NULL; - m->type = MATCHER_NREGEX; - return m; -} /* sdb_store_nregex_matcher */ - -sdb_store_matcher_t * -sdb_store_isnull_matcher(sdb_store_expr_t *expr) -{ - return M(sdb_object_create("isnull-matcher", unary_type, - MATCHER_ISNULL, expr)); -} /* sdb_store_isnull_matcher */ - -sdb_store_matcher_t * -sdb_store_istrue_matcher(sdb_store_expr_t *expr) -{ - return M(sdb_object_create("istrue-matcher", unary_type, - MATCHER_ISTRUE, expr)); -} /* sdb_store_istrue_matcher */ - -sdb_store_matcher_t * -sdb_store_isfalse_matcher(sdb_store_expr_t *expr) -{ - return M(sdb_object_create("isfalse-matcher", unary_type, - MATCHER_ISFALSE, expr)); -} /* sdb_store_isfalse_matcher */ - -sdb_store_matcher_t * -sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right) -{ - return M(sdb_object_create("dis-matcher", op_type, MATCHER_OR, - left, right)); -} /* sdb_store_dis_matcher */ - -sdb_store_matcher_t * -sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right) -{ - return M(sdb_object_create("con-matcher", op_type, MATCHER_AND, - left, right)); -} /* sdb_store_con_matcher */ - -sdb_store_matcher_t * -sdb_store_inv_matcher(sdb_store_matcher_t *m) -{ - return M(sdb_object_create("inv-matcher", uop_type, MATCHER_NOT, m)); -} /* sdb_store_inv_matcher */ - -int -sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter) -{ - if (filter && (! sdb_store_matcher_matches(filter, obj, NULL))) - return 0; - - /* "NULL" always matches */ - if ((! m) || (! obj)) - return 1; - - if ((m->type < 0) || ((size_t)m->type >= SDB_STATIC_ARRAY_LEN(matchers))) - return 0; - - if (! matchers[m->type]) - return 0; - return matchers[m->type](m, obj, filter); -} /* sdb_store_matcher_matches */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/src/core/store_query.c b/src/core/store_query.c deleted file mode 100644 index ff7089c..0000000 --- a/src/core/store_query.c +++ /dev/null @@ -1,354 +0,0 @@ -/* - * SysDB - src/core/store_query.c - * Copyright (C) 2014-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. - */ - -#include "core/object.h" -#include "core/store-private.h" -#include "parser/ast.h" -#include "utils/error.h" - -#include - -static sdb_store_matcher_t * -node_to_matcher(sdb_ast_node_t *n); - -static sdb_store_expr_t * -node_to_expr(sdb_ast_node_t *n) -{ - sdb_store_expr_t *left = NULL, *right = NULL; - sdb_store_expr_t *e; - int op; - - if (! n) { - sdb_log(SDB_LOG_ERR, "store: 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 " - "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); - return NULL; - } - - left = node_to_expr(SDB_AST_OP(n)->left); - if (! left) - return NULL; - right = node_to_expr(SDB_AST_OP(n)->right); - if (! right) { - sdb_object_deref(SDB_OBJ(left)); - return NULL; - } - op = SDB_AST_OP_TO_DATA_OP(SDB_AST_OP(n)->kind); - e = sdb_store_expr_create(op, left, right); - break; - - case SDB_AST_TYPE_CONST: - return sdb_store_expr_constvalue(&SDB_AST_CONST(n)->value); - - case SDB_AST_TYPE_VALUE: - if (SDB_AST_VALUE(n)->type == SDB_ATTRIBUTE) - return sdb_store_expr_attrvalue(SDB_AST_VALUE(n)->name); - return sdb_store_expr_fieldvalue(SDB_AST_VALUE(n)->type); - - case SDB_AST_TYPE_TYPED: - right = node_to_expr(SDB_AST_TYPED(n)->expr); - if (! right) - return NULL; - e = sdb_store_expr_typed(SDB_AST_TYPED(n)->type, right); - break; - - default: - sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)", - SDB_AST_TYPE_TO_STRING(n), n->type); - e = NULL; - } - - /* expressions take a reference */ - sdb_object_deref(SDB_OBJ(left)); - sdb_object_deref(SDB_OBJ(right)); - return e; -} /* node_to_expr */ - -static sdb_store_matcher_t * -logical_to_matcher(sdb_ast_node_t *n) -{ - sdb_store_matcher_t *left = NULL, *right; - sdb_store_matcher_t *m; - - if (SDB_AST_OP(n)->left) { - left = node_to_matcher(SDB_AST_OP(n)->left); - if (! left) - return NULL; - } - right = node_to_matcher(SDB_AST_OP(n)->right); - if (! right) { - sdb_object_deref(SDB_OBJ(left)); - return NULL; - } - - switch (SDB_AST_OP(n)->kind) { - case SDB_AST_AND: - m = sdb_store_con_matcher(left, right); - break; - case SDB_AST_OR: - m = sdb_store_dis_matcher(left, right); - break; - case SDB_AST_NOT: - m = sdb_store_inv_matcher(right); - break; - - default: - m = NULL; - } - - /* matchers take a reference */ - sdb_object_deref(SDB_OBJ(left)); - sdb_object_deref(SDB_OBJ(right)); - return m; -} /* logical_to_matcher */ - -static sdb_store_matcher_t * -cmp_to_matcher(sdb_ast_node_t *n) -{ - sdb_store_expr_t *left = NULL, *right; - sdb_store_matcher_t *m; - - if (SDB_AST_OP(n)->left) { - left = node_to_expr(SDB_AST_OP(n)->left); - if (! left) - return NULL; - } - right = node_to_expr(SDB_AST_OP(n)->right); - if (! right) { - sdb_object_deref(SDB_OBJ(left)); - return NULL; - } - - switch (SDB_AST_OP(n)->kind) { - case SDB_AST_LT: - m = sdb_store_lt_matcher(left, right); - break; - case SDB_AST_LE: - m = sdb_store_le_matcher(left, right); - break; - case SDB_AST_EQ: - m = sdb_store_eq_matcher(left, right); - break; - case SDB_AST_NE: - m = sdb_store_ne_matcher(left, right); - break; - case SDB_AST_GE: - m = sdb_store_ge_matcher(left, right); - break; - case SDB_AST_GT: - m = sdb_store_gt_matcher(left, right); - break; - case SDB_AST_REGEX: - m = sdb_store_regex_matcher(left, right); - break; - case SDB_AST_NREGEX: - m = sdb_store_nregex_matcher(left, right); - break; - case SDB_AST_ISNULL: - m = sdb_store_isnull_matcher(right); - break; - case SDB_AST_ISTRUE: - m = sdb_store_istrue_matcher(right); - break; - case SDB_AST_ISFALSE: - m = sdb_store_isfalse_matcher(right); - break; - case SDB_AST_IN: - m = sdb_store_in_matcher(left, right); - break; - - default: - sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)", - SDB_AST_TYPE_TO_STRING(n), n->type); - m = NULL; - } - - /* matchers take a reference */ - sdb_object_deref(SDB_OBJ(left)); - sdb_object_deref(SDB_OBJ(right)); - return m; -} /* cmp_to_matcher */ - -static sdb_store_matcher_t * -iter_to_matcher(sdb_ast_node_t *n) -{ - sdb_store_expr_t *iter; - sdb_store_matcher_t *expr, *m; - - assert((SDB_AST_ITER(n)->expr->type == SDB_AST_TYPE_OPERATOR) - && (! SDB_AST_OP(SDB_AST_ITER(n)->expr)->left)); - - iter = node_to_expr(SDB_AST_ITER(n)->iter); - if (! iter) - return NULL; - expr = cmp_to_matcher(SDB_AST_ITER(n)->expr); - if (! expr) { - sdb_object_deref(SDB_OBJ(iter)); - return NULL; - } - - switch (SDB_AST_ITER(n)->kind) { - case SDB_AST_ALL: - m = sdb_store_all_matcher(iter, expr); - break; - case SDB_AST_ANY: - m = sdb_store_any_matcher(iter, expr); - break; - - default: - sdb_log(SDB_LOG_ERR, "store: Invalid iterator node of type %s (%#x)", - SDB_AST_OP_TO_STRING(SDB_AST_ITER(n)->kind), SDB_AST_ITER(n)->kind); - m = NULL; - } - - /* matchers take a reference */ - sdb_object_deref(SDB_OBJ(iter)); - sdb_object_deref(SDB_OBJ(expr)); - return m; -} /* iter_to_matcher */ - -static sdb_store_matcher_t * -node_to_matcher(sdb_ast_node_t *n) -{ - int kind; - - if (! n) { - sdb_log(SDB_LOG_ERR, "store: 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 " - "type %s (%#x)", SDB_AST_TYPE_TO_STRING(n), n->type); - return NULL; - } - - kind = SDB_AST_OP(n)->kind; - if ((kind == SDB_AST_AND) || (kind == SDB_AST_OR) || (kind == SDB_AST_NOT)) - return logical_to_matcher(n); - else - return cmp_to_matcher(n); - - case SDB_AST_TYPE_ITERATOR: - return iter_to_matcher(n); - } - - sdb_log(SDB_LOG_ERR, "store: Invalid matcher node of type %s (%#x)", - SDB_AST_TYPE_TO_STRING(n), n->type); - return NULL; -} /* node_to_matcher */ - -/* - * query type - */ - -static int -query_init(sdb_object_t *obj, va_list ap) -{ - sdb_ast_node_t *ast = va_arg(ap, sdb_ast_node_t *); - sdb_ast_node_t *matcher = NULL, *filter = NULL; - - QUERY(obj)->ast = ast; - sdb_object_ref(SDB_OBJ(ast)); - - switch (ast->type) { - case SDB_AST_TYPE_FETCH: - filter = SDB_AST_FETCH(ast)->filter; - break; - case SDB_AST_TYPE_LIST: - filter = SDB_AST_LIST(ast)->filter; - break; - case SDB_AST_TYPE_LOOKUP: - matcher = SDB_AST_LOOKUP(ast)->matcher; - filter = SDB_AST_LOOKUP(ast)->filter; - break; - case SDB_AST_TYPE_STORE: - case SDB_AST_TYPE_TIMESERIES: - /* nothing to do */ - break; - - default: - sdb_log(SDB_LOG_ERR, "store: Invalid top-level AST node " - "of type %#x", ast->type); - return -1; - } - - if (matcher) { - QUERY(obj)->matcher = node_to_matcher(matcher); - if (! QUERY(obj)->matcher) - return -1; - } - if (filter) { - QUERY(obj)->filter = node_to_matcher(filter); - if (! QUERY(obj)->filter) - return -1; - } - - return 0; -} /* query_init */ - -static void -query_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(QUERY(obj)->ast)); - sdb_object_deref(SDB_OBJ(QUERY(obj)->matcher)); - sdb_object_deref(SDB_OBJ(QUERY(obj)->filter)); -} /* query_destroy */ - -static sdb_type_t query_type = { - /* size = */ sizeof(sdb_store_query_t), - /* init = */ query_init, - /* destroy = */ query_destroy, -}; - -/* - * public API - */ - -sdb_store_query_t * -sdb_store_query_prepare(sdb_ast_node_t *ast) -{ - if (! ast) - return NULL; - return QUERY(sdb_object_create(SDB_AST_TYPE_TO_STRING(ast), query_type, ast)); -} /* sdb_store_query_prepare */ - -sdb_store_matcher_t * -sdb_store_query_prepare_matcher(sdb_ast_node_t *ast) -{ - return node_to_matcher(ast); -} /* sdb_store_query_prepare_matcher */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index acdc699..03e58e5 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -83,193 +83,6 @@ struct sdb_conn { }; #define CONN(obj) ((sdb_conn_t *)(obj)) -/* - * node types - */ - -typedef struct { - sdb_conn_node_t super; - sdb_store_expr_t *expr; -} conn_expr_t; -#define CONN_EXPR(obj) ((conn_expr_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - sdb_store_matcher_t *matcher; -} conn_matcher_t; -#define CONN_MATCHER(obj) ((conn_matcher_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - int type; - conn_matcher_t *filter; -} conn_list_t; -#define CONN_LIST(obj) ((conn_list_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - int type; - char *host; - char *name; /* NULL for type == SDB_HOST */ - conn_matcher_t *filter; -} conn_fetch_t; -#define CONN_FETCH(obj) ((conn_fetch_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - int type; - conn_matcher_t *matcher; - conn_matcher_t *filter; -} conn_lookup_t; -#define CONN_LOOKUP(obj) ((conn_lookup_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - char *name; - sdb_time_t last_update; -} conn_store_host_t; -#define CONN_STORE_HOST(obj) ((conn_store_host_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - char *hostname; - char *name; - sdb_time_t last_update; -} conn_store_svc_t; -#define CONN_STORE_SVC(obj) ((conn_store_svc_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - char *hostname; - char *name; - char *store_type; /* optional */ - char *store_id; /* optional */ - sdb_time_t last_update; -} conn_store_metric_t; -#define CONN_STORE_METRIC(obj) ((conn_store_metric_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - int parent_type; - char *hostname; /* optional */ - char *parent; - char *key; - sdb_data_t value; - sdb_time_t last_update; -} conn_store_attr_t; -#define CONN_STORE_ATTR(obj) ((conn_store_attr_t *)(obj)) - -typedef struct { - sdb_conn_node_t super; - char *hostname; - char *metric; - sdb_timeseries_opts_t opts; -} conn_ts_t; -#define CONN_TS(obj) ((conn_ts_t *)(obj)) - -/* - * type helper functions - */ - -static void __attribute__((unused)) -conn_expr_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(CONN_EXPR(obj)->expr)); -} /* conn_expr_destroy */ - -static void __attribute__((unused)) -conn_matcher_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(CONN_MATCHER(obj)->matcher)); -} /* conn_matcher_destroy */ - -static void __attribute__((unused)) -conn_list_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(CONN_LIST(obj)->filter)); -} /* conn_list_destroy */ - -static void __attribute__((unused)) -conn_fetch_destroy(sdb_object_t *obj) -{ - if (CONN_FETCH(obj)->host) - free(CONN_FETCH(obj)->host); - if (CONN_FETCH(obj)->name) - free(CONN_FETCH(obj)->name); - sdb_object_deref(SDB_OBJ(CONN_FETCH(obj)->filter)); -} /* conn_fetch_destroy */ - -static void __attribute__((unused)) -conn_lookup_destroy(sdb_object_t *obj) -{ - sdb_object_deref(SDB_OBJ(CONN_LOOKUP(obj)->matcher)); - sdb_object_deref(SDB_OBJ(CONN_LOOKUP(obj)->filter)); -} /* conn_lookup_destroy */ - -static void __attribute__((unused)) -conn_store_host_destroy(sdb_object_t *obj) -{ - conn_store_host_t *host = CONN_STORE_HOST(obj); - if (host->name) - free((void *)host->name); - host->name = NULL; -} /* conn_store_host_destroy */ - -static void __attribute__((unused)) -conn_store_svc_destroy(sdb_object_t *obj) -{ - conn_store_svc_t *svc = CONN_STORE_SVC(obj); - if (svc->hostname) - free((void *)svc->hostname); - svc->hostname = NULL; - if (svc->name) - free((void *)svc->name); - svc->name = NULL; -} /* conn_store_svc_destroy */ - -static void __attribute__((unused)) -conn_store_metric_destroy(sdb_object_t *obj) -{ - conn_store_metric_t *metric = CONN_STORE_METRIC(obj); - if (metric->hostname) - free((void *)metric->hostname); - metric->hostname = NULL; - if (metric->name) - free((void *)metric->name); - metric->name = NULL; - if (metric->store_type) - free((void *)metric->store_type); - metric->store_type = NULL; - if (metric->store_id) - free((void *)metric->store_id); - metric->store_id = NULL; -} /* conn_store_metric_destroy */ - -static void __attribute__((unused)) -conn_store_attr_destroy(sdb_object_t *obj) -{ - conn_store_attr_t *attr = CONN_STORE_ATTR(obj); - if (attr->hostname) - free((void *)attr->hostname); - attr->hostname = NULL; - if (attr->parent) - free((void *)attr->parent); - attr->parent = NULL; - if (attr->key) - free((void *)attr->key); - attr->key = NULL; - sdb_data_free_datum(&attr->value); -} /* conn_store_attr_destroy */ - -static void __attribute__((unused)) -conn_ts_destroy(sdb_object_t *obj) -{ - if (CONN_TS(obj)->hostname) - free(CONN_TS(obj)->hostname); - if (CONN_TS(obj)->metric) - free(CONN_TS(obj)->metric); -} /* conn_ts_destroy */ - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/frontend/query.c b/src/frontend/query.c index 9a157fb..4ae4f64 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -46,8 +46,6 @@ /* * metric fetcher: * Implements the callbacks necessary to read a metric object. - * TODO: FETCH should allow to ignore child elements (attributes); then, we'd - * only need store_host/store_metric. */ typedef struct { @@ -77,15 +75,8 @@ metric_fetcher_metric(sdb_store_metric_t *metric, sdb_object_t *user_data) return 0; } /* metric_fetcher_metric */ -static int -metric_fetcher_attr(sdb_store_attribute_t __attribute__((unused)) *attr, - sdb_object_t __attribute__((unused)) *user_data) -{ - return 0; -} /* metric_fetcher_attr */ - static sdb_store_writer_t metric_fetcher = { - metric_fetcher_host, NULL, metric_fetcher_metric, metric_fetcher_attr, + metric_fetcher_host, NULL, metric_fetcher_metric, NULL, }; /* @@ -403,8 +394,9 @@ sdb_conn_fetch(sdb_conn_t *conn) ast = sdb_ast_fetch_create((int)type, hostname[0] ? strdup(hostname) : NULL, + -1, NULL, name[0] ? strdup(name) : NULL, - /* filter = */ NULL); + /* full */ 1, /* filter = */ NULL); status = exec_cmd(conn, ast); sdb_object_deref(SDB_OBJ(ast)); return status; diff --git a/src/include/core/memstore.h b/src/include/core/memstore.h new file mode 100644 index 0000000..8c1739e --- /dev/null +++ b/src/include/core/memstore.h @@ -0,0 +1,538 @@ +/* + * 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, sdb_time_t interval); +int +sdb_memstore_service(sdb_memstore_t *store, const char *hostname, const char *name, + sdb_time_t last_update, sdb_time_t interval); +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, sdb_time_t interval); +int +sdb_memstore_attribute(sdb_memstore_t *store, const char *hostname, + const char *key, const sdb_data_t *value, + sdb_time_t last_update, sdb_time_t interval); +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, sdb_time_t interval); +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_time_t interval); + +/* + * 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 an object'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 *obj, 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 4038fe4..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_store_t represents an in-memory store. It inherits from sdb_object_t - * and may safely be case to a generic object. - */ -struct sdb_store; -typedef struct sdb_store sdb_store_t; -#define SDB_STORE(obj) ((sdb_store_t *)(obj)) - -/* - * sdb_store_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_store_obj; -typedef struct sdb_store_obj sdb_store_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_store_expr; -typedef struct sdb_store_expr sdb_store_expr_t; -#define SDB_STORE_EXPR(obj) ((sdb_store_expr_t *)(obj)) - -/* - * An expression iterator iterates over the values of an iterable expression. - */ -struct sdb_store_expr_iter; -typedef struct sdb_store_expr_iter sdb_store_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_store_matcher; -typedef struct sdb_store_matcher sdb_store_matcher_t; -#define SDB_STORE_MATCHER(obj) ((sdb_store_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_store_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_store_writer; - /* * A store reader describes the interface to query a store implementation. */ @@ -300,422 +245,6 @@ typedef struct { sdb_strbuf_t *errbuf, sdb_object_t *user_data); } sdb_store_reader_t; -/* - * sdb_store_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_store_reader; - -/* - * sdb_store_create: - * Allocate a new in-memory store. - */ -sdb_store_t * -sdb_store_create(void); - -/* - * sdb_store_host, sdb_store_service, sdb_store_metric, sdb_store_attribute, - * sdb_store_metric_attr: - * Store an object in the specified store. The hostname is expected to be - * canonical. - */ -int -sdb_store_host(sdb_store_t *store, const char *name, sdb_time_t last_update); -int -sdb_store_service(sdb_store_t *store, const char *hostname, const char *name, - sdb_time_t last_update); -int -sdb_store_metric(sdb_store_t *store, const char *hostname, const char *name, - sdb_metric_store_t *metric_store, sdb_time_t last_update); -int -sdb_store_attribute(sdb_store_t *store, const char *hostname, - const char *key, const sdb_data_t *value, sdb_time_t last_update); -int -sdb_store_service_attr(sdb_store_t *store, const char *hostname, - const char *service, const char *key, const sdb_data_t *value, - sdb_time_t last_update); -int -sdb_store_metric_attr(sdb_store_t *store, const char *hostname, - const char *metric, const char *key, const sdb_data_t *value, - sdb_time_t last_update); - -/* - * sdb_store_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_store_obj_t * -sdb_store_get_host(sdb_store_t *store, const char *name); - -/* - * sdb_store_fetch_timeseries: - * Fetch the time-series described by the specified host's metric and - * serialize it as JSON into the provided string buffer. The host data is - * retrieved from the specified store. - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_store_fetch_timeseries(sdb_store_t *store, - const char *hostname, const char *metric, - sdb_timeseries_opts_t *opts, sdb_strbuf_t *buf); - -/* - * sdb_store_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_store_obj_t * -sdb_store_get_child(sdb_store_obj_t *host, int type, const char *name); - -/* - * sdb_store_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_store_get_field(sdb_store_obj_t *obj, int field, sdb_data_t *res); - -/* - * sdb_store_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_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res, - sdb_store_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_store_query_t: - * A parsed query readily prepared for execution. - */ -struct sdb_store_query; -typedef struct sdb_store_query sdb_store_query_t; - -/* - * sdb_store_query_prepare: - * Prepare the query described by 'ast' for execution in a store. - * - * Returns: - * - a store query on success - * - NULL else - */ -sdb_store_query_t * -sdb_store_query_prepare(sdb_ast_node_t *ast); - -/* - * sdb_store_query_prepare_matcher: - * Prepare the logical expression described by 'ast' for execution as a store - * matcher. - * - * Returns: - * - a matcher on success - * - NULL else - */ -sdb_store_matcher_t * -sdb_store_query_prepare_matcher(sdb_ast_node_t *ast); - -/* - * sdb_store_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_store_query_execute(sdb_store_t *store, sdb_store_query_t *m, - sdb_store_writer_t *w, sdb_object_t *wd, sdb_strbuf_t *errbuf); - -/* - * sdb_store_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_store_expr_t * -sdb_store_expr_create(int op, sdb_store_expr_t *left, sdb_store_expr_t *right); - -/* - * sdb_store_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_store_expr_t * -sdb_store_expr_typed(int typ, sdb_store_expr_t *expr); - -/* - * sdb_store_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_store_expr_t * -sdb_store_expr_fieldvalue(int field); - -/* - * sdb_store_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_store_expr_t * -sdb_store_expr_attrvalue(const char *name); - -/* - * sdb_store_expr_constvalue: - * Creates an expression which evaluates to the specified constant value. - * - * Returns: - * - an expression object on success - * - NULL else - */ -sdb_store_expr_t * -sdb_store_expr_constvalue(const sdb_data_t *value); - -/* - * sdb_store_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_store_expr_eval(sdb_store_expr_t *expr, sdb_store_obj_t *obj, - sdb_data_t *res, sdb_store_matcher_t *filter); - -/* - * sdb_store_expr_iter: - * Iterate over the elements of an iterable expression. sdb_store_expr_iter - * returns NULL if the expression is not iterable (for the specified object). - * - * sdb_store_expr_iter_get_next returns NULL if there is no next element. - */ -sdb_store_expr_iter_t * -sdb_store_expr_iter(sdb_store_expr_t *expr, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter); -void -sdb_store_expr_iter_destroy(sdb_store_expr_iter_t *iter); - -bool -sdb_store_expr_iter_has_next(sdb_store_expr_iter_t *iter); -sdb_data_t -sdb_store_expr_iter_get_next(sdb_store_expr_iter_t *iter); - -/* - * sdb_store_dis_matcher: - * Creates a matcher matching the disjunction (logical OR) of two matchers. - */ -sdb_store_matcher_t * -sdb_store_dis_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right); - -/* - * sdb_store_con_matcher: - * Creates a matcher matching the conjunction (logical AND) of two matchers. - */ -sdb_store_matcher_t * -sdb_store_con_matcher(sdb_store_matcher_t *left, sdb_store_matcher_t *right); - -/* - * sdb_store_inv_matcher:: - * Creates a matcher matching the inverse (logical NOT) of a matcher. - */ -sdb_store_matcher_t * -sdb_store_inv_matcher(sdb_store_matcher_t *m); - -/* - * sdb_store_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_store_matcher_t * -sdb_store_any_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m); - -/* - * sdb_store_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_store_matcher_t * -sdb_store_all_matcher(sdb_store_expr_t *iter, sdb_store_matcher_t *m); - -/* - * sdb_store_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_store_matcher_t * -sdb_store_in_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); - -/* - * sdb_store_lt_matcher, sdb_store_le_matcher, sdb_store_eq_matcher, - * sdb_store_ge_matcher, sdb_store_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_store_matcher_t * -sdb_store_lt_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); -sdb_store_matcher_t * -sdb_store_le_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); -sdb_store_matcher_t * -sdb_store_eq_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); -sdb_store_matcher_t * -sdb_store_ne_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); -sdb_store_matcher_t * -sdb_store_ge_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); -sdb_store_matcher_t * -sdb_store_gt_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); - -/* - * sdb_store_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_store_matcher_t * -sdb_store_regex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); - -/* - * sdb_store_nregex_matcher: - * Creates a regex matcher just like sdb_store_regex_matcher except that it - * matches in case the regular expression does not match. - */ -sdb_store_matcher_t * -sdb_store_nregex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right); - -/* - * sdb_store_isnull_matcher: - * Creates a matcher matching NULL values. - */ -sdb_store_matcher_t * -sdb_store_isnull_matcher(sdb_store_expr_t *expr); - -/* - * sdb_store_istrue_matcher, sdb_store_isfalse_matcher: - * Creates a matcher matching boolean values. - */ -sdb_store_matcher_t * -sdb_store_istrue_matcher(sdb_store_expr_t *expr); -sdb_store_matcher_t * -sdb_store_isfalse_matcher(sdb_store_expr_t *expr); - -/* - * sdb_store_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_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_obj_t *obj, - sdb_store_matcher_t *filter); - -/* - * sdb_store_matcher_op_cb: - * Callback constructing a matcher operator. - */ -typedef sdb_store_matcher_t *(*sdb_store_matcher_op_cb) - (sdb_store_expr_t *, sdb_store_expr_t *); - -/* - * sdb_store_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_store_lookup_cb)(sdb_store_obj_t *obj, - sdb_store_matcher_t *filter, void *user_data); - -/* - * sdb_store_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_store_matcher_matches' for details. - * - * Returns: - * - 0 on success - * - a negative value else - */ -int -sdb_store_scan(sdb_store_t *store, int type, - sdb_store_matcher_t *m, sdb_store_matcher_t *filter, - sdb_store_lookup_cb cb, void *user_data); - /* * Flags for JSON formatting. */ @@ -731,42 +260,6 @@ enum { sdb_store_json_formatter_t * sdb_store_json_formatter(sdb_strbuf_t *buf, int type, int flags); -/* - * sdb_store_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_store_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_store_emit(sdb_store_obj_t *obj, sdb_store_writer_t *w, sdb_object_t *wd); - -/* - * sdb_store_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_store_emit_full(sdb_store_obj_t *obj, sdb_store_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/include/parser/ast.h b/src/include/parser/ast.h index 8533fc7..01446ab 100644 --- a/src/include/parser/ast.h +++ b/src/include/parser/ast.h @@ -257,12 +257,17 @@ typedef struct { sdb_ast_node_t super; int obj_type; char *hostname; /* optional */ + int parent_type; /* optional */ + char *parent; /* optional */ char *name; + /* whether to include the full object, that is, + * including all attributes and all children */ + bool full; sdb_ast_node_t *filter; /* optional */ } sdb_ast_fetch_t; #define SDB_AST_FETCH(obj) ((sdb_ast_fetch_t *)(obj)) #define SDB_AST_FETCH_INIT \ - { { SDB_OBJECT_INIT, SDB_AST_TYPE_FETCH, -1 }, -1, NULL, NULL, NULL } + { { SDB_OBJECT_INIT, SDB_AST_TYPE_FETCH, -1 }, -1, NULL, -1, NULL, NULL, 0, NULL } /* * sdb_ast_list_t represents a LIST command. @@ -384,8 +389,9 @@ sdb_ast_value_create(int type, char *name); * takes ownership of the strings and the filter node. */ sdb_ast_node_t * -sdb_ast_fetch_create(int obj_type, char *hostname, char *name, - sdb_ast_node_t *filter); +sdb_ast_fetch_create(int obj_type, char *hostname, + int parent_type, char *parent, char *name, + bool full, sdb_ast_node_t *filter); /* * sdb_ast_list_create: diff --git a/src/parser/analyzer.c b/src/parser/analyzer.c index ecae40f..4adeafc 100644 --- a/src/parser/analyzer.c +++ b/src/parser/analyzer.c @@ -85,6 +85,79 @@ iter_error(sdb_strbuf_t *errbuf, sdb_ast_iter_t *iter, const char *reason, ...) r); } /* iter_error */ +/* + * generic checks + */ + +typedef struct { + int obj_type; + const char *hostname; + int parent_type; + const char *parent; + const char *name; +} parent_child_t; + +static int +analyze_parent_child(const char *cmd, parent_child_t *pc, sdb_strbuf_t *errbuf) +{ + if ((pc->obj_type != SDB_ATTRIBUTE) + && (! VALID_OBJ_TYPE(pc->obj_type))) { + sdb_strbuf_sprintf(errbuf, "Invalid object type %#x " + "in %s command", pc->obj_type, cmd); + return -1; + } + if (! pc->name) { + sdb_strbuf_sprintf(errbuf, "Missing object name in " + "%s %s command", cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type)); + return -1; + } + + if ((pc->obj_type == SDB_HOST) && pc->hostname) { + sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' " + "in %s HOST command", pc->hostname, cmd); + return -1; + } + else if ((pc->obj_type != SDB_HOST) && (! pc->hostname)) { + sdb_strbuf_sprintf(errbuf, "Missing parent hostname for '%s' " + "in %s %s command", pc->name, + cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type)); + return -1; + } + + if (pc->obj_type == SDB_ATTRIBUTE) { + if ((pc->parent_type <= 0) && pc->parent) { + sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' " + "in %s %s command", pc->parent, + cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type)); + return -1; + } + else if (pc->parent_type > 0) { + if (! VALID_OBJ_TYPE(pc->parent_type)) { + sdb_strbuf_sprintf(errbuf, "Invalid parent type %#x " + "in %s %s command", pc->parent_type, + cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type)); + return -1; + } + if (! pc->parent) { + sdb_strbuf_sprintf(errbuf, "Missing %s parent name " + "in %s %s command", + SDB_STORE_TYPE_TO_NAME(pc->parent_type), + cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type)); + return -1; + } + } + } + else if ((pc->parent_type > 0) || pc->parent) { + sdb_strbuf_sprintf(errbuf, "Unexpected %s parent name '%s' " + "in %s %s command", + SDB_STORE_TYPE_TO_NAME(pc->parent_type), + pc->parent ? pc->parent : "", + cmd, SDB_STORE_TYPE_TO_NAME(pc->obj_type)); + return -1; + } + return 0; +} /* analyze_parent_child */ + /* * expression nodes */ @@ -426,28 +499,13 @@ analyze_node(context_t ctx, sdb_ast_node_t *node, sdb_strbuf_t *errbuf) static int analyze_fetch(sdb_ast_fetch_t *fetch, sdb_strbuf_t *errbuf) { - if (! VALID_OBJ_TYPE(fetch->obj_type)) { - sdb_strbuf_sprintf(errbuf, "Invalid object type %#x " - "in FETCH command", fetch->obj_type); - return -1; - } - if (! fetch->name) { - sdb_strbuf_sprintf(errbuf, "Missing object name in " - "FETCH %s command", SDB_STORE_TYPE_TO_NAME(fetch->obj_type)); - return -1; - } + parent_child_t pc = { + fetch->obj_type, fetch->hostname, + fetch->parent_type, fetch->parent, fetch->name, + }; - if ((fetch->obj_type == SDB_HOST) && fetch->hostname) { - sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' " - "in FETCH HOST command", fetch->hostname); + if (analyze_parent_child("FETCH", &pc, errbuf)) return -1; - } - else if ((fetch->obj_type != SDB_HOST) && (! fetch->hostname)) { - sdb_strbuf_sprintf(errbuf, "Missing parent hostname for '%s' " - "in FETCH %s command", fetch->name, - SDB_STORE_TYPE_TO_NAME(fetch->obj_type)); - return -1; - } if (fetch->filter) return analyze_node(FILTER_CTX, fetch->filter, errbuf); @@ -488,61 +546,13 @@ analyze_lookup(sdb_ast_lookup_t *lookup, sdb_strbuf_t *errbuf) static int analyze_store(sdb_ast_store_t *st, sdb_strbuf_t *errbuf) { - if ((st->obj_type != SDB_ATTRIBUTE) - && (! VALID_OBJ_TYPE(st->obj_type))) { - sdb_strbuf_sprintf(errbuf, "Invalid object type %#x " - "in STORE command", st->obj_type); - return -1; - } - if (! st->name) { - sdb_strbuf_sprintf(errbuf, "Missing object name in " - "STORE %s command", SDB_STORE_TYPE_TO_NAME(st->obj_type)); - return -1; - } - - if ((st->obj_type == SDB_HOST) && st->hostname) { - sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' " - "in STORE HOST command", st->hostname); - return -1; - } - else if ((st->obj_type != SDB_HOST) && (! st->hostname)) { - sdb_strbuf_sprintf(errbuf, "Missing parent hostname for '%s' " - "in STORE %s command", st->name, - SDB_STORE_TYPE_TO_NAME(st->obj_type)); - return -1; - } + parent_child_t pc = { + st->obj_type, st->hostname, + st->parent_type, st->parent, st->name, + }; - if (st->obj_type == SDB_ATTRIBUTE) { - if ((st->parent_type <= 0) && st->parent) { - sdb_strbuf_sprintf(errbuf, "Unexpected parent hostname '%s' " - "in STORE %s command", st->parent, - SDB_STORE_TYPE_TO_NAME(st->obj_type)); - return -1; - } - else if (st->parent_type > 0) { - if (! VALID_OBJ_TYPE(st->parent_type)) { - sdb_strbuf_sprintf(errbuf, "Invalid parent type %#x " - "in STORE %s command", st->parent_type, - SDB_STORE_TYPE_TO_NAME(st->obj_type)); - return -1; - } - if (! st->parent) { - sdb_strbuf_sprintf(errbuf, "Missing %s parent name " - "in STORE %s command", - SDB_STORE_TYPE_TO_NAME(st->parent_type), - SDB_STORE_TYPE_TO_NAME(st->obj_type)); - return -1; - } - } - } - else if ((st->parent_type > 0) || st->parent) { - sdb_strbuf_sprintf(errbuf, "Unexpected %s parent name '%s' " - "in STORE %s command", - SDB_STORE_TYPE_TO_NAME(st->parent_type), - st->parent ? st->parent : "", - SDB_STORE_TYPE_TO_NAME(st->obj_type)); + if (analyze_parent_child("STORE", &pc, errbuf)) return -1; - } if (st->obj_type == SDB_METRIC) { if ((! st->store_type) != (! st->store_id)) { diff --git a/src/parser/ast.c b/src/parser/ast.c index 81a4c34..dcfe786 100644 --- a/src/parser/ast.c +++ b/src/parser/ast.c @@ -85,6 +85,8 @@ fetch_destroy(sdb_object_t *obj) sdb_ast_fetch_t *fetch = SDB_AST_FETCH(obj); if (fetch->hostname) free(fetch->hostname); + if (fetch->parent) + free(fetch->parent); if (fetch->name) free(fetch->name); fetch->hostname = fetch->name = NULL; @@ -289,8 +291,9 @@ sdb_ast_value_create(int type, char *name) } /* sdb_ast_value_create */ sdb_ast_node_t * -sdb_ast_fetch_create(int obj_type, char *hostname, char *name, - sdb_ast_node_t *filter) +sdb_ast_fetch_create(int obj_type, char *hostname, + int parent_type, char *parent, char *name, + bool full, sdb_ast_node_t *filter) { sdb_ast_fetch_t *fetch; fetch = SDB_AST_FETCH(sdb_object_create("FETCH", fetch_type)); @@ -301,7 +304,10 @@ sdb_ast_fetch_create(int obj_type, char *hostname, char *name, fetch->obj_type = obj_type; fetch->hostname = hostname; + fetch->parent_type = parent_type; + fetch->parent = parent; fetch->name = name; + fetch->full = full; fetch->filter = filter; return SDB_AST_NODE(fetch); } /* sdb_ast_fetch_create */ diff --git a/src/parser/grammar.y b/src/parser/grammar.y index 1b6d208..c350d54 100644 --- a/src/parser/grammar.y +++ b/src/parser/grammar.y @@ -281,13 +281,13 @@ statement: fetch_statement: FETCH object_type STRING filter_clause { - $$ = sdb_ast_fetch_create($2, NULL, $3, $4); + $$ = sdb_ast_fetch_create($2, NULL, -1, NULL, $3, 1, $4); CK_OOM($$); } | FETCH object_type STRING '.' STRING filter_clause { - $$ = sdb_ast_fetch_create($2, $3, $5, $6); + $$ = sdb_ast_fetch_create($2, $3, -1, NULL, $5, 1, $6); CK_OOM($$); } ; diff --git a/src/plugins/store/memory.c b/src/plugins/store/memory.c index 3cbc1e8..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" @@ -43,19 +44,19 @@ SDB_PLUGIN_MAGIC; static int mem_init(sdb_object_t *user_data) { - sdb_store_t *store = SDB_STORE(user_data); + sdb_memstore_t *store = SDB_MEMSTORE(user_data); if (! store) { sdb_log(SDB_LOG_ERR, "store: Failed to allocate store"); return -1; } if (sdb_plugin_register_writer("memstore", - &sdb_store_writer, SDB_OBJ(store))) { + &sdb_memstore_writer, SDB_OBJ(store))) { sdb_object_deref(SDB_OBJ(store)); return -1; } if (sdb_plugin_register_reader("memstore", - &sdb_store_reader, SDB_OBJ(store))) { + &sdb_memstore_reader, SDB_OBJ(store))) { sdb_object_deref(SDB_OBJ(store)); return -1; } @@ -73,7 +74,7 @@ int sdb_module_init(sdb_plugin_info_t *info) { /* store singleton */ - static sdb_store_t *store; + static sdb_memstore_t *store; sdb_plugin_set_info(info, SDB_PLUGIN_INFO_DESC, "in-memory object store"); sdb_plugin_set_info(info, SDB_PLUGIN_INFO_COPYRIGHT, @@ -83,7 +84,7 @@ sdb_module_init(sdb_plugin_info_t *info) sdb_plugin_set_info(info, SDB_PLUGIN_INFO_PLUGIN_VERSION, SDB_VERSION); if (! store) { - if (! (store = sdb_store_create())) { + if (! (store = sdb_memstore_create())) { sdb_log(SDB_LOG_ERR, "store::memory plugin: " "Failed to create store object"); return -1; diff --git a/t/unit/core/store_expr_test.c b/t/unit/core/store_expr_test.c index 3f21a82..c73ab34 100644 --- a/t/unit/core/store_expr_test.c +++ b/t/unit/core/store_expr_test.c @@ -30,13 +30,13 @@ #endif #include "core/store.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "parser/parser.h" #include "testutils.h" #include -static sdb_store_t *store; +static sdb_memstore_t *store; static void populate(void) @@ -94,43 +94,43 @@ populate(void) size_t i; - store = sdb_store_create(); + store = sdb_memstore_create(); ck_assert(store != NULL); for (i = 0; i < SDB_STATIC_ARRAY_LEN(hosts); ++i) { - int status = sdb_store_host(store, hosts[i], 1); + int status = sdb_memstore_host(store, hosts[i], 1, 0); ck_assert(status == 0); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(metrics); ++i) { - int status = sdb_store_metric(store, metrics[i].host, - metrics[i].metric, /* store */ NULL, 1); + int status = sdb_memstore_metric(store, metrics[i].host, + metrics[i].metric, /* store */ NULL, 1, 0); ck_assert(status == 0); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(services); ++i) { - int status = sdb_store_service(store, services[i].host, - services[i].service, 1); + int status = sdb_memstore_service(store, services[i].host, + services[i].service, 1, 0); ck_assert(status == 0); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(attrs); ++i) { - int status = sdb_store_attribute(store, attrs[i].host, - attrs[i].name, &attrs[i].value, 1); + int status = sdb_memstore_attribute(store, attrs[i].host, + attrs[i].name, &attrs[i].value, 1, 0); ck_assert(status == 0); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(svc_attrs); ++i) { - int status = sdb_store_service_attr(store, svc_attrs[i].host, + int status = sdb_memstore_service_attr(store, svc_attrs[i].host, svc_attrs[i].service, svc_attrs[i].name, - &svc_attrs[i].value, 1); + &svc_attrs[i].value, 1, 0); ck_assert(status == 0); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(metric_attrs); ++i) { - int status = sdb_store_metric_attr(store, metric_attrs[i].host, + int status = sdb_memstore_metric_attr(store, metric_attrs[i].host, metric_attrs[i].metric, metric_attrs[i].name, - &metric_attrs[i].value, 1); + &metric_attrs[i].value, 1, 0); ck_assert(status == 0); } } /* populate */ @@ -151,7 +151,7 @@ turndown(void) #define SERVICES { SDB_TYPE_INTEGER, { .integer = SDB_SERVICE } } #define METRICS { SDB_TYPE_INTEGER, { .integer = SDB_METRIC } } #define ATTRS { SDB_TYPE_INTEGER, { .integer = SDB_ATTRIBUTE } } -static sdb_store_expr_t namer = { +static sdb_memstore_expr_t namer = { SDB_OBJECT_INIT, FIELD_VALUE, -1, NULL, NULL, NAME, }; static int64_t int_values[] = { 1, 2, 3, 4, 5 }; @@ -163,7 +163,7 @@ static struct { unsigned char *datum; } bin_values[] = { { 4, (unsigned char *)"\3\2\0\1" } }; struct { - sdb_store_expr_t expr; + sdb_memstore_expr_t expr; bool iterable; char *host; @@ -555,19 +555,19 @@ struct { START_TEST(test_expr_iter) { - sdb_store_obj_t *obj = NULL; - sdb_store_matcher_t *filter = NULL; + sdb_memstore_obj_t *obj = NULL; + sdb_memstore_matcher_t *filter = NULL; int context = SDB_HOST; - sdb_store_expr_iter_t *iter; + sdb_memstore_expr_iter_t *iter; size_t i; if (expr_iter_data[_i].host) { - obj = sdb_store_get_host(store, expr_iter_data[_i].host); + obj = sdb_memstore_get_host(store, expr_iter_data[_i].host); ck_assert(obj != NULL); if (expr_iter_data[_i].child) { - sdb_store_obj_t *child = sdb_store_get_child(obj, + sdb_memstore_obj_t *child = sdb_memstore_get_child(obj, expr_iter_data[_i].child_type, expr_iter_data[_i].child); ck_assert(child != NULL); sdb_object_deref(SDB_OBJ(obj)); @@ -580,14 +580,14 @@ START_TEST(test_expr_iter) if (expr_iter_data[_i].filter) { sdb_ast_node_t *ast; ast = sdb_parser_parse_conditional(context, expr_iter_data[_i].filter, -1, NULL); - filter = sdb_store_query_prepare_matcher(ast); + filter = sdb_memstore_query_prepare_matcher(ast); sdb_object_deref(SDB_OBJ(ast)); ck_assert(filter != NULL); } - iter = sdb_store_expr_iter(&expr_iter_data[_i].expr, obj, filter); + iter = sdb_memstore_expr_iter(&expr_iter_data[_i].expr, obj, filter); fail_unless((iter != NULL) == expr_iter_data[_i].iterable, - "sdb_store_expr_iter(%s expression, %s, %s) = %s; expected: %s", + "sdb_memstore_expr_iter(%s expression, %s, %s) = %s; expected: %s", EXPR_TO_STRING(&expr_iter_data[_i].expr), obj ? SDB_STORE_TYPE_TO_NAME(obj->type) : "", expr_iter_data[_i].filter, iter ? "" : "NULL", @@ -598,7 +598,7 @@ START_TEST(test_expr_iter) sdb_object_deref(SDB_OBJ(filter)); filter = NULL; i = 0; - while (sdb_store_expr_iter_has_next(iter)) { + while (sdb_memstore_expr_iter_has_next(iter)) { char v_str[64], expected_str[64]; sdb_data_t v; @@ -608,7 +608,7 @@ START_TEST(test_expr_iter) SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter, i + 1, expr_iter_data[_i].expected_len); - v = sdb_store_expr_iter_get_next(iter); + v = sdb_memstore_expr_iter_get_next(iter); sdb_data_format(&v, v_str, sizeof(v_str), SDB_DOUBLE_QUOTED); sdb_data_format(&expr_iter_data[_i].expected[i], expected_str, sizeof(expected_str), SDB_DOUBLE_QUOTED); @@ -627,12 +627,12 @@ START_TEST(test_expr_iter) "expected: %zu", EXPR_TO_STRING(&expr_iter_data[_i].expr), SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter, i, expr_iter_data[_i].expected_len); - fail_unless(sdb_store_expr_iter_get_next(iter).type == SDB_TYPE_NULL, + fail_unless(sdb_memstore_expr_iter_get_next(iter).type == SDB_TYPE_NULL, "iter<%s expression, %s, %s> returned further elements " "passed the end", EXPR_TO_STRING(&expr_iter_data[_i].expr), SDB_STORE_TYPE_TO_NAME(context), expr_iter_data[_i].filter); - sdb_store_expr_iter_destroy(iter); + sdb_memstore_expr_iter_destroy(iter); } END_TEST diff --git a/t/unit/core/store_json_test.c b/t/unit/core/store_json_test.c index b880f7b..a0447b6 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" @@ -39,55 +40,53 @@ #undef SDB_INTERVAL_SECOND #define SDB_INTERVAL_SECOND 1000000000L -static sdb_store_t *store; +static sdb_memstore_t *store; static void populate(void) { sdb_data_t datum; - store = sdb_store_create(); + store = sdb_memstore_create(); ck_assert(store != NULL); - sdb_store_host(store, "h1", 1 * SDB_INTERVAL_SECOND); - sdb_store_host(store, "h2", 3 * SDB_INTERVAL_SECOND); + sdb_memstore_host(store, "h1", 1 * SDB_INTERVAL_SECOND, 0); + sdb_memstore_host(store, "h2", 3 * SDB_INTERVAL_SECOND, 0); datum.type = SDB_TYPE_STRING; datum.data.string = "v1"; - sdb_store_attribute(store, "h1", "k1", &datum, 1 * SDB_INTERVAL_SECOND); + sdb_memstore_attribute(store, "h1", "k1", &datum, 1 * SDB_INTERVAL_SECOND, 0); datum.data.string = "v2"; - sdb_store_attribute(store, "h1", "k2", &datum, 2 * SDB_INTERVAL_SECOND); + sdb_memstore_attribute(store, "h1", "k2", &datum, 2 * SDB_INTERVAL_SECOND, 0); datum.data.string = "v3"; - sdb_store_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND); + sdb_memstore_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND, 0); +/* TODO: move these tests into generic store tests */ +#if 0 /* make sure that older updates don't overwrite existing values */ datum.data.string = "fail"; - sdb_store_attribute(store, "h1", "k2", &datum, 1 * SDB_INTERVAL_SECOND); - sdb_store_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND); + sdb_memstore_attribute(store, "h1", "k2", &datum, 1 * SDB_INTERVAL_SECOND, 0); + sdb_memstore_attribute(store, "h1", "k3", &datum, 2 * SDB_INTERVAL_SECOND, 0); +#endif - sdb_store_metric(store, "h1", "m1", /* store */ NULL, 2 * SDB_INTERVAL_SECOND); - sdb_store_metric(store, "h1", "m2", /* store */ NULL, 1 * SDB_INTERVAL_SECOND); - sdb_store_metric(store, "h2", "m1", /* store */ NULL, 1 * SDB_INTERVAL_SECOND); + sdb_memstore_metric(store, "h1", "m1", /* store */ NULL, 2 * SDB_INTERVAL_SECOND, 0); + sdb_memstore_metric(store, "h1", "m2", /* store */ NULL, 1 * SDB_INTERVAL_SECOND, 0); + sdb_memstore_metric(store, "h2", "m1", /* store */ NULL, 1 * SDB_INTERVAL_SECOND, 0); - sdb_store_service(store, "h2", "s1", 1 * SDB_INTERVAL_SECOND); - sdb_store_service(store, "h2", "s2", 2 * SDB_INTERVAL_SECOND); + sdb_memstore_service(store, "h2", "s1", 1 * SDB_INTERVAL_SECOND, 0); + sdb_memstore_service(store, "h2", "s2", 2 * SDB_INTERVAL_SECOND, 0); datum.type = SDB_TYPE_INTEGER; datum.data.integer = 42; - sdb_store_metric_attr(store, "h1", "m1", "k3", - &datum, 2 * SDB_INTERVAL_SECOND); + sdb_memstore_metric_attr(store, "h1", "m1", "k3", + &datum, 2 * SDB_INTERVAL_SECOND, 0); datum.data.integer = 123; - sdb_store_service_attr(store, "h2", "s2", "k1", - &datum, 2 * SDB_INTERVAL_SECOND); + sdb_memstore_service_attr(store, "h2", "s2", "k1", + &datum, 2 * SDB_INTERVAL_SECOND, 0); datum.data.integer = 4711; - sdb_store_service_attr(store, "h2", "s2", "k2", - &datum, 1 * SDB_INTERVAL_SECOND); - - /* don't overwrite k1 */ - datum.data.integer = 666; - sdb_store_service_attr(store, "h2", "s2", "k1", - &datum, 2 * SDB_INTERVAL_SECOND); + sdb_memstore_service_attr(store, "h2", "s2", "k2", + &datum, 1 * SDB_INTERVAL_SECOND, 0); } /* populate */ static void @@ -98,18 +97,18 @@ turndown(void) } /* turndown */ static int -scan_tojson(sdb_store_obj_t *obj, - sdb_store_matcher_t __attribute__((unused)) *filter, +scan_tojson(sdb_memstore_obj_t *obj, + sdb_memstore_matcher_t __attribute__((unused)) *filter, void *user_data) { - return sdb_store_emit(obj, &sdb_store_json_writer, user_data); + return sdb_memstore_emit(obj, &sdb_store_json_writer, user_data); } /* scan_tojson */ static int -scan_tojson_full(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, +scan_tojson_full(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data) { - return sdb_store_emit_full(obj, filter, &sdb_store_json_writer, user_data); + return sdb_memstore_emit_full(obj, filter, &sdb_store_json_writer, user_data); } /* scan_tojson_full */ static void @@ -140,12 +139,12 @@ verify_json_output(sdb_strbuf_t *buf, const char *expected) struct { struct { - sdb_store_matcher_t *(*m)(sdb_store_expr_t *, sdb_store_expr_t *); + sdb_memstore_matcher_t *(*m)(sdb_memstore_expr_t *, sdb_memstore_expr_t *); int field; sdb_data_t value; } filter; int type; - int (*f)(sdb_store_obj_t *, sdb_store_matcher_t *, void *); + int (*f)(sdb_memstore_obj_t *, sdb_memstore_matcher_t *, void *); const char *expected; } store_tojson_data[] = { { { NULL, 0, SDB_DATA_INIT }, @@ -212,14 +211,14 @@ struct { "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", " "\"update_interval\": \"0s\", \"backends\": []}" "]" }, - { { sdb_store_eq_matcher, SDB_FIELD_NAME, + { { sdb_memstore_eq_matcher, SDB_FIELD_NAME, { SDB_TYPE_STRING, { .string = "h1" } } }, SDB_HOST, scan_tojson_full, "[" "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", " "\"update_interval\": \"0s\", \"backends\": []}" "]" }, - { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_gt_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } }, SDB_HOST, scan_tojson_full, "[" @@ -236,7 +235,7 @@ struct { "]}" "]}" "]" }, - { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_le_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } }, SDB_HOST, scan_tojson_full, "[" @@ -254,14 +253,14 @@ struct { "\"update_interval\": \"0s\", \"backends\": []}" "]}" "]" }, - { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_ge_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 3 * SDB_INTERVAL_SECOND } } }, SDB_HOST, scan_tojson_full, "[" "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", " "\"update_interval\": \"0s\", \"backends\": []}" "]" }, - { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_lt_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 0 } } }, SDB_HOST, scan_tojson_full, "[]" }, @@ -294,7 +293,7 @@ struct { "\"last_update\": \"1970-01-01 00:00:02 +0000\", " "\"update_interval\": \"0s\", \"backends\": []}" "]" }, - { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_gt_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } }, SDB_SERVICE, scan_tojson_full, "[" @@ -307,7 +306,7 @@ struct { "\"update_interval\": \"0s\", \"backends\": []}" "]}" "]" }, - { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_lt_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 0 } } }, SDB_SERVICE, scan_tojson_full, "[]" }, @@ -348,7 +347,7 @@ struct { "\"last_update\": \"1970-01-01 00:00:01 +0000\", " "\"update_interval\": \"0s\", \"backends\": []}" "]" }, - { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_le_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } }, SDB_METRIC, scan_tojson_full, "[" @@ -357,7 +356,7 @@ struct { "\"last_update\": \"1970-01-01 00:00:01 +0000\", " "\"update_interval\": \"0s\", \"backends\": []}" "]" }, - { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE, + { { sdb_memstore_lt_matcher, SDB_FIELD_LAST_UPDATE, { SDB_TYPE_DATETIME, { .datetime = 0 } } }, SDB_METRIC, scan_tojson_full, "[]" }, @@ -366,24 +365,24 @@ struct { START_TEST(test_store_tojson) { sdb_strbuf_t *buf = sdb_strbuf_create(0); - sdb_store_matcher_t *filter = NULL; + sdb_memstore_matcher_t *filter = NULL; sdb_store_json_formatter_t *f; int status; if (store_tojson_data[_i].filter.m) { - sdb_store_expr_t *field; - sdb_store_expr_t *value; + sdb_memstore_expr_t *field; + sdb_memstore_expr_t *value; - field = sdb_store_expr_fieldvalue(store_tojson_data[_i].filter.field); + field = sdb_memstore_expr_fieldvalue(store_tojson_data[_i].filter.field); fail_unless(field != NULL, - "INTERNAL ERROR: sdb_store_expr_fieldvalue() = NULL"); - value = sdb_store_expr_constvalue(&store_tojson_data[_i].filter.value); + "INTERNAL ERROR: sdb_memstore_expr_fieldvalue() = NULL"); + value = sdb_memstore_expr_constvalue(&store_tojson_data[_i].filter.value); fail_unless(value != NULL, - "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL"); + "INTERNAL ERROR: sdb_memstore_expr_constvalue() = NULL"); filter = store_tojson_data[_i].filter.m(field, value); fail_unless(filter != NULL, - "INTERNAL ERROR: sdb_store_*_matcher() = NULL"); + "INTERNAL ERROR: sdb_memstore_*_matcher() = NULL"); sdb_object_deref(SDB_OBJ(field)); sdb_object_deref(SDB_OBJ(value)); @@ -393,10 +392,10 @@ START_TEST(test_store_tojson) f = sdb_store_json_formatter(buf, store_tojson_data[_i].type, SDB_WANT_ARRAY); ck_assert(f != NULL); - status = sdb_store_scan(store, store_tojson_data[_i].type, + status = sdb_memstore_scan(store, store_tojson_data[_i].type, /* m = */ NULL, filter, store_tojson_data[_i].f, f); fail_unless(status == 0, - "sdb_store_scan(HOST, ..., tojson) = %d; expected: 0", + "sdb_memstore_scan(HOST, ..., tojson) = %d; expected: 0", status); sdb_store_json_finish(f); diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index d2c0064..0c30160 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -31,14 +31,14 @@ #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" #include #include -static sdb_store_t *store; +static sdb_memstore_t *store; static void populate(void) @@ -76,37 +76,37 @@ populate(void) size_t i; - store = sdb_store_create(); + store = sdb_memstore_create(); ck_assert(store != NULL); for (i = 0; i < SDB_STATIC_ARRAY_LEN(hosts); ++i) { - int status = sdb_store_host(store, hosts[i], 1); + int status = sdb_memstore_host(store, hosts[i], 1, 0); fail_unless(status == 0, - "sdb_store_host(%s, 1) = %d; expected: 0", + "sdb_memstore_host(%s, 1, 0) = %d; expected: 0", hosts[i], status); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(metrics); ++i) { - int status = sdb_store_metric(store, metrics[i].host, - metrics[i].metric, /* store */ NULL, 1); + int status = sdb_memstore_metric(store, metrics[i].host, + metrics[i].metric, /* store */ NULL, 1, 0); fail_unless(status == 0, - "sdb_store_metric(%s, %s, NULL, 1) = %d; expected: 0", + "sdb_memstore_metric(%s, %s, NULL, 1, 0) = %d; expected: 0", metrics[i].host, metrics[i].metric, status); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(services); ++i) { - int status = sdb_store_service(store, services[i].host, - services[i].service, 1); + int status = sdb_memstore_service(store, services[i].host, + services[i].service, 1, 0); fail_unless(status == 0, - "sdb_store_service(%s, %s, 1) = %d; expected: 0", + "sdb_memstore_service(%s, %s, 1, 0) = %d; expected: 0", services[i].host, services[i].service, status); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(attrs); ++i) { - int status = sdb_store_attribute(store, attrs[i].host, - attrs[i].name, &attrs[i].value, 1); + int status = sdb_memstore_attribute(store, attrs[i].host, + attrs[i].name, &attrs[i].value, 1, 0); fail_unless(status == 0, - "sdb_store_attribute(%s, %s, , 1) = %d; expected: 0", + "sdb_memstore_attribute(%s, %s, , 1, 0) = %d; expected: 0", attrs[i].host, attrs[i].name, status); } } /* populate */ @@ -161,41 +161,41 @@ struct { START_TEST(test_cmp_name) { - sdb_store_obj_t *host; + sdb_memstore_obj_t *host; sdb_data_t datum; - sdb_store_expr_t *obj = NULL, *value; - sdb_store_matcher_t *m, *n; + sdb_memstore_expr_t *obj = NULL, *value; + sdb_memstore_matcher_t *m, *n; int status; - host = sdb_store_get_host(store, "a"); + host = sdb_memstore_get_host(store, "a"); fail_unless(host != NULL, - "sdb_store_get_host(a) = NULL; expected: "); + "sdb_memstore_get_host(a) = NULL; expected: "); datum.type = SDB_TYPE_STRING; datum.data.string = cmp_name_data[_i].name; if (cmp_name_data[_i].type == SDB_HOST) { - obj = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); + obj = sdb_memstore_expr_fieldvalue(SDB_FIELD_NAME); fail_unless(obj != NULL, - "sdb_store_expr_fieldvalue(SDB_STORE_NAME) = NULL; " + "sdb_memstore_expr_fieldvalue(SDB_STORE_NAME) = NULL; " "expected: "); } - value = sdb_store_expr_constvalue(&datum); + value = sdb_memstore_expr_constvalue(&datum); fail_unless(value != NULL, - "sdb_store_expr_constvalue(%s) = NULL; " + "sdb_memstore_expr_constvalue(%s) = NULL; " "expected: ", cmp_name_data[_i].name); if (cmp_name_data[_i].re) - m = sdb_store_regex_matcher(obj, value); + m = sdb_memstore_regex_matcher(obj, value); else - m = sdb_store_eq_matcher(obj, value); + m = sdb_memstore_eq_matcher(obj, value); if (cmp_name_data[_i].type != SDB_HOST) { - sdb_store_expr_t *iter; - sdb_store_matcher_t *tmp; - obj = sdb_store_expr_fieldvalue(SDB_FIELD_NAME); - iter = sdb_store_expr_typed(cmp_name_data[_i].type, obj); - tmp = sdb_store_any_matcher(iter, m); + sdb_memstore_expr_t *iter; + sdb_memstore_matcher_t *tmp; + obj = sdb_memstore_expr_fieldvalue(SDB_FIELD_NAME); + iter = sdb_memstore_expr_typed(cmp_name_data[_i].type, obj); + tmp = sdb_memstore_any_matcher(iter, m); ck_assert(iter && m); sdb_object_deref(SDB_OBJ(iter)); sdb_object_deref(SDB_OBJ(m)); @@ -204,27 +204,27 @@ START_TEST(test_cmp_name) sdb_object_deref(SDB_OBJ(obj)); sdb_object_deref(SDB_OBJ(value)); fail_unless(m != NULL, - "sdb_store_%s_matcher(%s, %s) = NULL; " + "sdb_memstore_%s_matcher(%s, %s) = NULL; " "expected: ", cmp_name_data[_i].re ? "regex" : "eq", SDB_STORE_TYPE_TO_NAME(cmp_name_data[_i].type), cmp_name_data[_i].name); - status = sdb_store_matcher_matches(m, host, /* filter */ NULL); + status = sdb_memstore_matcher_matches(m, host, /* filter */ NULL); fail_unless(status == cmp_name_data[_i].expected, - "sdb_store_matcher_matches(%s->%s, , NULL) = %d; " + "sdb_memstore_matcher_matches(%s->%s, , NULL) = %d; " "expected: %d", SDB_STORE_TYPE_TO_NAME(cmp_name_data[_i].type), cmp_name_data[_i].name, status, cmp_name_data[_i].expected); - n = sdb_store_inv_matcher(m); + n = sdb_memstore_inv_matcher(m); fail_unless(n != NULL, - "sdb_store_inv_matcher() = NULL; expected: "); + "sdb_memstore_inv_matcher() = NULL; expected: "); sdb_object_deref(SDB_OBJ(m)); /* now match the inverted set of objects */ - status = sdb_store_matcher_matches(n, host, /* filter */ NULL); + status = sdb_memstore_matcher_matches(n, host, /* filter */ NULL); fail_unless(status == !cmp_name_data[_i].expected, - "sdb_store_matcher_matches(%s->%s, , NULL) = %d; " + "sdb_memstore_matcher_matches(%s->%s, , NULL) = %d; " "expected: %d", SDB_STORE_TYPE_TO_NAME(cmp_name_data[_i].type), cmp_name_data[_i].name, status, !cmp_name_data[_i].expected); @@ -256,55 +256,55 @@ struct { START_TEST(test_cmp_attr) { - sdb_store_obj_t *host; - sdb_store_expr_t *attr; - sdb_store_expr_t *value; + sdb_memstore_obj_t *host; + sdb_memstore_expr_t *attr; + sdb_memstore_expr_t *value; char value_str[1024]; int status; size_t j; struct { - sdb_store_matcher_t *(*matcher)(sdb_store_expr_t *, - sdb_store_expr_t *); + sdb_memstore_matcher_t *(*matcher)(sdb_memstore_expr_t *, + sdb_memstore_expr_t *); int expected; } tests[] = { - { sdb_store_lt_matcher, cmp_attr_data[_i].expected_lt }, - { sdb_store_le_matcher, cmp_attr_data[_i].expected_le }, - { sdb_store_eq_matcher, cmp_attr_data[_i].expected_eq }, - { sdb_store_ge_matcher, cmp_attr_data[_i].expected_ge }, - { sdb_store_gt_matcher, cmp_attr_data[_i].expected_gt }, + { sdb_memstore_lt_matcher, cmp_attr_data[_i].expected_lt }, + { sdb_memstore_le_matcher, cmp_attr_data[_i].expected_le }, + { sdb_memstore_eq_matcher, cmp_attr_data[_i].expected_eq }, + { sdb_memstore_ge_matcher, cmp_attr_data[_i].expected_ge }, + { sdb_memstore_gt_matcher, cmp_attr_data[_i].expected_gt }, }; const char *op_str[] = { "<", "<=", "=", ">=", ">" }; ck_assert(SDB_STATIC_ARRAY_LEN(tests) == SDB_STATIC_ARRAY_LEN(op_str)); - host = sdb_store_get_host(store, "a"); + host = sdb_memstore_get_host(store, "a"); fail_unless(host != NULL, - "sdb_store_get_host(a) = NULL; expected: "); + "sdb_memstore_get_host(a) = NULL; expected: "); sdb_data_format(&cmp_attr_data[_i].value, value_str, sizeof(value_str), SDB_UNQUOTED); - attr = sdb_store_expr_attrvalue(cmp_attr_data[_i].attr); + attr = sdb_memstore_expr_attrvalue(cmp_attr_data[_i].attr); fail_unless(attr != NULL, - "sdb_store_expr_attrvalue(%s) = NULL; expected: ", + "sdb_memstore_expr_attrvalue(%s) = NULL; expected: ", cmp_attr_data[_i].attr); - value = sdb_store_expr_constvalue(&cmp_attr_data[_i].value); + value = sdb_memstore_expr_constvalue(&cmp_attr_data[_i].value); fail_unless(value != NULL, - "sdb_store_expr_constvalue(%s) = NULL; expected: ", + "sdb_memstore_expr_constvalue(%s) = NULL; expected: ", value_str); for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) { - sdb_store_matcher_t *m; + sdb_memstore_matcher_t *m; m = tests[j].matcher(attr, value); fail_unless(m != NULL, - "sdb_store__matcher() = NULL; expected: "); + "sdb_memstore__matcher() = NULL; expected: "); - status = sdb_store_matcher_matches(m, host, /* filter */ NULL); + status = sdb_memstore_matcher_matches(m, host, /* filter */ NULL); fail_unless(status == tests[j].expected, - "sdb_store_matcher_matches(, " + "sdb_memstore_matcher_matches(, " ", NULL) = %d; expected: %d", cmp_attr_data[_i].attr, op_str[j], value_str, status, tests[j].expected); @@ -364,49 +364,49 @@ struct { START_TEST(test_cmp_obj) { - sdb_store_obj_t *host; - sdb_store_expr_t *field; - sdb_store_expr_t *value; + sdb_memstore_obj_t *host; + sdb_memstore_expr_t *field; + sdb_memstore_expr_t *value; char value_str[1024]; int status; size_t j; struct { - sdb_store_matcher_t *(*matcher)(sdb_store_expr_t *, - sdb_store_expr_t *); + sdb_memstore_matcher_t *(*matcher)(sdb_memstore_expr_t *, + sdb_memstore_expr_t *); int expected; } tests[] = { - { sdb_store_lt_matcher, cmp_obj_data[_i].expected_lt }, - { sdb_store_le_matcher, cmp_obj_data[_i].expected_le }, - { sdb_store_eq_matcher, cmp_obj_data[_i].expected_eq }, - { sdb_store_ge_matcher, cmp_obj_data[_i].expected_ge }, - { sdb_store_gt_matcher, cmp_obj_data[_i].expected_gt }, + { sdb_memstore_lt_matcher, cmp_obj_data[_i].expected_lt }, + { sdb_memstore_le_matcher, cmp_obj_data[_i].expected_le }, + { sdb_memstore_eq_matcher, cmp_obj_data[_i].expected_eq }, + { sdb_memstore_ge_matcher, cmp_obj_data[_i].expected_ge }, + { sdb_memstore_gt_matcher, cmp_obj_data[_i].expected_gt }, }; char *op_str[] = { "<", "<=", "=", ">=", ">" }; ck_assert(SDB_STATIC_ARRAY_LEN(tests) == SDB_STATIC_ARRAY_LEN(op_str)); - host = sdb_store_get_host(store, cmp_obj_data[_i].host); + host = sdb_memstore_get_host(store, cmp_obj_data[_i].host); fail_unless(host != NULL, - "sdb_store_get_host(%s) = NULL; expected: ", + "sdb_memstore_get_host(%s) = NULL; expected: ", cmp_obj_data[_i].host); sdb_data_format(&cmp_obj_data[_i].value, value_str, sizeof(value_str), SDB_UNQUOTED); - field = sdb_store_expr_fieldvalue(cmp_obj_data[_i].field); + field = sdb_memstore_expr_fieldvalue(cmp_obj_data[_i].field); fail_unless(field != NULL, - "sdb_store_expr_fieldvalue(%d) = NULL; " + "sdb_memstore_expr_fieldvalue(%d) = NULL; " "expected: ", cmp_obj_data[_i].field); - value = sdb_store_expr_constvalue(&cmp_obj_data[_i].value); + value = sdb_memstore_expr_constvalue(&cmp_obj_data[_i].value); fail_unless(value != NULL, - "sdb_store_expr_constvalue(%s) = NULL; " + "sdb_memstore_expr_constvalue(%s) = NULL; " "expected: ", value_str); for (j = 0; j < SDB_STATIC_ARRAY_LEN(tests); ++j) { char m_str[1024]; - sdb_store_matcher_t *m; + sdb_memstore_matcher_t *m; snprintf(m_str, sizeof(m_str), "%s %s %s", SDB_FIELD_TO_NAME(cmp_obj_data[_i].field), @@ -414,11 +414,11 @@ START_TEST(test_cmp_obj) m = tests[j].matcher(field, value); fail_unless(m != NULL, - "sdb_store__matcher() = NULL; expected: "); + "sdb_memstore__matcher() = NULL; expected: "); - status = sdb_store_matcher_matches(m, host, /* filter */ NULL); + status = sdb_memstore_matcher_matches(m, host, /* filter */ NULL); fail_unless(status == tests[j].expected, - "sdb_store_matcher_matches(<%s>, , NULL) = %d; " + "sdb_memstore_matcher_matches(<%s>, , NULL) = %d; " "expected: %d", m_str, cmp_obj_data[_i].host, status, tests[j].expected); @@ -433,18 +433,18 @@ END_TEST START_TEST(test_store_match_op) { - sdb_store_obj_t *obj; + sdb_memstore_obj_t *obj; sdb_data_t d = { SDB_TYPE_STRING, { .string = "a" } }; - sdb_store_expr_t *e = sdb_store_expr_constvalue(&d); + sdb_memstore_expr_t *e = sdb_memstore_expr_constvalue(&d); - sdb_store_matcher_t *never = sdb_store_isnull_matcher(e); - sdb_store_matcher_t *always = sdb_store_inv_matcher(never); + sdb_memstore_matcher_t *never = sdb_memstore_isnull_matcher(e); + sdb_memstore_matcher_t *always = sdb_memstore_inv_matcher(never); struct { const char *op; - sdb_store_matcher_t *left; - sdb_store_matcher_t *right; + sdb_memstore_matcher_t *left; + sdb_memstore_matcher_t *right; int expected; } golden_data[] = { { "OR", always, always, 1 }, @@ -460,23 +460,23 @@ START_TEST(test_store_match_op) int status; size_t i; - obj = sdb_store_get_host(store, "a"); + obj = sdb_memstore_get_host(store, "a"); - status = sdb_store_matcher_matches(always, obj, /* filter */ NULL); + status = sdb_memstore_matcher_matches(always, obj, /* filter */ NULL); fail_unless(status == 1, "INTERNAL ERROR: 'always' did not match host"); - status = sdb_store_matcher_matches(never, obj, /* filter */ NULL); + status = sdb_memstore_matcher_matches(never, obj, /* filter */ NULL); fail_unless(status == 0, "INTERNAL ERROR: 'never' matches host"); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { - sdb_store_matcher_t *m; + sdb_memstore_matcher_t *m; if (! strcmp(golden_data[i].op, "OR")) - m = sdb_store_dis_matcher(golden_data[i].left, + m = sdb_memstore_dis_matcher(golden_data[i].left, golden_data[i].right); else if (! strcmp(golden_data[i].op, "AND")) - m = sdb_store_con_matcher(golden_data[i].left, + m = sdb_memstore_con_matcher(golden_data[i].left, golden_data[i].right); else { fail("INTERNAL ERROR: unexpected operator %s", golden_data[i].op); @@ -486,7 +486,7 @@ START_TEST(test_store_match_op) #define TO_NAME(v) (((v) == always) ? "always" \ : ((v) == never) ? "never" : "") - status = sdb_store_matcher_matches(m, obj, /* filter */ NULL); + status = sdb_memstore_matcher_matches(m, obj, /* filter */ NULL); fail_unless(status == golden_data[i].expected, "%s(%s, %s, NULL) = %d; expected: %d", golden_data[i].op, TO_NAME(golden_data[i].left), TO_NAME(golden_data[i].right), @@ -506,18 +506,18 @@ START_TEST(test_store_match_op) END_TEST static int -scan_cb(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data) +scan_cb(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data) { int *i = user_data; - if (! sdb_store_matcher_matches(filter, obj, NULL)) + if (! sdb_memstore_matcher_matches(filter, obj, NULL)) return 0; fail_unless(obj != NULL, - "sdb_store_scan callback received NULL obj; expected: " + "sdb_memstore_scan callback received NULL obj; expected: " ""); fail_unless(i != NULL, - "sdb_store_scan callback received NULL user_data; " + "sdb_memstore_scan callback received NULL user_data; " "expected: "); ++(*i); @@ -628,21 +628,21 @@ struct { START_TEST(test_scan) { sdb_strbuf_t *errbuf = sdb_strbuf_create(64); - sdb_store_matcher_t *m, *filter = NULL; + sdb_memstore_matcher_t *m, *filter = NULL; sdb_ast_node_t *ast; int check, n; n = 0; - check = sdb_store_scan(store, SDB_HOST, + check = sdb_memstore_scan(store, SDB_HOST, /* matcher */ NULL, /* filter */ NULL, scan_cb, &n); fail_unless(check == 0, - "sdb_store_scan() = %d; expected: 0", check); + "sdb_memstore_scan() = %d; expected: 0", check); fail_unless(n == 3, - "sdb_store_scan called callback %d times; expected: 3", (int)n); + "sdb_memstore_scan called callback %d times; expected: 3", (int)n); ast = sdb_parser_parse_conditional(SDB_HOST, scan_data[_i].query, -1, errbuf); - m = sdb_store_query_prepare_matcher(ast); + m = sdb_memstore_query_prepare_matcher(ast); sdb_object_deref(SDB_OBJ(ast)); fail_unless(m != NULL, "sdb_parser_parse_conditional(HOST, %s, -1) = NULL; expected: " @@ -651,7 +651,7 @@ START_TEST(test_scan) if (scan_data[_i].filter) { ast = sdb_parser_parse_conditional(SDB_HOST, scan_data[_i].filter, -1, errbuf); - filter = sdb_store_query_prepare_matcher(ast); + filter = sdb_memstore_query_prepare_matcher(ast); sdb_object_deref(SDB_OBJ(ast)); fail_unless(filter != NULL, "sdb_parser_parse_conditional(HOST, %s, -1) = NULL; " @@ -660,9 +660,9 @@ START_TEST(test_scan) } n = 0; - sdb_store_scan(store, SDB_HOST, m, filter, scan_cb, &n); + sdb_memstore_scan(store, SDB_HOST, m, filter, scan_cb, &n); fail_unless(n == scan_data[_i].expected, - "sdb_store_scan(HOST, matcher{%s}, filter{%s}) " + "sdb_memstore_scan(HOST, matcher{%s}, filter{%s}) " "found %d hosts; expected: %d", scan_data[_i].query, scan_data[_i].filter, n, scan_data[_i].expected); diff --git a/t/unit/core/store_test.c b/t/unit/core/store_test.c index 1d524b6..50d041e 100644 --- a/t/unit/core/store_test.c +++ b/t/unit/core/store_test.c @@ -31,19 +31,19 @@ #include "core/plugin.h" #include "core/store.h" -#include "core/store-private.h" +#include "core/memstore-private.h" #include "testutils.h" #include #include #include -static sdb_store_t *store; +static sdb_memstore_t *store; static void init(void) { - store = sdb_store_create(); + store = sdb_memstore_create(); ck_assert(store != NULL); } @@ -52,41 +52,41 @@ populate(void) { sdb_data_t datum; - sdb_store_host(store, "h1", 1); - sdb_store_host(store, "h2", 3); + sdb_memstore_host(store, "h1", 1, 0); + sdb_memstore_host(store, "h2", 3, 0); datum.type = SDB_TYPE_STRING; datum.data.string = "v1"; - sdb_store_attribute(store, "h1", "k1", &datum, 1); + sdb_memstore_attribute(store, "h1", "k1", &datum, 1, 0); datum.data.string = "v2"; - sdb_store_attribute(store, "h1", "k2", &datum, 2); + sdb_memstore_attribute(store, "h1", "k2", &datum, 2, 0); datum.data.string = "v3"; - sdb_store_attribute(store, "h1", "k3", &datum, 2); + sdb_memstore_attribute(store, "h1", "k3", &datum, 2, 0); /* make sure that older updates don't overwrite existing values */ datum.data.string = "fail"; - sdb_store_attribute(store, "h1", "k2", &datum, 1); - sdb_store_attribute(store, "h1", "k3", &datum, 2); + sdb_memstore_attribute(store, "h1", "k2", &datum, 1, 0); + sdb_memstore_attribute(store, "h1", "k3", &datum, 2, 0); - sdb_store_metric(store, "h1", "m1", /* store */ NULL, 2); - sdb_store_metric(store, "h1", "m2", /* store */ NULL, 1); - sdb_store_metric(store, "h2", "m1", /* store */ NULL, 1); + sdb_memstore_metric(store, "h1", "m1", /* store */ NULL, 2, 0); + sdb_memstore_metric(store, "h1", "m2", /* store */ NULL, 1, 0); + sdb_memstore_metric(store, "h2", "m1", /* store */ NULL, 1, 0); - sdb_store_service(store, "h2", "s1", 1); - sdb_store_service(store, "h2", "s2", 2); + sdb_memstore_service(store, "h2", "s1", 1, 0); + sdb_memstore_service(store, "h2", "s2", 2, 0); datum.type = SDB_TYPE_INTEGER; datum.data.integer = 42; - sdb_store_metric_attr(store, "h1", "m1", "k3", &datum, 2); + sdb_memstore_metric_attr(store, "h1", "m1", "k3", &datum, 2, 0); datum.data.integer = 123; - sdb_store_service_attr(store, "h2", "s2", "k1", &datum, 2); + sdb_memstore_service_attr(store, "h2", "s2", "k1", &datum, 2, 0); datum.data.integer = 4711; - sdb_store_service_attr(store, "h2", "s2", "k2", &datum, 1); + sdb_memstore_service_attr(store, "h2", "s2", "k2", &datum, 1, 0); /* don't overwrite k1 */ datum.data.integer = 666; - sdb_store_service_attr(store, "h2", "s2", "k1", &datum, 2); + sdb_memstore_service_attr(store, "h2", "s2", "k1", &datum, 2, 0); } /* populate */ static void @@ -105,21 +105,17 @@ START_TEST(test_store_host) } golden_data[] = { { "a", 1, 0 }, { "a", 2, 0 }, - { "a", 1, 1 }, { "b", 1, 0 }, - { "b", 1, 1 }, - { "A", 1, 1 }, /* case-insensitive */ - { "A", 3, 0 }, }; struct { const char *name; bool have; } golden_hosts[] = { - { "a", 1 == 1 }, - { "b", 1 == 1 }, - { "c", 0 == 1 }, - { "A", 1 == 1 }, + { "a", 1 }, + { "b", 1 }, + { "c", 0 }, + { "A", 1 }, }; size_t i; @@ -127,20 +123,20 @@ START_TEST(test_store_host) for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { int status; - status = sdb_store_host(store, golden_data[i].name, - golden_data[i].last_update); + status = sdb_memstore_host(store, golden_data[i].name, + golden_data[i].last_update, 0); fail_unless(status == golden_data[i].expected, - "sdb_store_host(%s, %d) = %d; expected: %d", + "sdb_memstore_host(%s, %d, 0) = %d; expected: %d", golden_data[i].name, (int)golden_data[i].last_update, status, golden_data[i].expected); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) { - sdb_store_obj_t *have; + sdb_memstore_obj_t *have; - have = sdb_store_get_host(store, golden_hosts[i].name); + have = sdb_memstore_get_host(store, golden_hosts[i].name); fail_unless((have != NULL) == golden_hosts[i].have, - "sdb_store_get_host(%s) = %p; expected: %s", + "sdb_memstore_get_host(%s) = %p; expected: %s", golden_hosts[i].name, have, golden_hosts[i].have ? "" : "NULL"); sdb_object_deref(SDB_OBJ(have)); @@ -155,36 +151,36 @@ START_TEST(test_store_get_host) size_t i; for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) { - int status = sdb_store_host(store, golden_hosts[i], 1); + int status = sdb_memstore_host(store, golden_hosts[i], 1, 0); fail_unless(status >= 0, - "sdb_store_host(%s) = %d; expected: >=0", + "sdb_memstore_host(%s) = %d; expected: >=0", golden_hosts[i], status); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_hosts); ++i) { - sdb_store_obj_t *sobj1, *sobj2; + sdb_memstore_obj_t *sobj1, *sobj2; int ref_cnt; - sobj1 = sdb_store_get_host(store, golden_hosts[i]); + sobj1 = sdb_memstore_get_host(store, golden_hosts[i]); fail_unless(sobj1 != NULL, - "sdb_store_get_host(%s) = NULL; expected: ", + "sdb_memstore_get_host(%s) = NULL; expected: ", golden_hosts[i]); ref_cnt = SDB_OBJ(sobj1)->ref_cnt; fail_unless(ref_cnt > 1, - "sdb_store_get_host(%s) did not increment ref count: " + "sdb_memstore_get_host(%s) did not increment ref count: " "got: %d; expected: >1", golden_hosts[i], ref_cnt); - sobj2 = sdb_store_get_host(store, golden_hosts[i]); + sobj2 = sdb_memstore_get_host(store, golden_hosts[i]); fail_unless(sobj2 != NULL, - "sdb_store_get_host(%s) = NULL; expected: ", + "sdb_memstore_get_host(%s) = NULL; expected: ", golden_hosts[i]); fail_unless(sobj1 == sobj2, - "sdb_store_get_host(%s) returned different objects " + "sdb_memstore_get_host(%s) returned different objects " "in successive calls", golden_hosts[i]); fail_unless(SDB_OBJ(sobj2)->ref_cnt == ref_cnt + 1, - "sdb_store_get_hosts(%s) did not increment ref count " + "sdb_memstore_get_hosts(%s) did not increment ref count " "(first call: %d; second call: %d)", golden_hosts[i], ref_cnt, SDB_OBJ(sobj2)->ref_cnt); @@ -192,10 +188,10 @@ START_TEST(test_store_get_host) sdb_object_deref(SDB_OBJ(sobj2)); } for (i = 0; i < SDB_STATIC_ARRAY_LEN(unknown_hosts); ++i) { - sdb_store_obj_t *sobj; + sdb_memstore_obj_t *sobj; - sobj = sdb_store_get_host(store, unknown_hosts[i]); - fail_unless(!sobj, "sdb_store_get_host(%s) = ; expected: NULL", + sobj = sdb_memstore_get_host(store, unknown_hosts[i]); + fail_unless(!sobj, "sdb_memstore_get_host(%s) = ; expected: NULL", unknown_hosts[i], sobj ? SDB_OBJ(sobj)->name : "NULL"); } } @@ -214,16 +210,14 @@ START_TEST(test_store_attr) { "k", "k", "v", 1, -1 }, /* retry to ensure the host is not created */ { "l", "k1", "v1", 1, 0 }, { "l", "k1", "v2", 2, 0 }, - { "l", "k1", "v3", 2, 1 }, { "l", "k2", "v1", 1, 0 }, { "m", "k", "v1", 1, 0 }, - { "m", "k", "v2", 1, 1 }, }; size_t i; - sdb_store_host(store, "l", 1); - sdb_store_host(store, "m", 1); + sdb_memstore_host(store, "l", 1, 0); + sdb_memstore_host(store, "m", 1, 0); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { sdb_data_t datum; int status; @@ -232,13 +226,13 @@ START_TEST(test_store_attr) datum.type = SDB_TYPE_STRING; datum.data.string = golden_data[i].value; - status = sdb_store_attribute(store, golden_data[i].host, + status = sdb_memstore_attribute(store, golden_data[i].host, golden_data[i].key, &datum, - golden_data[i].last_update); + golden_data[i].last_update, 0); fail_unless(status == golden_data[i].expected, - "sdb_store_attribute(%s, %s, %s, %d) = %d; expected: %d", + "sdb_memstore_attribute(%s, %s, %s, %d) = %d; expected: %d", golden_data[i].host, golden_data[i].key, golden_data[i].value, - golden_data[i].last_update, status, golden_data[i].expected); + golden_data[i].last_update, status, golden_data[i].expected, 0); } } END_TEST @@ -261,13 +255,11 @@ START_TEST(test_store_metric) { "l", "m1", NULL, 1, 0 }, { "l", "m1", &store1, 2, 0 }, { "l", "m1", &store1, 3, 0 }, - { "l", "m1", NULL, 3, 1 }, { "l", "m2", &store1, 1, 0 }, { "l", "m2", &store2, 2, 0 }, { "l", "m2", NULL, 3, 0 }, { "m", "m", &store1, 1, 0 }, { "m", "m", NULL, 2, 0 }, - { "m", "m", NULL, 2, 1 }, { "m", "m", &store1, 3, 0 }, { "m", "m", &store2, 4, 0 }, { "m", "m", NULL, 5, 0 }, @@ -275,16 +267,16 @@ START_TEST(test_store_metric) size_t i; - sdb_store_host(store, "m", 1); - sdb_store_host(store, "l", 1); + sdb_memstore_host(store, "m", 1, 0); + sdb_memstore_host(store, "l", 1, 0); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { int status; - status = sdb_store_metric(store, golden_data[i].host, + status = sdb_memstore_metric(store, golden_data[i].host, golden_data[i].metric, golden_data[i].store, - golden_data[i].last_update); + golden_data[i].last_update, 0); fail_unless(status == golden_data[i].expected, - "sdb_store_metric(%s, %s, %p, %d) = %d; expected: %d", + "sdb_memstore_metric(%s, %s, %p, %d, 0) = %d; expected: %d", golden_data[i].host, golden_data[i].metric, golden_data[i].store, golden_data[i].last_update, status, golden_data[i].expected); @@ -309,30 +301,28 @@ START_TEST(test_store_metric_attr) /* retry, it should still fail */ { "l", "mX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 }, { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, - { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 }, { "l", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 }, { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, - { "l", "m1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 }, { "l", "m2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, { "m", "m1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, }; size_t i; - sdb_store_host(store, "m", 1); - sdb_store_host(store, "l", 1); - sdb_store_metric(store, "m", "m1", NULL, 1); - sdb_store_metric(store, "l", "m1", NULL, 1); - sdb_store_metric(store, "l", "m2", NULL, 1); + sdb_memstore_host(store, "m", 1, 0); + sdb_memstore_host(store, "l", 1, 0); + sdb_memstore_metric(store, "m", "m1", NULL, 1, 0); + sdb_memstore_metric(store, "l", "m1", NULL, 1, 0); + sdb_memstore_metric(store, "l", "m2", NULL, 1, 0); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { int status; - status = sdb_store_metric_attr(store, golden_data[i].host, + status = sdb_memstore_metric_attr(store, golden_data[i].host, golden_data[i].metric, golden_data[i].attr, - &golden_data[i].value, golden_data[i].last_update); + &golden_data[i].value, golden_data[i].last_update, 0); fail_unless(status == golden_data[i].expected, - "sdb_store_metric_attr(%s, %s, %s, %d, %d) = %d; " + "sdb_memstore_metric_attr(%s, %s, %s, %d, %d, 0) = %d; " "expected: %d", golden_data[i].host, golden_data[i].metric, golden_data[i].attr, golden_data[i].value.data.integer, golden_data[i].last_update, status, golden_data[i].expected); @@ -352,23 +342,21 @@ START_TEST(test_store_service) { "k", "s", 1, -1 }, /* retry to ensure the host is not created */ { "l", "s1", 1, 0 }, { "l", "s1", 2, 0 }, - { "l", "s1", 2, 1 }, { "l", "s2", 1, 0 }, { "m", "s", 1, 0 }, - { "m", "s", 1, 1 }, }; size_t i; - sdb_store_host(store, "m", 1); - sdb_store_host(store, "l", 1); + sdb_memstore_host(store, "m", 1, 0); + sdb_memstore_host(store, "l", 1, 0); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { int status; - status = sdb_store_service(store, golden_data[i].host, - golden_data[i].svc, golden_data[i].last_update); + status = sdb_memstore_service(store, golden_data[i].host, + golden_data[i].svc, golden_data[i].last_update, 0); fail_unless(status == golden_data[i].expected, - "sdb_store_service(%s, %s, %d) = %d; expected: %d", + "sdb_memstore_service(%s, %s, %d, 0) = %d; expected: %d", golden_data[i].host, golden_data[i].svc, golden_data[i].last_update, status, golden_data[i].expected); } @@ -392,30 +380,28 @@ START_TEST(test_store_service_attr) /* retry, it should still fail */ { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 }, { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, - { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 }, { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 }, { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, - { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 }, { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 }, }; size_t i; - sdb_store_host(store, "m", 1); - sdb_store_host(store, "l", 1); - sdb_store_service(store, "m", "s1", 1); - sdb_store_service(store, "l", "s1", 1); - sdb_store_service(store, "l", "s2", 1); + sdb_memstore_host(store, "m", 1, 0); + sdb_memstore_host(store, "l", 1, 0); + sdb_memstore_service(store, "m", "s1", 1, 0); + sdb_memstore_service(store, "l", "s1", 1, 0); + sdb_memstore_service(store, "l", "s2", 1, 0); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { int status; - status = sdb_store_service_attr(store, golden_data[i].host, + status = sdb_memstore_service_attr(store, golden_data[i].host, golden_data[i].svc, golden_data[i].attr, - &golden_data[i].value, golden_data[i].last_update); + &golden_data[i].value, golden_data[i].last_update, 0); fail_unless(status == golden_data[i].expected, - "sdb_store_service_attr(%s, %s, %s, %d, %d) = %d; " + "sdb_memstore_service_attr(%s, %s, %s, %d, %d, 0) = %d; " "expected: %d", golden_data[i].host, golden_data[i].svc, golden_data[i].attr, golden_data[i].value.data.integer, golden_data[i].last_update, status, golden_data[i].expected); @@ -471,37 +457,35 @@ static struct { (obj) ? SDB_OBJ(obj)->name : "" START_TEST(test_get_field) { - sdb_store_obj_t *obj = NULL; + sdb_memstore_obj_t *obj = NULL; sdb_data_t value = SDB_DATA_INIT; char value_str[128], expected_value_str[128]; sdb_time_t now = sdb_gettime(); int check; - sdb_store_host(store, "host", 10); - sdb_store_host(store, "host", 20); - sdb_store_attribute(store, "host", "attr", &get_field_data[_i].value, 10); - sdb_store_attribute(store, "host", "attr", &get_field_data[_i].value, 20); + sdb_memstore_host(store, "host", 20, 10); + sdb_memstore_attribute(store, "host", "attr", &get_field_data[_i].value, 20, 10); if (get_field_data[_i].hostname) { - obj = sdb_store_get_host(store, get_field_data[_i].hostname); + obj = sdb_memstore_get_host(store, get_field_data[_i].hostname); ck_assert(obj != NULL); if (get_field_data[_i].attr) { - sdb_store_obj_t *tmp = sdb_store_get_child(obj, + sdb_memstore_obj_t *tmp = sdb_memstore_get_child(obj, SDB_ATTRIBUTE, get_field_data[_i].attr); sdb_object_deref(SDB_OBJ(obj)); obj = tmp; } } - check = sdb_store_get_field(obj, get_field_data[_i].field, NULL); + check = sdb_memstore_get_field(obj, get_field_data[_i].field, NULL); fail_unless(check == get_field_data[_i].expected, - "sdb_store_get_field(%s %s, %s, NULL) = %d; expected: %d", + "sdb_memstore_get_field(%s %s, %s, NULL) = %d; expected: %d", OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field), check, get_field_data[_i].expected); - check = sdb_store_get_field(obj, get_field_data[_i].field, &value); + check = sdb_memstore_get_field(obj, get_field_data[_i].field, &value); fail_unless(check == get_field_data[_i].expected, - "sdb_store_get_field(%s %s, %s, ) = %d; expected: %d", + "sdb_memstore_get_field(%s %s, %s, ) = %d; expected: %d", OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field), check, get_field_data[_i].expected); @@ -522,14 +506,14 @@ START_TEST(test_get_field) if (get_field_data[_i].field == SDB_FIELD_AGE) { fail_unless((value.type == SDB_TYPE_DATETIME) && (value.data.datetime >= now), - "sdb_store_get_field(%s %s, %s, ) " + "sdb_memstore_get_field(%s %s, %s, ) " "returned value %s; expected >=%s", OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field), value_str, expected_value_str); } else { fail_unless(! sdb_data_cmp(&value, &get_field_data[_i].value), - "sdb_store_get_field(%s %s, %s, ) " + "sdb_memstore_get_field(%s %s, %s, ) " "returned value %s; expected %s", OBJ_NAME(obj), SDB_FIELD_TO_NAME(get_field_data[_i].field), value_str, expected_value_str); @@ -544,28 +528,34 @@ START_TEST(test_get_child) { struct { const char *host; + int parent_type; + const char *parent; const char *name; int type; int expected; } golden_data[] = { - { "h1", NULL, SDB_HOST, 0 }, - { "h1", NULL, SDB_SERVICE, -1 }, - { "h1", NULL, SDB_METRIC, -1 }, - { "h1", NULL, SDB_ATTRIBUTE, -1 }, - { "h2", NULL, SDB_HOST, 0 }, - { "h2", NULL, SDB_SERVICE, -1 }, - { "h2", NULL, SDB_METRIC, -1 }, - { "h2", NULL, SDB_ATTRIBUTE, -1 }, - { "h3", NULL, SDB_HOST, -1 }, - { "h1", "k1", SDB_ATTRIBUTE, 0 }, - { "h1", "x1", SDB_ATTRIBUTE, -1 }, - { "h2", "k1", SDB_ATTRIBUTE, -1 }, - { "h1", "k1", SDB_SERVICE, -1 }, - { "h1", "k1", SDB_METRIC, -1 }, - { "h1", "s1", SDB_SERVICE, -1 }, - { "h2", "s1", SDB_SERVICE, 0 }, - { "h1", "m2", SDB_METRIC, 0 }, - { "h2", "m2", SDB_METRIC, -1 }, + { "h1", -1, NULL, NULL, SDB_HOST, 0 }, + { "h1", -1, NULL, NULL, SDB_SERVICE, -1 }, + { "h1", -1, NULL, NULL, SDB_METRIC, -1 }, + { "h1", -1, NULL, NULL, SDB_ATTRIBUTE, -1 }, + { "h2", -1, NULL, NULL, SDB_HOST, 0 }, + { "h2", -1, NULL, NULL, SDB_SERVICE, -1 }, + { "h2", -1, NULL, NULL, SDB_METRIC, -1 }, + { "h2", -1, NULL, NULL, SDB_ATTRIBUTE, -1 }, + { "h3", -1, NULL, NULL, SDB_HOST, -1 }, + { "h1", -1, NULL, "k1", SDB_ATTRIBUTE, 0 }, + { "h1", -1, NULL, "x1", SDB_ATTRIBUTE, -1 }, + { "h2", -1, NULL, "k1", SDB_ATTRIBUTE, -1 }, + { "h1", -1, NULL, "k1", SDB_SERVICE, -1 }, + { "h1", -1, NULL, "k1", SDB_METRIC, -1 }, + { "h1", -1, NULL, "s1", SDB_SERVICE, -1 }, + { "h2", -1, NULL, "s1", SDB_SERVICE, 0 }, + { "h1", -1, NULL, "m2", SDB_METRIC, 0 }, + { "h2", -1, NULL, "m2", SDB_METRIC, -1 }, + { "h1", SDB_METRIC, "m1", "k3", SDB_ATTRIBUTE, 0 }, + { "h1", SDB_METRIC, "m1", "x1", SDB_ATTRIBUTE, -1 }, + { "h2", SDB_SERVICE, "s2", "k1", SDB_ATTRIBUTE, 0 }, + { "h2", SDB_SERVICE, "s2", "x1", SDB_ATTRIBUTE, -1 }, }; size_t i; @@ -573,35 +563,42 @@ START_TEST(test_get_child) populate(); for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) { - sdb_store_obj_t *obj; + sdb_memstore_obj_t *obj; const char *expected_name = golden_data[i].host; - obj = sdb_store_get_host(store, golden_data[i].host); + obj = sdb_memstore_get_host(store, golden_data[i].host); + if (golden_data[i].parent) { + sdb_memstore_obj_t *o; + o = sdb_memstore_get_child(obj, + golden_data[i].parent_type, golden_data[i].parent); + sdb_object_deref(SDB_OBJ(obj)); + obj = o; + } if (golden_data[i].expected && (golden_data[i].type == SDB_HOST)) fail_unless(obj == NULL, - "sdb_store_get_host(%s) = %p; expected: NULL", + "sdb_memstore_get_host(%s) = %p; expected: NULL", golden_data[i].host, obj); else fail_unless(obj != NULL, - "sdb_store_get_host(%s) = NULL; expected: ", + "sdb_memstore_get_host(%s) = NULL; expected: ", golden_data[i].host); if (golden_data[i].type != SDB_HOST) { - sdb_store_obj_t *tmp; + sdb_memstore_obj_t *tmp; expected_name = golden_data[i].name; - tmp = sdb_store_get_child(obj, + tmp = sdb_memstore_get_child(obj, golden_data[i].type, golden_data[i].name); if (golden_data[i].expected) fail_unless(tmp == NULL, - "sdb_store_get_child(<%s>, %s, %s) = %p; " + "sdb_memstore_get_child(<%s>, %s, %s) = %p; " "expected: NULL", golden_data[i].host, SDB_STORE_TYPE_TO_NAME(golden_data[i].type), golden_data[i].name, tmp); else fail_unless(tmp != NULL, - "sdb_store_get_child(<%s>, %s, %s) = NULL; " + "sdb_memstore_get_child(<%s>, %s, %s) = NULL; " "expected: ", golden_data[i].host, SDB_STORE_TYPE_TO_NAME(golden_data[i].type), golden_data[i].name); @@ -614,12 +611,12 @@ START_TEST(test_get_child) continue; fail_unless(obj->type == golden_data[i].type, - "sdb_store_get_<%s>(%s, %s) returned object of type %d; " + "sdb_memstore_get_<%s>(%s, %s) returned object of type %d; " "expected: %d", SDB_STORE_TYPE_TO_NAME(golden_data[i].type), golden_data[i].host, golden_data[i].name, obj->type, golden_data[i].type); fail_unless(! strcasecmp(SDB_OBJ(obj)->name, expected_name), - "sdb_store_get_<%s>(%s, %s) returned object named '%s'; " + "sdb_memstore_get_<%s>(%s, %s) returned object named '%s'; " "expected: '%s'", SDB_STORE_TYPE_TO_NAME(golden_data[i].type), golden_data[i].host, golden_data[i].name, SDB_OBJ(obj)->name, expected_name); @@ -629,75 +626,78 @@ START_TEST(test_get_child) } END_TEST +/* TODO: move these tests into generic store tests */ +#if 0 START_TEST(test_interval) { - sdb_store_obj_t *host; + sdb_memstore_obj_t *host; /* 10 us interval */ - sdb_store_host(store, "host", 10); - sdb_store_host(store, "host", 20); - sdb_store_host(store, "host", 30); - sdb_store_host(store, "host", 40); + sdb_memstore_host(store, "host", 10); + sdb_memstore_host(store, "host", 20); + sdb_memstore_host(store, "host", 30); + sdb_memstore_host(store, "host", 40); - host = sdb_store_get_host(store, "host"); + host = sdb_memstore_get_host(store, "host"); fail_unless(host != NULL, "INTERNAL ERROR: store doesn't have host after adding it"); fail_unless(host->interval == 10, - "sdb_store_host() did not calculate interval correctly: " + "sdb_memstore_host() did not calculate interval correctly: " "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10); /* multiple updates for the same timestamp don't modify the interval */ - sdb_store_host(store, "host", 40); - sdb_store_host(store, "host", 40); - sdb_store_host(store, "host", 40); - sdb_store_host(store, "host", 40); + sdb_memstore_host(store, "host", 40); + sdb_memstore_host(store, "host", 40); + sdb_memstore_host(store, "host", 40); + sdb_memstore_host(store, "host", 40); fail_unless(host->interval == 10, - "sdb_store_host() changed interval when doing multiple updates " + "sdb_memstore_host() changed interval when doing multiple updates " "using the same timestamp; got: %"PRIsdbTIME"; " "expected: %"PRIsdbTIME, host->interval, 10); /* multiple updates using an timestamp don't modify the interval */ - sdb_store_host(store, "host", 20); - sdb_store_host(store, "host", 20); - sdb_store_host(store, "host", 20); - sdb_store_host(store, "host", 20); + sdb_memstore_host(store, "host", 20); + sdb_memstore_host(store, "host", 20); + sdb_memstore_host(store, "host", 20); + sdb_memstore_host(store, "host", 20); fail_unless(host->interval == 10, - "sdb_store_host() changed interval when doing multiple updates " + "sdb_memstore_host() changed interval when doing multiple updates " "using an old timestamp; got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 10); /* new interval: 20 us */ - sdb_store_host(store, "host", 60); + sdb_memstore_host(store, "host", 60); fail_unless(host->interval == 11, - "sdb_store_host() did not calculate interval correctly: " + "sdb_memstore_host() did not calculate interval correctly: " "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11); /* new interval: 40 us */ - sdb_store_host(store, "host", 100); + sdb_memstore_host(store, "host", 100); fail_unless(host->interval == 13, - "sdb_store_host() did not calculate interval correctly: " + "sdb_memstore_host() did not calculate interval correctly: " "got: %"PRIsdbTIME"; expected: %"PRIsdbTIME, host->interval, 11); sdb_object_deref(SDB_OBJ(host)); } END_TEST +#endif static int -scan_count(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data) +scan_count(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data) { intptr_t *i = user_data; - if (! sdb_store_matcher_matches(filter, obj, NULL)) + if (! sdb_memstore_matcher_matches(filter, obj, NULL)) return 0; fail_unless(obj != NULL, - "sdb_store_scan callback received NULL obj; expected: " + "sdb_memstore_scan callback received NULL obj; expected: " ""); fail_unless(i != NULL, - "sdb_store_scan callback received NULL user_data; " + "sdb_memstore_scan callback received NULL user_data; " "expected: "); ++(*i); @@ -705,18 +705,18 @@ scan_count(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data) } /* scan_count */ static int -scan_error(sdb_store_obj_t *obj, sdb_store_matcher_t *filter, void *user_data) +scan_error(sdb_memstore_obj_t *obj, sdb_memstore_matcher_t *filter, void *user_data) { intptr_t *i = user_data; - if (! sdb_store_matcher_matches(filter, obj, NULL)) + if (! sdb_memstore_matcher_matches(filter, obj, NULL)) return 0; fail_unless(obj != NULL, - "sdb_store_scan callback received NULL obj; expected: " + "sdb_memstore_scan callback received NULL obj; expected: " ""); fail_unless(i != NULL, - "sdb_store_scan callback received NULL user_data; " + "sdb_memstore_scan callback received NULL user_data; " "expected: "); ++(*i); @@ -729,49 +729,49 @@ START_TEST(test_scan) int check; /* empty store */ - check = sdb_store_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL, + check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL, scan_count, &i); fail_unless(check == 0, - "sdb_store_scan(HOST), empty store = %d; expected: 0", check); + "sdb_memstore_scan(HOST), empty store = %d; expected: 0", check); fail_unless(i == 0, - "sdb_store_scan(HOST) called callback %d times; " + "sdb_memstore_scan(HOST) called callback %d times; " "expected: 0", (int)i); populate(); - check = sdb_store_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL, + check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL, scan_count, &i); fail_unless(check == 0, - "sdb_store_scan(HOST) = %d; expected: 0", check); + "sdb_memstore_scan(HOST) = %d; expected: 0", check); fail_unless(i == 2, - "sdb_store_scan(HOST) called callback %d times; " + "sdb_memstore_scan(HOST) called callback %d times; " "expected: 1", (int)i); i = 0; - check = sdb_store_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL, + check = sdb_memstore_scan(store, SDB_HOST, /* m, filter = */ NULL, NULL, scan_error, &i); fail_unless(check == -1, - "sdb_store_scan(HOST), error callback = %d; expected: -1", check); + "sdb_memstore_scan(HOST), error callback = %d; expected: -1", check); fail_unless(i == 1, - "sdb_store_scan(HOST) called callback %d times " + "sdb_memstore_scan(HOST) called callback %d times " "(callback returned error); expected: 1", (int)i); i = 0; - check = sdb_store_scan(store, SDB_SERVICE, /* m, filter = */ NULL, NULL, + check = sdb_memstore_scan(store, SDB_SERVICE, /* m, filter = */ NULL, NULL, scan_count, &i); fail_unless(check == 0, - "sdb_store_scan(SERVICE) = %d; expected: 0", check); + "sdb_memstore_scan(SERVICE) = %d; expected: 0", check); fail_unless(i == 2, - "sdb_store_scan(SERVICE) called callback %d times; " + "sdb_memstore_scan(SERVICE) called callback %d times; " "expected: 2", (int)i); i = 0; - check = sdb_store_scan(store, SDB_METRIC, /* m, filter = */ NULL, NULL, + check = sdb_memstore_scan(store, SDB_METRIC, /* m, filter = */ NULL, NULL, scan_count, &i); fail_unless(check == 0, - "sdb_store_scan(METRIC) = %d; expected: 0", check); + "sdb_memstore_scan(METRIC) = %d; expected: 0", check); fail_unless(i == 3, - "sdb_store_scan(METRIC) called callback %d times; " + "sdb_memstore_scan(METRIC) called callback %d times; " "expected: 3", (int)i); } END_TEST @@ -789,7 +789,6 @@ TEST_MAIN("core::store") tcase_add_test(tc, test_store_service_attr); TC_ADD_LOOP_TEST(tc, get_field); tcase_add_test(tc, test_get_child); - tcase_add_test(tc, test_interval); tcase_add_test(tc, test_scan); ADD_TCASE(tc); } diff --git a/t/unit/frontend/query_test.c b/t/unit/frontend/query_test.c index de8ab80..e81bb58 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" @@ -43,16 +44,16 @@ static void populate(void) { - sdb_store_t *store; + sdb_memstore_t *store; sdb_data_t datum; /* the frontend accesses the store via the plugin API */ - store = sdb_store_create(); + store = sdb_memstore_create(); ck_assert(store != NULL); ck_assert(sdb_plugin_register_writer("test-writer", - &sdb_store_writer, SDB_OBJ(store)) == 0); + &sdb_memstore_writer, SDB_OBJ(store)) == 0); ck_assert(sdb_plugin_register_reader("test-reader", - &sdb_store_reader, SDB_OBJ(store)) == 0); + &sdb_memstore_reader, SDB_OBJ(store)) == 0); sdb_object_deref(SDB_OBJ(store)); /* populate the store */ @@ -367,391 +368,390 @@ static struct { int query_len; int expected; uint32_t code; - size_t len; uint32_t type; const char *data; } query_data[] = { /* hosts */ { SDB_CONNECTION_QUERY, "LIST hosts", -1, - 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "["HOST_H1_LISTING","HOST_H2_LISTING"]", }, { SDB_CONNECTION_LIST, "\0\0\0\1", 4, - 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "["HOST_H1_LISTING","HOST_H2_LISTING"]", }, { SDB_CONNECTION_LIST, "", 0, /* LIST defaults to hosts */ - 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "["HOST_H1_LISTING","HOST_H2_LISTING"]", }, { SDB_CONNECTION_QUERY, "LIST hosts; LIST hosts", -1, /* ignore second (and later) commands */ - 0, SDB_CONNECTION_DATA, 205, SDB_CONNECTION_LIST, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "["HOST_H1_LISTING","HOST_H2_LISTING"]", }, { SDB_CONNECTION_QUERY, "LIST hosts FILTER name = 'h1'", -1, - 0, SDB_CONNECTION_DATA, 105, SDB_CONNECTION_LIST, "["HOST_H1_LISTING"]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "["HOST_H1_LISTING"]", }, { SDB_CONNECTION_QUERY, "LIST hosts FILTER name = 's1'", -1, - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "[]", }, /* SDB_CONNECTION_LIST doesn't support filters yet */ { SDB_CONNECTION_QUERY, "FETCH host 'h1'", -1, - 0, SDB_CONNECTION_DATA, 1110, SDB_CONNECTION_FETCH, HOST_H1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, HOST_H1, }, { SDB_CONNECTION_FETCH, "\0\0\0\1""h1", 7, - 0, SDB_CONNECTION_DATA, 1110, SDB_CONNECTION_FETCH, HOST_H1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, HOST_H1, }, { SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'h1'", -1, - 0, SDB_CONNECTION_DATA, 1112, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY, }, { SDB_CONNECTION_LOOKUP, "\0\0\0\1""name = 'h1'", 16, - 0, SDB_CONNECTION_DATA, 1112, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY, }, { SDB_CONNECTION_QUERY, "FETCH host 'h1' FILTER age >= 0s", -1, /* always matches */ - 0, SDB_CONNECTION_DATA, 1110, SDB_CONNECTION_FETCH, HOST_H1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, HOST_H1, }, /* SDB_CONNECTION_FETCH doesn't support filters yet */ { SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'h1' FILTER age >= 0s", -1, /* always matches */ - 0, SDB_CONNECTION_DATA, 1112, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, HOST_H1_ARRAY, }, { SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING ANY backend = 'b'", -1, - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, { SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING ANY backend || 'b' = 'b'", -1, - 0, SDB_CONNECTION_DATA, 2205, SDB_CONNECTION_LOOKUP, HOST_H12_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, HOST_H12_ARRAY, }, { SDB_CONNECTION_QUERY, "FETCH host 'h1' FILTER age < 0s", -1, /* never matches */ - -1, UINT32_MAX, 0, 0, NULL, /* FETCH fails if the object doesn't exist */ + -1, UINT32_MAX, 0, NULL, /* FETCH fails if the object doesn't exist */ }, /* SDB_CONNECTION_FETCH doesn't support filters yet */ { SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'h1' FILTER age < 0s", -1, /* never matches */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, /* SDB_CONNECTION_LOOKUP doesn't support filters yet */ { SDB_CONNECTION_QUERY, "FETCH host 'x1'", -1, /* does not exist */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_FETCH, "\0\0\0\1x1", 7, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_QUERY, "LOOKUP hosts MATCHING name = 'x1'", -1, /* does not exist */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, { SDB_CONNECTION_LOOKUP, "\0\0\0\1""name = 'x1'", 16, /* does not exist */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, { SDB_CONNECTION_QUERY, "FETCH host 'h1'.'s1'", -1, /* invalid args */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_QUERY, "LOOKUP hosts BY name = 'x1'", -1, /* does not exist */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* services */ { SDB_CONNECTION_QUERY, "LIST services", -1, - 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING, }, { SDB_CONNECTION_LIST, "\0\0\0\2", 4, - 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING, }, { SDB_CONNECTION_QUERY, "LIST services FILTER host.name = 'h2'", -1, - 0, SDB_CONNECTION_DATA, 320, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, SERVICE_H2_S12_LISTING, }, { SDB_CONNECTION_QUERY, "LIST services FILTER host.name = 'h1'", -1, - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "[]", }, /* SDB_CONNECTION_LIST doesn't support filters yet */ { SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1'", -1, - 0, SDB_CONNECTION_DATA, 356, SDB_CONNECTION_FETCH, SERVICE_H2_S1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, SERVICE_H2_S1, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1'", -1, - 0, SDB_CONNECTION_DATA, 358, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY, }, { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING host.name = 'h2'", -1, - 0, SDB_CONNECTION_DATA, 825, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", }, { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING ANY host.metric.name = 'm1'", -1, - 0, SDB_CONNECTION_DATA, 825, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", }, { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING ANY host.metric.last_update = 10s", -1, - 0, SDB_CONNECTION_DATA, 825, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", }, { /* stupid but valid ;-) */ SDB_CONNECTION_QUERY, "LOOKUP services MATCHING ANY host.host.metric.metric.interval = 5s", -1, - 0, SDB_CONNECTION_DATA, 825, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "["SERVICE_H2_S12"]", }, { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING ANY host.metric.name = 'mX'", -1, - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, { SDB_CONNECTION_LOOKUP, "\0\0\0\2""name = 's1'", 16, - 0, SDB_CONNECTION_DATA, 358, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY, }, { SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1' FILTER age >= 0s", -1, /* always matches */ - 0, SDB_CONNECTION_DATA, 356, SDB_CONNECTION_FETCH, SERVICE_H2_S1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, SERVICE_H2_S1, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1' FILTER age >= 0s", -1, /* always matches */ - 0, SDB_CONNECTION_DATA, 358, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, SERVICE_H2_S1_ARRAY, }, { SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1' FILTER age < 0s", -1, /* never matches */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1' FILTER age < 0s", -1, /* never matches */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, /* SDB_CONNECTION_LOOKUP doesn't support filters yet */ { SDB_CONNECTION_QUERY, "FETCH service 'h2'.'s1' FILTER name = 'h2'", -1, /* only matches host */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ { SDB_CONNECTION_QUERY, "LOOKUP services MATCHING name = 's1' FILTER name = 'h2'", -1, /* only matches host */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, { SDB_CONNECTION_QUERY, "FETCH service 'h2'.'x1'", -1, /* does not exist */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ { SDB_CONNECTION_QUERY, "FETCH service 'x2'.'s1'", -1, /* does not exist */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ { SDB_CONNECTION_QUERY, "FETCH service 'h2'", -1, /* invalid args */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support services yet */ /* metrics */ { SDB_CONNECTION_QUERY, "LIST metrics", -1, - 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING, }, { SDB_CONNECTION_LIST, "\0\0\0\3", 4, - 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING, }, { SDB_CONNECTION_QUERY, "LIST metrics FILTER age > 0s", -1, - 0, SDB_CONNECTION_DATA, 596, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, METRIC_H12_M12_LISTING, }, { SDB_CONNECTION_QUERY, "LIST metrics FILTER age < 0s", -1, - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LIST, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LIST, "[]", }, /* SDB_CONNECTION_LIST doesn't support filters yet */ { SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1'", -1, - 0, SDB_CONNECTION_DATA, 489, SDB_CONNECTION_FETCH, METRIC_H1_M1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, METRIC_H1_M1, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ { SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1'", -1, - 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, }, { /* stupid but valid ;-) */ SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING metric.metric.name = 'm1'", -1, - 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, }, { /* also stupid but valid ;-) */ SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING metric.metric.host.host.last_update = 3s", -1, - 0, SDB_CONNECTION_DATA, 378, SDB_CONNECTION_LOOKUP, "["METRIC_H2_M1"]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "["METRIC_H2_M1"]", }, { SDB_CONNECTION_LOOKUP, "\0\0\0\3""name = 'm1'", 16, - 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, }, { SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1' FILTER age >= 0s", -1, /* always matches */ - 0, SDB_CONNECTION_DATA, 489, SDB_CONNECTION_FETCH, METRIC_H1_M1, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_FETCH, METRIC_H1_M1, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ { SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1' FILTER age >= 0s", -1, /* always matches */ - 0, SDB_CONNECTION_DATA, 864, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, METRIC_H12_M1_ARRAY, }, { SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1' FILTER age < 0s", -1, /* never matches */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ { SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1' FILTER age < 0s", -1, /* never matches */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, /* SDB_CONEECTION_LOOKUP doesn't support filters yet */ { SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'m1' FILTER name = 'h1'", -1, /* only matches host */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ { SDB_CONNECTION_QUERY, "LOOKUP metrics MATCHING name = 'm1' FILTER name = 'h1'", -1, /* only matches host */ - 0, SDB_CONNECTION_DATA, 6, SDB_CONNECTION_LOOKUP, "[]", + 0, SDB_CONNECTION_DATA, SDB_CONNECTION_LOOKUP, "[]", }, { SDB_CONNECTION_QUERY, "FETCH metric 'h1'.'x1'", -1, /* does not exist */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ { SDB_CONNECTION_QUERY, "FETCH metric 'x1'.'m1'", -1, /* does not exist */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ { SDB_CONNECTION_QUERY, "FETCH metric 'x1'", -1, /* invalid args */ - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, /* SDB_CONNECTION_FETCH doesn't support metrics yet */ /* timeseries */ { SDB_CONNECTION_QUERY, "TIMESERIES 'h1'.'m1'", -1, - -1, UINT32_MAX, 0, 0, NULL, /* no data-store available */ + -1, UINT32_MAX, 0, NULL, /* no data-store available */ }, { SDB_CONNECTION_QUERY, "TIMESERIES 'h1'.'x1'", -1, - -1, UINT32_MAX, 0, 0, NULL, /* does not exist */ + -1, UINT32_MAX, 0, NULL, /* does not exist */ }, { SDB_CONNECTION_QUERY, "TIMESERIES 'x1'.'m1'", -1, - -1, UINT32_MAX, 0, 0, NULL, /* does not exist */ + -1, UINT32_MAX, 0, NULL, /* does not exist */ }, /* store commands */ { SDB_CONNECTION_QUERY, "STORE host 'hA' LAST UPDATE 01:00", -1, - 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored host hA", }, { SDB_CONNECTION_STORE, "\0\0\0\1""\0\0\0\0\xd6\x93\xa4\0""hA", 15, - 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored host hA", }, { SDB_CONNECTION_QUERY, "STORE host 'hA'", -1, - 0, SDB_CONNECTION_OK, 27, 0, "Successfully stored host hA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored host hA", }, { SDB_CONNECTION_QUERY, "STORE host attribute 'h1'.'aA' 'vA'", -1, - 0, SDB_CONNECTION_OK, 40, 0, "Successfully stored host attribute h1.aA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored host attribute h1.aA", }, { SDB_CONNECTION_STORE, "\0\0\0\x11""\0\0\0\0\xd6\x93\xa4\0""h1\0aA\0"VALUE, 18+VALUE_LEN, - 0, SDB_CONNECTION_OK, 40, 0, "Successfully stored host attribute h1.aA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored host attribute h1.aA", }, { SDB_CONNECTION_QUERY, "STORE host attribute 'x1'.'aA' 'vA'", -1, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_STORE, "\0\0\0\x11""\0\0\0\0\xd6\x93\xa4\0""x1\0aA\0"VALUE, 18+VALUE_LEN, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_QUERY, "STORE service 'h1'.'sA'", -1, - 0, SDB_CONNECTION_OK, 33, 0, "Successfully stored service h1.sA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored service h1.sA", }, { SDB_CONNECTION_STORE, "\0\0\0\2""\0\0\0\0\xd6\x93\xa4\0""h1\0sA", 18, - 0, SDB_CONNECTION_OK, 33, 0, "Successfully stored service h1.sA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored service h1.sA", }, { SDB_CONNECTION_QUERY, "STORE service 'x1'.'sA'", -1, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_STORE, "\0\0\0\x12""\0\0\0\0\xd6\x93\xa4\0""x1\0sA", 18, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_QUERY, "STORE service attribute 'h2'.'s1'.'aA' 'vA'", -1, - 0, SDB_CONNECTION_OK, 46, 0, "Successfully stored service attribute h2.s1.aA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored service attribute h2.s1.aA", }, { SDB_CONNECTION_STORE, "\0\0\0\x12""\0\0\0\0\xd6\x93\xa4\0""h2\0s1\0aA\0"VALUE,27+VALUE_LEN, - 0, SDB_CONNECTION_OK, 46, 0, "Successfully stored service attribute h2.s1.aA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored service attribute h2.s1.aA", }, { SDB_CONNECTION_QUERY, "STORE service attribute 'h2'.'x1'.'aA' 'vA'", -1, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_STORE, "\0\0\0\x12""\0\0\0\0\xd6\x93\xa4\0""h2\0x1\0aA\0"VALUE,27+VALUE_LEN, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_QUERY, "STORE metric 'h1'.'mA'", -1, - 0, SDB_CONNECTION_OK, 32, 0, "Successfully stored metric h1.mA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored metric h1.mA", }, { SDB_CONNECTION_STORE, "\0\0\0\3""\0\0\0\0\xd6\x93\xa4\0""h1\0mA", 18, - 0, SDB_CONNECTION_OK, 32, 0, "Successfully stored metric h1.mA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored metric h1.mA", }, { SDB_CONNECTION_QUERY, "STORE metric 'x1'.'mA'", -1, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_STORE, "\0\0\0\3""\0\0\0\0\xd6\x93\xa4\0""x1\0mA", 18, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_QUERY, "STORE metric attribute 'h1'.'m1'.'aA' 'vA'", -1, - 0, SDB_CONNECTION_OK, 45, 0, "Successfully stored metric attribute h1.m1.aA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored metric attribute h1.m1.aA", }, { SDB_CONNECTION_STORE, "\0\0\0\x13""\0\0\0\0\xd6\x93\xa4\0""h1\0m1\0aA\0"VALUE, 27+VALUE_LEN, - 0, SDB_CONNECTION_OK, 45, 0, "Successfully stored metric attribute h1.m1.aA", + 0, SDB_CONNECTION_OK, 0, "Successfully stored metric attribute h1.m1.aA", }, { SDB_CONNECTION_QUERY, "STORE metric attribute 'h1'.'x1'.'aA' 'vA'", -1, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, { SDB_CONNECTION_STORE, "\0\0\0\x13""\0\0\0\0\xd6\x93\xa4\0""h1\0x1\0aA\0"VALUE, 27+VALUE_LEN, - -1, UINT32_MAX, 0, 0, NULL, + -1, UINT32_MAX, 0, NULL, }, }; @@ -814,11 +814,9 @@ START_TEST(test_query) data += tmp; len -= tmp; - fail_unless((code == query_data[_i].code) - && ((size_t)msg_len == query_data[_i].len), - "sdb_conn_query(%s) returned %u, %u; expected: %u, %zu", - query_data[_i].query, code, msg_len, - query_data[_i].code, query_data[_i].len); + fail_unless(code == query_data[_i].code, + "sdb_conn_query(%s) returned <%u>; expected: <%u>", + query_data[_i].query, code, query_data[_i].code); if (code == SDB_CONNECTION_DATA) { tmp = sdb_proto_unmarshal_int32(data, len, &code); diff --git a/t/unit/parser/parser_test.c b/t/unit/parser/parser_test.c index 8da4ef0..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 @@ -678,7 +678,7 @@ START_TEST(test_parse) sdb_strbuf_t *errbuf = sdb_strbuf_create(64); sdb_llist_t *check; sdb_ast_node_t *node; - sdb_store_query_t *q; + sdb_memstore_query_t *q; _Bool ok; check = sdb_parser_parse(parse_data[_i].query, @@ -741,9 +741,9 @@ START_TEST(test_parse) } /* TODO: this should move into front-end specific tests */ - q = sdb_store_query_prepare(node); + 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));