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 | |
24 | grn_rc |
25 | grn_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 | |
88 | grn_rc |
89 | grn_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 | |
128 | grn_rc |
129 | grn_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 | |
174 | grn_obj * |
175 | grn_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 | |
217 | grn_rc |
218 | grn_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 | |
226 | grn_bool |
227 | grn_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 | |
239 | uint32_t |
240 | grn_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 | |
254 | uint32_t |
255 | grn_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. */ |
274 | grn_rc |
275 | grn_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 | |
282 | grn_rc |
283 | grn_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 | |