Navigation Menu

Skip to content

Commit

Permalink
Add DB level configuration store
Browse files Browse the repository at this point in the history
  • Loading branch information
kou committed Oct 8, 2015
1 parent 5a348ae commit 29f96b3
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/groonga.h
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions include/groonga/Makefile.am
@@ -1,6 +1,7 @@
groonga_includedir = $(pkgincludedir)/groonga
groonga_include_HEADERS = \
command.h \
conf.h \
expr.h \
geo.h \
groonga.h \
Expand Down
42 changes: 42 additions & 0 deletions include/groonga/conf.h
@@ -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 */
116 changes: 116 additions & 0 deletions lib/conf.c
@@ -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);
}
81 changes: 74 additions & 7 deletions lib/db.c
Expand Up @@ -33,6 +33,7 @@
#include "grn_report.h"
#include "grn_util.h"
#include <string.h>
#include <sys/stat.h>

typedef struct {
grn_id id;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
Expand Down Expand Up @@ -234,20 +280,24 @@ 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);
grn_db_init_builtin_types(ctx);
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);
Expand All @@ -264,6 +314,12 @@ grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg)
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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 :
Expand Down
1 change: 1 addition & 0 deletions lib/grn_db.h
Expand Up @@ -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;
};
Expand Down
1 change: 1 addition & 0 deletions lib/sources.am
Expand Up @@ -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 \
Expand Down
4 changes: 3 additions & 1 deletion test/unit/core/Makefile.am
Expand Up @@ -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 = \
Expand Down Expand Up @@ -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

0 comments on commit 29f96b3

Please sign in to comment.