X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=blobdiff_plain;f=src%2Fcore%2Fmemstore_exec.c;fp=src%2Fcore%2Fmemstore_exec.c;h=a489a665c57ece9d19254611b8ae0832e10b168b;hp=0000000000000000000000000000000000000000;hb=25bba5d07cafb9f1169d687bffb742dae6f77a8e;hpb=78ea02850cbffccb0df63d77cd4e42238137e63f 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 : */