[Groonga-commit] groonga/groonga at 29f96b3 [master] Add DB level configuration store

Back to archive index

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 



More information about the Groonga-commit mailing list
Back to archive index