Kouhei Sutou
null+****@clear*****
Thu Oct 8 17:35:18 JST 2015
Kouhei Sutou 2015-10-08 17:35:18 +0900 (Thu, 08 Oct 2015) New Revision: 29f96b380b77d227619a2082e671bc43db5358d6 https://github.com/groonga/groonga/commit/29f96b380b77d227619a2082e671bc43db5358d6 Message: Add DB level configuration store Added files: include/groonga/conf.h lib/conf.c test/unit/core/test-conf.c Modified files: include/groonga.h include/groonga/Makefile.am lib/db.c lib/grn_db.h lib/sources.am test/unit/core/Makefile.am Modified: include/groonga.h (+1 -0) =================================================================== --- include/groonga.h 2015-10-08 15:35:39 +0900 (8f68051) +++ include/groonga.h 2015-10-08 17:35:18 +0900 (57143d0) @@ -20,6 +20,7 @@ #include "groonga/portability.h" #include "groonga/groonga.h" +#include "groonga/conf.h" #include "groonga/obj.h" #include "groonga/ii.h" #include "groonga/geo.h" Modified: include/groonga/Makefile.am (+1 -0) =================================================================== --- include/groonga/Makefile.am 2015-10-08 15:35:39 +0900 (1cc2ed1) +++ include/groonga/Makefile.am 2015-10-08 17:35:18 +0900 (c39b664) @@ -1,6 +1,7 @@ groonga_includedir = $(pkgincludedir)/groonga groonga_include_HEADERS = \ command.h \ + conf.h \ expr.h \ geo.h \ groonga.h \ Added: include/groonga/conf.h (+42 -0) 100644 =================================================================== --- /dev/null +++ include/groonga/conf.h 2015-10-08 17:35:18 +0900 (9fc556c) @@ -0,0 +1,42 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRN_CONF_H +#define GRN_CONF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_CONF_MAX_KEY_SIZE GRN_TABLE_MAX_KEY_SIZE +#define GRN_CONF_MAX_VALUE_SIZE \ + (GRN_CONF_VALUE_SPACE_SIZE - sizeof(uint32_t) - 1) /* 1 is for '\0' */ +#define GRN_CONF_VALUE_SPACE_SIZE (4 * 1024) + +GRN_API grn_rc grn_conf_set(grn_ctx *ctx, + const char *key, int key_size, + const char *value, int value_size); +GRN_API grn_rc grn_conf_get(grn_ctx *ctx, + const char *key, int key_size, + const char **value, uint32_t *value_size); + +#ifdef __cplusplus +} +#endif + +#endif /* GRN_CONF_H */ Added: lib/conf.c (+116 -0) 100644 =================================================================== --- /dev/null +++ lib/conf.c 2015-10-08 17:35:18 +0900 (5408e8b) @@ -0,0 +1,116 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "grn_ctx_impl.h" +#include "grn_hash.h" +#include "grn_db.h" + +#include <string.h> + +grn_rc +grn_conf_set(grn_ctx *ctx, + const char *key, int key_size, + const char *value, int value_size) +{ + grn_obj *db; + grn_hash *conf; + void *packed_value; + grn_id id; + + GRN_API_ENTER; + + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[conf][set] DB isn't initialized"); + GRN_API_RETURN(ctx->rc); + } + + if (key_size == -1) { + key_size = strlen(key); + } + if (key_size > GRN_CONF_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[conf][set] too large key: max=<%d>: <%d>", + GRN_CONF_MAX_KEY_SIZE, key_size); + GRN_API_RETURN(ctx->rc); + } + + if (value_size == -1) { + value_size = strlen(value); + } + if (value_size > GRN_CONF_MAX_VALUE_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[conf][set] too large value: max=<%lu>: <%d>", + GRN_CONF_MAX_VALUE_SIZE, value_size); + GRN_API_RETURN(ctx->rc); + } + + conf = ((grn_db *)db)->conf; + id = grn_hash_add(ctx, conf, key, key_size, &packed_value, NULL); + if (id == GRN_ID_NIL && ctx->rc == GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[conf][set] failed to set: name=<%.*s>: <%d>", + key_size, key, value_size); + } + + *((uint32_t *)packed_value) = (uint32_t)value_size; + grn_memcpy((char *)packed_value + sizeof(uint32_t), + value, value_size); + ((char *)packed_value)[sizeof(uint32_t) + value_size] = '\0'; + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_conf_get(grn_ctx *ctx, + const char *key, int key_size, + const char **value, uint32_t *value_size) +{ + grn_obj *db; + grn_hash *conf; + grn_id id; + void *packed_value; + + GRN_API_ENTER; + + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[conf][get] DB isn't initialized"); + GRN_API_RETURN(ctx->rc); + } + + if (key_size == -1) { + key_size = strlen(key); + } + if (key_size > GRN_CONF_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[conf][get] too large key: max=<%d>: <%d>", + GRN_CONF_MAX_KEY_SIZE, key_size); + GRN_API_RETURN(ctx->rc); + } + + conf = ((grn_db *)db)->conf; + id = grn_hash_get(ctx, conf, key, key_size, &packed_value); + if (id == GRN_ID_NIL) { + *value = NULL; + *value_size = 0; + GRN_API_RETURN(GRN_SUCCESS); + } + + *value = (char *)packed_value + sizeof(uint32_t); + *value_size = *((uint32_t *)packed_value); + GRN_API_RETURN(GRN_SUCCESS); +} Modified: lib/db.c (+74 -7) =================================================================== --- lib/db.c 2015-10-08 15:35:39 +0900 (549b996) +++ lib/db.c 2015-10-08 17:35:18 +0900 (3b7f76e) @@ -33,6 +33,7 @@ #include "grn_report.h" #include "grn_util.h" #include <string.h> +#include <sys/stat.h> typedef struct { grn_id id; @@ -174,6 +175,50 @@ typedef struct { uint32_t done; } db_value; +static const char *GRN_DB_CONF_PATH_FORMAT = "%s.conf"; + +static grn_bool +grn_db_conf_create(grn_ctx *ctx, grn_db *s, const char *path, + const char *context_tag) +{ + char conf_path[PATH_MAX]; + uint32_t flags = GRN_OBJ_KEY_VAR_SIZE; + + grn_snprintf(conf_path, PATH_MAX, PATH_MAX, GRN_DB_CONF_PATH_FORMAT, path); + s->conf = grn_hash_create(ctx, conf_path, + GRN_CONF_MAX_KEY_SIZE, + GRN_CONF_VALUE_SPACE_SIZE, + flags); + if (!s->conf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "%s failed to create conf: <%s>", + context_tag, conf_path); + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static grn_bool +grn_db_conf_open(grn_ctx *ctx, grn_db *s, const char *path) +{ + char conf_path[PATH_MAX]; + struct stat status; + + grn_snprintf(conf_path, PATH_MAX, PATH_MAX, GRN_DB_CONF_PATH_FORMAT, path); + if (stat(conf_path, &status) == 0) { + s->conf = grn_hash_open(ctx, conf_path); + if (!s->conf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[db][open] failed to open conf: <%s>", conf_path); + return GRN_FALSE; + } + return GRN_TRUE; + } else { + return grn_db_conf_create(ctx, s, path, "[db][open]"); + } +} + grn_obj * grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg) { @@ -199,6 +244,7 @@ grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg) GRN_TINY_ARRAY_USE_MALLOC); s->keys = NULL; s->specs = NULL; + s->conf = NULL; { grn_bool use_default_db_key = GRN_TRUE; @@ -234,12 +280,17 @@ grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg) DB_OBJ(&s->obj)->range = GRN_ID_NIL; /* prepare builtin classes and load builtin plugins. */ if (path) { - char specs_path[PATH_MAX]; - gen_pathname(path, specs_path, 0); - s->specs = grn_ja_create(ctx, specs_path, 65536, 0); - if (!s->specs) { - ERR(GRN_NO_MEMORY_AVAILABLE, - "failed to create specs: <%s>", specs_path); + { + char specs_path[PATH_MAX]; + gen_pathname(path, specs_path, 0); + s->specs = grn_ja_create(ctx, specs_path, 65536, 0); + if (!s->specs) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to create specs: <%s>", specs_path); + goto exit; + } + } + if (!grn_db_conf_create(ctx, s, path, "[db][create]")) { goto exit; } grn_ctx_use(ctx, (grn_obj *)s); @@ -247,7 +298,6 @@ grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg) grn_obj_flush(ctx, (grn_obj *)s); GRN_API_RETURN((grn_obj *)s); } else { - s->specs = NULL; grn_ctx_use(ctx, (grn_obj *)s); grn_db_init_builtin_types(ctx); GRN_API_RETURN((grn_obj *)s); @@ -264,6 +314,12 @@ exit: grn_dat_remove(ctx, path); } } + if (s->specs) { + const char *specs_path; + specs_path = grn_obj_path(ctx, (grn_obj *)(s->specs)); + grn_ja_close(ctx, s->specs); + grn_ja_remove(ctx, specs_path); + } grn_tiny_array_fin(&s->values); CRITICAL_SECTION_FIN(s->lock); GRN_FREE(s); @@ -302,6 +358,7 @@ grn_db_open(grn_ctx *ctx, const char *path) GRN_TINY_ARRAY_USE_MALLOC); s->keys = NULL; s->specs = NULL; + s->conf = NULL; { uint32_t type = grn_io_detect_type(ctx, path); @@ -337,6 +394,9 @@ grn_db_open(grn_ctx *ctx, const char *path) goto exit; } } + if (!grn_db_conf_open(ctx, s, path)) { + goto exit; + } GRN_DB_OBJ_SET_TYPE(s, GRN_DB); s->obj.db = (grn_obj *)s; @@ -356,6 +416,9 @@ grn_db_open(grn_ctx *ctx, const char *path) exit: if (s) { + if (s->specs) { + grn_ja_close(ctx, s->specs); + } if (s->keys) { if (s->keys->header.type == GRN_TABLE_PAT_KEY) { grn_pat_close(ctx, (grn_pat *)s->keys); @@ -439,6 +502,7 @@ grn_db_close(grn_ctx *ctx, grn_obj *db) } CRITICAL_SECTION_FIN(s->lock); if (s->specs) { grn_ja_close(ctx, s->specs); } + grn_hash_close(ctx, s->conf); GRN_FREE(s); if (ctx_used_db) { @@ -10284,6 +10348,9 @@ grn_obj_flush(grn_ctx *ctx, grn_obj *obj) if (rc == GRN_SUCCESS && db->specs) { rc = grn_obj_flush(ctx, (grn_obj *)(db->specs)); } + if (rc == GRN_SUCCESS) { + rc = grn_obj_flush(ctx, (grn_obj *)(db->conf)); + } } break; case GRN_TABLE_DAT_KEY : Modified: lib/grn_db.h (+1 -0) =================================================================== --- lib/grn_db.h 2015-10-08 15:35:39 +0900 (57dae16) +++ lib/grn_db.h 2015-10-08 17:35:18 +0900 (f647f14) @@ -47,6 +47,7 @@ struct _grn_db { grn_db_obj obj; grn_obj *keys; grn_ja *specs; + grn_hash *conf; grn_tiny_array values; grn_critical_section lock; }; Modified: lib/sources.am (+1 -0) =================================================================== --- lib/sources.am 2015-10-08 15:35:39 +0900 (5fdb9cc) +++ lib/sources.am 2015-10-08 17:35:18 +0900 (631c407) @@ -2,6 +2,7 @@ libgroonga_la_SOURCES = \ com.c \ grn_com.h \ command.c \ + conf.c \ ctx.c \ grn_ctx.h \ grn_ctx_impl.h \ Modified: test/unit/core/Makefile.am (+3 -1) =================================================================== --- test/unit/core/Makefile.am 2015-10-08 15:35:39 +0900 (b4943ba) +++ test/unit/core/Makefile.am 2015-10-08 17:35:18 +0900 (b2c4619) @@ -64,7 +64,8 @@ noinst_LTLIBRARIES = \ test-tokenizer.la \ test-proc.la \ test-uvector.la \ - test-operator.la + test-operator.la \ + test-conf.la endif AM_CPPFLAGS = \ @@ -154,3 +155,4 @@ test_tokenizer_la_SOURCES = test-tokenizer.c test_proc_la_SOURCES = test-proc.c test_uvector_la_SOURCES = test-uvector.c test_operator_la_SOURCES = test-operator.c +test_conf_la_SOURCES = test-conf.c Added: test/unit/core/test-conf.c (+93 -0) 100644 =================================================================== --- /dev/null +++ test/unit/core/test-conf.c 2015-10-08 17:35:18 +0900 (2df0301) @@ -0,0 +1,93 @@ +/* -*- c-basic-offset: 2; coding: utf-8 -*- */ +/* + Copyright (C) 2015 Kouhei Sutou <kou �� clear-code.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <groonga.h> + +#include <gcutter.h> +#include <glib/gstdio.h> + +#include "../lib/grn-assertions.h" + +static gchar *tmp_directory; +static gchar *path; +static grn_ctx context; +static grn_obj *database; + +void test_set_and_get(void); +void test_get_nonexistent(void); + +void +cut_startup(void) +{ + tmp_directory = g_build_filename(grn_test_get_tmp_dir(), + "test-conf", + NULL); +} + +void +cut_shutdown(void) +{ + g_free(tmp_directory); +} + +void +cut_setup(void) +{ + cut_remove_path(tmp_directory, NULL); + g_mkdir_with_parents(tmp_directory, 0700); + path = g_build_filename(tmp_directory, "text-conf", NULL); + grn_ctx_init(&context, 0); + database = grn_db_create(&context, path, NULL); +} + +void +cut_teardown(void) +{ + grn_obj_close(&context, database); + grn_ctx_fin(&context); + cut_remove_path(tmp_directory, NULL); + g_free(path); +} + +void +test_set_and_get(void) +{ + const char *value; + uint32_t value_size; + + grn_test_assert(grn_conf_set(&context, "key", -1, "value", -1)); + grn_test_assert(grn_conf_get(&context, "key", -1, &value, &value_size)); + + cut_assert_equal_memory("value", strlen("value"), + value, value_size); +} + +void +test_get_nonexistent(void) +{ + const char *value; + uint32_t value_size; + + grn_test_assert(grn_conf_get(&context, + "noneixstent", -1, + &value, &value_size)); + + cut_assert_equal_memory(NULL, 0, + value, value_size); +} + -------------- next part -------------- HTML����������������������������...Download