From 4404b790e34bebc820c02d5749c84c0c975ba417 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Mon, 18 May 2015 23:57:06 +0200 Subject: [PATCH] frontend: Drop sdb_fe_store_* in favor of sdb_store_query_execute. Instead, build a temporary AST to represent the command to be executed. --- src/Makefile.am | 1 - src/frontend/query.c | 111 ++++++++++++++++++ src/frontend/store.c | 221 ----------------------------------- t/unit/frontend/query_test.c | 6 +- 4 files changed, 113 insertions(+), 226 deletions(-) delete mode 100644 src/frontend/store.c diff --git a/src/Makefile.am b/src/Makefile.am index 52bd42b..48561c3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -92,7 +92,6 @@ libsysdb_la_SOURCES = \ frontend/parser.c include/frontend/parser.h \ frontend/sock.c include/frontend/sock.h \ frontend/session.c \ - frontend/store.c \ frontend/query.c \ parser/analyzer.c \ parser/ast.c include/parser/ast.h \ diff --git a/src/frontend/query.c b/src/frontend/query.c index d04aca9..97698fd 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -46,6 +46,12 @@ * private helper functions */ +static char * +sstrdup(const char *s) +{ + return s ? strdup(s) : NULL; +} /* sstrdup */ + static int query_exec(sdb_conn_t *conn, sdb_ast_node_t *ast) { @@ -261,5 +267,110 @@ sdb_fe_lookup(sdb_conn_t *conn) return status; } /* sdb_fe_lookup */ +int +sdb_fe_store(sdb_conn_t *conn) +{ + sdb_ast_node_t *ast; + const char *buf = sdb_strbuf_string(conn->buf); + size_t len = conn->cmd_len; + uint32_t type; + ssize_t n; + int status; + + if ((! conn) || (conn->cmd != SDB_CONNECTION_STORE)) + return -1; + + if ((n = sdb_proto_unmarshal_int32(buf, len, &type)) < 0) { + sdb_log(SDB_LOG_ERR, "frontend: Invalid command length %zu for " + "STORE command", len); + sdb_strbuf_sprintf(conn->errbuf, + "STORE: Invalid command length %zu", len); + return -1; + } + + switch (type) { + case SDB_HOST: + { + sdb_proto_host_t host; + if (sdb_proto_unmarshal_host(buf, len, &host) < 0) { + sdb_strbuf_sprintf(conn->errbuf, + "STORE: Failed to unmarshal host object"); + return -1; + } + ast = sdb_ast_store_create(SDB_HOST, /* host */ NULL, + /* parent */ 0, NULL, sstrdup(host.name), host.last_update, + /* metric store */ NULL, NULL, SDB_DATA_NULL); + } + break; + + case SDB_SERVICE: + { + sdb_proto_service_t svc; + if (sdb_proto_unmarshal_service(buf, len, &svc) < 0) { + sdb_strbuf_sprintf(conn->errbuf, + "STORE: Failed to unmarshal service object"); + return -1; + } + ast = sdb_ast_store_create(SDB_SERVICE, sstrdup(svc.hostname), + /* parent */ 0, NULL, sstrdup(svc.name), svc.last_update, + /* metric store */ NULL, NULL, SDB_DATA_NULL); + } + break; + + case SDB_METRIC: + { + sdb_proto_metric_t metric; + if (sdb_proto_unmarshal_metric(buf, len, &metric) < 0) { + sdb_strbuf_sprintf(conn->errbuf, + "STORE: Failed to unmarshal metric object"); + return -1; + } + ast = sdb_ast_store_create(SDB_METRIC, sstrdup(metric.hostname), + /* parent */ 0, NULL, sstrdup(metric.name), metric.last_update, + sstrdup(metric.store_type), sstrdup(metric.store_id), + SDB_DATA_NULL); + } + break; + } + + if (type & SDB_ATTRIBUTE) { + sdb_proto_attribute_t attr; + const char *hostname, *parent; + int parent_type; + if (sdb_proto_unmarshal_attribute(buf, len, &attr) < 0) { + sdb_strbuf_sprintf(conn->errbuf, + "STORE: Failed to unmarshal attribute object"); + return -1; + } + if (attr.parent_type == SDB_HOST) { + hostname = attr.parent; + parent_type = 0; + parent = NULL; + } + else { + hostname = attr.hostname; + parent_type = attr.parent_type; + parent = attr.parent; + } + ast = sdb_ast_store_create(SDB_ATTRIBUTE, sstrdup(hostname), + parent_type, sstrdup(parent), sstrdup(attr.key), + attr.last_update, /* metric store */ NULL, NULL, + attr.value); + } + + if (! ast) { + sdb_log(SDB_LOG_ERR, "frontend: Invalid object type %d for " + "STORE COMMAND", type); + sdb_strbuf_sprintf(conn->errbuf, "STORE: Invalid object type %d", type); + return -1; + } + + status = sdb_parser_analyze(ast, conn->errbuf); + if (! status) + status = query_exec(conn, ast); + sdb_object_deref(SDB_OBJ(ast)); + return status; +} /* sdb_fe_store */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/frontend/store.c b/src/frontend/store.c deleted file mode 100644 index 3d1a847..0000000 --- a/src/frontend/store.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * SysDB - src/frontend/store.c - * Copyright (C) 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 "sysdb.h" - -#include "core/store.h" -#include "frontend/connection-private.h" -#include "utils/error.h" -#include "utils/proto.h" -#include "utils/strbuf.h" - -#include -#include - -/* - * private helper functions - */ - -static int -store_reply(sdb_conn_t *conn, int type, const char *name, int status) -{ - if (status < 0) { - sdb_strbuf_sprintf(conn->errbuf, "STORE: Failed to store %s object", - SDB_STORE_TYPE_TO_NAME(type)); - return -1; - } - - if (! status) { - char msg[strlen(name) + 64]; - snprintf(msg, sizeof(msg), "Successfully stored %s %s", - SDB_STORE_TYPE_TO_NAME(type), name); - msg[sizeof(msg) - 1] = '\0'; - sdb_connection_send(conn, SDB_CONNECTION_OK, - (uint32_t)strlen(msg), msg); - } - else { - char msg[strlen(name) + 64]; - snprintf(msg, sizeof(msg), "%s %s already up to date", - SDB_STORE_TYPE_TO_NAME(type), name); - msg[0] = (char)toupper((int)msg[0]); - msg[sizeof(msg) - 1] = '\0'; - sdb_connection_send(conn, SDB_CONNECTION_OK, - (uint32_t)strlen(msg), msg); - } - return 0; -} /* store_reply */ - -/* - * public API - */ - -/* - * TODO: move sdb_fe_store to frontend/query.c and let it build an AST - */ - -int -sdb_fe_store(sdb_conn_t *conn) -{ - uint32_t type; - - const char *buf = sdb_strbuf_string(conn->buf); - size_t len = conn->cmd_len; - ssize_t n; - - if ((! conn) || (conn->cmd != SDB_CONNECTION_STORE)) - return -1; - - if ((n = sdb_proto_unmarshal_int32(buf, len, &type)) < 0) { - sdb_log(SDB_LOG_ERR, "frontend: Invalid command length %zu for " - "STORE command", len); - sdb_strbuf_sprintf(conn->errbuf, - "STORE: Invalid command length %zu", len); - return -1; - } - - switch (type) { - case SDB_HOST: - { - sdb_proto_host_t host; - if (sdb_proto_unmarshal_host(buf, len, &host) < 0) { - sdb_strbuf_sprintf(conn->errbuf, - "STORE: Failed to unmarshal host object"); - return -1; - } - return sdb_fe_store_host(conn, &host); - } - case SDB_SERVICE: - { - sdb_proto_service_t svc; - if (sdb_proto_unmarshal_service(buf, len, &svc) < 0) { - sdb_strbuf_sprintf(conn->errbuf, - "STORE: Failed to unmarshal service object"); - return -1; - } - return sdb_fe_store_service(conn, &svc); - } - case SDB_METRIC: - { - sdb_proto_metric_t metric; - if (sdb_proto_unmarshal_metric(buf, len, &metric) < 0) { - sdb_strbuf_sprintf(conn->errbuf, - "STORE: Failed to unmarshal metric object"); - return -1; - } - return sdb_fe_store_metric(conn, &metric); - } - } - if (type & SDB_ATTRIBUTE) { - sdb_proto_attribute_t attr; - int status; - if (sdb_proto_unmarshal_attribute(buf, len, &attr) < 0) { - sdb_strbuf_sprintf(conn->errbuf, - "STORE: Failed to unmarshal attribute object"); - return -1; - } - status = sdb_fe_store_attribute(conn, &attr); - sdb_data_free_datum(&attr.value); - return status; - } - - sdb_log(SDB_LOG_ERR, "frontend: Invalid object type %d for " - "STORE COMMAND", type); - sdb_strbuf_sprintf(conn->errbuf, "STORE: Invalid object type %d", type); - return -1; -} /* sdb_fe_store */ - -int -sdb_fe_store_host(sdb_conn_t *conn, const sdb_proto_host_t *host) -{ - if ((! conn) || (! host) || (! host->name)) - return -1; - - return store_reply(conn, SDB_HOST, host->name, - sdb_store_host(host->name, host->last_update)); -} /* sdb_fe_store_host */ - -int -sdb_fe_store_service(sdb_conn_t *conn, const sdb_proto_service_t *svc) -{ - char name[svc ? strlen(svc->hostname) + strlen(svc->name) + 2 : 2]; - - if ((! conn) || (! svc) || (! svc->hostname) || (! svc->name)) - return -1; - - snprintf(name, sizeof(name), "%s.%s", svc->hostname, svc->name); - return store_reply(conn, SDB_SERVICE, name, - sdb_store_service(svc->hostname, svc->name, svc->last_update)); -} /* sdb_fe_store_service */ - -int -sdb_fe_store_metric(sdb_conn_t *conn, const sdb_proto_metric_t *metric) -{ - sdb_metric_store_t store; - char name[metric ? strlen(metric->hostname) + strlen(metric->name) + 2 : 2]; - - if ((! conn) || (! metric) || (! metric->hostname) || (! metric->name)) - return -1; - - store.type = metric->store_type; - store.id = metric->store_id; - snprintf(name, sizeof(name), "%s.%s", metric->hostname, metric->name); - return store_reply(conn, SDB_METRIC, name, - sdb_store_metric(metric->hostname, metric->name, - &store, metric->last_update)); -} /* sdb_fe_store_metric */ - -int -sdb_fe_store_attribute(sdb_conn_t *conn, const sdb_proto_attribute_t *attr) -{ - char name[attr ? strlen(attr->parent) + strlen(attr->key) + 2 : 2]; - int status; - - if ((! conn) || (! attr) || (! attr->parent) || (! attr->key)) - return -1; - - if (attr->parent_type == SDB_HOST) - status = sdb_store_attribute(attr->parent, - attr->key, &attr->value, attr->last_update); - else if (attr->parent_type == SDB_SERVICE) - status = sdb_store_service_attr(attr->hostname, attr->parent, - attr->key, &attr->value, attr->last_update); - else if (attr->parent_type == SDB_METRIC) - status = sdb_store_metric_attr(attr->hostname, attr->parent, - attr->key, &attr->value, attr->last_update); - else { - sdb_strbuf_sprintf(conn->errbuf, - "STORE: Invalid parent object type %d", - attr->parent_type); - return -1; - } - - snprintf(name, sizeof(name), "%s.%s", attr->parent, attr->key); - return store_reply(conn, attr->parent_type | SDB_ATTRIBUTE, name, status); -} /* sdb_fe_store_attribute */ - -/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ - diff --git a/t/unit/frontend/query_test.c b/t/unit/frontend/query_test.c index 00a208f..a90b00f 100644 --- a/t/unit/frontend/query_test.c +++ b/t/unit/frontend/query_test.c @@ -597,8 +597,7 @@ static struct { }, { 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, 43, 0, "Successfully stored service attribute s1.aA", - /* TODO: 46, h2.s1.aA */ + 0, SDB_CONNECTION_OK, 46, 0, "Successfully stored service attribute h2.s1.aA", }, { SDB_CONNECTION_QUERY, "STORE service attribute 'h2'.'x1'.'aA' 'vA'", -1, @@ -630,8 +629,7 @@ static struct { }, { 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, 42, 0, "Successfully stored metric attribute m1.aA", - /* TODO: 45, h1.m1.aA */ + 0, SDB_CONNECTION_OK, 45, 0, "Successfully stored metric attribute h1.m1.aA", }, { SDB_CONNECTION_QUERY, "STORE metric attribute 'h1'.'x1'.'aA' 'vA'", -1, -- 2.30.2