1 /* -*- c-basic-offset: 2 -*- */
2 /*
3 Copyright(C) 2009-2017 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-1335 USA
17 */
18 #include "grn.h"
19 #include "grn_str.h"
20 #include "grn_store.h"
21 #include "grn_ctx_impl.h"
22 #include "grn_output.h"
23 #include <string.h>
24
25 /* rectangular arrays */
26
27 #define GRN_RA_W_SEGMENT 22
28 #define GRN_RA_SEGMENT_SIZE (1 << GRN_RA_W_SEGMENT)
29
30 static grn_ra *
_grn_ra_create(grn_ctx * ctx,grn_ra * ra,const char * path,unsigned int element_size)31 _grn_ra_create(grn_ctx *ctx, grn_ra *ra, const char *path, unsigned int element_size)
32 {
33 grn_io *io;
34 int max_segments, n_elm, w_elm;
35 struct grn_ra_header *header;
36 unsigned int actual_size;
37 if (element_size > GRN_RA_SEGMENT_SIZE) {
38 GRN_LOG(ctx, GRN_LOG_ERROR, "element_size too large (%d)", element_size);
39 return NULL;
40 }
41 for (actual_size = 1; actual_size < element_size; actual_size *= 2) ;
42 max_segments = ((GRN_ID_MAX + 1) / GRN_RA_SEGMENT_SIZE) * actual_size;
43 io = grn_io_create(ctx, path, sizeof(struct grn_ra_header),
44 GRN_RA_SEGMENT_SIZE, max_segments, grn_io_auto,
45 GRN_IO_EXPIRE_SEGMENT);
46 if (!io) { return NULL; }
47 header = grn_io_header(io);
48 grn_io_set_type(io, GRN_COLUMN_FIX_SIZE);
49 header->element_size = actual_size;
50 n_elm = GRN_RA_SEGMENT_SIZE / header->element_size;
51 for (w_elm = GRN_RA_W_SEGMENT; (1 << w_elm) > n_elm; w_elm--);
52 ra->io = io;
53 ra->header = header;
54 ra->element_mask = n_elm - 1;
55 ra->element_width = w_elm;
56 return ra;
57 }
58
59 grn_ra *
grn_ra_create(grn_ctx * ctx,const char * path,unsigned int element_size)60 grn_ra_create(grn_ctx *ctx, const char *path, unsigned int element_size)
61 {
62 grn_ra *ra = (grn_ra *)GRN_CALLOC(sizeof(grn_ra));
63 if (!ra) {
64 return NULL;
65 }
66 GRN_DB_OBJ_SET_TYPE(ra, GRN_COLUMN_FIX_SIZE);
67 if (!_grn_ra_create(ctx, ra, path, element_size)) {
68 GRN_FREE(ra);
69 return NULL;
70 }
71 return ra;
72 }
73
74 grn_ra *
grn_ra_open(grn_ctx * ctx,const char * path)75 grn_ra_open(grn_ctx *ctx, const char *path)
76 {
77 grn_io *io;
78 int n_elm, w_elm;
79 grn_ra *ra = NULL;
80 struct grn_ra_header *header;
81 uint32_t io_type;
82 io = grn_io_open(ctx, path, grn_io_auto);
83 if (!io) { return NULL; }
84 header = grn_io_header(io);
85 io_type = grn_io_get_type(io);
86 if (io_type != GRN_COLUMN_FIX_SIZE) {
87 ERR(GRN_INVALID_FORMAT,
88 "[column][fix-size] file type must be %#04x: <%#04x>",
89 GRN_COLUMN_FIX_SIZE, io_type);
90 grn_io_close(ctx, io);
91 return NULL;
92 }
93 ra = GRN_MALLOCN(grn_ra, 1);
94 if (!ra) {
95 grn_io_close(ctx, io);
96 return NULL;
97 }
98 n_elm = GRN_RA_SEGMENT_SIZE / header->element_size;
99 for (w_elm = GRN_RA_W_SEGMENT; (1 << w_elm) > n_elm; w_elm--);
100 GRN_DB_OBJ_SET_TYPE(ra, GRN_COLUMN_FIX_SIZE);
101 ra->io = io;
102 ra->header = header;
103 ra->element_mask = n_elm - 1;
104 ra->element_width = w_elm;
105 return ra;
106 }
107
108 grn_rc
grn_ra_info(grn_ctx * ctx,grn_ra * ra,unsigned int * element_size)109 grn_ra_info(grn_ctx *ctx, grn_ra *ra, unsigned int *element_size)
110 {
111 if (!ra) { return GRN_INVALID_ARGUMENT; }
112 if (element_size) { *element_size = ra->header->element_size; }
113 return GRN_SUCCESS;
114 }
115
116 grn_rc
grn_ra_close(grn_ctx * ctx,grn_ra * ra)117 grn_ra_close(grn_ctx *ctx, grn_ra *ra)
118 {
119 grn_rc rc;
120 if (!ra) { return GRN_INVALID_ARGUMENT; }
121 rc = grn_io_close(ctx, ra->io);
122 GRN_FREE(ra);
123 return rc;
124 }
125
126 grn_rc
grn_ra_remove(grn_ctx * ctx,const char * path)127 grn_ra_remove(grn_ctx *ctx, const char *path)
128 {
129 if (!path) { return GRN_INVALID_ARGUMENT; }
130 return grn_io_remove(ctx, path);
131 }
132
133 grn_rc
grn_ra_truncate(grn_ctx * ctx,grn_ra * ra)134 grn_ra_truncate(grn_ctx *ctx, grn_ra *ra)
135 {
136 grn_rc rc;
137 const char *io_path;
138 char *path;
139 unsigned int element_size;
140 if ((io_path = grn_io_path(ra->io)) && *io_path != '\0') {
141 if (!(path = GRN_STRDUP(io_path))) {
142 ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path);
143 return GRN_NO_MEMORY_AVAILABLE;
144 }
145 } else {
146 path = NULL;
147 }
148 element_size = ra->header->element_size;
149 if ((rc = grn_io_close(ctx, ra->io))) { goto exit; }
150 ra->io = NULL;
151 if (path && (rc = grn_io_remove(ctx, path))) { goto exit; }
152 if (!_grn_ra_create(ctx, ra, path, element_size)) {
153 rc = GRN_UNKNOWN_ERROR;
154 }
155 exit:
156 if (path) { GRN_FREE(path); }
157 return rc;
158 }
159
160 void *
grn_ra_ref(grn_ctx * ctx,grn_ra * ra,grn_id id)161 grn_ra_ref(grn_ctx *ctx, grn_ra *ra, grn_id id)
162 {
163 void *p = NULL;
164 uint16_t seg;
165 if (id > GRN_ID_MAX) { return NULL; }
166 seg = id >> ra->element_width;
167 GRN_IO_SEG_REF(ra->io, seg, p);
168 if (!p) { return NULL; }
169 return (void *)(((byte *)p) + ((id & ra->element_mask) * ra->header->element_size));
170 }
171
172 grn_rc
grn_ra_unref(grn_ctx * ctx,grn_ra * ra,grn_id id)173 grn_ra_unref(grn_ctx *ctx, grn_ra *ra, grn_id id)
174 {
175 uint16_t seg;
176 if (id > GRN_ID_MAX) { return GRN_INVALID_ARGUMENT; }
177 seg = id >> ra->element_width;
178 GRN_IO_SEG_UNREF(ra->io, seg);
179 return GRN_SUCCESS;
180 }
181
182 void *
grn_ra_ref_cache(grn_ctx * ctx,grn_ra * ra,grn_id id,grn_ra_cache * cache)183 grn_ra_ref_cache(grn_ctx *ctx, grn_ra *ra, grn_id id, grn_ra_cache *cache)
184 {
185 void *p = NULL;
186 uint16_t seg;
187 if (id > GRN_ID_MAX) { return NULL; }
188 seg = id >> ra->element_width;
189 if (seg == cache->seg) {
190 p = cache->p;
191 } else {
192 if (cache->seg != -1) { GRN_IO_SEG_UNREF(ra->io, cache->seg); }
193 GRN_IO_SEG_REF(ra->io, seg, p);
194 cache->seg = seg;
195 cache->p = p;
196 }
197 if (!p) { return NULL; }
198 return (void *)(((byte *)p) + ((id & ra->element_mask) * ra->header->element_size));
199 }
200
201 grn_rc
grn_ra_cache_fin(grn_ctx * ctx,grn_ra * ra,grn_id id)202 grn_ra_cache_fin(grn_ctx *ctx, grn_ra *ra, grn_id id)
203 {
204 uint16_t seg;
205 if (id > GRN_ID_MAX) { return GRN_INVALID_ARGUMENT; }
206 seg = id >> ra->element_width;
207 GRN_IO_SEG_UNREF(ra->io, seg);
208 return GRN_SUCCESS;
209 }
210
211 /**** jagged arrays ****/
212
213 #define GRN_JA_W_SEGREGATE_THRESH_V1 7
214 #define GRN_JA_W_SEGREGATE_THRESH_V2 16
215 #define GRN_JA_W_CAPACITY 38
216 #define GRN_JA_W_SEGMENT 22
217
218 #define JA_ESEG_VOID (0xffffffffU)
219 #define JA_SEGMENT_SIZE (1U << GRN_JA_W_SEGMENT)
220 #define JA_W_EINFO 3
221 #define JA_W_SEGMENTS_MAX (GRN_JA_W_CAPACITY - GRN_JA_W_SEGMENT)
222 #define JA_W_EINFO_IN_A_SEGMENT (GRN_JA_W_SEGMENT - JA_W_EINFO)
223 #define JA_N_EINFO_IN_A_SEGMENT (1U << JA_W_EINFO_IN_A_SEGMENT)
224 #define JA_M_EINFO_IN_A_SEGMENT (JA_N_EINFO_IN_A_SEGMENT - 1)
225 #define JA_N_GARBAGES_IN_A_SEGMENT ((1U << (GRN_JA_W_SEGMENT - 3)) - 2)
226 #define JA_N_ELEMENT_VARIATION_V1 (GRN_JA_W_SEGREGATE_THRESH_V1 - JA_W_EINFO + 1)
227 #define JA_N_ELEMENT_VARIATION_V2 (GRN_JA_W_SEGREGATE_THRESH_V2 - JA_W_EINFO + 1)
228 #define JA_N_DSEGMENTS (1U << JA_W_SEGMENTS_MAX)
229 #define JA_N_ESEGMENTS (1U << (GRN_ID_WIDTH - JA_W_EINFO_IN_A_SEGMENT))
230
231 typedef struct _grn_ja_einfo grn_ja_einfo;
232
233 struct _grn_ja_einfo {
234 union {
235 struct {
236 uint16_t seg;
237 uint16_t pos;
238 uint16_t size;
239 uint8_t c1;
240 uint8_t c2;
241 } n;
242 struct {
243 uint32_t size;
244 uint16_t seg;
245 uint8_t c1;
246 uint8_t c2;
247 } h;
248 uint8_t c[8];
249 } u;
250 };
251
252 #define ETINY (0x80)
253 #define EHUGE (0x40)
254 #define ETINY_P(e) ((e)->u.c[7] & ETINY)
255 #define ETINY_ENC(e,_size) ((e)->u.c[7] = (_size) + ETINY)
256 #define ETINY_DEC(e,_size) ((_size) = (e)->u.c[7] & ~(ETINY|EHUGE))
257 #define EHUGE_P(e) ((e)->u.c[7] & EHUGE)
258 #define EHUGE_ENC(e,_seg,_size) do {\
259 (e)->u.h.c1 = 0;\
260 (e)->u.h.c2 = EHUGE;\
261 (e)->u.h.seg = (_seg);\
262 (e)->u.h.size = (_size);\
263 } while (0)
264 #define EHUGE_DEC(e,_seg,_size) do {\
265 (_seg) = (e)->u.h.seg;\
266 (_size) = (e)->u.h.size;\
267 } while (0)
268 #define EINFO_ENC(e,_seg,_pos,_size) do {\
269 (e)->u.n.c1 = (_pos) >> 16;\
270 (e)->u.n.c2 = ((_size) >> 16);\
271 (e)->u.n.seg = (_seg);\
272 (e)->u.n.pos = (_pos);\
273 (e)->u.n.size = (_size);\
274 } while (0)
275 #define EINFO_DEC(e,_seg,_pos,_size) do {\
276 (_seg) = (e)->u.n.seg;\
277 (_pos) = ((e)->u.n.c1 << 16) + (e)->u.n.pos;\
278 (_size) = ((e)->u.n.c2 << 16) + (e)->u.n.size;\
279 } while (0)
280
281 typedef struct {
282 uint32_t seg;
283 uint32_t pos;
284 } ja_pos;
285
286 typedef struct {
287 uint32_t head;
288 uint32_t tail;
289 uint32_t nrecs;
290 uint32_t next;
291 ja_pos recs[JA_N_GARBAGES_IN_A_SEGMENT];
292 } grn_ja_ginfo;
293
294 struct grn_ja_header_v1 {
295 uint32_t flags;
296 uint32_t curr_seg;
297 uint32_t curr_pos;
298 uint32_t max_element_size;
299 ja_pos free_elements[JA_N_ELEMENT_VARIATION_V1];
300 uint32_t garbages[JA_N_ELEMENT_VARIATION_V1];
301 uint32_t ngarbages[JA_N_ELEMENT_VARIATION_V1];
302 uint32_t dsegs[JA_N_DSEGMENTS];
303 uint32_t esegs[JA_N_ESEGMENTS];
304 };
305
306 struct grn_ja_header_v2 {
307 uint32_t flags;
308 uint32_t curr_seg;
309 uint32_t curr_pos;
310 uint32_t max_element_size;
311 ja_pos free_elements[JA_N_ELEMENT_VARIATION_V2];
312 uint32_t garbages[JA_N_ELEMENT_VARIATION_V2];
313 uint32_t ngarbages[JA_N_ELEMENT_VARIATION_V2];
314 uint32_t dsegs[JA_N_DSEGMENTS];
315 uint32_t esegs[JA_N_ESEGMENTS];
316 uint8_t segregate_threshold;
317 uint8_t n_element_variation;
318 };
319
320 struct grn_ja_header {
321 uint32_t flags;
322 uint32_t *curr_seg;
323 uint32_t *curr_pos;
324 uint32_t max_element_size;
325 ja_pos *free_elements;
326 uint32_t *garbages;
327 uint32_t *ngarbages;
328 uint32_t *dsegs;
329 uint32_t *esegs;
330 uint8_t segregate_threshold;
331 uint8_t n_element_variation;
332 };
333
334 #define SEG_SEQ (0x10000000U)
335 #define SEG_HUGE (0x20000000U)
336 #define SEG_EINFO (0x30000000U)
337 #define SEG_GINFO (0x40000000U)
338 #define SEG_MASK (0xf0000000U)
339
340 #define SEGMENTS_AT(ja,seg) ((ja)->header->dsegs[seg])
341 #define SEGMENTS_SEGRE_ON(ja,seg,width) (SEGMENTS_AT(ja,seg) = width)
342 #define SEGMENTS_SEQ_ON(ja,seg) (SEGMENTS_AT(ja,seg) = SEG_SEQ)
343 #define SEGMENTS_HUGE_ON(ja,seg) (SEGMENTS_AT(ja,seg) = SEG_HUGE)
344 #define SEGMENTS_EINFO_ON(ja,seg,lseg) (SEGMENTS_AT(ja,seg) = SEG_EINFO|(lseg))
345 #define SEGMENTS_GINFO_ON(ja,seg,width) (SEGMENTS_AT(ja,seg) = SEG_GINFO|(width))
346 #define SEGMENTS_OFF(ja,seg) (SEGMENTS_AT(ja,seg) = 0)
347
348 static grn_ja *
_grn_ja_create(grn_ctx * ctx,grn_ja * ja,const char * path,unsigned int max_element_size,uint32_t flags)349 _grn_ja_create(grn_ctx *ctx, grn_ja *ja, const char *path,
350 unsigned int max_element_size, uint32_t flags)
351 {
352 unsigned int i;
353 grn_io *io;
354 struct grn_ja_header *header;
355 struct grn_ja_header_v2 *header_v2;
356 io = grn_io_create(ctx, path, sizeof(struct grn_ja_header_v2),
357 JA_SEGMENT_SIZE, JA_N_DSEGMENTS, grn_io_auto,
358 GRN_IO_EXPIRE_SEGMENT);
359 if (!io) { return NULL; }
360 grn_io_set_type(io, GRN_COLUMN_VAR_SIZE);
361
362 header_v2 = grn_io_header(io);
363 header_v2->flags = flags;
364 header_v2->curr_seg = 0;
365 header_v2->curr_pos = JA_SEGMENT_SIZE;
366 header_v2->max_element_size = max_element_size;
367 for (i = 0; i < JA_N_ESEGMENTS; i++) { header_v2->esegs[i] = JA_ESEG_VOID; }
368 header_v2->segregate_threshold = GRN_JA_W_SEGREGATE_THRESH_V2;
369 header_v2->n_element_variation = JA_N_ELEMENT_VARIATION_V2;
370
371 header = GRN_MALLOCN(struct grn_ja_header, 1);
372 if (!header) {
373 grn_io_close(ctx, io);
374 return NULL;
375 }
376 header->flags = header_v2->flags;
377 header->curr_seg = &(header_v2->curr_seg);
378 header->curr_pos = &(header_v2->curr_pos);
379 header->max_element_size = header_v2->max_element_size;
380 header->free_elements = header_v2->free_elements;
381 header->garbages = header_v2->garbages;
382 header->ngarbages = header_v2->ngarbages;
383 header->dsegs = header_v2->dsegs;
384 header->esegs = header_v2->esegs;
385 header->segregate_threshold = header_v2->segregate_threshold;
386 header->n_element_variation = header_v2->n_element_variation;
387
388 ja->io = io;
389 ja->header = header;
390 SEGMENTS_EINFO_ON(ja, 0, 0);
391 header->esegs[0] = 0;
392 return ja;
393 }
394
395 grn_ja *
grn_ja_create(grn_ctx * ctx,const char * path,unsigned int max_element_size,uint32_t flags)396 grn_ja_create(grn_ctx *ctx, const char *path, unsigned int max_element_size, uint32_t flags)
397 {
398 grn_ja *ja = NULL;
399 ja = (grn_ja *)GRN_CALLOC(sizeof(grn_ja));
400 if (!ja) {
401 return NULL;
402 }
403 GRN_DB_OBJ_SET_TYPE(ja, GRN_COLUMN_VAR_SIZE);
404 if (!_grn_ja_create(ctx, ja, path, max_element_size, flags)) {
405 GRN_FREE(ja);
406 return NULL;
407 }
408 return ja;
409 }
410
411 grn_ja *
grn_ja_open(grn_ctx * ctx,const char * path)412 grn_ja_open(grn_ctx *ctx, const char *path)
413 {
414 grn_io *io;
415 grn_ja *ja = NULL;
416 struct grn_ja_header *header;
417 struct grn_ja_header_v2 *header_v2;
418 uint32_t io_type;
419 io = grn_io_open(ctx, path, grn_io_auto);
420 if (!io) { return NULL; }
421 header_v2 = grn_io_header(io);
422 io_type = grn_io_get_type(io);
423 if (io_type != GRN_COLUMN_VAR_SIZE) {
424 ERR(GRN_INVALID_FORMAT,
425 "[column][var-size] file type must be %#04x: <%#04x>",
426 GRN_COLUMN_VAR_SIZE, io_type);
427 grn_io_close(ctx, io);
428 return NULL;
429 }
430 if (header_v2->segregate_threshold == 0) {
431 header_v2->segregate_threshold = GRN_JA_W_SEGREGATE_THRESH_V1;
432 }
433 if (header_v2->n_element_variation == 0) {
434 header_v2->n_element_variation = JA_N_ELEMENT_VARIATION_V1;
435 }
436 ja = GRN_MALLOCN(grn_ja, 1);
437 if (!ja) {
438 grn_io_close(ctx, io);
439 return NULL;
440 }
441 GRN_DB_OBJ_SET_TYPE(ja, GRN_COLUMN_VAR_SIZE);
442 header = GRN_MALLOCN(struct grn_ja_header, 1);
443 if (!header) {
444 grn_io_close(ctx, io);
445 GRN_FREE(ja);
446 return NULL;
447 }
448
449 header->flags = header_v2->flags;
450 header->curr_seg = &(header_v2->curr_seg);
451 header->curr_pos = &(header_v2->curr_pos);
452 header->max_element_size = header_v2->max_element_size;
453 header->segregate_threshold = header_v2->segregate_threshold;
454 header->n_element_variation = header_v2->n_element_variation;
455 if (header->segregate_threshold == GRN_JA_W_SEGREGATE_THRESH_V1) {
456 struct grn_ja_header_v1 *header_v1 = (struct grn_ja_header_v1 *)header_v2;
457 header->free_elements = header_v1->free_elements;
458 header->garbages = header_v1->garbages;
459 header->ngarbages = header_v1->ngarbages;
460 header->dsegs = header_v1->dsegs;
461 header->esegs = header_v1->esegs;
462 } else {
463 header->free_elements = header_v2->free_elements;
464 header->garbages = header_v2->garbages;
465 header->ngarbages = header_v2->ngarbages;
466 header->dsegs = header_v2->dsegs;
467 header->esegs = header_v2->esegs;
468 }
469
470 ja->io = io;
471 ja->header = header;
472
473 return ja;
474 }
475
476 grn_rc
grn_ja_info(grn_ctx * ctx,grn_ja * ja,unsigned int * max_element_size)477 grn_ja_info(grn_ctx *ctx, grn_ja *ja, unsigned int *max_element_size)
478 {
479 if (!ja) { return GRN_INVALID_ARGUMENT; }
480 if (max_element_size) { *max_element_size = ja->header->max_element_size; }
481 return GRN_SUCCESS;
482 }
483
484 grn_column_flags
grn_ja_get_flags(grn_ctx * ctx,grn_ja * ja)485 grn_ja_get_flags(grn_ctx *ctx, grn_ja *ja)
486 {
487 if (!ja) {
488 return 0;
489 }
490
491 return ja->header->flags;
492 }
493
494 grn_rc
grn_ja_close(grn_ctx * ctx,grn_ja * ja)495 grn_ja_close(grn_ctx *ctx, grn_ja *ja)
496 {
497 grn_rc rc;
498 if (!ja) { return GRN_INVALID_ARGUMENT; }
499 rc = grn_io_close(ctx, ja->io);
500 GRN_FREE(ja->header);
501 GRN_FREE(ja);
502 return rc;
503 }
504
505 grn_rc
grn_ja_remove(grn_ctx * ctx,const char * path)506 grn_ja_remove(grn_ctx *ctx, const char *path)
507 {
508 if (!path) { return GRN_INVALID_ARGUMENT; }
509 return grn_io_remove(ctx, path);
510 }
511
512 grn_rc
grn_ja_truncate(grn_ctx * ctx,grn_ja * ja)513 grn_ja_truncate(grn_ctx *ctx, grn_ja *ja)
514 {
515 grn_rc rc;
516 const char *io_path;
517 char *path;
518 unsigned int max_element_size;
519 uint32_t flags;
520 if ((io_path = grn_io_path(ja->io)) && *io_path != '\0') {
521 if (!(path = GRN_STRDUP(io_path))) {
522 ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path);
523 return GRN_NO_MEMORY_AVAILABLE;
524 }
525 } else {
526 path = NULL;
527 }
528 max_element_size = ja->header->max_element_size;
529 flags = ja->header->flags;
530 if ((rc = grn_io_close(ctx, ja->io))) { goto exit; }
531 ja->io = NULL;
532 if (path && (rc = grn_io_remove(ctx, path))) { goto exit; }
533 GRN_FREE(ja->header);
534 if (!_grn_ja_create(ctx, ja, path, max_element_size, flags)) {
535 rc = GRN_UNKNOWN_ERROR;
536 }
537 exit:
538 if (path) { GRN_FREE(path); }
539 return rc;
540 }
541
542 static void *
grn_ja_ref_raw(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_io_win * iw,uint32_t * value_len)543 grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
544 {
545 uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
546 iw->size = 0;
547 iw->addr = NULL;
548 iw->pseg = pseg;
549 iw->uncompressed_value = NULL;
550 if (pseg != JA_ESEG_VOID) {
551 grn_ja_einfo *einfo = NULL;
552 GRN_IO_SEG_REF(ja->io, pseg, einfo);
553 if (einfo) {
554 grn_ja_einfo *ei = &einfo[id & JA_M_EINFO_IN_A_SEGMENT];
555 if (ETINY_P(ei)) {
556 iw->tiny_p = 1;
557 ETINY_DEC(ei, iw->size);
558 iw->io = ja->io;
559 iw->ctx = ctx;
560 iw->addr = (void *)ei;
561 } else {
562 uint32_t jag, vpos, vsize;
563 iw->tiny_p = 0;
564 if (EHUGE_P(ei)) {
565 EHUGE_DEC(ei, jag, vsize);
566 vpos = 0;
567 } else {
568 EINFO_DEC(ei, jag, vpos, vsize);
569 }
570 grn_io_win_map(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly);
571 }
572 if (!iw->addr) { GRN_IO_SEG_UNREF(ja->io, pseg); }
573 }
574 }
575 *value_len = iw->size;
576 return iw->addr;
577 }
578
579 grn_rc
grn_ja_unref(grn_ctx * ctx,grn_io_win * iw)580 grn_ja_unref(grn_ctx *ctx, grn_io_win *iw)
581 {
582 if (iw->uncompressed_value) {
583 GRN_FREE(iw->uncompressed_value);
584 iw->uncompressed_value = NULL;
585 }
586 if (!iw->addr) { return GRN_INVALID_ARGUMENT; }
587 GRN_IO_SEG_UNREF(iw->io, iw->pseg);
588 if (!iw->tiny_p) { grn_io_win_unmap(iw); }
589 return GRN_SUCCESS;
590 }
591
592 #define DELETED 0x80000000
593
594 static grn_rc
grn_ja_free(grn_ctx * ctx,grn_ja * ja,grn_ja_einfo * einfo)595 grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
596 {
597 grn_ja_ginfo *ginfo = NULL;
598 uint32_t seg, pos, element_size, aligned_size, m, *gseg;
599 if (ETINY_P(einfo)) { return GRN_SUCCESS; }
600 if (EHUGE_P(einfo)) {
601 uint32_t n;
602 EHUGE_DEC(einfo, seg, element_size);
603 n = ((element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT);
604 for (; n--; seg++) { SEGMENTS_OFF(ja, seg); }
605 return GRN_SUCCESS;
606 }
607 EINFO_DEC(einfo, seg, pos, element_size);
608 if (!element_size) { return GRN_SUCCESS; }
609 {
610 int es = element_size - 1;
611 GRN_BIT_SCAN_REV(es, m);
612 m++;
613 }
614 if (m > ja->header->segregate_threshold) {
615 byte *addr = NULL;
616 GRN_IO_SEG_REF(ja->io, seg, addr);
617 if (!addr) { return GRN_NO_MEMORY_AVAILABLE; }
618 aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
619 *(uint32_t *)(addr + pos - sizeof(grn_id)) = DELETED|aligned_size;
620 if (SEGMENTS_AT(ja, seg) < (aligned_size + sizeof(grn_id)) + SEG_SEQ) {
621 GRN_LOG(ctx, GRN_WARN, "inconsistent ja entry detected (%d > %d)",
622 element_size, SEGMENTS_AT(ja, seg) - SEG_SEQ);
623 }
624 SEGMENTS_AT(ja, seg) -= (aligned_size + sizeof(grn_id));
625 if (SEGMENTS_AT(ja, seg) == SEG_SEQ) {
626 /* reuse the segment */
627 SEGMENTS_OFF(ja, seg);
628 if (seg == *(ja->header->curr_seg)) {
629 *(ja->header->curr_pos) = JA_SEGMENT_SIZE;
630 }
631 }
632 GRN_IO_SEG_UNREF(ja->io, seg);
633 } else {
634 uint32_t lseg = 0, lseg_;
635 gseg = &ja->header->garbages[m - JA_W_EINFO];
636 while ((lseg_ = *gseg)) {
637 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
638 GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
639 if (!ginfo) {
640 return GRN_NO_MEMORY_AVAILABLE;
641 }
642 lseg = lseg_;
643 if (ginfo->nrecs < JA_N_GARBAGES_IN_A_SEGMENT) { break; }
644 gseg = &ginfo->next;
645 }
646 if (!lseg_) {
647 uint32_t i = 0;
648 while (SEGMENTS_AT(ja, i)) {
649 if (++i >= JA_N_DSEGMENTS) {
650 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
651 return GRN_NO_MEMORY_AVAILABLE;
652 }
653 }
654 SEGMENTS_GINFO_ON(ja, i, m - JA_W_EINFO);
655 *gseg = i;
656 lseg_ = *gseg;
657 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
658 GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
659 lseg = lseg_;
660 if (!ginfo) {
661 return GRN_NO_MEMORY_AVAILABLE;
662 }
663 ginfo->head = 0;
664 ginfo->tail = 0;
665 ginfo->nrecs = 0;
666 ginfo->next = 0;
667 }
668 ginfo->recs[ginfo->head].seg = seg;
669 ginfo->recs[ginfo->head].pos = pos;
670 if (++ginfo->head == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->head = 0; }
671 ginfo->nrecs++;
672 ja->header->ngarbages[m - JA_W_EINFO]++;
673 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
674 }
675 return GRN_SUCCESS;
676 }
677
678 grn_rc
grn_ja_replace(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_ja_einfo * ei,uint64_t * cas)679 grn_ja_replace(grn_ctx *ctx, grn_ja *ja, grn_id id,
680 grn_ja_einfo *ei, uint64_t *cas)
681 {
682 grn_rc rc = GRN_SUCCESS;
683 uint32_t lseg, *pseg, pos;
684 grn_ja_einfo *einfo = NULL, eback;
685 lseg = id >> JA_W_EINFO_IN_A_SEGMENT;
686 pos = id & JA_M_EINFO_IN_A_SEGMENT;
687 pseg = &ja->header->esegs[lseg];
688 if (grn_io_lock(ctx, ja->io, grn_lock_timeout)) {
689 return ctx->rc;
690 }
691 if (*pseg == JA_ESEG_VOID) {
692 unsigned int i = 0;
693 while (SEGMENTS_AT(ja, i)) {
694 if (++i >= JA_N_DSEGMENTS) {
695 ERR(GRN_NOT_ENOUGH_SPACE, "grn_ja file (%s) is full", ja->io->path);
696 rc = GRN_NOT_ENOUGH_SPACE;
697 goto exit;
698 }
699 }
700 SEGMENTS_EINFO_ON(ja, i, lseg);
701 GRN_IO_SEG_REF(ja->io, i, einfo);
702 if (einfo) {
703 *pseg = i;
704 memset(einfo, 0, JA_SEGMENT_SIZE);
705 }
706 } else {
707 GRN_IO_SEG_REF(ja->io, *pseg, einfo);
708 }
709 if (!einfo) {
710 rc = GRN_NO_MEMORY_AVAILABLE;
711 goto exit;
712 }
713 eback = einfo[pos];
714 if (cas && *cas != *((uint64_t *)&eback)) {
715 ERR(GRN_CAS_ERROR, "cas failed (%d)", id);
716 GRN_IO_SEG_UNREF(ja->io, *pseg);
717 rc = GRN_CAS_ERROR;
718 goto exit;
719 }
720 // smb_wmb();
721 {
722 uint64_t *location = (uint64_t *)(einfo + pos);
723 uint64_t value = *((uint64_t *)ei);
724 GRN_SET_64BIT(location, value);
725 }
726 GRN_IO_SEG_UNREF(ja->io, *pseg);
727 grn_ja_free(ctx, ja, &eback);
728 exit :
729 grn_io_unlock(ja->io);
730 return rc;
731 }
732
733 #define JA_N_GARBAGES_TH 10
734
735 // todo : grn_io_win_map cause verbose copy when nseg > 1, it should be copied directly.
736 static grn_rc
grn_ja_alloc(grn_ctx * ctx,grn_ja * ja,grn_id id,uint32_t element_size,grn_ja_einfo * einfo,grn_io_win * iw)737 grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id,
738 uint32_t element_size, grn_ja_einfo *einfo, grn_io_win *iw)
739 {
740 byte *addr = NULL;
741 iw->io = ja->io;
742 iw->ctx = ctx;
743 iw->cached = 1;
744 if (element_size < 8) {
745 ETINY_ENC(einfo, element_size);
746 iw->tiny_p = 1;
747 iw->addr = (void *)einfo;
748 return GRN_SUCCESS;
749 }
750 iw->tiny_p = 0;
751 if (grn_io_lock(ctx, ja->io, grn_lock_timeout)) { return ctx->rc; }
752 if (element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) {
753 uint i;
754 int j, n = (element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT;
755 for (i = 0, j = -1; i < JA_N_DSEGMENTS; i++) {
756 if (SEGMENTS_AT(ja, i)) {
757 j = i;
758 } else {
759 if (i == j + n) {
760 j++;
761 addr = grn_io_win_map(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly);
762 if (!addr) {
763 grn_io_unlock(ja->io);
764 return GRN_NO_MEMORY_AVAILABLE;
765 }
766 EHUGE_ENC(einfo, j, element_size);
767 for (; j <= i; j++) { SEGMENTS_HUGE_ON(ja, j); }
768 grn_io_unlock(ja->io);
769 return GRN_SUCCESS;
770 }
771 }
772 }
773 GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. requested element_size=%d.", element_size);
774 grn_io_unlock(ja->io);
775 return GRN_NO_MEMORY_AVAILABLE;
776 } else {
777 ja_pos *vp;
778 int m, aligned_size, es = element_size - 1;
779 GRN_BIT_SCAN_REV(es, m);
780 m++;
781 if (m > ja->header->segregate_threshold) {
782 uint32_t seg = *(ja->header->curr_seg);
783 uint32_t pos = *(ja->header->curr_pos);
784 if (pos + element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) {
785 seg = 0;
786 while (SEGMENTS_AT(ja, seg)) {
787 if (++seg >= JA_N_DSEGMENTS) {
788 grn_io_unlock(ja->io);
789 GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. seg=%d.", seg);
790 return GRN_NOT_ENOUGH_SPACE;
791 }
792 }
793 SEGMENTS_SEQ_ON(ja, seg);
794 *(ja->header->curr_seg) = seg;
795 pos = 0;
796 }
797 GRN_IO_SEG_REF(ja->io, seg, addr);
798 if (!addr) {
799 grn_io_unlock(ja->io);
800 return GRN_NO_MEMORY_AVAILABLE;
801 }
802 *(grn_id *)(addr + pos) = id;
803 aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
804 if (pos + aligned_size < JA_SEGMENT_SIZE) {
805 *(grn_id *)(addr + pos + aligned_size) = GRN_ID_NIL;
806 }
807 SEGMENTS_AT(ja, seg) += aligned_size + sizeof(grn_id);
808 pos += sizeof(grn_id);
809 EINFO_ENC(einfo, seg, pos, element_size);
810 iw->segment = seg;
811 iw->addr = addr + pos;
812 *(ja->header->curr_pos) = pos + aligned_size;
813 grn_io_unlock(ja->io);
814 return GRN_SUCCESS;
815 } else {
816 uint32_t lseg = 0, lseg_;
817 aligned_size = 1 << m;
818 if (ja->header->ngarbages[m - JA_W_EINFO] > JA_N_GARBAGES_TH) {
819 grn_ja_ginfo *ginfo = NULL;
820 uint32_t seg, pos, *gseg;
821 gseg = &ja->header->garbages[m - JA_W_EINFO];
822 while ((lseg_ = *gseg)) {
823 GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
824 if (!ginfo) {
825 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
826 grn_io_unlock(ja->io);
827 return GRN_NO_MEMORY_AVAILABLE;
828 }
829 if (ginfo->next || ginfo->nrecs > JA_N_GARBAGES_TH) {
830 seg = ginfo->recs[ginfo->tail].seg;
831 pos = ginfo->recs[ginfo->tail].pos;
832 GRN_IO_SEG_REF(ja->io, seg, addr);
833 if (!addr) {
834 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
835 GRN_IO_SEG_UNREF(ja->io, lseg_);
836 grn_io_unlock(ja->io);
837 return GRN_NO_MEMORY_AVAILABLE;
838 }
839 EINFO_ENC(einfo, seg, pos, element_size);
840 iw->segment = seg;
841 iw->addr = addr + pos;
842 if (++ginfo->tail == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->tail = 0; }
843 ginfo->nrecs--;
844 ja->header->ngarbages[m - JA_W_EINFO]--;
845 if (!ginfo->nrecs) {
846 SEGMENTS_OFF(ja, *gseg);
847 *gseg = ginfo->next;
848 }
849 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
850 GRN_IO_SEG_UNREF(ja->io, lseg_);
851 grn_io_unlock(ja->io);
852 return GRN_SUCCESS;
853 }
854 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
855 if (!ginfo->next) {
856 GRN_IO_SEG_UNREF(ja->io, lseg_);
857 break;
858 }
859 lseg = lseg_;
860 gseg = &ginfo->next;
861 }
862 }
863 vp = &ja->header->free_elements[m - JA_W_EINFO];
864 if (!vp->seg) {
865 int i = 0;
866 while (SEGMENTS_AT(ja, i)) {
867 if (++i >= JA_N_DSEGMENTS) {
868 grn_io_unlock(ja->io);
869 return GRN_NO_MEMORY_AVAILABLE;
870 }
871 }
872 SEGMENTS_SEGRE_ON(ja, i, m);
873 vp->seg = i;
874 vp->pos = 0;
875 }
876 }
877 EINFO_ENC(einfo, vp->seg, vp->pos, element_size);
878 GRN_IO_SEG_REF(ja->io, vp->seg, addr);
879 if (!addr) {
880 grn_io_unlock(ja->io);
881 return GRN_NO_MEMORY_AVAILABLE;
882 }
883 iw->segment = vp->seg;
884 iw->addr = addr + vp->pos;
885 if ((vp->pos += aligned_size) == JA_SEGMENT_SIZE) {
886 vp->seg = 0;
887 vp->pos = 0;
888 }
889 iw->uncompressed_value = NULL;
890 grn_io_unlock(ja->io);
891 return GRN_SUCCESS;
892 }
893 }
894
895 static grn_rc
set_value(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,grn_ja_einfo * einfo)896 set_value(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
897 grn_ja_einfo *einfo)
898 {
899 grn_rc rc = GRN_SUCCESS;
900 grn_io_win iw;
901 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
902 value_len >= ja->header->max_element_size) {
903 if ((rc = grn_ja_alloc(ctx, ja, id, value_len + sizeof(uint32_t), einfo, &iw))) {
904 return rc;
905 }
906 grn_memcpy(iw.addr, value, value_len);
907 memset((byte *)iw.addr + value_len, 0, sizeof(uint32_t));
908 grn_io_win_unmap(&iw);
909 } else {
910 if ((rc = grn_ja_alloc(ctx, ja, id, value_len, einfo, &iw))) { return rc; }
911 grn_memcpy(iw.addr, value, value_len);
912 grn_io_win_unmap(&iw);
913 }
914 return rc;
915 }
916
917 static grn_rc
grn_ja_put_raw(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,int flags,uint64_t * cas)918 grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id,
919 void *value, uint32_t value_len, int flags, uint64_t *cas)
920 {
921 int rc;
922 int64_t buf;
923 grn_io_win iw;
924 grn_ja_einfo einfo;
925
926 if ((flags & GRN_OBJ_SET_MASK) == GRN_OBJ_SET &&
927 value_len > 0) {
928 grn_io_win jw;
929 uint32_t old_len;
930 void *old_value;
931 grn_bool same_value = GRN_FALSE;
932
933 old_value = grn_ja_ref(ctx, ja, id, &jw, &old_len);
934 if (value_len == old_len && memcmp(value, old_value, value_len) == 0) {
935 same_value = GRN_TRUE;
936 }
937 grn_ja_unref(ctx, &jw);
938 if (same_value) {
939 return GRN_SUCCESS;
940 }
941 }
942
943 switch (flags & GRN_OBJ_SET_MASK) {
944 case GRN_OBJ_APPEND :
945 if (value_len) {
946 grn_io_win jw;
947 uint32_t old_len;
948 void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
949 if (oldvalue) {
950 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
951 old_len + value_len >= ja->header->max_element_size) {
952 if (old_len >= ja->header->max_element_size) {
953 byte *b = oldvalue;
954 uint32_t el = old_len - sizeof(uint32_t);
955 uint32_t pos = *((uint32_t *)(b + el));
956 GRN_ASSERT(pos < el);
957 if (el <= pos + value_len) {
958 uint32_t rest = el - pos;
959 grn_memcpy(b + pos, value, rest);
960 grn_memcpy(b, (byte *)value + rest, value_len - rest);
961 *((uint32_t *)(b + el)) = value_len - rest;
962 } else {
963 grn_memcpy(b + pos, value, value_len);
964 *((uint32_t *)(b + el)) = pos + value_len;
965 }
966 return GRN_SUCCESS;
967 } else {
968 if ((rc = grn_ja_alloc(ctx, ja, id,
969 value_len + old_len + sizeof(uint32_t),
970 &einfo, &iw))) {
971 grn_ja_unref(ctx, &jw);
972 return rc;
973 }
974 grn_memcpy(iw.addr, oldvalue, old_len);
975 grn_memcpy((byte *)iw.addr + old_len, value, value_len);
976 memset((byte *)iw.addr + old_len + value_len, 0, sizeof(uint32_t));
977 grn_io_win_unmap(&iw);
978 }
979 } else {
980 if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
981 grn_ja_unref(ctx, &jw);
982 return rc;
983 }
984 grn_memcpy(iw.addr, oldvalue, old_len);
985 grn_memcpy((byte *)iw.addr + old_len, value, value_len);
986 grn_io_win_unmap(&iw);
987 }
988 grn_ja_unref(ctx, &jw);
989 } else {
990 set_value(ctx, ja, id, value, value_len, &einfo);
991 }
992 }
993 break;
994 case GRN_OBJ_PREPEND :
995 if (value_len) {
996 grn_io_win jw;
997 uint32_t old_len;
998 void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
999 if (oldvalue) {
1000 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
1001 old_len + value_len >= ja->header->max_element_size) {
1002 if (old_len >= ja->header->max_element_size) {
1003 byte *b = oldvalue;
1004 uint32_t el = old_len - sizeof(uint32_t);
1005 uint32_t pos = *((uint32_t *)(b + el));
1006 GRN_ASSERT(pos < el);
1007 if (pos < value_len) {
1008 uint32_t rest = value_len - pos;
1009 grn_memcpy(b, (byte *)value + rest, pos);
1010 grn_memcpy(b + el - rest, value, rest);
1011 *((uint32_t *)(b + el)) = el - rest;
1012 } else {
1013 grn_memcpy(b + pos - value_len, value, value_len);
1014 *((uint32_t *)(b + el)) = pos - value_len;
1015 }
1016 return GRN_SUCCESS;
1017 } else {
1018 if ((rc = grn_ja_alloc(ctx, ja, id,
1019 value_len + old_len + sizeof(uint32_t),
1020 &einfo, &iw))) {
1021 grn_ja_unref(ctx, &jw);
1022 return rc;
1023 }
1024 grn_memcpy(iw.addr, value, value_len);
1025 grn_memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
1026 memset((byte *)iw.addr + value_len + old_len, 0, sizeof(uint32_t));
1027 grn_io_win_unmap(&iw);
1028 }
1029 } else {
1030 if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
1031 grn_ja_unref(ctx, &jw);
1032 return rc;
1033 }
1034 grn_memcpy(iw.addr, value, value_len);
1035 grn_memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
1036 grn_io_win_unmap(&iw);
1037 }
1038 grn_ja_unref(ctx, &jw);
1039 } else {
1040 set_value(ctx, ja, id, value, value_len, &einfo);
1041 }
1042 }
1043 break;
1044 case GRN_OBJ_DECR :
1045 if (value_len == sizeof(int64_t)) {
1046 int64_t *v = (int64_t *)&buf;
1047 *v = -(*(int64_t *)value);
1048 value = v;
1049 } else if (value_len == sizeof(int32_t)) {
1050 int32_t *v = (int32_t *)&buf;
1051 *v = -(*(int32_t *)value);
1052 value = v;
1053 } else {
1054 return GRN_INVALID_ARGUMENT;
1055 }
1056 /* fallthru */
1057 case GRN_OBJ_INCR :
1058 {
1059 grn_io_win jw;
1060 uint32_t old_len;
1061 void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
1062 if (oldvalue && old_len) {
1063 grn_rc rc = GRN_INVALID_ARGUMENT;
1064 if (old_len == sizeof(int64_t) && value_len == sizeof(int64_t)) {
1065 (*(int64_t *)oldvalue) += (*(int64_t *)value);
1066 rc = GRN_SUCCESS;
1067 } else if (old_len == sizeof(int32_t) && value_len == sizeof(int32_t)) {
1068 (*(int32_t *)oldvalue) += (*(int32_t *)value);
1069 rc = GRN_SUCCESS;
1070 }
1071 grn_ja_unref(ctx, &jw);
1072 return rc;
1073 }
1074 }
1075 /* fallthru */
1076 case GRN_OBJ_SET :
1077 if (value_len) {
1078 set_value(ctx, ja, id, value, value_len, &einfo);
1079 } else {
1080 memset(&einfo, 0, sizeof(grn_ja_einfo));
1081 }
1082 break;
1083 default :
1084 ERR(GRN_INVALID_ARGUMENT, "grn_ja_put_raw called with illegal flags value");
1085 return GRN_INVALID_ARGUMENT;
1086 }
1087 if ((rc = grn_ja_replace(ctx, ja, id, &einfo, cas))) {
1088 if (!grn_io_lock(ctx, ja->io, grn_lock_timeout)) {
1089 grn_ja_free(ctx, ja, &einfo);
1090 grn_io_unlock(ja->io);
1091 }
1092 }
1093 return rc;
1094 }
1095
1096 grn_rc
grn_ja_putv(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_obj * vector,int flags)1097 grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *vector, int flags)
1098 {
1099 grn_obj header, footer;
1100 grn_rc rc = GRN_SUCCESS;
1101 grn_section *vp;
1102 int i, f = 0, n = grn_vector_size(ctx, vector);
1103 GRN_TEXT_INIT(&header, 0);
1104 GRN_TEXT_INIT(&footer, 0);
1105 grn_text_benc(ctx, &header, n);
1106 for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) {
1107 grn_text_benc(ctx, &header, vp->length);
1108 if (vp->weight || vp->domain) { f = 1; }
1109 }
1110 if (f) {
1111 for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) {
1112 grn_text_benc(ctx, &footer, vp->weight);
1113 grn_text_benc(ctx, &footer, vp->domain);
1114 }
1115 }
1116 {
1117 grn_io_win iw;
1118 grn_ja_einfo einfo;
1119 grn_obj *body = vector->u.v.body;
1120 size_t sizeh = GRN_BULK_VSIZE(&header);
1121 size_t sizev = body ? GRN_BULK_VSIZE(body) : 0;
1122 size_t sizef = GRN_BULK_VSIZE(&footer);
1123 if ((rc = grn_ja_alloc(ctx, ja, id, sizeh + sizev + sizef, &einfo, &iw))) { goto exit; }
1124 grn_memcpy(iw.addr, GRN_BULK_HEAD(&header), sizeh);
1125 if (body) {
1126 grn_memcpy((char *)iw.addr + sizeh, GRN_BULK_HEAD(body), sizev);
1127 }
1128 if (f) {
1129 grn_memcpy((char *)iw.addr + sizeh + sizev, GRN_BULK_HEAD(&footer), sizef);
1130 }
1131 grn_io_win_unmap(&iw);
1132 rc = grn_ja_replace(ctx, ja, id, &einfo, NULL);
1133 }
1134 exit :
1135 GRN_OBJ_FIN(ctx, &footer);
1136 GRN_OBJ_FIN(ctx, &header);
1137 return rc;
1138 }
1139
1140 uint32_t
grn_ja_size(grn_ctx * ctx,grn_ja * ja,grn_id id)1141 grn_ja_size(grn_ctx *ctx, grn_ja *ja, grn_id id)
1142 {
1143 grn_ja_einfo *einfo = NULL, *ei;
1144 uint32_t lseg, *pseg, pos, size;
1145 lseg = id >> JA_W_EINFO_IN_A_SEGMENT;
1146 pos = id & JA_M_EINFO_IN_A_SEGMENT;
1147 pseg = &ja->header->esegs[lseg];
1148 if (*pseg == JA_ESEG_VOID) {
1149 ctx->rc = GRN_INVALID_ARGUMENT;
1150 return 0;
1151 }
1152 GRN_IO_SEG_REF(ja->io, *pseg, einfo);
1153 if (!einfo) {
1154 ctx->rc = GRN_NO_MEMORY_AVAILABLE;
1155 return 0;
1156 }
1157 ei = &einfo[pos];
1158 if (ETINY_P(ei)) {
1159 ETINY_DEC(ei, size);
1160 } else {
1161 if (EHUGE_P(ei)) {
1162 size = ei->u.h.size;
1163 } else {
1164 size = (ei->u.n.c2 << 16) + ei->u.n.size;
1165 }
1166 }
1167 GRN_IO_SEG_UNREF(ja->io, *pseg);
1168 return size;
1169 }
1170
1171 grn_rc
grn_ja_element_info(grn_ctx * ctx,grn_ja * ja,grn_id id,uint64_t * cas,uint32_t * pos,uint32_t * size)1172 grn_ja_element_info(grn_ctx *ctx, grn_ja *ja, grn_id id,
1173 uint64_t *cas, uint32_t *pos, uint32_t *size)
1174 {
1175 uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
1176 if (pseg == JA_ESEG_VOID) {
1177 return GRN_INVALID_ARGUMENT;
1178 } else {
1179 grn_ja_einfo *einfo = NULL;
1180 GRN_IO_SEG_REF(ja->io, pseg, einfo);
1181 if (einfo) {
1182 grn_ja_einfo *ei;
1183 *cas = *((uint64_t *)&einfo[id & JA_M_EINFO_IN_A_SEGMENT]);
1184 ei = (grn_ja_einfo *)cas;
1185 if (ETINY_P(ei)) {
1186 ETINY_DEC(ei, *size);
1187 *pos = 0;
1188 } else {
1189 uint32_t jag;
1190 if (EHUGE_P(ei)) {
1191 EHUGE_DEC(ei, jag, *size);
1192 *pos = 0;
1193 } else {
1194 EINFO_DEC(ei, jag, *pos, *size);
1195 }
1196 }
1197 GRN_IO_SEG_UNREF(ja->io, pseg);
1198 } else {
1199 return GRN_INVALID_ARGUMENT;
1200 }
1201 }
1202 return GRN_SUCCESS;
1203 }
1204
1205 #define COMPRESSED_VALUE_META_FLAG(meta) ((meta) & 0xf000000000000000)
1206 #define COMPRESSED_VALUE_META_FLAG_RAW 0x1000000000000000
1207 #define COMPRESSED_VALUE_META_UNCOMPRESSED_LEN(meta) \
1208 ((meta) & 0x0fffffffffffffff)
1209
1210 #define COMPRESS_THRESHOLD_BYTE 256
1211 #define COMPRESS_PACKED_VALUE_SIZE_MAX 257
1212 /* COMPRESS_THRESHOLD_BYTE - 1 + sizeof(uint64_t) = 257 */
1213
1214 #if defined(GRN_WITH_ZLIB) || defined(GRN_WITH_LZ4) || defined(GRN_WITH_ZSTD)
1215 # define GRN_WITH_COMPRESSED
1216 #endif
1217
1218 #ifdef GRN_WITH_COMPRESSED
1219 static void *
grn_ja_ref_packed(grn_ctx * ctx,grn_io_win * iw,uint32_t * value_len,void * raw_value,uint32_t raw_value_len,void ** compressed_value,uint32_t * compressed_value_len,uint32_t * uncompressed_value_len)1220 grn_ja_ref_packed(grn_ctx *ctx,
1221 grn_io_win *iw,
1222 uint32_t *value_len,
1223 void *raw_value,
1224 uint32_t raw_value_len,
1225 void **compressed_value,
1226 uint32_t *compressed_value_len,
1227 uint32_t *uncompressed_value_len)
1228 {
1229 uint64_t compressed_value_meta;
1230
1231 compressed_value_meta = *((uint64_t *)raw_value);
1232 *compressed_value = (void *)(((uint64_t *)raw_value) + 1);
1233 *compressed_value_len = raw_value_len - sizeof(uint64_t);
1234
1235 *uncompressed_value_len =
1236 COMPRESSED_VALUE_META_UNCOMPRESSED_LEN(compressed_value_meta);
1237 switch (COMPRESSED_VALUE_META_FLAG(compressed_value_meta)) {
1238 case COMPRESSED_VALUE_META_FLAG_RAW :
1239 iw->uncompressed_value = NULL;
1240 *value_len = *uncompressed_value_len;
1241 return *compressed_value;
1242 default :
1243 return NULL;
1244 }
1245 }
1246
1247 static grn_rc
grn_ja_put_packed(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,int flags,uint64_t * cas)1248 grn_ja_put_packed(grn_ctx *ctx,
1249 grn_ja *ja,
1250 grn_id id,
1251 void *value,
1252 uint32_t value_len,
1253 int flags,
1254 uint64_t *cas)
1255 {
1256 char *packed_value[COMPRESS_PACKED_VALUE_SIZE_MAX];
1257 uint32_t packed_value_len;
1258 uint64_t packed_value_meta;
1259
1260 packed_value_len = value_len + sizeof(uint64_t);
1261 packed_value_meta = value_len | COMPRESSED_VALUE_META_FLAG_RAW;
1262 *((uint64_t *)packed_value) = packed_value_meta;
1263 memcpy(((uint64_t *)packed_value) + 1,
1264 value,
1265 value_len);
1266 return grn_ja_put_raw(ctx,
1267 ja,
1268 id,
1269 packed_value,
1270 packed_value_len,
1271 flags,
1272 cas);
1273 }
1274
1275 static void
grn_ja_compress_error(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_rc rc,const char * message,const char * detail)1276 grn_ja_compress_error(grn_ctx *ctx,
1277 grn_ja *ja,
1278 grn_id id,
1279 grn_rc rc,
1280 const char *message,
1281 const char *detail)
1282 {
1283 char name[GRN_TABLE_MAX_KEY_SIZE];
1284 int name_len;
1285
1286 if (ja->obj.id == GRN_ID_NIL) {
1287 name[0] = '\0';
1288 name_len = 0;
1289 } else {
1290 name_len = grn_obj_name(ctx, (grn_obj *)ja, name, GRN_TABLE_MAX_KEY_SIZE);
1291 }
1292 ERR(GRN_ZSTD_ERROR,
1293 "[ja]%s: %s%.*s%s<%u>%s%s%s",
1294 message,
1295 name_len == 0 ? "" : "<",
1296 name_len,
1297 name,
1298 name_len == 0 ? "" : ">: ",
1299 id,
1300 detail ? " :<" : "",
1301 detail ? detail : "",
1302 detail ? ">" : "");
1303 }
1304 #endif /* GRN_WITH_COMPRESSED */
1305
1306 #ifdef GRN_WITH_ZLIB
1307 #include <zlib.h>
1308
1309 static const char *
grn_zrc_to_string(int zrc)1310 grn_zrc_to_string(int zrc)
1311 {
1312 switch (zrc) {
1313 case Z_OK :
1314 return "OK";
1315 case Z_STREAM_END :
1316 return "Stream is end";
1317 case Z_NEED_DICT :
1318 return "Need dictionary";
1319 case Z_ERRNO :
1320 return "See errno";
1321 case Z_STREAM_ERROR :
1322 return "Stream error";
1323 case Z_DATA_ERROR :
1324 return "Data error";
1325 case Z_MEM_ERROR :
1326 return "Memory error";
1327 case Z_BUF_ERROR :
1328 return "Buffer error";
1329 case Z_VERSION_ERROR :
1330 return "Version error";
1331 default :
1332 return "Unknown";
1333 }
1334 }
1335
1336 static void *
grn_ja_ref_zlib(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_io_win * iw,uint32_t * value_len)1337 grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1338 {
1339 z_stream zstream;
1340 void *raw_value;
1341 uint32_t raw_value_len;
1342 void *zvalue;
1343 uint32_t zvalue_len;
1344 void *unpacked_value;
1345 uint32_t uncompressed_value_len;
1346 int zrc;
1347
1348 if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) {
1349 iw->uncompressed_value = NULL;
1350 *value_len = 0;
1351 return NULL;
1352 }
1353
1354 unpacked_value = grn_ja_ref_packed(ctx,
1355 iw, value_len,
1356 raw_value, raw_value_len,
1357 &zvalue, &zvalue_len,
1358 &uncompressed_value_len);
1359 if (unpacked_value) {
1360 return unpacked_value;
1361 }
1362
1363 zstream.next_in = (Bytef *)zvalue;
1364 zstream.avail_in = zvalue_len;
1365 zstream.zalloc = Z_NULL;
1366 zstream.zfree = Z_NULL;
1367 zrc = inflateInit2(&zstream, 15 /* windowBits */);
1368 if (zrc != Z_OK) {
1369 iw->uncompressed_value = NULL;
1370 *value_len = 0;
1371 grn_ja_compress_error(ctx,
1372 ja,
1373 id,
1374 GRN_ZLIB_ERROR,
1375 "[zlib] failed to decompress: initialize",
1376 grn_zrc_to_string(zrc));
1377 return NULL;
1378 }
1379 if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) {
1380 inflateEnd(&zstream);
1381 iw->uncompressed_value = NULL;
1382 *value_len = 0;
1383 grn_ja_compress_error(ctx,
1384 ja,
1385 id,
1386 GRN_ZLIB_ERROR,
1387 "[zlib] failed to decompress: allocate buffer",
1388 NULL);
1389 return NULL;
1390 }
1391 zstream.next_out = (Bytef *)iw->uncompressed_value;
1392 zstream.avail_out = uncompressed_value_len;
1393 zrc = inflate(&zstream, Z_FINISH);
1394 if (zrc != Z_STREAM_END) {
1395 inflateEnd(&zstream);
1396 GRN_FREE(iw->uncompressed_value);
1397 iw->uncompressed_value = NULL;
1398 *value_len = 0;
1399 grn_ja_compress_error(ctx,
1400 ja,
1401 id,
1402 GRN_ZLIB_ERROR,
1403 "[zlib] failed to decompress: finish",
1404 grn_zrc_to_string(zrc));
1405 return NULL;
1406 }
1407 *value_len = zstream.total_out;
1408 zrc = inflateEnd(&zstream);
1409 if (zrc != Z_OK) {
1410 GRN_FREE(iw->uncompressed_value);
1411 iw->uncompressed_value = NULL;
1412 *value_len = 0;
1413 grn_ja_compress_error(ctx,
1414 ja,
1415 id,
1416 GRN_ZLIB_ERROR,
1417 "[zlib] failed to decompress: end",
1418 grn_zrc_to_string(zrc));
1419 return NULL;
1420 }
1421 return iw->uncompressed_value;
1422 }
1423 #endif /* GRN_WITH_ZLIB */
1424
1425 #ifdef GRN_WITH_LZ4
1426 #include <lz4.h>
1427
1428 # if (LZ4_VERSION_MAJOR == 1 && LZ4_VERSION_MINOR < 6)
1429 # define LZ4_compress_default(source, dest, source_size, max_dest_size) \
1430 LZ4_compress((source), (dest), (source_size))
1431 # endif
1432
1433 static void *
grn_ja_ref_lz4(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_io_win * iw,uint32_t * value_len)1434 grn_ja_ref_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1435 {
1436 void *raw_value;
1437 uint32_t raw_value_len;
1438 void *lz4_value;
1439 uint32_t lz4_value_len;
1440 void *unpacked_value;
1441 uint32_t uncompressed_value_len;
1442
1443 if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) {
1444 iw->uncompressed_value = NULL;
1445 *value_len = 0;
1446 return NULL;
1447 }
1448
1449 unpacked_value = grn_ja_ref_packed(ctx,
1450 iw, value_len,
1451 raw_value, raw_value_len,
1452 &lz4_value, &lz4_value_len,
1453 &uncompressed_value_len);
1454 if (unpacked_value) {
1455 return unpacked_value;
1456 }
1457
1458 if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) {
1459 iw->uncompressed_value = NULL;
1460 *value_len = 0;
1461 return NULL;
1462 }
1463 if (LZ4_decompress_safe((const char *)(lz4_value),
1464 (char *)(iw->uncompressed_value),
1465 lz4_value_len,
1466 uncompressed_value_len) < 0) {
1467 GRN_FREE(iw->uncompressed_value);
1468 iw->uncompressed_value = NULL;
1469 *value_len = 0;
1470 grn_ja_compress_error(ctx,
1471 ja,
1472 id,
1473 GRN_LZ4_ERROR,
1474 "[lz4] failed to decompress",
1475 NULL);
1476 return NULL;
1477 }
1478 *value_len = uncompressed_value_len;
1479 return iw->uncompressed_value;
1480 }
1481 #endif /* GRN_WITH_LZ4 */
1482
1483 #ifdef GRN_WITH_ZSTD
1484 #include <zstd.h>
1485
1486 static void *
grn_ja_ref_zstd(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_io_win * iw,uint32_t * value_len)1487 grn_ja_ref_zstd(grn_ctx *ctx,
1488 grn_ja *ja,
1489 grn_id id,
1490 grn_io_win *iw,
1491 uint32_t *value_len)
1492 {
1493 void *raw_value;
1494 uint32_t raw_value_len;
1495 void *zstd_value;
1496 uint32_t zstd_value_len;
1497 void *unpacked_value;
1498 uint32_t uncompressed_value_len;
1499 size_t written_len;
1500
1501 if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) {
1502 iw->uncompressed_value = NULL;
1503 *value_len = 0;
1504 return NULL;
1505 }
1506
1507 unpacked_value = grn_ja_ref_packed(ctx,
1508 iw, value_len,
1509 raw_value, raw_value_len,
1510 &zstd_value, &zstd_value_len,
1511 &uncompressed_value_len);
1512 if (unpacked_value) {
1513 return unpacked_value;
1514 }
1515
1516 if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) {
1517 iw->uncompressed_value = NULL;
1518 *value_len = 0;
1519 return NULL;
1520 }
1521
1522 written_len = ZSTD_decompress((char *)(iw->uncompressed_value),
1523 uncompressed_value_len,
1524 zstd_value,
1525 zstd_value_len);
1526 if (ZSTD_isError(written_len)) {
1527 GRN_FREE(iw->uncompressed_value);
1528 iw->uncompressed_value = NULL;
1529 *value_len = 0;
1530 grn_ja_compress_error(ctx,
1531 ja,
1532 id,
1533 GRN_ZSTD_ERROR,
1534 "[zstd] failed to decompress",
1535 ZSTD_getErrorName(written_len));
1536 return NULL;
1537 }
1538 *value_len = uncompressed_value_len;
1539 return iw->uncompressed_value;
1540 }
1541 #endif /* GRN_WITH_ZSTD */
1542
1543 void *
grn_ja_ref(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_io_win * iw,uint32_t * value_len)1544 grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1545 {
1546 switch (ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
1547 #ifdef GRN_WITH_ZLIB
1548 case GRN_OBJ_COMPRESS_ZLIB :
1549 return grn_ja_ref_zlib(ctx, ja, id, iw, value_len);
1550 #endif /* GRN_WITH_ZLIB */
1551 #ifdef GRN_WITH_LZ4
1552 case GRN_OBJ_COMPRESS_LZ4 :
1553 return grn_ja_ref_lz4(ctx, ja, id, iw, value_len);
1554 #endif /* GRN_WITH_LZ4 */
1555 #ifdef GRN_WITH_ZSTD
1556 case GRN_OBJ_COMPRESS_ZSTD :
1557 return grn_ja_ref_zstd(ctx, ja, id, iw, value_len);
1558 #endif /* GRN_WITH_ZSTD */
1559 default :
1560 return grn_ja_ref_raw(ctx, ja, id, iw, value_len);
1561 }
1562 }
1563
1564 grn_obj *
grn_ja_get_value(grn_ctx * ctx,grn_ja * ja,grn_id id,grn_obj * value)1565 grn_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *value)
1566 {
1567 void *v;
1568 uint32_t len;
1569 grn_io_win iw;
1570 if (!value) {
1571 if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) {
1572 ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed");
1573 goto exit;
1574 }
1575 }
1576 if ((v = grn_ja_ref(ctx, ja, id, &iw, &len))) {
1577 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
1578 len > ja->header->max_element_size) {
1579 byte *b = v;
1580 uint32_t el = len - sizeof(uint32_t);
1581 uint32_t pos = *((uint32_t *)(b + el));
1582 GRN_ASSERT(pos < el);
1583 grn_bulk_write(ctx, value, (char *)(b + pos), el - pos);
1584 grn_bulk_write(ctx, value, (char *)(b), pos);
1585 } else {
1586 grn_bulk_write(ctx, value, v, len);
1587 }
1588 grn_ja_unref(ctx, &iw);
1589 }
1590 exit :
1591 return value;
1592 }
1593
1594 #ifdef GRN_WITH_ZLIB
1595 inline static grn_rc
grn_ja_put_zlib(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,int flags,uint64_t * cas)1596 grn_ja_put_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id,
1597 void *value, uint32_t value_len, int flags, uint64_t *cas)
1598 {
1599 grn_rc rc;
1600 z_stream zstream;
1601 void *zvalue;
1602 int zvalue_len;
1603 int zrc;
1604
1605 if (value_len == 0) {
1606 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1607 }
1608
1609 if (value_len < COMPRESS_THRESHOLD_BYTE) {
1610 return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas);
1611 }
1612
1613 zstream.next_in = value;
1614 zstream.avail_in = value_len;
1615 zstream.zalloc = Z_NULL;
1616 zstream.zfree = Z_NULL;
1617 zrc = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
1618 15 /* windowBits */,
1619 8 /* memLevel */,
1620 Z_DEFAULT_STRATEGY);
1621 if (zrc != Z_OK) {
1622 grn_ja_compress_error(ctx,
1623 ja,
1624 id,
1625 GRN_ZLIB_ERROR,
1626 "[zlib] failed to compress: initialize",
1627 grn_zrc_to_string(zrc));
1628 return ctx->rc;
1629 }
1630 zvalue_len = deflateBound(&zstream, value_len);
1631 if (!(zvalue = GRN_MALLOC(zvalue_len + sizeof(uint64_t)))) {
1632 deflateEnd(&zstream);
1633 grn_ja_compress_error(ctx,
1634 ja,
1635 id,
1636 GRN_ZLIB_ERROR,
1637 "[zlib] failed to allocate compress buffer",
1638 NULL);
1639 return ctx->rc;
1640 }
1641 zstream.next_out = (Bytef *)(((uint64_t *)zvalue) + 1);
1642 zstream.avail_out = zvalue_len;
1643 zrc = deflate(&zstream, Z_FINISH);
1644 if (zrc != Z_STREAM_END) {
1645 deflateEnd(&zstream);
1646 GRN_FREE(zvalue);
1647 grn_ja_compress_error(ctx,
1648 ja,
1649 id,
1650 GRN_ZLIB_ERROR,
1651 "[zlib] failed to compress: finish",
1652 grn_zrc_to_string(zrc));
1653 return ctx->rc;
1654 }
1655 zvalue_len = zstream.total_out;
1656 zrc = deflateEnd(&zstream);
1657 if (zrc != Z_OK) {
1658 GRN_FREE(zvalue);
1659 grn_ja_compress_error(ctx,
1660 ja,
1661 id,
1662 GRN_ZLIB_ERROR,
1663 "[zlib] failed to compress: end",
1664 grn_zrc_to_string(zrc));
1665 return ctx->rc;
1666 }
1667 *(uint64_t *)zvalue = value_len;
1668 rc = grn_ja_put_raw(ctx, ja, id, zvalue, zvalue_len + sizeof(uint64_t), flags, cas);
1669 GRN_FREE(zvalue);
1670 return rc;
1671 }
1672 #endif /* GRN_WITH_ZLIB */
1673
1674 #ifdef GRN_WITH_LZ4
1675 inline static grn_rc
grn_ja_put_lz4(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,int flags,uint64_t * cas)1676 grn_ja_put_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id,
1677 void *value, uint32_t value_len, int flags, uint64_t *cas)
1678 {
1679 grn_rc rc;
1680 void *packed_value;
1681 int packed_value_len_max;
1682 int packed_value_len_real;
1683 char *lz4_value;
1684 int lz4_value_len_max;
1685 int lz4_value_len_real;
1686
1687 if (value_len == 0) {
1688 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1689 }
1690
1691 if (value_len < COMPRESS_THRESHOLD_BYTE) {
1692 return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas);
1693 }
1694
1695 if (value_len > (uint32_t)LZ4_MAX_INPUT_SIZE) {
1696 uint64_t packed_value_meta;
1697
1698 packed_value_len_real = value_len + sizeof(uint64_t);
1699 packed_value = GRN_MALLOC(packed_value_len_real);
1700 if (!packed_value) {
1701 grn_ja_compress_error(ctx,
1702 ja,
1703 id,
1704 GRN_LZ4_ERROR,
1705 "[lz4] failed to allocate packed buffer",
1706 NULL);
1707 return ctx->rc;
1708 }
1709 packed_value_meta = value_len | COMPRESSED_VALUE_META_FLAG_RAW;
1710 *((uint64_t *)packed_value) = packed_value_meta;
1711 memcpy(((uint64_t *)packed_value) + 1,
1712 value,
1713 value_len);
1714 rc = grn_ja_put_raw(ctx,
1715 ja,
1716 id,
1717 packed_value,
1718 packed_value_len_real,
1719 flags,
1720 cas);
1721 GRN_FREE(packed_value);
1722 return rc;
1723 }
1724
1725 lz4_value_len_max = LZ4_compressBound(value_len);
1726 packed_value_len_max = lz4_value_len_max + sizeof(uint64_t);
1727 if (!(packed_value = GRN_MALLOC(packed_value_len_max))) {
1728 grn_ja_compress_error(ctx,
1729 ja,
1730 id,
1731 GRN_LZ4_ERROR,
1732 "[lz4] failed to allocate compress buffer",
1733 NULL);
1734 return ctx->rc;
1735 }
1736 lz4_value = (char *)((uint64_t *)packed_value + 1);
1737 lz4_value_len_real = LZ4_compress_default((const char *)value,
1738 lz4_value,
1739 value_len,
1740 lz4_value_len_max);
1741 if (lz4_value_len_real <= 0) {
1742 GRN_FREE(packed_value);
1743 grn_ja_compress_error(ctx,
1744 ja,
1745 id,
1746 GRN_LZ4_ERROR,
1747 "[lz4] failed to compress",
1748 NULL);
1749 return ctx->rc;
1750 }
1751 *(uint64_t *)packed_value = value_len;
1752 packed_value_len_real = lz4_value_len_real + sizeof(uint64_t);
1753 rc = grn_ja_put_raw(ctx,
1754 ja,
1755 id,
1756 packed_value,
1757 packed_value_len_real,
1758 flags,
1759 cas);
1760 GRN_FREE(packed_value);
1761 return rc;
1762 }
1763 #endif /* GRN_WITH_LZ4 */
1764
1765 #ifdef GRN_WITH_ZSTD
1766 inline static grn_rc
grn_ja_put_zstd(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,int flags,uint64_t * cas)1767 grn_ja_put_zstd(grn_ctx *ctx,
1768 grn_ja *ja,
1769 grn_id id,
1770 void *value,
1771 uint32_t value_len,
1772 int flags,
1773 uint64_t *cas)
1774 {
1775 grn_rc rc;
1776 void *packed_value;
1777 int packed_value_len_max;
1778 int packed_value_len_real;
1779 void *zstd_value;
1780 int zstd_value_len_max;
1781 int zstd_value_len_real;
1782 int zstd_compression_level = 3;
1783
1784 if (value_len == 0) {
1785 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1786 }
1787
1788 if (value_len < COMPRESS_THRESHOLD_BYTE) {
1789 return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas);
1790 }
1791
1792 zstd_value_len_max = ZSTD_compressBound(value_len);
1793 packed_value_len_max = zstd_value_len_max + sizeof(uint64_t);
1794 if (!(packed_value = GRN_MALLOC(packed_value_len_max))) {
1795 grn_ja_compress_error(ctx,
1796 ja,
1797 id,
1798 GRN_ZSTD_ERROR,
1799 "[zstd] failed to allocate compress buffer",
1800 NULL);
1801 return ctx->rc;
1802 }
1803 zstd_value = ((uint64_t *)packed_value) + 1;
1804 zstd_value_len_real = ZSTD_compress(zstd_value, zstd_value_len_max,
1805 value, value_len,
1806 zstd_compression_level);
1807 if (ZSTD_isError(zstd_value_len_real)) {
1808 grn_ja_compress_error(ctx,
1809 ja,
1810 id,
1811 GRN_ZSTD_ERROR,
1812 "[zstd] failed to compress",
1813 ZSTD_getErrorName(zstd_value_len_real));
1814 return ctx->rc;
1815 }
1816 *(uint64_t *)packed_value = value_len;
1817 packed_value_len_real = zstd_value_len_real + sizeof(uint64_t);
1818 rc = grn_ja_put_raw(ctx,
1819 ja,
1820 id,
1821 packed_value,
1822 packed_value_len_real,
1823 flags,
1824 cas);
1825 GRN_FREE(packed_value);
1826 return rc;
1827 }
1828 #endif /* GRN_WITH_ZSTD */
1829
1830 grn_rc
grn_ja_put(grn_ctx * ctx,grn_ja * ja,grn_id id,void * value,uint32_t value_len,int flags,uint64_t * cas)1831 grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
1832 int flags, uint64_t *cas)
1833 {
1834 switch (ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
1835 #ifdef GRN_WITH_ZLIB
1836 case GRN_OBJ_COMPRESS_ZLIB :
1837 return grn_ja_put_zlib(ctx, ja, id, value, value_len, flags, cas);
1838 #endif /* GRN_WITH_ZLIB */
1839 #ifdef GRN_WITH_LZ4
1840 case GRN_OBJ_COMPRESS_LZ4 :
1841 return grn_ja_put_lz4(ctx, ja, id, value, value_len, flags, cas);
1842 #endif /* GRN_WITH_LZ4 */
1843 #ifdef GRN_WITH_ZSTD
1844 case GRN_OBJ_COMPRESS_ZSTD :
1845 return grn_ja_put_zstd(ctx, ja, id, value, value_len, flags, cas);
1846 #endif /* GRN_WITH_ZSTD */
1847 default :
1848 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1849 }
1850 }
1851
1852 static grn_rc
grn_ja_defrag_seg(grn_ctx * ctx,grn_ja * ja,uint32_t seg)1853 grn_ja_defrag_seg(grn_ctx *ctx, grn_ja *ja, uint32_t seg)
1854 {
1855 byte *v = NULL, *ve;
1856 uint32_t element_size, cum = 0, *seginfo = &SEGMENTS_AT(ja,seg), sum;
1857 sum = (*seginfo & ~SEG_MASK);
1858 GRN_IO_SEG_REF(ja->io, seg, v);
1859 if (!v) { return GRN_NO_MEMORY_AVAILABLE; }
1860 ve = v + JA_SEGMENT_SIZE;
1861 while (v < ve && cum < sum) {
1862 grn_id id = *((grn_id *)v);
1863 if (!id) { break; }
1864 if (id & DELETED) {
1865 element_size = (id & ~DELETED);
1866 } else {
1867 uint64_t cas;
1868 uint32_t pos;
1869 if (grn_ja_element_info(ctx, ja, id, &cas, &pos, &element_size)) { break; }
1870 if (v + sizeof(uint32_t) != ve - JA_SEGMENT_SIZE + pos) {
1871 GRN_LOG(ctx, GRN_LOG_WARNING,
1872 "dseges[%d] = pos unmatch (%d != %" GRN_FMT_LLD ")",
1873 seg, pos, (long long int)(v + sizeof(uint32_t) + JA_SEGMENT_SIZE - ve));
1874 break;
1875 }
1876 if (grn_ja_put(ctx, ja, id, v + sizeof(uint32_t), element_size, GRN_OBJ_SET, &cas)) {
1877 GRN_LOG(ctx, GRN_LOG_WARNING,
1878 "dseges[%d] = put failed (%d)", seg, id);
1879 break;
1880 }
1881 element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
1882 cum += sizeof(uint32_t) + element_size;
1883 }
1884 v += sizeof(uint32_t) + element_size;
1885 }
1886 if (*seginfo) {
1887 GRN_LOG(ctx, GRN_LOG_WARNING, "dseges[%d] = %d after defrag", seg, (*seginfo & ~SEG_MASK));
1888 }
1889 GRN_IO_SEG_UNREF(ja->io, seg);
1890 return GRN_SUCCESS;
1891 }
1892
1893 int
grn_ja_defrag(grn_ctx * ctx,grn_ja * ja,int threshold)1894 grn_ja_defrag(grn_ctx *ctx, grn_ja *ja, int threshold)
1895 {
1896 int nsegs = 0;
1897 uint32_t seg, ts = 1U << (GRN_JA_W_SEGMENT - threshold);
1898 for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
1899 if (seg == *(ja->header->curr_seg)) { continue; }
1900 if (((SEGMENTS_AT(ja, seg) & SEG_MASK) == SEG_SEQ) &&
1901 ((SEGMENTS_AT(ja, seg) & ~SEG_MASK) < ts)) {
1902 if (!grn_ja_defrag_seg(ctx, ja, seg)) { nsegs++; }
1903 }
1904 }
1905 return nsegs;
1906 }
1907
1908 void
grn_ja_check(grn_ctx * ctx,grn_ja * ja)1909 grn_ja_check(grn_ctx *ctx, grn_ja *ja)
1910 {
1911 char buf[8];
1912 uint32_t seg;
1913 struct grn_ja_header *h = ja->header;
1914 GRN_OUTPUT_ARRAY_OPEN("RESULT", 8);
1915 GRN_OUTPUT_MAP_OPEN("SUMMARY", 8);
1916 GRN_OUTPUT_CSTR("flags");
1917 grn_itoh(h->flags, buf, 8);
1918 GRN_OUTPUT_STR(buf, 8);
1919 GRN_OUTPUT_CSTR("curr seg");
1920 GRN_OUTPUT_INT64(*(h->curr_seg));
1921 GRN_OUTPUT_CSTR("curr pos");
1922 GRN_OUTPUT_INT64(*(h->curr_pos));
1923 GRN_OUTPUT_CSTR("max_element_size");
1924 GRN_OUTPUT_INT64(h->max_element_size);
1925 GRN_OUTPUT_CSTR("segregate_threshold");
1926 GRN_OUTPUT_INT64(h->segregate_threshold);
1927 GRN_OUTPUT_CSTR("n_element_variation");
1928 GRN_OUTPUT_INT64(h->n_element_variation);
1929 GRN_OUTPUT_MAP_CLOSE();
1930 GRN_OUTPUT_ARRAY_OPEN("DETAIL", -1);
1931 for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
1932 int dseg = SEGMENTS_AT(ja, seg);
1933 if (dseg) {
1934 GRN_OUTPUT_MAP_OPEN("SEG", -1);
1935 GRN_OUTPUT_CSTR("seg id");
1936 GRN_OUTPUT_INT64(seg);
1937 GRN_OUTPUT_CSTR("seg type");
1938 GRN_OUTPUT_INT64((dseg & SEG_MASK)>>28);
1939 GRN_OUTPUT_CSTR("seg value");
1940 GRN_OUTPUT_INT64(dseg & ~SEG_MASK);
1941 if ((dseg & SEG_MASK) == SEG_SEQ) {
1942 byte *v = NULL, *ve;
1943 uint32_t element_size, cum = 0, sum = dseg & ~SEG_MASK;
1944 uint32_t n_del_elements = 0, n_elements = 0, s_del_elements = 0, s_elements = 0;
1945 GRN_IO_SEG_REF(ja->io, seg, v);
1946 if (v) {
1947 /*
1948 GRN_OUTPUT_CSTR("seg seq");
1949 GRN_OUTPUT_ARRAY_OPEN("SEQ", -1);
1950 */
1951 ve = v + JA_SEGMENT_SIZE;
1952 while (v < ve && cum < sum) {
1953 grn_id id = *((grn_id *)v);
1954 /*
1955 GRN_OUTPUT_MAP_OPEN("ENTRY", -1);
1956 GRN_OUTPUT_CSTR("id");
1957 GRN_OUTPUT_INT64(id);
1958 */
1959 if (!id) { break; }
1960 if (id & DELETED) {
1961 element_size = (id & ~DELETED);
1962 n_del_elements++;
1963 s_del_elements += element_size;
1964 } else {
1965 element_size = grn_ja_size(ctx, ja, id);
1966 element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
1967 cum += sizeof(uint32_t) + element_size;
1968 n_elements++;
1969 s_elements += sizeof(uint32_t) + element_size;
1970 }
1971 v += sizeof(uint32_t) + element_size;
1972 /*
1973 GRN_OUTPUT_CSTR("size");
1974 GRN_OUTPUT_INT64(element_size);
1975 GRN_OUTPUT_CSTR("cum");
1976 GRN_OUTPUT_INT64(cum);
1977 GRN_OUTPUT_MAP_CLOSE();
1978 */
1979 }
1980 GRN_IO_SEG_UNREF(ja->io, seg);
1981 /*
1982 GRN_OUTPUT_ARRAY_CLOSE();
1983 */
1984 GRN_OUTPUT_CSTR("n_elements");
1985 GRN_OUTPUT_INT64(n_elements);
1986 GRN_OUTPUT_CSTR("s_elements");
1987 GRN_OUTPUT_INT64(s_elements);
1988 GRN_OUTPUT_CSTR("n_del_elements");
1989 GRN_OUTPUT_INT64(n_del_elements);
1990 GRN_OUTPUT_CSTR("s_del_elements");
1991 GRN_OUTPUT_INT64(s_del_elements);
1992 if (cum != sum) {
1993 GRN_OUTPUT_CSTR("cum gap");
1994 GRN_OUTPUT_INT64(cum - sum);
1995 }
1996 }
1997 }
1998 GRN_OUTPUT_MAP_CLOSE();
1999 }
2000 }
2001 GRN_OUTPUT_ARRAY_CLOSE();
2002 GRN_OUTPUT_ARRAY_CLOSE();
2003 }
2004
2005 /* grn_ja_reader */
2006
2007 grn_rc
grn_ja_reader_init(grn_ctx * ctx,grn_ja_reader * reader,grn_ja * ja)2008 grn_ja_reader_init(grn_ctx *ctx, grn_ja_reader *reader, grn_ja *ja)
2009 {
2010 reader->ja = ja;
2011 reader->einfo_seg_id = JA_ESEG_VOID;
2012 reader->ref_avail = GRN_FALSE;
2013 reader->ref_seg_id = JA_ESEG_VOID;
2014 reader->ref_seg_ids = NULL;
2015 reader->nref_seg_ids = 0;
2016 reader->ref_seg_ids_size = 0;
2017 reader->body_seg_id = JA_ESEG_VOID;
2018 reader->body_seg_addr = NULL;
2019 reader->packed_buf = NULL;
2020 reader->packed_buf_size = 0;
2021 #ifdef GRN_WITH_ZLIB
2022 if (reader->ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) {
2023 z_stream *new_stream = GRN_MALLOCN(z_stream, 1);
2024 if (!new_stream) {
2025 return GRN_NO_MEMORY_AVAILABLE;
2026 }
2027 new_stream->zalloc = NULL;
2028 new_stream->zfree = NULL;
2029 new_stream->opaque = NULL;
2030 if (inflateInit2(new_stream, 15) != Z_OK) {
2031 GRN_FREE(new_stream);
2032 return GRN_ZLIB_ERROR;
2033 }
2034 reader->stream = new_stream;
2035 }
2036 #endif /* GRN_WITH_ZLIB */
2037 return GRN_SUCCESS;
2038 }
2039
2040 grn_rc
grn_ja_reader_fin(grn_ctx * ctx,grn_ja_reader * reader)2041 grn_ja_reader_fin(grn_ctx *ctx, grn_ja_reader *reader)
2042 {
2043 grn_rc rc = GRN_SUCCESS;
2044 if (reader->einfo_seg_id != JA_ESEG_VOID) {
2045 GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
2046 }
2047 if (reader->ref_seg_ids) {
2048 grn_ja_reader_unref(ctx, reader);
2049 GRN_FREE(reader->ref_seg_ids);
2050 }
2051 if (reader->body_seg_addr) {
2052 GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
2053 }
2054 if (reader->packed_buf) {
2055 GRN_FREE(reader->packed_buf);
2056 }
2057 #ifdef GRN_WITH_ZLIB
2058 if (reader->ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) {
2059 if (reader->stream) {
2060 if (inflateEnd((z_stream *)reader->stream) != Z_OK) {
2061 rc = GRN_UNKNOWN_ERROR;
2062 }
2063 GRN_FREE(reader->stream);
2064 }
2065 }
2066 #endif /* GRN_WITH_ZLIB */
2067 return rc;
2068 }
2069
2070 grn_rc
grn_ja_reader_open(grn_ctx * ctx,grn_ja * ja,grn_ja_reader ** reader)2071 grn_ja_reader_open(grn_ctx *ctx, grn_ja *ja, grn_ja_reader **reader)
2072 {
2073 grn_rc rc;
2074 grn_ja_reader *new_reader = GRN_MALLOCN(grn_ja_reader, 1);
2075 if (!new_reader) {
2076 return GRN_NO_MEMORY_AVAILABLE;
2077 }
2078 rc = grn_ja_reader_init(ctx, new_reader, ja);
2079 if (rc != GRN_SUCCESS) {
2080 GRN_FREE(new_reader);
2081 return rc;
2082 }
2083 *reader = new_reader;
2084 return GRN_SUCCESS;
2085 }
2086
2087 grn_rc
grn_ja_reader_close(grn_ctx * ctx,grn_ja_reader * reader)2088 grn_ja_reader_close(grn_ctx *ctx, grn_ja_reader *reader)
2089 {
2090 grn_rc rc = grn_ja_reader_fin(ctx, reader);
2091 GRN_FREE(reader);
2092 return rc;
2093 }
2094
2095 #ifdef GRN_WITH_COMPRESSED
2096 /* grn_ja_reader_seek_compressed() prepares to access a compressed value. */
2097 static grn_rc
grn_ja_reader_seek_compressed(grn_ctx * ctx,grn_ja_reader * reader,grn_id id)2098 grn_ja_reader_seek_compressed(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
2099 {
2100 grn_ja_einfo *einfo;
2101 void *seg_addr;
2102 uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
2103 if (seg_id == JA_ESEG_VOID) {
2104 return GRN_INVALID_ARGUMENT;
2105 }
2106 if (seg_id != reader->einfo_seg_id) {
2107 GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr);
2108 if (!seg_addr) {
2109 return GRN_UNKNOWN_ERROR;
2110 }
2111 if (reader->einfo_seg_id != JA_ESEG_VOID) {
2112 GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
2113 }
2114 reader->einfo_seg_id = seg_id;
2115 reader->einfo_seg_addr = seg_addr;
2116 }
2117 einfo = (grn_ja_einfo *)reader->einfo_seg_addr;
2118 einfo += id & JA_M_EINFO_IN_A_SEGMENT;
2119 reader->einfo = einfo;
2120 /* ETINY_P(einfo) is always false because the original size needs 8 bytes. */
2121 if (EHUGE_P(einfo)) {
2122 EHUGE_DEC(einfo, seg_id, reader->packed_size);
2123 reader->body_seg_offset = 0;
2124 } else {
2125 EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->packed_size);
2126 }
2127 if (seg_id != reader->body_seg_id) {
2128 GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr);
2129 if (!seg_addr) {
2130 return GRN_UNKNOWN_ERROR;
2131 }
2132 if (reader->body_seg_addr) {
2133 GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
2134 }
2135 reader->body_seg_id = seg_id;
2136 reader->body_seg_addr = seg_addr;
2137 }
2138 seg_addr = (char *)reader->body_seg_addr + reader->body_seg_offset;
2139 reader->value_size = (uint32_t)*(uint64_t *)seg_addr;
2140 return GRN_SUCCESS;
2141 }
2142 #endif /* GRN_WITH_COMPRESSED */
2143
2144 /* grn_ja_reader_seek_raw() prepares to access a value. */
2145 static grn_rc
grn_ja_reader_seek_raw(grn_ctx * ctx,grn_ja_reader * reader,grn_id id)2146 grn_ja_reader_seek_raw(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
2147 {
2148 grn_ja_einfo *einfo;
2149 void *seg_addr;
2150 uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
2151 if (seg_id == JA_ESEG_VOID) {
2152 return GRN_INVALID_ARGUMENT;
2153 }
2154 if (seg_id != reader->einfo_seg_id) {
2155 GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr);
2156 if (!seg_addr) {
2157 return GRN_UNKNOWN_ERROR;
2158 }
2159 if (reader->einfo_seg_id != JA_ESEG_VOID) {
2160 GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
2161 }
2162 reader->einfo_seg_id = seg_id;
2163 reader->einfo_seg_addr = seg_addr;
2164 }
2165 einfo = (grn_ja_einfo *)reader->einfo_seg_addr;
2166 einfo += id & JA_M_EINFO_IN_A_SEGMENT;
2167 reader->einfo = einfo;
2168 if (ETINY_P(einfo)) {
2169 ETINY_DEC(einfo, reader->value_size);
2170 reader->ref_avail = GRN_FALSE;
2171 } else {
2172 if (EHUGE_P(einfo)) {
2173 EHUGE_DEC(einfo, seg_id, reader->value_size);
2174 reader->ref_avail = GRN_FALSE;
2175 } else {
2176 EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->value_size);
2177 reader->ref_avail = GRN_TRUE;
2178 }
2179 if (reader->body_seg_addr) {
2180 if (seg_id != reader->body_seg_id) {
2181 GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
2182 reader->body_seg_addr = NULL;
2183 }
2184 }
2185 reader->body_seg_id = seg_id;
2186 }
2187 return GRN_SUCCESS;
2188 }
2189
2190 grn_rc
grn_ja_reader_seek(grn_ctx * ctx,grn_ja_reader * reader,grn_id id)2191 grn_ja_reader_seek(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
2192 {
2193 switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
2194 #ifdef GRN_WITH_ZLIB
2195 case GRN_OBJ_COMPRESS_ZLIB :
2196 return grn_ja_reader_seek_compressed(ctx, reader, id);
2197 #endif /* GRN_WITH_ZLIB */
2198 #ifdef GRN_WITH_LZ4
2199 case GRN_OBJ_COMPRESS_LZ4 :
2200 return grn_ja_reader_seek_compressed(ctx, reader, id);
2201 #endif /* GRN_WITH_LZ4 */
2202 #ifdef GRN_WITH_ZSTD
2203 case GRN_OBJ_COMPRESS_ZSTD :
2204 return grn_ja_reader_seek_compressed(ctx, reader, id);
2205 #endif /* GRN_WITH_ZSTD */
2206 default :
2207 return grn_ja_reader_seek_raw(ctx, reader, id);
2208 }
2209 }
2210
2211 grn_rc
grn_ja_reader_ref(grn_ctx * ctx,grn_ja_reader * reader,void ** addr)2212 grn_ja_reader_ref(grn_ctx *ctx, grn_ja_reader *reader, void **addr)
2213 {
2214 if (!reader->ref_avail) {
2215 return GRN_INVALID_ARGUMENT;
2216 }
2217 if (reader->body_seg_id != reader->ref_seg_id) {
2218 void *seg_addr;
2219 if (reader->nref_seg_ids == reader->ref_seg_ids_size) {
2220 size_t n_bytes;
2221 uint32_t new_size, *new_seg_ids;
2222 if (reader->ref_seg_ids_size == 0) {
2223 new_size = GRN_JA_READER_INITIAL_REF_SEG_IDS_SIZE;
2224 } else {
2225 new_size = reader->ref_seg_ids_size * 2;
2226 }
2227 n_bytes = sizeof(uint32_t) * new_size;
2228 new_seg_ids = (uint32_t *)GRN_REALLOC(reader->ref_seg_ids, n_bytes);
2229 if (!new_seg_ids) {
2230 return GRN_NO_MEMORY_AVAILABLE;
2231 }
2232 reader->ref_seg_ids = new_seg_ids;
2233 reader->ref_seg_ids_size = new_size;
2234 }
2235 GRN_IO_SEG_REF(reader->ja->io, reader->body_seg_id, seg_addr);
2236 if (!seg_addr) {
2237 return GRN_UNKNOWN_ERROR;
2238 }
2239 reader->ref_seg_id = reader->body_seg_id;
2240 reader->ref_seg_addr = seg_addr;
2241 reader->ref_seg_ids[reader->nref_seg_ids++] = reader->body_seg_id;
2242 }
2243 *addr = (char *)reader->ref_seg_addr + reader->body_seg_offset;
2244 return GRN_SUCCESS;
2245 }
2246
2247 grn_rc
grn_ja_reader_unref(grn_ctx * ctx,grn_ja_reader * reader)2248 grn_ja_reader_unref(grn_ctx *ctx, grn_ja_reader *reader)
2249 {
2250 uint32_t i;
2251 for (i = 0; i < reader->nref_seg_ids; i++) {
2252 GRN_IO_SEG_UNREF(reader->ja->io, reader->ref_seg_ids[i]);
2253 }
2254 reader->ref_seg_id = JA_ESEG_VOID;
2255 reader->nref_seg_ids = 0;
2256 return GRN_FUNCTION_NOT_IMPLEMENTED;
2257 }
2258
2259 #ifdef GRN_WITH_ZLIB
2260 /* grn_ja_reader_read_zlib() reads a value compressed with zlib. */
2261 static grn_rc
grn_ja_reader_read_zlib(grn_ctx * ctx,grn_ja_reader * reader,void * buf)2262 grn_ja_reader_read_zlib(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2263 {
2264 uLong dest_size = reader->value_size;
2265 z_stream *stream = (z_stream *)reader->stream;
2266 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2267 if (EHUGE_P(einfo)) {
2268 /* TODO: Use z_stream to avoid copy. */
2269 grn_io *io = reader->ja->io;
2270 void *seg_addr;
2271 char *packed_ptr;
2272 uint32_t size, seg_id;
2273 if (reader->packed_size > reader->packed_buf_size) {
2274 void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size);
2275 if (!new_buf) {
2276 return GRN_NO_MEMORY_AVAILABLE;
2277 }
2278 reader->packed_buf = new_buf;
2279 reader->packed_buf_size = reader->packed_size;
2280 }
2281 packed_ptr = (char *)reader->packed_buf;
2282 grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t),
2283 io->header->segment_size - sizeof(uint64_t));
2284 packed_ptr += io->header->segment_size - sizeof(uint64_t);
2285 size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t));
2286 seg_id = reader->body_seg_id + 1;
2287 while (size > io->header->segment_size) {
2288 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2289 if (!seg_addr) {
2290 return GRN_UNKNOWN_ERROR;
2291 }
2292 grn_memcpy(packed_ptr, seg_addr, io->header->segment_size);
2293 GRN_IO_SEG_UNREF(io, seg_id);
2294 seg_id++;
2295 size -= io->header->segment_size;
2296 packed_ptr += io->header->segment_size;
2297 }
2298 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2299 if (!seg_addr) {
2300 return GRN_UNKNOWN_ERROR;
2301 }
2302 grn_memcpy(packed_ptr, seg_addr, size);
2303 GRN_IO_SEG_UNREF(io, seg_id);
2304 seg_id++;
2305 if (uncompress((Bytef *)buf, &dest_size, (Bytef *)reader->packed_buf,
2306 reader->packed_size - sizeof(uint64_t)) != Z_OK) {
2307 return GRN_ZLIB_ERROR;
2308 }
2309 if (dest_size != reader->value_size) {
2310 return GRN_ZLIB_ERROR;
2311 }
2312 } else {
2313 char *packed_addr = (char *)reader->body_seg_addr;
2314 packed_addr += reader->body_seg_offset + sizeof(uint64_t);
2315 if (inflateReset(stream) != Z_OK) {
2316 return GRN_ZLIB_ERROR;
2317 }
2318 stream->next_in = (Bytef *)packed_addr;
2319 stream->avail_in = reader->packed_size - sizeof(uint64_t);
2320 stream->next_out = (Bytef *)buf;
2321 stream->avail_out = dest_size;
2322 if ((inflate(stream, Z_FINISH) != Z_STREAM_END) || stream->avail_out) {
2323 return GRN_ZLIB_ERROR;
2324 }
2325 }
2326 return GRN_SUCCESS;
2327 }
2328 #endif /* GRN_WITH_ZLIB */
2329
2330 #ifdef GRN_WITH_LZ4
2331 /* grn_ja_reader_read_lz4() reads a value compressed with LZ4. */
2332 static grn_rc
grn_ja_reader_read_lz4(grn_ctx * ctx,grn_ja_reader * reader,void * buf)2333 grn_ja_reader_read_lz4(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2334 {
2335 int src_size, dest_size;
2336 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2337 if (EHUGE_P(einfo)) {
2338 grn_io *io = reader->ja->io;
2339 void *seg_addr;
2340 char *packed_ptr;
2341 uint32_t size, seg_id;
2342 if (reader->packed_size > reader->packed_buf_size) {
2343 void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size);
2344 if (!new_buf) {
2345 return GRN_NO_MEMORY_AVAILABLE;
2346 }
2347 reader->packed_buf = new_buf;
2348 reader->packed_buf_size = reader->packed_size;
2349 }
2350 packed_ptr = (char *)reader->packed_buf;
2351 grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t),
2352 io->header->segment_size - sizeof(uint64_t));
2353 packed_ptr += io->header->segment_size - sizeof(uint64_t);
2354 size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t));
2355 seg_id = reader->body_seg_id + 1;
2356 while (size > io->header->segment_size) {
2357 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2358 if (!seg_addr) {
2359 return GRN_UNKNOWN_ERROR;
2360 }
2361 grn_memcpy(packed_ptr, seg_addr, io->header->segment_size);
2362 GRN_IO_SEG_UNREF(io, seg_id);
2363 seg_id++;
2364 size -= io->header->segment_size;
2365 packed_ptr += io->header->segment_size;
2366 }
2367 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2368 if (!seg_addr) {
2369 return GRN_UNKNOWN_ERROR;
2370 }
2371 grn_memcpy(packed_ptr, seg_addr, size);
2372 GRN_IO_SEG_UNREF(io, seg_id);
2373 seg_id++;
2374 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2375 dest_size = LZ4_decompress_safe(reader->packed_buf, buf, src_size,
2376 (int)reader->value_size);
2377 } else {
2378 char *packed_addr = (char *)reader->body_seg_addr;
2379 packed_addr += reader->body_seg_offset + sizeof(uint64_t);
2380 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2381 dest_size = LZ4_decompress_safe(packed_addr, buf, src_size,
2382 (int)reader->value_size);
2383 }
2384 if ((uint32_t)dest_size != reader->value_size) {
2385 return GRN_LZ4_ERROR;
2386 }
2387 return GRN_SUCCESS;
2388 }
2389 #endif /* GRN_WITH_LZ4 */
2390
2391 #ifdef GRN_WITH_ZSTD
2392 /* grn_ja_reader_read_zstd() reads a value compressed with Zstandard. */
2393 static grn_rc
grn_ja_reader_read_zstd(grn_ctx * ctx,grn_ja_reader * reader,void * buf)2394 grn_ja_reader_read_zstd(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2395 {
2396 int src_size, dest_size;
2397 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2398 if (EHUGE_P(einfo)) {
2399 grn_io *io = reader->ja->io;
2400 void *seg_addr;
2401 char *packed_ptr;
2402 uint32_t size, seg_id;
2403 if (reader->packed_size > reader->packed_buf_size) {
2404 void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size);
2405 if (!new_buf) {
2406 return GRN_NO_MEMORY_AVAILABLE;
2407 }
2408 reader->packed_buf = new_buf;
2409 reader->packed_buf_size = reader->packed_size;
2410 }
2411 packed_ptr = (char *)reader->packed_buf;
2412 grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t),
2413 io->header->segment_size - sizeof(uint64_t));
2414 packed_ptr += io->header->segment_size - sizeof(uint64_t);
2415 size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t));
2416 seg_id = reader->body_seg_id + 1;
2417 while (size > io->header->segment_size) {
2418 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2419 if (!seg_addr) {
2420 return GRN_UNKNOWN_ERROR;
2421 }
2422 grn_memcpy(packed_ptr, seg_addr, io->header->segment_size);
2423 GRN_IO_SEG_UNREF(io, seg_id);
2424 seg_id++;
2425 size -= io->header->segment_size;
2426 packed_ptr += io->header->segment_size;
2427 }
2428 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2429 if (!seg_addr) {
2430 return GRN_UNKNOWN_ERROR;
2431 }
2432 grn_memcpy(packed_ptr, seg_addr, size);
2433 GRN_IO_SEG_UNREF(io, seg_id);
2434 seg_id++;
2435 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2436 dest_size = ZSTD_decompress(reader->packed_buf, reader->value_size,
2437 buf, src_size);
2438 } else {
2439 char *packed_addr = (char *)reader->body_seg_addr;
2440 packed_addr += reader->body_seg_offset + sizeof(uint64_t);
2441 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2442 dest_size = ZSTD_decompress(packed_addr, reader->value_size,
2443 buf, src_size);
2444 }
2445 if ((uint32_t)dest_size != reader->value_size) {
2446 return GRN_ZSTD_ERROR;
2447 }
2448 return GRN_SUCCESS;
2449 }
2450 #endif /* GRN_WITH_ZSTD */
2451
2452 /* grn_ja_reader_read_raw() reads a value. */
2453 static grn_rc
grn_ja_reader_read_raw(grn_ctx * ctx,grn_ja_reader * reader,void * buf)2454 grn_ja_reader_read_raw(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2455 {
2456 grn_io *io = reader->ja->io;
2457 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2458 if (ETINY_P(einfo)) {
2459 grn_memcpy(buf, einfo, reader->value_size);
2460 } else if (EHUGE_P(einfo)) {
2461 char *buf_ptr = (char *)buf;
2462 void *seg_addr;
2463 uint32_t seg_id = reader->body_seg_id;
2464 uint32_t size = reader->value_size;
2465 while (size > io->header->segment_size) {
2466 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2467 if (!seg_addr) {
2468 return GRN_UNKNOWN_ERROR;
2469 }
2470 grn_memcpy(buf_ptr, seg_addr, io->header->segment_size);
2471 GRN_IO_SEG_UNREF(io, seg_id);
2472 seg_id++;
2473 size -= io->header->segment_size;
2474 buf_ptr += io->header->segment_size;
2475 }
2476 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2477 if (!seg_addr) {
2478 return GRN_UNKNOWN_ERROR;
2479 }
2480 grn_memcpy(buf_ptr, seg_addr, size);
2481 GRN_IO_SEG_UNREF(io, seg_id);
2482 seg_id++;
2483 } else {
2484 if (!reader->body_seg_addr) {
2485 GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr);
2486 if (!reader->body_seg_addr) {
2487 return GRN_UNKNOWN_ERROR;
2488 }
2489 }
2490 grn_memcpy(buf, (char *)reader->body_seg_addr + reader->body_seg_offset,
2491 reader->value_size);
2492 }
2493 return GRN_SUCCESS;
2494 }
2495
2496 grn_rc
grn_ja_reader_read(grn_ctx * ctx,grn_ja_reader * reader,void * buf)2497 grn_ja_reader_read(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2498 {
2499 switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
2500 #ifdef GRN_WITH_ZLIB
2501 case GRN_OBJ_COMPRESS_ZLIB :
2502 return grn_ja_reader_read_zlib(ctx, reader, buf);
2503 #endif /* GRN_WITH_ZLIB */
2504 #ifdef GRN_WITH_LZ4
2505 case GRN_OBJ_COMPRESS_LZ4 :
2506 return grn_ja_reader_read_lz4(ctx, reader, buf);
2507 #endif /* GRN_WITH_LZ4 */
2508 #ifdef GRN_WITH_ZSTD
2509 case GRN_OBJ_COMPRESS_ZSTD :
2510 return grn_ja_reader_read_zstd(ctx, reader, buf);
2511 #endif /* GRN_WITH_ZSTD */
2512 default :
2513 return grn_ja_reader_read_raw(ctx, reader, buf);
2514 }
2515 }
2516
2517 #ifdef GRN_WITH_ZLIB
2518 /* grn_ja_reader_pread_zlib() reads a part of a value compressed with zlib. */
2519 static grn_rc
grn_ja_reader_pread_zlib(grn_ctx * ctx,grn_ja_reader * reader,size_t offset,size_t size,void * buf)2520 grn_ja_reader_pread_zlib(grn_ctx *ctx, grn_ja_reader *reader,
2521 size_t offset, size_t size, void *buf)
2522 {
2523 /* TODO: To be supported? */
2524 return GRN_FUNCTION_NOT_IMPLEMENTED;
2525 }
2526 #endif /* GRN_WITH_ZLIB */
2527
2528 #ifdef GRN_WITH_LZ4
2529 /* grn_ja_reader_pread_lz4() reads a part of a value compressed with LZ4. */
2530 static grn_rc
grn_ja_reader_pread_lz4(grn_ctx * ctx,grn_ja_reader * reader,size_t offset,size_t size,void * buf)2531 grn_ja_reader_pread_lz4(grn_ctx *ctx, grn_ja_reader *reader,
2532 size_t offset, size_t size, void *buf)
2533 {
2534 /* TODO: To be supported? */
2535 return GRN_FUNCTION_NOT_IMPLEMENTED;
2536 }
2537 #endif /* GRN_WITH_LZ4 */
2538
2539 #ifdef GRN_WITH_ZSTD
2540 /* grn_ja_reader_pread_zstd() reads a part of a value compressed with ZSTD. */
2541 static grn_rc
grn_ja_reader_pread_zstd(grn_ctx * ctx,grn_ja_reader * reader,size_t offset,size_t size,void * buf)2542 grn_ja_reader_pread_zstd(grn_ctx *ctx, grn_ja_reader *reader,
2543 size_t offset, size_t size, void *buf)
2544 {
2545 /* TODO: To be supported? */
2546 return GRN_FUNCTION_NOT_IMPLEMENTED;
2547 }
2548 #endif /* GRN_WITH_ZSTD */
2549
2550 /* grn_ja_reader_pread_raw() reads a part of a value. */
2551 static grn_rc
grn_ja_reader_pread_raw(grn_ctx * ctx,grn_ja_reader * reader,size_t offset,size_t size,void * buf)2552 grn_ja_reader_pread_raw(grn_ctx *ctx, grn_ja_reader *reader,
2553 size_t offset, size_t size, void *buf)
2554 {
2555 grn_io *io = reader->ja->io;
2556 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2557 if ((offset >= reader->value_size) || !size) {
2558 return GRN_SUCCESS;
2559 }
2560 if (size > (reader->value_size - offset)) {
2561 size = reader->value_size - offset;
2562 }
2563 if (ETINY_P(einfo)) {
2564 grn_memcpy(buf, (char *)einfo + offset, size);
2565 } else if (EHUGE_P(einfo)) {
2566 char *buf_ptr = (char *)buf;
2567 void *seg_addr;
2568 uint32_t seg_id = reader->body_seg_id;
2569 if (offset >= io->header->segment_size) {
2570 seg_id += offset / io->header->segment_size;
2571 offset %= io->header->segment_size;
2572 }
2573 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2574 if (!seg_addr) {
2575 return GRN_UNKNOWN_ERROR;
2576 }
2577 grn_memcpy(buf_ptr, (char *)seg_addr + offset,
2578 io->header->segment_size - offset);
2579 GRN_IO_SEG_UNREF(io, seg_id);
2580 seg_id++;
2581 size -= io->header->segment_size - offset;
2582 buf_ptr += io->header->segment_size - offset;
2583 while (size > io->header->segment_size) {
2584 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2585 if (!seg_addr) {
2586 return GRN_UNKNOWN_ERROR;
2587 }
2588 grn_memcpy(buf_ptr, (char *)seg_addr, io->header->segment_size);
2589 GRN_IO_SEG_UNREF(io, seg_id);
2590 seg_id++;
2591 size -= io->header->segment_size;
2592 buf_ptr += io->header->segment_size;
2593 }
2594 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2595 if (!seg_addr) {
2596 return GRN_UNKNOWN_ERROR;
2597 }
2598 grn_memcpy(buf_ptr, seg_addr, size);
2599 GRN_IO_SEG_UNREF(io, seg_id);
2600 } else {
2601 if (!reader->body_seg_addr) {
2602 GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr);
2603 if (!reader->body_seg_addr) {
2604 return GRN_UNKNOWN_ERROR;
2605 }
2606 }
2607 offset += reader->body_seg_offset;
2608 grn_memcpy(buf, (char *)reader->body_seg_addr + offset, size);
2609 }
2610 return GRN_SUCCESS;
2611 }
2612
2613 grn_rc
grn_ja_reader_pread(grn_ctx * ctx,grn_ja_reader * reader,size_t offset,size_t size,void * buf)2614 grn_ja_reader_pread(grn_ctx *ctx, grn_ja_reader *reader,
2615 size_t offset, size_t size, void *buf)
2616 {
2617 switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
2618 #ifdef GRN_WITH_ZLIB
2619 case GRN_OBJ_COMPRESS_ZLIB :
2620 return grn_ja_reader_pread_zlib(ctx, reader, offset, size, buf);
2621 #endif /* GRN_WITH_ZLIB */
2622 #ifdef GRN_WITH_LZ4
2623 case GRN_OBJ_COMPRESS_LZ4 :
2624 return grn_ja_reader_pread_lz4(ctx, reader, offset, size, buf);
2625 #endif /* GRN_WITH_LZ4 */
2626 #ifdef GRN_WITH_ZSTD
2627 case GRN_OBJ_COMPRESS_ZSTD :
2628 return grn_ja_reader_pread_zstd(ctx, reader, offset, size, buf);
2629 #endif /* GRN_WITH_ZSTD */
2630 default :
2631 return grn_ja_reader_pread_raw(ctx, reader, offset, size, buf);
2632 }
2633 }
2634
2635 /**** vgram ****/
2636
2637 /*
2638
2639 static int len_sum = 0;
2640 static int img_sum = 0;
2641 static int simple_sum = 0;
2642 static int skip_sum = 0;
2643
2644 grn_vgram *
2645 grn_vgram_create(const char *path)
2646 {
2647 grn_vgram *s;
2648 if (!(s = GRN_MALLOCN(grn_vgram, 1))) { return NULL; }
2649 s->vgram = grn_sym_create(path, sizeof(grn_id) * 2, 0, GRN_ENC_NONE);
2650 if (!s->vgram) {
2651 GRN_FREE(s);
2652 return NULL;
2653 }
2654 return s;
2655 }
2656
2657 grn_vgram *
2658 grn_vgram_open(const char *path)
2659 {
2660 grn_vgram *s;
2661 if (!(s = GRN_MALLOCN(grn_vgram, 1))) { return NULL; }
2662 s->vgram = grn_sym_open(path);
2663 if (!s->vgram) {
2664 GRN_FREE(s);
2665 return NULL;
2666 }
2667 return s;
2668 }
2669
2670 grn_vgram_buf *
2671 grn_vgram_buf_open(size_t len)
2672 {
2673 grn_vgram_buf *b;
2674 if (!(b = GRN_MALLOCN(grn_vgram_buf, 1))) { return NULL; }
2675 b->len = len;
2676 b->tvs = b->tvp = GRN_MALLOCN(grn_id, len);
2677 if (!b->tvp) { GRN_FREE(b); return NULL; }
2678 b->tve = b->tvs + len;
2679 b->vps = b->vpp = GRN_MALLOCN(grn_vgram_vnode, len * 2);
2680 if (!b->vpp) { GRN_FREE(b->tvp); GRN_FREE(b); return NULL; }
2681 b->vpe = b->vps + len;
2682 return b;
2683 }
2684
2685 grn_rc
2686 grn_vgram_buf_add(grn_vgram_buf *b, grn_id tid)
2687 {
2688 uint8_t dummybuf[8], *dummyp;
2689 if (b->tvp < b->tve) { *b->tvp++ = tid; }
2690 dummyp = dummybuf;
2691 GRN_B_ENC(tid, dummyp);
2692 simple_sum += dummyp - dummybuf;
2693 return GRN_SUCCESS;
2694 }
2695
2696 typedef struct {
2697 grn_id vid;
2698 grn_id tid;
2699 } vgram_key;
2700
2701 grn_rc
2702 grn_vgram_update(grn_vgram *vgram, grn_id rid, grn_vgram_buf *b, grn_hash *terms)
2703 {
2704 grn_inv_updspec **u;
2705 if (b && b->tvs < b->tvp) {
2706 grn_id *t0, *tn;
2707 for (t0 = b->tvs; t0 < b->tvp - 1; t0++) {
2708 grn_vgram_vnode *v, **vp;
2709 if (grn_set_at(terms, t0, (void **) &u)) {
2710 vp = &(*u)->vnodes;
2711 for (tn = t0 + 1; tn < b->tvp; tn++) {
2712 for (v = *vp; v && v->tid != *tn; v = v->cdr) ;
2713 if (!v) {
2714 if (b->vpp < b->vpe) {
2715 v = b->vpp++;
2716 } else {
2717 // todo;
2718 break;
2719 }
2720 v->car = NULL;
2721 v->cdr = *vp;
2722 *vp = v;
2723 v->tid = *tn;
2724 v->vid = 0;
2725 v->freq = 0;
2726 v->len = tn - t0;
2727 }
2728 v->freq++;
2729 if (v->vid) {
2730 vp = &v->car;
2731 } else {
2732 break;
2733 }
2734 }
2735 }
2736 }
2737 {
2738 grn_set *th = grn_set_open(sizeof(grn_id), sizeof(int), 0);
2739 if (!th) { return GRN_NO_MEMORY_AVAILABLE; }
2740 if (t0 == b->tvp) { GRN_LOG(ctx, GRN_LOG_DEBUG, "t0 == tvp"); }
2741 for (t0 = b->tvs; t0 < b->tvp; t0++) {
2742 grn_id vid, vid0 = *t0, vid1 = 0;
2743 grn_vgram_vnode *v, *v2 = NULL, **vp;
2744 if (grn_set_at(terms, t0, (void **) &u)) {
2745 vp = &(*u)->vnodes;
2746 for (tn = t0 + 1; tn < b->tvp; tn++) {
2747 for (v = *vp; v; v = v->cdr) {
2748 if (!v->vid && (v->freq < 2 || v->freq * v->len < 4)) {
2749 *vp = v->cdr;
2750 v->freq = 0;
2751 }
2752 if (v->tid == *tn) { break; }
2753 vp = &v->cdr;
2754 }
2755 if (v) {
2756 if (v->freq) {
2757 v2 = v;
2758 vid1 = vid0;
2759 vid0 = v->vid;
2760 }
2761 if (v->vid) {
2762 vp = &v->car;
2763 continue;
2764 }
2765 }
2766 break;
2767 }
2768 }
2769 if (v2) {
2770 if (!v2->vid) {
2771 vgram_key key;
2772 key.vid = vid1;
2773 key.tid = v2->tid;
2774 if (!(v2->vid = grn_sym_get(vgram->vgram, (char *)&key))) {
2775 grn_set_close(th);
2776 return GRN_NO_MEMORY_AVAILABLE;
2777 }
2778 }
2779 vid = *t0 = v2->vid * 2 + 1;
2780 memset(t0 + 1, 0, sizeof(grn_id) * v2->len);
2781 t0 += v2->len;
2782 } else {
2783 vid = *t0 *= 2;
2784 }
2785 {
2786 int *tf;
2787 if (!grn_set_get(th, &vid, (void **) &tf)) {
2788 grn_set_close(th);
2789 return GRN_NO_MEMORY_AVAILABLE;
2790 }
2791 (*tf)++;
2792 }
2793 }
2794 if (!th->n_entries) { GRN_LOG(ctx, GRN_LOG_DEBUG, "th->n_entries == 0"); }
2795 {
2796 int j = 0;
2797 int skip = 0;
2798 grn_set_eh *ehs, *ehp, *ehe;
2799 grn_set_sort_optarg arg;
2800 uint8_t *ps = GRN_MALLOC(b->len * 2), *pp, *pe;
2801 if (!ps) {
2802 grn_set_close(th);
2803 return GRN_NO_MEMORY_AVAILABLE;
2804 }
2805 pp = ps;
2806 pe = ps + b->len * 2;
2807 arg.mode = grn_sort_descending;
2808 arg.compar = NULL;
2809 arg.compar_arg = (void *)(intptr_t)sizeof(grn_id);
2810 ehs = grn_set_sort(th, 0, &arg);
2811 if (!ehs) {
2812 GRN_FREE(ps);
2813 grn_set_close(th);
2814 return GRN_NO_MEMORY_AVAILABLE;
2815 }
2816 GRN_B_ENC(th->n_entries, pp);
2817 for (ehp = ehs, ehe = ehs + th->n_entries; ehp < ehe; ehp++, j++) {
2818 int *id = (int *)GRN_SET_INTVAL(*ehp);
2819 GRN_B_ENC(*GRN_SET_INTKEY(*ehp), pp);
2820 *id = j;
2821 }
2822 for (t0 = b->tvs; t0 < b->tvp; t0++) {
2823 if (*t0) {
2824 int *id;
2825 if (!grn_set_at(th, t0, (void **) &id)) {
2826 GRN_LOG(ctx, GRN_LOG_ERROR, "lookup error (%d)", *t0);
2827 }
2828 GRN_B_ENC(*id, pp);
2829 } else {
2830 skip++;
2831 }
2832 }
2833 len_sum += b->len;
2834 img_sum += pp - ps;
2835 skip_sum += skip;
2836 GRN_FREE(ehs);
2837 GRN_FREE(ps);
2838 }
2839 grn_set_close(th);
2840 }
2841 }
2842 return GRN_SUCCESS;
2843 }
2844
2845 grn_rc
2846 grn_vgram_buf_close(grn_vgram_buf *b)
2847 {
2848 if (!b) { return GRN_INVALID_ARGUMENT; }
2849 if (b->tvs) { GRN_FREE(b->tvs); }
2850 if (b->vps) { GRN_FREE(b->vps); }
2851 GRN_FREE(b);
2852 return GRN_SUCCESS;
2853 }
2854
2855 grn_rc
2856 grn_vgram_close(grn_vgram *vgram)
2857 {
2858 if (!vgram) { return GRN_INVALID_ARGUMENT; }
2859 GRN_LOG(ctx, GRN_LOG_DEBUG, "len=%d img=%d skip=%d simple=%d", len_sum, img_sum, skip_sum, simple_sum);
2860 grn_sym_close(vgram->vgram);
2861 GRN_FREE(vgram);
2862 return GRN_SUCCESS;
2863 }
2864 */
2865