1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2015-2016 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "grn_ctx_impl.h"
20#include "grn_config.h"
21
22#include <string.h>
23
24grn_rc
25grn_config_set(grn_ctx *ctx,
26 const char *key, int32_t key_size,
27 const char *value, int32_t value_size)
28{
29 grn_obj *db;
30 grn_hash *config;
31 void *packed_value;
32 grn_id id;
33
34 GRN_API_ENTER;
35
36 if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
37 ERR(GRN_INVALID_ARGUMENT, "[config][set] DB isn't initialized");
38 GRN_API_RETURN(ctx->rc);
39 }
40
41 if (key_size == -1) {
42 key_size = strlen(key);
43 }
44 if (key_size > GRN_CONFIG_MAX_KEY_SIZE) {
45 ERR(GRN_INVALID_ARGUMENT,
46 "[config][set] too large key: max=<%d>: <%d>",
47 GRN_CONFIG_MAX_KEY_SIZE, key_size);
48 GRN_API_RETURN(ctx->rc);
49 }
50
51 if (value_size == -1) {
52 value_size = strlen(value);
53 }
54 if (value_size > GRN_CONFIG_MAX_VALUE_SIZE) {
55 ERR(GRN_INVALID_ARGUMENT,
56 "[config][set] too large value: max=<%" GRN_FMT_SIZE ">: <%d>",
57 GRN_CONFIG_MAX_VALUE_SIZE, value_size);
58 GRN_API_RETURN(ctx->rc);
59 }
60
61 config = ((grn_db *)db)->config;
62 {
63 grn_rc rc;
64 rc = grn_io_lock(ctx, config->io, grn_lock_timeout);
65 if (rc != GRN_SUCCESS) {
66 if (ctx->rc == GRN_SUCCESS) {
67 ERR(rc, "[config][set] failed to lock");
68 }
69 GRN_API_RETURN(rc);
70 }
71 id = grn_hash_add(ctx, config, key, key_size, &packed_value, NULL);
72 grn_io_unlock(config->io);
73 }
74 if (id == GRN_ID_NIL && ctx->rc == GRN_SUCCESS) {
75 ERR(GRN_INVALID_ARGUMENT,
76 "[config][set] failed to set: name=<%.*s>: <%d>",
77 key_size, key, value_size);
78 }
79
80 *((uint32_t *)packed_value) = (uint32_t)value_size;
81 grn_memcpy((char *)packed_value + sizeof(uint32_t),
82 value, value_size);
83 ((char *)packed_value)[sizeof(uint32_t) + value_size] = '\0';
84
85 GRN_API_RETURN(ctx->rc);
86}
87
88grn_rc
89grn_config_get(grn_ctx *ctx,
90 const char *key, int32_t key_size,
91 const char **value, uint32_t *value_size)
92{
93 grn_obj *db;
94 grn_hash *config;
95 grn_id id;
96 void *packed_value;
97
98 GRN_API_ENTER;
99
100 if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
101 ERR(GRN_INVALID_ARGUMENT, "[config][get] DB isn't initialized");
102 GRN_API_RETURN(ctx->rc);
103 }
104
105 if (key_size == -1) {
106 key_size = strlen(key);
107 }
108 if (key_size > GRN_CONFIG_MAX_KEY_SIZE) {
109 ERR(GRN_INVALID_ARGUMENT,
110 "[config][get] too large key: max=<%d>: <%d>",
111 GRN_CONFIG_MAX_KEY_SIZE, key_size);
112 GRN_API_RETURN(ctx->rc);
113 }
114
115 config = ((grn_db *)db)->config;
116 id = grn_hash_get(ctx, config, key, key_size, &packed_value);
117 if (id == GRN_ID_NIL) {
118 *value = NULL;
119 *value_size = 0;
120 GRN_API_RETURN(GRN_SUCCESS);
121 }
122
123 *value = (char *)packed_value + sizeof(uint32_t);
124 *value_size = *((uint32_t *)packed_value);
125 GRN_API_RETURN(GRN_SUCCESS);
126}
127
128grn_rc
129grn_config_delete(grn_ctx *ctx,
130 const char *key, int key_size)
131{
132 grn_obj *db;
133 grn_hash *config;
134
135 GRN_API_ENTER;
136
137 if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
138 ERR(GRN_INVALID_ARGUMENT, "[config][delete] DB isn't initialized");
139 GRN_API_RETURN(ctx->rc);
140 }
141
142 if (key_size == -1) {
143 key_size = strlen(key);
144 }
145 if (key_size > GRN_CONFIG_MAX_KEY_SIZE) {
146 ERR(GRN_INVALID_ARGUMENT,
147 "[config][delete] too large key: max=<%d>: <%d>",
148 GRN_CONFIG_MAX_KEY_SIZE, key_size);
149 GRN_API_RETURN(ctx->rc);
150 }
151
152 config = ((grn_db *)db)->config;
153 {
154 grn_rc rc;
155 rc = grn_io_lock(ctx, config->io, grn_lock_timeout);
156 if (rc != GRN_SUCCESS) {
157 if (ctx->rc == GRN_SUCCESS) {
158 ERR(rc, "[config][delete] failed to lock");
159 }
160 GRN_API_RETURN(rc);
161 }
162 rc = grn_hash_delete(ctx, config, key, key_size, NULL);
163 grn_io_unlock(config->io);
164 if (rc != GRN_SUCCESS) {
165 if (ctx->rc == GRN_SUCCESS) {
166 ERR(rc, "[config][delete] failed to delete");
167 }
168 }
169 }
170
171 GRN_API_RETURN(ctx->rc);
172}
173
174grn_obj *
175grn_config_cursor_open(grn_ctx *ctx)
176{
177 grn_obj *db;
178 grn_hash *config;
179 grn_config_cursor *cursor;
180 grn_id id;
181
182 GRN_API_ENTER;
183
184 if (!ctx || !ctx->impl || !(db = ctx->impl->db)) {
185 ERR(GRN_INVALID_ARGUMENT, "[config][cursor][open] DB isn't initialized");
186 GRN_API_RETURN(NULL);
187 }
188 config = ((grn_db *)db)->config;
189
190 cursor = GRN_MALLOCN(grn_config_cursor, 1);
191 if (!cursor) {
192 ERR(GRN_NO_MEMORY_AVAILABLE,
193 "[config][cursor][open] failed to allocate memory for config cursor");
194 GRN_API_RETURN(NULL);
195 }
196
197 GRN_DB_OBJ_SET_TYPE(cursor, GRN_CURSOR_CONFIG);
198 cursor->hash_cursor = grn_hash_cursor_open(ctx, config,
199 NULL, -1,
200 NULL, -1,
201 0, -1, 0);
202 if (!cursor->hash_cursor) {
203 GRN_FREE(cursor);
204 ERR(GRN_NO_MEMORY_AVAILABLE,
205 "[config][cursor][open] failed to allocate memory for hash cursor");
206 GRN_API_RETURN(NULL);
207 }
208
209 id = grn_obj_register(ctx, ctx->impl->db, NULL, 0);
210 DB_OBJ(cursor)->header.domain = GRN_ID_NIL;
211 DB_OBJ(cursor)->range = GRN_ID_NIL;
212 grn_db_obj_init(ctx, ctx->impl->db, id, DB_OBJ(cursor));
213
214 GRN_API_RETURN((grn_obj *)cursor);
215}
216
217grn_rc
218grn_config_cursor_close(grn_ctx *ctx, grn_config_cursor *cursor)
219{
220 grn_hash_cursor_close(ctx, cursor->hash_cursor);
221 GRN_FREE(cursor);
222
223 return GRN_SUCCESS;
224}
225
226grn_bool
227grn_config_cursor_next(grn_ctx *ctx, grn_obj *cursor)
228{
229 grn_bool have_next;
230 grn_config_cursor *config_cursor = (grn_config_cursor *)cursor;
231
232 GRN_API_ENTER;
233
234 have_next = grn_hash_cursor_next(ctx, config_cursor->hash_cursor) != GRN_ID_NIL;
235
236 GRN_API_RETURN(have_next);
237}
238
239uint32_t
240grn_config_cursor_get_key(grn_ctx *ctx, grn_obj *cursor, const char **key)
241{
242 void *key_raw;
243 uint32_t key_size;
244 grn_config_cursor *config_cursor = (grn_config_cursor *)cursor;
245
246 GRN_API_ENTER;
247
248 key_size = grn_hash_cursor_get_key(ctx, config_cursor->hash_cursor, &key_raw);
249 *key = key_raw;
250
251 GRN_API_RETURN(key_size);
252}
253
254uint32_t
255grn_config_cursor_get_value(grn_ctx *ctx, grn_obj *cursor, const char **value)
256{
257 void *value_raw;
258 uint32_t value_size;
259 uint32_t value_size_raw;
260 grn_config_cursor *config_cursor = (grn_config_cursor *)cursor;
261
262 GRN_API_ENTER;
263
264 value_size_raw = grn_hash_cursor_get_value(ctx,
265 config_cursor->hash_cursor,
266 &value_raw);
267 *value = (char *)value_raw + sizeof(uint32_t);
268 value_size = *((uint32_t *)value_raw);
269
270 GRN_API_RETURN(value_size);
271}
272
273/* Deprecated since 5.1.2. Use grn_config_* instead. */
274grn_rc
275grn_conf_set(grn_ctx *ctx,
276 const char *key, int32_t key_size,
277 const char *value, int32_t value_size)
278{
279 return grn_config_set(ctx, key, key_size, value, value_size);
280}
281
282grn_rc
283grn_conf_get(grn_ctx *ctx,
284 const char *key, int32_t key_size,
285 const char **value, uint32_t *value_size)
286{
287 return grn_config_get(ctx, key, key_size, value, value_size);
288}
289
290