Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
store.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 2 -*- */
2 /* Copyright(C) 2009-2012 Brazil
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License version 2.1 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Lesser General Public License for more details.
12 
13  You should have received a copy of the GNU Lesser General Public
14  License along with this library; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 #include "groonga_in.h"
18 #include "str.h"
19 #include "store.h"
20 #include "ctx_impl.h"
21 #include "output.h"
22 #include <string.h>
23 
24 /* rectangular arrays */
25 
26 #define GRN_RA_SEGMENT_SIZE (1 << 22)
27 
28 static grn_ra *
29 _grn_ra_create(grn_ctx *ctx, grn_ra *ra, const char *path, unsigned int element_size)
30 {
31  grn_io *io;
32  int max_segments, n_elm, w_elm;
33  struct grn_ra_header *header;
34  unsigned int actual_size;
35  if (element_size > GRN_RA_SEGMENT_SIZE) {
36  GRN_LOG(ctx, GRN_LOG_ERROR, "element_size too large (%d)", element_size);
37  return NULL;
38  }
39  for (actual_size = 1; actual_size < element_size; actual_size *= 2) ;
40  max_segments = ((GRN_ID_MAX + 1) / GRN_RA_SEGMENT_SIZE) * actual_size;
41  io = grn_io_create(ctx, path, sizeof(struct grn_ra_header),
42  GRN_RA_SEGMENT_SIZE, max_segments, grn_io_auto,
44  if (!io) { return NULL; }
45  header = grn_io_header(io);
47  header->element_size = actual_size;
48  n_elm = GRN_RA_SEGMENT_SIZE / header->element_size;
49  for (w_elm = 22; (1 << w_elm) > n_elm; w_elm--);
50  ra->io = io;
51  ra->header = header;
52  ra->element_mask = n_elm - 1;
53  ra->element_width = w_elm;
54  return ra;
55 }
56 
57 grn_ra *
58 grn_ra_create(grn_ctx *ctx, const char *path, unsigned int element_size)
59 {
60  grn_ra *ra = NULL;
61  if (!(ra = GRN_GMALLOC(sizeof(grn_ra)))) {
62  return NULL;
63  }
65  if (!_grn_ra_create(ctx, ra, path, element_size)) {
66  GRN_FREE(ra);
67  return NULL;
68  }
69  return ra;
70 }
71 
72 grn_ra *
73 grn_ra_open(grn_ctx *ctx, const char *path)
74 {
75  grn_io *io;
76  int n_elm, w_elm;
77  grn_ra *ra = NULL;
78  struct grn_ra_header *header;
79  io = grn_io_open(ctx, path, grn_io_auto);
80  if (!io) { return NULL; }
81  header = grn_io_header(io);
83  ERR(GRN_INVALID_FORMAT, "file type unmatch");
84  grn_io_close(ctx, io);
85  return NULL;
86  }
87  if (!(ra = GRN_GMALLOC(sizeof(grn_ra)))) {
88  grn_io_close(ctx, io);
89  return NULL;
90  }
91  n_elm = GRN_RA_SEGMENT_SIZE / header->element_size;
92  for (w_elm = 22; (1 << w_elm) > n_elm; w_elm--);
94  ra->io = io;
95  ra->header = header;
96  ra->element_mask = n_elm - 1;
97  ra->element_width = w_elm;
98  return ra;
99 }
100 
101 grn_rc
102 grn_ra_info(grn_ctx *ctx, grn_ra *ra, unsigned int *element_size)
103 {
104  if (!ra) { return GRN_INVALID_ARGUMENT; }
105  if (element_size) { *element_size = ra->header->element_size; }
106  return GRN_SUCCESS;
107 }
108 
109 grn_rc
111 {
112  grn_rc rc;
113  if (!ra) { return GRN_INVALID_ARGUMENT; }
114  rc = grn_io_close(ctx, ra->io);
115  GRN_GFREE(ra);
116  return rc;
117 }
118 
119 grn_rc
120 grn_ra_remove(grn_ctx *ctx, const char *path)
121 {
122  if (!path) { return GRN_INVALID_ARGUMENT; }
123  return grn_io_remove(ctx, path);
124 }
125 
126 grn_rc
128 {
129  grn_rc rc;
130  const char *io_path;
131  char *path;
132  unsigned int element_size;
133  if ((io_path = grn_io_path(ra->io)) && *io_path != '\0') {
134  if (!(path = GRN_STRDUP(io_path))) {
135  ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path);
137  }
138  } else {
139  path = NULL;
140  }
141  element_size = ra->header->element_size;
142  if ((rc = grn_io_close(ctx, ra->io))) { goto exit; }
143  ra->io = NULL;
144  if (path && (rc = grn_io_remove(ctx, path))) { goto exit; }
145  if (!_grn_ra_create(ctx, ra, path, element_size)) {
146  rc = GRN_UNKNOWN_ERROR;
147  }
148 exit:
149  if (path) { GRN_FREE(path); }
150  return rc;
151 }
152 
153 void *
155 {
156  void *p = NULL;
157  uint16_t seg;
158  if (id > GRN_ID_MAX) { return NULL; }
159  seg = id >> ra->element_width;
160  GRN_IO_SEG_REF(ra->io, seg, p);
161  if (!p) { return NULL; }
162  return (void *)(((byte *)p) + ((id & ra->element_mask) * ra->header->element_size));
163 }
164 
165 grn_rc
167 {
168  uint16_t seg;
169  if (id > GRN_ID_MAX) { return GRN_INVALID_ARGUMENT; }
170  seg = id >> ra->element_width;
171  GRN_IO_SEG_UNREF(ra->io, seg);
172  return GRN_SUCCESS;
173 }
174 
175 void *
177 {
178  void *p = NULL;
179  uint16_t seg;
180  if (id > GRN_ID_MAX) { return NULL; }
181  seg = id >> ra->element_width;
182  if (seg == cache->seg) {
183  p = cache->p;
184  } else {
185  if (cache->seg != -1) { GRN_IO_SEG_UNREF(ra->io, cache->seg); }
186  GRN_IO_SEG_REF(ra->io, seg, p);
187  cache->seg = seg;
188  cache->p = p;
189  }
190  if (!p) { return NULL; }
191  return (void *)(((byte *)p) + ((id & ra->element_mask) * ra->header->element_size));
192 }
193 
194 grn_rc
196 {
197  uint16_t seg;
198  if (id > GRN_ID_MAX) { return GRN_INVALID_ARGUMENT; }
199  seg = id >> ra->element_width;
200  GRN_IO_SEG_UNREF(ra->io, seg);
201  return GRN_SUCCESS;
202 }
203 
204 /**** jagged arrays ****/
205 
206 #define GRN_JA_W_SEGREGATE_THRESH 7
207 #define GRN_JA_W_CAPACITY 38
208 #define GRN_JA_W_SEGMENT 22
209 
210 #define JA_ESEG_VOID (0xffffffffU)
211 #define JA_SEGMENT_SIZE (1U << GRN_JA_W_SEGMENT)
212 #define JA_W_EINFO 3
213 #define JA_W_SEGMENTS_MAX (GRN_JA_W_CAPACITY - GRN_JA_W_SEGMENT)
214 #define JA_W_EINFO_IN_A_SEGMENT (GRN_JA_W_SEGMENT - JA_W_EINFO)
215 #define JA_N_EINFO_IN_A_SEGMENT (1U << JA_W_EINFO_IN_A_SEGMENT)
216 #define JA_M_EINFO_IN_A_SEGMENT (JA_N_EINFO_IN_A_SEGMENT - 1)
217 #define JA_N_GARBAGES_IN_A_SEGMENT ((1U << (GRN_JA_W_SEGMENT - 3)) - 2)
218 #define JA_N_ELEMENT_VARIATION (GRN_JA_W_SEGREGATE_THRESH - JA_W_EINFO + 1)
219 #define JA_N_DSEGMENTS (1U << JA_W_SEGMENTS_MAX)
220 #define JA_N_ESEGMENTS (1U << (GRN_ID_WIDTH - JA_W_EINFO_IN_A_SEGMENT))
221 
223 
225  union {
226  struct {
227  uint16_t seg;
228  uint16_t pos;
229  uint16_t size;
230  uint8_t c1;
231  uint8_t c2;
232  } n;
233  struct {
234  uint32_t size;
235  uint16_t seg;
236  uint8_t c1;
237  uint8_t c2;
238  } h;
239  uint8_t c[8];
240  } u;
241 };
242 
243 #define ETINY (0x80)
244 #define EHUGE (0x40)
245 #define ETINY_P(e) ((e)->u.c[7] & ETINY)
246 #define ETINY_ENC(e,_size) ((e)->u.c[7] = (_size) + ETINY)
247 #define ETINY_DEC(e,_size) ((_size) = (e)->u.c[7] & ~(ETINY|EHUGE))
248 #define EHUGE_P(e) ((e)->u.c[7] & EHUGE)
249 #define EHUGE_ENC(e,_seg,_size) do {\
250  (e)->u.h.c1 = 0;\
251  (e)->u.h.c2 = EHUGE;\
252  (e)->u.h.seg = (_seg);\
253  (e)->u.h.size = (_size);\
254 } while (0)
255 #define EHUGE_DEC(e,_seg,_size) do {\
256  (_seg) = (e)->u.h.seg;\
257  (_size) = (e)->u.h.size;\
258 } while (0)
259 #define EINFO_ENC(e,_seg,_pos,_size) do {\
260  (e)->u.n.c1 = (_pos) >> 16;\
261  (e)->u.n.c2 = ((_size) >> 16);\
262  (e)->u.n.seg = (_seg);\
263  (e)->u.n.pos = (_pos);\
264  (e)->u.n.size = (_size);\
265 } while (0)
266 #define EINFO_DEC(e,_seg,_pos,_size) do {\
267  (_seg) = (e)->u.n.seg;\
268  (_pos) = ((e)->u.n.c1 << 16) + (e)->u.n.pos;\
269  (_size) = ((e)->u.n.c2 << 16) + (e)->u.n.size;\
270 } while (0)
271 
272 typedef struct {
273  uint32_t seg;
274  uint32_t pos;
275 } ja_pos;
276 
277 typedef struct {
278  uint32_t head;
279  uint32_t tail;
280  uint32_t nrecs;
281  uint32_t next;
283 } grn_ja_ginfo;
284 
286  uint32_t flags;
287  uint32_t curr_seg;
288  uint32_t curr_pos;
295 };
296 
297 #define SEG_SEQ (0x10000000U)
298 #define SEG_HUGE (0x20000000U)
299 #define SEG_EINFO (0x30000000U)
300 #define SEG_GINFO (0x40000000U)
301 #define SEG_MASK (0xf0000000U)
302 
303 #define SEGMENTS_AT(ja,seg) ((ja)->header->dsegs[seg])
304 #define SEGMENTS_SEGRE_ON(ja,seg,width) (SEGMENTS_AT(ja,seg) = width)
305 #define SEGMENTS_SEQ_ON(ja,seg) (SEGMENTS_AT(ja,seg) = SEG_SEQ)
306 #define SEGMENTS_HUGE_ON(ja,seg) (SEGMENTS_AT(ja,seg) = SEG_HUGE)
307 #define SEGMENTS_EINFO_ON(ja,seg,lseg) (SEGMENTS_AT(ja,seg) = SEG_EINFO|(lseg))
308 #define SEGMENTS_GINFO_ON(ja,seg,width) (SEGMENTS_AT(ja,seg) = SEG_GINFO|(width))
309 #define SEGMENTS_OFF(ja,seg) (SEGMENTS_AT(ja,seg) = 0)
310 
312 
313 static grn_ja *
314 _grn_ja_create(grn_ctx *ctx, grn_ja *ja, const char *path,
315  unsigned int max_element_size, uint32_t flags)
316 {
317  int i;
318  grn_io *io;
319  struct grn_ja_header *header;
320  io = grn_io_create(ctx, path, sizeof(struct grn_ja_header),
323  if (!io) { return NULL; }
325  header = grn_io_header(io);
326  header->curr_pos = JA_SEGMENT_SIZE;
327  header->flags = flags;
328  for (i = 0; i < JA_N_ESEGMENTS; i++) { header->esegs[i] = JA_ESEG_VOID; }
329  ja->io = io;
330  ja->header = header;
332  SEGMENTS_EINFO_ON(ja, 0, 0);
333  header->esegs[0] = 0;
334  return ja;
335 }
336 
337 grn_ja *
338 grn_ja_create(grn_ctx *ctx, const char *path, unsigned int max_element_size, uint32_t flags)
339 {
340  grn_ja *ja = NULL;
341  if (!(ja = GRN_GMALLOC(sizeof(grn_ja)))) {
342  return NULL;
343  }
345  if (!_grn_ja_create(ctx, ja, path, max_element_size, flags)) {
346  GRN_FREE(ja);
347  return NULL;
348  }
349  return ja;
350 }
351 
352 grn_ja *
353 grn_ja_open(grn_ctx *ctx, const char *path)
354 {
355  grn_io *io;
356  grn_ja *ja = NULL;
357  struct grn_ja_header *header;
358  io = grn_io_open(ctx, path, grn_io_auto);
359  if (!io) { return NULL; }
360  header = grn_io_header(io);
362  ERR(GRN_INVALID_FORMAT, "file type unmatch");
363  grn_io_close(ctx, io);
364  return NULL;
365  }
366  if (!(ja = GRN_GMALLOC(sizeof(grn_ja)))) {
367  grn_io_close(ctx, io);
368  return NULL;
369  }
371  ja->io = io;
372  ja->header = header;
373  return ja;
374 }
375 
376 grn_rc
377 grn_ja_info(grn_ctx *ctx, grn_ja *ja, unsigned int *max_element_size)
378 {
379  if (!ja) { return GRN_INVALID_ARGUMENT; }
380  if (max_element_size) { *max_element_size = ja->header->max_element_size; }
381  return GRN_SUCCESS;
382 }
383 
384 grn_rc
386 {
387  grn_rc rc;
388  if (!ja) { return GRN_INVALID_ARGUMENT; }
389  rc = grn_io_close(ctx, ja->io);
390  GRN_GFREE(ja);
391  return rc;
392 }
393 
394 grn_rc
395 grn_ja_remove(grn_ctx *ctx, const char *path)
396 {
397  if (!path) { return GRN_INVALID_ARGUMENT; }
398  return grn_io_remove(ctx, path);
399 }
400 
401 grn_rc
403 {
404  grn_rc rc;
405  const char *io_path;
406  char *path;
407  unsigned int max_element_size;
408  uint32_t flags;
409  if ((io_path = grn_io_path(ja->io)) && *io_path != '\0') {
410  if (!(path = GRN_STRDUP(io_path))) {
411  ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path);
413  }
414  } else {
415  path = NULL;
416  }
417  max_element_size = ja->header->max_element_size;
418  flags = ja->header->flags;
419  if ((rc = grn_io_close(ctx, ja->io))) { goto exit; }
420  ja->io = NULL;
421  if (path && (rc = grn_io_remove(ctx, path))) { goto exit; }
422  if (!_grn_ja_create(ctx, ja, path, max_element_size, flags)) {
423  rc = GRN_UNKNOWN_ERROR;
424  }
425 exit:
426  if (path) { GRN_FREE(path); }
427  return rc;
428 }
429 
430 static void *
431 grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
432 {
433  uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
434  iw->size = 0;
435  iw->addr = NULL;
436  iw->pseg = pseg;
437  if (pseg != JA_ESEG_VOID) {
438  grn_ja_einfo *einfo = NULL;
439  GRN_IO_SEG_REF(ja->io, pseg, einfo);
440  if (einfo) {
441  grn_ja_einfo *ei = &einfo[id & JA_M_EINFO_IN_A_SEGMENT];
442  if (ETINY_P(ei)) {
443  iw->tiny_p = 1;
444  ETINY_DEC(ei, iw->size);
445  iw->io = ja->io;
446  iw->ctx = ctx;
447  iw->addr = (void *)ei;
448  } else {
449  uint32_t jag, vpos, vsize;
450  iw->tiny_p = 0;
451  if (EHUGE_P(ei)) {
452  EHUGE_DEC(ei, jag, vsize);
453  vpos = 0;
454  } else {
455  EINFO_DEC(ei, jag, vpos, vsize);
456  }
457  grn_io_win_map2(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly);
458  }
459  if (!iw->addr) { GRN_IO_SEG_UNREF(ja->io, pseg); }
460  }
461  }
462  *value_len = iw->size;
463  return iw->addr;
464 }
465 
466 grn_rc
468 {
469  if (!iw->addr) { return GRN_INVALID_ARGUMENT; }
470  GRN_IO_SEG_UNREF(iw->io, iw->pseg);
471  if (!iw->tiny_p) { grn_io_win_unmap2(iw); }
472  return GRN_SUCCESS;
473 }
474 
475 #define DELETED 0x80000000
476 
477 static grn_rc
478 grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo)
479 {
480  grn_ja_ginfo *ginfo = NULL;
481  uint32_t seg, pos, element_size, aligned_size, m, *gseg;
482  if (ETINY_P(einfo)) { return GRN_SUCCESS; }
483  if (EHUGE_P(einfo)) {
484  uint32_t n;
485  EHUGE_DEC(einfo, seg, element_size);
486  n = ((element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT);
487  for (; n--; seg++) { SEGMENTS_OFF(ja, seg); }
488  return GRN_SUCCESS;
489  }
490  EINFO_DEC(einfo, seg, pos, element_size);
491  if (!element_size) { return GRN_SUCCESS; }
492  {
493  int es = element_size - 1;
494  GRN_BIT_SCAN_REV(es, m);
495  m++;
496  }
497  if (m > GRN_JA_W_SEGREGATE_THRESH) {
498  byte *addr = NULL;
499  GRN_IO_SEG_REF(ja->io, seg, addr);
500  if (!addr) { return GRN_NO_MEMORY_AVAILABLE; }
501  aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
502  *(uint32_t *)(addr + pos - sizeof(grn_id)) = DELETED|aligned_size;
503  if (SEGMENTS_AT(ja, seg) < (aligned_size + sizeof(grn_id)) + SEG_SEQ) {
504  GRN_LOG(ctx, GRN_WARN, "inconsistent ja entry detected (%d > %d)",
505  element_size, SEGMENTS_AT(ja, seg) - SEG_SEQ);
506  }
507  SEGMENTS_AT(ja, seg) -= (aligned_size + sizeof(grn_id));
508  if (SEGMENTS_AT(ja, seg) == SEG_SEQ) {
509  /* reuse the segment */
510  SEGMENTS_OFF(ja, seg);
511  if (seg == ja->header->curr_seg) {
513  }
514  }
515  GRN_IO_SEG_UNREF(ja->io, seg);
516  } else {
517  uint32_t lseg = 0, lseg_;
518  gseg = &ja->header->garbages[m - JA_W_EINFO];
519  while ((lseg_ = *gseg)) {
520  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
521  GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
522  if (!ginfo) {
524  }
525  lseg = lseg_;
526  if (ginfo->nrecs < JA_N_GARBAGES_IN_A_SEGMENT) { break; }
527  gseg = &ginfo->next;
528  }
529  if (!lseg_) {
530  uint32_t i = 0;
531  while (SEGMENTS_AT(ja, i)) {
532  if (++i >= JA_N_DSEGMENTS) {
533  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
535  }
536  }
537  SEGMENTS_GINFO_ON(ja, i, m - JA_W_EINFO);
538  *gseg = i;
539  lseg_ = *gseg;
540  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
541  GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
542  lseg = lseg_;
543  if (!ginfo) {
545  }
546  ginfo->head = 0;
547  ginfo->tail = 0;
548  ginfo->nrecs = 0;
549  ginfo->next = 0;
550  }
551  ginfo->recs[ginfo->head].seg = seg;
552  ginfo->recs[ginfo->head].pos = pos;
553  if (++ginfo->head == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->head = 0; }
554  ginfo->nrecs++;
555  ja->header->ngarbages[m - JA_W_EINFO]++;
556  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
557  }
558  return GRN_SUCCESS;
559 }
560 
561 grn_rc
563  grn_ja_einfo *ei, uint64_t *cas)
564 {
565  grn_rc rc = GRN_SUCCESS;
566  uint32_t lseg, *pseg, pos;
567  grn_ja_einfo *einfo = NULL, eback;
568  lseg = id >> JA_W_EINFO_IN_A_SEGMENT;
569  pos = id & JA_M_EINFO_IN_A_SEGMENT;
570  pseg = &ja->header->esegs[lseg];
571  if (grn_io_lock(ctx, ja->io, 10000000)) {
572  return ctx->rc;
573  }
574  if (*pseg == JA_ESEG_VOID) {
575  int i = 0;
576  while (SEGMENTS_AT(ja, i)) {
577  if (++i >= JA_N_DSEGMENTS) {
578  ERR(GRN_NOT_ENOUGH_SPACE, "grn_ja file (%s) is full", ja->io->path);
580  goto exit;
581  }
582  }
583  SEGMENTS_EINFO_ON(ja, i, lseg);
584  GRN_IO_SEG_REF(ja->io, i, einfo);
585  if (einfo) {
586  *pseg = i;
587  memset(einfo, 0, JA_SEGMENT_SIZE);
588  }
589  } else {
590  GRN_IO_SEG_REF(ja->io, *pseg, einfo);
591  }
592  if (!einfo) {
594  goto exit;
595  }
596  eback = einfo[pos];
597  if (cas && *cas != *((uint64_t *)&eback)) {
598  ERR(GRN_CAS_ERROR, "cas failed (%d)", id);
599  GRN_IO_SEG_UNREF(ja->io, *pseg);
600  rc = GRN_CAS_ERROR;
601  goto exit;
602  }
603  // smb_wmb();
604  {
605  uint64_t *location = (uint64_t *)(einfo + pos);
606  uint64_t value = *((uint64_t *)ei);
607  GRN_SET_64BIT(location, value);
608  }
609  GRN_IO_SEG_UNREF(ja->io, *pseg);
610  grn_ja_free(ctx, ja, &eback);
611 exit :
612  grn_io_unlock(ja->io);
613  return rc;
614 }
615 
616 #define JA_N_GARBAGES_TH 10
617 
618 // todo : grn_io_win_map2 cause verbose copy when nseg > 1, it should be copied directly.
619 static grn_rc
620 grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id,
621  uint32_t element_size, grn_ja_einfo *einfo, grn_io_win *iw)
622 {
623  byte *addr = NULL;
624  iw->io = ja->io;
625  iw->ctx = ctx;
626  iw->cached = 1;
627  if (element_size < 8) {
628  ETINY_ENC(einfo, element_size);
629  iw->tiny_p = 1;
630  iw->addr = (void *)einfo;
631  return GRN_SUCCESS;
632  }
633  iw->tiny_p = 0;
634  if (grn_io_lock(ctx, ja->io, 10000000)) { return ctx->rc; }
635  if (element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) {
636  int i, j, n = (element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT;
637  for (i = 0, j = -1; i < JA_N_DSEGMENTS; i++) {
638  if (SEGMENTS_AT(ja, i)) {
639  j = i;
640  } else {
641  if (i == j + n) {
642  j++;
643  addr = grn_io_win_map2(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly);
644  if (!addr) {
645  grn_io_unlock(ja->io);
647  }
648  EHUGE_ENC(einfo, j, element_size);
649  for (; j <= i; j++) { SEGMENTS_HUGE_ON(ja, j); }
650  grn_io_unlock(ja->io);
651  return GRN_SUCCESS;
652  }
653  }
654  }
655  GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. requested element_size=%d.", element_size);
656  grn_io_unlock(ja->io);
658  } else {
659  ja_pos *vp;
660  int m, aligned_size, es = element_size - 1;
661  GRN_BIT_SCAN_REV(es, m);
662  m++;
663  if (m > GRN_JA_W_SEGREGATE_THRESH) {
664  uint32_t seg = ja->header->curr_seg, pos = ja->header->curr_pos;
665  if (pos + element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) {
666  seg = 0;
667  while (SEGMENTS_AT(ja, seg)) {
668  if (++seg >= JA_N_DSEGMENTS) {
669  grn_io_unlock(ja->io);
670  GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. seg=%d.", seg);
671  return GRN_NOT_ENOUGH_SPACE;
672  }
673  }
674  SEGMENTS_SEQ_ON(ja, seg);
675  ja->header->curr_seg = seg;
676  pos = 0;
677  }
678  GRN_IO_SEG_REF(ja->io, seg, addr);
679  if (!addr) {
680  grn_io_unlock(ja->io);
682  }
683  *(grn_id *)(addr + pos) = id;
684  aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
685  if (pos + aligned_size < JA_SEGMENT_SIZE) {
686  *(grn_id *)(addr + pos + aligned_size) = GRN_ID_NIL;
687  }
688  SEGMENTS_AT(ja, seg) += aligned_size + sizeof(grn_id);
689  pos += sizeof(grn_id);
690  EINFO_ENC(einfo, seg, pos, element_size);
691  iw->segment = seg;
692  iw->addr = addr + pos;
693  ja->header->curr_pos = pos + aligned_size;
694  grn_io_unlock(ja->io);
695  return GRN_SUCCESS;
696  } else {
697  uint32_t lseg = 0, lseg_;
698  aligned_size = 1 << m;
699  if (ja->header->ngarbages[m - JA_W_EINFO] > JA_N_GARBAGES_TH) {
700  grn_ja_ginfo *ginfo = NULL;
701  uint32_t seg, pos, *gseg;
702  gseg = &ja->header->garbages[m - JA_W_EINFO];
703  while ((lseg_ = *gseg)) {
704  GRN_IO_SEG_REF(ja->io, lseg_, ginfo);
705  if (!ginfo) {
706  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
707  grn_io_unlock(ja->io);
709  }
710  if (ginfo->next || ginfo->nrecs > JA_N_GARBAGES_TH) {
711  seg = ginfo->recs[ginfo->tail].seg;
712  pos = ginfo->recs[ginfo->tail].pos;
713  GRN_IO_SEG_REF(ja->io, seg, addr);
714  if (!addr) {
715  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
716  GRN_IO_SEG_UNREF(ja->io, lseg_);
717  grn_io_unlock(ja->io);
719  }
720  EINFO_ENC(einfo, seg, pos, element_size);
721  iw->segment = seg;
722  iw->addr = addr + pos;
723  if (++ginfo->tail == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->tail = 0; }
724  ginfo->nrecs--;
725  ja->header->ngarbages[m - JA_W_EINFO]--;
726  if (!ginfo->nrecs) {
727  SEGMENTS_OFF(ja, *gseg);
728  *gseg = ginfo->next;
729  }
730  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
731  GRN_IO_SEG_UNREF(ja->io, lseg_);
732  grn_io_unlock(ja->io);
733  return GRN_SUCCESS;
734  }
735  if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); }
736  if (!ginfo->next) {
737  GRN_IO_SEG_UNREF(ja->io, lseg_);
738  break;
739  }
740  lseg = lseg_;
741  gseg = &ginfo->next;
742  }
743  }
744  vp = &ja->header->free_elements[m - JA_W_EINFO];
745  if (!vp->seg) {
746  int i = 0;
747  while (SEGMENTS_AT(ja, i)) {
748  if (++i >= JA_N_DSEGMENTS) {
749  grn_io_unlock(ja->io);
751  }
752  }
753  SEGMENTS_SEGRE_ON(ja, i, m);
754  vp->seg = i;
755  vp->pos = 0;
756  }
757  }
758  EINFO_ENC(einfo, vp->seg, vp->pos, element_size);
759  GRN_IO_SEG_REF(ja->io, vp->seg, addr);
760  if (!addr) {
761  grn_io_unlock(ja->io);
763  }
764  iw->segment = vp->seg;
765  iw->addr = addr + vp->pos;
766  if ((vp->pos += aligned_size) == JA_SEGMENT_SIZE) {
767  vp->seg = 0;
768  vp->pos = 0;
769  }
770  grn_io_unlock(ja->io);
771  return GRN_SUCCESS;
772  }
773 }
774 
775 static grn_rc
776 set_value(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
777  grn_ja_einfo *einfo)
778 {
779  grn_rc rc = GRN_SUCCESS;
780  grn_io_win iw;
781  if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
782  value_len >= ja->header->max_element_size) {
783  if ((rc = grn_ja_alloc(ctx, ja, id, value_len + sizeof(uint32_t), einfo, &iw))) {
784  return rc;
785  }
786  memcpy(iw.addr, value, value_len);
787  memset((byte *)iw.addr + value_len, 0, sizeof(uint32_t));
788  grn_io_win_unmap2(&iw);
789  } else {
790  if ((rc = grn_ja_alloc(ctx, ja, id, value_len, einfo, &iw))) { return rc; }
791  memcpy(iw.addr, value, value_len);
792  grn_io_win_unmap2(&iw);
793  }
794  return rc;
795 }
796 
797 grn_rc
799  void *value, uint32_t value_len, int flags, uint64_t *cas)
800 {
801  int rc;
802  int64_t buf;
803  grn_io_win iw;
804  grn_ja_einfo einfo;
805 
807  (flags & GRN_OBJ_SET_MASK) == GRN_OBJ_SET &&
808  value_len > 0) {
809  grn_io_win jw;
810  uint32_t old_len;
811  void *old_value;
812  grn_bool same_value = GRN_FALSE;
813 
814  old_value = grn_ja_ref(ctx, ja, id, &jw, &old_len);
815  if (value_len == old_len && memcmp(value, old_value, value_len) == 0) {
816  same_value = GRN_TRUE;
817  }
818  grn_ja_unref(ctx, &jw);
819  if (same_value) {
820  return GRN_SUCCESS;
821  }
822  }
823 
824  switch (flags & GRN_OBJ_SET_MASK) {
825  case GRN_OBJ_APPEND :
826  if (value_len) {
827  grn_io_win jw;
828  uint32_t old_len;
829  void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
830  if (oldvalue) {
831  if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
832  old_len + value_len >= ja->header->max_element_size) {
833  if (old_len >= ja->header->max_element_size) {
834  byte *b = oldvalue;
835  uint32_t el = old_len - sizeof(uint32_t);
836  uint32_t pos = *((uint32_t *)(b + el));
837  GRN_ASSERT(pos < el);
838  if (el <= pos + value_len) {
839  uint32_t rest = el - pos;
840  memcpy(b + pos, value, rest);
841  memcpy(b, (byte *)value + rest, value_len - rest);
842  *((uint32_t *)(b + el)) = value_len - rest;
843  } else {
844  memcpy(b + pos, value, value_len);
845  *((uint32_t *)(b + el)) = pos + value_len;
846  }
847  return GRN_SUCCESS;
848  } else {
849  if ((rc = grn_ja_alloc(ctx, ja, id,
850  value_len + old_len + sizeof(uint32_t),
851  &einfo, &iw))) {
852  grn_ja_unref(ctx, &jw);
853  return rc;
854  }
855  memcpy(iw.addr, oldvalue, old_len);
856  memcpy((byte *)iw.addr + old_len, value, value_len);
857  memset((byte *)iw.addr + old_len + value_len, 0, sizeof(uint32_t));
858  grn_io_win_unmap2(&iw);
859  }
860  } else {
861  if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
862  grn_ja_unref(ctx, &jw);
863  return rc;
864  }
865  memcpy(iw.addr, oldvalue, old_len);
866  memcpy((byte *)iw.addr + old_len, value, value_len);
867  grn_io_win_unmap2(&iw);
868  }
869  grn_ja_unref(ctx, &jw);
870  } else {
871  set_value(ctx, ja, id, value, value_len, &einfo);
872  }
873  }
874  break;
875  case GRN_OBJ_PREPEND :
876  if (value_len) {
877  grn_io_win jw;
878  uint32_t old_len;
879  void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
880  if (oldvalue) {
881  if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
882  old_len + value_len >= ja->header->max_element_size) {
883  if (old_len >= ja->header->max_element_size) {
884  byte *b = oldvalue;
885  uint32_t el = old_len - sizeof(uint32_t);
886  uint32_t pos = *((uint32_t *)(b + el));
887  GRN_ASSERT(pos < el);
888  if (pos < value_len) {
889  uint32_t rest = value_len - pos;
890  memcpy(b, (byte *)value + rest, pos);
891  memcpy(b + el - rest, value, rest);
892  *((uint32_t *)(b + el)) = el - rest;
893  } else {
894  memcpy(b + pos - value_len, value, value_len);
895  *((uint32_t *)(b + el)) = pos - value_len;
896  }
897  return GRN_SUCCESS;
898  } else {
899  if ((rc = grn_ja_alloc(ctx, ja, id,
900  value_len + old_len + sizeof(uint32_t),
901  &einfo, &iw))) {
902  grn_ja_unref(ctx, &jw);
903  return rc;
904  }
905  memcpy(iw.addr, value, value_len);
906  memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
907  memset((byte *)iw.addr + value_len + old_len, 0, sizeof(uint32_t));
908  grn_io_win_unmap2(&iw);
909  }
910  } else {
911  if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) {
912  grn_ja_unref(ctx, &jw);
913  return rc;
914  }
915  memcpy(iw.addr, value, value_len);
916  memcpy((byte *)iw.addr + value_len, oldvalue, old_len);
917  grn_io_win_unmap2(&iw);
918  }
919  grn_ja_unref(ctx, &jw);
920  } else {
921  set_value(ctx, ja, id, value, value_len, &einfo);
922  }
923  }
924  break;
925  case GRN_OBJ_DECR :
926  if (value_len == sizeof(int64_t)) {
927  int64_t *v = (int64_t *)&buf;
928  *v = -(*(int64_t *)value);
929  value = v;
930  } else if (value_len == sizeof(int32_t)) {
931  int32_t *v = (int32_t *)&buf;
932  *v = -(*(int32_t *)value);
933  value = v;
934  } else {
935  return GRN_INVALID_ARGUMENT;
936  }
937  /* fallthru */
938  case GRN_OBJ_INCR :
939  {
940  grn_io_win jw;
941  uint32_t old_len;
942  void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len);
943  if (oldvalue && old_len) {
945  if (old_len == sizeof(int64_t) && value_len == sizeof(int64_t)) {
946  (*(int64_t *)oldvalue) += (*(int64_t *)value);
947  rc = GRN_SUCCESS;
948  } else if (old_len == sizeof(int32_t) && value_len == sizeof(int32_t)) {
949  (*(int32_t *)oldvalue) += (*(int32_t *)value);
950  rc = GRN_SUCCESS;
951  }
952  grn_ja_unref(ctx, &jw);
953  return rc;
954  }
955  }
956  /* fallthru */
957  case GRN_OBJ_SET :
958  if (value_len) {
959  set_value(ctx, ja, id, value, value_len, &einfo);
960  } else {
961  memset(&einfo, 0, sizeof(grn_ja_einfo));
962  }
963  break;
964  default :
965  ERR(GRN_INVALID_ARGUMENT, "grn_ja_put_raw called with illegal flags value");
966  return GRN_INVALID_ARGUMENT;
967  }
968  if ((rc = grn_ja_replace(ctx, ja, id, &einfo, cas))) {
969  if (!grn_io_lock(ctx, ja->io, 10000000)) {
970  grn_ja_free(ctx, ja, &einfo);
971  grn_io_unlock(ja->io);
972  }
973  }
974  return rc;
975 }
976 
977 grn_rc
978 grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *vector, int flags)
979 {
980  grn_obj header, footer;
981  grn_rc rc = GRN_SUCCESS;
982  grn_section *vp;
983  int i, f = 0, n = grn_vector_size(ctx, vector);
984  GRN_TEXT_INIT(&header, 0);
985  GRN_TEXT_INIT(&footer, 0);
986  grn_text_benc(ctx, &header, n);
987  for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) {
988  grn_text_benc(ctx, &header, vp->length);
989  if (vp->weight || vp->domain) { f = 1; }
990  }
991  if (f) {
992  for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) {
993  grn_text_benc(ctx, &footer, vp->weight);
994  grn_text_benc(ctx, &footer, vp->domain);
995  }
996  }
997  {
998  grn_io_win iw;
999  grn_ja_einfo einfo;
1000  grn_obj *body = vector->u.v.body;
1001  size_t sizeh = GRN_BULK_VSIZE(&header);
1002  size_t sizev = body ? GRN_BULK_VSIZE(body) : 0;
1003  size_t sizef = GRN_BULK_VSIZE(&footer);
1004  if ((rc = grn_ja_alloc(ctx, ja, id, sizeh + sizev + sizef, &einfo, &iw))) { goto exit; }
1005  memcpy(iw.addr, GRN_BULK_HEAD(&header), sizeh);
1006  if (body) { memcpy((char *)iw.addr + sizeh, GRN_BULK_HEAD(body), sizev); }
1007  if (f) { memcpy((char *)iw.addr + sizeh + sizev, GRN_BULK_HEAD(&footer), sizef); }
1008  grn_io_win_unmap2(&iw);
1009  rc = grn_ja_replace(ctx, ja, id, &einfo, NULL);
1010  }
1011 exit :
1012  GRN_OBJ_FIN(ctx, &footer);
1013  GRN_OBJ_FIN(ctx, &header);
1014  return rc;
1015 }
1016 
1017 uint32_t
1019 {
1020  grn_ja_einfo *einfo = NULL, *ei;
1021  uint32_t lseg, *pseg, pos, size;
1022  lseg = id >> JA_W_EINFO_IN_A_SEGMENT;
1023  pos = id & JA_M_EINFO_IN_A_SEGMENT;
1024  pseg = &ja->header->esegs[lseg];
1025  if (*pseg == JA_ESEG_VOID) {
1026  ctx->rc = GRN_INVALID_ARGUMENT;
1027  return 0;
1028  }
1029  GRN_IO_SEG_REF(ja->io, *pseg, einfo);
1030  if (!einfo) {
1031  ctx->rc = GRN_NO_MEMORY_AVAILABLE;
1032  return 0;
1033  }
1034  ei = &einfo[pos];
1035  if (ETINY_P(ei)) {
1036  ETINY_DEC(ei, size);
1037  } else {
1038  if (EHUGE_P(ei)) {
1039  size = ei->u.h.size;
1040  } else {
1041  size = (ei->u.n.c2 << 16) + ei->u.n.size;
1042  }
1043  }
1044  GRN_IO_SEG_UNREF(ja->io, *pseg);
1045  return size;
1046 }
1047 
1048 grn_rc
1050  uint64_t *cas, uint32_t *pos, uint32_t *size)
1051 {
1052  uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT];
1053  if (pseg == JA_ESEG_VOID) {
1054  return GRN_INVALID_ARGUMENT;
1055  } else {
1056  grn_ja_einfo *einfo = NULL;
1057  GRN_IO_SEG_REF(ja->io, pseg, einfo);
1058  if (einfo) {
1059  grn_ja_einfo *ei;
1060  *cas = *((uint64_t *)&einfo[id & JA_M_EINFO_IN_A_SEGMENT]);
1061  ei = (grn_ja_einfo *)cas;
1062  if (ETINY_P(ei)) {
1063  ETINY_DEC(ei, *size);
1064  *pos = 0;
1065  } else {
1066  uint32_t jag;
1067  if (EHUGE_P(ei)) {
1068  EHUGE_DEC(ei, jag, *size);
1069  *pos = 0;
1070  } else {
1071  EINFO_DEC(ei, jag, *pos, *size);
1072  }
1073  }
1074  GRN_IO_SEG_UNREF(ja->io, pseg);
1075  } else {
1076  return GRN_INVALID_ARGUMENT;
1077  }
1078  }
1079  return GRN_SUCCESS;
1080 }
1081 
1082 #ifdef GRN_WITH_ZLIB
1083 #include <zlib.h>
1084 
1085 static void *
1086 grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1087 {
1088  /* TODO: This function leaks a memory. The return value
1089  * must be freed. */
1090  z_stream zstream;
1091  void *value, *zvalue;
1092  uint32_t zvalue_len;
1093  if (!(zvalue = grn_ja_ref_raw(ctx, ja, id, iw, &zvalue_len))) {
1094  *value_len = 0;
1095  return NULL;
1096  }
1097  zstream.next_in = (Bytef *)(((uint64_t *)zvalue) + 1);
1098  zstream.avail_in = zvalue_len + sizeof(uint64_t);
1099  zstream.zalloc = Z_NULL;
1100  zstream.zfree = Z_NULL;
1101  if (inflateInit2(&zstream, 15 /* windowBits */) != Z_OK) {
1102  *value_len = 0;
1103  return NULL;
1104  }
1105  if (!(value = GRN_MALLOC(*((uint64_t *)zvalue)))) {
1106  inflateEnd(&zstream);
1107  *value_len = 0;
1108  return NULL;
1109  }
1110  zstream.next_out = (Bytef *)value;
1111  zstream.avail_out = *(uint64_t *)zvalue;
1112  if (inflate(&zstream, Z_FINISH) != Z_STREAM_END) {
1113  inflateEnd(&zstream);
1114  GRN_FREE(value);
1115  *value_len = 0;
1116  return NULL;
1117  }
1118  *value_len = zstream.total_out;
1119  if (inflateEnd(&zstream) != Z_OK) {
1120  GRN_FREE(value);
1121  *value_len = 0;
1122  return NULL;
1123  }
1124  return value;
1125 }
1126 #endif /* GRN_WITH_ZLIB */
1127 
1128 #ifdef GRN_WITH_LZO
1129 #include <lzo/lzo1x.h>
1130 
1131 static void *
1132 grn_ja_ref_lzo(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1133 {
1134  /* TODO: This function leaks a memory. The return value
1135  * must be freed. */
1136  void *value, *lvalue;
1137  uint32_t lvalue_len;
1138  lzo_uint lout_len;
1139  if (!(lvalue = grn_ja_ref_raw(ctx, ja, id, iw, &lvalue_len))) {
1140  *value_len = 0;
1141  return NULL;
1142  }
1143  if (!(value = GRN_MALLOC(*((uint64_t *)lvalue)))) {
1144  *value_len = 0;
1145  return NULL;
1146  }
1147  lout_len = *((uint64_t *)lvalue);
1148  switch (lzo1x_decompress((lzo_bytep)(((uint64_t *)lvalue) + 1),
1149  lvalue_len,
1150  (lzo_bytep)(value),
1151  &lout_len,
1152  NULL)) {
1153  case LZO_E_OK :
1154  case LZO_E_INPUT_NOT_CONSUMED :
1155  break;
1156  default :
1157  GRN_FREE(value);
1158  *value_len = 0;
1159  return NULL;
1160  }
1161  *value_len = lout_len;
1162  return value;
1163 }
1164 #endif /* GRN_WITH_LZO */
1165 
1166 void *
1167 grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len)
1168 {
1169 #ifdef GRN_WITH_ZLIB
1170  if (ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) {
1171  return grn_ja_ref_zlib(ctx, ja, id, iw, value_len);
1172  }
1173 #endif /* GRN_WITH_ZLIB */
1174 #ifdef GRN_WITH_LZO
1175  if (ja->header->flags & GRN_OBJ_COMPRESS_LZO) {
1176  return grn_ja_ref_lzo(ctx, ja, id, iw, value_len);
1177  }
1178 #endif /* GRN_WITH_LZO */
1179  return grn_ja_ref_raw(ctx, ja, id, iw, value_len);
1180 }
1181 
1182 grn_obj *
1184 {
1185  void *v;
1186  uint32_t len;
1187  grn_io_win iw;
1188  if (!value) {
1189  if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) {
1190  ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed");
1191  goto exit;
1192  }
1193  }
1194  if ((v = grn_ja_ref(ctx, ja, id, &iw, &len))) {
1195  if ((ja->header->flags & GRN_OBJ_RING_BUFFER) &&
1196  len > ja->header->max_element_size) {
1197  byte *b = v;
1198  uint32_t el = len - sizeof(uint32_t);
1199  uint32_t pos = *((uint32_t *)(b + el));
1200  GRN_ASSERT(pos < el);
1201  grn_bulk_write(ctx, value, (char *)(b + pos), el - pos);
1202  grn_bulk_write(ctx, value, (char *)(b), pos);
1203  } else {
1204  grn_bulk_write(ctx, value, v, len);
1205  }
1206  grn_ja_unref(ctx, &iw);
1207  }
1208 exit :
1209  return value;
1210 }
1211 
1212 #ifdef GRN_WITH_ZLIB
1213 inline static grn_rc
1214 grn_ja_put_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id,
1215  void *value, uint32_t value_len, int flags, uint64_t *cas)
1216 {
1217  grn_rc rc;
1218  z_stream zstream;
1219  void *zvalue;
1220  int zvalue_len;
1221 
1222  if (value_len == 0) {
1223  return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1224  }
1225 
1226  zstream.next_in = value;
1227  zstream.avail_in = value_len;
1228  zstream.zalloc = Z_NULL;
1229  zstream.zfree = Z_NULL;
1230  if (deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
1231  15 /* windowBits */,
1232  8 /* memLevel */,
1233  Z_DEFAULT_STRATEGY) != Z_OK) {
1234  ERR(GRN_ZLIB_ERROR, "deflateInit2 failed");
1235  return ctx->rc;
1236  }
1237  zvalue_len = deflateBound(&zstream, value_len);
1238  if (!(zvalue = GRN_MALLOC(zvalue_len + sizeof(uint64_t)))) { deflateEnd(&zstream); return GRN_NO_MEMORY_AVAILABLE; }
1239  zstream.next_out = (Bytef *)(((uint64_t *)zvalue) + 1);
1240  zstream.avail_out = zvalue_len;
1241  if (deflate(&zstream, Z_FINISH) != Z_STREAM_END) {
1242  deflateEnd(&zstream);
1243  GRN_FREE(zvalue);
1244  ERR(GRN_ZLIB_ERROR, "deflate failed");
1245  return ctx->rc;
1246  }
1247  zvalue_len = zstream.total_out;
1248  if (deflateEnd(&zstream) != Z_OK) {
1249  GRN_FREE(zvalue);
1250  ERR(GRN_ZLIB_ERROR, "deflateEnd failed");
1251  return ctx->rc;
1252  }
1253  *(uint64_t *)zvalue = value_len;
1254  rc = grn_ja_put_raw(ctx, ja, id, zvalue, zvalue_len + sizeof(uint64_t), flags, cas);
1255  GRN_FREE(zvalue);
1256  return rc;
1257 }
1258 #endif /* GRN_WITH_ZLIB */
1259 
1260 #ifdef GRN_WITH_LZO
1261 inline static grn_rc
1262 grn_ja_put_lzo(grn_ctx *ctx, grn_ja *ja, grn_id id,
1263  void *value, uint32_t value_len, int flags, uint64_t *cas)
1264 {
1265  grn_rc rc;
1266  void *lvalue, *lwork;
1267  lzo_uint lvalue_len = value_len + value_len / 16 + 64 + 3;
1268 
1269  if (value_len == 0) {
1270  return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1271  }
1272 
1273  if (!(lvalue = GRN_MALLOC(lvalue_len + sizeof(uint64_t)))) { return GRN_NO_MEMORY_AVAILABLE; }
1274  if (!(lwork = GRN_MALLOC(LZO1X_1_MEM_COMPRESS))) { GRN_FREE(lvalue); return GRN_NO_MEMORY_AVAILABLE; }
1275  if (lzo1x_1_compress(value, value_len, (lzo_bytep)((uint64_t *)lvalue + 1), &lvalue_len, lwork) != LZO_E_OK) {
1276  GRN_FREE(lwork);
1277  GRN_FREE(lvalue);
1278  ERR(GRN_LZO_ERROR, "lzo1x_1_compress");
1279  return ctx->rc;
1280  }
1281  GRN_FREE(lwork);
1282  *(uint64_t *)lvalue = value_len;
1283  rc = grn_ja_put_raw(ctx, ja, id, lvalue, lvalue_len + sizeof(uint64_t), flags, cas);
1284  GRN_FREE(lvalue);
1285  return rc;
1286 }
1287 #endif /* GRN_WITH_LZO */
1288 
1289 grn_rc
1290 grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len,
1291  int flags, uint64_t *cas)
1292 {
1293 #ifdef GRN_WITH_ZLIB
1294  if (ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) {
1295  return grn_ja_put_zlib(ctx, ja, id, value, value_len, flags, cas);
1296  }
1297 #endif /* GRN_WITH_ZLIB */
1298 #ifdef GRN_WITH_LZO
1299  if (ja->header->flags & GRN_OBJ_COMPRESS_LZO) {
1300  return grn_ja_put_lzo(ctx, ja, id, value, value_len, flags, cas);
1301  }
1302 #endif /* GRN_WITH_LZO */
1303  return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas);
1304 }
1305 
1306 static grn_rc
1307 grn_ja_defrag_seg(grn_ctx *ctx, grn_ja *ja, uint32_t seg)
1308 {
1309  byte *v = NULL, *ve;
1310  uint32_t element_size, cum = 0, *seginfo = &SEGMENTS_AT(ja,seg), sum;
1311  sum = (*seginfo & ~SEG_MASK);
1312  GRN_IO_SEG_REF(ja->io, seg, v);
1313  if (!v) { return GRN_NO_MEMORY_AVAILABLE; }
1314  ve = v + JA_SEGMENT_SIZE;
1315  while (v < ve && cum < sum) {
1316  grn_id id = *((grn_id *)v);
1317  if (!id) { break; }
1318  if (id & DELETED) {
1319  element_size = (id & ~DELETED);
1320  } else {
1321  uint64_t cas;
1322  uint32_t pos;
1323  if (grn_ja_element_info(ctx, ja, id, &cas, &pos, &element_size)) { break; }
1324  if (v + sizeof(uint32_t) != ve - JA_SEGMENT_SIZE + pos) {
1325  GRN_LOG(ctx, GRN_LOG_WARNING,
1326  "dseges[%d] = pos unmatch (%d != %" GRN_FMT_LLD ")",
1327  seg, pos, (long long int)(v + sizeof(uint32_t) + JA_SEGMENT_SIZE - ve));
1328  break;
1329  }
1330  if (grn_ja_put(ctx, ja, id, v + sizeof(uint32_t), element_size, GRN_OBJ_SET, &cas)) {
1331  GRN_LOG(ctx, GRN_LOG_WARNING,
1332  "dseges[%d] = put failed (%d)", seg, id);
1333  break;
1334  }
1335  element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
1336  cum += sizeof(uint32_t) + element_size;
1337  }
1338  v += sizeof(uint32_t) + element_size;
1339  }
1340  if (*seginfo) {
1341  GRN_LOG(ctx, GRN_LOG_WARNING, "dseges[%d] = %d after defrag", seg, (*seginfo & ~SEG_MASK));
1342  }
1343  GRN_IO_SEG_UNREF(ja->io, seg);
1344  return GRN_SUCCESS;
1345 }
1346 
1347 int
1348 grn_ja_defrag(grn_ctx *ctx, grn_ja *ja, int threshold)
1349 {
1350  int nsegs = 0;
1351  uint32_t seg, ts = 1U << (GRN_JA_W_SEGMENT - threshold);
1352  for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
1353  if (seg == ja->header->curr_seg) { continue; }
1354  if (((SEGMENTS_AT(ja, seg) & SEG_MASK) == SEG_SEQ) &&
1355  ((SEGMENTS_AT(ja, seg) & ~SEG_MASK) < ts)) {
1356  if (!grn_ja_defrag_seg(ctx, ja, seg)) { nsegs++; }
1357  }
1358  }
1359  return nsegs;
1360 }
1361 
1362 void
1364 {
1365  char buf[8];
1366  uint32_t seg;
1367  struct grn_ja_header *h = ja->header;
1368  GRN_OUTPUT_ARRAY_OPEN("RESULT", 8);
1369  GRN_OUTPUT_MAP_OPEN("SUMMARY", 8);
1370  GRN_OUTPUT_CSTR("flags");
1371  grn_itoh(h->flags, buf, 8);
1372  GRN_OUTPUT_STR(buf, 8);
1373  GRN_OUTPUT_CSTR("curr seg");
1375  GRN_OUTPUT_CSTR("curr pos");
1377  GRN_OUTPUT_CSTR("max_element_size");
1380  GRN_OUTPUT_ARRAY_OPEN("DETAIL", -1);
1381  for (seg = 0; seg < JA_N_DSEGMENTS; seg++) {
1382  int dseg = SEGMENTS_AT(ja, seg);
1383  if (dseg) {
1384  GRN_OUTPUT_MAP_OPEN("SEG", -1);
1385  GRN_OUTPUT_CSTR("seg id");
1386  GRN_OUTPUT_INT64(seg);
1387  GRN_OUTPUT_CSTR("seg type");
1388  GRN_OUTPUT_INT64((dseg & SEG_MASK)>>28);
1389  GRN_OUTPUT_CSTR("seg value");
1390  GRN_OUTPUT_INT64(dseg & ~SEG_MASK);
1391  if ((dseg & SEG_MASK) == SEG_SEQ) {
1392  byte *v = NULL, *ve;
1393  uint32_t element_size, cum = 0, sum = dseg & ~SEG_MASK;
1394  uint32_t n_del_elements = 0, n_elements = 0, s_del_elements = 0, s_elements = 0;
1395  GRN_IO_SEG_REF(ja->io, seg, v);
1396  if (v) {
1397  /*
1398  GRN_OUTPUT_CSTR("seg seq");
1399  GRN_OUTPUT_ARRAY_OPEN("SEQ", -1);
1400  */
1401  ve = v + JA_SEGMENT_SIZE;
1402  while (v < ve && cum < sum) {
1403  grn_id id = *((grn_id *)v);
1404  /*
1405  GRN_OUTPUT_MAP_OPEN("ENTRY", -1);
1406  GRN_OUTPUT_CSTR("id");
1407  GRN_OUTPUT_INT64(id);
1408  */
1409  if (!id) { break; }
1410  if (id & DELETED) {
1411  element_size = (id & ~DELETED);
1412  n_del_elements++;
1413  s_del_elements += element_size;
1414  } else {
1415  element_size = grn_ja_size(ctx, ja, id);
1416  element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1);
1417  cum += sizeof(uint32_t) + element_size;
1418  n_elements++;
1419  s_elements += sizeof(uint32_t) + element_size;
1420  }
1421  v += sizeof(uint32_t) + element_size;
1422  /*
1423  GRN_OUTPUT_CSTR("size");
1424  GRN_OUTPUT_INT64(element_size);
1425  GRN_OUTPUT_CSTR("cum");
1426  GRN_OUTPUT_INT64(cum);
1427  GRN_OUTPUT_MAP_CLOSE();
1428  */
1429  }
1430  GRN_IO_SEG_UNREF(ja->io, seg);
1431  /*
1432  GRN_OUTPUT_ARRAY_CLOSE();
1433  */
1434  GRN_OUTPUT_CSTR("n_elements");
1435  GRN_OUTPUT_INT64(n_elements);
1436  GRN_OUTPUT_CSTR("s_elements");
1437  GRN_OUTPUT_INT64(s_elements);
1438  GRN_OUTPUT_CSTR("n_del_elements");
1439  GRN_OUTPUT_INT64(n_del_elements);
1440  GRN_OUTPUT_CSTR("s_del_elements");
1441  GRN_OUTPUT_INT64(s_del_elements);
1442  if (cum != sum) {
1443  GRN_OUTPUT_CSTR("cum gap");
1444  GRN_OUTPUT_INT64(cum - sum);
1445  }
1446  }
1447  }
1449  }
1450  }
1453 }
1454 
1455 /**** vgram ****/
1456 
1457 /*
1458 
1459 static int len_sum = 0;
1460 static int img_sum = 0;
1461 static int simple_sum = 0;
1462 static int skip_sum = 0;
1463 
1464 grn_vgram *
1465 grn_vgram_create(const char *path)
1466 {
1467  grn_vgram *s;
1468  if (!(s = GRN_GMALLOC(sizeof(grn_vgram)))) { return NULL; }
1469  s->vgram = grn_sym_create(path, sizeof(grn_id) * 2, 0, GRN_ENC_NONE);
1470  if (!s->vgram) {
1471  GRN_GFREE(s);
1472  return NULL;
1473  }
1474  return s;
1475 }
1476 
1477 grn_vgram *
1478 grn_vgram_open(const char *path)
1479 {
1480  grn_vgram *s;
1481  if (!(s = GRN_GMALLOC(sizeof(grn_vgram)))) { return NULL; }
1482  s->vgram = grn_sym_open(path);
1483  if (!s->vgram) {
1484  GRN_GFREE(s);
1485  return NULL;
1486  }
1487  return s;
1488 }
1489 
1490 grn_vgram_buf *
1491 grn_vgram_buf_open(size_t len)
1492 {
1493  grn_vgram_buf *b;
1494  if (!(b = GRN_GMALLOC(sizeof(grn_vgram_buf)))) { return NULL; }
1495  b->len = len;
1496  b->tvs = b->tvp = GRN_GMALLOC(sizeof(grn_id) * len);
1497  if (!b->tvp) { GRN_GFREE(b); return NULL; }
1498  b->tve = b->tvs + len;
1499  b->vps = b->vpp = GRN_GMALLOC(sizeof(grn_vgram_vnode) * len * 2);
1500  if (!b->vpp) { GRN_GFREE(b->tvp); GRN_GFREE(b); return NULL; }
1501  b->vpe = b->vps + len;
1502  return b;
1503 }
1504 
1505 grn_rc
1506 grn_vgram_buf_add(grn_vgram_buf *b, grn_id tid)
1507 {
1508  uint8_t dummybuf[8], *dummyp;
1509  if (b->tvp < b->tve) { *b->tvp++ = tid; }
1510  dummyp = dummybuf;
1511  GRN_B_ENC(tid, dummyp);
1512  simple_sum += dummyp - dummybuf;
1513  return GRN_SUCCESS;
1514 }
1515 
1516 typedef struct {
1517  grn_id vid;
1518  grn_id tid;
1519 } vgram_key;
1520 
1521 grn_rc
1522 grn_vgram_update(grn_vgram *vgram, grn_id rid, grn_vgram_buf *b, grn_hash *terms)
1523 {
1524  grn_inv_updspec **u;
1525  if (b && b->tvs < b->tvp) {
1526  grn_id *t0, *tn;
1527  for (t0 = b->tvs; t0 < b->tvp - 1; t0++) {
1528  grn_vgram_vnode *v, **vp;
1529  if (grn_set_at(terms, t0, (void **) &u)) {
1530  vp = &(*u)->vnodes;
1531  for (tn = t0 + 1; tn < b->tvp; tn++) {
1532  for (v = *vp; v && v->tid != *tn; v = v->cdr) ;
1533  if (!v) {
1534  if (b->vpp < b->vpe) {
1535  v = b->vpp++;
1536  } else {
1537  // todo;
1538  break;
1539  }
1540  v->car = NULL;
1541  v->cdr = *vp;
1542  *vp = v;
1543  v->tid = *tn;
1544  v->vid = 0;
1545  v->freq = 0;
1546  v->len = tn - t0;
1547  }
1548  v->freq++;
1549  if (v->vid) {
1550  vp = &v->car;
1551  } else {
1552  break;
1553  }
1554  }
1555  }
1556  }
1557  {
1558  grn_set *th = grn_set_open(sizeof(grn_id), sizeof(int), 0);
1559  if (!th) { return GRN_NO_MEMORY_AVAILABLE; }
1560  if (t0 == b->tvp) { GRN_LOG(ctx, GRN_LOG_DEBUG, "t0 == tvp"); }
1561  for (t0 = b->tvs; t0 < b->tvp; t0++) {
1562  grn_id vid, vid0 = *t0, vid1 = 0;
1563  grn_vgram_vnode *v, *v2 = NULL, **vp;
1564  if (grn_set_at(terms, t0, (void **) &u)) {
1565  vp = &(*u)->vnodes;
1566  for (tn = t0 + 1; tn < b->tvp; tn++) {
1567  for (v = *vp; v; v = v->cdr) {
1568  if (!v->vid && (v->freq < 2 || v->freq * v->len < 4)) {
1569  *vp = v->cdr;
1570  v->freq = 0;
1571  }
1572  if (v->tid == *tn) { break; }
1573  vp = &v->cdr;
1574  }
1575  if (v) {
1576  if (v->freq) {
1577  v2 = v;
1578  vid1 = vid0;
1579  vid0 = v->vid;
1580  }
1581  if (v->vid) {
1582  vp = &v->car;
1583  continue;
1584  }
1585  }
1586  break;
1587  }
1588  }
1589  if (v2) {
1590  if (!v2->vid) {
1591  vgram_key key;
1592  key.vid = vid1;
1593  key.tid = v2->tid;
1594  if (!(v2->vid = grn_sym_get(vgram->vgram, (char *)&key))) {
1595  grn_set_close(th);
1596  return GRN_NO_MEMORY_AVAILABLE;
1597  }
1598  }
1599  vid = *t0 = v2->vid * 2 + 1;
1600  memset(t0 + 1, 0, sizeof(grn_id) * v2->len);
1601  t0 += v2->len;
1602  } else {
1603  vid = *t0 *= 2;
1604  }
1605  {
1606  int *tf;
1607  if (!grn_set_get(th, &vid, (void **) &tf)) {
1608  grn_set_close(th);
1609  return GRN_NO_MEMORY_AVAILABLE;
1610  }
1611  (*tf)++;
1612  }
1613  }
1614  if (!th->n_entries) { GRN_LOG(ctx, GRN_LOG_DEBUG, "th->n_entries == 0"); }
1615  {
1616  int j = 0;
1617  int skip = 0;
1618  grn_set_eh *ehs, *ehp, *ehe;
1619  grn_set_sort_optarg arg;
1620  uint8_t *ps = GRN_GMALLOC(b->len * 2), *pp, *pe;
1621  if (!ps) {
1622  grn_set_close(th);
1623  return GRN_NO_MEMORY_AVAILABLE;
1624  }
1625  pp = ps;
1626  pe = ps + b->len * 2;
1627  arg.mode = grn_sort_descending;
1628  arg.compar = NULL;
1629  arg.compar_arg = (void *)(intptr_t)sizeof(grn_id);
1630  ehs = grn_set_sort(th, 0, &arg);
1631  if (!ehs) {
1632  GRN_GFREE(ps);
1633  grn_set_close(th);
1634  return GRN_NO_MEMORY_AVAILABLE;
1635  }
1636  GRN_B_ENC(th->n_entries, pp);
1637  for (ehp = ehs, ehe = ehs + th->n_entries; ehp < ehe; ehp++, j++) {
1638  int *id = (int *)GRN_SET_INTVAL(*ehp);
1639  GRN_B_ENC(*GRN_SET_INTKEY(*ehp), pp);
1640  *id = j;
1641  }
1642  for (t0 = b->tvs; t0 < b->tvp; t0++) {
1643  if (*t0) {
1644  int *id;
1645  if (!grn_set_at(th, t0, (void **) &id)) {
1646  GRN_LOG(ctx, GRN_LOG_ERROR, "lookup error (%d)", *t0);
1647  }
1648  GRN_B_ENC(*id, pp);
1649  } else {
1650  skip++;
1651  }
1652  }
1653  len_sum += b->len;
1654  img_sum += pp - ps;
1655  skip_sum += skip;
1656  GRN_GFREE(ehs);
1657  GRN_GFREE(ps);
1658  }
1659  grn_set_close(th);
1660  }
1661  }
1662  return GRN_SUCCESS;
1663 }
1664 
1665 grn_rc
1666 grn_vgram_buf_close(grn_vgram_buf *b)
1667 {
1668  if (!b) { return GRN_INVALID_ARGUMENT; }
1669  if (b->tvs) { GRN_GFREE(b->tvs); }
1670  if (b->vps) { GRN_GFREE(b->vps); }
1671  GRN_GFREE(b);
1672  return GRN_SUCCESS;
1673 }
1674 
1675 grn_rc
1676 grn_vgram_close(grn_vgram *vgram)
1677 {
1678  if (!vgram) { return GRN_INVALID_ARGUMENT; }
1679  GRN_LOG(ctx, GRN_LOG_DEBUG, "len=%d img=%d skip=%d simple=%d", len_sum, img_sum, skip_sum, simple_sum);
1680  grn_sym_close(vgram->vgram);
1681  GRN_GFREE(vgram);
1682  return GRN_SUCCESS;
1683 }
1684 */