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-1301 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
30static grn_ra *
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
59grn_ra *
60grn_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
74grn_ra *
75grn_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
108grn_rc
109grn_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
116grn_rc
117grn_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
126grn_rc
127grn_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
133grn_rc
134grn_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 }
155exit:
156 if (path) { GRN_FREE(path); }
157 return rc;
158}
159
160void *
161grn_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
172grn_rc
173grn_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
182void *
183grn_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
201grn_rc
202grn_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
231typedef struct _grn_ja_einfo grn_ja_einfo;
232
233struct _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
281typedef struct {
282 uint32_t seg;
283 uint32_t pos;
284} ja_pos;
285
286typedef 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
294struct 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
306struct 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
320struct 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
348static grn_ja *
349_grn_ja_create(grn_ctx *ctx, grn_ja *ja, const char *path,
350 unsigned int max_element_size, uint32_t flags)
351{
352 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
395grn_ja *
396grn_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
411grn_ja *
412grn_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
476grn_rc
477grn_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
484grn_column_flags
485grn_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
494grn_rc
495grn_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
505grn_rc
506grn_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
512grn_rc
513grn_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 }
537exit:
538 if (path) { GRN_FREE(path); }
539 return rc;
540}
541
542static void *
543grn_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
579grn_rc
580grn_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
594static grn_rc
595grn_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
678grn_rc
679grn_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 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);
728exit :
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.
736static grn_rc
737grn_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 int i, j, n = (element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT;
754 for (i = 0, j = -1; i < JA_N_DSEGMENTS; i++) {
755 if (SEGMENTS_AT(ja, i)) {
756 j = i;
757 } else {
758 if (i == j + n) {
759 j++;
760 addr = grn_io_win_map(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly);
761 if (!addr) {
762 grn_io_unlock(ja->io);
763 return GRN_NO_MEMORY_AVAILABLE;
764 }
765 EHUGE_ENC(einfo, j, element_size);
766 for (; j <= i; j++) { SEGMENTS_HUGE_ON(ja, j); }
767 grn_io_unlock(ja->io);
768 return GRN_SUCCESS;
769 }
770 }
771 }
772 GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. requested element_size=%d.", element_size);
773 grn_io_unlock(ja->io);
774 return GRN_NO_MEMORY_AVAILABLE;
775 } else {
776 ja_pos *vp;
777 int m, aligned_size, es = element_size - 1;
778 GRN_BIT_SCAN_REV(es, m);
779 m++;
780 if (m > ja->header->segregate_threshold) {
781 uint32_t seg = *(ja->header->curr_seg);
782 uint32_t pos = *(ja->header->curr_pos);
783 if (pos + element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) {
784 seg = 0;
785 while (SEGMENTS_AT(ja, seg)) {
786 if (++seg >= JA_N_DSEGMENTS) {
787 grn_io_unlock(ja->io);
788 GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. seg=%d.", seg);
789 return GRN_NOT_ENOUGH_SPACE;
790 }
791 }
792 SEGMENTS_SEQ_ON(ja, seg);
793 *(ja->header->curr_seg) = seg;
794 pos = 0;
795 }
796 GRN_IO_SEG_REF(ja->io, seg, addr);
797 if (!addr) {
798 grn_io_unlock(ja->io);
799 return GRN_NO_MEMORY_AVAILABLE;
800 }
801 *(grn_id *)(addr + pos) = id;
802 aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
803 if (pos + aligned_size < JA_SEGMENT_SIZE) {
804 *(grn_id *)(addr + pos + aligned_size) = GRN_ID_NIL;
805 }
806 SEGMENTS_AT(ja, seg) += aligned_size + sizeof(grn_id);
807 pos += sizeof(grn_id);
808 EINFO_ENC(einfo, seg, pos, element_size);
809 iw->segment = seg;
810 iw->addr = addr + pos;
811 *(ja->header->curr_pos) = pos + aligned_size;
812 grn_io_unlock(ja->io);
813 return GRN_SUCCESS;
814 } else {
815 uint32_t lseg = 0, lseg_;
816 aligned_size = 1 << m;
817 if (ja->header->ngarbages[m - JA_W_EINFO] > JA_N_GARBAGES_TH) {
818 grn_ja_ginfo *ginfo = NULL;
819 uint32_t seg, pos, *gseg;
820 gseg = &ja->header->garbages[m - JA_W_EINFO];
821 while ((lseg_ = *gseg)) {
822 GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
823 if (!ginfo) {
824 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
825 grn_io_unlock(ja->io);
826 return GRN_NO_MEMORY_AVAILABLE;
827 }
828 if (ginfo->next || ginfo->nrecs > JA_N_GARBAGES_TH) {
829 seg = ginfo->recs[ginfo->tail].seg;
830 pos = ginfo->recs[ginfo->tail].pos;
831 GRN_IO_SEG_REF(ja->io, seg, addr);
832 if (!addr) {
833 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
834 GRN_IO_SEG_UNREF(ja->io, lseg_);
835 grn_io_unlock(ja->io);
836 return GRN_NO_MEMORY_AVAILABLE;
837 }
838 EINFO_ENC(einfo, seg, pos, element_size);
839 iw->segment = seg;
840 iw->addr = addr + pos;
841 if (++ginfo->tail == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->tail = 0; }
842 ginfo->nrecs--;
843 ja->header->ngarbages[m - JA_W_EINFO]--;
844 if (!ginfo->nrecs) {
845 SEGMENTS_OFF(ja, *gseg);
846 *gseg = ginfo->next;
847 }
848 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
849 GRN_IO_SEG_UNREF(ja->io, lseg_);
850 grn_io_unlock(ja->io);
851 return GRN_SUCCESS;
852 }
853 if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
854 if (!ginfo->next) {
855 GRN_IO_SEG_UNREF(ja->io, lseg_);
856 break;
857 }
858 lseg = lseg_;
859 gseg = &ginfo->next;
860 }
861 }
862 vp = &ja->header->free_elements[m - JA_W_EINFO];
863 if (!vp->seg) {
864 int i = 0;
865 while (SEGMENTS_AT(ja, i)) {
866 if (++i >= JA_N_DSEGMENTS) {
867 grn_io_unlock(ja->io);
868 return GRN_NO_MEMORY_AVAILABLE;
869 }
870 }
871 SEGMENTS_SEGRE_ON(ja, i, m);
872 vp->seg = i;
873 vp->pos = 0;
874 }
875 }
876 EINFO_ENC(einfo, vp->seg, vp->pos, element_size);
877 GRN_IO_SEG_REF(ja->io, vp->seg, addr);
878 if (!addr) {
879 grn_io_unlock(ja->io);
880 return GRN_NO_MEMORY_AVAILABLE;
881 }
882 iw->segment = vp->seg;
883 iw->addr = addr + vp->pos;
884 if ((vp->pos += aligned_size) == JA_SEGMENT_SIZE) {
885 vp->seg = 0;
886 vp->pos = 0;
887 }
888 iw->uncompressed_value = NULL;
889 grn_io_unlock(ja->io);
890 return GRN_SUCCESS;
891 }
892}
893
894static grn_rc
895set_value(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
896 grn_ja_einfo *einfo)
897{
898 grn_rc rc = GRN_SUCCESS;
899 grn_io_win iw;
900 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
901 value_len >= ja->header->max_element_size) {
902 if ((rc = grn_ja_alloc(ctx, ja, id, value_len + sizeof(uint32_t), einfo, &iw))) {
903 return rc;
904 }
905 grn_memcpy(iw.addr, value, value_len);
906 memset((byte *)iw.addr + value_len, 0, sizeof(uint32_t));
907 grn_io_win_unmap(&iw);
908 } else {
909 if ((rc = grn_ja_alloc(ctx, ja, id, value_len, einfo, &iw))) { return rc; }
910 grn_memcpy(iw.addr, value, value_len);
911 grn_io_win_unmap(&iw);
912 }
913 return rc;
914}
915
916static grn_rc
917grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id,
918 void *value, uint32_t value_len, int flags, uint64_t *cas)
919{
920 int rc;
921 int64_t buf;
922 grn_io_win iw;
923 grn_ja_einfo einfo;
924
925 if ((flags & GRN_OBJ_SET_MASK) == GRN_OBJ_SET &&
926 value_len > 0) {
927 grn_io_win jw;
928 uint32_t old_len;
929 void *old_value;
930 grn_bool same_value = GRN_FALSE;
931
932 old_value = grn_ja_ref(ctx, ja, id, &jw, &old_len);
933 if (value_len == old_len && memcmp(value, old_value, value_len) == 0) {
934 same_value = GRN_TRUE;
935 }
936 grn_ja_unref(ctx, &jw);
937 if (same_value) {
938 return GRN_SUCCESS;
939 }
940 }
941
942 switch (flags & GRN_OBJ_SET_MASK) {
943 case GRN_OBJ_APPEND :
944 if (value_len) {
945 grn_io_win jw;
946 uint32_t old_len;
947 void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
948 if (oldvalue) {
949 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
950 old_len + value_len >= ja->header->max_element_size) {
951 if (old_len >= ja->header->max_element_size) {
952 byte *b = oldvalue;
953 uint32_t el = old_len - sizeof(uint32_t);
954 uint32_t pos = *((uint32_t *)(b + el));
955 GRN_ASSERT(pos < el);
956 if (el <= pos + value_len) {
957 uint32_t rest = el - pos;
958 grn_memcpy(b + pos, value, rest);
959 grn_memcpy(b, (byte *)value + rest, value_len - rest);
960 *((uint32_t *)(b + el)) = value_len - rest;
961 } else {
962 grn_memcpy(b + pos, value, value_len);
963 *((uint32_t *)(b + el)) = pos + value_len;
964 }
965 return GRN_SUCCESS;
966 } else {
967 if ((rc = grn_ja_alloc(ctx, ja, id,
968 value_len + old_len + sizeof(uint32_t),
969 &einfo, &iw))) {
970 grn_ja_unref(ctx, &jw);
971 return rc;
972 }
973 grn_memcpy(iw.addr, oldvalue, old_len);
974 grn_memcpy((byte *)iw.addr + old_len, value, value_len);
975 memset((byte *)iw.addr + old_len + value_len, 0, sizeof(uint32_t));
976 grn_io_win_unmap(&iw);
977 }
978 } else {
979 if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
980 grn_ja_unref(ctx, &jw);
981 return rc;
982 }
983 grn_memcpy(iw.addr, oldvalue, old_len);
984 grn_memcpy((byte *)iw.addr + old_len, value, value_len);
985 grn_io_win_unmap(&iw);
986 }
987 grn_ja_unref(ctx, &jw);
988 } else {
989 set_value(ctx, ja, id, value, value_len, &einfo);
990 }
991 }
992 break;
993 case GRN_OBJ_PREPEND :
994 if (value_len) {
995 grn_io_win jw;
996 uint32_t old_len;
997 void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
998 if (oldvalue) {
999 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
1000 old_len + value_len >= ja->header->max_element_size) {
1001 if (old_len >= ja->header->max_element_size) {
1002 byte *b = oldvalue;
1003 uint32_t el = old_len - sizeof(uint32_t);
1004 uint32_t pos = *((uint32_t *)(b + el));
1005 GRN_ASSERT(pos < el);
1006 if (pos < value_len) {
1007 uint32_t rest = value_len - pos;
1008 grn_memcpy(b, (byte *)value + rest, pos);
1009 grn_memcpy(b + el - rest, value, rest);
1010 *((uint32_t *)(b + el)) = el - rest;
1011 } else {
1012 grn_memcpy(b + pos - value_len, value, value_len);
1013 *((uint32_t *)(b + el)) = pos - value_len;
1014 }
1015 return GRN_SUCCESS;
1016 } else {
1017 if ((rc = grn_ja_alloc(ctx, ja, id,
1018 value_len + old_len + sizeof(uint32_t),
1019 &einfo, &iw))) {
1020 grn_ja_unref(ctx, &jw);
1021 return rc;
1022 }
1023 grn_memcpy(iw.addr, value, value_len);
1024 grn_memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
1025 memset((byte *)iw.addr + value_len + old_len, 0, sizeof(uint32_t));
1026 grn_io_win_unmap(&iw);
1027 }
1028 } else {
1029 if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
1030 grn_ja_unref(ctx, &jw);
1031 return rc;
1032 }
1033 grn_memcpy(iw.addr, value, value_len);
1034 grn_memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
1035 grn_io_win_unmap(&iw);
1036 }
1037 grn_ja_unref(ctx, &jw);
1038 } else {
1039 set_value(ctx, ja, id, value, value_len, &einfo);
1040 }
1041 }
1042 break;
1043 case GRN_OBJ_DECR :
1044 if (value_len == sizeof(int64_t)) {
1045 int64_t *v = (int64_t *)&buf;
1046 *v = -(*(int64_t *)value);
1047 value = v;
1048 } else if (value_len == sizeof(int32_t)) {
1049 int32_t *v = (int32_t *)&buf;
1050 *v = -(*(int32_t *)value);
1051 value = v;
1052 } else {
1053 return GRN_INVALID_ARGUMENT;
1054 }
1055 /* fallthru */
1056 case GRN_OBJ_INCR :
1057 {
1058 grn_io_win jw;
1059 uint32_t old_len;
1060 void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
1061 if (oldvalue && old_len) {
1062 grn_rc rc = GRN_INVALID_ARGUMENT;
1063 if (old_len == sizeof(int64_t) && value_len == sizeof(int64_t)) {
1064 (*(int64_t *)oldvalue) += (*(int64_t *)value);
1065 rc = GRN_SUCCESS;
1066 } else if (old_len == sizeof(int32_t) && value_len == sizeof(int32_t)) {
1067 (*(int32_t *)oldvalue) += (*(int32_t *)value);
1068 rc = GRN_SUCCESS;
1069 }
1070 grn_ja_unref(ctx, &jw);
1071 return rc;
1072 }
1073 }
1074 /* fallthru */
1075 case GRN_OBJ_SET :
1076 if (value_len) {
1077 set_value(ctx, ja, id, value, value_len, &einfo);
1078 } else {
1079 memset(&einfo, 0, sizeof(grn_ja_einfo));
1080 }
1081 break;
1082 default :
1083 ERR(GRN_INVALID_ARGUMENT, "grn_ja_put_raw called with illegal flags value");
1084 return GRN_INVALID_ARGUMENT;
1085 }
1086 if ((rc = grn_ja_replace(ctx, ja, id, &einfo, cas))) {
1087 if (!grn_io_lock(ctx, ja->io, grn_lock_timeout)) {
1088 grn_ja_free(ctx, ja, &einfo);
1089 grn_io_unlock(ja->io);
1090 }
1091 }
1092 return rc;
1093}
1094
1095grn_rc
1096grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *vector, int flags)
1097{
1098 grn_obj header, footer;
1099 grn_rc rc = GRN_SUCCESS;
1100 grn_section *vp;
1101 int i, f = 0, n = grn_vector_size(ctx, vector);
1102 GRN_TEXT_INIT(&header, 0);
1103 GRN_TEXT_INIT(&footer, 0);
1104 grn_text_benc(ctx, &header, n);
1105 for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) {
1106 grn_text_benc(ctx, &header, vp->length);
1107 if (vp->weight || vp->domain) { f = 1; }
1108 }
1109 if (f) {
1110 for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) {
1111 grn_text_benc(ctx, &footer, vp->weight);
1112 grn_text_benc(ctx, &footer, vp->domain);
1113 }
1114 }
1115 {
1116 grn_io_win iw;
1117 grn_ja_einfo einfo;
1118 grn_obj *body = vector->u.v.body;
1119 size_t sizeh = GRN_BULK_VSIZE(&header);
1120 size_t sizev = body ? GRN_BULK_VSIZE(body) : 0;
1121 size_t sizef = GRN_BULK_VSIZE(&footer);
1122 if ((rc = grn_ja_alloc(ctx, ja, id, sizeh + sizev + sizef, &einfo, &iw))) { goto exit; }
1123 grn_memcpy(iw.addr, GRN_BULK_HEAD(&header), sizeh);
1124 if (body) {
1125 grn_memcpy((char *)iw.addr + sizeh, GRN_BULK_HEAD(body), sizev);
1126 }
1127 if (f) {
1128 grn_memcpy((char *)iw.addr + sizeh + sizev, GRN_BULK_HEAD(&footer), sizef);
1129 }
1130 grn_io_win_unmap(&iw);
1131 rc = grn_ja_replace(ctx, ja, id, &einfo, NULL);
1132 }
1133exit :
1134 GRN_OBJ_FIN(ctx, &footer);
1135 GRN_OBJ_FIN(ctx, &header);
1136 return rc;
1137}
1138
1139uint32_t
1140grn_ja_size(grn_ctx *ctx, grn_ja *ja, grn_id id)
1141{
1142 grn_ja_einfo *einfo = NULL, *ei;
1143 uint32_t lseg, *pseg, pos, size;
1144 lseg = id >> JA_W_EINFO_IN_A_SEGMENT;
1145 pos = id & JA_M_EINFO_IN_A_SEGMENT;
1146 pseg = &ja->header->esegs[lseg];
1147 if (*pseg == JA_ESEG_VOID) {
1148 ctx->rc = GRN_INVALID_ARGUMENT;
1149 return 0;
1150 }
1151 GRN_IO_SEG_REF(ja->io, *pseg, einfo);
1152 if (!einfo) {
1153 ctx->rc = GRN_NO_MEMORY_AVAILABLE;
1154 return 0;
1155 }
1156 ei = &einfo[pos];
1157 if (ETINY_P(ei)) {
1158 ETINY_DEC(ei, size);
1159 } else {
1160 if (EHUGE_P(ei)) {
1161 size = ei->u.h.size;
1162 } else {
1163 size = (ei->u.n.c2 << 16) + ei->u.n.size;
1164 }
1165 }
1166 GRN_IO_SEG_UNREF(ja->io, *pseg);
1167 return size;
1168}
1169
1170grn_rc
1171grn_ja_element_info(grn_ctx *ctx, grn_ja *ja, grn_id id,
1172 uint64_t *cas, uint32_t *pos, uint32_t *size)
1173{
1174 uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
1175 if (pseg == JA_ESEG_VOID) {
1176 return GRN_INVALID_ARGUMENT;
1177 } else {
1178 grn_ja_einfo *einfo = NULL;
1179 GRN_IO_SEG_REF(ja->io, pseg, einfo);
1180 if (einfo) {
1181 grn_ja_einfo *ei;
1182 *cas = *((uint64_t *)&einfo[id & JA_M_EINFO_IN_A_SEGMENT]);
1183 ei = (grn_ja_einfo *)cas;
1184 if (ETINY_P(ei)) {
1185 ETINY_DEC(ei, *size);
1186 *pos = 0;
1187 } else {
1188 uint32_t jag;
1189 if (EHUGE_P(ei)) {
1190 EHUGE_DEC(ei, jag, *size);
1191 *pos = 0;
1192 } else {
1193 EINFO_DEC(ei, jag, *pos, *size);
1194 }
1195 }
1196 GRN_IO_SEG_UNREF(ja->io, pseg);
1197 } else {
1198 return GRN_INVALID_ARGUMENT;
1199 }
1200 }
1201 return GRN_SUCCESS;
1202}
1203
1204#define COMPRESSED_VALUE_META_FLAG(meta) ((meta) & 0xf000000000000000)
1205#define COMPRESSED_VALUE_META_FLAG_RAW 0x1000000000000000
1206#define COMPRESSED_VALUE_META_UNCOMPRESSED_LEN(meta) \
1207 ((meta) & 0x0fffffffffffffff)
1208
1209#define COMPRESS_THRESHOLD_BYTE 256
1210#define COMPRESS_PACKED_VALUE_SIZE_MAX 257
1211 /* COMPRESS_THRESHOLD_BYTE - 1 + sizeof(uint64_t) = 257 */
1212
1213#if defined(GRN_WITH_ZLIB) || defined(GRN_WITH_LZ4) || defined(GRN_WITH_ZSTD)
1214# define GRN_WITH_COMPRESSED
1215#endif
1216
1217#ifdef GRN_WITH_COMPRESSED
1218static void *
1219grn_ja_ref_packed(grn_ctx *ctx,
1220 grn_io_win *iw,
1221 uint32_t *value_len,
1222 void *raw_value,
1223 uint32_t raw_value_len,
1224 void **compressed_value,
1225 uint32_t *compressed_value_len,
1226 uint32_t *uncompressed_value_len)
1227{
1228 uint64_t compressed_value_meta;
1229
1230 compressed_value_meta = *((uint64_t *)raw_value);
1231 *compressed_value = (void *)(((uint64_t *)raw_value) + 1);
1232 *compressed_value_len = raw_value_len - sizeof(uint64_t);
1233
1234 *uncompressed_value_len =
1235 COMPRESSED_VALUE_META_UNCOMPRESSED_LEN(compressed_value_meta);
1236 switch (COMPRESSED_VALUE_META_FLAG(compressed_value_meta)) {
1237 case COMPRESSED_VALUE_META_FLAG_RAW :
1238 iw->uncompressed_value = NULL;
1239 *value_len = *uncompressed_value_len;
1240 return *compressed_value;
1241 default :
1242 return NULL;
1243 }
1244}
1245
1246static grn_rc
1247grn_ja_put_packed(grn_ctx *ctx,
1248 grn_ja *ja,
1249 grn_id id,
1250 void *value,
1251 uint32_t value_len,
1252 int flags,
1253 uint64_t *cas)
1254{
1255 char *packed_value[COMPRESS_PACKED_VALUE_SIZE_MAX];
1256 uint32_t packed_value_len;
1257 uint64_t packed_value_meta;
1258
1259 packed_value_len = value_len + sizeof(uint64_t);
1260 packed_value_meta = value_len | COMPRESSED_VALUE_META_FLAG_RAW;
1261 *((uint64_t *)packed_value) = packed_value_meta;
1262 memcpy(((uint64_t *)packed_value) + 1,
1263 value,
1264 value_len);
1265 return grn_ja_put_raw(ctx,
1266 ja,
1267 id,
1268 packed_value,
1269 packed_value_len,
1270 flags,
1271 cas);
1272}
1273
1274static void
1275grn_ja_compress_error(grn_ctx *ctx,
1276 grn_ja *ja,
1277 grn_id id,
1278 grn_rc rc,
1279 const char *message,
1280 const char *detail)
1281{
1282 char name[GRN_TABLE_MAX_KEY_SIZE];
1283 int name_len;
1284
1285 if (ja->obj.id == GRN_ID_NIL) {
1286 name[0] = '\0';
1287 name_len = 0;
1288 } else {
1289 name_len = grn_obj_name(ctx, (grn_obj *)ja, name, GRN_TABLE_MAX_KEY_SIZE);
1290 }
1291 ERR(GRN_ZSTD_ERROR,
1292 "[ja]%s: %s%.*s%s<%u>%s%s%s",
1293 message,
1294 name_len == 0 ? "" : "<",
1295 name_len,
1296 name,
1297 name_len == 0 ? "" : ">: ",
1298 id,
1299 detail ? " :<" : "",
1300 detail ? detail : "",
1301 detail ? ">" : "");
1302}
1303#endif /* GRN_WITH_COMPRESSED */
1304
1305#ifdef GRN_WITH_ZLIB
1306#include <zlib.h>
1307
1308static const char *
1309grn_zrc_to_string(int zrc)
1310{
1311 switch (zrc) {
1312 case Z_OK :
1313 return "OK";
1314 case Z_STREAM_END :
1315 return "Stream is end";
1316 case Z_NEED_DICT :
1317 return "Need dictionary";
1318 case Z_ERRNO :
1319 return "See errno";
1320 case Z_STREAM_ERROR :
1321 return "Stream error";
1322 case Z_DATA_ERROR :
1323 return "Data error";
1324 case Z_MEM_ERROR :
1325 return "Memory error";
1326 case Z_BUF_ERROR :
1327 return "Buffer error";
1328 case Z_VERSION_ERROR :
1329 return "Version error";
1330 default :
1331 return "Unknown";
1332 }
1333}
1334
1335static void *
1336grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1337{
1338 z_stream zstream;
1339 void *raw_value;
1340 uint32_t raw_value_len;
1341 void *zvalue;
1342 uint32_t zvalue_len;
1343 void *unpacked_value;
1344 uint32_t uncompressed_value_len;
1345 int zrc;
1346
1347 if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) {
1348 iw->uncompressed_value = NULL;
1349 *value_len = 0;
1350 return NULL;
1351 }
1352
1353 unpacked_value = grn_ja_ref_packed(ctx,
1354 iw, value_len,
1355 raw_value, raw_value_len,
1356 &zvalue, &zvalue_len,
1357 &uncompressed_value_len);
1358 if (unpacked_value) {
1359 return unpacked_value;
1360 }
1361
1362 zstream.next_in = (Bytef *)zvalue;
1363 zstream.avail_in = zvalue_len;
1364 zstream.zalloc = Z_NULL;
1365 zstream.zfree = Z_NULL;
1366 zrc = inflateInit2(&zstream, 15 /* windowBits */);
1367 if (zrc != Z_OK) {
1368 iw->uncompressed_value = NULL;
1369 *value_len = 0;
1370 grn_ja_compress_error(ctx,
1371 ja,
1372 id,
1373 GRN_ZLIB_ERROR,
1374 "[zlib] failed to decompress: initialize",
1375 grn_zrc_to_string(zrc));
1376 return NULL;
1377 }
1378 if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) {
1379 inflateEnd(&zstream);
1380 iw->uncompressed_value = NULL;
1381 *value_len = 0;
1382 grn_ja_compress_error(ctx,
1383 ja,
1384 id,
1385 GRN_ZLIB_ERROR,
1386 "[zlib] failed to decompress: allocate buffer",
1387 NULL);
1388 return NULL;
1389 }
1390 zstream.next_out = (Bytef *)iw->uncompressed_value;
1391 zstream.avail_out = uncompressed_value_len;
1392 zrc = inflate(&zstream, Z_FINISH);
1393 if (zrc != Z_STREAM_END) {
1394 inflateEnd(&zstream);
1395 GRN_FREE(iw->uncompressed_value);
1396 iw->uncompressed_value = NULL;
1397 *value_len = 0;
1398 grn_ja_compress_error(ctx,
1399 ja,
1400 id,
1401 GRN_ZLIB_ERROR,
1402 "[zlib] failed to decompress: finish",
1403 grn_zrc_to_string(zrc));
1404 return NULL;
1405 }
1406 *value_len = zstream.total_out;
1407 zrc = inflateEnd(&zstream);
1408 if (zrc != Z_OK) {
1409 GRN_FREE(iw->uncompressed_value);
1410 iw->uncompressed_value = NULL;
1411 *value_len = 0;
1412 grn_ja_compress_error(ctx,
1413 ja,
1414 id,
1415 GRN_ZLIB_ERROR,
1416 "[zlib] failed to decompress: end",
1417 grn_zrc_to_string(zrc));
1418 return NULL;
1419 }
1420 return iw->uncompressed_value;
1421}
1422#endif /* GRN_WITH_ZLIB */
1423
1424#ifdef GRN_WITH_LZ4
1425#include <lz4.h>
1426
1427# if (LZ4_VERSION_MAJOR == 1 && LZ4_VERSION_MINOR < 6)
1428# define LZ4_compress_default(source, dest, source_size, max_dest_size) \
1429 LZ4_compress((source), (dest), (source_size))
1430# endif
1431
1432static void *
1433grn_ja_ref_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1434{
1435 void *raw_value;
1436 uint32_t raw_value_len;
1437 void *lz4_value;
1438 uint32_t lz4_value_len;
1439 void *unpacked_value;
1440 uint32_t uncompressed_value_len;
1441
1442 if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) {
1443 iw->uncompressed_value = NULL;
1444 *value_len = 0;
1445 return NULL;
1446 }
1447
1448 unpacked_value = grn_ja_ref_packed(ctx,
1449 iw, value_len,
1450 raw_value, raw_value_len,
1451 &lz4_value, &lz4_value_len,
1452 &uncompressed_value_len);
1453 if (unpacked_value) {
1454 return unpacked_value;
1455 }
1456
1457 if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) {
1458 iw->uncompressed_value = NULL;
1459 *value_len = 0;
1460 return NULL;
1461 }
1462 if (LZ4_decompress_safe((const char *)(lz4_value),
1463 (char *)(iw->uncompressed_value),
1464 lz4_value_len,
1465 uncompressed_value_len) < 0) {
1466 GRN_FREE(iw->uncompressed_value);
1467 iw->uncompressed_value = NULL;
1468 *value_len = 0;
1469 grn_ja_compress_error(ctx,
1470 ja,
1471 id,
1472 GRN_LZ4_ERROR,
1473 "[lz4] failed to decompress",
1474 NULL);
1475 return NULL;
1476 }
1477 *value_len = uncompressed_value_len;
1478 return iw->uncompressed_value;
1479}
1480#endif /* GRN_WITH_LZ4 */
1481
1482#ifdef GRN_WITH_ZSTD
1483#include <zstd.h>
1484
1485static void *
1486grn_ja_ref_zstd(grn_ctx *ctx,
1487 grn_ja *ja,
1488 grn_id id,
1489 grn_io_win *iw,
1490 uint32_t *value_len)
1491{
1492 void *raw_value;
1493 uint32_t raw_value_len;
1494 void *zstd_value;
1495 uint32_t zstd_value_len;
1496 void *unpacked_value;
1497 uint32_t uncompressed_value_len;
1498 size_t written_len;
1499
1500 if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) {
1501 iw->uncompressed_value = NULL;
1502 *value_len = 0;
1503 return NULL;
1504 }
1505
1506 unpacked_value = grn_ja_ref_packed(ctx,
1507 iw, value_len,
1508 raw_value, raw_value_len,
1509 &zstd_value, &zstd_value_len,
1510 &uncompressed_value_len);
1511 if (unpacked_value) {
1512 return unpacked_value;
1513 }
1514
1515 if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) {
1516 iw->uncompressed_value = NULL;
1517 *value_len = 0;
1518 return NULL;
1519 }
1520
1521 written_len = ZSTD_decompress((char *)(iw->uncompressed_value),
1522 uncompressed_value_len,
1523 zstd_value,
1524 zstd_value_len);
1525 if (ZSTD_isError(written_len)) {
1526 GRN_FREE(iw->uncompressed_value);
1527 iw->uncompressed_value = NULL;
1528 *value_len = 0;
1529 grn_ja_compress_error(ctx,
1530 ja,
1531 id,
1532 GRN_ZSTD_ERROR,
1533 "[zstd] failed to decompress",
1534 ZSTD_getErrorName(written_len));
1535 return NULL;
1536 }
1537 *value_len = uncompressed_value_len;
1538 return iw->uncompressed_value;
1539}
1540#endif /* GRN_WITH_ZSTD */
1541
1542void *
1543grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1544{
1545 switch (ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
1546#ifdef GRN_WITH_ZLIB
1547 case GRN_OBJ_COMPRESS_ZLIB :
1548 return grn_ja_ref_zlib(ctx, ja, id, iw, value_len);
1549#endif /* GRN_WITH_ZLIB */
1550#ifdef GRN_WITH_LZ4
1551 case GRN_OBJ_COMPRESS_LZ4 :
1552 return grn_ja_ref_lz4(ctx, ja, id, iw, value_len);
1553#endif /* GRN_WITH_LZ4 */
1554#ifdef GRN_WITH_ZSTD
1555 case GRN_OBJ_COMPRESS_ZSTD :
1556 return grn_ja_ref_zstd(ctx, ja, id, iw, value_len);
1557#endif /* GRN_WITH_ZSTD */
1558 default :
1559 return grn_ja_ref_raw(ctx, ja, id, iw, value_len);
1560 }
1561}
1562
1563grn_obj *
1564grn_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *value)
1565{
1566 void *v;
1567 uint32_t len;
1568 grn_io_win iw;
1569 if (!value) {
1570 if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) {
1571 ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed");
1572 goto exit;
1573 }
1574 }
1575 if ((v = grn_ja_ref(ctx, ja, id, &iw, &len))) {
1576 if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
1577 len > ja->header->max_element_size) {
1578 byte *b = v;
1579 uint32_t el = len - sizeof(uint32_t);
1580 uint32_t pos = *((uint32_t *)(b + el));
1581 GRN_ASSERT(pos < el);
1582 grn_bulk_write(ctx, value, (char *)(b + pos), el - pos);
1583 grn_bulk_write(ctx, value, (char *)(b), pos);
1584 } else {
1585 grn_bulk_write(ctx, value, v, len);
1586 }
1587 grn_ja_unref(ctx, &iw);
1588 }
1589exit :
1590 return value;
1591}
1592
1593#ifdef GRN_WITH_ZLIB
1594inline static grn_rc
1595grn_ja_put_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id,
1596 void *value, uint32_t value_len, int flags, uint64_t *cas)
1597{
1598 grn_rc rc;
1599 z_stream zstream;
1600 void *zvalue;
1601 int zvalue_len;
1602 int zrc;
1603
1604 if (value_len == 0) {
1605 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1606 }
1607
1608 if (value_len < COMPRESS_THRESHOLD_BYTE) {
1609 return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas);
1610 }
1611
1612 zstream.next_in = value;
1613 zstream.avail_in = value_len;
1614 zstream.zalloc = Z_NULL;
1615 zstream.zfree = Z_NULL;
1616 zrc = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
1617 15 /* windowBits */,
1618 8 /* memLevel */,
1619 Z_DEFAULT_STRATEGY);
1620 if (zrc != Z_OK) {
1621 grn_ja_compress_error(ctx,
1622 ja,
1623 id,
1624 GRN_ZLIB_ERROR,
1625 "[zlib] failed to compress: initialize",
1626 grn_zrc_to_string(zrc));
1627 return ctx->rc;
1628 }
1629 zvalue_len = deflateBound(&zstream, value_len);
1630 if (!(zvalue = GRN_MALLOC(zvalue_len + sizeof(uint64_t)))) {
1631 deflateEnd(&zstream);
1632 grn_ja_compress_error(ctx,
1633 ja,
1634 id,
1635 GRN_ZLIB_ERROR,
1636 "[zlib] failed to allocate compress buffer",
1637 NULL);
1638 return ctx->rc;
1639 }
1640 zstream.next_out = (Bytef *)(((uint64_t *)zvalue) + 1);
1641 zstream.avail_out = zvalue_len;
1642 zrc = deflate(&zstream, Z_FINISH);
1643 if (zrc != Z_STREAM_END) {
1644 deflateEnd(&zstream);
1645 GRN_FREE(zvalue);
1646 grn_ja_compress_error(ctx,
1647 ja,
1648 id,
1649 GRN_ZLIB_ERROR,
1650 "[zlib] failed to compress: finish",
1651 grn_zrc_to_string(zrc));
1652 return ctx->rc;
1653 }
1654 zvalue_len = zstream.total_out;
1655 zrc = deflateEnd(&zstream);
1656 if (zrc != Z_OK) {
1657 GRN_FREE(zvalue);
1658 grn_ja_compress_error(ctx,
1659 ja,
1660 id,
1661 GRN_ZLIB_ERROR,
1662 "[zlib] failed to compress: end",
1663 grn_zrc_to_string(zrc));
1664 return ctx->rc;
1665 }
1666 *(uint64_t *)zvalue = value_len;
1667 rc = grn_ja_put_raw(ctx, ja, id, zvalue, zvalue_len + sizeof(uint64_t), flags, cas);
1668 GRN_FREE(zvalue);
1669 return rc;
1670}
1671#endif /* GRN_WITH_ZLIB */
1672
1673#ifdef GRN_WITH_LZ4
1674inline static grn_rc
1675grn_ja_put_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id,
1676 void *value, uint32_t value_len, int flags, uint64_t *cas)
1677{
1678 grn_rc rc;
1679 void *packed_value;
1680 int packed_value_len_max;
1681 int packed_value_len_real;
1682 char *lz4_value;
1683 int lz4_value_len_max;
1684 int lz4_value_len_real;
1685
1686 if (value_len == 0) {
1687 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1688 }
1689
1690 if (value_len < COMPRESS_THRESHOLD_BYTE) {
1691 return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas);
1692 }
1693
1694 if (value_len > (uint32_t)LZ4_MAX_INPUT_SIZE) {
1695 uint64_t packed_value_meta;
1696
1697 packed_value_len_real = value_len + sizeof(uint64_t);
1698 packed_value = GRN_MALLOC(packed_value_len_real);
1699 if (!packed_value) {
1700 grn_ja_compress_error(ctx,
1701 ja,
1702 id,
1703 GRN_LZ4_ERROR,
1704 "[lz4] failed to allocate packed buffer",
1705 NULL);
1706 return ctx->rc;
1707 }
1708 packed_value_meta = value_len | COMPRESSED_VALUE_META_FLAG_RAW;
1709 *((uint64_t *)packed_value) = packed_value_meta;
1710 memcpy(((uint64_t *)packed_value) + 1,
1711 value,
1712 value_len);
1713 rc = grn_ja_put_raw(ctx,
1714 ja,
1715 id,
1716 packed_value,
1717 packed_value_len_real,
1718 flags,
1719 cas);
1720 GRN_FREE(packed_value);
1721 return rc;
1722 }
1723
1724 lz4_value_len_max = LZ4_compressBound(value_len);
1725 packed_value_len_max = lz4_value_len_max + sizeof(uint64_t);
1726 if (!(packed_value = GRN_MALLOC(packed_value_len_max))) {
1727 grn_ja_compress_error(ctx,
1728 ja,
1729 id,
1730 GRN_LZ4_ERROR,
1731 "[lz4] failed to allocate compress buffer",
1732 NULL);
1733 return ctx->rc;
1734 }
1735 lz4_value = (char *)((uint64_t *)packed_value + 1);
1736 lz4_value_len_real = LZ4_compress_default((const char *)value,
1737 lz4_value,
1738 value_len,
1739 lz4_value_len_max);
1740 if (lz4_value_len_real <= 0) {
1741 GRN_FREE(packed_value);
1742 grn_ja_compress_error(ctx,
1743 ja,
1744 id,
1745 GRN_LZ4_ERROR,
1746 "[lz4] failed to compress",
1747 NULL);
1748 return ctx->rc;
1749 }
1750 *(uint64_t *)packed_value = value_len;
1751 packed_value_len_real = lz4_value_len_real + sizeof(uint64_t);
1752 rc = grn_ja_put_raw(ctx,
1753 ja,
1754 id,
1755 packed_value,
1756 packed_value_len_real,
1757 flags,
1758 cas);
1759 GRN_FREE(packed_value);
1760 return rc;
1761}
1762#endif /* GRN_WITH_LZ4 */
1763
1764#ifdef GRN_WITH_ZSTD
1765inline static grn_rc
1766grn_ja_put_zstd(grn_ctx *ctx,
1767 grn_ja *ja,
1768 grn_id id,
1769 void *value,
1770 uint32_t value_len,
1771 int flags,
1772 uint64_t *cas)
1773{
1774 grn_rc rc;
1775 void *packed_value;
1776 int packed_value_len_max;
1777 int packed_value_len_real;
1778 void *zstd_value;
1779 int zstd_value_len_max;
1780 int zstd_value_len_real;
1781 int zstd_compression_level = 3;
1782
1783 if (value_len == 0) {
1784 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1785 }
1786
1787 if (value_len < COMPRESS_THRESHOLD_BYTE) {
1788 return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas);
1789 }
1790
1791 zstd_value_len_max = ZSTD_compressBound(value_len);
1792 packed_value_len_max = zstd_value_len_max + sizeof(uint64_t);
1793 if (!(packed_value = GRN_MALLOC(packed_value_len_max))) {
1794 grn_ja_compress_error(ctx,
1795 ja,
1796 id,
1797 GRN_ZSTD_ERROR,
1798 "[zstd] failed to allocate compress buffer",
1799 NULL);
1800 return ctx->rc;
1801 }
1802 zstd_value = ((uint64_t *)packed_value) + 1;
1803 zstd_value_len_real = ZSTD_compress(zstd_value, zstd_value_len_max,
1804 value, value_len,
1805 zstd_compression_level);
1806 if (ZSTD_isError(zstd_value_len_real)) {
1807 grn_ja_compress_error(ctx,
1808 ja,
1809 id,
1810 GRN_ZSTD_ERROR,
1811 "[zstd] failed to compress",
1812 ZSTD_getErrorName(zstd_value_len_real));
1813 return ctx->rc;
1814 }
1815 *(uint64_t *)packed_value = value_len;
1816 packed_value_len_real = zstd_value_len_real + sizeof(uint64_t);
1817 rc = grn_ja_put_raw(ctx,
1818 ja,
1819 id,
1820 packed_value,
1821 packed_value_len_real,
1822 flags,
1823 cas);
1824 GRN_FREE(packed_value);
1825 return rc;
1826}
1827#endif /* GRN_WITH_ZSTD */
1828
1829grn_rc
1830grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
1831 int flags, uint64_t *cas)
1832{
1833 switch (ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
1834#ifdef GRN_WITH_ZLIB
1835 case GRN_OBJ_COMPRESS_ZLIB :
1836 return grn_ja_put_zlib(ctx, ja, id, value, value_len, flags, cas);
1837#endif /* GRN_WITH_ZLIB */
1838#ifdef GRN_WITH_LZ4
1839 case GRN_OBJ_COMPRESS_LZ4 :
1840 return grn_ja_put_lz4(ctx, ja, id, value, value_len, flags, cas);
1841#endif /* GRN_WITH_LZ4 */
1842#ifdef GRN_WITH_ZSTD
1843 case GRN_OBJ_COMPRESS_ZSTD :
1844 return grn_ja_put_zstd(ctx, ja, id, value, value_len, flags, cas);
1845#endif /* GRN_WITH_ZSTD */
1846 default :
1847 return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1848 }
1849}
1850
1851static grn_rc
1852grn_ja_defrag_seg(grn_ctx *ctx, grn_ja *ja, uint32_t seg)
1853{
1854 byte *v = NULL, *ve;
1855 uint32_t element_size, cum = 0, *seginfo = &SEGMENTS_AT(ja,seg), sum;
1856 sum = (*seginfo & ~SEG_MASK);
1857 GRN_IO_SEG_REF(ja->io, seg, v);
1858 if (!v) { return GRN_NO_MEMORY_AVAILABLE; }
1859 ve = v + JA_SEGMENT_SIZE;
1860 while (v < ve && cum < sum) {
1861 grn_id id = *((grn_id *)v);
1862 if (!id) { break; }
1863 if (id & DELETED) {
1864 element_size = (id & ~DELETED);
1865 } else {
1866 uint64_t cas;
1867 uint32_t pos;
1868 if (grn_ja_element_info(ctx, ja, id, &cas, &pos, &element_size)) { break; }
1869 if (v + sizeof(uint32_t) != ve - JA_SEGMENT_SIZE + pos) {
1870 GRN_LOG(ctx, GRN_LOG_WARNING,
1871 "dseges[%d] = pos unmatch (%d != %" GRN_FMT_LLD ")",
1872 seg, pos, (long long int)(v + sizeof(uint32_t) + JA_SEGMENT_SIZE - ve));
1873 break;
1874 }
1875 if (grn_ja_put(ctx, ja, id, v + sizeof(uint32_t), element_size, GRN_OBJ_SET, &cas)) {
1876 GRN_LOG(ctx, GRN_LOG_WARNING,
1877 "dseges[%d] = put failed (%d)", seg, id);
1878 break;
1879 }
1880 element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
1881 cum += sizeof(uint32_t) + element_size;
1882 }
1883 v += sizeof(uint32_t) + element_size;
1884 }
1885 if (*seginfo) {
1886 GRN_LOG(ctx, GRN_LOG_WARNING, "dseges[%d] = %d after defrag", seg, (*seginfo & ~SEG_MASK));
1887 }
1888 GRN_IO_SEG_UNREF(ja->io, seg);
1889 return GRN_SUCCESS;
1890}
1891
1892int
1893grn_ja_defrag(grn_ctx *ctx, grn_ja *ja, int threshold)
1894{
1895 int nsegs = 0;
1896 uint32_t seg, ts = 1U << (GRN_JA_W_SEGMENT - threshold);
1897 for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
1898 if (seg == *(ja->header->curr_seg)) { continue; }
1899 if (((SEGMENTS_AT(ja, seg) & SEG_MASK) == SEG_SEQ) &&
1900 ((SEGMENTS_AT(ja, seg) & ~SEG_MASK) < ts)) {
1901 if (!grn_ja_defrag_seg(ctx, ja, seg)) { nsegs++; }
1902 }
1903 }
1904 return nsegs;
1905}
1906
1907void
1908grn_ja_check(grn_ctx *ctx, grn_ja *ja)
1909{
1910 char buf[8];
1911 uint32_t seg;
1912 struct grn_ja_header *h = ja->header;
1913 GRN_OUTPUT_ARRAY_OPEN("RESULT", 8);
1914 GRN_OUTPUT_MAP_OPEN("SUMMARY", 8);
1915 GRN_OUTPUT_CSTR("flags");
1916 grn_itoh(h->flags, buf, 8);
1917 GRN_OUTPUT_STR(buf, 8);
1918 GRN_OUTPUT_CSTR("curr seg");
1919 GRN_OUTPUT_INT64(*(h->curr_seg));
1920 GRN_OUTPUT_CSTR("curr pos");
1921 GRN_OUTPUT_INT64(*(h->curr_pos));
1922 GRN_OUTPUT_CSTR("max_element_size");
1923 GRN_OUTPUT_INT64(h->max_element_size);
1924 GRN_OUTPUT_CSTR("segregate_threshold");
1925 GRN_OUTPUT_INT64(h->segregate_threshold);
1926 GRN_OUTPUT_CSTR("n_element_variation");
1927 GRN_OUTPUT_INT64(h->n_element_variation);
1928 GRN_OUTPUT_MAP_CLOSE();
1929 GRN_OUTPUT_ARRAY_OPEN("DETAIL", -1);
1930 for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
1931 int dseg = SEGMENTS_AT(ja, seg);
1932 if (dseg) {
1933 GRN_OUTPUT_MAP_OPEN("SEG", -1);
1934 GRN_OUTPUT_CSTR("seg id");
1935 GRN_OUTPUT_INT64(seg);
1936 GRN_OUTPUT_CSTR("seg type");
1937 GRN_OUTPUT_INT64((dseg & SEG_MASK)>>28);
1938 GRN_OUTPUT_CSTR("seg value");
1939 GRN_OUTPUT_INT64(dseg & ~SEG_MASK);
1940 if ((dseg & SEG_MASK) == SEG_SEQ) {
1941 byte *v = NULL, *ve;
1942 uint32_t element_size, cum = 0, sum = dseg & ~SEG_MASK;
1943 uint32_t n_del_elements = 0, n_elements = 0, s_del_elements = 0, s_elements = 0;
1944 GRN_IO_SEG_REF(ja->io, seg, v);
1945 if (v) {
1946 /*
1947 GRN_OUTPUT_CSTR("seg seq");
1948 GRN_OUTPUT_ARRAY_OPEN("SEQ", -1);
1949 */
1950 ve = v + JA_SEGMENT_SIZE;
1951 while (v < ve && cum < sum) {
1952 grn_id id = *((grn_id *)v);
1953 /*
1954 GRN_OUTPUT_MAP_OPEN("ENTRY", -1);
1955 GRN_OUTPUT_CSTR("id");
1956 GRN_OUTPUT_INT64(id);
1957 */
1958 if (!id) { break; }
1959 if (id & DELETED) {
1960 element_size = (id & ~DELETED);
1961 n_del_elements++;
1962 s_del_elements += element_size;
1963 } else {
1964 element_size = grn_ja_size(ctx, ja, id);
1965 element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
1966 cum += sizeof(uint32_t) + element_size;
1967 n_elements++;
1968 s_elements += sizeof(uint32_t) + element_size;
1969 }
1970 v += sizeof(uint32_t) + element_size;
1971 /*
1972 GRN_OUTPUT_CSTR("size");
1973 GRN_OUTPUT_INT64(element_size);
1974 GRN_OUTPUT_CSTR("cum");
1975 GRN_OUTPUT_INT64(cum);
1976 GRN_OUTPUT_MAP_CLOSE();
1977 */
1978 }
1979 GRN_IO_SEG_UNREF(ja->io, seg);
1980 /*
1981 GRN_OUTPUT_ARRAY_CLOSE();
1982 */
1983 GRN_OUTPUT_CSTR("n_elements");
1984 GRN_OUTPUT_INT64(n_elements);
1985 GRN_OUTPUT_CSTR("s_elements");
1986 GRN_OUTPUT_INT64(s_elements);
1987 GRN_OUTPUT_CSTR("n_del_elements");
1988 GRN_OUTPUT_INT64(n_del_elements);
1989 GRN_OUTPUT_CSTR("s_del_elements");
1990 GRN_OUTPUT_INT64(s_del_elements);
1991 if (cum != sum) {
1992 GRN_OUTPUT_CSTR("cum gap");
1993 GRN_OUTPUT_INT64(cum - sum);
1994 }
1995 }
1996 }
1997 GRN_OUTPUT_MAP_CLOSE();
1998 }
1999 }
2000 GRN_OUTPUT_ARRAY_CLOSE();
2001 GRN_OUTPUT_ARRAY_CLOSE();
2002}
2003
2004/* grn_ja_reader */
2005
2006grn_rc
2007grn_ja_reader_init(grn_ctx *ctx, grn_ja_reader *reader, grn_ja *ja)
2008{
2009 reader->ja = ja;
2010 reader->einfo_seg_id = JA_ESEG_VOID;
2011 reader->ref_avail = GRN_FALSE;
2012 reader->ref_seg_id = JA_ESEG_VOID;
2013 reader->ref_seg_ids = NULL;
2014 reader->nref_seg_ids = 0;
2015 reader->ref_seg_ids_size = 0;
2016 reader->body_seg_id = JA_ESEG_VOID;
2017 reader->body_seg_addr = NULL;
2018 reader->packed_buf = NULL;
2019 reader->packed_buf_size = 0;
2020#ifdef GRN_WITH_ZLIB
2021 if (reader->ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) {
2022 z_stream *new_stream = GRN_MALLOCN(z_stream, 1);
2023 if (!new_stream) {
2024 return GRN_NO_MEMORY_AVAILABLE;
2025 }
2026 new_stream->zalloc = NULL;
2027 new_stream->zfree = NULL;
2028 new_stream->opaque = NULL;
2029 if (inflateInit2(new_stream, 15) != Z_OK) {
2030 GRN_FREE(new_stream);
2031 return GRN_ZLIB_ERROR;
2032 }
2033 reader->stream = new_stream;
2034 }
2035#endif /* GRN_WITH_ZLIB */
2036 return GRN_SUCCESS;
2037}
2038
2039grn_rc
2040grn_ja_reader_fin(grn_ctx *ctx, grn_ja_reader *reader)
2041{
2042 grn_rc rc = GRN_SUCCESS;
2043 if (reader->einfo_seg_id != JA_ESEG_VOID) {
2044 GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
2045 }
2046 if (reader->ref_seg_ids) {
2047 grn_ja_reader_unref(ctx, reader);
2048 GRN_FREE(reader->ref_seg_ids);
2049 }
2050 if (reader->body_seg_addr) {
2051 GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
2052 }
2053 if (reader->packed_buf) {
2054 GRN_FREE(reader->packed_buf);
2055 }
2056#ifdef GRN_WITH_ZLIB
2057 if (reader->ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) {
2058 if (reader->stream) {
2059 if (inflateEnd((z_stream *)reader->stream) != Z_OK) {
2060 rc = GRN_UNKNOWN_ERROR;
2061 }
2062 GRN_FREE(reader->stream);
2063 }
2064 }
2065#endif /* GRN_WITH_ZLIB */
2066 return rc;
2067}
2068
2069grn_rc
2070grn_ja_reader_open(grn_ctx *ctx, grn_ja *ja, grn_ja_reader **reader)
2071{
2072 grn_rc rc;
2073 grn_ja_reader *new_reader = GRN_MALLOCN(grn_ja_reader, 1);
2074 if (!new_reader) {
2075 return GRN_NO_MEMORY_AVAILABLE;
2076 }
2077 rc = grn_ja_reader_init(ctx, new_reader, ja);
2078 if (rc != GRN_SUCCESS) {
2079 GRN_FREE(new_reader);
2080 return rc;
2081 }
2082 *reader = new_reader;
2083 return GRN_SUCCESS;
2084}
2085
2086grn_rc
2087grn_ja_reader_close(grn_ctx *ctx, grn_ja_reader *reader)
2088{
2089 grn_rc rc = grn_ja_reader_fin(ctx, reader);
2090 GRN_FREE(reader);
2091 return rc;
2092}
2093
2094#ifdef GRN_WITH_COMPRESSED
2095/* grn_ja_reader_seek_compressed() prepares to access a compressed value. */
2096static grn_rc
2097grn_ja_reader_seek_compressed(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
2098{
2099 grn_ja_einfo *einfo;
2100 void *seg_addr;
2101 uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
2102 if (seg_id == JA_ESEG_VOID) {
2103 return GRN_INVALID_ARGUMENT;
2104 }
2105 if (seg_id != reader->einfo_seg_id) {
2106 GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr);
2107 if (!seg_addr) {
2108 return GRN_UNKNOWN_ERROR;
2109 }
2110 if (reader->einfo_seg_id != JA_ESEG_VOID) {
2111 GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
2112 }
2113 reader->einfo_seg_id = seg_id;
2114 reader->einfo_seg_addr = seg_addr;
2115 }
2116 einfo = (grn_ja_einfo *)reader->einfo_seg_addr;
2117 einfo += id & JA_M_EINFO_IN_A_SEGMENT;
2118 reader->einfo = einfo;
2119 /* ETINY_P(einfo) is always false because the original size needs 8 bytes. */
2120 if (EHUGE_P(einfo)) {
2121 EHUGE_DEC(einfo, seg_id, reader->packed_size);
2122 reader->body_seg_offset = 0;
2123 } else {
2124 EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->packed_size);
2125 }
2126 if (seg_id != reader->body_seg_id) {
2127 GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr);
2128 if (!seg_addr) {
2129 return GRN_UNKNOWN_ERROR;
2130 }
2131 if (reader->body_seg_addr) {
2132 GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
2133 }
2134 reader->body_seg_id = seg_id;
2135 reader->body_seg_addr = seg_addr;
2136 }
2137 seg_addr = (char *)reader->body_seg_addr + reader->body_seg_offset;
2138 reader->value_size = (uint32_t)*(uint64_t *)seg_addr;
2139 return GRN_SUCCESS;
2140}
2141#endif /* GRN_WITH_COMPRESSED */
2142
2143/* grn_ja_reader_seek_raw() prepares to access a value. */
2144static grn_rc
2145grn_ja_reader_seek_raw(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
2146{
2147 grn_ja_einfo *einfo;
2148 void *seg_addr;
2149 uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
2150 if (seg_id == JA_ESEG_VOID) {
2151 return GRN_INVALID_ARGUMENT;
2152 }
2153 if (seg_id != reader->einfo_seg_id) {
2154 GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr);
2155 if (!seg_addr) {
2156 return GRN_UNKNOWN_ERROR;
2157 }
2158 if (reader->einfo_seg_id != JA_ESEG_VOID) {
2159 GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id);
2160 }
2161 reader->einfo_seg_id = seg_id;
2162 reader->einfo_seg_addr = seg_addr;
2163 }
2164 einfo = (grn_ja_einfo *)reader->einfo_seg_addr;
2165 einfo += id & JA_M_EINFO_IN_A_SEGMENT;
2166 reader->einfo = einfo;
2167 if (ETINY_P(einfo)) {
2168 ETINY_DEC(einfo, reader->value_size);
2169 reader->ref_avail = GRN_FALSE;
2170 } else {
2171 if (EHUGE_P(einfo)) {
2172 EHUGE_DEC(einfo, seg_id, reader->value_size);
2173 reader->ref_avail = GRN_FALSE;
2174 } else {
2175 EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->value_size);
2176 reader->ref_avail = GRN_TRUE;
2177 }
2178 if (reader->body_seg_addr) {
2179 if (seg_id != reader->body_seg_id) {
2180 GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id);
2181 reader->body_seg_addr = NULL;
2182 }
2183 }
2184 reader->body_seg_id = seg_id;
2185 }
2186 return GRN_SUCCESS;
2187}
2188
2189grn_rc
2190grn_ja_reader_seek(grn_ctx *ctx, grn_ja_reader *reader, grn_id id)
2191{
2192 switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
2193#ifdef GRN_WITH_ZLIB
2194 case GRN_OBJ_COMPRESS_ZLIB :
2195 return grn_ja_reader_seek_compressed(ctx, reader, id);
2196#endif /* GRN_WITH_ZLIB */
2197#ifdef GRN_WITH_LZ4
2198 case GRN_OBJ_COMPRESS_LZ4 :
2199 return grn_ja_reader_seek_compressed(ctx, reader, id);
2200#endif /* GRN_WITH_LZ4 */
2201#ifdef GRN_WITH_ZSTD
2202 case GRN_OBJ_COMPRESS_ZSTD :
2203 return grn_ja_reader_seek_compressed(ctx, reader, id);
2204#endif /* GRN_WITH_ZSTD */
2205 default :
2206 return grn_ja_reader_seek_raw(ctx, reader, id);
2207 }
2208}
2209
2210grn_rc
2211grn_ja_reader_ref(grn_ctx *ctx, grn_ja_reader *reader, void **addr)
2212{
2213 if (!reader->ref_avail) {
2214 return GRN_INVALID_ARGUMENT;
2215 }
2216 if (reader->body_seg_id != reader->ref_seg_id) {
2217 void *seg_addr;
2218 if (reader->nref_seg_ids == reader->ref_seg_ids_size) {
2219 size_t n_bytes;
2220 uint32_t new_size, *new_seg_ids;
2221 if (reader->ref_seg_ids_size == 0) {
2222 new_size = GRN_JA_READER_INITIAL_REF_SEG_IDS_SIZE;
2223 } else {
2224 new_size = reader->ref_seg_ids_size * 2;
2225 }
2226 n_bytes = sizeof(uint32_t) * new_size;
2227 new_seg_ids = (uint32_t *)GRN_REALLOC(reader->ref_seg_ids, n_bytes);
2228 if (!new_seg_ids) {
2229 return GRN_NO_MEMORY_AVAILABLE;
2230 }
2231 reader->ref_seg_ids = new_seg_ids;
2232 reader->ref_seg_ids_size = new_size;
2233 }
2234 GRN_IO_SEG_REF(reader->ja->io, reader->body_seg_id, seg_addr);
2235 if (!seg_addr) {
2236 return GRN_UNKNOWN_ERROR;
2237 }
2238 reader->ref_seg_id = reader->body_seg_id;
2239 reader->ref_seg_addr = seg_addr;
2240 reader->ref_seg_ids[reader->nref_seg_ids++] = reader->body_seg_id;
2241 }
2242 *addr = (char *)reader->ref_seg_addr + reader->body_seg_offset;
2243 return GRN_SUCCESS;
2244}
2245
2246grn_rc
2247grn_ja_reader_unref(grn_ctx *ctx, grn_ja_reader *reader)
2248{
2249 uint32_t i;
2250 for (i = 0; i < reader->nref_seg_ids; i++) {
2251 GRN_IO_SEG_UNREF(reader->ja->io, reader->ref_seg_ids[i]);
2252 }
2253 reader->ref_seg_id = JA_ESEG_VOID;
2254 reader->nref_seg_ids = 0;
2255 return GRN_FUNCTION_NOT_IMPLEMENTED;
2256}
2257
2258#ifdef GRN_WITH_ZLIB
2259/* grn_ja_reader_read_zlib() reads a value compressed with zlib. */
2260static grn_rc
2261grn_ja_reader_read_zlib(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2262{
2263 uLong dest_size = reader->value_size;
2264 z_stream *stream = (z_stream *)reader->stream;
2265 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2266 if (EHUGE_P(einfo)) {
2267 /* TODO: Use z_stream to avoid copy. */
2268 grn_io *io = reader->ja->io;
2269 void *seg_addr;
2270 char *packed_ptr;
2271 uint32_t size, seg_id;
2272 if (reader->packed_size > reader->packed_buf_size) {
2273 void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size);
2274 if (!new_buf) {
2275 return GRN_NO_MEMORY_AVAILABLE;
2276 }
2277 reader->packed_buf = new_buf;
2278 reader->packed_buf_size = reader->packed_size;
2279 }
2280 packed_ptr = (char *)reader->packed_buf;
2281 grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t),
2282 io->header->segment_size - sizeof(uint64_t));
2283 packed_ptr += io->header->segment_size - sizeof(uint64_t);
2284 size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t));
2285 seg_id = reader->body_seg_id + 1;
2286 while (size > io->header->segment_size) {
2287 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2288 if (!seg_addr) {
2289 return GRN_UNKNOWN_ERROR;
2290 }
2291 grn_memcpy(packed_ptr, seg_addr, io->header->segment_size);
2292 GRN_IO_SEG_UNREF(io, seg_id);
2293 seg_id++;
2294 size -= io->header->segment_size;
2295 packed_ptr += io->header->segment_size;
2296 }
2297 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2298 if (!seg_addr) {
2299 return GRN_UNKNOWN_ERROR;
2300 }
2301 grn_memcpy(packed_ptr, seg_addr, size);
2302 GRN_IO_SEG_UNREF(io, seg_id);
2303 seg_id++;
2304 if (uncompress((Bytef *)buf, &dest_size, (Bytef *)reader->packed_buf,
2305 reader->packed_size - sizeof(uint64_t)) != Z_OK) {
2306 return GRN_ZLIB_ERROR;
2307 }
2308 if (dest_size != reader->value_size) {
2309 return GRN_ZLIB_ERROR;
2310 }
2311 } else {
2312 char *packed_addr = (char *)reader->body_seg_addr;
2313 packed_addr += reader->body_seg_offset + sizeof(uint64_t);
2314 if (inflateReset(stream) != Z_OK) {
2315 return GRN_ZLIB_ERROR;
2316 }
2317 stream->next_in = (Bytef *)packed_addr;
2318 stream->avail_in = reader->packed_size - sizeof(uint64_t);
2319 stream->next_out = (Bytef *)buf;
2320 stream->avail_out = dest_size;
2321 if ((inflate(stream, Z_FINISH) != Z_STREAM_END) || stream->avail_out) {
2322 return GRN_ZLIB_ERROR;
2323 }
2324 }
2325 return GRN_SUCCESS;
2326}
2327#endif /* GRN_WITH_ZLIB */
2328
2329#ifdef GRN_WITH_LZ4
2330/* grn_ja_reader_read_lz4() reads a value compressed with LZ4. */
2331static grn_rc
2332grn_ja_reader_read_lz4(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2333{
2334 int src_size, dest_size;
2335 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2336 if (EHUGE_P(einfo)) {
2337 grn_io *io = reader->ja->io;
2338 void *seg_addr;
2339 char *packed_ptr;
2340 uint32_t size, seg_id;
2341 if (reader->packed_size > reader->packed_buf_size) {
2342 void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size);
2343 if (!new_buf) {
2344 return GRN_NO_MEMORY_AVAILABLE;
2345 }
2346 reader->packed_buf = new_buf;
2347 reader->packed_buf_size = reader->packed_size;
2348 }
2349 packed_ptr = (char *)reader->packed_buf;
2350 grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t),
2351 io->header->segment_size - sizeof(uint64_t));
2352 packed_ptr += io->header->segment_size - sizeof(uint64_t);
2353 size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t));
2354 seg_id = reader->body_seg_id + 1;
2355 while (size > io->header->segment_size) {
2356 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2357 if (!seg_addr) {
2358 return GRN_UNKNOWN_ERROR;
2359 }
2360 grn_memcpy(packed_ptr, seg_addr, io->header->segment_size);
2361 GRN_IO_SEG_UNREF(io, seg_id);
2362 seg_id++;
2363 size -= io->header->segment_size;
2364 packed_ptr += io->header->segment_size;
2365 }
2366 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2367 if (!seg_addr) {
2368 return GRN_UNKNOWN_ERROR;
2369 }
2370 grn_memcpy(packed_ptr, seg_addr, size);
2371 GRN_IO_SEG_UNREF(io, seg_id);
2372 seg_id++;
2373 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2374 dest_size = LZ4_decompress_safe(reader->packed_buf, buf, src_size,
2375 (int)reader->value_size);
2376 } else {
2377 char *packed_addr = (char *)reader->body_seg_addr;
2378 packed_addr += reader->body_seg_offset + sizeof(uint64_t);
2379 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2380 dest_size = LZ4_decompress_safe(packed_addr, buf, src_size,
2381 (int)reader->value_size);
2382 }
2383 if ((uint32_t)dest_size != reader->value_size) {
2384 return GRN_LZ4_ERROR;
2385 }
2386 return GRN_SUCCESS;
2387}
2388#endif /* GRN_WITH_LZ4 */
2389
2390#ifdef GRN_WITH_ZSTD
2391/* grn_ja_reader_read_zstd() reads a value compressed with Zstandard. */
2392static grn_rc
2393grn_ja_reader_read_zstd(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2394{
2395 int src_size, dest_size;
2396 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2397 if (EHUGE_P(einfo)) {
2398 grn_io *io = reader->ja->io;
2399 void *seg_addr;
2400 char *packed_ptr;
2401 uint32_t size, seg_id;
2402 if (reader->packed_size > reader->packed_buf_size) {
2403 void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size);
2404 if (!new_buf) {
2405 return GRN_NO_MEMORY_AVAILABLE;
2406 }
2407 reader->packed_buf = new_buf;
2408 reader->packed_buf_size = reader->packed_size;
2409 }
2410 packed_ptr = (char *)reader->packed_buf;
2411 grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t),
2412 io->header->segment_size - sizeof(uint64_t));
2413 packed_ptr += io->header->segment_size - sizeof(uint64_t);
2414 size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t));
2415 seg_id = reader->body_seg_id + 1;
2416 while (size > io->header->segment_size) {
2417 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2418 if (!seg_addr) {
2419 return GRN_UNKNOWN_ERROR;
2420 }
2421 grn_memcpy(packed_ptr, seg_addr, io->header->segment_size);
2422 GRN_IO_SEG_UNREF(io, seg_id);
2423 seg_id++;
2424 size -= io->header->segment_size;
2425 packed_ptr += io->header->segment_size;
2426 }
2427 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2428 if (!seg_addr) {
2429 return GRN_UNKNOWN_ERROR;
2430 }
2431 grn_memcpy(packed_ptr, seg_addr, size);
2432 GRN_IO_SEG_UNREF(io, seg_id);
2433 seg_id++;
2434 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2435 dest_size = ZSTD_decompress(reader->packed_buf, reader->value_size,
2436 buf, src_size);
2437 } else {
2438 char *packed_addr = (char *)reader->body_seg_addr;
2439 packed_addr += reader->body_seg_offset + sizeof(uint64_t);
2440 src_size = (int)(reader->packed_size - sizeof(uint64_t));
2441 dest_size = ZSTD_decompress(packed_addr, reader->value_size,
2442 buf, src_size);
2443 }
2444 if ((uint32_t)dest_size != reader->value_size) {
2445 return GRN_ZSTD_ERROR;
2446 }
2447 return GRN_SUCCESS;
2448}
2449#endif /* GRN_WITH_ZSTD */
2450
2451/* grn_ja_reader_read_raw() reads a value. */
2452static grn_rc
2453grn_ja_reader_read_raw(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2454{
2455 grn_io *io = reader->ja->io;
2456 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2457 if (ETINY_P(einfo)) {
2458 grn_memcpy(buf, einfo, reader->value_size);
2459 } else if (EHUGE_P(einfo)) {
2460 char *buf_ptr = (char *)buf;
2461 void *seg_addr;
2462 uint32_t seg_id = reader->body_seg_id;
2463 uint32_t size = reader->value_size;
2464 while (size > io->header->segment_size) {
2465 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2466 if (!seg_addr) {
2467 return GRN_UNKNOWN_ERROR;
2468 }
2469 grn_memcpy(buf_ptr, seg_addr, io->header->segment_size);
2470 GRN_IO_SEG_UNREF(io, seg_id);
2471 seg_id++;
2472 size -= io->header->segment_size;
2473 buf_ptr += io->header->segment_size;
2474 }
2475 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2476 if (!seg_addr) {
2477 return GRN_UNKNOWN_ERROR;
2478 }
2479 grn_memcpy(buf_ptr, seg_addr, size);
2480 GRN_IO_SEG_UNREF(io, seg_id);
2481 seg_id++;
2482 } else {
2483 if (!reader->body_seg_addr) {
2484 GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr);
2485 if (!reader->body_seg_addr) {
2486 return GRN_UNKNOWN_ERROR;
2487 }
2488 }
2489 grn_memcpy(buf, (char *)reader->body_seg_addr + reader->body_seg_offset,
2490 reader->value_size);
2491 }
2492 return GRN_SUCCESS;
2493}
2494
2495grn_rc
2496grn_ja_reader_read(grn_ctx *ctx, grn_ja_reader *reader, void *buf)
2497{
2498 switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
2499#ifdef GRN_WITH_ZLIB
2500 case GRN_OBJ_COMPRESS_ZLIB :
2501 return grn_ja_reader_read_zlib(ctx, reader, buf);
2502#endif /* GRN_WITH_ZLIB */
2503#ifdef GRN_WITH_LZ4
2504 case GRN_OBJ_COMPRESS_LZ4 :
2505 return grn_ja_reader_read_lz4(ctx, reader, buf);
2506#endif /* GRN_WITH_LZ4 */
2507#ifdef GRN_WITH_ZSTD
2508 case GRN_OBJ_COMPRESS_ZSTD :
2509 return grn_ja_reader_read_zstd(ctx, reader, buf);
2510#endif /* GRN_WITH_ZSTD */
2511 default :
2512 return grn_ja_reader_read_raw(ctx, reader, buf);
2513 }
2514}
2515
2516#ifdef GRN_WITH_ZLIB
2517/* grn_ja_reader_pread_zlib() reads a part of a value compressed with zlib. */
2518static grn_rc
2519grn_ja_reader_pread_zlib(grn_ctx *ctx, grn_ja_reader *reader,
2520 size_t offset, size_t size, void *buf)
2521{
2522 /* TODO: To be supported? */
2523 return GRN_FUNCTION_NOT_IMPLEMENTED;
2524}
2525#endif /* GRN_WITH_ZLIB */
2526
2527#ifdef GRN_WITH_LZ4
2528/* grn_ja_reader_pread_lz4() reads a part of a value compressed with LZ4. */
2529static grn_rc
2530grn_ja_reader_pread_lz4(grn_ctx *ctx, grn_ja_reader *reader,
2531 size_t offset, size_t size, void *buf)
2532{
2533 /* TODO: To be supported? */
2534 return GRN_FUNCTION_NOT_IMPLEMENTED;
2535}
2536#endif /* GRN_WITH_LZ4 */
2537
2538#ifdef GRN_WITH_ZSTD
2539/* grn_ja_reader_pread_zstd() reads a part of a value compressed with ZSTD. */
2540static grn_rc
2541grn_ja_reader_pread_zstd(grn_ctx *ctx, grn_ja_reader *reader,
2542 size_t offset, size_t size, void *buf)
2543{
2544 /* TODO: To be supported? */
2545 return GRN_FUNCTION_NOT_IMPLEMENTED;
2546}
2547#endif /* GRN_WITH_ZSTD */
2548
2549/* grn_ja_reader_pread_raw() reads a part of a value. */
2550static grn_rc
2551grn_ja_reader_pread_raw(grn_ctx *ctx, grn_ja_reader *reader,
2552 size_t offset, size_t size, void *buf)
2553{
2554 grn_io *io = reader->ja->io;
2555 grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo;
2556 if ((offset >= reader->value_size) || !size) {
2557 return GRN_SUCCESS;
2558 }
2559 if (size > (reader->value_size - offset)) {
2560 size = reader->value_size - offset;
2561 }
2562 if (ETINY_P(einfo)) {
2563 grn_memcpy(buf, (char *)einfo + offset, size);
2564 } else if (EHUGE_P(einfo)) {
2565 char *buf_ptr = (char *)buf;
2566 void *seg_addr;
2567 uint32_t seg_id = reader->body_seg_id;
2568 if (offset >= io->header->segment_size) {
2569 seg_id += offset / io->header->segment_size;
2570 offset %= io->header->segment_size;
2571 }
2572 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2573 if (!seg_addr) {
2574 return GRN_UNKNOWN_ERROR;
2575 }
2576 grn_memcpy(buf_ptr, (char *)seg_addr + offset,
2577 io->header->segment_size - offset);
2578 GRN_IO_SEG_UNREF(io, seg_id);
2579 seg_id++;
2580 size -= io->header->segment_size - offset;
2581 buf_ptr += io->header->segment_size - offset;
2582 while (size > io->header->segment_size) {
2583 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2584 if (!seg_addr) {
2585 return GRN_UNKNOWN_ERROR;
2586 }
2587 grn_memcpy(buf_ptr, (char *)seg_addr, io->header->segment_size);
2588 GRN_IO_SEG_UNREF(io, seg_id);
2589 seg_id++;
2590 size -= io->header->segment_size;
2591 buf_ptr += io->header->segment_size;
2592 }
2593 GRN_IO_SEG_REF(io, seg_id, seg_addr);
2594 if (!seg_addr) {
2595 return GRN_UNKNOWN_ERROR;
2596 }
2597 grn_memcpy(buf_ptr, seg_addr, size);
2598 GRN_IO_SEG_UNREF(io, seg_id);
2599 } else {
2600 if (!reader->body_seg_addr) {
2601 GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr);
2602 if (!reader->body_seg_addr) {
2603 return GRN_UNKNOWN_ERROR;
2604 }
2605 }
2606 offset += reader->body_seg_offset;
2607 grn_memcpy(buf, (char *)reader->body_seg_addr + offset, size);
2608 }
2609 return GRN_SUCCESS;
2610}
2611
2612grn_rc
2613grn_ja_reader_pread(grn_ctx *ctx, grn_ja_reader *reader,
2614 size_t offset, size_t size, void *buf)
2615{
2616 switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) {
2617#ifdef GRN_WITH_ZLIB
2618 case GRN_OBJ_COMPRESS_ZLIB :
2619 return grn_ja_reader_pread_zlib(ctx, reader, offset, size, buf);
2620#endif /* GRN_WITH_ZLIB */
2621#ifdef GRN_WITH_LZ4
2622 case GRN_OBJ_COMPRESS_LZ4 :
2623 return grn_ja_reader_pread_lz4(ctx, reader, offset, size, buf);
2624#endif /* GRN_WITH_LZ4 */
2625#ifdef GRN_WITH_ZSTD
2626 case GRN_OBJ_COMPRESS_ZSTD :
2627 return grn_ja_reader_pread_zstd(ctx, reader, offset, size, buf);
2628#endif /* GRN_WITH_ZSTD */
2629 default :
2630 return grn_ja_reader_pread_raw(ctx, reader, offset, size, buf);
2631 }
2632}
2633
2634/**** vgram ****/
2635
2636/*
2637
2638static int len_sum = 0;
2639static int img_sum = 0;
2640static int simple_sum = 0;
2641static int skip_sum = 0;
2642
2643grn_vgram *
2644grn_vgram_create(const char *path)
2645{
2646 grn_vgram *s;
2647 if (!(s = GRN_MALLOCN(grn_vgram, 1))) { return NULL; }
2648 s->vgram = grn_sym_create(path, sizeof(grn_id) * 2, 0, GRN_ENC_NONE);
2649 if (!s->vgram) {
2650 GRN_FREE(s);
2651 return NULL;
2652 }
2653 return s;
2654}
2655
2656grn_vgram *
2657grn_vgram_open(const char *path)
2658{
2659 grn_vgram *s;
2660 if (!(s = GRN_MALLOCN(grn_vgram, 1))) { return NULL; }
2661 s->vgram = grn_sym_open(path);
2662 if (!s->vgram) {
2663 GRN_FREE(s);
2664 return NULL;
2665 }
2666 return s;
2667}
2668
2669grn_vgram_buf *
2670grn_vgram_buf_open(size_t len)
2671{
2672 grn_vgram_buf *b;
2673 if (!(b = GRN_MALLOCN(grn_vgram_buf, 1))) { return NULL; }
2674 b->len = len;
2675 b->tvs = b->tvp = GRN_MALLOCN(grn_id, len);
2676 if (!b->tvp) { GRN_FREE(b); return NULL; }
2677 b->tve = b->tvs + len;
2678 b->vps = b->vpp = GRN_MALLOCN(grn_vgram_vnode, len * 2);
2679 if (!b->vpp) { GRN_FREE(b->tvp); GRN_FREE(b); return NULL; }
2680 b->vpe = b->vps + len;
2681 return b;
2682}
2683
2684grn_rc
2685grn_vgram_buf_add(grn_vgram_buf *b, grn_id tid)
2686{
2687 uint8_t dummybuf[8], *dummyp;
2688 if (b->tvp < b->tve) { *b->tvp++ = tid; }
2689 dummyp = dummybuf;
2690 GRN_B_ENC(tid, dummyp);
2691 simple_sum += dummyp - dummybuf;
2692 return GRN_SUCCESS;
2693}
2694
2695typedef struct {
2696 grn_id vid;
2697 grn_id tid;
2698} vgram_key;
2699
2700grn_rc
2701grn_vgram_update(grn_vgram *vgram, grn_id rid, grn_vgram_buf *b, grn_hash *terms)
2702{
2703 grn_inv_updspec **u;
2704 if (b && b->tvs < b->tvp) {
2705 grn_id *t0, *tn;
2706 for (t0 = b->tvs; t0 < b->tvp - 1; t0++) {
2707 grn_vgram_vnode *v, **vp;
2708 if (grn_set_at(terms, t0, (void **) &u)) {
2709 vp = &(*u)->vnodes;
2710 for (tn = t0 + 1; tn < b->tvp; tn++) {
2711 for (v = *vp; v && v->tid != *tn; v = v->cdr) ;
2712 if (!v) {
2713 if (b->vpp < b->vpe) {
2714 v = b->vpp++;
2715 } else {
2716 // todo;
2717 break;
2718 }
2719 v->car = NULL;
2720 v->cdr = *vp;
2721 *vp = v;
2722 v->tid = *tn;
2723 v->vid = 0;
2724 v->freq = 0;
2725 v->len = tn - t0;
2726 }
2727 v->freq++;
2728 if (v->vid) {
2729 vp = &v->car;
2730 } else {
2731 break;
2732 }
2733 }
2734 }
2735 }
2736 {
2737 grn_set *th = grn_set_open(sizeof(grn_id), sizeof(int), 0);
2738 if (!th) { return GRN_NO_MEMORY_AVAILABLE; }
2739 if (t0 == b->tvp) { GRN_LOG(ctx, GRN_LOG_DEBUG, "t0 == tvp"); }
2740 for (t0 = b->tvs; t0 < b->tvp; t0++) {
2741 grn_id vid, vid0 = *t0, vid1 = 0;
2742 grn_vgram_vnode *v, *v2 = NULL, **vp;
2743 if (grn_set_at(terms, t0, (void **) &u)) {
2744 vp = &(*u)->vnodes;
2745 for (tn = t0 + 1; tn < b->tvp; tn++) {
2746 for (v = *vp; v; v = v->cdr) {
2747 if (!v->vid && (v->freq < 2 || v->freq * v->len < 4)) {
2748 *vp = v->cdr;
2749 v->freq = 0;
2750 }
2751 if (v->tid == *tn) { break; }
2752 vp = &v->cdr;
2753 }
2754 if (v) {
2755 if (v->freq) {
2756 v2 = v;
2757 vid1 = vid0;
2758 vid0 = v->vid;
2759 }
2760 if (v->vid) {
2761 vp = &v->car;
2762 continue;
2763 }
2764 }
2765 break;
2766 }
2767 }
2768 if (v2) {
2769 if (!v2->vid) {
2770 vgram_key key;
2771 key.vid = vid1;
2772 key.tid = v2->tid;
2773 if (!(v2->vid = grn_sym_get(vgram->vgram, (char *)&key))) {
2774 grn_set_close(th);
2775 return GRN_NO_MEMORY_AVAILABLE;
2776 }
2777 }
2778 vid = *t0 = v2->vid * 2 + 1;
2779 memset(t0 + 1, 0, sizeof(grn_id) * v2->len);
2780 t0 += v2->len;
2781 } else {
2782 vid = *t0 *= 2;
2783 }
2784 {
2785 int *tf;
2786 if (!grn_set_get(th, &vid, (void **) &tf)) {
2787 grn_set_close(th);
2788 return GRN_NO_MEMORY_AVAILABLE;
2789 }
2790 (*tf)++;
2791 }
2792 }
2793 if (!th->n_entries) { GRN_LOG(ctx, GRN_LOG_DEBUG, "th->n_entries == 0"); }
2794 {
2795 int j = 0;
2796 int skip = 0;
2797 grn_set_eh *ehs, *ehp, *ehe;
2798 grn_set_sort_optarg arg;
2799 uint8_t *ps = GRN_MALLOC(b->len * 2), *pp, *pe;
2800 if (!ps) {
2801 grn_set_close(th);
2802 return GRN_NO_MEMORY_AVAILABLE;
2803 }
2804 pp = ps;
2805 pe = ps + b->len * 2;
2806 arg.mode = grn_sort_descending;
2807 arg.compar = NULL;
2808 arg.compar_arg = (void *)(intptr_t)sizeof(grn_id);
2809 ehs = grn_set_sort(th, 0, &arg);
2810 if (!ehs) {
2811 GRN_FREE(ps);
2812 grn_set_close(th);
2813 return GRN_NO_MEMORY_AVAILABLE;
2814 }
2815 GRN_B_ENC(th->n_entries, pp);
2816 for (ehp = ehs, ehe = ehs + th->n_entries; ehp < ehe; ehp++, j++) {
2817 int *id = (int *)GRN_SET_INTVAL(*ehp);
2818 GRN_B_ENC(*GRN_SET_INTKEY(*ehp), pp);
2819 *id = j;
2820 }
2821 for (t0 = b->tvs; t0 < b->tvp; t0++) {
2822 if (*t0) {
2823 int *id;
2824 if (!grn_set_at(th, t0, (void **) &id)) {
2825 GRN_LOG(ctx, GRN_LOG_ERROR, "lookup error (%d)", *t0);
2826 }
2827 GRN_B_ENC(*id, pp);
2828 } else {
2829 skip++;
2830 }
2831 }
2832 len_sum += b->len;
2833 img_sum += pp - ps;
2834 skip_sum += skip;
2835 GRN_FREE(ehs);
2836 GRN_FREE(ps);
2837 }
2838 grn_set_close(th);
2839 }
2840 }
2841 return GRN_SUCCESS;
2842}
2843
2844grn_rc
2845grn_vgram_buf_close(grn_vgram_buf *b)
2846{
2847 if (!b) { return GRN_INVALID_ARGUMENT; }
2848 if (b->tvs) { GRN_FREE(b->tvs); }
2849 if (b->vps) { GRN_FREE(b->vps); }
2850 GRN_FREE(b);
2851 return GRN_SUCCESS;
2852}
2853
2854grn_rc
2855grn_vgram_close(grn_vgram *vgram)
2856{
2857 if (!vgram) { return GRN_INVALID_ARGUMENT; }
2858 GRN_LOG(ctx, GRN_LOG_DEBUG, "len=%d img=%d skip=%d simple=%d", len_sum, img_sum, skip_sum, simple_sum);
2859 grn_sym_close(vgram->vgram);
2860 GRN_FREE(vgram);
2861 return GRN_SUCCESS;
2862}
2863*/
2864