Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ii.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 <stdio.h>
19 #include <fcntl.h>
20 #include <string.h>
21 #include <sys/stat.h>
22 
23 #include "ii.h"
24 #include "ctx_impl.h"
25 #include "token.h"
26 #include "pat.h"
27 #include "db.h"
28 #include "output.h"
29 #include "util.h"
30 
31 #define MAX_PSEG 0x20000
32 #define S_CHUNK (1 << GRN_II_W_CHUNK)
33 #define W_SEGMENT 18
34 #define S_SEGMENT (1 << W_SEGMENT)
35 #define N_CHUNKS_PER_FILE (GRN_IO_FILE_SIZE >> W_SEGMENT)
36 #define W_ARRAY_ELEMENT 3
37 #define S_ARRAY_ELEMENT (1 << W_ARRAY_ELEMENT)
38 #define W_ARRAY (W_SEGMENT - W_ARRAY_ELEMENT)
39 #define ARRAY_MASK_IN_A_SEGMENT ((1 << W_ARRAY) - 1)
40 #define NOT_ASSIGNED 0xffffffff
41 
42 #define S_GARBAGE (1<<12)
43 
44 #define CHUNK_SPLIT 0x80000000
45 #define CHUNK_SPLIT_THRESHOLD 0x60000
46 
47 #define MAX_N_ELEMENTS 5
48 
49 #define LSEG(pos) ((pos) >> 16)
50 #define LPOS(pos) (((pos) & 0xffff) << 2)
51 #define SEG2POS(seg,pos) ((((uint32_t)(seg)) << 16) + (((uint32_t)(pos)) >> 2))
52 
53 #define NEXT_ADDR(p) (((byte *)(p)) + sizeof(*(p)))
54 
55 #ifndef S_IRUSR
56 # define S_IRUSR 0400
57 #endif /* S_IRUSR */
58 #ifndef S_IWUSR
59 # define S_IWUSR 0200
60 #endif /* S_IWUSR */
61 
62 /* segment */
63 
64 inline static uint32_t
65 segment_get(grn_ctx *ctx, grn_ii *ii)
66 {
67  uint32_t pseg;
68  if (ii->header->bgqtail == ((ii->header->bgqhead + 1) & (GRN_II_BGQSIZE - 1))) {
69  pseg = ii->header->bgqbody[ii->header->bgqtail];
70  ii->header->bgqtail = (ii->header->bgqtail + 1) & (GRN_II_BGQSIZE - 1);
71  } else {
72  pseg = ii->header->pnext;
73 #ifndef CUT_OFF_COMPATIBILITY
74  if (!pseg) {
75  int i;
76  uint32_t pmax = 0;
77  char *used = GRN_CALLOC(MAX_PSEG);
78  if (!used) { return MAX_PSEG; }
79  for (i = 0; i < GRN_II_MAX_LSEG; i++) {
80  if ((pseg = ii->header->ainfo[i]) != NOT_ASSIGNED) {
81  if (pseg > pmax) { pmax = pseg; }
82  used[pseg] = 1;
83  }
84  if ((pseg = ii->header->binfo[i]) != NOT_ASSIGNED) {
85  if (pseg > pmax) { pmax = pseg; }
86  used[pseg] = 1;
87  }
88  }
89  for (pseg = 0; used[pseg] && pseg < MAX_PSEG; pseg++) ;
90  GRN_FREE(used);
91  ii->header->pnext = pmax + 1;
92  } else
93 #endif /* CUT_OFF_COMPATIBILITY */
94  if (ii->header->pnext < MAX_PSEG) { ii->header->pnext++; }
95  }
96  return pseg;
97 }
98 
99 inline static grn_rc
100 segment_get_clear(grn_ctx *ctx, grn_ii *ii, uint32_t *pseg)
101 {
102  uint32_t seg = segment_get(ctx, ii);
103  if (seg < MAX_PSEG) {
104  void *p = NULL;
105  GRN_IO_SEG_REF(ii->seg, seg, p);
106  if (!p) { return GRN_NO_MEMORY_AVAILABLE; }
107  memset(p, 0, S_SEGMENT);
108  GRN_IO_SEG_UNREF(ii->seg, seg);
109  *pseg = seg;
110  return GRN_SUCCESS;
111  } else {
113  }
114 }
115 
116 inline static grn_rc
117 buffer_segment_new(grn_ctx *ctx, grn_ii *ii, uint32_t *segno)
118 {
119  uint32_t lseg, pseg;
120  if (*segno < GRN_II_MAX_LSEG) {
121  if (ii->header->binfo[*segno] != NOT_ASSIGNED) {
122  return GRN_INVALID_ARGUMENT;
123  }
124  lseg = *segno;
125  } else {
126  for (lseg = 0; lseg < GRN_II_MAX_LSEG; lseg++) {
127  if (ii->header->binfo[lseg] == NOT_ASSIGNED) { break; }
128  }
129  if (lseg == GRN_II_MAX_LSEG) { return GRN_NO_MEMORY_AVAILABLE; }
130  *segno = lseg;
131  }
132  pseg = segment_get(ctx, ii);
133  if (pseg < MAX_PSEG) {
134  ii->header->binfo[lseg] = pseg;
135  if (lseg >= ii->header->bmax) { ii->header->bmax = lseg + 1; }
136  return GRN_SUCCESS;
137  } else {
139  }
140 }
141 
142 static grn_rc
143 buffer_segment_reserve(grn_ctx *ctx, grn_ii *ii,
144  uint32_t *lseg0, uint32_t *pseg0,
145  uint32_t *lseg1, uint32_t *pseg1)
146 {
147  uint32_t i = 0;
148  for (;; i++) {
149  if (i == GRN_II_MAX_LSEG) { return GRN_NO_MEMORY_AVAILABLE; }
150  if (ii->header->binfo[i] == NOT_ASSIGNED) { break; }
151  }
152  *lseg0 = i++;
153  for (;; i++) {
154  if (i == GRN_II_MAX_LSEG) { return GRN_NO_MEMORY_AVAILABLE; }
155  if (ii->header->binfo[i] == NOT_ASSIGNED) { break; }
156  }
157  *lseg1 = i;
158  if ((*pseg0 = segment_get(ctx, ii)) == MAX_PSEG) { return GRN_NO_MEMORY_AVAILABLE; }
159  if ((*pseg1 = segment_get(ctx, ii)) == MAX_PSEG) { return GRN_NO_MEMORY_AVAILABLE; }
160  /*
161  {
162  uint32_t pseg;
163  char *used = GRN_CALLOC(MAX_PSEG);
164  if (!used) { return GRN_NO_MEMORY_AVAILABLE; }
165  for (i = 0; i < GRN_II_MAX_LSEG; i++) {
166  if ((pseg = ii->header->ainfo[i]) != NOT_ASSIGNED) { used[pseg] = 1; }
167  if ((pseg = ii->header->binfo[i]) != NOT_ASSIGNED) { used[pseg] = 1; }
168  }
169  for (pseg = 0;; pseg++) {
170  if (pseg == MAX_PSEG) { GRN_FREE(used); return GRN_NO_MEMORY_AVAILABLE; }
171  if (!used[pseg]) { break; }
172  }
173  *pseg0 = pseg++;
174  for (;; pseg++) {
175  if (pseg == MAX_PSEG) { GRN_FREE(used); return GRN_NO_MEMORY_AVAILABLE; }
176  if (!used[pseg]) { break; }
177  }
178  *pseg1 = pseg;
179  GRN_FREE(used);
180  }
181  */
182  return GRN_SUCCESS;
183 }
184 
185 #define BGQENQUE(lseg) do {\
186  if (ii->header->binfo[lseg] != NOT_ASSIGNED) {\
187  ii->header->bgqbody[ii->header->bgqhead] = ii->header->binfo[lseg];\
188  ii->header->bgqhead = (ii->header->bgqhead + 1) & (GRN_II_BGQSIZE - 1);\
189  GRN_ASSERT(ii->header->bgqhead != ii->header->bgqtail);\
190  }\
191 } while (0)
192 
193 inline static void
194 buffer_segment_update(grn_ii *ii, uint32_t lseg, uint32_t pseg)
195 {
196  BGQENQUE(lseg);
197  // smb_wmb();
198  ii->header->binfo[lseg] = pseg;
199  if (lseg >= ii->header->bmax) { ii->header->bmax = lseg + 1; }
200 }
201 
202 inline static void
203 buffer_segment_clear(grn_ii *ii, uint32_t lseg)
204 {
205  BGQENQUE(lseg);
206  // smb_wmb();
207  ii->header->binfo[lseg] = NOT_ASSIGNED;
208 }
209 
210 /* chunk */
211 
212 #define HEADER_CHUNK_AT(ii,offset) \
213  ((((ii)->header->chunks[((offset) >> 3)]) >> ((offset) & 7)) & 1)
214 
215 #define HEADER_CHUNK_ON(ii,offset) \
216  (((ii)->header->chunks[((offset) >> 3)]) |= (1 << ((offset) & 7)))
217 
218 #define HEADER_CHUNK_OFF(ii,offset) \
219  (((ii)->header->chunks[((offset) >> 3)]) &= ~(1 << ((offset) & 7)))
220 
221 #define N_GARBAGES_TH 1
222 
223 #define N_GARBAGES ((S_GARBAGE - (sizeof(uint32_t) * 4))/(sizeof(uint32_t)))
224 
225 typedef struct {
226  uint32_t head;
227  uint32_t tail;
228  uint32_t nrecs;
229  uint32_t next;
230  uint32_t recs[N_GARBAGES];
231 } grn_ii_ginfo;
232 
233 #define WIN_MAP2(chunk,ctx,iw,seg,pos,size,mode)\
234  grn_io_win_map2(chunk, ctx, iw,\
235  ((seg) >> GRN_II_N_CHUNK_VARIATION),\
236  (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK) + (pos),\
237  size,mode)
238 /*
239 static int new_histogram[32];
240 static int free_histogram[32];
241 */
242 static grn_rc
243 chunk_new(grn_ctx *ctx, grn_ii *ii, uint32_t *res, uint32_t size)
244 {
245  /*
246  if (size) {
247  int m, es = size - 1;
248  GRN_BIT_SCAN_REV(es, m);
249  m++;
250  new_histogram[m]++;
251  }
252  */
253  if (size > S_CHUNK) {
254  int i, j;
255  uint32_t n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK;
256  for (i = 0, j = -1; i < GRN_II_MAX_CHUNK; i++) {
257  if (HEADER_CHUNK_AT(ii, i)) {
258  j = i;
259  } else {
260  if (i == j + n) {
261  j++;
262  *res = j << GRN_II_N_CHUNK_VARIATION;
263  for (; j <= i; j++) { HEADER_CHUNK_ON(ii, j); }
264  return GRN_SUCCESS;
265  }
266  }
267  }
268  GRN_LOG(ctx, GRN_LOG_CRIT, "index full. requested chunk_size=%d.", size);
270  } else {
271  uint32_t *vp;
272  int m, aligned_size;
273  if (size > (1 << GRN_II_W_LEAST_CHUNK)) {
274  int es = size - 1;
275  GRN_BIT_SCAN_REV(es, m);
276  m++;
277  } else {
279  }
280  aligned_size = 1 << (m - GRN_II_W_LEAST_CHUNK);
282  grn_ii_ginfo *ginfo;
283  uint32_t *gseg;
284  grn_io_win iw, iw_;
285  iw_.addr = NULL;
286  gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK];
287  while (*gseg != NOT_ASSIGNED) {
288  ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
289  //GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo);
290  if (!ginfo) {
291  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
293  }
294  if (ginfo->next != NOT_ASSIGNED || ginfo->nrecs > N_GARBAGES_TH) {
295  *res = ginfo->recs[ginfo->tail];
296  if (++ginfo->tail == N_GARBAGES) { ginfo->tail = 0; }
297  ginfo->nrecs--;
299  if (!ginfo->nrecs) {
300  HEADER_CHUNK_OFF(ii, *gseg);
301  *gseg = ginfo->next;
302  }
303  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
304  grn_io_win_unmap2(&iw);
305  return GRN_SUCCESS;
306  }
307  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
308  iw_ = iw;
309  gseg = &ginfo->next;
310  }
311  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
312  }
313  vp = &ii->header->free_chunks[m - GRN_II_W_LEAST_CHUNK];
314  if (*vp == NOT_ASSIGNED) {
315  int i = 0;
316  while (HEADER_CHUNK_AT(ii, i)) {
317  if (++i >= GRN_II_MAX_CHUNK) { return GRN_NO_MEMORY_AVAILABLE; }
318  }
319  HEADER_CHUNK_ON(ii, i);
320  *vp = i << GRN_II_N_CHUNK_VARIATION;
321  }
322  *res = *vp;
323  *vp += 1 << (m - GRN_II_W_LEAST_CHUNK);
324  if (!(*vp & ((1 << GRN_II_N_CHUNK_VARIATION) - 1))) {
325  *vp = NOT_ASSIGNED;
326  }
327  return GRN_SUCCESS;
328  }
329 }
330 
331 static grn_rc
332 chunk_free(grn_ctx *ctx, grn_ii *ii, uint32_t offset, uint32_t dummy, uint32_t size)
333 {
334  /*
335  if (size) {
336  int m, es = size - 1;
337  GRN_BIT_SCAN_REV(es, m);
338  m++;
339  free_histogram[m]++;
340  }
341  */
342  grn_io_win iw, iw_;
343  grn_ii_ginfo *ginfo;
344  uint32_t seg, m, *gseg;
345  seg = offset >> GRN_II_N_CHUNK_VARIATION;
346  if (size > S_CHUNK) {
347  int n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK;
348  for (; n--; seg++) { HEADER_CHUNK_OFF(ii, seg); }
349  return GRN_SUCCESS;
350  }
351  if (size > (1 << GRN_II_W_LEAST_CHUNK)) {
352  int es = size - 1;
353  GRN_BIT_SCAN_REV(es, m);
354  m++;
355  } else {
357  }
358  gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK];
359  iw_.addr = NULL;
360  while (*gseg != NOT_ASSIGNED) {
361  ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
362  // GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo);
363  if (!ginfo) {
364  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
366  }
367  if (ginfo->nrecs < N_GARBAGES) { break; }
368  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
369  iw_ = iw;
370  gseg = &ginfo->next;
371  }
372  if (*gseg == NOT_ASSIGNED) {
373  grn_rc rc;
374  if ((rc = chunk_new(ctx, ii, gseg, S_GARBAGE))) {
375  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
376  return rc;
377  }
378  ginfo = WIN_MAP2(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr);
379  /*
380  uint32_t i = 0;
381  while (HEADER_CHUNK_AT(ii, i)) {
382  if (++i >= GRN_II_MAX_CHUNK) { return GRN_NO_MEMORY_AVAILABLE; }
383  }
384  HEADER_CHUNK_ON(ii, i);
385  *gseg = i;
386  GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo);
387  */
388  if (!ginfo) {
389  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
391  }
392  ginfo->head = 0;
393  ginfo->tail = 0;
394  ginfo->nrecs = 0;
395  ginfo->next = NOT_ASSIGNED;
396  }
397  if (iw_.addr) { grn_io_win_unmap2(&iw_); }
398  ginfo->recs[ginfo->head] = offset;
399  if (++ginfo->head == N_GARBAGES) { ginfo->head = 0; }
400  ginfo->nrecs++;
401  grn_io_win_unmap2(&iw);
403  return GRN_SUCCESS;
404 }
405 
406 /*
407 inline static grn_rc
408 chunk_new(grn_ii *ii, uint32_t *res, uint32_t size)
409 {
410  int i, j;
411  uint32_t n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK;
412  uint32_t base_seg = grn_io_base_seg(ii->chunk);
413  for (i = 0, j = -1; i < GRN_II_MAX_CHUNK; i++) {
414  if (HEADER_CHUNK_AT(ii, i)) {
415  j = i;
416  } else {
417  if (i == j + n) {
418  j++;
419  if (res) { *res = j; }
420  for (; j <= i; j++) { HEADER_CHUNK_ON(ii, j); }
421  return GRN_SUCCESS;
422  }
423  // todo : cut off
424  if ((i + base_seg)/ N_CHUNKS_PER_FILE !=
425  (i + base_seg + 1) / N_CHUNKS_PER_FILE) { j = i; }
426  }
427  }
428  GRN_LOG(ctx, GRN_LOG_CRIT, "index full.");
429  return GRN_NO_MEMORY_AVAILABLE;
430 }
431 
432 static void
433 chunk_free(grn_ii *ii, int offset, uint32_t size1, uint32_t size2)
434 {
435  uint32_t i = offset + ((size1 + S_CHUNK - 1) >> GRN_II_W_CHUNK);
436  uint32_t n = offset + ((size2 + S_CHUNK - 1) >> GRN_II_W_CHUNK);
437  for (; i < n; i++) { HEADER_CHUNK_OFF(ii, i); }
438 }
439 */
440 
441 #define UNIT_SIZE 0x80
442 #define UNIT_MASK (UNIT_SIZE - 1)
443 
444 /* <generated> */
445 static uint8_t *
446 pack_1(uint32_t *p, uint8_t *rp)
447 {
448  uint8_t v;
449  v = *p++ << 7;
450  v += *p++ << 6;
451  v += *p++ << 5;
452  v += *p++ << 4;
453  v += *p++ << 3;
454  v += *p++ << 2;
455  v += *p++ << 1;
456  *rp++ = v + *p++;
457  return rp;
458 }
459 static uint8_t *
460 unpack_1(uint32_t *p, uint8_t *dp)
461 {
462  *p++ = (*dp >> 7);
463  *p++ = ((*dp >> 6) & 0x1);
464  *p++ = ((*dp >> 5) & 0x1);
465  *p++ = ((*dp >> 4) & 0x1);
466  *p++ = ((*dp >> 3) & 0x1);
467  *p++ = ((*dp >> 2) & 0x1);
468  *p++ = ((*dp >> 1) & 0x1);
469  *p++ = (*dp++ & 0x1);
470  return dp;
471 }
472 static uint8_t *
473 pack_2(uint32_t *p, uint8_t *rp)
474 {
475  uint8_t v;
476  v = *p++ << 6;
477  v += *p++ << 4;
478  v += *p++ << 2;
479  *rp++ = v + *p++;
480  v = *p++ << 6;
481  v += *p++ << 4;
482  v += *p++ << 2;
483  *rp++ = v + *p++;
484  return rp;
485 }
486 static uint8_t *
487 unpack_2(uint32_t *p, uint8_t *dp)
488 {
489  *p++ = (*dp >> 6);
490  *p++ = ((*dp >> 4) & 0x3);
491  *p++ = ((*dp >> 2) & 0x3);
492  *p++ = (*dp++ & 0x3);
493  *p++ = (*dp >> 6);
494  *p++ = ((*dp >> 4) & 0x3);
495  *p++ = ((*dp >> 2) & 0x3);
496  *p++ = (*dp++ & 0x3);
497  return dp;
498 }
499 static uint8_t *
500 pack_3(uint32_t *p, uint8_t *rp)
501 {
502  uint8_t v;
503  v = *p++ << 5;
504  v += *p++ << 2;
505  *rp++ = v + (*p >> 1); v = *p++ << 7;
506  v += *p++ << 4;
507  v += *p++ << 1;
508  *rp++ = v + (*p >> 2); v = *p++ << 6;
509  v += *p++ << 3;
510  *rp++ = v + *p++;
511  return rp;
512 }
513 static uint8_t *
514 unpack_3(uint32_t *p, uint8_t *dp)
515 {
516  uint32_t v;
517  *p++ = (*dp >> 5);
518  *p++ = ((*dp >> 2) & 0x7);
519  v = ((*dp++ << 1) & 0x7); *p++ = v + (*dp >> 7);
520  *p++ = ((*dp >> 4) & 0x7);
521  *p++ = ((*dp >> 1) & 0x7);
522  v = ((*dp++ << 2) & 0x7); *p++ = v + (*dp >> 6);
523  *p++ = ((*dp >> 3) & 0x7);
524  *p++ = (*dp++ & 0x7);
525  return dp;
526 }
527 static uint8_t *
528 pack_4(uint32_t *p, uint8_t *rp)
529 {
530  uint8_t v;
531  v = *p++ << 4;
532  *rp++ = v + *p++;
533  v = *p++ << 4;
534  *rp++ = v + *p++;
535  v = *p++ << 4;
536  *rp++ = v + *p++;
537  v = *p++ << 4;
538  *rp++ = v + *p++;
539  return rp;
540 }
541 static uint8_t *
542 unpack_4(uint32_t *p, uint8_t *dp)
543 {
544  *p++ = (*dp >> 4);
545  *p++ = (*dp++ & 0xf);
546  *p++ = (*dp >> 4);
547  *p++ = (*dp++ & 0xf);
548  *p++ = (*dp >> 4);
549  *p++ = (*dp++ & 0xf);
550  *p++ = (*dp >> 4);
551  *p++ = (*dp++ & 0xf);
552  return dp;
553 }
554 static uint8_t *
555 pack_5(uint32_t *p, uint8_t *rp)
556 {
557  uint8_t v;
558  v = *p++ << 3;
559  *rp++ = v + (*p >> 2); v = *p++ << 6;
560  v += *p++ << 1;
561  *rp++ = v + (*p >> 4); v = *p++ << 4;
562  *rp++ = v + (*p >> 1); v = *p++ << 7;
563  v += *p++ << 2;
564  *rp++ = v + (*p >> 3); v = *p++ << 5;
565  *rp++ = v + *p++;
566  return rp;
567 }
568 static uint8_t *
569 unpack_5(uint32_t *p, uint8_t *dp)
570 {
571  uint32_t v;
572  *p++ = (*dp >> 3);
573  v = ((*dp++ << 2) & 0x1f); *p++ = v + (*dp >> 6);
574  *p++ = ((*dp >> 1) & 0x1f);
575  v = ((*dp++ << 4) & 0x1f); *p++ = v + (*dp >> 4);
576  v = ((*dp++ << 1) & 0x1f); *p++ = v + (*dp >> 7);
577  *p++ = ((*dp >> 2) & 0x1f);
578  v = ((*dp++ << 3) & 0x1f); *p++ = v + (*dp >> 5);
579  *p++ = (*dp++ & 0x1f);
580  return dp;
581 }
582 static uint8_t *
583 pack_6(uint32_t *p, uint8_t *rp)
584 {
585  uint8_t v;
586  v = *p++ << 2;
587  *rp++ = v + (*p >> 4); v = *p++ << 4;
588  *rp++ = v + (*p >> 2); v = *p++ << 6;
589  *rp++ = v + *p++;
590  v = *p++ << 2;
591  *rp++ = v + (*p >> 4); v = *p++ << 4;
592  *rp++ = v + (*p >> 2); v = *p++ << 6;
593  *rp++ = v + *p++;
594  return rp;
595 }
596 static uint8_t *
597 unpack_6(uint32_t *p, uint8_t *dp)
598 {
599  uint32_t v;
600  *p++ = (*dp >> 2);
601  v = ((*dp++ << 4) & 0x3f); *p++ = v + (*dp >> 4);
602  v = ((*dp++ << 2) & 0x3f); *p++ = v + (*dp >> 6);
603  *p++ = (*dp++ & 0x3f);
604  *p++ = (*dp >> 2);
605  v = ((*dp++ << 4) & 0x3f); *p++ = v + (*dp >> 4);
606  v = ((*dp++ << 2) & 0x3f); *p++ = v + (*dp >> 6);
607  *p++ = (*dp++ & 0x3f);
608  return dp;
609 }
610 static uint8_t *
611 pack_7(uint32_t *p, uint8_t *rp)
612 {
613  uint8_t v;
614  v = *p++ << 1;
615  *rp++ = v + (*p >> 6); v = *p++ << 2;
616  *rp++ = v + (*p >> 5); v = *p++ << 3;
617  *rp++ = v + (*p >> 4); v = *p++ << 4;
618  *rp++ = v + (*p >> 3); v = *p++ << 5;
619  *rp++ = v + (*p >> 2); v = *p++ << 6;
620  *rp++ = v + (*p >> 1); v = *p++ << 7;
621  *rp++ = v + *p++;
622  return rp;
623 }
624 static uint8_t *
625 unpack_7(uint32_t *p, uint8_t *dp)
626 {
627  uint32_t v;
628  *p++ = (*dp >> 1);
629  v = ((*dp++ << 6) & 0x7f); *p++ = v + (*dp >> 2);
630  v = ((*dp++ << 5) & 0x7f); *p++ = v + (*dp >> 3);
631  v = ((*dp++ << 4) & 0x7f); *p++ = v + (*dp >> 4);
632  v = ((*dp++ << 3) & 0x7f); *p++ = v + (*dp >> 5);
633  v = ((*dp++ << 2) & 0x7f); *p++ = v + (*dp >> 6);
634  v = ((*dp++ << 1) & 0x7f); *p++ = v + (*dp >> 7);
635  *p++ = (*dp++ & 0x7f);
636  return dp;
637 }
638 static uint8_t *
639 pack_8(uint32_t *p, uint8_t *rp)
640 {
641  *rp++ = *p++;
642  *rp++ = *p++;
643  *rp++ = *p++;
644  *rp++ = *p++;
645  *rp++ = *p++;
646  *rp++ = *p++;
647  *rp++ = *p++;
648  *rp++ = *p++;
649  return rp;
650 }
651 static uint8_t *
652 unpack_8(uint32_t *p, uint8_t *dp)
653 {
654  *p++ = *dp++;
655  *p++ = *dp++;
656  *p++ = *dp++;
657  *p++ = *dp++;
658  *p++ = *dp++;
659  *p++ = *dp++;
660  *p++ = *dp++;
661  *p++ = *dp++;
662  return dp;
663 }
664 static uint8_t *
665 pack_9(uint32_t *p, uint8_t *rp)
666 {
667  uint8_t v;
668  *rp++ = (*p >> 1); v = *p++ << 7;
669  *rp++ = v + (*p >> 2); v = *p++ << 6;
670  *rp++ = v + (*p >> 3); v = *p++ << 5;
671  *rp++ = v + (*p >> 4); v = *p++ << 4;
672  *rp++ = v + (*p >> 5); v = *p++ << 3;
673  *rp++ = v + (*p >> 6); v = *p++ << 2;
674  *rp++ = v + (*p >> 7); v = *p++ << 1;
675  *rp++ = v + (*p >> 8); *rp++ = *p++;
676  return rp;
677 }
678 static uint8_t *
679 unpack_9(uint32_t *p, uint8_t *dp)
680 {
681  uint32_t v;
682  v = *dp++ << 1; *p++ = v + (*dp >> 7);
683  v = ((*dp++ << 2) & 0x1ff); *p++ = v + (*dp >> 6);
684  v = ((*dp++ << 3) & 0x1ff); *p++ = v + (*dp >> 5);
685  v = ((*dp++ << 4) & 0x1ff); *p++ = v + (*dp >> 4);
686  v = ((*dp++ << 5) & 0x1ff); *p++ = v + (*dp >> 3);
687  v = ((*dp++ << 6) & 0x1ff); *p++ = v + (*dp >> 2);
688  v = ((*dp++ << 7) & 0x1ff); *p++ = v + (*dp >> 1);
689  v = ((*dp++ << 8) & 0x1ff); *p++ = v + *dp++;
690  return dp;
691 }
692 static uint8_t *
693 pack_10(uint32_t *p, uint8_t *rp)
694 {
695  uint8_t v;
696  *rp++ = (*p >> 2); v = *p++ << 6;
697  *rp++ = v + (*p >> 4); v = *p++ << 4;
698  *rp++ = v + (*p >> 6); v = *p++ << 2;
699  *rp++ = v + (*p >> 8); *rp++ = *p++;
700  *rp++ = (*p >> 2); v = *p++ << 6;
701  *rp++ = v + (*p >> 4); v = *p++ << 4;
702  *rp++ = v + (*p >> 6); v = *p++ << 2;
703  *rp++ = v + (*p >> 8); *rp++ = *p++;
704  return rp;
705 }
706 static uint8_t *
707 unpack_10(uint32_t *p, uint8_t *dp)
708 {
709  uint32_t v;
710  v = *dp++ << 2; *p++ = v + (*dp >> 6);
711  v = ((*dp++ << 4) & 0x3ff); *p++ = v + (*dp >> 4);
712  v = ((*dp++ << 6) & 0x3ff); *p++ = v + (*dp >> 2);
713  v = ((*dp++ << 8) & 0x3ff); *p++ = v + *dp++;
714  v = *dp++ << 2; *p++ = v + (*dp >> 6);
715  v = ((*dp++ << 4) & 0x3ff); *p++ = v + (*dp >> 4);
716  v = ((*dp++ << 6) & 0x3ff); *p++ = v + (*dp >> 2);
717  v = ((*dp++ << 8) & 0x3ff); *p++ = v + *dp++;
718  return dp;
719 }
720 static uint8_t *
721 pack_11(uint32_t *p, uint8_t *rp)
722 {
723  uint8_t v;
724  *rp++ = (*p >> 3); v = *p++ << 5;
725  *rp++ = v + (*p >> 6); v = *p++ << 2;
726  *rp++ = v + (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
727  *rp++ = v + (*p >> 4); v = *p++ << 4;
728  *rp++ = v + (*p >> 7); v = *p++ << 1;
729  *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
730  *rp++ = v + (*p >> 5); v = *p++ << 3;
731  *rp++ = v + (*p >> 8); *rp++ = *p++;
732  return rp;
733 }
734 static uint8_t *
735 unpack_11(uint32_t *p, uint8_t *dp)
736 {
737  uint32_t v;
738  v = *dp++ << 3; *p++ = v + (*dp >> 5);
739  v = ((*dp++ << 6) & 0x7ff); *p++ = v + (*dp >> 2);
740  v = ((*dp++ << 9) & 0x7ff); v += *dp++ << 1; *p++ = v + (*dp >> 7);
741  v = ((*dp++ << 4) & 0x7ff); *p++ = v + (*dp >> 4);
742  v = ((*dp++ << 7) & 0x7ff); *p++ = v + (*dp >> 1);
743  v = ((*dp++ << 10) & 0x7ff); v += *dp++ << 2; *p++ = v + (*dp >> 6);
744  v = ((*dp++ << 5) & 0x7ff); *p++ = v + (*dp >> 3);
745  v = ((*dp++ << 8) & 0x7ff); *p++ = v + *dp++;
746  return dp;
747 }
748 static uint8_t *
749 pack_12(uint32_t *p, uint8_t *rp)
750 {
751  uint8_t v;
752  *rp++ = (*p >> 4); v = *p++ << 4;
753  *rp++ = v + (*p >> 8); *rp++ = *p++;
754  *rp++ = (*p >> 4); v = *p++ << 4;
755  *rp++ = v + (*p >> 8); *rp++ = *p++;
756  *rp++ = (*p >> 4); v = *p++ << 4;
757  *rp++ = v + (*p >> 8); *rp++ = *p++;
758  *rp++ = (*p >> 4); v = *p++ << 4;
759  *rp++ = v + (*p >> 8); *rp++ = *p++;
760  return rp;
761 }
762 static uint8_t *
763 unpack_12(uint32_t *p, uint8_t *dp)
764 {
765  uint32_t v;
766  v = *dp++ << 4; *p++ = v + (*dp >> 4);
767  v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++;
768  v = *dp++ << 4; *p++ = v + (*dp >> 4);
769  v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++;
770  v = *dp++ << 4; *p++ = v + (*dp >> 4);
771  v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++;
772  v = *dp++ << 4; *p++ = v + (*dp >> 4);
773  v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++;
774  return dp;
775 }
776 static uint8_t *
777 pack_13(uint32_t *p, uint8_t *rp)
778 {
779  uint8_t v;
780  *rp++ = (*p >> 5); v = *p++ << 3;
781  *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
782  *rp++ = v + (*p >> 7); v = *p++ << 1;
783  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
784  *rp++ = v + (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
785  *rp++ = v + (*p >> 6); v = *p++ << 2;
786  *rp++ = v + (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
787  *rp++ = v + (*p >> 8); *rp++ = *p++;
788  return rp;
789 }
790 static uint8_t *
791 unpack_13(uint32_t *p, uint8_t *dp)
792 {
793  uint32_t v;
794  v = *dp++ << 5; *p++ = v + (*dp >> 3);
795  v = ((*dp++ << 10) & 0x1fff); v += *dp++ << 2; *p++ = v + (*dp >> 6);
796  v = ((*dp++ << 7) & 0x1fff); *p++ = v + (*dp >> 1);
797  v = ((*dp++ << 12) & 0x1fff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
798  v = ((*dp++ << 9) & 0x1fff); v += *dp++ << 1; *p++ = v + (*dp >> 7);
799  v = ((*dp++ << 6) & 0x1fff); *p++ = v + (*dp >> 2);
800  v = ((*dp++ << 11) & 0x1fff); v += *dp++ << 3; *p++ = v + (*dp >> 5);
801  v = ((*dp++ << 8) & 0x1fff); *p++ = v + *dp++;
802  return dp;
803 }
804 static uint8_t *
805 pack_14(uint32_t *p, uint8_t *rp)
806 {
807  uint8_t v;
808  *rp++ = (*p >> 6); v = *p++ << 2;
809  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
810  *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
811  *rp++ = v + (*p >> 8); *rp++ = *p++;
812  *rp++ = (*p >> 6); v = *p++ << 2;
813  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
814  *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
815  *rp++ = v + (*p >> 8); *rp++ = *p++;
816  return rp;
817 }
818 static uint8_t *
819 unpack_14(uint32_t *p, uint8_t *dp)
820 {
821  uint32_t v;
822  v = *dp++ << 6; *p++ = v + (*dp >> 2);
823  v = ((*dp++ << 12) & 0x3fff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
824  v = ((*dp++ << 10) & 0x3fff); v += *dp++ << 2; *p++ = v + (*dp >> 6);
825  v = ((*dp++ << 8) & 0x3fff); *p++ = v + *dp++;
826  v = *dp++ << 6; *p++ = v + (*dp >> 2);
827  v = ((*dp++ << 12) & 0x3fff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
828  v = ((*dp++ << 10) & 0x3fff); v += *dp++ << 2; *p++ = v + (*dp >> 6);
829  v = ((*dp++ << 8) & 0x3fff); *p++ = v + *dp++;
830  return dp;
831 }
832 static uint8_t *
833 pack_15(uint32_t *p, uint8_t *rp)
834 {
835  uint8_t v;
836  *rp++ = (*p >> 7); v = *p++ << 1;
837  *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
838  *rp++ = v + (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
839  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
840  *rp++ = v + (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
841  *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
842  *rp++ = v + (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
843  *rp++ = v + (*p >> 8); *rp++ = *p++;
844  return rp;
845 }
846 static uint8_t *
847 unpack_15(uint32_t *p, uint8_t *dp)
848 {
849  uint32_t v;
850  v = *dp++ << 7; *p++ = v + (*dp >> 1);
851  v = ((*dp++ << 14) & 0x7fff); v += *dp++ << 6; *p++ = v + (*dp >> 2);
852  v = ((*dp++ << 13) & 0x7fff); v += *dp++ << 5; *p++ = v + (*dp >> 3);
853  v = ((*dp++ << 12) & 0x7fff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
854  v = ((*dp++ << 11) & 0x7fff); v += *dp++ << 3; *p++ = v + (*dp >> 5);
855  v = ((*dp++ << 10) & 0x7fff); v += *dp++ << 2; *p++ = v + (*dp >> 6);
856  v = ((*dp++ << 9) & 0x7fff); v += *dp++ << 1; *p++ = v + (*dp >> 7);
857  v = ((*dp++ << 8) & 0x7fff); *p++ = v + *dp++;
858  return dp;
859 }
860 static uint8_t *
861 pack_16(uint32_t *p, uint8_t *rp)
862 {
863  *rp++ = (*p >> 8); *rp++ = *p++;
864  *rp++ = (*p >> 8); *rp++ = *p++;
865  *rp++ = (*p >> 8); *rp++ = *p++;
866  *rp++ = (*p >> 8); *rp++ = *p++;
867  *rp++ = (*p >> 8); *rp++ = *p++;
868  *rp++ = (*p >> 8); *rp++ = *p++;
869  *rp++ = (*p >> 8); *rp++ = *p++;
870  *rp++ = (*p >> 8); *rp++ = *p++;
871  return rp;
872 }
873 static uint8_t *
874 unpack_16(uint32_t *p, uint8_t *dp)
875 {
876  uint32_t v;
877  v = *dp++ << 8; *p++ = v + *dp++;
878  v = *dp++ << 8; *p++ = v + *dp++;
879  v = *dp++ << 8; *p++ = v + *dp++;
880  v = *dp++ << 8; *p++ = v + *dp++;
881  v = *dp++ << 8; *p++ = v + *dp++;
882  v = *dp++ << 8; *p++ = v + *dp++;
883  v = *dp++ << 8; *p++ = v + *dp++;
884  v = *dp++ << 8; *p++ = v + *dp++;
885  return dp;
886 }
887 static uint8_t *
888 pack_17(uint32_t *p, uint8_t *rp)
889 {
890  uint8_t v;
891  *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
892  *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
893  *rp++ = v + (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
894  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
895  *rp++ = v + (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
896  *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
897  *rp++ = v + (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
898  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
899  return rp;
900 }
901 static uint8_t *
902 unpack_17(uint32_t *p, uint8_t *dp)
903 {
904  uint32_t v;
905  v = *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
906  v = ((*dp++ << 10) & 0x1ffff); v += *dp++ << 2; *p++ = v + (*dp >> 6);
907  v = ((*dp++ << 11) & 0x1ffff); v += *dp++ << 3; *p++ = v + (*dp >> 5);
908  v = ((*dp++ << 12) & 0x1ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
909  v = ((*dp++ << 13) & 0x1ffff); v += *dp++ << 5; *p++ = v + (*dp >> 3);
910  v = ((*dp++ << 14) & 0x1ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2);
911  v = ((*dp++ << 15) & 0x1ffff); v += *dp++ << 7; *p++ = v + (*dp >> 1);
912  v = ((*dp++ << 16) & 0x1ffff); v += *dp++ << 8; *p++ = v + *dp++;
913  return dp;
914 }
915 static uint8_t *
916 pack_18(uint32_t *p, uint8_t *rp)
917 {
918  uint8_t v;
919  *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
920  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
921  *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
922  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
923  *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
924  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
925  *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
926  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
927  return rp;
928 }
929 static uint8_t *
930 unpack_18(uint32_t *p, uint8_t *dp)
931 {
932  uint32_t v;
933  v = *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
934  v = ((*dp++ << 12) & 0x3ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
935  v = ((*dp++ << 14) & 0x3ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2);
936  v = ((*dp++ << 16) & 0x3ffff); v += *dp++ << 8; *p++ = v + *dp++;
937  v = *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
938  v = ((*dp++ << 12) & 0x3ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
939  v = ((*dp++ << 14) & 0x3ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2);
940  v = ((*dp++ << 16) & 0x3ffff); v += *dp++ << 8; *p++ = v + *dp++;
941  return dp;
942 }
943 static uint8_t *
944 pack_19(uint32_t *p, uint8_t *rp)
945 {
946  uint8_t v;
947  *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
948  *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
949  *rp++ = v + (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
950  *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
951  *rp++ = v + (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
952  *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
953  *rp++ = v + (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
954  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
955  return rp;
956 }
957 static uint8_t *
958 unpack_19(uint32_t *p, uint8_t *dp)
959 {
960  uint32_t v;
961  v = *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
962  v = ((*dp++ << 14) & 0x7ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2);
963  v = ((*dp++ << 17) & 0x7ffff); v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
964  v = ((*dp++ << 12) & 0x7ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4);
965  v = ((*dp++ << 15) & 0x7ffff); v += *dp++ << 7; *p++ = v + (*dp >> 1);
966  v = ((*dp++ << 18) & 0x7ffff); v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
967  v = ((*dp++ << 13) & 0x7ffff); v += *dp++ << 5; *p++ = v + (*dp >> 3);
968  v = ((*dp++ << 16) & 0x7ffff); v += *dp++ << 8; *p++ = v + *dp++;
969  return dp;
970 }
971 static uint8_t *
972 pack_20(uint32_t *p, uint8_t *rp)
973 {
974  uint8_t v;
975  *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
976  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
977  *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
978  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
979  *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
980  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
981  *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
982  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
983  return rp;
984 }
985 static uint8_t *
986 unpack_20(uint32_t *p, uint8_t *dp)
987 {
988  uint32_t v;
989  v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
990  v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++;
991  v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
992  v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++;
993  v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
994  v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++;
995  v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
996  v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++;
997  return dp;
998 }
999 static uint8_t *
1000 pack_21(uint32_t *p, uint8_t *rp)
1001 {
1002  uint8_t v;
1003  *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
1004  *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1005  *rp++ = v + (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
1006  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1007  *rp++ = v + (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
1008  *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1009  *rp++ = v + (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
1010  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1011  return rp;
1012 }
1013 static uint8_t *
1014 unpack_21(uint32_t *p, uint8_t *dp)
1015 {
1016  uint32_t v;
1017  v = *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3);
1018  v = ((*dp++ << 18) & 0x1fffff); v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1019  v = ((*dp++ << 15) & 0x1fffff); v += *dp++ << 7; *p++ = v + (*dp >> 1);
1020  v = ((*dp++ << 20) & 0x1fffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1021  v = ((*dp++ << 17) & 0x1fffff); v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
1022  v = ((*dp++ << 14) & 0x1fffff); v += *dp++ << 6; *p++ = v + (*dp >> 2);
1023  v = ((*dp++ << 19) & 0x1fffff); v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
1024  v = ((*dp++ << 16) & 0x1fffff); v += *dp++ << 8; *p++ = v + *dp++;
1025  return dp;
1026 }
1027 static uint8_t *
1028 pack_22(uint32_t *p, uint8_t *rp)
1029 {
1030  uint8_t v;
1031  *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1032  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1033  *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1034  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1035  *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1036  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1037  *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1038  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1039  return rp;
1040 }
1041 static uint8_t *
1042 unpack_22(uint32_t *p, uint8_t *dp)
1043 {
1044  uint32_t v;
1045  v = *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1046  v = ((*dp++ << 20) & 0x3fffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1047  v = ((*dp++ << 18) & 0x3fffff); v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1048  v = ((*dp++ << 16) & 0x3fffff); v += *dp++ << 8; *p++ = v + *dp++;
1049  v = *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1050  v = ((*dp++ << 20) & 0x3fffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1051  v = ((*dp++ << 18) & 0x3fffff); v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1052  v = ((*dp++ << 16) & 0x3fffff); v += *dp++ << 8; *p++ = v + *dp++;
1053  return dp;
1054 }
1055 static uint8_t *
1056 pack_23(uint32_t *p, uint8_t *rp)
1057 {
1058  uint8_t v;
1059  *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
1060  *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1061  *rp++ = v + (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
1062  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1063  *rp++ = v + (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
1064  *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1065  *rp++ = v + (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
1066  *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1067  return rp;
1068 }
1069 static uint8_t *
1070 unpack_23(uint32_t *p, uint8_t *dp)
1071 {
1072  uint32_t v;
1073  v = *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1);
1074  v = ((*dp++ << 22) & 0x7fffff); v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1075  v = ((*dp++ << 21) & 0x7fffff); v += *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3);
1076  v = ((*dp++ << 20) & 0x7fffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1077  v = ((*dp++ << 19) & 0x7fffff); v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
1078  v = ((*dp++ << 18) & 0x7fffff); v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1079  v = ((*dp++ << 17) & 0x7fffff); v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
1080  v = ((*dp++ << 16) & 0x7fffff); v += *dp++ << 8; *p++ = v + *dp++;
1081  return dp;
1082 }
1083 static uint8_t *
1084 pack_24(uint32_t *p, uint8_t *rp)
1085 {
1086  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1087  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1088  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1089  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1090  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1091  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1092  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1093  *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1094  return rp;
1095 }
1096 static uint8_t *
1097 unpack_24(uint32_t *p, uint8_t *dp)
1098 {
1099  uint32_t v;
1100  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1101  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1102  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1103  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1104  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1105  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1106  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1107  v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1108  return dp;
1109 }
1110 static uint8_t *
1111 pack_25(uint32_t *p, uint8_t *rp)
1112 {
1113  uint8_t v;
1114  *rp++ = (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
1115  *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1116  *rp++ = v + (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
1117  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1118  *rp++ = v + (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
1119  *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1120  *rp++ = v + (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
1121  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1122  return rp;
1123 }
1124 static uint8_t *
1125 unpack_25(uint32_t *p, uint8_t *dp)
1126 {
1127  uint32_t v;
1128  v = *dp++ << 17; v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
1129  v = ((*dp++ << 18) & 0x1ffffff); v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1130  v = ((*dp++ << 19) & 0x1ffffff); v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
1131  v = ((*dp++ << 20) & 0x1ffffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1132  v = ((*dp++ << 21) & 0x1ffffff); v += *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3);
1133  v = ((*dp++ << 22) & 0x1ffffff); v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1134  v = ((*dp++ << 23) & 0x1ffffff); v += *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1);
1135  v = ((*dp++ << 24) & 0x1ffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1136  return dp;
1137 }
1138 static uint8_t *
1139 pack_26(uint32_t *p, uint8_t *rp)
1140 {
1141  uint8_t v;
1142  *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1143  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1144  *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1145  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1146  *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1147  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1148  *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1149  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1150  return rp;
1151 }
1152 static uint8_t *
1153 unpack_26(uint32_t *p, uint8_t *dp)
1154 {
1155  uint32_t v;
1156  v = *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1157  v = ((*dp++ << 20) & 0x3ffffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1158  v = ((*dp++ << 22) & 0x3ffffff); v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1159  v = ((*dp++ << 24) & 0x3ffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1160  v = *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1161  v = ((*dp++ << 20) & 0x3ffffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1162  v = ((*dp++ << 22) & 0x3ffffff); v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1163  v = ((*dp++ << 24) & 0x3ffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1164  return dp;
1165 }
1166 static uint8_t *
1167 pack_27(uint32_t *p, uint8_t *rp)
1168 {
1169  uint8_t v;
1170  *rp++ = (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
1171  *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1172  *rp++ = v + (*p >> 25); *rp++ = (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
1173  *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1174  *rp++ = v + (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
1175  *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1176  *rp++ = v + (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
1177  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1178  return rp;
1179 }
1180 static uint8_t *
1181 unpack_27(uint32_t *p, uint8_t *dp)
1182 {
1183  uint32_t v;
1184  v = *dp++ << 19; v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
1185  v = ((*dp++ << 22) & 0x7ffffff); v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1186  v = ((*dp++ << 25) & 0x7ffffff); v += *dp++ << 17; v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
1187  v = ((*dp++ << 20) & 0x7ffffff); v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1188  v = ((*dp++ << 23) & 0x7ffffff); v += *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1);
1189  v = ((*dp++ << 26) & 0x7ffffff); v += *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1190  v = ((*dp++ << 21) & 0x7ffffff); v += *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3);
1191  v = ((*dp++ << 24) & 0x7ffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1192  return dp;
1193 }
1194 static uint8_t *
1195 pack_28(uint32_t *p, uint8_t *rp)
1196 {
1197  uint8_t v;
1198  *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1199  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1200  *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1201  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1202  *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1203  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1204  *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1205  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1206  return rp;
1207 }
1208 static uint8_t *
1209 unpack_28(uint32_t *p, uint8_t *dp)
1210 {
1211  uint32_t v;
1212  v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1213  v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1214  v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1215  v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1216  v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1217  v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1218  v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1219  v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1220  return dp;
1221 }
1222 static uint8_t *
1223 pack_29(uint32_t *p, uint8_t *rp)
1224 {
1225  uint8_t v;
1226  *rp++ = (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
1227  *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1228  *rp++ = v + (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
1229  *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1230  *rp++ = v + (*p >> 25); *rp++ = (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
1231  *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1232  *rp++ = v + (*p >> 27); *rp++ = (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
1233  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1234  return rp;
1235 }
1236 static uint8_t *
1237 unpack_29(uint32_t *p, uint8_t *dp)
1238 {
1239  uint32_t v;
1240  v = *dp++ << 21; v += *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3);
1241  v = ((*dp++ << 26) & 0x1fffffff); v += *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1242  v = ((*dp++ << 23) & 0x1fffffff); v += *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1);
1243  v = ((*dp++ << 28) & 0x1fffffff); v += *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1244  v = ((*dp++ << 25) & 0x1fffffff); v += *dp++ << 17; v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
1245  v = ((*dp++ << 22) & 0x1fffffff); v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1246  v = ((*dp++ << 27) & 0x1fffffff); v += *dp++ << 19; v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
1247  v = ((*dp++ << 24) & 0x1fffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1248  return dp;
1249 }
1250 static uint8_t *
1251 pack_30(uint32_t *p, uint8_t *rp)
1252 {
1253  uint8_t v;
1254  *rp++ = (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1255  *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1256  *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1257  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1258  *rp++ = (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1259  *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1260  *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1261  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1262  return rp;
1263 }
1264 static uint8_t *
1265 unpack_30(uint32_t *p, uint8_t *dp)
1266 {
1267  uint32_t v;
1268  v = *dp++ << 22; v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1269  v = ((*dp++ << 28) & 0x3fffffff); v += *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1270  v = ((*dp++ << 26) & 0x3fffffff); v += *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1271  v = ((*dp++ << 24) & 0x3fffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1272  v = *dp++ << 22; v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1273  v = ((*dp++ << 28) & 0x3fffffff); v += *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1274  v = ((*dp++ << 26) & 0x3fffffff); v += *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1275  v = ((*dp++ << 24) & 0x3fffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1276  return dp;
1277 }
1278 static uint8_t *
1279 pack_31(uint32_t *p, uint8_t *rp)
1280 {
1281  uint8_t v;
1282  *rp++ = (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1;
1283  *rp++ = v + (*p >> 30); *rp++ = (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2;
1284  *rp++ = v + (*p >> 29); *rp++ = (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3;
1285  *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4;
1286  *rp++ = v + (*p >> 27); *rp++ = (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5;
1287  *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6;
1288  *rp++ = v + (*p >> 25); *rp++ = (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7;
1289  *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1290  return rp;
1291 }
1292 static uint8_t *
1293 unpack_31(uint32_t *p, uint8_t *dp)
1294 {
1295  uint32_t v;
1296  v = *dp++ << 23; v += *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1);
1297  v = ((*dp++ << 30) & 0x7fffffff); v += *dp++ << 22; v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2);
1298  v = ((*dp++ << 29) & 0x7fffffff); v += *dp++ << 21; v += *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3);
1299  v = ((*dp++ << 28) & 0x7fffffff); v += *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4);
1300  v = ((*dp++ << 27) & 0x7fffffff); v += *dp++ << 19; v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5);
1301  v = ((*dp++ << 26) & 0x7fffffff); v += *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6);
1302  v = ((*dp++ << 25) & 0x7fffffff); v += *dp++ << 17; v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7);
1303  v = ((*dp++ << 24) & 0x7fffffff); v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1304  return dp;
1305 }
1306 static uint8_t *
1307 pack_32(uint32_t *p, uint8_t *rp)
1308 {
1309  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1310  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1311  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1312  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1313  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1314  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1315  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1316  *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++;
1317  return rp;
1318 }
1319 static uint8_t *
1320 unpack_32(uint32_t *p, uint8_t *dp)
1321 {
1322  uint32_t v;
1323  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1324  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1325  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1326  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1327  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1328  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1329  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1330  v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++;
1331  return dp;
1332 }
1333 /* </generated> */
1334 
1335 static uint8_t *
1336 pack_(uint32_t *p, uint32_t i, int w, uint8_t *rp)
1337 {
1338  while (i >= 8) {
1339  switch (w) {
1340  case 0 : break;
1341  case 1 : rp = pack_1(p, rp); break;
1342  case 2 : rp = pack_2(p, rp); break;
1343  case 3 : rp = pack_3(p, rp); break;
1344  case 4 : rp = pack_4(p, rp); break;
1345  case 5 : rp = pack_5(p, rp); break;
1346  case 6 : rp = pack_6(p, rp); break;
1347  case 7 : rp = pack_7(p, rp); break;
1348  case 8 : rp = pack_8(p, rp); break;
1349  case 9 : rp = pack_9(p, rp); break;
1350  case 10 : rp = pack_10(p, rp); break;
1351  case 11 : rp = pack_11(p, rp); break;
1352  case 12 : rp = pack_12(p, rp); break;
1353  case 13 : rp = pack_13(p, rp); break;
1354  case 14 : rp = pack_14(p, rp); break;
1355  case 15 : rp = pack_15(p, rp); break;
1356  case 16 : rp = pack_16(p, rp); break;
1357  case 17 : rp = pack_17(p, rp); break;
1358  case 18 : rp = pack_18(p, rp); break;
1359  case 19 : rp = pack_19(p, rp); break;
1360  case 20 : rp = pack_20(p, rp); break;
1361  case 21 : rp = pack_21(p, rp); break;
1362  case 22 : rp = pack_22(p, rp); break;
1363  case 23 : rp = pack_23(p, rp); break;
1364  case 24 : rp = pack_24(p, rp); break;
1365  case 25 : rp = pack_25(p, rp); break;
1366  case 26 : rp = pack_26(p, rp); break;
1367  case 27 : rp = pack_27(p, rp); break;
1368  case 28 : rp = pack_28(p, rp); break;
1369  case 29 : rp = pack_29(p, rp); break;
1370  case 30 : rp = pack_30(p, rp); break;
1371  case 31 : rp = pack_31(p, rp); break;
1372  case 32 : rp = pack_32(p, rp); break;
1373  }
1374  p += 8;
1375  i -= 8;
1376  }
1377  {
1378  int b;
1379  uint8_t v;
1380  uint32_t *pe = p + i;
1381  for (b = 8 - w, v = 0; p < pe;) {
1382  if (b > 0) {
1383  v += *p++ << b;
1384  b -= w;
1385  } else if (b < 0) {
1386  *rp++ = v + (*p >> -b);
1387  b += 8;
1388  v = 0;
1389  } else {
1390  *rp++ = v + *p++;
1391  b = 8 - w;
1392  v = 0;
1393  }
1394  }
1395  if (b + w != 8) { *rp++ = v; }
1396  return rp;
1397  }
1398 }
1399 
1400 static uint8_t *
1401 pack(uint32_t *p, uint32_t i, uint8_t *freq, uint8_t *rp)
1402 {
1403  int32_t k, w;
1404  uint8_t ebuf[UNIT_SIZE], *ep = ebuf;
1405  uint32_t s, *pe = p + i, r, th = i - (i >> 3);
1406  for (w = 0, s = 0; w <= 32; w++) {
1407  if ((s += freq[w]) >= th) { break; }
1408  }
1409  if (i == s) {
1410  *rp++ = w;
1411  return pack_(p, i, w, rp);
1412  }
1413  r = 1 << w;
1414  *rp++ = w + 0x80;
1415  *rp++ = i - s;
1416  if (r >= UNIT_SIZE) {
1417  uint32_t first, *last = &first;
1418  for (k = 0; p < pe; p++, k++) {
1419  if (*p >= r) {
1420  GRN_B_ENC(*p - r, ep);
1421  *last = k;
1422  last = p;
1423  }
1424  }
1425  *last = 0;
1426  *rp++ = (uint8_t) first;
1427  } else {
1428  for (k = 0; p < pe; p++, k++) {
1429  if (*p >= r) {
1430  *ep++ = k;
1431  GRN_B_ENC(*p - r, ep);
1432  *p = 0;
1433  }
1434  }
1435  }
1436  rp = pack_(p - i, i, w, rp);
1437  memcpy(rp, ebuf, ep - ebuf);
1438  return rp + (ep - ebuf);
1439 }
1440 
1441 int
1442 grn_p_enc(grn_ctx *ctx, uint32_t *data, uint32_t data_size, uint8_t **res)
1443 {
1444  uint8_t *rp, freq[33];
1445  uint32_t j, *dp, *dpe, d, w, buf[UNIT_SIZE];
1446  *res = rp = GRN_MALLOC(data_size * sizeof(uint32_t) * 2);
1447  GRN_B_ENC(data_size, rp);
1448  memset(freq, 0, 33);
1449  for (j = 0, dp = data, dpe = dp + data_size; dp < dpe; j++, dp++) {
1450  if (j == UNIT_SIZE) {
1451  rp = pack(buf, j, freq, rp);
1452  memset(freq, 0, 33);
1453  j = 0;
1454  }
1455  if ((d = buf[j] = *dp)) {
1456  GRN_BIT_SCAN_REV(d, w);
1457  freq[w + 1]++;
1458  } else {
1459  freq[0]++;
1460  }
1461  }
1462  if (j) { rp = pack(buf, j, freq, rp); }
1463  return rp - *res;
1464 }
1465 
1466 #define USE_P_ENC (1<<0)
1467 #define CUT_OFF (1<<1)
1468 #define ODD (1<<2)
1469 
1470 typedef struct {
1471  uint32_t *data;
1472  uint32_t data_size;
1473  uint32_t flags;
1474 } datavec;
1475 
1476 static grn_rc
1477 datavec_reset(grn_ctx *ctx, datavec *dv, uint32_t dvlen,
1478  size_t unitsize, size_t totalsize)
1479 {
1480  int i;
1481  if (!dv[0].data || dv[dvlen].data < dv[0].data + totalsize) {
1482  if (dv[0].data) { GRN_FREE(dv[0].data); }
1483  if (!(dv[0].data = GRN_MALLOC(totalsize * sizeof(uint32_t)))) {
1484  return GRN_NO_MEMORY_AVAILABLE;
1485  }
1486  dv[dvlen].data = dv[0].data + totalsize;
1487  }
1488  for (i = 1; i < dvlen; i++) {
1489  dv[i].data = dv[i - 1].data + unitsize;
1490  }
1491  return GRN_SUCCESS;
1492 }
1493 
1494 static grn_rc
1495 datavec_init(grn_ctx *ctx, datavec *dv, uint32_t dvlen,
1496  size_t unitsize, size_t totalsize)
1497 {
1498  int i;
1499  if (!totalsize) {
1500  memset(dv, 0, sizeof(datavec) * (dvlen + 1));
1501  return GRN_SUCCESS;
1502  }
1503  if (!(dv[0].data = GRN_MALLOC(totalsize * sizeof(uint32_t)))) {
1504  return GRN_NO_MEMORY_AVAILABLE;
1505  }
1506  dv[dvlen].data = dv[0].data + totalsize;
1507  for (i = 1; i < dvlen; i++) {
1508  dv[i].data = dv[i - 1].data + unitsize;
1509  }
1510  return GRN_SUCCESS;
1511 }
1512 
1513 static void
1514 datavec_fin(grn_ctx *ctx, datavec *dv)
1515 {
1516  if (dv[0].data) { GRN_FREE(dv[0].data); }
1517 }
1518 
1519 size_t
1520 grn_p_encv(grn_ctx *ctx, datavec *dv, uint32_t dvlen, uint8_t *res)
1521 {
1522  uint8_t *rp = res, freq[33];
1523  uint32_t pgap, usep, l, df, data_size, *dp, *dpe;
1524  if (!dvlen || !(df = dv[0].data_size)) { return 0; }
1525  for (usep = 0, data_size = 0, l = 0; l < dvlen; l++) {
1526  uint32_t dl = dv[l].data_size;
1527  if (dl < df || ((dl > df) && (l != dvlen - 1))) {
1528  /* invalid argument */
1529  return 0;
1530  }
1531  usep += (dv[l].flags & USE_P_ENC) << l;
1532  data_size += dl;
1533  }
1534  pgap = data_size - df * dvlen;
1535  if (!usep) {
1536  GRN_B_ENC((df << 1) + 1, rp);
1537  for (l = 0; l < dvlen; l++) {
1538  for (dp = dv[l].data, dpe = dp + dv[l].data_size; dp < dpe; dp++) {
1539  GRN_B_ENC(*dp, rp);
1540  }
1541  }
1542  } else {
1543  uint32_t buf[UNIT_SIZE];
1544  GRN_B_ENC((usep << 1), rp);
1545  GRN_B_ENC(df, rp);
1546  if (dv[dvlen - 1].flags & ODD) {
1547  GRN_B_ENC(pgap, rp);
1548  } else {
1549  GRN_ASSERT(!pgap);
1550  }
1551  for (l = 0; l < dvlen; l++) {
1552  dp = dv[l].data;
1553  dpe = dp + dv[l].data_size;
1554  if ((dv[l].flags & USE_P_ENC)) {
1555  uint32_t j = 0, d;
1556  memset(freq, 0, 33);
1557  while (dp < dpe) {
1558  if (j == UNIT_SIZE) {
1559  rp = pack(buf, j, freq, rp);
1560  memset(freq, 0, 33);
1561  j = 0;
1562  }
1563  if ((d = buf[j++] = *dp++)) {
1564  uint32_t w;
1565  GRN_BIT_SCAN_REV(d, w);
1566  freq[w + 1]++;
1567  } else {
1568  freq[0]++;
1569  }
1570  }
1571  if (j) { rp = pack(buf, j, freq, rp); }
1572  } else {
1573  while (dp < dpe) { GRN_B_ENC(*dp++, rp); }
1574  }
1575  }
1576  }
1577  return rp - res;
1578 }
1579 
1580 #define GRN_B_DEC_CHECK(v,p,pe) do { \
1581  uint8_t *_p = (uint8_t *)p; \
1582  uint32_t _v; \
1583  if (_p >= pe) { return 0; } \
1584  _v = *_p++; \
1585  switch (_v >> 4) { \
1586  case 0x08 : \
1587  if (_v == 0x8f) { \
1588  if (_p + sizeof(uint32_t) > pe) { return 0; } \
1589  memcpy(&_v, _p, sizeof(uint32_t)); \
1590  _p += sizeof(uint32_t); \
1591  } \
1592  break; \
1593  case 0x09 : \
1594  if (_p + 3 > pe) { return 0; } \
1595  _v = (_v - 0x90) * 0x100 + *_p++; \
1596  _v = _v * 0x100 + *_p++; \
1597  _v = _v * 0x100 + *_p++ + 0x20408f; \
1598  break; \
1599  case 0x0a : \
1600  case 0x0b : \
1601  if (_p + 2 > pe) { return 0; } \
1602  _v = (_v - 0xa0) * 0x100 + *_p++; \
1603  _v = _v * 0x100 + *_p++ + 0x408f; \
1604  break; \
1605  case 0x0c : \
1606  case 0x0d : \
1607  case 0x0e : \
1608  case 0x0f : \
1609  if (_p + 1 > pe) { return 0; } \
1610  _v = (_v - 0xc0) * 0x100 + *_p++ + 0x8f; \
1611  break; \
1612  } \
1613  v = _v; \
1614  p = _p; \
1615 } while (0)
1616 
1617 static uint8_t *
1618 unpack(uint8_t *dp, uint8_t *dpe, int i, uint32_t *rp)
1619 {
1620  uint8_t ne = 0, k = 0, w = *dp++;
1621  uint32_t m, *p = rp;
1622  if (w & 0x80) {
1623  ne = *dp++;
1624  w -= 0x80;
1625  m = (1 << w) - 1;
1626  if (m >= UNIT_MASK) { k = *dp++; }
1627  } else {
1628  m = (1 << w) - 1;
1629  }
1630  if (w) {
1631  while (i >= 8) {
1632  if (dp + w > dpe) { return NULL; }
1633  switch (w) {
1634  case 1 : dp = unpack_1(p, dp); break;
1635  case 2 : dp = unpack_2(p, dp); break;
1636  case 3 : dp = unpack_3(p, dp); break;
1637  case 4 : dp = unpack_4(p, dp); break;
1638  case 5 : dp = unpack_5(p, dp); break;
1639  case 6 : dp = unpack_6(p, dp); break;
1640  case 7 : dp = unpack_7(p, dp); break;
1641  case 8 : dp = unpack_8(p, dp); break;
1642  case 9 : dp = unpack_9(p, dp); break;
1643  case 10 : dp = unpack_10(p, dp); break;
1644  case 11 : dp = unpack_11(p, dp); break;
1645  case 12 : dp = unpack_12(p, dp); break;
1646  case 13 : dp = unpack_13(p, dp); break;
1647  case 14 : dp = unpack_14(p, dp); break;
1648  case 15 : dp = unpack_15(p, dp); break;
1649  case 16 : dp = unpack_16(p, dp); break;
1650  case 17 : dp = unpack_17(p, dp); break;
1651  case 18 : dp = unpack_18(p, dp); break;
1652  case 19 : dp = unpack_19(p, dp); break;
1653  case 20 : dp = unpack_20(p, dp); break;
1654  case 21 : dp = unpack_21(p, dp); break;
1655  case 22 : dp = unpack_22(p, dp); break;
1656  case 23 : dp = unpack_23(p, dp); break;
1657  case 24 : dp = unpack_24(p, dp); break;
1658  case 25 : dp = unpack_25(p, dp); break;
1659  case 26 : dp = unpack_26(p, dp); break;
1660  case 27 : dp = unpack_27(p, dp); break;
1661  case 28 : dp = unpack_28(p, dp); break;
1662  case 29 : dp = unpack_29(p, dp); break;
1663  case 30 : dp = unpack_30(p, dp); break;
1664  case 31 : dp = unpack_31(p, dp); break;
1665  case 32 : dp = unpack_32(p, dp); break;
1666  }
1667  i -= 8;
1668  p += 8;
1669  }
1670  {
1671  int b;
1672  uint32_t v, *pe;
1673  for (b = 8 - w, v = 0, pe = p + i; p < pe && dp < dpe;) {
1674  if (b > 0) {
1675  *p++ = v + ((*dp >> b) & m);
1676  b -= w;
1677  v = 0;
1678  } else if (b < 0) {
1679  v += (*dp++ << -b) & m;
1680  b += 8;
1681  } else {
1682  *p++ = v + (*dp++ & m);
1683  b = 8 - w;
1684  v = 0;
1685  }
1686  }
1687  if (b + w != 8) { dp++; }
1688  }
1689  } else {
1690  memset(p, 0, sizeof(uint32_t) * i);
1691  }
1692  if (ne) {
1693  if (m >= UNIT_MASK) {
1694  uint32_t *pp;
1695  while (ne--) {
1696  pp = &rp[k];
1697  k = *pp;
1698  GRN_B_DEC_CHECK(*pp, dp, dpe);
1699  *pp += (m + 1);
1700  }
1701  } else {
1702  while (ne--) {
1703  k = *dp++;
1704  GRN_B_DEC_CHECK(rp[k], dp, dpe);
1705  rp[k] += (m + 1);
1706  }
1707  }
1708  }
1709  return dp;
1710 }
1711 
1712 int
1713 grn_p_dec(grn_ctx *ctx, uint8_t *data, uint32_t data_size, uint32_t nreq, uint32_t **res)
1714 {
1715  uint8_t *dp = data, *dpe = data + data_size;
1716  uint32_t rest, orig_size, *rp, *rpe;
1717  GRN_B_DEC(orig_size, dp);
1718  if (!orig_size) {
1719  if (!nreq || nreq > data_size) { nreq = data_size; }
1720  if ((*res = rp = GRN_MALLOC(nreq * 4))) {
1721  for (rpe = rp + nreq; dp < data + data_size && rp < rpe; rp++) {
1722  GRN_B_DEC(*rp, dp);
1723  }
1724  }
1725  return rp - *res;
1726  } else {
1727  if (!(*res = rp = GRN_MALLOC(orig_size * sizeof(uint32_t)))) {
1728  return 0;
1729  }
1730  if (!nreq || nreq > orig_size) { nreq = orig_size; }
1731  for (rest = nreq; rest >= UNIT_SIZE; rest -= UNIT_SIZE) {
1732  if (!(dp = unpack(dp, dpe, UNIT_SIZE, rp))) { return 0; }
1733  rp += UNIT_SIZE;
1734  }
1735  if (rest) { if (!(dp = unpack(dp, dpe, rest, rp))) { return 0; } }
1736  GRN_ASSERT(data + data_size == dp);
1737  return nreq;
1738  }
1739 }
1740 
1741 int
1742 grn_p_decv(grn_ctx *ctx, uint8_t *data, uint32_t data_size, datavec *dv, uint32_t dvlen)
1743 {
1744  size_t size;
1745  uint32_t df, l, i, *rp, nreq;
1746  uint8_t *dp = data, *dpe = data + data_size;
1747  if (!data_size) {
1748  dv[0].data_size = 0;
1749  return 0;
1750  }
1751  for (nreq = 0; nreq < dvlen; nreq++) {
1752  if (dv[nreq].flags & CUT_OFF) { break; }
1753  }
1754  if (!nreq) { return 0; }
1755  GRN_B_DEC_CHECK(df, dp, dpe);
1756  if ((df & 1)) {
1757  df >>= 1;
1758  size = nreq == dvlen ? data_size : df * nreq;
1759  if (dv[dvlen].data < dv[0].data + size) {
1760  if (dv[0].data) { GRN_FREE(dv[0].data); }
1761  if (!(rp = GRN_MALLOC(size * sizeof(uint32_t)))) { return 0; }
1762  dv[dvlen].data = rp + size;
1763  } else {
1764  rp = dv[0].data;
1765  }
1766  for (l = 0; l < dvlen; l++) {
1767  if (dv[l].flags & CUT_OFF) { break; }
1768  dv[l].data = rp;
1769  if (l < dvlen - 1) {
1770  for (i = 0; i < df; i++, rp++) { GRN_B_DEC_CHECK(*rp, dp, dpe); }
1771  } else {
1772  for (i = 0; dp < dpe; i++, rp++) { GRN_B_DEC_CHECK(*rp, dp, dpe); }
1773  }
1774  dv[l].data_size = i;
1775  }
1776  } else {
1777  uint32_t n, rest, usep = df >> 1;
1778  GRN_B_DEC_CHECK(df, dp, dpe);
1779  if (dv[dvlen -1].flags & ODD) {
1780  GRN_B_DEC_CHECK(rest, dp, dpe);
1781  } else {
1782  rest = 0;
1783  }
1784  size = df * nreq + (nreq == dvlen ? rest : 0);
1785  if (dv[dvlen].data < dv[0].data + size) {
1786  if (dv[0].data) { GRN_FREE(dv[0].data); }
1787  if (!(rp = GRN_MALLOC(size * sizeof(uint32_t)))) { return 0; }
1788  dv[dvlen].data = rp + size;
1789  } else {
1790  rp = dv[0].data;
1791  }
1792  for (l = 0; l < dvlen; l++) {
1793  if (dv[l].flags & CUT_OFF) { break; }
1794  dv[l].data = rp;
1795  dv[l].data_size = n = (l < dvlen - 1) ? df : df + rest;
1796  if (usep & (1 << l)) {
1797  for (; n >= UNIT_SIZE; n -= UNIT_SIZE) {
1798  if (!(dp = unpack(dp, dpe, UNIT_SIZE, rp))) { return 0; }
1799  rp += UNIT_SIZE;
1800  }
1801  if (n) {
1802  if (!(dp = unpack(dp, dpe, n, rp))) { return 0; }
1803  rp += n;
1804  }
1805  dv[l].flags |= USE_P_ENC;
1806  } else {
1807  for (; n; n--, rp++) {
1808  GRN_B_DEC_CHECK(*rp, dp, dpe);
1809  }
1810  }
1811  }
1812  GRN_ASSERT(dp == dpe);
1813  if (dp != dpe) {
1814  GRN_LOG(ctx, GRN_LOG_NOTICE, "data_size=%d, %" GRN_FMT_LLD,
1815  data_size, (long long int)(dpe - dp));
1816  }
1817  }
1818  return rp - dv[0].data;
1819 }
1820 
1821 int
1822 grn_b_enc(grn_ctx *ctx, uint32_t *data, uint32_t data_size, uint8_t **res)
1823 {
1824  uint8_t *rp;
1825  uint32_t *dp, i;
1826  *res = rp = GRN_MALLOC(data_size * sizeof(uint32_t) * 2);
1827  GRN_B_ENC(data_size, rp);
1828  for (i = data_size, dp = data; i; i--, dp++) {
1829  GRN_B_ENC(*dp, rp);
1830  }
1831  return rp - *res;
1832 }
1833 
1834 int
1835 grn_b_dec(grn_ctx *ctx, uint8_t *data, uint32_t data_size, uint32_t **res)
1836 {
1837  uint32_t i, *rp, orig_size;
1838  uint8_t *dp = data;
1839  GRN_B_DEC(orig_size, dp);
1840  *res = rp = GRN_MALLOC(orig_size * sizeof(uint32_t));
1841  for (i = orig_size; i; i--, rp++) {
1842  GRN_B_DEC(*rp, dp);
1843  }
1844  return orig_size;
1845 }
1846 
1847 /* buffer */
1848 
1849 typedef struct {
1850  uint32_t tid;
1851  uint32_t size_in_chunk;
1852  uint32_t pos_in_chunk;
1853  uint16_t size_in_buffer;
1854  uint16_t pos_in_buffer;
1855 } buffer_term;
1856 
1857 typedef struct {
1858  uint16_t step;
1859  uint16_t jump;
1860 } buffer_rec;
1861 
1862 typedef struct {
1863  uint32_t chunk;
1864  uint32_t chunk_size;
1865  uint32_t buffer_free;
1866  uint16_t nterms;
1867  uint16_t nterms_void;
1868 } buffer_header;
1869 
1873 };
1874 
1875 typedef struct grn_ii_buffer buffer;
1876 
1877 inline static uint32_t
1878 buffer_open(grn_ctx *ctx, grn_ii *ii, uint32_t pos, buffer_term **bt, buffer **b)
1879 {
1880  byte *p = NULL;
1881  uint16_t lseg = (uint16_t) (LSEG(pos));
1882  uint32_t pseg = ii->header->binfo[lseg];
1883  if (pseg != NOT_ASSIGNED) {
1884  GRN_IO_SEG_REF(ii->seg, pseg, p);
1885  if (!p) { return NOT_ASSIGNED; }
1886  if (b) { *b = (buffer *)p; }
1887  if (bt) { *bt = (buffer_term *)(p + LPOS(pos)); }
1888  }
1889  return pseg;
1890 }
1891 
1892 inline static grn_rc
1893 buffer_close(grn_ctx *ctx, grn_ii *ii, uint32_t pseg)
1894 {
1895  if (pseg >= MAX_PSEG) {
1896  GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid pseg buffer_close(%d)", pseg);
1897  return GRN_INVALID_ARGUMENT;
1898  }
1899  GRN_IO_SEG_UNREF(ii->seg, pseg);
1900  return GRN_SUCCESS;
1901 }
1902 
1903 inline static uint32_t
1904 buffer_open_if_capable(grn_ctx *ctx, grn_ii *ii, int32_t seg, int size, buffer **b)
1905 {
1906  uint32_t pseg, pos = SEG2POS(seg, 0);
1907  if ((pseg = buffer_open(ctx, ii, pos, NULL, b)) != NOT_ASSIGNED) {
1908  uint16_t nterms = (*b)->header.nterms - (*b)->header.nterms_void;
1909  if (!((nterms < 4096 ||
1910  (ii->header->total_chunk_size >> ((nterms >> 8) - 6))
1911  > (*b)->header.chunk_size) &&
1912  ((*b)->header.buffer_free >= size + sizeof(buffer_term)))) {
1913  buffer_close(ctx, ii, pseg);
1914  return NOT_ASSIGNED;
1915  }
1916  }
1917  return pseg;
1918 }
1919 
1920 typedef struct {
1921  uint32_t rid;
1922  uint32_t sid;
1923 } docid;
1924 
1925 #define BUFFER_REC_DEL(r) ((r)->jump = 1)
1926 #define BUFFER_REC_DELETED(r) ((r)->jump == 1)
1927 
1928 #define BUFFER_REC_AT(b,pos) ((buffer_rec *)(b) + (pos))
1929 #define BUFFER_REC_POS(b,rec) ((uint16_t)((rec) - (buffer_rec *)(b)))
1930 
1931 inline static void
1932 buffer_term_dump(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_term *bt)
1933 {
1934  int pos, rid, sid;
1935  uint8_t *p;
1936  buffer_rec *r;
1937  GRN_LOG(ctx, GRN_LOG_DEBUG,
1938  "b=(%x %u %u %u)", b->header.chunk, b->header.chunk_size, b->header.buffer_free, b->header.nterms);
1939  GRN_LOG(ctx, GRN_LOG_DEBUG,
1940  "bt=(%u %u %u %u %u)", bt->tid, bt->size_in_chunk, bt->pos_in_chunk, bt->size_in_buffer, bt->pos_in_buffer);
1941  for (pos = bt->pos_in_buffer; pos; pos = r->step) {
1942  r = BUFFER_REC_AT(b, pos);
1943  p = NEXT_ADDR(r);
1944  GRN_B_DEC(rid, p);
1945  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
1946  GRN_B_DEC(sid, p);
1947  } else {
1948  sid = 1;
1949  }
1950  GRN_LOG(ctx, GRN_LOG_DEBUG, "%d=(%d:%d),(%d:%d)", pos, r->jump, r->step, rid, sid);
1951  }
1952 }
1953 
1954 inline static grn_rc
1955 check_jump(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_rec *r, int j)
1956 {
1957  uint16_t i = BUFFER_REC_POS(b, r);
1958  uint8_t *p;
1959  buffer_rec *r2;
1960  docid id, id2;
1961  if (!j) { return GRN_SUCCESS; }
1962  p = NEXT_ADDR(r);
1963  GRN_B_DEC(id.rid, p);
1964  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
1965  GRN_B_DEC(id.sid, p);
1966  } else {
1967  id.sid = 1;
1968  }
1969  if (j == 1) {
1970  GRN_LOG(ctx, GRN_LOG_DEBUG, "deleting! %d(%d:%d)", i, id.rid, id.sid);
1971  return GRN_SUCCESS;
1972  }
1973  r2 = BUFFER_REC_AT(b, j);
1974  p = NEXT_ADDR(r2);
1975  GRN_B_DEC(id2.rid, p);
1976  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
1977  GRN_B_DEC(id2.sid, p);
1978  } else {
1979  id2.sid = 1;
1980  }
1981  if (r2->step == i) {
1982  GRN_LOG(ctx, GRN_LOG_EMERG, "cycle! %d(%d:%d)<->%d(%d:%d)", i, id.rid, id.sid, j, id2.rid, id2.sid);
1983  return GRN_FILE_CORRUPT;
1984  }
1985  if (id2.rid < id.rid || (id2.rid == id.rid && id2.sid <= id.sid)) {
1986  GRN_LOG(ctx, GRN_LOG_CRIT, "invalid jump! %d(%d:%d)(%d:%d)->%d(%d:%d)(%d:%d)", i, r->jump, r->step, id.rid, id.sid, j, r2->jump, r2->step, id2.rid, id2.sid);
1987  return GRN_FILE_CORRUPT;
1988  }
1989  return GRN_SUCCESS;
1990 }
1991 
1992 inline static grn_rc
1993 set_jump_r(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_rec *from, int to)
1994 {
1995  int i, j, max_jump = 100;
1996  buffer_rec *r, *r2;
1997  for (r = from, j = to; j > 1 && max_jump--; r = BUFFER_REC_AT(b, r->step)) {
1998  r2 = BUFFER_REC_AT(b, j);
1999  if (r == r2) { break; }
2000  if (BUFFER_REC_DELETED(r2)) { break; }
2001  if (j == (i = r->jump)) { break; }
2002  if (j == r->step) { break; }
2003  if (check_jump(ctx, ii, b, r, j)) {
2004  ERR(GRN_FILE_CORRUPT, "check_jump failed");
2005  return ctx->rc;
2006  }
2007  r->jump = j;
2008  j = i;
2009  if (!r->step) { return GRN_FILE_CORRUPT; }
2010  }
2011  return GRN_SUCCESS;
2012 }
2013 
2014 #define GET_NUM_BITS(x,n) do {\
2015  n = x;\
2016  n = (n & 0x55555555) + ((n >> 1) & 0x55555555);\
2017  n = (n & 0x33333333) + ((n >> 2) & 0x33333333);\
2018  n = (n & 0x0F0F0F0F) + ((n >> 4) & 0x0F0F0F0F);\
2019  n = (n & 0x00FF00FF) + ((n >> 8) & 0x00FF00FF);\
2020  n = (n & 0x0000FFFF) + ((n >>16) & 0x0000FFFF);\
2021 } while (0)
2022 
2023 inline static grn_rc
2024 buffer_put(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_term *bt,
2025  buffer_rec *rnew, uint8_t *bs, grn_ii_updspec *u, int size)
2026 {
2027  uint8_t *p;
2028  grn_rc rc = GRN_SUCCESS;
2029  docid id_curr = {0, 0}, id_start = {0, 0}, id_post = {0, 0};
2030  buffer_rec *r_curr, *r_start = NULL;
2031  uint16_t last = 0, *lastp = &bt->pos_in_buffer, pos = BUFFER_REC_POS(b, rnew);
2032  int vdelta = 0, delta, delta0 = 0, vhops = 0, nhops = 0, reset = 1;
2033  memcpy(NEXT_ADDR(rnew), bs, size - sizeof(buffer_rec));
2034  for (;;) {
2035  if (!*lastp) {
2036  rnew->step = 0;
2037  rnew->jump = 0;
2038  // smb_wmb();
2039  *lastp = pos;
2040  if (bt->size_in_buffer++ > 1) {
2041  buffer_rec *rhead = BUFFER_REC_AT(b, bt->pos_in_buffer);
2042  rhead->jump = pos;
2043  if (!(bt->size_in_buffer & 1)) {
2044  int n;
2045  buffer_rec *r = BUFFER_REC_AT(b, rhead->step), *r2;
2046  GET_NUM_BITS(bt->size_in_buffer, n);
2047  while (n-- && (r->jump > 1)) {
2048  r2 = BUFFER_REC_AT(b, r->jump);
2049  if (BUFFER_REC_DELETED(r2)) { break; }
2050  r = r2;
2051  }
2052  if (r != rnew) { set_jump_r(ctx, ii, b, r, last); }
2053  }
2054  }
2055  break;
2056  }
2057  r_curr = BUFFER_REC_AT(b, *lastp);
2058  p = NEXT_ADDR(r_curr);
2059  GRN_B_DEC(id_curr.rid, p);
2060  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
2061  GRN_B_DEC(id_curr.sid, p);
2062  } else {
2063  id_curr.sid = 1;
2064  }
2065  if (id_curr.rid < id_post.rid ||
2066  (id_curr.rid == id_post.rid && id_curr.sid < id_post.sid)) {
2067  rc = GRN_FILE_CORRUPT;
2068  ERRSET(ctx, GRN_CRIT, rc, "loop found!!! (%d:%d)->(%d:%d)",
2069  id_post.rid, id_post.sid, id_curr.rid, id_curr.sid);
2070  buffer_term_dump(ctx, ii, b, bt);
2071  bt->pos_in_buffer = 0;
2072  bt->size_in_buffer = 0;
2073  lastp = &bt->pos_in_buffer;
2074  continue;
2075  }
2076  id_post.rid = id_curr.rid;
2077  id_post.sid = id_curr.sid;
2078  if (u->rid < id_curr.rid || (u->rid == id_curr.rid && u->sid <= id_curr.sid)) {
2079  uint16_t step = *lastp, jump = r_curr->jump;
2080  if (u->rid == id_curr.rid) {
2081  if (u->sid == 0) {
2082  while (id_curr.rid == u->rid) {
2083  BUFFER_REC_DEL(r_curr);
2084  if (!(step = r_curr->step)) { break; }
2085  r_curr = BUFFER_REC_AT(b, step);
2086  p = NEXT_ADDR(r_curr);
2087  GRN_B_DEC(id_curr.rid, p);
2088  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
2089  GRN_B_DEC(id_curr.sid, p);
2090  } else {
2091  id_curr.sid = 1;
2092  }
2093  }
2094  } else if (u->sid == id_curr.sid) {
2095  BUFFER_REC_DEL(r_curr);
2096  step = r_curr->step;
2097  }
2098  }
2099  rnew->step = step;
2100  rnew->jump = check_jump(ctx, ii, b, rnew, jump) ? 0 : jump;
2101  // smb_wmb();
2102  *lastp = pos;
2103  break;
2104  }
2105 
2106  if (reset) {
2107  r_start = r_curr;
2108  id_start.rid = id_curr.rid;
2109  id_start.sid = id_curr.sid;
2110  if (!(delta0 = u->rid - id_start.rid)) { delta0 = u->sid - id_start.sid; }
2111  nhops = 0;
2112  vhops = 1;
2113  vdelta = delta0 >> 1;
2114  } else {
2115  if (!(delta = id_curr.rid - id_start.rid)) { delta = id_curr.sid - id_start.sid; }
2116  if (vdelta < delta) {
2117  vdelta += (delta0 >> ++vhops);
2118  r_start = r_curr;
2119  }
2120  if (nhops > vhops) {
2121  set_jump_r(ctx, ii, b, r_start, *lastp);
2122  } else {
2123  nhops++;
2124  }
2125  }
2126 
2127  last = *lastp;
2128  lastp = &r_curr->step;
2129  reset = 0;
2130  {
2131  uint16_t posj = r_curr->jump;
2132  if (posj > 1) {
2133  buffer_rec *rj = BUFFER_REC_AT(b, posj);
2134  if (!BUFFER_REC_DELETED(rj)) {
2135  docid idj;
2136  p = NEXT_ADDR(rj);
2137  GRN_B_DEC(idj.rid, p);
2138  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
2139  GRN_B_DEC(idj.sid, p);
2140  } else {
2141  idj.sid = 1;
2142  }
2143  if (idj.rid < u->rid || (idj.rid == u->rid && idj.sid < u->sid)) {
2144  last = posj;
2145  lastp = &rj->step;
2146  } else {
2147  reset = 1;
2148  }
2149  }
2150  }
2151  }
2152  }
2153  return rc;
2154 }
2155 
2156 /* array */
2157 
2158 inline static uint32_t *
2159 array_at(grn_ctx *ctx, grn_ii *ii, uint32_t id)
2160 {
2161  byte *p = NULL;
2162  uint32_t seg, pseg;
2163  if (id > GRN_ID_MAX) { return NULL; }
2164  seg = id >> W_ARRAY;
2165  if ((pseg = ii->header->ainfo[seg]) == NOT_ASSIGNED) { return NULL; }
2166  GRN_IO_SEG_REF(ii->seg, pseg, p);
2167  if (!p) { return NULL; }
2168  return (uint32_t *)(p + (id & ARRAY_MASK_IN_A_SEGMENT) * S_ARRAY_ELEMENT);
2169 }
2170 
2171 inline static uint32_t *
2172 array_get(grn_ctx *ctx, grn_ii *ii, uint32_t id)
2173 {
2174  byte *p = NULL;
2175  uint16_t seg;
2176  uint32_t pseg;
2177  if (id > GRN_ID_MAX) { return NULL; }
2178  seg = id >> W_ARRAY;
2179  if ((pseg = ii->header->ainfo[seg]) == NOT_ASSIGNED) {
2180  if (segment_get_clear(ctx, ii, &pseg)) { return NULL; }
2181  ii->header->ainfo[seg] = pseg;
2182  if (seg >= ii->header->amax) { ii->header->amax = seg + 1; }
2183  }
2184  GRN_IO_SEG_REF(ii->seg, pseg, p);
2185  if (!p) { return NULL; }
2186  return (uint32_t *)(p + (id & ARRAY_MASK_IN_A_SEGMENT) * S_ARRAY_ELEMENT);
2187 }
2188 
2189 inline static void
2190 array_unref(grn_ii *ii, uint32_t id)
2191 {
2192  GRN_IO_SEG_UNREF(ii->seg, ii->header->ainfo[id >> W_ARRAY]);
2193 }
2194 
2195 /* updspec */
2196 
2198 grn_ii_updspec_open(grn_ctx *ctx, uint32_t rid, uint32_t sid)
2199 {
2200  grn_ii_updspec *u;
2201  if (!(u = GRN_MALLOC(sizeof(grn_ii_updspec)))) { return NULL; }
2202  u->rid = rid;
2203  u->sid = sid;
2204  u->weight = 0;
2205  u->tf = 0;
2206  u->atf = 0;
2207  u->pos = NULL;
2208  u->tail = NULL;
2209  // u->vnodes = NULL;
2210  return u;
2211 }
2212 
2213 #define GRN_II_MAX_TF 0x1ffff
2214 
2215 grn_rc
2216 grn_ii_updspec_add(grn_ctx *ctx, grn_ii_updspec *u, int pos, int32_t weight)
2217 {
2218  struct _grn_ii_pos *p;
2219  u->atf++;
2220  if (u->tf >= GRN_II_MAX_TF) { return GRN_SUCCESS; }
2221  if (!(p = GRN_MALLOC(sizeof(struct _grn_ii_pos)))) {
2222  return GRN_NO_MEMORY_AVAILABLE;
2223  }
2224  u->weight += weight;
2225  p->pos = pos;
2226  p->next = NULL;
2227  if (u->tail) {
2228  u->tail->next = p;
2229  } else {
2230  u->pos = p;
2231  }
2232  u->tail = p;
2233  u->tf++;
2234  return GRN_SUCCESS;
2235 }
2236 
2237 int
2239 {
2240  struct _grn_ii_pos *pa, *pb;
2241  if (a->rid != b->rid) { return a->rid - b->rid; }
2242  if (a->sid != b->sid) { return a->sid - b->sid; }
2243  if (a->weight != b->weight) { return a->weight - b->weight; }
2244  if (a->tf != b->tf) { return a->tf - b->tf; }
2245  for (pa = a->pos, pb = b->pos; pa && pb; pa = pa->next, pb = pb->next) {
2246  if (pa->pos != pb->pos) { return pa->pos - pb->pos; }
2247  }
2248  if (pa) { return 1; }
2249  if (pb) { return -1; }
2250  return 0;
2251 }
2252 
2253 grn_rc
2255 {
2256  struct _grn_ii_pos *p = u->pos, *q;
2257  while (p) {
2258  q = p->next;
2259  GRN_FREE(p);
2260  p = q;
2261  }
2262  GRN_FREE(u);
2263  return GRN_SUCCESS;
2264 }
2265 
2266 inline static uint8_t *
2267 encode_rec(grn_ctx *ctx, grn_ii *ii, grn_ii_updspec *u, unsigned int *size, int deletep)
2268 {
2269  uint8_t *br, *p;
2270  struct _grn_ii_pos *pp;
2271  uint32_t lpos, tf, weight;
2272  if (deletep) {
2273  tf = 0;
2274  weight = 0;
2275  } else {
2276  tf = u->tf;
2277  weight = u->weight;
2278  }
2279  if (!(br = GRN_MALLOC((tf + 4) * 5))) {
2280  return NULL;
2281  }
2282  p = br;
2283  GRN_B_ENC(u->rid, p);
2284  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
2285  GRN_B_ENC(u->sid, p);
2286  } else {
2287  u->sid = 1;
2288  }
2289  GRN_B_ENC(tf, p);
2290  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { GRN_B_ENC(weight, p); }
2291  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
2292  for (lpos = 0, pp = u->pos; pp && tf--; lpos = pp->pos, pp = pp->next) {
2293  GRN_B_ENC(pp->pos - lpos, p);
2294  }
2295  }
2296  while (((intptr_t)p & 0x03)) { *p++ = 0; }
2297  *size = (unsigned int) ((p - br) + sizeof(buffer_rec));
2298  return br;
2299 }
2300 
2301 typedef struct {
2305 
2306 #ifdef CASCADE_DELETE_LEXICON
2307 static int
2308 lexicon_deletable(grn_ctx *ctx, grn_obj *lexicon, grn_id tid, void *arg)
2309 {
2310  uint32_t *a;
2311  grn_hash *h = ((lexicon_deletable_arg *)arg)->h;
2312  grn_ii *ii = ((lexicon_deletable_arg *)arg)->ii;
2313  if (!h) { return 0; }
2314  if ((a = array_at(ctx, ii, tid))) {
2315  if (a[0]) {
2316  array_unref(ii, tid);
2317  return 0;
2318  }
2319  array_unref(ii, tid);
2320  }
2321  {
2322  grn_ii_updspec **u;
2323  if (!grn_hash_get(ctx, h, &tid, sizeof(grn_id), (void **) &u)) {
2324  return (ERRP(ctx, GRN_ERROR)) ? 0 : 1;
2325  }
2326  if (!(*u)->tf || !(*u)->sid) { return 1; }
2327  return 0;
2328  }
2329 }
2330 #endif /* CASCADE_DELETE_LEXICON */
2331 
2332 inline static void
2333 lexicon_delete(grn_ctx *ctx, grn_ii *ii, uint32_t tid, grn_hash *h)
2334 {
2335 #ifdef CASCADE_DELETE_LEXICON
2336  lexicon_deletable_arg arg = {ii, h};
2337  grn_table_delete_optarg optarg = {0, lexicon_deletable, &arg};
2338  _grn_table_delete_by_id(ctx, ii->lexicon, tid, &optarg);
2339 #endif /* CASCADE_DELETE_LEXICON */
2340 }
2341 
2342 typedef struct {
2344  uint32_t sid;
2345  uint32_t tf;
2346  uint32_t weight;
2347  uint32_t flags;
2348 } docinfo;
2349 
2350 #define GETNEXTC() do {\
2351  if (sdf) {\
2352  uint32_t dgap = *srp++;\
2353  cid.rid += dgap;\
2354  if (dgap) { cid.sid = 0; }\
2355  snp += cid.tf;\
2356  cid.tf = 1 + *stp++;\
2357  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { cid.weight = *sop++; }\
2358  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {\
2359  cid.sid += 1 + *ssp++;\
2360  } else {\
2361  cid.sid = 1;\
2362  }\
2363  sdf--;\
2364  } else {\
2365  cid.rid = 0;\
2366  }\
2367 } while (0)
2368 
2369 #define PUTNEXT_(id) do {\
2370  uint32_t dgap = id.rid - lid.rid;\
2371  uint32_t sgap = (dgap ? id.sid : id.sid - lid.sid) - 1;\
2372  *ridp++ = dgap;\
2373  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {\
2374  *sidp++ = sgap;\
2375  }\
2376  *tfp++ = id.tf - 1;\
2377  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { *weightp++ = id.weight; }\
2378  lid.rid = id.rid;\
2379  lid.sid = id.sid;\
2380 } while (0)
2381 
2382 #define PUTNEXTC() do {\
2383  if (cid.rid) {\
2384  if (cid.tf) {\
2385  if (lid.rid > cid.rid || (lid.rid == cid.rid && lid.sid >= cid.sid)) {\
2386  GRN_LOG(ctx, GRN_LOG_CRIT, "brokenc!! (%d:%d) -> (%d:%d)", lid.rid, lid.sid, bid.rid, bid.sid);\
2387  rc = GRN_FILE_CORRUPT;\
2388  break;\
2389  }\
2390  PUTNEXT_(cid);\
2391  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {\
2392  uint32_t i;\
2393  for (i = 0; i < cid.tf; i++) {\
2394  *posp++ = snp[i];\
2395  spos += snp[i];\
2396  }\
2397  }\
2398  } else {\
2399  GRN_LOG(ctx, GRN_LOG_CRIT, "invalid chunk(%d,%d)", bt->tid, cid.rid);\
2400  rc = GRN_FILE_CORRUPT;\
2401  break;\
2402  }\
2403  }\
2404  GETNEXTC();\
2405 } while (0)
2406 
2407 #define GETNEXTB() do {\
2408  if (nextb) {\
2409  uint32_t lrid = bid.rid, lsid = bid.sid;\
2410  buffer_rec *br = BUFFER_REC_AT(sb, nextb);\
2411  sbp = NEXT_ADDR(br);\
2412  GRN_B_DEC(bid.rid, sbp);\
2413  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {\
2414  GRN_B_DEC(bid.sid, sbp);\
2415  } else {\
2416  bid.sid = 1;\
2417  }\
2418  if (lrid > bid.rid || (lrid == bid.rid && lsid >= bid.sid)) {\
2419  GRN_LOG(ctx, GRN_LOG_CRIT, "brokeng!! (%d:%d) -> (%d:%d)", lrid, lsid, bid.rid, bid.sid);\
2420  rc = GRN_FILE_CORRUPT;\
2421  break;\
2422  }\
2423  nextb = br->step;\
2424  } else {\
2425  bid.rid = 0;\
2426  }\
2427 } while (0)
2428 
2429 #define PUTNEXTB() do {\
2430  if (bid.rid && bid.sid) {\
2431  GRN_B_DEC(bid.tf, sbp);\
2432  if (bid.tf > 0) {\
2433  if (lid.rid > bid.rid || (lid.rid == bid.rid && lid.sid >= bid.sid)) {\
2434  GRN_LOG(ctx, GRN_LOG_CRIT, "brokenb!! (%d:%d) -> (%d:%d)", lid.rid, lid.sid, bid.rid, bid.sid);\
2435  rc = GRN_FILE_CORRUPT;\
2436  break;\
2437  }\
2438  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { GRN_B_DEC(bid.weight, sbp); }\
2439  PUTNEXT_(bid);\
2440  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {\
2441  while (bid.tf--) { GRN_B_DEC(*posp, sbp); spos += *posp++; }\
2442  }\
2443  }\
2444  }\
2445  GETNEXTB();\
2446 } while (0)
2447 
2448 #define MERGE_BC(cond) do {\
2449  if (bid.rid) {\
2450  if (cid.rid) {\
2451  if (cid.rid < bid.rid) {\
2452  PUTNEXTC();\
2453  } else {\
2454  if (bid.rid < cid.rid) {\
2455  PUTNEXTB();\
2456  } else {\
2457  if (bid.sid) {\
2458  if (cid.sid < bid.sid) {\
2459  PUTNEXTC();\
2460  } else {\
2461  if (bid.sid == cid.sid) { GETNEXTC(); }\
2462  PUTNEXTB();\
2463  }\
2464  } else {\
2465  GETNEXTC();\
2466  }\
2467  }\
2468  }\
2469  } else {\
2470  PUTNEXTB();\
2471  }\
2472  } else {\
2473  if (cid.rid) {\
2474  PUTNEXTC();\
2475  } else {\
2476  break;\
2477  }\
2478  }\
2479 } while (cond)
2480 
2481 typedef struct {
2482  uint32_t segno;
2483  uint32_t size;
2484  uint32_t dgap;
2485 } chunk_info;
2486 
2487 static grn_rc
2488 chunk_flush(grn_ctx *ctx, grn_ii *ii, chunk_info *cinfo, uint8_t *enc, uint32_t encsize)
2489 {
2490  grn_rc rc;
2491  uint8_t *dc;
2492  uint32_t dcn;
2493  grn_io_win dw;
2494  if (!(rc = chunk_new(ctx, ii, &dcn, encsize))) {
2495  if ((dc = WIN_MAP2(ii->chunk, ctx, &dw, dcn, 0, encsize, grn_io_wronly))) {
2496  memcpy(dc, enc, encsize);
2497  grn_io_win_unmap2(&dw);
2498  cinfo->segno = dcn;
2499  cinfo->size = encsize;
2500  rc = GRN_SUCCESS;
2501  } else {
2502  chunk_free(ctx, ii, dcn, 0, encsize);
2504  }
2505  }
2506  return rc;
2507 }
2508 
2509 static grn_rc
2510 chunk_merge(grn_ctx *ctx, grn_ii *ii, buffer *sb, buffer_term *bt,
2511  chunk_info *cinfo, grn_id rid, datavec *dv,
2512  uint16_t *nextbp, uint8_t **sbpp, docinfo *bidp, int32_t *balance)
2513 {
2514  grn_rc rc;
2515  grn_io_win sw;
2516  uint64_t spos = 0;
2517  uint32_t segno = cinfo->segno, size = cinfo->size, sdf = 0, ndf = 0;
2518  uint32_t *ridp = NULL, *sidp = NULL, *tfp, *weightp = NULL, *posp = NULL;
2519  docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = *bidp;
2520  uint8_t *scp = WIN_MAP2(ii->chunk, ctx, &sw, segno, 0, size, grn_io_rdonly);
2521  if (scp) {
2522  uint16_t nextb = *nextbp;
2523  uint32_t snn = 0, *srp, *ssp = NULL, *stp, *sop = NULL, *snp;
2524  uint8_t *sbp = *sbpp;
2525  datavec rdv[MAX_N_ELEMENTS + 1];
2526  size_t bufsize = S_SEGMENT * ii->n_elements;
2527  datavec_init(ctx, rdv, ii->n_elements, 0, 0);
2528  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
2529  rdv[ii->n_elements - 1].flags = ODD;
2530  }
2531  bufsize += grn_p_decv(ctx, scp, cinfo->size, rdv, ii->n_elements);
2532  // (df in chunk list) = a[1] - sdf;
2533  {
2534  int j = 0;
2535  sdf = rdv[j].data_size;
2536  srp = rdv[j++].data;
2537  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { ssp = rdv[j++].data; }
2538  stp = rdv[j++].data;
2539  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { sop = rdv[j++].data; }
2540  snn = rdv[j].data_size;
2541  snp = rdv[j].data;
2542  }
2543  if (!(rc = datavec_reset(ctx, dv, ii->n_elements, sdf + S_SEGMENT, bufsize))) {
2544  {
2545  int j = 0;
2546  ridp = dv[j++].data;
2547  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { sidp = dv[j++].data; }
2548  tfp = dv[j++].data;
2549  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { weightp = dv[j++].data; }
2550  posp = dv[j].data;
2551  }
2552  GETNEXTC();
2553  MERGE_BC(bid.rid <= rid || cid.rid);
2554  *sbpp = sbp;
2555  *nextbp = nextb;
2556  *bidp = bid;
2557  GRN_ASSERT(posp < dv[ii->n_elements].data);
2558  ndf = ridp - dv[0].data;
2559  }
2560  datavec_fin(ctx, rdv);
2561  grn_io_win_unmap2(&sw);
2562  } else {
2564  }
2565  if (!rc) {
2566  int j = 0;
2567  uint8_t *enc;
2568  uint32_t encsize;
2569  uint32_t np = posp - dv[ii->n_elements - 1].data;
2570  uint32_t f_s = (ndf < 3) ? 0 : USE_P_ENC;
2571  uint32_t f_d = ((ndf < 16) || (ndf <= (lid.rid >> 8))) ? 0 : USE_P_ENC;
2572  dv[j].data_size = ndf; dv[j++].flags = f_d;
2573  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
2574  dv[j].data_size = ndf; dv[j++].flags = f_s;
2575  }
2576  dv[j].data_size = ndf; dv[j++].flags = f_s;
2577  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
2578  dv[j].data_size = ndf; dv[j++].flags = f_s;
2579  }
2580  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
2581  uint32_t f_p = ((np < 32) || (np <= (spos >> 13))) ? 0 : USE_P_ENC;
2582  dv[j].data_size = np; dv[j].flags = f_p|ODD;
2583  }
2584  if ((enc = GRN_MALLOC((ndf * 4 + np) * 2))) {
2585  encsize = grn_p_encv(ctx, dv, ii->n_elements, enc);
2586  if (!(rc = chunk_flush(ctx, ii, cinfo, enc, encsize))) {
2587  chunk_free(ctx, ii, segno, 0, size);
2588  }
2589  GRN_FREE(enc);
2590  } else {
2592  }
2593  }
2594  *balance += (ndf - sdf);
2595  return rc;
2596 }
2597 
2598 static grn_rc
2599 buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h,
2600  buffer *sb, uint8_t *sc, buffer *db, uint8_t *dc)
2601 {
2602  buffer_term *bt;
2603  grn_rc rc = GRN_SUCCESS;
2604  uint8_t *sbp = NULL, *dcp = dc;
2605  datavec dv[MAX_N_ELEMENTS + 1];
2606  datavec rdv[MAX_N_ELEMENTS + 1];
2607  uint16_t n = db->header.nterms, nterms_void = 0;
2608  size_t unitsize = (S_SEGMENT + sb->header.chunk_size / sb->header.nterms) * 2;
2609  // size_t unitsize = (S_SEGMENT + sb->header.chunk_size) * 2 + (1<<24);
2610  size_t totalsize = unitsize * ii->n_elements;
2611  //todo : realloc
2612  if ((rc = datavec_init(ctx, dv, ii->n_elements, unitsize, totalsize))) {
2613  return rc;
2614  }
2615  datavec_init(ctx, rdv, ii->n_elements, 0, 0);
2616  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
2617  rdv[ii->n_elements - 1].flags = ODD;
2618  }
2619  for (bt = db->terms; n; n--, bt++) {
2620  uint16_t nextb;
2621  uint64_t spos = 0;
2622  int32_t balance = 0;
2623  uint32_t *ridp, *sidp = NULL, *tfp, *weightp = NULL, *posp, nchunks = 0;
2624  chunk_info *cinfo = NULL;
2625  grn_id crid = GRN_ID_NIL;
2626  docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = {0, 0};
2627  uint32_t sdf = 0, snn = 0, ndf;
2628  uint32_t *srp = NULL, *ssp = NULL, *stp = NULL, *sop = NULL, *snp = NULL;
2629  if (!bt->tid) {
2630  nterms_void++;
2631  continue;
2632  }
2633  if (!bt->pos_in_buffer) {
2634  GRN_ASSERT(!bt->size_in_buffer);
2635  if (bt->size_in_chunk) {
2636  memcpy(dcp, sc + bt->pos_in_chunk, bt->size_in_chunk);
2637  bt->pos_in_chunk = (uint32_t)(dcp - dc);
2638  dcp += bt->size_in_chunk;
2639  }
2640  continue;
2641  }
2642  nextb = bt->pos_in_buffer;
2643  GETNEXTB();
2644  if (sc && bt->size_in_chunk) {
2645  uint8_t *scp = sc + bt->pos_in_chunk;
2646  uint8_t *sce = scp + bt->size_in_chunk;
2647  size_t size = S_SEGMENT * ii->n_elements;
2648  if ((bt->tid & CHUNK_SPLIT)) {
2649  int i;
2650  GRN_B_DEC(nchunks, scp);
2651  if (!(cinfo = GRN_MALLOCN(chunk_info, nchunks + 1))) {
2652  datavec_fin(ctx, dv);
2653  datavec_fin(ctx, rdv);
2654  return GRN_NO_MEMORY_AVAILABLE;
2655  }
2656  for (i = 0; i < nchunks; i++) {
2657  GRN_B_DEC(cinfo[i].segno, scp);
2658  GRN_B_DEC(cinfo[i].size, scp);
2659  GRN_B_DEC(cinfo[i].dgap, scp);
2660  crid += cinfo[i].dgap;
2661  if (bid.rid <= crid) {
2662  rc = chunk_merge(ctx, ii, sb, bt, &cinfo[i], crid, dv,
2663  &nextb, &sbp, &bid, &balance);
2664  if (rc) {
2665  datavec_fin(ctx, dv);
2666  datavec_fin(ctx, rdv);
2667  return rc;
2668  }
2669  }
2670  }
2671  }
2672  if (sce > scp) {
2673  size += grn_p_decv(ctx, scp, sce - scp, rdv, ii->n_elements);
2674  {
2675  int j = 0;
2676  sdf = rdv[j].data_size;
2677  srp = rdv[j++].data;
2678  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { ssp = rdv[j++].data; }
2679  stp = rdv[j++].data;
2680  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { sop = rdv[j++].data; }
2681  snn = rdv[j].data_size;
2682  snp = rdv[j].data;
2683  }
2684  if ((rc = datavec_reset(ctx, dv, ii->n_elements, sdf + S_SEGMENT, size))) {
2685  datavec_fin(ctx, dv);
2686  datavec_fin(ctx, rdv);
2687  return rc;
2688  }
2689  }
2690  }
2691  {
2692  int j = 0;
2693  ridp = dv[j++].data;
2694  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { sidp = dv[j++].data; }
2695  tfp = dv[j++].data;
2696  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { weightp = dv[j++].data; }
2697  posp = dv[j].data;
2698  }
2699  GETNEXTC();
2700  MERGE_BC(1);
2701  GRN_ASSERT(posp < dv[ii->n_elements].data);
2702  ndf = ridp - dv[0].data;
2703  /*
2704  {
2705  grn_obj buf;
2706  uint32_t rid, sid, tf, i, pos, *pp;
2707  GRN_TEXT_INIT(&buf, 0);
2708  rid = 0;
2709  pp = dv[3].data;
2710  for (i = 0; i < ndf; i++) {
2711  GRN_BULK_REWIND(&buf);
2712  rid += dv[0].data[i];
2713  if (dv[0].data[i]) { sid = 0; }
2714  sid += dv[1].data[i] + 1;
2715  tf = dv[2].data[i] + 1;
2716  pos = 0;
2717  grn_text_itoa(ctx, &buf, rid);
2718  GRN_TEXT_PUTC(ctx, &buf, ':');
2719  grn_text_itoa(ctx, &buf, sid);
2720  GRN_TEXT_PUTC(ctx, &buf, ':');
2721  grn_text_itoa(ctx, &buf, tf);
2722  GRN_TEXT_PUTC(ctx, &buf, ':');
2723  while (tf--) {
2724  pos += *pp++;
2725  grn_text_itoa(ctx, &buf, pos);
2726  if (tf) { GRN_TEXT_PUTC(ctx, &buf, ','); }
2727  }
2728  GRN_TEXT_PUTC(ctx, &buf, '\0');
2729  GRN_LOG(ctx, GRN_LOG_NOTICE, "Posting:%s", GRN_TEXT_VALUE(&buf));
2730  }
2731  GRN_OBJ_FIN(ctx, &buf);
2732  }
2733  */
2734  {
2735  grn_id tid = bt->tid & GRN_ID_MAX;
2736  uint32_t *a = array_at(ctx, ii, tid);
2737  if (!a) {
2738  GRN_LOG(ctx, GRN_LOG_NOTICE, "array_entry not found tid=%d", tid);
2739  memset(bt, 0, sizeof(buffer_term));
2740  nterms_void++;
2741  } else {
2742  if (!ndf && !nchunks) {
2743  a[0] = 0;
2744  a[1] = 0;
2745  lexicon_delete(ctx, ii, tid, h);
2746  memset(bt, 0, sizeof(buffer_term));
2747  nterms_void++;
2748  } else if ((ii->header->flags & GRN_OBJ_WITH_SECTION)
2749  && !nchunks && ndf == 1 && lid.rid < 0x100000 &&
2750  lid.sid < 0x800 && lid.tf == 1 && lid.weight == 0) {
2751  a[0] = (lid.rid << 12) + (lid.sid << 1) + 1;
2752  a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0;
2753  memset(bt, 0, sizeof(buffer_term));
2754  nterms_void++;
2755  } else if (!(ii->header->flags & GRN_OBJ_WITH_SECTION)
2756  && !nchunks && ndf == 1 && lid.tf == 1 && lid.weight == 0) {
2757  a[0] = (lid.rid << 1) + 1;
2758  a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0;
2759  memset(bt, 0, sizeof(buffer_term));
2760  nterms_void++;
2761  } else {
2762  int j = 0;
2763  uint8_t *dcp0;
2764  uint32_t encsize;
2765  uint32_t f_s = (ndf < 3) ? 0 : USE_P_ENC;
2766  uint32_t f_d = ((ndf < 16) || (ndf <= (lid.rid >> 8))) ? 0 : USE_P_ENC;
2767  dv[j].data_size = ndf; dv[j++].flags = f_d;
2768  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
2769  dv[j].data_size = ndf; dv[j++].flags = f_s;
2770  }
2771  dv[j].data_size = ndf; dv[j++].flags = f_s;
2772  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
2773  dv[j].data_size = ndf; dv[j++].flags = f_s;
2774  }
2775  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
2776  uint32_t np = posp - dv[ii->n_elements - 1].data;
2777  uint32_t f_p = ((np < 32) || (np <= (spos >> 13))) ? 0 : USE_P_ENC;
2778  dv[j].data_size = np; dv[j].flags = f_p|ODD;
2779  }
2780  dcp0 = dcp;
2781  a[1] = (bt->size_in_chunk ? a[1] : 0) + (ndf - sdf) + balance;
2782  if (nchunks) {
2783  int i;
2784  GRN_B_ENC(nchunks, dcp);
2785  for (i = 0; i < nchunks; i++) {
2786  GRN_B_ENC(cinfo[i].segno, dcp);
2787  GRN_B_ENC(cinfo[i].size, dcp);
2788  GRN_B_ENC(cinfo[i].dgap, dcp);
2789  }
2790  }
2791  encsize = grn_p_encv(ctx, dv, ii->n_elements, dcp);
2792 
2793  if (sb->header.chunk_size + S_SEGMENT <= (dcp - dc) + encsize) {
2794  int i;
2795  char buf[255], *bufp;
2796  GRN_LOG(ctx, GRN_LOG_NOTICE,
2797  "cs(%d)+(%d)=(%d)<=(%" GRN_FMT_LLD ")+(%d)=(%" GRN_FMT_LLD ")",
2799  (long long int)(dcp - dc), encsize, (long long int)((dcp - dc) + encsize));
2800  for (j = 0; j < ii->n_elements; j++) {
2801  GRN_LOG(ctx, GRN_LOG_NOTICE, "rdv[%d] data_size=%d, flags=%d",
2802  j, rdv[j].data_size, rdv[j].flags);
2803  for (i = 0, bufp = buf; i < rdv[j].data_size;) {
2804  bufp += sprintf(bufp, " %d", rdv[j].data[i]);
2805  i++;
2806  if (!(i % 32) || i == rdv[j].data_size) {
2807  GRN_LOG(ctx, GRN_LOG_NOTICE, "rdv[%d].data[%d]%s", j, i, buf);
2808  bufp = buf;
2809  }
2810  }
2811  }
2812 
2813  for (j = 0; j < ii->n_elements; j++) {
2814  GRN_LOG(ctx, GRN_LOG_NOTICE, "dv[%d] data_size=%d, flags=%d",
2815  j, dv[j].data_size, dv[j].flags);
2816  for (i = 0, bufp = buf; i < dv[j].data_size;) {
2817  bufp += sprintf(bufp, " %d", dv[j].data[i]);
2818  i++;
2819  if (!(i % 32) || i == dv[j].data_size) {
2820  GRN_LOG(ctx, GRN_LOG_NOTICE, "dv[%d].data[%d]%s", j, i, buf);
2821  bufp = buf;
2822  }
2823  }
2824  }
2825 
2826  }
2827 
2828  if (encsize > CHUNK_SPLIT_THRESHOLD &&
2829  (cinfo || (cinfo = GRN_MALLOCN(chunk_info, nchunks + 1))) &&
2830  !chunk_flush(ctx, ii, &cinfo[nchunks], dcp, encsize)) {
2831  int i;
2832  cinfo[nchunks].dgap = lid.rid - crid;
2833  nchunks++;
2834  dcp = dcp0;
2835  GRN_B_ENC(nchunks, dcp);
2836  for (i = 0; i < nchunks; i++) {
2837  GRN_B_ENC(cinfo[i].segno, dcp);
2838  GRN_B_ENC(cinfo[i].size, dcp);
2839  GRN_B_ENC(cinfo[i].dgap, dcp);
2840  }
2841  GRN_LOG(ctx, GRN_LOG_NOTICE, "split (%d) encsize=%d", tid, encsize);
2842  bt->tid |= CHUNK_SPLIT;
2843  } else {
2844  dcp += encsize;
2845  }
2846  bt->pos_in_chunk = (uint32_t)(dcp0 - dc);
2847  bt->size_in_chunk = (uint32_t)(dcp - dcp0);
2848  bt->size_in_buffer = 0;
2849  bt->pos_in_buffer = 0;
2850  }
2851  array_unref(ii, tid);
2852  }
2853  }
2854  if (cinfo) { GRN_FREE(cinfo); }
2855  }
2856  datavec_fin(ctx, rdv);
2857  datavec_fin(ctx, dv);
2858  db->header.chunk_size = (uint32_t)(dcp - dc);
2859  db->header.buffer_free =
2860  S_SEGMENT - sizeof(buffer_header) - db->header.nterms * sizeof(buffer_term);
2861  db->header.nterms_void = nterms_void;
2862  return rc;
2863 }
2864 
2865 static void
2866 fake_map2(grn_ctx *ctx, grn_io *io, grn_io_win *iw, void *addr, uint32_t seg, uint32_t size)
2867 {
2868  iw->ctx = ctx;
2869  iw->diff = 0;
2870  iw->io = io;
2871  iw->mode = grn_io_wronly;
2872  iw->segment = ((seg) >> GRN_II_N_CHUNK_VARIATION);
2873  iw->offset = (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK);
2874  iw->size = size;
2875  iw->cached = 0;
2876  iw->addr = addr;
2877 }
2878 
2879 static grn_rc
2880 buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
2881 {
2882  grn_rc rc;
2883  grn_io_win sw, dw;
2884  buffer *sb, *db = NULL;
2885  uint8_t *dc, *sc = NULL;
2886  uint32_t ds, pseg, scn, dcn = 0;
2887  if (ii->header->binfo[seg] == NOT_ASSIGNED) { return GRN_FILE_CORRUPT; }
2888  if ((ds = segment_get(ctx, ii)) == MAX_PSEG) { return GRN_NO_MEMORY_AVAILABLE; }
2889  pseg = buffer_open(ctx, ii, SEG2POS(seg, 0), NULL, &sb);
2890  if (pseg != NOT_ASSIGNED) {
2891  GRN_IO_SEG_REF(ii->seg, ds, db);
2892  if (db) {
2893  uint32_t actual_chunk_size = 0;
2894  uint32_t max_dest_chunk_size = sb->header.chunk_size + S_SEGMENT;
2895  if ((dc = GRN_MALLOC(max_dest_chunk_size * 2))) {
2896  if ((scn = sb->header.chunk) == NOT_ASSIGNED ||
2897  (sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0,
2898  sb->header.chunk_size, grn_io_rdonly))) {
2899  uint16_t n = sb->header.nterms;
2900  memset(db, 0, S_SEGMENT);
2901  memcpy(db->terms, sb->terms, n * sizeof(buffer_term));
2902  db->header.nterms = n;
2903  if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db, dc))) {
2904  actual_chunk_size = db->header.chunk_size;
2905  if (actual_chunk_size >= max_dest_chunk_size) {
2906  GRN_LOG(ctx, GRN_LOG_WARNING, "actual_chunk_size(%d) >= max_dest_chunk_size(%d)",
2907  actual_chunk_size, max_dest_chunk_size);
2908  }
2909  if (!actual_chunk_size || !(rc = chunk_new(ctx, ii, &dcn, actual_chunk_size))) {
2910  db->header.chunk = actual_chunk_size ? dcn : NOT_ASSIGNED;
2911  fake_map2(ctx, ii->chunk, &dw, dc, dcn, actual_chunk_size);
2912  if (!(rc = grn_io_win_unmap2(&dw))) {
2913  buffer_segment_update(ii, seg, ds);
2914  ii->header->total_chunk_size += actual_chunk_size;
2915  if (scn != NOT_ASSIGNED) {
2916  grn_io_win_unmap2(&sw);
2917  chunk_free(ctx, ii, scn, 0, sb->header.chunk_size);
2919  }
2920  } else {
2921  GRN_FREE(dc);
2922  if (actual_chunk_size) {
2923  chunk_free(ctx, ii, dcn, 0, actual_chunk_size);
2924  }
2925  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
2926  }
2927  } else {
2928  GRN_FREE(dc);
2929  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
2930  }
2931  } else {
2932  GRN_FREE(dc);
2933  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
2934  }
2935  } else {
2936  GRN_FREE(dc);
2938  }
2939  } else {
2941  }
2942  GRN_IO_SEG_UNREF(ii->seg, ds);
2943  } else {
2945  }
2946  buffer_close(ctx, ii, pseg);
2947  } else {
2949  }
2950  return rc;
2951 }
2952 
2953 void
2954 grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg)
2955 {
2956  grn_rc rc;
2957  grn_io_win sw;
2958  buffer *sb;
2959  uint8_t *sc = NULL;
2960  uint32_t pseg, scn, nterms_with_corrupt_chunk = 0, nterm_with_chunk = 0;
2961  uint32_t ndeleted_terms_with_value = 0;
2962  buffer_term *bt;
2963  uint8_t *sbp = NULL;
2964  datavec rdv[MAX_N_ELEMENTS + 1];
2965  uint16_t n;
2966  int nterms_void = 0;
2967  int size_in_buffer = 0;
2968  grn_obj buf;
2969  size_t lower_bound;
2970  int64_t nloops = 0, nviolations = 0;
2971  if (ii->header->binfo[seg] == NOT_ASSIGNED) {
2973  return;
2974  }
2975  pseg = buffer_open(ctx, ii, SEG2POS(seg, 0), NULL, &sb);
2976  if (pseg == NOT_ASSIGNED) {
2978  return;
2979  }
2980  lower_bound =
2981  (sb->header.buffer_free + sizeof(buffer_term) * sb->header.nterms)
2982  / sizeof(buffer_rec);
2983  datavec_init(ctx, rdv, ii->n_elements, 0, 0);
2984  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
2985  rdv[ii->n_elements - 1].flags = ODD;
2986  }
2987  GRN_OUTPUT_MAP_OPEN("BUFFER", -1);
2988  GRN_OUTPUT_CSTR("buffer id");
2989  GRN_OUTPUT_INT64(seg);
2990  if ((scn = sb->header.chunk) == NOT_ASSIGNED) {
2991  GRN_OUTPUT_CSTR("void chunk size");
2993  } else {
2994  if ((sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0, sb->header.chunk_size, grn_io_rdonly))) {
2995  GRN_OUTPUT_CSTR("chunk size");
2997  } else {
2998  GRN_OUTPUT_CSTR("unmappable chunk size");
3000  }
3001  }
3002  GRN_OUTPUT_CSTR("buffer term");
3003  GRN_OUTPUT_ARRAY_OPEN("TERMS", sb->header.nterms);
3004 
3005  GRN_OBJ_INIT(&buf, GRN_BULK, 0, ii->lexicon->header.domain);
3006  for (bt = sb->terms, n = sb->header.nterms; n; n--, bt++) {
3007  grn_id tid, tid_;
3008  char key[GRN_TABLE_MAX_KEY_SIZE];
3009  int key_size;
3010  uint16_t nextb;
3011  uint32_t nchunks = 0;
3012  chunk_info *cinfo = NULL;
3013  grn_id crid = GRN_ID_NIL;
3014  docinfo bid = {0, 0};
3015  uint32_t sdf = 0, snn = 0;
3016  uint32_t *srp = NULL, *ssp = NULL, *stp = NULL, *sop = NULL, *snp = NULL;
3017  if (!bt->tid && !bt->pos_in_buffer && !bt->size_in_buffer) {
3018  nterms_void++;
3019  continue;
3020  }
3021  GRN_OUTPUT_ARRAY_OPEN("TERM", -1);
3022  tid = (bt->tid & GRN_ID_MAX);
3023  key_size = grn_table_get_key(ctx, ii->lexicon, tid, key, GRN_TABLE_MAX_KEY_SIZE);
3024  tid_ = grn_table_get(ctx, ii->lexicon, key, key_size);
3025  GRN_TEXT_SET(ctx, &buf, key, key_size);
3026  GRN_OUTPUT_OBJ(&buf, NULL);
3027  GRN_OUTPUT_INT64(bt->tid);
3028  GRN_OUTPUT_INT64(tid_);
3029  nextb = bt->pos_in_buffer;
3030  size_in_buffer += bt->size_in_buffer;
3031  if (tid != tid_ && (bt->size_in_buffer || bt->size_in_chunk)) {
3032  ndeleted_terms_with_value++;
3033  }
3034  GETNEXTB();
3037  if (sc && bt->size_in_chunk) {
3038  uint8_t *scp = sc + bt->pos_in_chunk;
3039  uint8_t *sce = scp + bt->size_in_chunk;
3040  size_t size = S_SEGMENT * ii->n_elements;
3041  if ((bt->tid & CHUNK_SPLIT)) {
3042  int i;
3043  GRN_B_DEC(nchunks, scp);
3044  if (!(cinfo = GRN_MALLOCN(chunk_info, nchunks + 1))) {
3045  datavec_fin(ctx, rdv);
3046  GRN_OBJ_FIN(ctx, &buf);
3047  return;
3048  }
3049  for (i = 0; i < nchunks; i++) {
3050  GRN_B_DEC(cinfo[i].segno, scp);
3051  GRN_B_DEC(cinfo[i].size, scp);
3052  GRN_B_DEC(cinfo[i].dgap, scp);
3053  crid += cinfo[i].dgap;
3054  }
3055  }
3056  if (sce > scp) {
3057  size += grn_p_decv(ctx, scp, sce - scp, rdv, ii->n_elements);
3058  {
3059  int j = 0;
3060  sdf = rdv[j].data_size;
3061  GRN_OUTPUT_INT64(sdf);
3062  srp = rdv[j++].data;
3063  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { ssp = rdv[j++].data; }
3064  if (sdf != rdv[j].data_size) {
3065  nterms_with_corrupt_chunk++;
3066  }
3067  stp = rdv[j++].data;
3068  if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { sop = rdv[j++].data; }
3069  GRN_OUTPUT_INT64(rdv[j].data_size);
3070  snn = rdv[j].data_size;
3071  snp = rdv[j].data;
3072  }
3073  nterm_with_chunk++;
3074  }
3075  }
3076  {
3077  uint16_t pos;
3078  grn_id rid, sid, rid_ = 0, sid_ = 0;
3079  uint8_t *p;
3080  buffer_rec *r;
3081  for (pos = bt->pos_in_buffer; pos; pos = r->step) {
3082  if (pos < lower_bound) {
3083  nviolations++;
3084  }
3085  r = BUFFER_REC_AT(sb, pos);
3086  p = NEXT_ADDR(r);
3087  GRN_B_DEC(rid, p);
3088  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
3089  GRN_B_DEC(sid, p);
3090  } else {
3091  sid = 1;
3092  }
3093  if (rid < rid_ || (rid == rid_ && sid < sid_)) {
3094  nloops++;
3095  }
3096  rid_ = rid;
3097  sid_ = sid;
3098  }
3099  }
3101  if (cinfo) { GRN_FREE(cinfo); }
3102  }
3103  GRN_OBJ_FIN(ctx, &buf);
3104 
3106  GRN_OUTPUT_CSTR("buffer free");
3108  GRN_OUTPUT_CSTR("size in buffer");
3109  GRN_OUTPUT_INT64(size_in_buffer);
3110  GRN_OUTPUT_CSTR("nterms");
3112  if (nterms_void != sb->header.nterms_void) {
3113  GRN_OUTPUT_CSTR("nterms void gap");
3114  GRN_OUTPUT_INT64(nterms_void - sb->header.nterms_void);
3115  }
3116  GRN_OUTPUT_CSTR("nterms with chunk");
3117  GRN_OUTPUT_INT64(nterm_with_chunk);
3118  if (nterms_with_corrupt_chunk) {
3119  GRN_OUTPUT_CSTR("nterms with corrupt chunk");
3120  GRN_OUTPUT_INT64(nterms_with_corrupt_chunk);
3121  }
3122  if (ndeleted_terms_with_value) {
3123  GRN_OUTPUT_CSTR("number of deleted terms with value");
3124  GRN_OUTPUT_INT64(ndeleted_terms_with_value);
3125  }
3126  if (nloops) {
3127  GRN_OUTPUT_CSTR("number of loops");
3128  GRN_OUTPUT_INT64(nloops);
3129  }
3130  if (nviolations) {
3131  GRN_OUTPUT_CSTR("number of violations");
3132  GRN_OUTPUT_INT64(nviolations);
3133  }
3135  datavec_fin(ctx, rdv);
3136  if (sc) { grn_io_win_unmap2(&sw); }
3137  buffer_close(ctx, ii, pseg);
3138 }
3139 
3140 typedef struct {
3142  const char *key;
3143  uint32_t key_size;
3144 } term_sort;
3145 
3146 static int
3147 term_compar(const void *t1, const void *t2)
3148 {
3149  int r;
3150  const term_sort *x = (term_sort *)t1, *y = (term_sort *)t2;
3151  if (x->key_size > y->key_size) {
3152  return (r = memcmp(x->key, y->key, y->key_size)) ? r : x->key_size - y->key_size;
3153  } else {
3154  return (r = memcmp(x->key, y->key, x->key_size)) ? r : x->key_size - y->key_size;
3155  }
3156 }
3157 
3158 static grn_rc
3159 term_split(grn_ctx *ctx, grn_obj *lexicon, buffer *sb, buffer *db0, buffer *db1)
3160 {
3161  uint16_t i, n, *nt;
3162  buffer_term *bt;
3163  uint32_t s, th = (sb->header.chunk_size + sb->header.nterms) >> 1;
3164  term_sort *ts = GRN_MALLOC(sb->header.nterms * sizeof(term_sort));
3165  if (!ts) { return GRN_NO_MEMORY_AVAILABLE; }
3166  for (i = 0, n = sb->header.nterms, bt = sb->terms; n; bt++, n--) {
3167  if (bt->tid) {
3168  grn_id tid = bt->tid & GRN_ID_MAX;
3169  ts[i].key = _grn_table_key(ctx, lexicon, tid, &ts[i].key_size);
3170  ts[i].bt = bt;
3171  i++;
3172  }
3173  }
3174  qsort(ts, i, sizeof(term_sort), term_compar);
3175  memset(db0, 0, S_SEGMENT);
3176  bt = db0->terms;
3177  nt = &db0->header.nterms;
3178  for (s = 0; n + 1 < i && s <= th; n++, bt++) {
3179  memcpy(bt, ts[n].bt, sizeof(buffer_term));
3180  (*nt)++;
3181  s += ts[n].bt->size_in_chunk + 1;
3182  }
3183  memset(db1, 0, S_SEGMENT);
3184  bt = db1->terms;
3185  nt = &db1->header.nterms;
3186  for (; n < i; n++, bt++) {
3187  memcpy(bt, ts[n].bt, sizeof(buffer_term));
3188  (*nt)++;
3189  }
3190  GRN_FREE(ts);
3191  GRN_LOG(ctx, GRN_LOG_NOTICE, "d0=%d d1=%d", db0->header.nterms, db1->header.nterms);
3192  return GRN_SUCCESS;
3193 }
3194 
3195 static void
3196 array_update(grn_ctx *ctx, grn_ii *ii, uint32_t dls, buffer *db)
3197 {
3198  uint16_t n;
3199  buffer_term *bt;
3200  uint32_t *a, pos = SEG2POS(dls, sizeof(buffer_header));
3201  for (n = db->header.nterms, bt = db->terms; n; n--, bt++) {
3202  if (bt->tid) {
3203  grn_id tid = bt->tid & GRN_ID_MAX;
3204  if ((a = array_at(ctx, ii, tid))) {
3205  a[0] = pos;
3206  array_unref(ii, tid);
3207  } else {
3208  GRN_LOG(ctx, GRN_LOG_WARNING, "array_at failed (%d)", tid);
3209  }
3210  }
3211  pos += sizeof(buffer_term) >> 2;
3212  }
3213 }
3214 
3215 static grn_rc
3216 buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h)
3217 {
3218  grn_rc rc;
3219  grn_io_win sw, dw0, dw1;
3220  buffer *sb, *db0 = NULL, *db1 = NULL;
3221  uint8_t *sc = NULL, *dc0, *dc1;
3222  uint32_t dps0, dps1, dls0, dls1, sps, scn, dcn0 = 0, dcn1 = 0;
3223  if (ii->header->binfo[seg] == NOT_ASSIGNED) { return GRN_FILE_CORRUPT; }
3224  if ((rc = buffer_segment_reserve(ctx, ii, &dls0, &dps0, &dls1, &dps1))) {
3225  return rc;
3226  }
3227  sps = buffer_open(ctx, ii, SEG2POS(seg, 0), NULL, &sb);
3228  if (sps != NOT_ASSIGNED) {
3229  GRN_IO_SEG_REF(ii->seg, dps0, db0);
3230  if (db0) {
3231  GRN_IO_SEG_REF(ii->seg, dps1, db1);
3232  if (db1) {
3233  uint32_t actual_db0_chunk_size = 0;
3234  uint32_t actual_db1_chunk_size = 0;
3235  uint32_t max_dest_chunk_size = sb->header.chunk_size + S_SEGMENT;
3236  if ((dc0 = GRN_MALLOC(max_dest_chunk_size * 2))) {
3237  if ((dc1 = GRN_MALLOC(max_dest_chunk_size * 2))) {
3238  if ((scn = sb->header.chunk) == NOT_ASSIGNED ||
3239  (sc = WIN_MAP2(ii->chunk, ctx, &sw, scn, 0,
3240  sb->header.chunk_size, grn_io_rdonly))) {
3241  term_split(ctx, ii->lexicon, sb, db0, db1);
3242  if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db0, dc0))) {
3243  actual_db0_chunk_size = db0->header.chunk_size;
3244  if (actual_db0_chunk_size >= max_dest_chunk_size) {
3245  GRN_LOG(ctx, GRN_LOG_WARNING,
3246  "actual_db0_chunk_size(%d) >= max_dest_chunk_size(%d)",
3247  actual_db0_chunk_size, max_dest_chunk_size);
3248  }
3249  if (!actual_db0_chunk_size ||
3250  !(rc = chunk_new(ctx, ii, &dcn0, actual_db0_chunk_size))) {
3251  db0->header.chunk = actual_db0_chunk_size ? dcn0 : NOT_ASSIGNED;
3252  fake_map2(ctx, ii->chunk, &dw0, dc0, dcn0, actual_db0_chunk_size);
3253  if (!(rc = grn_io_win_unmap2(&dw0))) {
3254  if (!(rc = buffer_merge(ctx, ii, seg, h, sb, sc, db1, dc1))) {
3255  actual_db1_chunk_size = db1->header.chunk_size;
3256  if (actual_db1_chunk_size >= max_dest_chunk_size) {
3257  GRN_LOG(ctx, GRN_LOG_WARNING,
3258  "actual_db1_chunk_size(%d) >= max_dest_chunk_size(%d)",
3259  actual_db1_chunk_size, max_dest_chunk_size);
3260  }
3261  if (!actual_db1_chunk_size ||
3262  !(rc = chunk_new(ctx, ii, &dcn1, actual_db1_chunk_size))) {
3263  fake_map2(ctx, ii->chunk, &dw1, dc1, dcn1, actual_db1_chunk_size);
3264  if (!(rc = grn_io_win_unmap2(&dw1))) {
3265  db1->header.chunk = actual_db1_chunk_size ? dcn1 : NOT_ASSIGNED;
3266  buffer_segment_update(ii, dls0, dps0);
3267  buffer_segment_update(ii, dls1, dps1);
3268  array_update(ctx, ii, dls0, db0);
3269  array_update(ctx, ii, dls1, db1);
3270  buffer_segment_clear(ii, seg);
3271  ii->header->total_chunk_size += actual_db0_chunk_size;
3272  ii->header->total_chunk_size += actual_db1_chunk_size;
3273  if (scn != NOT_ASSIGNED) {
3274  grn_io_win_unmap2(&sw);
3275  chunk_free(ctx, ii, scn, 0, sb->header.chunk_size);
3277  }
3278  } else {
3279  if (actual_db1_chunk_size) {
3280  chunk_free(ctx, ii, dcn1, 0, actual_db1_chunk_size);
3281  }
3282  if (actual_db0_chunk_size) {
3283  chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
3284  }
3285  GRN_FREE(dc1);
3286  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
3287  }
3288  } else {
3289  if (actual_db0_chunk_size) {
3290  chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
3291  }
3292  GRN_FREE(dc1);
3293  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
3294  }
3295  } else {
3296  if (actual_db0_chunk_size) {
3297  chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
3298  }
3299  GRN_FREE(dc1);
3300  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
3301  }
3302  } else {
3303  if (actual_db0_chunk_size) {
3304  chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size);
3305  }
3306  GRN_FREE(dc1);
3307  GRN_FREE(dc0);
3308  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
3309  }
3310  } else {
3311  GRN_FREE(dc1);
3312  GRN_FREE(dc0);
3313  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
3314  }
3315  } else {
3316  GRN_FREE(dc1);
3317  GRN_FREE(dc0);
3318  if (scn != NOT_ASSIGNED) { grn_io_win_unmap2(&sw); }
3319  }
3320  } else {
3321  GRN_FREE(dc1);
3322  GRN_FREE(dc0);
3324  }
3325  } else {
3326  GRN_FREE(dc0);
3328  }
3329  } else {
3331  }
3332  GRN_IO_SEG_UNREF(ii->seg, dps1);
3333  } else {
3335  }
3336  GRN_IO_SEG_UNREF(ii->seg, dps0);
3337  } else {
3339  }
3340  buffer_close(ctx, ii, sps);
3341  } else {
3343  }
3344  return rc;
3345 }
3346 
3347 #define SCALE_FACTOR 2048
3348 #define MAX_NTERMS 8192
3349 #define SPLIT_COND (b->header.nterms > 1024 ||\
3350  (b->header.nterms > 1 &&\
3351  b->header.chunk_size * 100 > ii->header->total_chunk_size))
3352 
3353 inline static uint32_t
3354 buffer_new(grn_ctx *ctx, grn_ii *ii, int size, uint32_t *pos,
3355  buffer_term **bt, buffer_rec **br, buffer **bp, grn_id id, grn_hash *h)
3356 {
3357  buffer *b = NULL;
3358  grn_id tid;
3359  uint16_t offset;
3360  char key[GRN_TABLE_MAX_KEY_SIZE];
3361  // unsigned int key_size;
3362  // const char *key = _grn_table_key(ctx, ii->lexicon, id, &key_size);
3363  int key_size = grn_table_get_key(ctx, ii->lexicon, id, key, GRN_TABLE_MAX_KEY_SIZE);
3364  uint32_t *a, lseg = NOT_ASSIGNED, pseg = NOT_ASSIGNED;
3365  grn_table_cursor *tc = NULL;
3366  if (ii->lexicon->header.type == GRN_TABLE_PAT_KEY) {
3368  tc = grn_table_cursor_open(ctx, ii->lexicon, key, key_size, NULL, 0, 0, -1,
3370  } else {
3371  tc = grn_table_cursor_open(ctx, ii->lexicon, NULL, 0, key, key_size, 0, -1,
3373  }
3374  } else {
3375  tc = grn_table_cursor_open(ctx, ii->lexicon, NULL, 0, NULL, 0, 0, -1,
3377  }
3378  if (tc) {
3379  while (lseg == NOT_ASSIGNED && (tid = grn_table_cursor_next(ctx, tc))) {
3380  if ((a = array_at(ctx, ii, tid))) {
3381  for (;;) {
3382  uint32_t pos = a[0];
3383  if (!pos || (pos & 1)) { break; }
3384  if ((pseg = buffer_open(ctx, ii, pos, NULL, &b)) == NOT_ASSIGNED) { break; }
3385  if (b->header.buffer_free >= size + sizeof(buffer_term)) {
3386  lseg = LSEG(pos);
3387  break;
3388  }
3389  buffer_close(ctx, ii, pseg);
3390  if (SPLIT_COND)
3391  /* ((S_SEGMENT - sizeof(buffer_header) + ii->header->bmax -
3392  b->header.nterms * sizeof(buffer_term)) * 4 <
3393  b->header.chunk_size) */
3394  {
3395  GRN_LOG(ctx, GRN_LOG_NOTICE,
3396  "nterms=%d chunk=%d total=%" GRN_FMT_INT64U,
3397  b->header.nterms,
3398  b->header.chunk_size,
3399  ii->header->total_chunk_size >> 10);
3400  if (buffer_split(ctx, ii, LSEG(pos), h)) { break; }
3401  } else {
3402  if (buffer_flush(ctx, ii, LSEG(pos), h)) { break; }
3403  }
3404  }
3405  array_unref(ii, tid);
3406  }
3407  }
3408  grn_table_cursor_close(ctx, tc);
3409  }
3410  if (lseg == NOT_ASSIGNED) {
3411  if (buffer_segment_new(ctx, ii, &lseg) ||
3412  (pseg = buffer_open(ctx, ii, SEG2POS(lseg, 0), NULL, &b)) == NOT_ASSIGNED) {
3413  return NOT_ASSIGNED;
3414  }
3415  memset(b, 0, S_SEGMENT);
3416  b->header.buffer_free = S_SEGMENT - sizeof(buffer_header);
3417  b->header.chunk = NOT_ASSIGNED;
3418  }
3419  if (b->header.nterms_void) {
3420  for (offset = 0; offset < b->header.nterms; offset++) {
3421  if (!b->terms[offset].tid) { break; }
3422  }
3423  if (offset == b->header.nterms) {
3424  GRN_LOG(ctx, GRN_LOG_NOTICE, "inconsistent buffer(%d)", lseg);
3425  b->header.nterms_void = 0;
3426  b->header.nterms++;
3427  b->header.buffer_free -= size + sizeof(buffer_term);
3428  } else {
3429  b->header.nterms_void--;
3430  b->header.buffer_free -= size;
3431  }
3432  } else {
3433  offset = b->header.nterms++;
3434  b->header.buffer_free -= size + sizeof(buffer_term);
3435  }
3436  *pos = SEG2POS(lseg, (sizeof(buffer_header) + sizeof(buffer_term) * offset));
3437  *bt = &b->terms[offset];
3438  *br = (buffer_rec *)(((byte *)&b->terms[b->header.nterms]) + b->header.buffer_free);
3439  *bp = b;
3440  return pseg;
3441 }
3442 
3443 /* ii */
3444 
3445 static grn_ii *
3446 _grn_ii_create(grn_ctx *ctx, grn_ii *ii, const char *path, grn_obj *lexicon, uint32_t flags)
3447 {
3448  int i;
3449  grn_io *seg, *chunk;
3450  char path2[PATH_MAX];
3451  struct grn_ii_header *header;
3452  grn_obj_flags lflags;
3453  grn_encoding encoding;
3454  grn_obj *tokenizer;
3455  /*
3456  for (i = 0; i < 32; i++) {
3457  new_histogram[i] = 0;
3458  free_histogram[i] = 0;
3459  }
3460  */
3461  if (grn_table_get_info(ctx, lexicon, &lflags, &encoding, &tokenizer, NULL)) {
3462  return NULL;
3463  }
3464  if (path && strlen(path) + 6 >= PATH_MAX) { return NULL; }
3465  seg = grn_io_create(ctx, path, sizeof(struct grn_ii_header),
3466  S_SEGMENT, GRN_II_MAX_LSEG, grn_io_auto, GRN_IO_EXPIRE_SEGMENT);
3467  if (!seg) { return NULL; }
3468  if (path) {
3469  strcpy(path2, path);
3470  strcat(path2, ".c");
3471  chunk = grn_io_create(ctx, path2, 0, S_CHUNK, GRN_II_MAX_CHUNK, grn_io_auto,
3473  } else {
3474  chunk = grn_io_create(ctx, NULL, 0, S_CHUNK, GRN_II_MAX_CHUNK, grn_io_auto, 0);
3475  }
3476  if (!chunk) {
3477  grn_io_close(ctx, seg);
3478  return NULL;
3479  }
3480  header = grn_io_header(seg);
3482  for (i = 0; i < GRN_II_MAX_LSEG; i++) {
3483  header->ainfo[i] = NOT_ASSIGNED;
3484  header->binfo[i] = NOT_ASSIGNED;
3485  }
3486  for (i = 0; i <= GRN_II_N_CHUNK_VARIATION; i++) {
3487  header->free_chunks[i] = NOT_ASSIGNED;
3488  header->garbages[i] = NOT_ASSIGNED;
3489  }
3490  header->flags = flags;
3491  ii->seg = seg;
3492  ii->chunk = chunk;
3493  ii->lexicon = lexicon;
3494  ii->lflags = lflags;
3495  ii->encoding = encoding;
3496  ii->header = header;
3497  ii->n_elements = 2;
3498  if ((flags & GRN_OBJ_WITH_SECTION)) { ii->n_elements++; }
3499  if ((flags & GRN_OBJ_WITH_WEIGHT)) { ii->n_elements++; }
3500  if ((flags & GRN_OBJ_WITH_POSITION)) { ii->n_elements++; }
3501  return ii;
3502 }
3503 
3504 grn_ii *
3505 grn_ii_create(grn_ctx *ctx, const char *path, grn_obj *lexicon, uint32_t flags)
3506 {
3507  grn_ii *ii = NULL;
3508  if (!(ii = GRN_GMALLOC(sizeof(grn_ii)))) {
3509  return NULL;
3510  }
3512  if (!_grn_ii_create(ctx, ii, path, lexicon, flags)) {
3513  GRN_FREE(ii);
3514  return NULL;
3515  }
3516  return ii;
3517 }
3518 
3519 grn_rc
3520 grn_ii_remove(grn_ctx *ctx, const char *path)
3521 {
3522  grn_rc rc;
3523  char buffer[PATH_MAX];
3524  if (!path || strlen(path) > PATH_MAX - 4) { return GRN_INVALID_ARGUMENT; }
3525  if ((rc = grn_io_remove(ctx, path))) { goto exit; }
3526  snprintf(buffer, PATH_MAX, "%s.c", path);
3527  rc = grn_io_remove(ctx, buffer);
3528 exit :
3529  return rc;
3530 }
3531 
3532 grn_rc
3534 {
3535  grn_rc rc;
3536  const char *io_segpath, *io_chunkpath;
3537  char *segpath, *chunkpath = NULL;
3538  grn_obj *lexicon;
3539  uint32_t flags;
3540  if ((io_segpath = grn_io_path(ii->seg)) && *io_segpath != '\0') {
3541  if (!(segpath = GRN_STRDUP(io_segpath))) {
3542  ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_segpath);
3543  return GRN_NO_MEMORY_AVAILABLE;
3544  }
3545  if ((io_chunkpath = grn_io_path(ii->chunk)) && *io_chunkpath != '\0') {
3546  if (!(chunkpath = GRN_STRDUP(io_chunkpath))) {
3547  ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_chunkpath);
3548  return GRN_NO_MEMORY_AVAILABLE;
3549  }
3550  } else {
3551  chunkpath = NULL;
3552  }
3553  } else {
3554  segpath = NULL;
3555  }
3556  lexicon = ii->lexicon;
3557  flags = ii->header->flags;
3558  if ((rc = grn_io_close(ctx, ii->seg))) { goto exit; }
3559  if ((rc = grn_io_close(ctx, ii->chunk))) { goto exit; }
3560  ii->seg = NULL;
3561  ii->chunk = NULL;
3562  if (segpath && (rc = grn_io_remove(ctx, segpath))) { goto exit; }
3563  if (chunkpath && (rc = grn_io_remove(ctx, chunkpath))) { goto exit; }
3564  if (!_grn_ii_create(ctx, ii, segpath, lexicon, flags)) {
3565  rc = GRN_UNKNOWN_ERROR;
3566  }
3567 exit:
3568  if (segpath) { GRN_FREE(segpath); }
3569  if (chunkpath) { GRN_FREE(chunkpath); }
3570  return rc;
3571 }
3572 
3573 grn_ii *
3574 grn_ii_open(grn_ctx *ctx, const char *path, grn_obj *lexicon)
3575 {
3576  grn_io *seg, *chunk;
3577  grn_ii *ii;
3578  char path2[PATH_MAX];
3579  struct grn_ii_header *header;
3580  grn_obj_flags lflags;
3581  grn_encoding encoding;
3582  grn_obj *tokenizer;
3583  if (grn_table_get_info(ctx, lexicon, &lflags, &encoding, &tokenizer, NULL)) {
3584  return NULL;
3585  }
3586  if (strlen(path) + 6 >= PATH_MAX) { return NULL; }
3587  strcpy(path2, path);
3588  strcat(path2, ".c");
3589  seg = grn_io_open(ctx, path, grn_io_auto);
3590  if (!seg) { return NULL; }
3591  chunk = grn_io_open(ctx, path2, grn_io_auto);
3592  if (!chunk) {
3593  grn_io_close(ctx, seg);
3594  return NULL;
3595  }
3596  header = grn_io_header(seg);
3597  if (grn_io_get_type(seg) != GRN_COLUMN_INDEX) {
3598  ERR(GRN_INVALID_FORMAT, "file type unmatch");
3599  grn_io_close(ctx, seg);
3600  grn_io_close(ctx, chunk);
3601  return NULL;
3602  }
3603  if (!(ii = GRN_GMALLOC(sizeof(grn_ii)))) {
3604  grn_io_close(ctx, seg);
3605  grn_io_close(ctx, chunk);
3606  return NULL;
3607  }
3609  ii->seg = seg;
3610  ii->chunk = chunk;
3611  ii->lexicon = lexicon;
3612  ii->lflags = lflags;
3613  ii->encoding = encoding;
3614  ii->header = header;
3615  ii->n_elements = 2;
3616  if ((header->flags & GRN_OBJ_WITH_SECTION)) { ii->n_elements++; }
3617  if ((header->flags & GRN_OBJ_WITH_WEIGHT)) { ii->n_elements++; }
3618  if ((header->flags & GRN_OBJ_WITH_POSITION)) { ii->n_elements++; }
3619  return ii;
3620 }
3621 
3622 grn_rc
3624 {
3625  grn_rc rc;
3626  if (!ii) { return GRN_INVALID_ARGUMENT; }
3627  if ((rc = grn_io_close(ctx, ii->seg))) { return rc; }
3628  if ((rc = grn_io_close(ctx, ii->chunk))) { return rc; }
3629  GRN_GFREE(ii);
3630  /*
3631  {
3632  int i;
3633  for (i = 0; i < 32; i++) {
3634  GRN_LOG(ctx, GRN_LOG_NOTICE, "new[%d]=%d free[%d]=%d",
3635  i, new_histogram[i],
3636  i, free_histogram[i]);
3637  }
3638  }
3639  */
3640  return rc;
3641 }
3642 
3643 grn_rc
3644 grn_ii_info(grn_ctx *ctx, grn_ii *ii, uint64_t *seg_size, uint64_t *chunk_size)
3645 {
3646  grn_rc rc;
3647 
3648  if (seg_size) {
3649  if ((rc = grn_io_size(ctx, ii->seg, seg_size))) {
3650  return rc;
3651  }
3652  }
3653 
3654  if (chunk_size) {
3655  if ((rc = grn_io_size(ctx, ii->chunk, chunk_size))) {
3656  return rc;
3657  }
3658  }
3659 
3660  return GRN_SUCCESS;
3661 }
3662 
3663 void
3665 {
3666  /*
3667  grn_io_expire(ctx, ii->seg, 128, 1000000);
3668  */
3669  grn_io_expire(ctx, ii->chunk, 0, 1000000);
3670 }
3671 
3672 #define BIT11_01(x) ((x >> 1) & 0x7ff)
3673 #define BIT31_12(x) (x >> 12)
3674 
3675 grn_rc
3677 {
3678  grn_rc rc = GRN_SUCCESS;
3679  buffer *b;
3680  uint8_t *bs;
3681  buffer_rec *br = NULL;
3682  buffer_term *bt;
3683  uint32_t pseg = 0, pos = 0, size, *a;
3684  if (!tid) { return rc; }
3685  if (!u->tf || !u->sid) { return grn_ii_delete_one(ctx, ii, tid, u, h); }
3686  if (u->sid > ii->header->smax) { ii->header->smax = u->sid; }
3687  if (!(a = array_get(ctx, ii, tid))) { return GRN_NO_MEMORY_AVAILABLE; }
3688  if (!(bs = encode_rec(ctx, ii, u, &size, 0))) {
3689  rc = GRN_NO_MEMORY_AVAILABLE; goto exit;
3690  }
3691  for (;;) {
3692  if (a[0]) {
3693  if (!(a[0] & 1)) {
3694  pos = a[0];
3695  if ((pseg = buffer_open(ctx, ii, pos, &bt, &b)) == NOT_ASSIGNED) {
3697  goto exit;
3698  }
3699  if (b->header.buffer_free < size) {
3700  int bfb = b->header.buffer_free;
3701  GRN_LOG(ctx, GRN_LOG_DEBUG, "flushing a[0]=%d seg=%d(%p) free=%d",
3702  a[0], LSEG(a[0]), b, b->header.buffer_free);
3703  buffer_close(ctx, ii, pseg);
3704  if (SPLIT_COND)
3705  /*((S_SEGMENT - sizeof(buffer_header) + ii->header->bmax -
3706  b->header.nterms * sizeof(buffer_term)) * 4 <
3707  b->header.chunk_size)*/
3708  {
3709  GRN_LOG(ctx, GRN_LOG_NOTICE,
3710  "nterms=%d chunk=%d total=%" GRN_FMT_INT64U,
3711  b->header.nterms,
3712  b->header.chunk_size,
3713  ii->header->total_chunk_size >> 10);
3714  if ((rc = buffer_split(ctx, ii, LSEG(pos), h))) { goto exit; }
3715  continue;
3716  }
3717  if ((rc = buffer_flush(ctx, ii, LSEG(pos), h))) { goto exit; }
3718  if (a[0] != pos) {
3719  GRN_LOG(ctx, GRN_LOG_DEBUG, "grn_ii_update_one: a[0] changed %d->%d", a[0], pos);
3720  continue;
3721  }
3722  if ((pseg = buffer_open(ctx, ii, pos, &bt, &b)) == NOT_ASSIGNED) {
3723  GRN_LOG(ctx, GRN_LOG_CRIT, "buffer not found a[0]=%d", a[0]);
3725  goto exit;
3726  }
3727  GRN_LOG(ctx, GRN_LOG_DEBUG, "flushed a[0]=%d seg=%d(%p) free=%d->%d nterms=%d v=%d",
3728  a[0], LSEG(a[0]), b, bfb, b->header.buffer_free,
3729  b->header.nterms, b->header.nterms_void);
3730  if (b->header.buffer_free < size) {
3731  buffer_close(ctx, ii, pseg);
3732  GRN_LOG(ctx, GRN_LOG_CRIT, "buffer(%d) is full (%d < %d) in grn_ii_update_one",
3733  a[0], b->header.buffer_free, size);
3734  /* todo: direct merge */
3736  goto exit;
3737  }
3738  }
3739  b->header.buffer_free -= size;
3740  br = (buffer_rec *)(((byte *)&b->terms[b->header.nterms])
3741  + b->header.buffer_free);
3742  } else {
3743  grn_ii_updspec u2;
3744  uint32_t size2 = 0, v = a[0];
3745  struct _grn_ii_pos pos2;
3746  pos2.pos = a[1];
3747  pos2.next = NULL;
3748  u2.pos = &pos2;
3749  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
3750  u2.rid = BIT31_12(v);
3751  u2.sid = BIT11_01(v);
3752  } else {
3753  u2.rid = v >> 1;
3754  u2.sid = 1;
3755  }
3756  u2.tf = 1;
3757  u2.weight = 0;
3758  if (u2.rid != u->rid || u2.sid != u->sid) {
3759  uint8_t *bs2 = encode_rec(ctx, ii, &u2, &size2, 0);
3760  if (!bs2) {
3761  GRN_LOG(ctx, GRN_LOG_ALERT, "encode_rec on grn_ii_update_one failed !");
3763  goto exit;
3764  }
3765  pseg = buffer_new(ctx, ii, size + size2, &pos, &bt, &br, &b, tid, h);
3766  if (pseg == NOT_ASSIGNED) {
3767  GRN_FREE(bs2);
3768  goto exit;
3769  }
3770  bt->tid = tid;
3771  bt->size_in_chunk = 0;
3772  bt->pos_in_chunk = 0;
3773  bt->size_in_buffer = 0;
3774  bt->pos_in_buffer = 0;
3775  if ((rc = buffer_put(ctx, ii, b, bt, br, bs2, &u2, size2))) {
3776  GRN_FREE(bs2);
3777  buffer_close(ctx, ii, pseg);
3778  goto exit;
3779  }
3780  br = (buffer_rec *)(((byte *)br) + size2);
3781  GRN_FREE(bs2);
3782  }
3783  }
3784  }
3785  break;
3786  }
3787  if (!br) {
3788  if (u->tf == 1 && u->weight == 0) {
3789  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
3790  if (u->rid < 0x100000 && u->sid < 0x800) {
3791  a[0] = (u->rid << 12) + (u->sid << 1) + 1;
3792  a[1] = u->pos->pos;
3793  goto exit;
3794  }
3795  } else {
3796  a[0] = (u->rid << 1) + 1;
3797  a[1] = u->pos->pos;
3798  goto exit;
3799  }
3800  }
3801  pseg = buffer_new(ctx, ii, size, &pos, &bt, &br, &b, tid, h);
3802  if (pseg == NOT_ASSIGNED) { goto exit; }
3803  bt->tid = tid;
3804  bt->size_in_chunk = 0;
3805  bt->pos_in_chunk = 0;
3806  bt->size_in_buffer = 0;
3807  bt->pos_in_buffer = 0;
3808  }
3809  rc = buffer_put(ctx, ii, b, bt, br, bs, u, size);
3810  buffer_close(ctx, ii, pseg);
3811  if (!a[0] || (a[0] & 1)) { a[0] = pos; }
3812 exit :
3813  array_unref(ii, tid);
3814  if (bs) { GRN_FREE(bs); }
3815  if (u->tf != u->atf) {
3816  char term[GRN_TABLE_MAX_KEY_SIZE];
3817  int term_size;
3818  term_size = grn_table_get_key(ctx, ii->lexicon, tid,
3819  term, GRN_TABLE_MAX_KEY_SIZE);
3820  GRN_LOG(ctx, GRN_LOG_WARNING,
3821  "too many postings(%d). %d postings are discarded. "
3822  "term: <%d>(<%.*s>)",
3823  u->atf, u->atf - u->tf,
3824  tid, term_size, term);
3825  }
3826  grn_ii_expire(ctx, ii);
3827  return rc;
3828 }
3829 
3830 grn_rc
3832 {
3833  grn_rc rc = GRN_SUCCESS;
3834  buffer *b;
3835  uint8_t *bs = NULL;
3836  buffer_rec *br;
3837  buffer_term *bt;
3838  uint32_t pseg, size, *a;
3839  if (!tid) { return rc; }
3840  if (!(a = array_at(ctx, ii, tid))) { return GRN_INVALID_ARGUMENT; }
3841  for (;;) {
3842  if (!a[0]) { goto exit; }
3843  if (a[0] & 1) {
3844  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
3845  uint32_t rid = BIT31_12(a[0]);
3846  uint32_t sid = BIT11_01(a[0]);
3847  if (u->rid == rid && (!u->sid || u->sid == sid)) {
3848  a[0] = 0;
3849  lexicon_delete(ctx, ii, tid, h);
3850  }
3851  } else {
3852  uint32_t rid = a[0] >> 1;
3853  if (u->rid == rid) {
3854  a[0] = 0;
3855  lexicon_delete(ctx, ii, tid, h);
3856  }
3857  }
3858  goto exit;
3859  }
3860  if (!(bs = encode_rec(ctx, ii, u, &size, 1))) {
3862  goto exit;
3863  }
3864  if ((pseg = buffer_open(ctx, ii, a[0], &bt, &b)) == NOT_ASSIGNED) {
3866  goto exit;
3867  }
3868  if (b->header.buffer_free < size) {
3869  uint32_t _a = a[0];
3870  GRN_LOG(ctx, GRN_LOG_DEBUG, "flushing! b=%p free=%d, seg(%d)", b, b->header.buffer_free, LSEG(a[0]));
3871  buffer_close(ctx, ii, pseg);
3872  if ((rc = buffer_flush(ctx, ii, LSEG(a[0]), h))) { goto exit; }
3873  if (a[0] != _a) {
3874  GRN_LOG(ctx, GRN_LOG_DEBUG, "grn_ii_delete_one: a[0] changed %d->%d)", a[0], _a);
3875  continue;
3876  }
3877  if ((pseg = buffer_open(ctx, ii, a[0], &bt, &b)) == NOT_ASSIGNED) {
3879  goto exit;
3880  }
3881  GRN_LOG(ctx, GRN_LOG_DEBUG, "flushed! b=%p free=%d, seg(%d)", b, b->header.buffer_free, LSEG(a[0]));
3882  if (b->header.buffer_free < size) {
3883  GRN_LOG(ctx, GRN_LOG_CRIT, "buffer(%d) is full (%d < %d) in grn_ii_delete_one",
3884  a[0], b->header.buffer_free, size);
3886  buffer_close(ctx, ii, pseg);
3887  goto exit;
3888  }
3889  }
3890 
3891  b->header.buffer_free -= size;
3892  br = (buffer_rec *)(((byte *)&b->terms[b->header.nterms]) + b->header.buffer_free);
3893  rc = buffer_put(ctx, ii, b, bt, br, bs, u, size);
3894  buffer_close(ctx, ii, pseg);
3895  break;
3896  }
3897 exit :
3898  array_unref(ii, tid);
3899  if (bs) { GRN_FREE(bs); }
3900  return rc;
3901 }
3902 
3903 #define CHUNK_USED 1
3904 #define BUFFER_USED 2
3905 #define SOLE_DOC_USED 4
3906 #define SOLE_POS_USED 8
3907 
3914 
3919 
3920  uint32_t cdf;
3921  uint32_t *cdp;
3922  uint32_t *crp;
3923  uint32_t *csp;
3924  uint32_t *ctp;
3925  uint32_t *cwp;
3926  uint32_t *cpp;
3927 
3928  uint8_t *bp;
3929 
3931  uint32_t nchunks;
3932  uint32_t curr_chunk;
3935  uint8_t *cp;
3936  uint8_t *cpe;
3938 
3940  uint16_t stat;
3941  uint16_t nextb;
3942  uint32_t buffer_pseg;
3943  int flags;
3944  uint32_t *ppseg;
3945 };
3946 
3947 static int
3948 buffer_is_reused(grn_ctx *ctx, grn_ii *ii, grn_ii_cursor *c)
3949 {
3950  if (*c->ppseg != c->buffer_pseg) {
3951  uint32_t i;
3952  for (i = ii->header->bgqtail; i != ii->header->bgqhead; i = (i + 1) & (GRN_II_BGQSIZE - 1)) {
3953  if (ii->header->bgqbody[i] == c->buffer_pseg) { return 0; }
3954  }
3955  return 1;
3956  }
3957  return 0;
3958 }
3959 
3960 static int
3961 chunk_is_reused(grn_ctx *ctx, grn_ii *ii, grn_ii_cursor *c, uint32_t offset, uint32_t size)
3962 {
3963  if (*c->ppseg != c->buffer_pseg) {
3964  uint32_t i, m, gseg;
3965  if (size > S_CHUNK) { return 1; }
3966  if (size > (1 << GRN_II_W_LEAST_CHUNK)) {
3967  int es = size - 1;
3968  GRN_BIT_SCAN_REV(es, m);
3969  m++;
3970  } else {
3972  }
3973  gseg = ii->header->garbages[m - GRN_II_W_LEAST_CHUNK];
3974  while (gseg != NOT_ASSIGNED) {
3975  grn_io_win iw;
3976  grn_ii_ginfo *ginfo = WIN_MAP2(ii->chunk, ctx, &iw, gseg, 0, S_GARBAGE, grn_io_rdwr);
3977  if (!ginfo) { break; }
3978  for (i = 0; i < ginfo->nrecs; i++) {
3979  if (ginfo->recs[i] == offset) {
3980  grn_io_win_unmap2(&iw);
3981  return 0;
3982  }
3983  }
3984  gseg = ginfo->next;
3985  grn_io_win_unmap2(&iw);
3986  }
3987  return 1;
3988  }
3989  return 0;
3990 }
3991 
3992 #define GRN_II_CURSOR_CMP(c1,c2) \
3993  (((c1)->post->rid > (c2)->post->rid) || \
3994  (((c1)->post->rid == (c2)->post->rid) && \
3995  (((c1)->post->sid > (c2)->post->sid) || \
3996  (((c1)->post->sid == (c2)->post->sid) && \
3997  ((c1)->post->pos > (c2)->post->pos)))))
3998 
3999 grn_ii_cursor *
4001  grn_id min, grn_id max, int nelements, int flags)
4002 {
4003  grn_ii_cursor *c = NULL;
4004  uint32_t pos, *a;
4005  if (!(a = array_at(ctx, ii, tid))) { return NULL; }
4006  for (;;) {
4007  if (!(pos = a[0])) { goto exit; }
4008  if (!(c = GRN_MALLOC(sizeof(grn_ii_cursor)))) { goto exit; }
4009  memset(c, 0, sizeof(grn_ii_cursor));
4010  c->ctx = ctx;
4011  c->ii = ii;
4012  c->id = tid;
4013  c->min = min;
4014  c->max = max;
4015  c->nelements = nelements;
4016  c->flags = flags;
4017  if (pos & 1) {
4018  c->stat = 0;
4019  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
4020  c->pb.rid = BIT31_12(pos);
4021  c->pb.sid = BIT11_01(pos);
4022  } else {
4023  c->pb.rid = pos >> 1;
4024  c->pb.sid = 1;
4025  }
4026  c->pb.tf = 1;
4027  c->pb.weight = 0;
4028  c->pb.pos = a[1];
4029  } else {
4030  uint32_t chunk;
4031  buffer_term *bt;
4032  if ((c->buffer_pseg = buffer_open(ctx, ii, pos, &bt, &c->buf)) == NOT_ASSIGNED) {
4033  GRN_FREE(c);
4034  c = NULL;
4035  goto exit;
4036  }
4037  c->ppseg = &ii->header->binfo[LSEG(pos)];
4038  if (bt->size_in_chunk && (chunk = c->buf->header.chunk) != NOT_ASSIGNED) {
4039  if (!(c->cp = WIN_MAP2(ii->chunk, ctx, &c->iw, chunk, bt->pos_in_chunk,
4040  bt->size_in_chunk, grn_io_rdonly))) {
4041  buffer_close(ctx, ii, c->buffer_pseg);
4042  GRN_FREE(c);
4043  c = NULL;
4044  goto exit;
4045  }
4046  if (buffer_is_reused(ctx, ii, c)) {
4047  grn_ii_cursor_close(ctx, c);
4048  continue;
4049  }
4050  c->cpe = c->cp + bt->size_in_chunk;
4051  if ((bt->tid & CHUNK_SPLIT)) {
4052  int i;
4053  grn_id crid;
4054  GRN_B_DEC(c->nchunks, c->cp);
4055  if (chunk_is_reused(ctx, ii, c, chunk, c->buf->header.chunk_size)) {
4056  grn_ii_cursor_close(ctx, c);
4057  continue;
4058  }
4059  if (!(c->cinfo = GRN_MALLOCN(chunk_info, c->nchunks))) {
4060  buffer_close(ctx, ii, c->buffer_pseg);
4061  grn_io_win_unmap2(&c->iw);
4062  GRN_FREE(c);
4063  c = NULL;
4064  goto exit;
4065  }
4066  for (i = 0, crid = GRN_ID_NIL; i < c->nchunks; i++) {
4067  GRN_B_DEC(c->cinfo[i].segno, c->cp);
4068  GRN_B_DEC(c->cinfo[i].size, c->cp);
4069  GRN_B_DEC(c->cinfo[i].dgap, c->cp);
4070  crid += c->cinfo[i].dgap;
4071  if (crid < min) { c->curr_chunk = i + 1; }
4072  }
4073  if (chunk_is_reused(ctx, ii, c, chunk, c->buf->header.chunk_size)) {
4074  grn_ii_cursor_close(ctx, c);
4075  continue;
4076  }
4077  }
4078  if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {
4079  c->rdv[ii->n_elements - 1].flags = ODD;
4080  }
4081  }
4082  c->nextb = bt->pos_in_buffer;
4084  }
4085  if (pos == a[0]) { break; }
4086  grn_ii_cursor_close(ctx, c);
4087  }
4088 exit :
4089  array_unref(ii, tid);
4090  return c;
4091 }
4092 
4093 #ifdef USE_AIO
4094 grn_ii_cursor *
4096 {
4097  grn_ii_cursor *c = NULL;
4098  uint32_t pos, *a = array_at(ctx, ii, tid);
4099  if (!a) { return NULL; }
4100  if (!(pos = a[0])) { goto exit; }
4101  if (!(c = GRN_MALLOC(sizeof(grn_ii_cursor)))) { goto exit; }
4102  memset(c, 0, sizeof(grn_ii_cursor));
4103  c->ii = ii;
4104  if (pos & 1) {
4105  c->stat = 0;
4106  if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {
4107  c->pb.rid = BIT31_12(pos);
4108  c->pb.sid = BIT11_01(pos);
4109  } else {
4110  c->pb.rid = pos >> 1;
4111  c->pb.sid = 1;
4112  }
4113  c->pb.tf = 1;
4114  c->pb.weight = 0;
4115  c->pb.pos = a[1];
4116  } else {
4117  buffer_term *bt;
4118  c->pb.rid = 0; c->pb.sid = 0;
4119  if ((c->buffer_pseg = buffer_open(ctx, ii, pos, &bt, &c->buf)) == NOT_ASSIGNED) {
4120  GRN_FREE(c);
4121  c = NULL;
4122  goto exit;
4123  }
4124  c->iw.io = ii->chunk;
4125  c->iw.mode = grn_io_rdonly;
4126  c->iw.segment = c->buf->header.chunk;
4127  c->iw.offset = bt->pos_in_chunk;
4128  c->iw.size = bt->size_in_chunk;
4129  c->nextb = bt->pos_in_buffer;
4131  }
4132 exit :
4133  array_unref(ii, tid);
4134  return c;
4135 }
4136 
4137 grn_rc
4138 grn_ii_cursor_openv2(grn_ctx *ctx, grn_ii_cursor **cursors, int ncursors)
4139 {
4140  grn_rc rc = GRN_SUCCESS;
4141  int i, j = 0;
4142  grn_ii_cursor *c;
4143  grn_io_win **iws = GRN_MALLOC(sizeof(grn_io_win *) * ncursors);
4144  if (!iws) { return GRN_NO_MEMORY_AVAILABLE; }
4145  for (i = 0; i < ncursors; i++) {
4146  c = cursors[i];
4147  if (c->stat && c->iw.size && c->iw.segment != NOT_ASSIGNED) {
4148  iws[j++] = &c->iw;
4149  }
4150  }
4151  if (j) { rc = grn_io_win_mapv(iws, ctx, j); }
4152  for (i = 0; i < ncursors; i++) {
4153  c = cursors[i];
4154  if (c->iw.addr) {
4155  c->cp = c->iw.addr + c->iw.diff;
4156  c->cpe = c->cp + c->iw.size;
4157  c->pc.rid = 0;
4158  c->pc.sid = 0;
4159  }
4160  }
4161  GRN_FREE(iws);
4162  return rc;
4163 }
4164 #endif /* USE_AIO */
4165 
4168 {
4169  if (c->buf) {
4170  for (;;) {
4171  if (c->stat & CHUNK_USED) {
4172  for (;;) {
4173  if (c->crp < c->cdp + c->cdf) {
4174  uint32_t dgap = *c->crp++;
4175  c->pc.rid += dgap;
4176  if (dgap) { c->pc.sid = 0; }
4177  if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
4178  c->pc.sid += 1 + *c->csp++;
4179  } else {
4180  c->pc.sid = 1;
4181  }
4182  c->cpp += c->pc.rest;
4183  c->pc.rest = c->pc.tf = 1 + *c->ctp++;
4184  if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
4185  c->pc.weight = *c->cwp++;
4186  } else {
4187  c->pc.weight = 0;
4188  }
4189  c->pc.pos = 0;
4190  /*
4191  {
4192  static int count = 0;
4193  int tf = c->pc.tf, pos = 0, *pp = (int *)c->cpp;
4194  grn_obj buf;
4195  GRN_TEXT_INIT(&buf, 0);
4196  grn_text_itoa(ctx, &buf, c->pc.rid);
4197  GRN_TEXT_PUTC(ctx, &buf, ':');
4198  grn_text_itoa(ctx, &buf, c->pc.sid);
4199  GRN_TEXT_PUTC(ctx, &buf, ':');
4200  grn_text_itoa(ctx, &buf, c->pc.tf);
4201  GRN_TEXT_PUTC(ctx, &buf, '(');
4202  while (tf--) {
4203  pos += *pp++;
4204  count++;
4205  grn_text_itoa(ctx, &buf, pos);
4206  if (tf) { GRN_TEXT_PUTC(ctx, &buf, ':'); }
4207  }
4208  GRN_TEXT_PUTC(ctx, &buf, ')');
4209  GRN_TEXT_PUTC(ctx, &buf, '\0');
4210  GRN_LOG(ctx, GRN_LOG_NOTICE, "posting(%d):%s", count, GRN_TEXT_VALUE(&buf));
4211  GRN_OBJ_FIN(ctx, &buf);
4212  }
4213  */
4214  } else {
4215  if (c->curr_chunk <= c->nchunks) {
4216  if (c->curr_chunk == c->nchunks) {
4217  if (c->cp < c->cpe) {
4218  grn_p_decv(ctx, c->cp, c->cpe - c->cp, c->rdv, c->ii->n_elements);
4219  } else {
4220  c->pc.rid = 0;
4221  break;
4222  }
4223  } else {
4224  uint8_t *cp;
4225  grn_io_win iw;
4226  uint32_t size = c->cinfo[c->curr_chunk].size;
4227  if (size && (cp = WIN_MAP2(c->ii->chunk, ctx, &iw,
4228  c->cinfo[c->curr_chunk].segno, 0,
4229  size, grn_io_rdonly))) {
4230  grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements);
4231  grn_io_win_unmap2(&iw);
4232  if (chunk_is_reused(ctx, c->ii, c,
4233  c->cinfo[c->curr_chunk].segno, size)) {
4234  GRN_LOG(ctx, GRN_LOG_WARNING,
4235  "chunk(%d) is reused by another thread",
4236  c->cinfo[c->curr_chunk].segno);
4237  c->pc.rid = 0;
4238  break;
4239  }
4240  } else {
4241  c->pc.rid = 0;
4242  break;
4243  }
4244  }
4245  {
4246  int j = 0;
4247  c->cdf = c->rdv[j].data_size;
4248  c->crp = c->cdp = c->rdv[j++].data;
4249  if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
4250  c->csp = c->rdv[j++].data;
4251  }
4252  c->ctp = c->rdv[j++].data;
4253  if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
4254  c->cwp = c->rdv[j++].data;
4255  }
4256  c->cpp = c->rdv[j].data;
4257  }
4258  c->pc.rid = 0;
4259  c->pc.sid = 0;
4260  c->pc.rest = 0;
4261  c->curr_chunk++;
4262  continue;
4263  } else {
4264  c->pc.rid = 0;
4265  }
4266  }
4267  break;
4268  }
4269  }
4270  if (c->stat & BUFFER_USED) {
4271  if (c->nextb) {
4272  uint32_t lrid = c->pb.rid, lsid = c->pb.sid; /* for check */
4273  buffer_rec *br = BUFFER_REC_AT(c->buf, c->nextb);
4274  if (buffer_is_reused(ctx, c->ii, c)) {
4275  GRN_LOG(ctx, GRN_LOG_NOTICE, "buffer reused(%d,%d)", c->buffer_pseg, *c->ppseg);
4276  // todo : rewind;
4277  }
4278  c->bp = NEXT_ADDR(br);
4279  GRN_B_DEC(c->pb.rid, c->bp);
4280  if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
4281  GRN_B_DEC(c->pb.sid, c->bp);
4282  } else {
4283  c->pb.sid = 1;
4284  }
4285  if (lrid > c->pb.rid || (lrid == c->pb.rid && lsid >= c->pb.sid)) {
4286  ERR(GRN_FILE_CORRUPT, "brokend!! (%d:%d) -> (%d:%d) (%d->%d)", lrid, lsid, c->pb.rid, c->pb.sid, c->buffer_pseg, *c->ppseg);
4287  }
4288  c->nextb = br->step;
4289  GRN_B_DEC(c->pb.tf, c->bp);
4290  if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
4291  GRN_B_DEC(c->pb.weight, c->bp);
4292  } else {
4293  c->pb.weight = 0;
4294  }
4295  c->pb.rest = c->pb.tf;
4296  c->pb.pos = 0;
4297  } else {
4298  c->pb.rid = 0;
4299  }
4300  }
4301  if (c->pb.rid) {
4302  if (c->pc.rid) {
4303  if (c->pc.rid < c->pb.rid) {
4304  c->stat = CHUNK_USED;
4305  if (c->pc.tf && c->pc.sid) { c->post = &c->pc; break; }
4306  } else {
4307  if (c->pb.rid < c->pc.rid) {
4308  c->stat = BUFFER_USED;
4309  if (c->pb.tf && c->pb.sid) { c->post = &c->pb; break; }
4310  } else {
4311  if (c->pb.sid) {
4312  if (c->pc.sid < c->pb.sid) {
4313  c->stat = CHUNK_USED;
4314  if (c->pc.tf && c->pc.sid) { c->post = &c->pc; break; }
4315  } else {
4316  c->stat = BUFFER_USED;
4317  if (c->pb.sid == c->pc.sid) { c->stat |= CHUNK_USED; }
4318  if (c->pb.tf) { c->post = &c->pb; break; }
4319  }
4320  } else {
4321  c->stat = CHUNK_USED;
4322  }
4323  }
4324  }
4325  } else {
4326  c->stat = BUFFER_USED;
4327  if (c->pb.tf && c->pb.sid) { c->post = &c->pb; break; }
4328  }
4329  } else {
4330  if (c->pc.rid) {
4331  c->stat = CHUNK_USED;
4332  if (c->pc.tf && c->pc.sid) { c->post = &c->pc; break; }
4333  } else {
4334  c->post = NULL;
4335  return NULL;
4336  }
4337  }
4338  }
4339  } else {
4340  if (c->stat & SOLE_DOC_USED) {
4341  c->post = NULL;
4342  return NULL;
4343  } else {
4344  c->post = &c->pb;
4345  c->stat |= SOLE_DOC_USED;
4346  }
4347  }
4348  return c->post;
4349 }
4350 
4353 {
4354  uint32_t gap;
4355  if ((c->ii->header->flags & GRN_OBJ_WITH_POSITION)) {
4356  if (c->nelements == c->ii->n_elements) {
4357  if (c->buf) {
4358  if (c->post == &c->pc) {
4359  if (c->pc.rest) {
4360  c->pc.rest--;
4361  c->pc.pos += *c->cpp++;
4362  } else {
4363  return NULL;
4364  }
4365  } else if (c->post == &c->pb) {
4366  if (buffer_is_reused(ctx, c->ii, c)) {
4367  GRN_LOG(ctx, GRN_LOG_NOTICE, "buffer reused(%d,%d)", c->buffer_pseg, *c->ppseg);
4368  // todo : rewind;
4369  }
4370  if (c->pb.rest) {
4371  c->pb.rest--;
4372  GRN_B_DEC(gap, c->bp);
4373  c->pb.pos += gap;
4374  } else {
4375  return NULL;
4376  }
4377  } else {
4378  return NULL;
4379  }
4380  } else {
4381  if (c->stat & SOLE_POS_USED) {
4382  return NULL;
4383  } else {
4384  c->stat |= SOLE_POS_USED;
4385  }
4386  }
4387  }
4388  } else {
4389  if (c->stat & SOLE_POS_USED) {
4390  return NULL;
4391  } else {
4392  c->stat |= SOLE_POS_USED;
4393  }
4394  }
4395  return c->post;
4396 }
4397 
4398 grn_rc
4400 {
4401  if (!c) { return GRN_INVALID_ARGUMENT; }
4402  datavec_fin(ctx, c->rdv);
4403  if (c->cinfo) { GRN_FREE(c->cinfo); }
4404  if (c->buf) { buffer_close(ctx, c->ii, c->buffer_pseg); }
4405  if (c->cp) { grn_io_win_unmap2(&c->iw); }
4406  GRN_FREE(c);
4407  return GRN_SUCCESS;
4408 }
4409 
4410 uint32_t
4412 {
4413  uint32_t res, pos, *a;
4414  a = array_at(ctx, ii, tid);
4415  if (!a) { return 0; }
4416  if ((pos = a[0])) {
4417  if (pos & 1) {
4418  res = 0;
4419  } else {
4420  buffer *buf;
4421  uint32_t pseg;
4422  buffer_term *bt;
4423  if ((pseg = buffer_open(ctx, ii, pos, &bt, &buf)) == NOT_ASSIGNED) {
4424  res = 0;
4425  } else {
4426  res = bt->size_in_chunk;
4427  buffer_close(ctx, ii, pseg);
4428  }
4429  }
4430  } else {
4431  res = 0;
4432  }
4433  array_unref(ii, tid);
4434  return res;
4435 }
4436 
4437 uint32_t
4439 {
4440  uint32_t res, pos, *a;
4441  a = array_at(ctx, ii, tid);
4442  if (!a) { return 0; }
4443  if ((pos = a[0])) {
4444  if (pos & 1) {
4445  res = 1;
4446  } else {
4447  buffer *buf;
4448  uint32_t pseg;
4449  buffer_term *bt;
4450  if ((pseg = buffer_open(ctx, ii, pos, &bt, &buf)) == NOT_ASSIGNED) {
4451  res = 0;
4452  } else {
4453  res = a[1] + bt->size_in_buffer + 2;
4454  buffer_close(ctx, ii, pseg);
4455  }
4456  }
4457  } else {
4458  res = 0;
4459  }
4460  array_unref(ii, tid);
4461  return res;
4462 }
4463 
4464 int
4465 grn_ii_entry_info(grn_ctx *ctx, grn_ii *ii, grn_id tid, unsigned int *a,
4466  unsigned int *chunk, unsigned int *chunk_size, unsigned int *buffer_free,
4467  unsigned int *nterms, unsigned int *nterms_void, unsigned int *bt_tid,
4468  unsigned int *size_in_chunk, unsigned int *pos_in_chunk,
4469  unsigned int *size_in_buffer, unsigned int *pos_in_buffer)
4470 {
4471  buffer *b;
4472  buffer_term *bt;
4473  uint32_t pseg, *ap;
4474  ERRCLR(NULL);
4475  ap = array_at(ctx, ii, tid);
4476  if (!ap) { return 0; }
4477  a[0] = *ap;
4478  array_unref(ii, tid);
4479  if (!a[0]) { return 1; }
4480  if (a[0] & 1) { return 2; }
4481  if ((pseg = buffer_open(ctx, ii, a[0], &bt, &b)) == NOT_ASSIGNED) { return 3; }
4482  *chunk = b->header.chunk;
4483  *chunk_size = b->header.chunk_size;
4484  *buffer_free = b->header.buffer_free;
4485  *nterms = b->header.nterms;
4486  *bt_tid = bt->tid;
4487  *size_in_chunk = bt->size_in_chunk;
4488  *pos_in_chunk = bt->pos_in_chunk;
4489  *size_in_buffer = bt->size_in_buffer;
4490  *pos_in_buffer = bt->pos_in_buffer;
4491  buffer_close(ctx, ii, pseg);
4492  return 4;
4493 }
4494 
4495 const char *
4497 {
4498  return grn_io_path(ii->seg);
4499 }
4500 
4501 uint32_t
4503 {
4504  return ii->header->smax;
4505 }
4506 
4507 grn_obj *
4509 {
4510  return ii->lexicon;
4511 }
4512 
4513 /* private classes */
4514 
4515 /* b-heap */
4516 
4517 typedef struct {
4519  int n_bins;
4521 } cursor_heap;
4522 
4523 static inline cursor_heap *
4524 cursor_heap_open(grn_ctx *ctx, int max)
4525 {
4526  cursor_heap *h = GRN_MALLOC(sizeof(cursor_heap));
4527  if (!h) { return NULL; }
4528  h->bins = GRN_MALLOC(sizeof(grn_ii_cursor *) * max);
4529  if (!h->bins) {
4530  GRN_FREE(h);
4531  return NULL;
4532  }
4533  h->n_entries = 0;
4534  h->n_bins = max;
4535  return h;
4536 }
4537 
4538 static inline grn_rc
4539 cursor_heap_push(grn_ctx *ctx, cursor_heap *h, grn_ii *ii, grn_id tid, uint32_t offset2)
4540 {
4541  int n, n2;
4542  grn_ii_cursor *c, *c2;
4543  if (h->n_entries >= h->n_bins) {
4544  int max = h->n_bins * 2;
4545  grn_ii_cursor **bins = GRN_REALLOC(h->bins, sizeof(grn_ii_cursor *) * max);
4546  GRN_LOG(ctx, GRN_LOG_DEBUG, "expanded cursor_heap to %d,%p", max, bins);
4547  if (!bins) { return GRN_NO_MEMORY_AVAILABLE; }
4548  h->n_bins = max;
4549  h->bins = bins;
4550  }
4551 #ifdef USE_AIO
4552  if (grn_aio_enabled) {
4553  if (!(c = grn_ii_cursor_openv1(ii, tid))) {
4554  GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed");
4555  return ctx->rc;
4556  }
4557  h->bins[h->n_entries++] = c;
4558  } else
4559 #endif /* USE_AIO */
4560  {
4561  if (!(c = grn_ii_cursor_open(ctx, ii, tid, GRN_ID_NIL, GRN_ID_MAX,
4562  ii->n_elements, 0))) {
4563  GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed");
4564  return ctx->rc;
4565  }
4566  if (!grn_ii_cursor_next(ctx, c)) {
4567  grn_ii_cursor_close(ctx, c);
4568  return GRN_END_OF_DATA;
4569  }
4570  if (!grn_ii_cursor_next_pos(ctx, c)) {
4571  GRN_LOG(ctx, GRN_LOG_ERROR, "invalid ii_cursor b");
4572  grn_ii_cursor_close(ctx, c);
4573  return GRN_END_OF_DATA;
4574  }
4575  n = h->n_entries++;
4576  while (n) {
4577  n2 = (n - 1) >> 1;
4578  c2 = h->bins[n2];
4579  if (GRN_II_CURSOR_CMP(c, c2)) { break; }
4580  h->bins[n] = c2;
4581  n = n2;
4582  }
4583  h->bins[n] = c;
4584  }
4585  return GRN_SUCCESS;
4586 }
4587 
4588 static inline grn_rc
4589 cursor_heap_push2(cursor_heap *h)
4590 {
4591  grn_rc rc = GRN_SUCCESS;
4592 #ifdef USE_AIO
4593  if (grn_aio_enabled) {
4594  int i, j, n, n2;
4595  grn_ii_cursor *c, *c2;
4596  if (h && h->n_entries) {
4597  rc = grn_ii_cursor_openv2(ctx, h->bins, h->n_entries);
4598  GRN_ASSERT(rc);
4599  for (i = 0, j = 0; i < h->n_entries; i++) {
4600  c = h->bins[i];
4601  if (!grn_ii_cursor_next(ctx, c)) {
4602  grn_ii_cursor_close(ctx, c);
4603  continue;
4604  }
4605  if (!grn_ii_cursor_next_pos(ctx, c)) {
4606  GRN_LOG(ctx, GRN_LOG_ERROR, "invalid ii_cursor b");
4607  grn_ii_cursor_close(ctx, c);
4608  continue;
4609  }
4610  n = j++;
4611  while (n) {
4612  n2 = (n - 1) >> 1;
4613  c2 = h->bins[n2];
4614  if (GRN_II_CURSOR_CMP(c, c2)) { break; }
4615  h->bins[n] = c2;
4616  n = n2;
4617  }
4618  h->bins[n] = c;
4619  }
4620  h->n_entries = j;
4621  }
4622  }
4623 #endif /* USE_AIO */
4624  return rc;
4625 }
4626 
4627 static inline grn_ii_cursor *
4628 cursor_heap_min(cursor_heap *h)
4629 {
4630  return h->n_entries ? h->bins[0] : NULL;
4631 }
4632 
4633 static inline void
4634 cursor_heap_recalc_min(cursor_heap *h)
4635 {
4636  int n = 0, n1, n2, m;
4637  if ((m = h->n_entries) > 1) {
4638  grn_ii_cursor *c = h->bins[0], *c1, *c2;
4639  for (;;) {
4640  n1 = n * 2 + 1;
4641  n2 = n1 + 1;
4642  c1 = n1 < m ? h->bins[n1] : NULL;
4643  c2 = n2 < m ? h->bins[n2] : NULL;
4644  if (c1 && GRN_II_CURSOR_CMP(c, c1)) {
4645  if (c2 && GRN_II_CURSOR_CMP(c, c2) && GRN_II_CURSOR_CMP(c1, c2)) {
4646  h->bins[n] = c2;
4647  n = n2;
4648  } else {
4649  h->bins[n] = c1;
4650  n = n1;
4651  }
4652  } else {
4653  if (c2 && GRN_II_CURSOR_CMP(c, c2)) {
4654  h->bins[n] = c2;
4655  n = n2;
4656  } else {
4657  h->bins[n] = c;
4658  break;
4659  }
4660  }
4661  }
4662  }
4663 }
4664 
4665 static inline void
4666 cursor_heap_pop(grn_ctx *ctx, cursor_heap *h)
4667 {
4668  if (h->n_entries) {
4669  grn_ii_cursor *c = h->bins[0];
4670  if (!grn_ii_cursor_next(ctx, c)) {
4671  grn_ii_cursor_close(ctx, c);
4672  h->bins[0] = h->bins[--h->n_entries];
4673  } else if (!grn_ii_cursor_next_pos(ctx, c)) {
4674  GRN_LOG(ctx, GRN_LOG_ERROR, "invalid ii_cursor c");
4675  grn_ii_cursor_close(ctx, c);
4676  h->bins[0] = h->bins[--h->n_entries];
4677  }
4678  if (h->n_entries > 1) { cursor_heap_recalc_min(h); }
4679  }
4680 }
4681 
4682 static inline void
4683 cursor_heap_pop_pos(grn_ctx *ctx, cursor_heap *h)
4684 {
4685  if (h->n_entries) {
4686  grn_ii_cursor *c = h->bins[0];
4687  if (!grn_ii_cursor_next_pos(ctx, c)) {
4688  if (!grn_ii_cursor_next(ctx, c)) {
4689  grn_ii_cursor_close(ctx, c);
4690  h->bins[0] = h->bins[--h->n_entries];
4691  } else if (!grn_ii_cursor_next_pos(ctx, c)) {
4692  GRN_LOG(ctx, GRN_LOG_ERROR, "invalid ii_cursor d");
4693  grn_ii_cursor_close(ctx, c);
4694  h->bins[0] = h->bins[--h->n_entries];
4695  }
4696  }
4697  if (h->n_entries > 1) { cursor_heap_recalc_min(h); }
4698  }
4699 }
4700 
4701 static inline void
4702 cursor_heap_close(grn_ctx *ctx, cursor_heap *h)
4703 {
4704  int i;
4705  if (!h) { return; }
4706  for (i = h->n_entries; i--;) { grn_ii_cursor_close(ctx, h->bins[i]); }
4707  GRN_FREE(h->bins);
4708  GRN_FREE(h);
4709 }
4710 
4711 /* update */
4712 #ifdef USE_VGRAM
4713 
4714 inline static grn_rc
4715 index_add(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgram,
4716  const char *value, size_t value_len)
4717 {
4718  grn_hash *h;
4719  unsigned int token_flags = 0;
4720  grn_token *token;
4721  grn_ii_updspec **u;
4722  grn_id tid, *tp;
4723  grn_rc r, rc = GRN_SUCCESS;
4724  grn_vgram_buf *sbuf = NULL;
4725  if (!rid) { return GRN_INVALID_ARGUMENT; }
4726  if (!(token = grn_token_open(ctx, lexicon, value, value_len,
4727  GRN_TOKEN_ADD, token_flags))) {
4728  return GRN_NO_MEMORY_AVAILABLE;
4729  }
4730  if (vgram) { sbuf = grn_vgram_buf_open(value_len); }
4731  h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), GRN_HASH_TINY);
4732  if (!h) {
4733  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on index_add failed !");
4734  grn_token_close(ctx, token);
4735  if (sbuf) { grn_vgram_buf_close(sbuf); }
4736  return GRN_NO_MEMORY_AVAILABLE;
4737  }
4738  while (!token->status) {
4739  (tid = grn_token_next(ctx, token));
4740  if (tid) {
4741  if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **) &u, NULL)) { break; }
4742  if (!*u) {
4743  if (!(*u = grn_ii_updspec_open(ctx, rid, 1))) {
4744  GRN_LOG(ctx, GRN_LOG_ERROR, "grn_ii_updspec_open on index_add failed!");
4745  goto exit;
4746  }
4747  }
4748  if (grn_ii_updspec_add(ctx, *u, token->pos, 0)) {
4749  GRN_LOG(ctx, GRN_LOG_ERROR, "grn_ii_updspec_add on index_add failed!");
4750  goto exit;
4751  }
4752  if (sbuf) { grn_vgram_buf_add(sbuf, tid); }
4753  }
4754  }
4755  grn_token_close(ctx, token);
4756  // todo : support vgram
4757  // if (sbuf) { grn_vgram_update(vgram, rid, sbuf, (grn_set *)h); }
4758  GRN_HASH_EACH(ctx, h, id, &tp, NULL, &u, {
4759  if ((r = grn_ii_update_one(ctx, ii, *tp, *u, h))) { rc = r; }
4760  grn_ii_updspec_close(ctx, *u);
4761  });
4762  grn_hash_close(ctx, h);
4763  if (sbuf) { grn_vgram_buf_close(sbuf); }
4764  return rc;
4765 exit:
4766  grn_hash_close(ctx, h);
4767  grn_token_close(ctx, token);
4768  if (sbuf) { grn_vgram_buf_close(sbuf); }
4769  return GRN_NO_MEMORY_AVAILABLE;
4770 }
4771 
4772 inline static grn_rc
4773 index_del(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgram,
4774  const char *value, size_t value_len)
4775 {
4776  grn_hash *h;
4777  unsigned int token_flags = 0;
4778  grn_token *token;
4779  grn_ii_updspec **u;
4780  grn_id tid, *tp;
4781  if (!rid) { return GRN_INVALID_ARGUMENT; }
4782  if (!(token = grn_token_open(ctx, lexicon, value, value_len,
4783  GRN_TOKEN_DEL, token_flags))) {
4784  return GRN_NO_MEMORY_AVAILABLE;
4785  }
4786  h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), GRN_HASH_TINY);
4787  if (!h) {
4788  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on index_del failed !");
4789  grn_token_close(ctx, token);
4790  return GRN_NO_MEMORY_AVAILABLE;
4791  }
4792  while (!token->status) {
4793  if ((tid = grn_token_next(ctx, token))) {
4794  if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **) &u, NULL)) { break; }
4795  if (!*u) {
4796  if (!(*u = grn_ii_updspec_open(ctx, rid, 0))) {
4797  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_open on index_del failed !");
4798  grn_hash_close(ctx, h);
4799  grn_token_close(ctx, token);
4800  return GRN_NO_MEMORY_AVAILABLE;
4801  }
4802  }
4803  }
4804  }
4805  grn_token_close(ctx, token);
4806  GRN_HASH_EACH(ctx, h, id, &tp, NULL, &u, {
4807  if (*tp) {
4808  grn_ii_delete_one(ctx, ii, *tp, *u, NULL);
4809  }
4810  grn_ii_updspec_close(ctx, *u);
4811  });
4812  grn_hash_close(ctx, h);
4813  return GRN_SUCCESS;
4814 }
4815 
4816 grn_rc
4817 grn_ii_upd(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram,
4818  const char *oldvalue, unsigned int oldvalue_len,
4819  const char *newvalue, unsigned int newvalue_len)
4820 {
4821  grn_rc rc;
4822  grn_obj *lexicon = ii->lexicon;
4823  if (!rid) { return GRN_INVALID_ARGUMENT; }
4824  if (oldvalue && *oldvalue) {
4825  if ((rc = index_del(ctx, rid, lexicon, ii, vgram, oldvalue, oldvalue_len))) {
4826  GRN_LOG(ctx, GRN_LOG_ERROR, "index_del on grn_ii_upd failed !");
4827  goto exit;
4828  }
4829  }
4830  if (newvalue && *newvalue) {
4831  rc = index_add(ctx, rid, lexicon, ii, vgram, newvalue, newvalue_len);
4832  }
4833 exit :
4834  return rc;
4835 }
4836 
4837 grn_rc
4838 grn_ii_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, unsigned int section,
4839  grn_values *oldvalues, grn_values *newvalues)
4840 {
4841  int j;
4842  grn_value *v;
4843  unsigned int token_flags = 0;
4844  grn_token *token;
4845  grn_rc rc = GRN_SUCCESS;
4846  grn_hash *old, *new;
4847  grn_id tid, *tp;
4848  grn_ii_updspec **u, **un;
4849  grn_obj *lexicon = ii->lexicon;
4850  if (!lexicon || !ii || !rid) {
4851  GRN_LOG(ctx, GRN_LOG_WARNING, "grn_ii_update: invalid argument");
4852  return GRN_INVALID_ARGUMENT;
4853  }
4854  if (newvalues) {
4855  new = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), GRN_HASH_TINY);
4856  if (!new) {
4857  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on grn_ii_update failed !");
4859  goto exit;
4860  }
4861  for (j = newvalues->n_values, v = newvalues->values; j; j--, v++) {
4862  if ((token = grn_token_open(ctx, lexicon, v->str, v->str_len,
4863  GRN_TOKEN_ADD, token_flags))) {
4864  while (!token->status) {
4865  if ((tid = grn_token_next(ctx, token))) {
4866  if (!grn_hash_add(ctx, new, &tid, sizeof(grn_id), (void **) &u, NULL)) {
4867  break;
4868  }
4869  if (!*u) {
4870  if (!(*u = grn_ii_updspec_open(ctx, rid, section))) {
4871  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_open on grn_ii_update failed!");
4872  grn_token_close(ctx, token);
4873  grn_hash_close(ctx, new);
4875  goto exit;
4876  }
4877  }
4878  if (grn_ii_updspec_add(ctx, *u, token->pos, v->weight)) {
4879  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_add on grn_ii_update failed!");
4880  grn_token_close(ctx, token);
4881  grn_hash_close(ctx, new);
4883  goto exit;
4884  }
4885  }
4886  }
4887  grn_token_close(ctx, token);
4888  }
4889  }
4890  if (!GRN_HASH_SIZE(new)) {
4891  grn_hash_close(ctx, new);
4892  new = NULL;
4893  }
4894  } else {
4895  new = NULL;
4896  }
4897  if (oldvalues) {
4898  old = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), GRN_HASH_TINY);
4899  if (!old) {
4900  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create(ctx, NULL, old) on grn_ii_update failed!");
4901  if (new) { grn_hash_close(ctx, new); }
4903  goto exit;
4904  }
4905  for (j = oldvalues->n_values, v = oldvalues->values; j; j--, v++) {
4906  if ((token = grn_token_open(ctx, lexicon, v->str, v->str_len,
4907  GRN_TOKEN_DEL, token_flags))) {
4908  while (!token->status) {
4909  if ((tid = grn_token_next(ctx, token))) {
4910  if (!grn_hash_add(ctx, old, &tid, sizeof(grn_id), (void **) &u, NULL)) {
4911  break;
4912  }
4913  if (!*u) {
4914  if (!(*u = grn_ii_updspec_open(ctx, rid, section))) {
4915  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_open on grn_ii_update failed!");
4916  grn_token_close(ctx, token);
4917  if (new) { grn_hash_close(ctx, new); };
4918  grn_hash_close(ctx, old);
4920  goto exit;
4921  }
4922  }
4923  if (grn_ii_updspec_add(ctx, *u, token->pos, v->weight)) {
4924  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_add on grn_ii_update failed!");
4925  grn_token_close(ctx, token);
4926  if (new) { grn_hash_close(ctx, new); };
4927  grn_hash_close(ctx, old);
4929  goto exit;
4930  }
4931  }
4932  }
4933  grn_token_close(ctx, token);
4934  }
4935  }
4936  } else {
4937  old = NULL;
4938  }
4939  if (old) {
4940  grn_id eid;
4941  GRN_HASH_EACH(ctx, old, id, &tp, NULL, &u, {
4942  if (new && (eid = grn_hash_get(ctx, new, tp, sizeof(grn_id), (void **) &un))) {
4943  if (!grn_ii_updspec_cmp(*u, *un)) {
4944  grn_ii_updspec_close(ctx, *un);
4945  grn_hash_delete_by_id(ctx, new, eid, NULL);
4946  }
4947  } else {
4948  grn_ii_delete_one(ctx, ii, *tp, *u, new);
4949  }
4950  grn_ii_updspec_close(ctx, *u);
4951  });
4952  grn_hash_close(ctx, old);
4953  }
4954  if (new) {
4955  GRN_HASH_EACH(ctx, new, id, &tp, NULL, &u, {
4956  grn_rc r;
4957  if ((r = grn_ii_update_one(ctx, ii, *tp, *u, new))) { rc = r; }
4958  grn_ii_updspec_close(ctx, *u);
4959  });
4960  grn_hash_close(ctx, new);
4961  } else {
4962  if (!section) {
4963  /* todo: delete key when all sections deleted */
4964  }
4965  }
4966 exit :
4967  return rc;
4968 }
4969 #endif /* USE_VGRAM */
4970 
4971 static grn_rc
4972 grn_vector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
4973  grn_obj *in, grn_obj *out, grn_token_mode mode, grn_obj *posting)
4974 {
4975  int j;
4976  grn_id tid;
4977  grn_section *v;
4978  grn_token *token;
4979  grn_ii_updspec **u;
4980  grn_hash *h = (grn_hash *)out;
4981  grn_obj *lexicon = ii->lexicon;
4982  if (in->u.v.body) {
4983  const char *head = GRN_BULK_HEAD(in->u.v.body);
4984  for (j = in->u.v.n_sections, v = in->u.v.sections; j; j--, v++) {
4985  unsigned int token_flags = 0;
4986  if (v->length &&
4987  (token = grn_token_open(ctx, lexicon, head + v->offset, v->length,
4988  mode, token_flags))) {
4989  while (!token->status) {
4990  if ((tid = grn_token_next(ctx, token))) {
4991  if (posting) { GRN_RECORD_PUT(ctx, posting, tid); }
4992  if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **) &u, NULL)) {
4993  break;
4994  }
4995  if (!*u) {
4996  if (!(*u = grn_ii_updspec_open(ctx, rid, section))) {
4997  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_open on grn_ii_update failed!");
4998  grn_token_close(ctx, token);
4999  return GRN_NO_MEMORY_AVAILABLE;
5000  }
5001  }
5002  if (grn_ii_updspec_add(ctx, *u, token->pos, v->weight)) {
5003  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_add on grn_ii_update failed!");
5004  grn_token_close(ctx, token);
5005  return GRN_NO_MEMORY_AVAILABLE;
5006  }
5007  }
5008  }
5009  grn_token_close(ctx, token);
5010  }
5011  }
5012  }
5013  return GRN_SUCCESS;
5014 }
5015 
5016 static grn_rc
5017 grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
5018  grn_obj *in, grn_obj *out)
5019 {
5020  int j;
5021  grn_ii_updspec **u;
5022  grn_hash *h = (grn_hash *)out;
5023  const grn_id *rp = (const grn_id *)GRN_BULK_HEAD(in);
5024  const grn_id *re = (const grn_id *)GRN_BULK_CURR(in);
5025  for (j = 0; rp < re; j++, rp++) {
5026  if (!grn_hash_add(ctx, h, rp, sizeof(grn_id), (void **) &u, NULL)) {
5027  break;
5028  }
5029  if (!*u) {
5030  if (!(*u = grn_ii_updspec_open(ctx, rid, section))) {
5031  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_open on grn_ii_update failed!");
5032  return GRN_NO_MEMORY_AVAILABLE;
5033  }
5034  }
5035  if (grn_ii_updspec_add(ctx, *u, j, 0)) {
5036  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ii_updspec_add on grn_ii_update failed!");
5037  return GRN_NO_MEMORY_AVAILABLE;
5038  }
5039  }
5040  return GRN_SUCCESS;
5041 }
5042 
5043 grn_rc
5044 grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
5045  grn_obj *oldvalue, grn_obj *newvalue, grn_obj *posting)
5046 {
5047  grn_id *tp;
5048  grn_bool do_grn_ii_updspec_cmp = GRN_TRUE;
5049  grn_rc rc = GRN_SUCCESS;
5050  grn_ii_updspec **u, **un;
5051  grn_obj *old_, *old = oldvalue, *new_, *new = newvalue, oldv, newv, buf, *post = NULL;
5052  if (!ii || !ii->lexicon || !rid) {
5053  ERR(GRN_INVALID_ARGUMENT, "grn_ii_column_update: invalid argument");
5054  return GRN_INVALID_ARGUMENT;
5055  }
5056  if (posting) {
5058  post = &buf;
5059  }
5060  if (grn_io_lock(ctx, ii->seg, 10000000)) { return ctx->rc; }
5061  if (new) {
5062  unsigned char type = (ii->obj.header.domain == new->header.domain)
5063  ? GRN_UVECTOR
5064  : new->header.type;
5065  switch (type) {
5066  case GRN_BULK :
5067  {
5068  if (grn_bulk_is_zero(ctx, new)) {
5069  do_grn_ii_updspec_cmp = GRN_FALSE;
5070  }
5071  new_ = new;
5073  newv.u.v.body = new;
5074  new = &newv;
5075  grn_vector_delimit(ctx, new, 0, GRN_ID_NIL);
5076  if (new_ != newvalue) { grn_obj_close(ctx, new_); }
5077  }
5078  /* fallthru */
5079  case GRN_VECTOR :
5080  new_ = new;
5081  new = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id),
5082  sizeof(grn_ii_updspec *),
5083  GRN_HASH_TINY);
5084  if (!new) {
5085  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on grn_ii_update failed !");
5087  } else {
5088  rc = grn_vector2updspecs(ctx, ii, rid, section, new_, new, GRN_TOKEN_ADD, post);
5089  }
5090  if (new_ != newvalue) { grn_obj_close(ctx, new_); }
5091  if (rc) { goto exit; }
5092  break;
5093  case GRN_UVECTOR :
5094  new_ = new;
5095  new = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id),
5096  sizeof(grn_ii_updspec *),
5097  GRN_HASH_TINY);
5098  if (!new) {
5099  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on grn_ii_update failed !");
5101  } else {
5102  rc = grn_uvector2updspecs(ctx, ii, rid, section, new_, new);
5103  }
5104  if (new_ != newvalue) { grn_obj_close(ctx, new_); }
5105  if (rc) { goto exit; }
5106  break;
5107  case GRN_TABLE_HASH_KEY :
5108  break;
5109  default :
5110  ERR(GRN_INVALID_ARGUMENT, "invalid object assigned as newvalue");
5111  goto exit;
5112  }
5113  }
5114  if (posting) {
5115  grn_ii_updspec *u_;
5116  uint32_t offset = 0;
5117  grn_id tid_ = 0, gap, tid, *tpe;
5120  GRN_TABLE_SORT_AS_UNSIGNED, NULL, NULL,0 };
5121  grn_array *sorted = grn_array_create(ctx, NULL, sizeof(grn_id), 0);
5122  grn_hash_sort(ctx, (grn_hash *)new, -1, sorted, &arg);
5123  GRN_TEXT_PUT(ctx, posting, ((grn_hash *)new)->n_entries, sizeof(uint32_t));
5124  GRN_ARRAY_EACH(ctx, sorted, 0, 0, id, &tp, {
5125  grn_hash_get_key(ctx, (grn_hash *)new, *tp, &tid, sizeof(grn_id));
5126  gap = tid - tid_;
5127  GRN_TEXT_PUT(ctx, posting, &gap, sizeof(grn_id));
5128  tid_ = tid;
5129  });
5130  GRN_ARRAY_EACH(ctx, sorted, 0, 0, id, &tp, {
5131  grn_hash_get_value(ctx, (grn_hash *)new, *tp, &u_);
5132  u_->offset = offset++;
5133  GRN_TEXT_PUT(ctx, posting, &u_->tf, sizeof(int32_t));
5134  });
5135  tpe = (grn_id *)GRN_BULK_CURR(post);
5136  for (tp = (grn_id *)GRN_BULK_HEAD(post); tp < tpe; tp++) {
5137  grn_hash_get(ctx, (grn_hash *)new, (void *)tp, sizeof(grn_id), (void **)&u);
5138  GRN_TEXT_PUT(ctx, posting, &(*u)->offset, sizeof(int32_t));
5139  }
5140  GRN_OBJ_FIN(ctx, post);
5141  grn_array_close(ctx, sorted);
5142  }
5143 
5144  if (old) {
5145  unsigned char type = (ii->obj.header.domain == old->header.domain)
5146  ? GRN_UVECTOR
5147  : old->header.type;
5148  switch (type) {
5149  case GRN_BULK :
5150  {
5151  // const char *str = GRN_BULK_HEAD(old);
5152  // unsigned int str_len = GRN_BULK_VSIZE(old);
5153  old_ = old;
5155  oldv.u.v.body = old;
5156  old = &oldv;
5157  grn_vector_delimit(ctx, old, 0, GRN_ID_NIL);
5158  if (old_ != oldvalue) { grn_obj_close(ctx, old_); }
5159  }
5160  /* fallthru */
5161  case GRN_VECTOR :
5162  old_ = old;
5163  old = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id),
5164  sizeof(grn_ii_updspec *),
5165  GRN_HASH_TINY);
5166  if (!old) {
5167  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create(ctx, NULL, old) on grn_ii_update failed!");
5169  } else {
5170  rc = grn_vector2updspecs(ctx, ii, rid, section, old_, old, GRN_TOKEN_DEL, NULL);
5171  }
5172  if (old_ != oldvalue) { grn_obj_close(ctx, old_); }
5173  if (rc) { goto exit; }
5174  break;
5175  case GRN_UVECTOR :
5176  old_ = old;
5177  old = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id),
5178  sizeof(grn_ii_updspec *),
5179  GRN_HASH_TINY);
5180  if (!old) {
5181  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create(ctx, NULL, old) on grn_ii_update failed!");
5183  } else {
5184  rc = grn_uvector2updspecs(ctx, ii, rid, section, old_, old);
5185  }
5186  if (old_ != oldvalue) { grn_obj_close(ctx, old_); }
5187  if (rc) { goto exit; }
5188  break;
5189  case GRN_TABLE_HASH_KEY :
5190  break;
5191  default :
5192  ERR(GRN_INVALID_ARGUMENT, "invalid object assigned as oldvalue");
5193  goto exit;
5194  }
5195  }
5196 
5197  if (old) {
5198  grn_id eid;
5199  grn_hash *o = (grn_hash *)old;
5200  grn_hash *n = (grn_hash *)new;
5201  GRN_HASH_EACH(ctx, o, id, &tp, NULL, &u, {
5202  if (n && (eid = grn_hash_get(ctx, n, tp, sizeof(grn_id), (void **) &un))) {
5203  if (do_grn_ii_updspec_cmp && !grn_ii_updspec_cmp(*u, *un)) {
5204  grn_ii_updspec_close(ctx, *un);
5205  grn_hash_delete_by_id(ctx, n, eid, NULL);
5206  }
5207  } else {
5208  grn_ii_delete_one(ctx, ii, *tp, *u, n);
5209  }
5210  grn_ii_updspec_close(ctx, *u);
5211  });
5212  }
5213  if (new) {
5214  grn_hash *n = (grn_hash *)new;
5215  GRN_HASH_EACH(ctx, n, id, &tp, NULL, &u, {
5216  grn_rc r;
5217  if ((r = grn_ii_update_one(ctx, ii, *tp, *u, n))) { rc = r; }
5218  grn_ii_updspec_close(ctx, *u);
5219  });
5220  } else {
5221  if (!section) {
5222  /* todo: delete key when all sections deleted */
5223  }
5224  }
5225 exit :
5226  grn_io_unlock(ii->seg);
5227  if (old && old != oldvalue) { grn_obj_close(ctx, old); }
5228  if (new && new != newvalue) { grn_obj_close(ctx, new); }
5229  return ctx->rc;
5230 }
5231 
5232 /* token_info */
5233 
5234 typedef struct {
5236  int offset;
5237  int pos;
5238  int size;
5239  int ntoken;
5241 } token_info;
5242 
5243 #define EX_NONE 0
5244 #define EX_PREFIX 1
5245 #define EX_SUFFIX 2
5246 #define EX_BOTH 3
5247 
5248 inline static void
5249 token_info_expand_both(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii,
5250  const char *key, unsigned int key_size, token_info *ti)
5251 {
5252  int s = 0;
5253  grn_hash *h, *g;
5254  uint32_t *offset2;
5255  grn_hash_cursor *c;
5256  grn_id *tp, *tq;
5257  if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) {
5258  grn_table_search(ctx, lexicon, key, key_size,
5260  if (GRN_HASH_SIZE(h)) {
5261  if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h) + 256))) {
5262  if ((c = grn_hash_cursor_open(ctx, h, NULL, 0, NULL, 0, 0, -1, 0))) {
5263  uint32_t key2_size;
5264  const char *key2;
5265  while (grn_hash_cursor_next(ctx, c)) {
5266  grn_hash_cursor_get_key(ctx, c, (void **) &tp);
5267  key2 = _grn_table_key(ctx, lexicon, *tp, &key2_size);
5268  if (!key2) { break; }
5269  if ((lexicon->header.type != GRN_TABLE_PAT_KEY) ||
5270  !(lexicon->header.flags & GRN_OBJ_KEY_WITH_SIS) ||
5271  key2_size <= 2) { // todo: refine
5272  if ((s = grn_ii_estimate_size(ctx, ii, *tp))) {
5273  cursor_heap_push(ctx, ti->cursors, ii, *tp, 0);
5274  ti->ntoken++;
5275  ti->size += s;
5276  }
5277  } else {
5278  if ((g = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY))) {
5279  grn_pat_suffix_search(ctx, (grn_pat *)lexicon, key2, key2_size, g);
5280  GRN_HASH_EACH(ctx, g, id, &tq, NULL, &offset2, {
5281  if ((s = grn_ii_estimate_size(ctx, ii, *tq))) {
5282  cursor_heap_push(ctx, ti->cursors, ii, *tq, /* *offset2 */ 0);
5283  ti->ntoken++;
5284  ti->size += s;
5285  }
5286  });
5287  grn_hash_close(ctx, g);
5288  }
5289  }
5290  }
5291  grn_hash_cursor_close(ctx, c);
5292  }
5293  }
5294  }
5295  grn_hash_close(ctx, h);
5296  }
5297 }
5298 
5299 inline static grn_rc
5300 token_info_close(grn_ctx *ctx, token_info *ti)
5301 {
5302  cursor_heap_close(ctx, ti->cursors);
5303  GRN_FREE(ti);
5304  return GRN_SUCCESS;
5305 }
5306 
5307 inline static token_info *
5308 token_info_open(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii,
5309  const char *key, unsigned int key_size, uint32_t offset, int mode)
5310 {
5311  int s = 0;
5312  grn_hash *h;
5313  token_info *ti;
5314  grn_id tid;
5315  grn_id *tp;
5316  if (!key) { return NULL; }
5317  if (!(ti = GRN_MALLOC(sizeof(token_info)))) { return NULL; }
5318  ti->cursors = NULL;
5319  ti->size = 0;
5320  ti->ntoken = 0;
5321  ti->offset = offset;
5322  switch (mode) {
5323  case EX_BOTH :
5324  token_info_expand_both(ctx, lexicon, ii, key, key_size, ti);
5325  break;
5326  case EX_NONE :
5327  if ((tid = grn_table_get(ctx, lexicon, key, key_size)) &&
5328  (s = grn_ii_estimate_size(ctx, ii, tid)) &&
5329  (ti->cursors = cursor_heap_open(ctx, 1))) {
5330  cursor_heap_push(ctx, ti->cursors, ii, tid, 0);
5331  ti->ntoken++;
5332  ti->size = s;
5333  }
5334  break;
5335  case EX_PREFIX :
5336  if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) {
5337  grn_table_search(ctx, lexicon, key, key_size,
5339  if (GRN_HASH_SIZE(h)) {
5340  if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h)))) {
5341  GRN_HASH_EACH(ctx, h, id, &tp, NULL, NULL, {
5342  if ((s = grn_ii_estimate_size(ctx, ii, *tp))) {
5343  cursor_heap_push(ctx, ti->cursors, ii, *tp, 0);
5344  ti->ntoken++;
5345  ti->size += s;
5346  }
5347  });
5348  }
5349  }
5350  grn_hash_close(ctx, h);
5351  }
5352  break;
5353  case EX_SUFFIX :
5354  if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) {
5355  grn_table_search(ctx, lexicon, key, key_size,
5357  if (GRN_HASH_SIZE(h)) {
5358  if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h)))) {
5359  uint32_t *offset2;
5360  GRN_HASH_EACH(ctx, h, id, &tp, NULL, &offset2, {
5361  if ((s = grn_ii_estimate_size(ctx, ii, *tp))) {
5362  cursor_heap_push(ctx, ti->cursors, ii, *tp, /* *offset2 */ 0);
5363  ti->ntoken++;
5364  ti->size += s;
5365  }
5366  });
5367  }
5368  }
5369  grn_hash_close(ctx, h);
5370  }
5371  break;
5372  }
5373  if (cursor_heap_push2(ti->cursors)) {
5374  token_info_close(ctx, ti);
5375  return NULL;
5376  }
5377  {
5378  grn_ii_cursor *ic;
5379  if (ti->cursors && (ic = cursor_heap_min(ti->cursors))) {
5380  grn_ii_posting *p = ic->post;
5381  ti->pos = p->pos - ti->offset;
5382  ti->p = p;
5383  } else {
5384  token_info_close(ctx, ti);
5385  ti = NULL;
5386  }
5387  }
5388  return ti;
5389 }
5390 
5391 static inline grn_rc
5392 token_info_skip(grn_ctx *ctx, token_info *ti, uint32_t rid, uint32_t sid)
5393 {
5394  grn_ii_cursor *c;
5395  grn_ii_posting *p;
5396  for (;;) {
5397  if (!(c = cursor_heap_min(ti->cursors))) { return GRN_END_OF_DATA; }
5398  p = c->post;
5399  if (p->rid > rid || (p->rid == rid && p->sid >= sid)) { break; }
5400  cursor_heap_pop(ctx, ti->cursors);
5401  }
5402  ti->pos = p->pos - ti->offset;
5403  ti->p = p;
5404  return GRN_SUCCESS;
5405 }
5406 
5407 static inline grn_rc
5408 token_info_skip_pos(grn_ctx *ctx, token_info *ti, uint32_t rid, uint32_t sid, uint32_t pos)
5409 {
5410  grn_ii_cursor *c;
5411  grn_ii_posting *p;
5412  pos += ti->offset;
5413  for (;;) {
5414  if (!(c = cursor_heap_min(ti->cursors))) { return GRN_END_OF_DATA; }
5415  p = c->post;
5416  if (p->rid != rid || p->sid != sid || p->pos >= pos) { break; }
5417  cursor_heap_pop_pos(ctx, ti->cursors);
5418  }
5419  ti->pos = p->pos - ti->offset;
5420  ti->p = p;
5421  return GRN_SUCCESS;
5422 }
5423 
5424 inline static int
5425 token_compare(const void *a, const void *b)
5426 {
5427  const token_info *t1 = *((token_info **)a), *t2 = *((token_info **)b);
5428  return t1->size - t2->size;
5429 }
5430 
5431 inline static grn_rc
5432 token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string, unsigned int string_len,
5433  token_info **tis, uint32_t *n, grn_operator mode)
5434 {
5435  token_info *ti;
5436  const char *key;
5437  uint32_t size;
5438  grn_rc rc = GRN_END_OF_DATA;
5439  unsigned int token_flags = GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER;
5440  grn_token *token = grn_token_open(ctx, lexicon, string, string_len,
5441  GRN_TOKEN_GET, token_flags);
5442  if (!token) { return GRN_NO_MEMORY_AVAILABLE; }
5443  if (mode == GRN_OP_UNSPLIT) {
5444  if ((ti = token_info_open(ctx, lexicon, ii, (char *)token->orig, token->orig_blen, 0, EX_BOTH))) {
5445  tis[(*n)++] = ti;
5446  rc = GRN_SUCCESS;
5447  }
5448  } else {
5449  grn_id tid;
5450  int ef;
5451  switch (mode) {
5452  case GRN_OP_PREFIX :
5453  ef = EX_PREFIX;
5454  break;
5455  case GRN_OP_SUFFIX :
5456  ef = EX_SUFFIX;
5457  break;
5458  case GRN_OP_PARTIAL :
5459  ef = EX_BOTH;
5460  break;
5461  default :
5462  ef = EX_NONE;
5463  break;
5464  }
5465  tid = grn_token_next(ctx, token);
5466  if (token->force_prefix) { ef |= EX_PREFIX; }
5467  switch (token->status) {
5468  case GRN_TOKEN_DOING :
5469  key = _grn_table_key(ctx, lexicon, tid, &size);
5470  ti = token_info_open(ctx, lexicon, ii, key, size, token->pos, ef & EX_SUFFIX);
5471  break;
5472  case GRN_TOKEN_DONE :
5473  ti = token_info_open(ctx, lexicon, ii, (const char *)token->curr,
5474  token->curr_size, 0, ef);
5475  /*
5476  key = _grn_table_key(ctx, lexicon, tid, &size);
5477  ti = token_info_open(ctx, lexicon, ii, token->curr, token->curr_size, token->pos, ef);
5478  ti = token_info_open(ctx, lexicon, ii, (char *)token->orig,
5479  token->orig_blen, token->pos, ef);
5480  */
5481  break;
5482  case GRN_TOKEN_NOT_FOUND :
5483  ti = token_info_open(ctx, lexicon, ii, (char *)token->orig,
5484  token->orig_blen, 0, ef);
5485  break;
5486  default :
5487  goto exit;
5488  }
5489  if (!ti) { goto exit ; }
5490  tis[(*n)++] = ti;
5491  while (token->status == GRN_TOKEN_DOING) {
5492  tid = grn_token_next(ctx, token);
5493  switch (token->status) {
5494  case GRN_TOKEN_DOING :
5495  key = _grn_table_key(ctx, lexicon, tid, &size);
5496  ti = token_info_open(ctx, lexicon, ii, key, size, token->pos, EX_NONE);
5497  break;
5498  case GRN_TOKEN_DONE :
5499  if (tid) {
5500  key = _grn_table_key(ctx, lexicon, tid, &size);
5501  ti = token_info_open(ctx, lexicon, ii, key, size, token->pos, ef & EX_PREFIX);
5502  break;
5503  } /* else fallthru */
5504  default :
5505  ti = token_info_open(ctx, lexicon, ii, (char *)token->curr,
5506  token->curr_size, token->pos, ef & EX_PREFIX);
5507  break;
5508  }
5509  if (!ti) { goto exit; }
5510  tis[(*n)++] = ti;
5511  }
5512  rc = GRN_SUCCESS;
5513  }
5514 exit :
5515  grn_token_close(ctx, token);
5516  return rc;
5517 }
5518 
5519 static void
5520 token_info_clear_offset(token_info **tis, uint32_t n)
5521 {
5522  token_info **tie;
5523  for (tie = tis + n; tis < tie; tis++) { (*tis)->offset = 0; }
5524 }
5525 
5526 /* select */
5527 
5528 inline static void
5529 res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, uint32_t score,
5530  grn_operator op)
5531 {
5532  grn_rset_recinfo *ri;
5533  switch (op) {
5534  case GRN_OP_OR :
5535  if (grn_hash_add(ctx, s, pi, s->key_size, (void **)&ri, NULL)) {
5536  if (s->obj.header.flags & GRN_OBJ_WITH_SUBREC) {
5537  grn_table_add_subrec((grn_obj *)s, ri, score, pi, 1);
5538  }
5539  }
5540  break;
5541  case GRN_OP_AND :
5542  if (grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri)) {
5543  if (s->obj.header.flags & GRN_OBJ_WITH_SUBREC) {
5545  grn_table_add_subrec((grn_obj *)s, ri, score, pi, 1);
5546  }
5547  }
5548  break;
5549  case GRN_OP_AND_NOT :
5550  {
5551  grn_id id;
5552  if ((id = grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri))) {
5553  grn_hash_delete_by_id(ctx, s, id, NULL);
5554  }
5555  }
5556  break;
5557  case GRN_OP_ADJUST :
5558  if (grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri)) {
5559  if (s->obj.header.flags & GRN_OBJ_WITH_SUBREC) {
5560  ri->score += score;
5561  }
5562  }
5563  break;
5564  default :
5565  break;
5566  }
5567 }
5568 
5569 grn_rc
5571 {
5572  res_add(ctx, s, (grn_rset_posinfo *)(pos), (1 + pos->weight), op);
5573  return ctx->rc;
5574 }
5575 
5576 #ifdef USE_BHEAP
5577 
5578 /* todo */
5579 
5580 #else /* USE_BHEAP */
5581 
5582 struct _btr_node {
5583  struct _btr_node *car;
5584  struct _btr_node *cdr;
5586 };
5587 
5588 typedef struct _btr_node btr_node;
5589 
5590 typedef struct {
5591  int n;
5596 } btr;
5597 
5598 inline static void
5599 bt_zap(btr *bt)
5600 {
5601  bt->n = 0;
5602  bt->min = NULL;
5603  bt->max = NULL;
5604  bt->root = NULL;
5605 }
5606 
5607 inline static btr *
5608 bt_open(grn_ctx *ctx, int size)
5609 {
5610  btr *bt = GRN_MALLOC(sizeof(btr));
5611  if (bt) {
5612  bt_zap(bt);
5613  if (!(bt->nodes = GRN_MALLOC(sizeof(btr_node) * size))) {
5614  GRN_FREE(bt);
5615  bt = NULL;
5616  }
5617  }
5618  return bt;
5619 }
5620 
5621 inline static void
5622 bt_close(grn_ctx *ctx, btr *bt)
5623 {
5624  if (!bt) { return; }
5625  GRN_FREE(bt->nodes);
5626  GRN_FREE(bt);
5627 }
5628 
5629 inline static void
5630 bt_push(btr *bt, token_info *ti)
5631 {
5632  int pos = ti->pos, minp = 1, maxp = 1;
5633  btr_node *node, *new, **last;
5634  new = bt->nodes + bt->n++;
5635  new->ti = ti;
5636  new->car = NULL;
5637  new->cdr = NULL;
5638  for (last = &bt->root; (node = *last);) {
5639  if (pos < node->ti->pos) {
5640  last = &node->car;
5641  maxp = 0;
5642  } else {
5643  last = &node->cdr;
5644  minp = 0;
5645  }
5646  }
5647  *last = new;
5648  if (minp) { bt->min = ti; }
5649  if (maxp) { bt->max = ti; }
5650 }
5651 
5652 inline static void
5653 bt_pop(btr *bt)
5654 {
5655  btr_node *node, *min, *newmin, **last;
5656  for (last = &bt->root; (min = *last) && min->car; last = &min->car) ;
5657  if (min) {
5658  int pos = min->ti->pos, minp = 1, maxp = 1;
5659  *last = min->cdr;
5660  min->cdr = NULL;
5661  for (last = &bt->root; (node = *last);) {
5662  if (pos < node->ti->pos) {
5663  last = &node->car;
5664  maxp = 0;
5665  } else {
5666  last = &node->cdr;
5667  minp = 0;
5668  }
5669  }
5670  *last = min;
5671  if (maxp) { bt->max = min->ti; }
5672  if (!minp) {
5673  for (newmin = bt->root; newmin->car; newmin = newmin->car) ;
5674  bt->min = newmin->ti;
5675  }
5676  }
5677 }
5678 
5679 #endif /* USE_BHEAP */
5680 
5681 typedef enum {
5686 } grn_wv_mode;
5687 
5688 inline static int
5689 get_weight(grn_ctx *ctx, grn_hash *s, grn_id rid, int sid,
5690  grn_wv_mode wvm, grn_select_optarg *optarg)
5691 {
5692  switch (wvm) {
5693  case grn_wv_none :
5694  return 1;
5695  case grn_wv_static :
5696  return sid <= optarg->vector_size ? optarg->weight_vector[sid - 1] : 0;
5697  case grn_wv_dynamic :
5698  /* todo : support hash with keys
5699  if (s->keys) {
5700  uint32_t key_size;
5701  const char *key = _grn_table_key(ctx, s->keys, rid, &key_size);
5702  // todo : change grn_select_optarg
5703  return key ? optarg->func(s, key, key_size, sid, optarg->func_arg) : 0;
5704  }
5705  */
5706  /* todo : cast */
5707  return optarg->func(ctx, (void *)s, (void *)(intptr_t)rid, sid, optarg->func_arg);
5708  case grn_wv_constant :
5709  return optarg->vector_size;
5710  default :
5711  return 1;
5712  }
5713 }
5714 
5715 grn_rc
5717  const char *string, unsigned int string_len,
5718  grn_hash *s, grn_operator op, grn_select_optarg *optarg)
5719 {
5720  int *w1, limit;
5721  grn_id tid, *tp, max_size;
5722  grn_rc rc = GRN_SUCCESS;
5723  grn_hash *h;
5724  grn_token *token;
5725  unsigned int token_flags = GRN_TOKEN_ENABLE_TOKENIZED_DELIMITER;
5726  grn_obj *lexicon = ii->lexicon;
5727  if (!lexicon || !ii || !string || !string_len || !s || !optarg) { return GRN_INVALID_ARGUMENT; }
5728  if (!(h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(int), 0))) {
5729  return GRN_NO_MEMORY_AVAILABLE;
5730  }
5731  if (!(token = grn_token_open(ctx, lexicon, string, string_len,
5732  GRN_TOKEN_GET, token_flags))) {
5733  grn_hash_close(ctx, h);
5734  return GRN_NO_MEMORY_AVAILABLE;
5735  }
5736  if (!(max_size = optarg->max_size)) { max_size = 1048576; }
5737  while (token->status != GRN_TOKEN_DONE) {
5738  if ((tid = grn_token_next(ctx, token))) {
5739  if (grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&w1, NULL)) { (*w1)++; }
5740  }
5741  if (tid && token->curr_size) {
5742  if (optarg->max_interval == GRN_OP_UNSPLIT) {
5743  grn_table_search(ctx, lexicon, token->curr, token->curr_size,
5745  }
5746  if (optarg->max_interval == GRN_OP_PARTIAL) {
5747  grn_table_search(ctx, lexicon, token->curr, token->curr_size,
5749  }
5750  }
5751  }
5752  grn_token_close(ctx, token);
5753  {
5754  grn_hash_cursor *c = grn_hash_cursor_open(ctx, h, NULL, 0, NULL, 0, 0, -1, 0);
5755  if (!c) {
5756  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_cursor_open on grn_ii_similar_search failed !");
5757  grn_hash_close(ctx, h);
5758  return GRN_NO_MEMORY_AVAILABLE;
5759  }
5760  while (grn_hash_cursor_next(ctx, c)) {
5761  uint32_t es;
5762  grn_hash_cursor_get_key_value(ctx, c, (void **) &tp, NULL, (void **) &w1);
5763  if ((es = grn_ii_estimate_size(ctx, ii, *tp))) {
5764  *w1 += max_size / es;
5765  } else {
5766  grn_hash_cursor_delete(ctx, c, NULL);
5767  }
5768  }
5769  grn_hash_cursor_close(ctx, c);
5770  }
5771  limit = optarg->similarity_threshold
5772  ? (optarg->similarity_threshold > GRN_HASH_SIZE(h)
5773  ? GRN_HASH_SIZE(h)
5774  : optarg->similarity_threshold)
5775  : (GRN_HASH_SIZE(h) >> 3) + 1;
5776  if (GRN_HASH_SIZE(h)) {
5777  grn_id j, id;
5778  int w2, rep;
5779  grn_ii_cursor *c;
5780  grn_ii_posting *pos;
5781  grn_wv_mode wvm = grn_wv_none;
5782  grn_table_sort_optarg arg = {GRN_TABLE_SORT_DESC, NULL, (void *)sizeof(grn_id), 0};
5783  grn_array *sorted = grn_array_create(ctx, NULL, sizeof(grn_id), 0);
5784  if (!sorted) {
5785  GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_sort on grn_ii_similar_search failed !");
5786  grn_hash_close(ctx, h);
5787  return GRN_NO_MEMORY_AVAILABLE;
5788  }
5789  grn_hash_sort(ctx, h, limit, sorted, &arg);
5790  /* todo support subrec
5791  rep = (s->record_unit == grn_rec_position || s->subrec_unit == grn_rec_position);
5792  */
5793  rep = 0;
5794  if (optarg->func) {
5795  wvm = grn_wv_dynamic;
5796  } else if (optarg->vector_size) {
5797  wvm = optarg->weight_vector ? grn_wv_static : grn_wv_constant;
5798  }
5799  for (j = 1; j <= limit; j++) {
5800  grn_array_get_value(ctx, sorted, j, &id);
5801  _grn_hash_get_key_value(ctx, h, id, (void **) &tp, (void **) &w1);
5802  if (!*tp || !(c = grn_ii_cursor_open(ctx, ii, *tp, GRN_ID_NIL, GRN_ID_MAX,
5803  rep
5804  ? ii->n_elements
5805  : ii->n_elements - 1, 0))) {
5806  GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed (%d)", *tp);
5807  continue;
5808  }
5809  if (rep) {
5810  while (grn_ii_cursor_next(ctx, c)) {
5811  pos = c->post;
5812  if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg))) {
5813  while (grn_ii_cursor_next_pos(ctx, c)) {
5814  res_add(ctx, s, (grn_rset_posinfo *) pos, *w1 * w2 * (1 + pos->weight), op);
5815  }
5816  }
5817  }
5818  } else {
5819  while (grn_ii_cursor_next(ctx, c)) {
5820  pos = c->post;
5821  if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg))) {
5822  res_add(ctx, s, (grn_rset_posinfo *) pos, *w1 * w2 * (pos->tf + pos->weight), op);
5823  }
5824  }
5825  }
5826  grn_ii_cursor_close(ctx, c);
5827  }
5828  grn_array_close(ctx, sorted);
5829  }
5830  grn_hash_close(ctx, h);
5831  grn_ii_resolve_sel_and(ctx, s, op);
5832  // grn_hash_cursor_clear(r);
5833  return rc;
5834 }
5835 
5836 #define TERM_EXTRACT_EACH_POST 0
5837 #define TERM_EXTRACT_EACH_TERM 1
5838 
5839 grn_rc
5840 grn_ii_term_extract(grn_ctx *ctx, grn_ii *ii, const char *string,
5841  unsigned int string_len, grn_hash *s,
5842  grn_operator op, grn_select_optarg *optarg)
5843 {
5844  grn_rset_posinfo pi;
5845  grn_id tid;
5846  const char *p, *pe;
5847  grn_obj *nstr;
5848  const char *normalized;
5849  unsigned int normalized_length_in_bytes;
5850  grn_ii_cursor *c;
5851  grn_ii_posting *pos;
5852  int skip, rep, policy;
5853  grn_rc rc = GRN_SUCCESS;
5854  grn_wv_mode wvm = grn_wv_none;
5855  if (!ii || !string || !string_len || !s || !optarg) {
5856  return GRN_INVALID_ARGUMENT;
5857  }
5858  if (!(nstr = grn_string_open(ctx, string, string_len, NULL, 0))) {
5859  return GRN_INVALID_ARGUMENT;
5860  }
5861  policy = optarg->max_interval;
5862  if (optarg->func) {
5863  wvm = grn_wv_dynamic;
5864  } else if (optarg->vector_size) {
5865  wvm = optarg->weight_vector ? grn_wv_static : grn_wv_constant;
5866  }
5867  /* todo support subrec
5868  if (policy == TERM_EXTRACT_EACH_POST) {
5869  if ((rc = grn_records_reopen(s, grn_rec_section, grn_rec_none, 0))) { goto exit; }
5870  }
5871  rep = (s->record_unit == grn_rec_position || s->subrec_unit == grn_rec_position);
5872  */
5873  rep = 0;
5874  grn_string_get_normalized(ctx, nstr, &normalized, &normalized_length_in_bytes,
5875  NULL);
5876  for (p = normalized, pe = p + normalized_length_in_bytes; p < pe; p += skip) {
5877  if ((tid = grn_table_lcp_search(ctx, ii->lexicon, p, pe - p))) {
5878  if (policy == TERM_EXTRACT_EACH_POST) {
5879  if (!(skip = grn_table_get_key(ctx, ii->lexicon, tid, NULL, 0))) { break; }
5880  } else {
5881  if (!(skip = (int)grn_charlen(ctx, p, pe))) { break; }
5882  }
5883  if (!(c = grn_ii_cursor_open(ctx, ii, tid, GRN_ID_NIL, GRN_ID_MAX,
5884  rep
5885  ? ii->n_elements
5886  : ii->n_elements - 1, 0))) {
5887  GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed (%d)", tid);
5888  continue;
5889  }
5890  if (rep) {
5891  while (grn_ii_cursor_next(ctx, c)) {
5892  pos = c->post;
5893  while (grn_ii_cursor_next_pos(ctx, c)) {
5894  res_add(ctx, s, (grn_rset_posinfo *) pos,
5895  get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg), op);
5896  }
5897  }
5898  } else {
5899  while (grn_ii_cursor_next(ctx, c)) {
5900  if (policy == TERM_EXTRACT_EACH_POST) {
5901  pi.rid = c->post->rid;
5902  pi.sid = p - normalized;
5903  res_add(ctx, s, &pi, pi.sid + 1, op);
5904  } else {
5905  pos = c->post;
5906  res_add(ctx, s, (grn_rset_posinfo *) pos,
5907  get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg), op);
5908  }
5909  }
5910  }
5911  grn_ii_cursor_close(ctx, c);
5912  } else {
5913  if (!(skip = (int)grn_charlen(ctx, p, pe))) {
5914  break;
5915  }
5916  }
5917  }
5918  grn_obj_close(ctx, nstr);
5919  return rc;
5920 }
5921 
5922 grn_rc
5923 grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len,
5924  grn_hash *s, grn_operator op, grn_select_optarg *optarg)
5925 {
5926  btr *bt = NULL;
5927  grn_rc rc = GRN_SUCCESS;
5928  int rep, orp, weight, max_interval = 0;
5929  token_info *ti, **tis = NULL, **tip, **tie;
5930  uint32_t n = 0, rid, sid, nrid, nsid;
5931  grn_operator mode = GRN_OP_EXACT;
5932  grn_wv_mode wvm = grn_wv_none;
5933  grn_obj *lexicon = ii->lexicon;
5934  if (!lexicon || !ii || !s) { return GRN_INVALID_ARGUMENT; }
5935  if (optarg) {
5936  mode = optarg->mode;
5937  if (optarg->func) {
5938  wvm = grn_wv_dynamic;
5939  } else if (optarg->vector_size) {
5940  wvm = optarg->weight_vector ? grn_wv_static : grn_wv_constant;
5941  }
5942  }
5943  if (mode == GRN_OP_SIMILAR) {
5944  return grn_ii_similar_search(ctx, ii, string, string_len, s, op, optarg);
5945  }
5946  if (mode == GRN_OP_TERM_EXTRACT) {
5947  return grn_ii_term_extract(ctx, ii, string, string_len, s, op, optarg);
5948  }
5949  /* todo : support subrec
5950  rep = (s->record_unit == grn_rec_position || s->subrec_unit == grn_rec_position);
5951  orp = (s->record_unit == grn_rec_position || op == GRN_OP_OR);
5952  */
5953  rep = 0;
5954  orp = op == GRN_OP_OR;
5955  if (!string_len) { goto exit; }
5956  if (!(tis = GRN_MALLOC(sizeof(token_info *) * string_len * 2))) {
5957  return GRN_NO_MEMORY_AVAILABLE;
5958  }
5959  if (token_info_build(ctx, lexicon, ii, string, string_len, tis, &n, mode) || !n) { goto exit; }
5960  switch (mode) {
5961  case GRN_OP_NEAR2 :
5962  token_info_clear_offset(tis, n);
5963  mode = GRN_OP_NEAR;
5964  /* fallthru */
5965  case GRN_OP_NEAR :
5966  if (!(bt = bt_open(ctx, n))) { rc = GRN_NO_MEMORY_AVAILABLE; goto exit; }
5967  max_interval = optarg->max_interval;
5968  break;
5969  default :
5970  break;
5971  }
5972  qsort(tis, n, sizeof(token_info *), token_compare);
5973  tie = tis + n;
5974  /*
5975  for (tip = tis; tip < tie; tip++) {
5976  ti = *tip;
5977  grn_log("o=%d n=%d s=%d r=%d", ti->offset, ti->ntoken, ti->size, ti->rid);
5978  }
5979  */
5980  GRN_LOG(ctx, GRN_LOG_INFO, "n=%d (%.*s)", n, string_len, string);
5981  /* todo : array as result
5982  if (n == 1 && (*tis)->cursors->n_entries == 1 && op == GRN_OP_OR
5983  && !GRN_HASH_SIZE(s) && !s->garbages
5984  && s->record_unit == grn_rec_document && !s->max_n_subrecs
5985  && grn_ii_max_section(ii) == 1) {
5986  grn_ii_cursor *c = (*tis)->cursors->bins[0];
5987  if ((rc = grn_hash_array_init(s, (*tis)->size + 32768))) { goto exit; }
5988  do {
5989  grn_rset_recinfo *ri;
5990  grn_ii_posting *p = c->post;
5991  if ((weight = get_weight(ctx, s, p->rid, p->sid, wvm, optarg))) {
5992  GRN_HASH_INT_ADD(s, p, ri);
5993  ri->score = (p->tf + p->score) * weight;
5994  ri->n_subrecs = 1;
5995  }
5996  } while (grn_ii_cursor_next(ctx, c));
5997  goto exit;
5998  }
5999  */
6000  for (;;) {
6001  rid = (*tis)->p->rid;
6002  sid = (*tis)->p->sid;
6003  for (tip = tis + 1, nrid = rid, nsid = sid + 1; tip < tie; tip++) {
6004  ti = *tip;
6005  if (token_info_skip(ctx, ti, rid, sid)) { goto exit; }
6006  if (ti->p->rid != rid || ti->p->sid != sid) {
6007  nrid = ti->p->rid;
6008  nsid = ti->p->sid;
6009  break;
6010  }
6011  }
6012  weight = get_weight(ctx, s, rid, sid, wvm, optarg);
6013  if (tip == tie && weight) {
6014  grn_rset_posinfo pi = {rid, sid, 0};
6015  if (orp || grn_hash_get(ctx, s, &pi, s->key_size, NULL)) {
6016  int count = 0, noccur = 0, pos = 0, score = 0, tscore = 0, min, max;
6017 
6018 #define SKIP_OR_BREAK(pos) {\
6019  if (token_info_skip_pos(ctx, ti, rid, sid, pos)) { break; } \
6020  if (ti->p->rid != rid || ti->p->sid != sid) { \
6021  nrid = ti->p->rid; \
6022  nsid = ti->p->sid; \
6023  break; \
6024  } \
6025 }
6026  if (n == 1 && !rep) {
6027  noccur = (*tis)->p->tf;
6028  tscore = (*tis)->p->weight;
6029  } else if (mode == GRN_OP_NEAR) {
6030  bt_zap(bt);
6031  for (tip = tis; tip < tie; tip++) {
6032  ti = *tip;
6033  SKIP_OR_BREAK(pos);
6034  bt_push(bt, ti);
6035  }
6036  if (tip == tie) {
6037  for (;;) {
6038  ti = bt->min; min = ti->pos; max = bt->max->pos;
6039  if (min > max) { exit(0); }
6040  if (max - min <= max_interval) {
6041  if (rep) { pi.pos = min; res_add(ctx, s, &pi, weight, op); }
6042  noccur++;
6043  if (ti->pos == max + 1) {
6044  break;
6045  }
6046  SKIP_OR_BREAK(max + 1);
6047  } else {
6048  if (ti->pos == max - max_interval) {
6049  break;
6050  }
6051  SKIP_OR_BREAK(max - max_interval);
6052  }
6053  bt_pop(bt);
6054  }
6055  }
6056  } else {
6057  for (tip = tis; ; tip++) {
6058  if (tip == tie) { tip = tis; }
6059  ti = *tip;
6060  SKIP_OR_BREAK(pos);
6061  if (ti->pos == pos) {
6062  score += ti->p->weight; count++;
6063  } else {
6064  score = ti->p->weight; count = 1; pos = ti->pos;
6065  }
6066  if (count == n) {
6067  if (rep) { pi.pos = pos; res_add(ctx, s, &pi, (score + 1) * weight, op); }
6068  tscore += score;
6069  score = 0; count = 0; pos++;
6070  noccur++;
6071  }
6072  }
6073  }
6074  if (noccur && !rep) { res_add(ctx, s, &pi, (noccur + tscore) * weight, op); }
6075 #undef SKIP_OR_BREAK
6076  }
6077  }
6078  if (token_info_skip(ctx, *tis, nrid, nsid)) { goto exit; }
6079  }
6080 exit :
6081  for (tip = tis; tip < tis + n; tip++) {
6082  if (*tip) { token_info_close(ctx, *tip); }
6083  }
6084  if (tis) { GRN_FREE(tis); }
6085  grn_ii_resolve_sel_and(ctx, s, op);
6086  // grn_hash_cursor_clear(r);
6087  bt_close(ctx, bt);
6088 #ifdef DEBUG
6089  {
6090  uint32_t segno = GRN_II_MAX_LSEG, nnref = 0;
6091  grn_io_mapinfo *info = ii->seg->maps;
6092  for (; segno; segno--, info++) { if (info->nref) { nnref++; } }
6093  GRN_LOG(ctx, GRN_LOG_INFO, "nnref=%d", nnref);
6094  }
6095 #endif /* DEBUG */
6096  return rc;
6097 }
6098 
6099 grn_rc
6100 grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len,
6101  grn_hash *s, grn_operator op, grn_search_optarg *optarg)
6102 {
6103  ERRCLR(ctx);
6104  GRN_LOG(ctx, GRN_LOG_INFO, "grn_ii_sel > (%.*s)", string_len, string);
6105  {
6106  grn_select_optarg arg = {GRN_OP_EXACT, 0, 0, NULL, 0, NULL, NULL, 0};
6107  if (!s) { return GRN_INVALID_ARGUMENT; }
6108  if (optarg) {
6109  switch (optarg->mode) {
6110  case GRN_OP_NEAR :
6111  case GRN_OP_NEAR2 :
6112  arg.mode = optarg->mode;
6113  arg.max_interval = optarg->max_interval;
6114  break;
6115  case GRN_OP_SIMILAR :
6116  arg.mode = optarg->mode;
6117  break;
6118  default :
6119  break;
6120  }
6121  if (optarg->vector_size > 0) {
6122  arg.weight_vector = optarg->weight_vector;
6123  arg.vector_size = optarg->vector_size;
6124  }
6125  }
6126  /* todo : support subrec
6127  grn_rset_init(ctx, s, grn_rec_document, 0, grn_rec_none, 0, 0);
6128  */
6129  if (grn_ii_select(ctx, ii, string, string_len, s, op, &arg)) {
6130  GRN_LOG(ctx, GRN_LOG_ERROR, "grn_ii_select on grn_ii_sel(1) failed !");
6131  return ctx->rc;
6132  }
6133  GRN_LOG(ctx, GRN_LOG_INFO, "exact: %d", GRN_HASH_SIZE(s));
6134  if (op == GRN_OP_OR) {
6135  if ((int64_t)GRN_HASH_SIZE(s) <= ctx->impl->match_escalation_threshold) {
6136  arg.mode = GRN_OP_UNSPLIT;
6137  if (grn_ii_select(ctx, ii, string, string_len, s, op, &arg)) {
6138  GRN_LOG(ctx, GRN_LOG_ERROR, "grn_ii_select on grn_ii_sel(2) failed !");
6139  return ctx->rc;
6140  }
6141  GRN_LOG(ctx, GRN_LOG_INFO, "unsplit: %d", GRN_HASH_SIZE(s));
6142  }
6143  if ((int64_t)GRN_HASH_SIZE(s) <= ctx->impl->match_escalation_threshold) {
6144  arg.mode = GRN_OP_PARTIAL;
6145  if (grn_ii_select(ctx, ii, string, string_len, s, op, &arg)) {
6146  GRN_LOG(ctx, GRN_LOG_ERROR, "grn_ii_select on grn_ii_sel(3) failed !");
6147  return ctx->rc;
6148  }
6149  GRN_LOG(ctx, GRN_LOG_INFO, "partial: %d", GRN_HASH_SIZE(s));
6150  }
6151  }
6152  GRN_LOG(ctx, GRN_LOG_INFO, "hits=%d", GRN_HASH_SIZE(s));
6153  return GRN_SUCCESS;
6154  }
6155 }
6156 
6157 grn_rc
6159 {
6160  int rep = 0;
6161  grn_ii_cursor *c;
6162  grn_ii_posting *pos;
6163  if ((c = grn_ii_cursor_open(ctx, ii, id, GRN_ID_NIL, GRN_ID_MAX,
6164  rep ? ii->n_elements : ii->n_elements - 1, 0))) {
6165  while ((pos = grn_ii_cursor_next(ctx, c))) {
6166  res_add(ctx, s, (grn_rset_posinfo *) pos, (1 + pos->weight), op);
6167  }
6168  grn_ii_cursor_close(ctx, c);
6169  }
6170  return ctx->rc;
6171 }
6172 
6173 void
6175 {
6176  if (op == GRN_OP_AND
6178  grn_id eid;
6179  grn_rset_recinfo *ri;
6180  grn_hash_cursor *c = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0);
6181  if (c) {
6182  while ((eid = grn_hash_cursor_next(ctx, c))) {
6183  grn_hash_cursor_get_value(ctx, c, (void **) &ri);
6184  if ((ri->n_subrecs & GRN_RSET_UTIL_BIT)) {
6185  ri->n_subrecs &= ~GRN_RSET_UTIL_BIT;
6186  } else {
6187  grn_hash_delete_by_id(ctx, s, eid, NULL);
6188  }
6189  }
6190  grn_hash_cursor_close(ctx, c);
6191  }
6192  }
6193 }
6194 
6195 /* just for inspect */
6196 static grn_ii_posting *
6197 grn_ii_cursor_next_all(grn_ctx *ctx, grn_ii_cursor *c)
6198 {
6199  if (c->buf) {
6200  for (;;) {
6201  if (c->stat & CHUNK_USED) {
6202  for (;;) {
6203  if (c->crp < c->cdp + c->cdf) {
6204  uint32_t dgap = *c->crp++;
6205  c->pc.rid += dgap;
6206  if (dgap) { c->pc.sid = 0; }
6207  if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
6208  c->pc.sid += 1 + *c->csp++;
6209  } else {
6210  c->pc.sid = 1;
6211  }
6212  c->cpp += c->pc.rest;
6213  c->pc.rest = c->pc.tf = 1 + *c->ctp++;
6214  if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
6215  c->pc.weight = *c->cwp++;
6216  } else {
6217  c->pc.weight = 0;
6218  }
6219  c->pc.pos = 0;
6220  /*
6221  {
6222  static int count = 0;
6223  int tf = c->pc.tf, pos = 0, *pp = (int *)c->cpp;
6224  grn_obj buf;
6225  GRN_TEXT_INIT(&buf, 0);
6226  grn_text_itoa(ctx, &buf, c->pc.rid);
6227  GRN_TEXT_PUTC(ctx, &buf, ':');
6228  grn_text_itoa(ctx, &buf, c->pc.sid);
6229  GRN_TEXT_PUTC(ctx, &buf, ':');
6230  grn_text_itoa(ctx, &buf, c->pc.tf);
6231  GRN_TEXT_PUTC(ctx, &buf, '(');
6232  while (tf--) {
6233  pos += *pp++;
6234  count++;
6235  grn_text_itoa(ctx, &buf, pos);
6236  if (tf) { GRN_TEXT_PUTC(ctx, &buf, ':'); }
6237  }
6238  GRN_TEXT_PUTC(ctx, &buf, ')');
6239  GRN_TEXT_PUTC(ctx, &buf, '\0');
6240  GRN_LOG(ctx, GRN_LOG_NOTICE, "posting(%d):%s", count, GRN_TEXT_VALUE(&buf));
6241  GRN_OBJ_FIN(ctx, &buf);
6242  }
6243  */
6244  } else {
6245  if (c->curr_chunk <= c->nchunks) {
6246  if (c->curr_chunk == c->nchunks) {
6247  if (c->cp < c->cpe) {
6248  grn_p_decv(ctx, c->cp, c->cpe - c->cp, c->rdv, c->ii->n_elements);
6249  } else {
6250  c->pc.rid = 0;
6251  break;
6252  }
6253  } else {
6254  uint8_t *cp;
6255  grn_io_win iw;
6256  uint32_t size = c->cinfo[c->curr_chunk].size;
6257  if (size && (cp = WIN_MAP2(c->ii->chunk, ctx, &iw,
6258  c->cinfo[c->curr_chunk].segno, 0,
6259  size, grn_io_rdonly))) {
6260  grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements);
6261  grn_io_win_unmap2(&iw);
6262  } else {
6263  c->pc.rid = 0;
6264  break;
6265  }
6266  }
6267  {
6268  int j = 0;
6269  c->cdf = c->rdv[j].data_size;
6270  c->crp = c->cdp = c->rdv[j++].data;
6271  if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
6272  c->csp = c->rdv[j++].data;
6273  }
6274  c->ctp = c->rdv[j++].data;
6275  if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
6276  c->cwp = c->rdv[j++].data;
6277  }
6278  c->cpp = c->rdv[j].data;
6279  }
6280  c->pc.rid = 0;
6281  c->pc.sid = 0;
6282  c->pc.rest = 0;
6283  c->curr_chunk++;
6284  continue;
6285  } else {
6286  c->pc.rid = 0;
6287  }
6288  }
6289  break;
6290  }
6291  }
6292  if (c->stat & BUFFER_USED) {
6293  if (c->nextb) {
6294  uint32_t lrid = c->pb.rid, lsid = c->pb.sid; /* for check */
6295  buffer_rec *br = BUFFER_REC_AT(c->buf, c->nextb);
6296  if (buffer_is_reused(ctx, c->ii, c)) {
6297  GRN_LOG(ctx, GRN_LOG_NOTICE, "buffer reused(%d,%d)", c->buffer_pseg, *c->ppseg);
6298  // todo : rewind;
6299  }
6300  c->bp = NEXT_ADDR(br);
6301  GRN_B_DEC(c->pb.rid, c->bp);
6302  if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
6303  GRN_B_DEC(c->pb.sid, c->bp);
6304  } else {
6305  c->pb.sid = 1;
6306  }
6307  if (lrid > c->pb.rid || (lrid == c->pb.rid && lsid >= c->pb.sid)) {
6308  ERR(GRN_FILE_CORRUPT, "brokend!! (%d:%d) -> (%d:%d) (%d->%d)", lrid, lsid, c->pb.rid, c->pb.sid, c->buffer_pseg, *c->ppseg);
6309  }
6310  c->nextb = br->step;
6311  GRN_B_DEC(c->pb.tf, c->bp);
6312  if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
6313  GRN_B_DEC(c->pb.weight, c->bp);
6314  } else {
6315  c->pb.weight = 0;
6316  }
6317  c->pb.rest = c->pb.tf;
6318  c->pb.pos = 0;
6319  } else {
6320  c->pb.rid = 0;
6321  }
6322  }
6323  if (c->pb.rid) {
6324  if (c->pc.rid) {
6325  if (c->pc.rid < c->pb.rid) {
6326  c->stat = CHUNK_USED;
6327  c->post = &c->pc;
6328  break;
6329  } else {
6330  if (c->pb.rid < c->pc.rid) {
6331  c->stat = BUFFER_USED;
6332  c->post = &c->pb;
6333  break;
6334  } else {
6335  if (c->pb.sid) {
6336  if (c->pc.sid < c->pb.sid) {
6337  c->stat = CHUNK_USED;
6338  c->post = &c->pc;
6339  break;
6340  } else {
6341  c->stat = BUFFER_USED;
6342  if (c->pb.sid == c->pc.sid) { c->stat |= CHUNK_USED; }
6343  c->post = &c->pb;
6344  break;
6345  }
6346  } else {
6347  c->stat = CHUNK_USED;
6348  }
6349  }
6350  }
6351  } else {
6352  c->stat = BUFFER_USED;
6353  c->post = &c->pb;
6354  break;
6355  }
6356  } else {
6357  if (c->pc.rid) {
6358  c->stat = CHUNK_USED;
6359  c->post = &c->pc;
6360  break;
6361  } else {
6362  c->post = NULL;
6363  return NULL;
6364  }
6365  }
6366  }
6367  } else {
6368  if (c->stat & SOLE_DOC_USED) {
6369  c->post = NULL;
6370  return NULL;
6371  } else {
6372  c->post = &c->pb;
6373  c->stat |= SOLE_DOC_USED;
6374  }
6375  }
6376  return c->post;
6377 }
6378 
6379 void
6381 {
6382  grn_obj key_buf;
6383  char key[GRN_TABLE_MAX_KEY_SIZE];
6384  int key_size;
6385  int i = 0;
6386 
6387  GRN_TEXT_PUTS(ctx, buf, " #<");
6388  key_size = grn_table_get_key(ctx, c->ii->lexicon, c->id,
6389  key, GRN_TABLE_MAX_KEY_SIZE);
6390  GRN_OBJ_INIT(&key_buf, GRN_BULK, 0, c->ii->lexicon->header.domain);
6391  GRN_TEXT_SET(ctx, &key_buf, key, key_size);
6392  grn_inspect(ctx, buf, &key_buf);
6393  GRN_OBJ_FIN(ctx, &key_buf);
6394 
6395  GRN_TEXT_PUTS(ctx, buf, "\n elements:[\n ");
6396  while (grn_ii_cursor_next_all(ctx, c)) {
6397  grn_ii_posting *pos = c->post;
6398  if (i > 0) {
6399  GRN_TEXT_PUTS(ctx, buf, ",\n ");
6400  }
6401  i++;
6402  GRN_TEXT_PUTS(ctx, buf, "{status:");
6403  if (pos->tf && pos->sid) {
6404  GRN_TEXT_PUTS(ctx, buf, "available");
6405  } else {
6406  GRN_TEXT_PUTS(ctx, buf, "garbage");
6407  }
6408  GRN_TEXT_PUTS(ctx, buf, ", rid:");
6409  grn_text_lltoa(ctx, buf, pos->rid);
6410  GRN_TEXT_PUTS(ctx, buf, ", sid:");
6411  grn_text_lltoa(ctx, buf, pos->sid);
6412  GRN_TEXT_PUTS(ctx, buf, ", pos:");
6413  grn_text_lltoa(ctx, buf, pos->pos);
6414  GRN_TEXT_PUTS(ctx, buf, ", tf:");
6415  grn_text_lltoa(ctx, buf, pos->tf);
6416  GRN_TEXT_PUTS(ctx, buf, ", weight:");
6417  grn_text_lltoa(ctx, buf, pos->weight);
6418  GRN_TEXT_PUTS(ctx, buf, ", rest:");
6419  grn_text_lltoa(ctx, buf, pos->rest);
6420  GRN_TEXT_PUTS(ctx, buf, "}");
6421  }
6422  GRN_TEXT_PUTS(ctx, buf, "\n ]\n >");
6423 }
6424 
6425 void
6427 {
6428  grn_table_cursor *tc;
6429  GRN_TEXT_PUTS(ctx, buf, "[");
6430  if ((tc = grn_table_cursor_open(ctx, ii->lexicon, NULL, 0, NULL, 0, 0, -1,
6432  int i = 0;
6433  grn_id tid;
6434  grn_ii_cursor *c;
6435  while ((tid = grn_table_cursor_next(ctx, tc))) {
6436  if (i > 0) {
6437  GRN_TEXT_PUTS(ctx, buf, ",");
6438  }
6439  i++;
6440  GRN_TEXT_PUTS(ctx, buf, "\n");
6441  if ((c = grn_ii_cursor_open(ctx, ii, tid, GRN_ID_NIL, GRN_ID_MAX,
6442  ii->n_elements,
6443  GRN_OBJ_WITH_POSITION|GRN_OBJ_WITH_SECTION))) {
6444  grn_ii_cursor_inspect(ctx, c, buf);
6445  grn_ii_cursor_close(ctx, c);
6446  }
6447  }
6448  grn_table_cursor_close(ctx, tc);
6449  }
6450  GRN_TEXT_PUTS(ctx, buf, "]");
6451 }
6452 
6453 /********************** buffered index builder ***********************/
6454 
6455 const grn_id II_BUFFER_RID_FLAG = 0x80000000;
6456 const grn_id II_BUFFER_WEIGHT_FLAG = 0x40000000;
6457 #ifdef II_BUFFER_ORDER_BY_ID
6458 const int II_BUFFER_ORDER = GRN_CURSOR_BY_ID;
6459 #else /* II_BUFFER_ORDER_BY_ID */
6460 const int II_BUFFER_ORDER = GRN_CURSOR_BY_KEY;
6461 #endif /* II_BUFFER_ORDER_BY_ID */
6462 const uint16_t II_BUFFER_NTERMS_PER_BUFFER = 16380;
6463 const uint32_t II_BUFFER_PACKED_BUF_SIZE = 0x4000000;
6464 const char *TMPFILE_PATH = "grn_ii_buffer_tmp";
6465 const uint32_t II_BUFFER_NCOUNTERS_MARGIN = 0x100000;
6466 const size_t II_BUFFER_BLOCK_SIZE = 0x1000000;
6467 const uint32_t II_BUFFER_BLOCK_READ_UNIT_SIZE = 0x200000;
6468 
6469 typedef struct {
6470  uint32_t nrecs;
6471  uint32_t nposts;
6473  uint32_t last_sid;
6474  uint32_t last_tf;
6475  uint32_t last_weight;
6476  uint32_t last_pos;
6477  uint32_t offset_rid;
6478  uint32_t offset_sid;
6479  uint32_t offset_tf;
6480  uint32_t offset_weight;
6481  uint32_t offset_pos;
6483 
6484 typedef struct {
6485  off_t head;
6486  off_t tail;
6487  uint32_t nextsize;
6488  uint8_t *buffer;
6489  uint32_t buffersize;
6490  uint8_t *bufcur;
6491  uint32_t rest;
6493  uint32_t nrecs;
6494  uint32_t nposts;
6496  uint32_t *tfs;
6497  uint32_t *posts;
6498 } ii_buffer_block;
6499 
6504  uint32_t nblocks;
6505  int tmpfd;
6508  // stuff for parsing
6509  off_t filepos;
6512  size_t block_pos;
6514  uint32_t ncounters;
6515  size_t total_size;
6516  size_t curr_size;
6517  // stuff for merging
6519  uint32_t lseg;
6520  uint32_t dseg;
6523  uint8_t *packed_buf;
6525  size_t packed_len;
6527 };
6528 
6529 static ii_buffer_block *
6530 block_new(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
6531 {
6532  ii_buffer_block *block;
6533  if (!(ii_buffer->nblocks & 0x3ff)) {
6534  ii_buffer_block *blocks;
6535  if (!(blocks = GRN_REALLOC(ii_buffer->blocks,
6536  (ii_buffer->nblocks + 0x400) *
6537  sizeof(ii_buffer_block)))) {
6538  return NULL;
6539  }
6540  ii_buffer->blocks = blocks;
6541  }
6542  block = &ii_buffer->blocks[ii_buffer->nblocks];
6543  block->head = ii_buffer->filepos;
6544  block->rest = 0;
6545  block->buffer = NULL;
6546  block->buffersize = 0;
6547  return block;
6548 }
6549 
6550 static uint8_t *
6551 allocate_outbuf(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
6552 {
6553  size_t bufsize = 0, bufsize_ = 0;
6554  uint32_t flags = ii_buffer->ii->header->flags;
6555  ii_buffer_counter *counter = ii_buffer->counters;
6556  grn_id tid, tid_max = grn_table_size(ctx, ii_buffer->tmp_lexicon);
6557  for (tid = 1; tid <= tid_max; counter++, tid++) {
6558  counter->offset_tf += GRN_B_ENC_SIZE(counter->last_tf - 1);
6559  counter->last_rid = 0;
6560  counter->last_tf = 0;
6561  bufsize += 5;
6562  bufsize += GRN_B_ENC_SIZE(counter->nrecs);
6563  bufsize += GRN_B_ENC_SIZE(counter->nposts);
6564  bufsize += counter->offset_rid;
6565  if ((flags & GRN_OBJ_WITH_SECTION)) {
6566  bufsize += counter->offset_sid;
6567  }
6568  bufsize += counter->offset_tf;
6569  if ((flags & GRN_OBJ_WITH_WEIGHT)) {
6570  bufsize += counter->offset_weight;
6571  }
6572  if ((flags & GRN_OBJ_WITH_POSITION)) {
6573  bufsize += counter->offset_pos;
6574  }
6575  if (bufsize_ + II_BUFFER_BLOCK_READ_UNIT_SIZE < bufsize) {
6576  bufsize += sizeof(uint32_t);
6577  bufsize_ = bufsize;
6578  }
6579  }
6580  GRN_LOG(ctx, GRN_LOG_INFO, "flushing:%d bufsize:%zu",
6581  ii_buffer->nblocks, bufsize);
6582  return (uint8_t *)GRN_MALLOC(bufsize);
6583 }
6584 
6585 static size_t
6586 encode_terms(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
6587  uint8_t *outbuf, ii_buffer_block *block)
6588 {
6589  grn_id tid;
6590  uint8_t *outbufp = outbuf;
6591  uint8_t *outbufp_ = outbuf;
6592  grn_table_cursor *tc;
6593  uint8_t *pnext = (uint8_t *)&block->nextsize;
6594  uint32_t flags = ii_buffer->ii->header->flags;
6595  tc = grn_table_cursor_open(ctx, ii_buffer->tmp_lexicon,
6596  NULL, 0, NULL, 0, 0, -1, II_BUFFER_ORDER);
6597  while ((tid = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
6598  char key[GRN_TABLE_MAX_KEY_SIZE];
6599  int key_size = grn_table_get_key(ctx, ii_buffer->tmp_lexicon, tid,
6600  key, GRN_TABLE_MAX_KEY_SIZE);
6601  grn_id gtid = grn_table_add(ctx, ii_buffer->lexicon, key, key_size, NULL);
6602  ii_buffer_counter *counter = &ii_buffer->counters[tid - 1];
6603  if (counter->nrecs) {
6604  uint32_t offset_rid = counter->offset_rid;
6605  uint32_t offset_sid = counter->offset_sid;
6606  uint32_t offset_tf = counter->offset_tf;
6607  uint32_t offset_weight = counter->offset_weight;
6608  uint32_t offset_pos = counter->offset_pos;
6609  GRN_B_ENC(gtid, outbufp);
6610  GRN_B_ENC(counter->nrecs, outbufp);
6611  GRN_B_ENC(counter->nposts, outbufp);
6612  ii_buffer->total_size += counter->nrecs + counter->nposts;
6613  counter->offset_rid = outbufp - outbuf;
6614  outbufp += offset_rid;
6615  if ((flags & GRN_OBJ_WITH_SECTION)) {
6616  counter->offset_sid = outbufp - outbuf;
6617  outbufp += offset_sid;
6618  }
6619  counter->offset_tf = outbufp - outbuf;
6620  outbufp += offset_tf;
6621  if ((flags & GRN_OBJ_WITH_WEIGHT)) {
6622  counter->offset_weight = outbufp - outbuf;
6623  outbufp += offset_weight;
6624  }
6625  if ((flags & GRN_OBJ_WITH_POSITION)) {
6626  counter->offset_pos = outbufp - outbuf;
6627  outbufp += offset_pos;
6628  }
6629  }
6630  if (outbufp_ + II_BUFFER_BLOCK_READ_UNIT_SIZE < outbufp) {
6631  uint32_t size = outbufp - outbufp_ + sizeof(uint32_t);
6632  memcpy(pnext, &size, sizeof(uint32_t));
6633  pnext = outbufp;
6634  outbufp += sizeof(uint32_t);
6635  outbufp_ = outbufp;
6636  }
6637  }
6638  grn_table_cursor_close(ctx, tc);
6639  if (outbufp_ < outbufp) {
6640  uint32_t size = outbufp - outbufp_;
6641  memcpy(pnext, &size, sizeof(uint32_t));
6642  }
6643  return outbufp - outbuf;
6644 }
6645 
6646 static void
6647 encode_postings(grn_ctx *ctx, grn_ii_buffer *ii_buffer, uint8_t *outbuf)
6648 {
6649  grn_id rid = 0;
6650  unsigned int sid = 1;
6651  unsigned int weight = 0;
6652  uint32_t pos = 0;
6653  uint32_t rest;
6654  grn_id *bp = ii_buffer->block_buf;
6655  uint32_t flags = ii_buffer->ii->header->flags;
6656  for (rest = ii_buffer->block_pos; rest; bp++, rest--) {
6657  grn_id id = *bp;
6658  if (id & II_BUFFER_RID_FLAG) {
6659  rid = id - II_BUFFER_RID_FLAG;
6660  if ((flags & GRN_OBJ_WITH_SECTION) && rest) {
6661  sid = *++bp;
6662  rest--;
6663  }
6664  weight = 0;
6665  pos = 0;
6666  } else if (id & II_BUFFER_WEIGHT_FLAG) {
6667  weight = id - II_BUFFER_WEIGHT_FLAG;
6668  } else {
6669  ii_buffer_counter *counter = &ii_buffer->counters[id - 1];
6670  if (counter->last_rid == rid && counter->last_sid == sid) {
6671  counter->last_tf++;
6672  counter->last_weight += weight;
6673  } else {
6674  if (counter->last_tf) {
6675  uint8_t *p = outbuf + counter->offset_tf;
6676  GRN_B_ENC(counter->last_tf - 1, p);
6677  counter->offset_tf = p - outbuf;
6678  if (flags & GRN_OBJ_WITH_WEIGHT) {
6679  p = outbuf + counter->offset_weight;
6680  GRN_B_ENC(counter->last_weight, p);
6681  counter->offset_weight = p - outbuf;
6682  }
6683  }
6684  {
6685  uint8_t *p = outbuf + counter->offset_rid;
6686  GRN_B_ENC(rid - counter->last_rid, p);
6687  counter->offset_rid = p - outbuf;
6688  }
6689  if (flags & GRN_OBJ_WITH_SECTION) {
6690  uint8_t *p = outbuf + counter->offset_sid;
6691  if (counter->last_rid != rid) {
6692  GRN_B_ENC(sid - 1, p);
6693  } else {
6694  GRN_B_ENC(sid - counter->last_sid - 1, p);
6695  }
6696  counter->offset_sid = p - outbuf;
6697  }
6698  counter->last_rid = rid;
6699  counter->last_sid = sid;
6700  counter->last_tf = 1;
6701  counter->last_weight = weight;
6702  counter->last_pos = 0;
6703  }
6704  if (flags & GRN_OBJ_WITH_POSITION) {
6705  uint8_t *p = outbuf + counter->offset_pos;
6706  GRN_B_ENC(pos - counter->last_pos, p);
6707  counter->offset_pos = p - outbuf;
6708  counter->last_pos = pos;
6709  }
6710  pos++;
6711  }
6712  }
6713 }
6714 
6715 static void
6716 encode_last_tf(grn_ctx *ctx, grn_ii_buffer *ii_buffer, uint8_t *outbuf)
6717 {
6718  ii_buffer_counter *counter = ii_buffer->counters;
6719  grn_id tid, tid_max = grn_table_size(ctx, ii_buffer->tmp_lexicon);
6720  for (tid = 1; tid <= tid_max; counter++, tid++) {
6721  uint8_t *p = outbuf + counter->offset_tf;
6722  GRN_B_ENC(counter->last_tf - 1, p);
6723  }
6724  if ((ii_buffer->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {
6725  for (tid = 1; tid <= tid_max; counter++, tid++) {
6726  uint8_t *p = outbuf + counter->offset_weight;
6727  GRN_B_ENC(counter->last_weight, p);
6728  }
6729  }
6730 }
6731 
6732 static void
6733 grn_ii_buffer_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
6734 {
6735  size_t encsize;
6736  uint8_t *outbuf;
6737  ii_buffer_block *block;
6738  GRN_LOG(ctx, GRN_LOG_NOTICE, "flushing:%d npostings:%zu",
6739  ii_buffer->nblocks, ii_buffer->block_pos);
6740  if (!(block = block_new(ctx, ii_buffer))) { return; }
6741  if (!(outbuf = allocate_outbuf(ctx, ii_buffer))) { return; }
6742  encsize = encode_terms(ctx, ii_buffer, outbuf, block);
6743  encode_postings(ctx, ii_buffer, outbuf);
6744  encode_last_tf(ctx, ii_buffer, outbuf);
6745  {
6746  ssize_t r = GRN_WRITE(ii_buffer->tmpfd, outbuf, encsize);
6747  if (r != encsize) {
6748  ERR(GRN_INPUT_OUTPUT_ERROR, "write returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU,
6749  (long long int)r, (unsigned long long int)encsize);
6750  return;
6751  }
6752  ii_buffer->filepos += r;
6753  block->tail = ii_buffer->filepos;
6754  }
6755  GRN_FREE(outbuf);
6756  memset(ii_buffer->counters, 0,
6757  grn_table_size(ctx, ii_buffer->tmp_lexicon) *
6758  sizeof(ii_buffer_counter));
6759  grn_obj_close(ctx, ii_buffer->tmp_lexicon);
6760  GRN_LOG(ctx, GRN_LOG_NOTICE, "flushed: %d encsize:%zu",
6761  ii_buffer->nblocks, encsize);
6762  ii_buffer->tmp_lexicon = NULL;
6763  ii_buffer->nblocks++;
6764  ii_buffer->block_pos = 0;
6765 }
6766 
6767 const uint32_t PAT_CACHE_SIZE = 1<<20;
6768 
6769 static grn_obj *
6770 get_tmp_lexicon(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
6771 {
6772  grn_obj *tmp_lexicon = ii_buffer->tmp_lexicon;
6773  if (!tmp_lexicon) {
6774  grn_obj *domain = grn_ctx_at(ctx, ii_buffer->lexicon->header.domain);
6775  grn_obj *range = grn_ctx_at(ctx, DB_OBJ(ii_buffer->lexicon)->range);
6776  grn_obj *tokenizer;
6777  grn_obj *normalizer;
6778  grn_obj_flags flags;
6779  grn_table_get_info(ctx, ii_buffer->lexicon, &flags, NULL,
6780  &tokenizer, &normalizer);
6781  flags &= ~GRN_OBJ_PERSISTENT;
6782  tmp_lexicon = grn_table_create(ctx, NULL, 0, NULL, flags, domain, range);
6783  if (tmp_lexicon) {
6784  ii_buffer->tmp_lexicon = tmp_lexicon;
6785  grn_obj_set_info(ctx, tmp_lexicon,
6786  GRN_INFO_DEFAULT_TOKENIZER, tokenizer);
6787  grn_obj_set_info(ctx, tmp_lexicon,
6788  GRN_INFO_NORMALIZER, normalizer);
6790  grn_pat_cache_enable(ctx, (grn_pat *)tmp_lexicon, PAT_CACHE_SIZE);
6791  }
6792  }
6793  }
6794  return tmp_lexicon;
6795 }
6796 
6797 static ii_buffer_counter *
6798 get_buffer_counter(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
6799  grn_obj *tmp_lexicon, grn_id tid)
6800 {
6801  if (tid > ii_buffer->ncounters) {
6802  ii_buffer_counter *counters;
6803  uint32_t ncounters =
6804  grn_table_size(ctx, tmp_lexicon) + II_BUFFER_NCOUNTERS_MARGIN;
6805  counters = GRN_REALLOC(ii_buffer->counters,
6806  ncounters * sizeof(ii_buffer_counter));
6807  if (!counters) { return NULL; }
6808  memset(&counters[ii_buffer->ncounters], 0,
6809  (ncounters - ii_buffer->ncounters) * sizeof(ii_buffer_counter));
6810  ii_buffer->ncounters = ncounters;
6811  ii_buffer->counters = counters;
6812  }
6813  return &ii_buffer->counters[tid - 1];
6814 }
6815 
6816 static void
6817 grn_ii_buffer_tokenize(grn_ctx *ctx, grn_ii_buffer *ii_buffer, grn_id rid,
6818  unsigned int sid, unsigned int weight,
6819  const char *value, uint32_t value_len)
6820 {
6821  if (value_len) {
6822  grn_obj *tmp_lexicon;
6823  uint32_t est_len = value_len + 2;
6824  if (ii_buffer->block_buf_size < ii_buffer->block_pos + est_len) {
6825  grn_ii_buffer_flush(ctx, ii_buffer);
6826  }
6827  if (ii_buffer->block_buf_size < est_len) {
6828  grn_id *block_buf = (grn_id *)GRN_REALLOC(ii_buffer->block_buf,
6829  est_len * sizeof(grn_id));
6830  if (!block_buf) { return; }
6831  ii_buffer->block_buf = block_buf;
6832  ii_buffer->block_buf_size = est_len;
6833  }
6834  if ((tmp_lexicon = get_tmp_lexicon(ctx, ii_buffer))) {
6835  unsigned int token_flags = 0;
6836  grn_token *token;
6837  grn_id *buffer = ii_buffer->block_buf;
6838  uint32_t block_pos = ii_buffer->block_pos;
6839  buffer[block_pos++] = rid + II_BUFFER_RID_FLAG;
6840  if ((ii_buffer->ii->header->flags & GRN_OBJ_WITH_SECTION)) {
6841  buffer[block_pos++] = sid;
6842  }
6843  if (weight) {
6844  buffer[block_pos++] = weight + II_BUFFER_WEIGHT_FLAG;
6845  }
6846  if ((token = grn_token_open(ctx, tmp_lexicon, value,
6847  value_len, GRN_TOKEN_ADD, token_flags))) {
6848  uint32_t pos;
6849  for (pos = 0; !token->status; pos++) {
6850  grn_id tid;
6851  if ((tid = grn_token_next(ctx, token))) {
6852  ii_buffer_counter *counter;
6853  counter = get_buffer_counter(ctx, ii_buffer, tmp_lexicon, tid);
6854  if (!counter) { return; }
6855  buffer[block_pos++] = tid;
6856  if (counter->last_rid != rid) {
6857  counter->offset_rid += GRN_B_ENC_SIZE(rid - counter->last_rid);
6858  counter->last_rid = rid;
6859  counter->offset_sid += GRN_B_ENC_SIZE(sid - 1);
6860  counter->last_sid = sid;
6861  if (counter->last_tf) {
6862  counter->offset_tf += GRN_B_ENC_SIZE(counter->last_tf - 1);
6863  counter->last_tf = 0;
6864  counter->offset_weight += GRN_B_ENC_SIZE(counter->last_weight);
6865  counter->last_weight = 0;
6866  }
6867  counter->last_pos = 0;
6868  counter->nrecs++;
6869  } else if (counter->last_sid != sid) {
6870  counter->offset_rid += GRN_B_ENC_SIZE(0);
6871  counter->offset_sid +=
6872  GRN_B_ENC_SIZE(sid - counter->last_sid - 1);
6873  counter->last_sid = sid;
6874  if (counter->last_tf) {
6875  counter->offset_tf += GRN_B_ENC_SIZE(counter->last_tf - 1);
6876  counter->last_tf = 0;
6877  counter->offset_weight += GRN_B_ENC_SIZE(counter->last_weight);
6878  counter->last_weight = 0;
6879  }
6880  counter->last_pos = 0;
6881  counter->nrecs++;
6882  }
6883  counter->offset_pos += GRN_B_ENC_SIZE(pos - counter->last_pos);
6884  counter->last_pos = pos;
6885  counter->last_tf++;
6886  counter->last_weight += weight;
6887  counter->nposts++;
6888  }
6889  }
6890  grn_token_close(ctx, token);
6891  }
6892  ii_buffer->block_pos = block_pos;
6893  }
6894  }
6895 }
6896 
6897 static void
6898 grn_ii_buffer_fetch(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
6899  ii_buffer_block *block)
6900 {
6901  if (!block->rest) {
6902  if (block->head < block->tail) {
6903  size_t bytesize = block->nextsize;
6904  if (block->buffersize < block->nextsize) {
6905  void *r = GRN_REALLOC(block->buffer, bytesize);
6906  if (r) {
6907  block->buffer = (uint8_t *)r;
6908  block->buffersize = block->nextsize;
6909  } else {
6910  GRN_LOG(ctx, GRN_LOG_WARNING, "realloc: %" GRN_FMT_LLU,
6911  (unsigned long long int)bytesize);
6912  return;
6913  }
6914  }
6915  if (lseek(ii_buffer->tmpfd, block->head, SEEK_SET) != block->head) {
6916  SERR("lseek");
6917  return;
6918  }
6919  if (read(ii_buffer->tmpfd, block->buffer, bytesize) != bytesize) {
6920  SERR("read");
6921  return;
6922  }
6923  block->head += bytesize;
6924  block->bufcur = block->buffer;
6925  if (block->head >= block->tail) {
6926  if (block->head > block->tail) {
6927  GRN_LOG(ctx, GRN_LOG_WARNING,
6928  "fetch error: %jd > %jd", block->head, block->tail);
6929  }
6930  block->rest = block->nextsize;
6931  block->nextsize = 0;
6932  } else {
6933  block->rest = block->nextsize - sizeof(uint32_t);
6934  memcpy(&block->nextsize,
6935  &block->buffer[block->rest], sizeof(uint32_t));
6936  }
6937  }
6938  }
6939  if (block->rest) {
6940  uint8_t *p = block->bufcur;
6941  GRN_B_DEC(block->tid, p);
6942  GRN_B_DEC(block->nrecs, p);
6943  GRN_B_DEC(block->nposts, p);
6944  block->rest -= (p - block->bufcur);
6945  block->bufcur = p;
6946  } else {
6947  block->tid = 0;
6948  }
6949 }
6950 
6951 static void
6952 grn_ii_buffer_chunk_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
6953 {
6954  grn_io_win io_win;
6955  uint32_t chunk_number;
6956  chunk_new(ctx, ii_buffer->ii, &chunk_number, ii_buffer->packed_len);
6957  GRN_LOG(ctx, GRN_LOG_INFO, "chunk:%d, packed_len:%zu",
6958  chunk_number, ii_buffer->packed_len);
6959  fake_map2(ctx, ii_buffer->ii->chunk, &io_win, ii_buffer->packed_buf,
6960  chunk_number, ii_buffer->packed_len);
6961  grn_io_win_unmap2(&io_win);
6962  ii_buffer->term_buffer->header.chunk = chunk_number;
6963  ii_buffer->term_buffer->header.chunk_size = ii_buffer->packed_len;
6964  ii_buffer->term_buffer->header.buffer_free =
6965  S_SEGMENT - sizeof(buffer_header) -
6966  ii_buffer->term_buffer->header.nterms * sizeof(buffer_term);
6967  ii_buffer->term_buffer->header.nterms_void = 0;
6968  buffer_segment_update(ii_buffer->ii, ii_buffer->lseg, ii_buffer->dseg);
6969  ii_buffer->ii->header->total_chunk_size += ii_buffer->packed_len;
6970  ii_buffer->total_chunk_size += ii_buffer->packed_len;
6971  GRN_LOG(ctx, GRN_LOG_NOTICE,
6972  "nterms=%d chunk=%d total=%" GRN_FMT_INT64U "KB",
6973  ii_buffer->term_buffer->header.nterms,
6974  ii_buffer->term_buffer->header.chunk_size,
6975  ii_buffer->ii->header->total_chunk_size >> 10);
6976  ii_buffer->term_buffer = NULL;
6977  ii_buffer->packed_buf = NULL;
6978  ii_buffer->packed_len = 0;
6979  ii_buffer->packed_buf_size = 0;
6980  ii_buffer->curr_size = 0;
6981 }
6982 
6983 static size_t
6984 merge_hit_blocks(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
6985  ii_buffer_block *hits[], int nhits)
6986 {
6987  uint64_t nrecs = 0;
6988  uint64_t nposts = 0;
6989  size_t max_size;
6990  uint64_t flags = ii_buffer->ii->header->flags;
6991  int i;
6992  for (i = 0; i < nhits; i++) {
6993  ii_buffer_block *block = hits[i];
6994  nrecs += block->nrecs;
6995  nposts += block->nposts;
6996  }
6997  ii_buffer->curr_size += nrecs + nposts;
6998  max_size = nrecs * (ii_buffer->ii->n_elements);
6999  if (flags & GRN_OBJ_WITH_POSITION) { max_size += nposts - nrecs; }
7000  datavec_reset(ctx, ii_buffer->data_vectors,
7001  ii_buffer->ii->n_elements, nrecs, max_size);
7002  {
7003  int i;
7004  uint32_t lr = 0;
7005  uint64_t spos = 0;
7006  uint32_t *ridp, *sidp = NULL, *tfp, *weightp = NULL, *posp = NULL;
7007  {
7008  int j = 0;
7009  ridp = ii_buffer->data_vectors[j++].data;
7010  if (flags & GRN_OBJ_WITH_SECTION) {
7011  sidp = ii_buffer->data_vectors[j++].data;
7012  }
7013  tfp = ii_buffer->data_vectors[j++].data;
7014  if (flags & GRN_OBJ_WITH_WEIGHT) {
7015  weightp = ii_buffer->data_vectors[j++].data;
7016  }
7017  if (flags & GRN_OBJ_WITH_POSITION) {
7018  posp = ii_buffer->data_vectors[j++].data;
7019  }
7020  }
7021  for (i = 0; i < nhits; i++) {
7022  ii_buffer_block *block = hits[i];
7023  uint8_t *p = block->bufcur;
7024  uint32_t n = block->nrecs;
7025  if (n) {
7026  GRN_B_DEC(*ridp, p);
7027  *ridp -= lr;
7028  lr += *ridp++;
7029  while (--n) {
7030  GRN_B_DEC(*ridp, p);
7031  lr += *ridp++;
7032  }
7033  }
7034  if ((flags & GRN_OBJ_WITH_SECTION)) {
7035  for (n = block->nrecs; n; n--) {
7036  GRN_B_DEC(*sidp++, p);
7037  }
7038  }
7039  for (n = block->nrecs; n; n--) {
7040  GRN_B_DEC(*tfp++, p);
7041  }
7042  if ((flags & GRN_OBJ_WITH_WEIGHT)) {
7043  for (n = block->nrecs; n; n--) {
7044  GRN_B_DEC(*weightp++, p);
7045  }
7046  }
7047  if ((flags & GRN_OBJ_WITH_POSITION)) {
7048  for (n = block->nposts; n; n--) {
7049  GRN_B_DEC(*posp, p);
7050  spos += *posp++;
7051  }
7052  }
7053  block->rest -= (p - block->bufcur);
7054  block->bufcur = p;
7055  grn_ii_buffer_fetch(ctx, ii_buffer, block);
7056  }
7057  {
7058  int j = 0;
7059  uint32_t f_s = (nrecs < 3) ? 0 : USE_P_ENC;
7060  uint32_t f_d = ((nrecs < 16) || (nrecs <= (lr >> 8))) ? 0 : USE_P_ENC;
7061  ii_buffer->data_vectors[j].data_size = nrecs;
7062  ii_buffer->data_vectors[j++].flags = f_d;
7063  if ((flags & GRN_OBJ_WITH_SECTION)) {
7064  ii_buffer->data_vectors[j].data_size = nrecs;
7065  ii_buffer->data_vectors[j++].flags = f_s;
7066  }
7067  ii_buffer->data_vectors[j].data_size = nrecs;
7068  ii_buffer->data_vectors[j++].flags = f_s;
7069  if ((flags & GRN_OBJ_WITH_WEIGHT)) {
7070  ii_buffer->data_vectors[j].data_size = nrecs;
7071  ii_buffer->data_vectors[j++].flags = f_s;
7072  }
7073  if ((flags & GRN_OBJ_WITH_POSITION)) {
7074  uint32_t f_p = (((nposts < 32) ||
7075  (nposts <= (spos >> 13))) ? 0 : USE_P_ENC);
7076  ii_buffer->data_vectors[j].data_size = nposts;
7077  ii_buffer->data_vectors[j++].flags = f_p|ODD;
7078  }
7079  }
7080  }
7081  return (max_size + ii_buffer->ii->n_elements) * 4;
7082 }
7083 
7084 static buffer *
7085 get_term_buffer(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
7086 {
7087  if (!ii_buffer->term_buffer) {
7088  uint32_t lseg;
7089  void *term_buffer;
7090  for (lseg = 0; lseg < GRN_II_MAX_LSEG; lseg++) {
7091  if (ii_buffer->ii->header->binfo[lseg] == NOT_ASSIGNED) { break; }
7092  }
7093  if (lseg == GRN_II_MAX_LSEG) {
7094  ERR(GRN_NO_MEMORY_AVAILABLE, "segment allocate failed");
7095  return NULL;
7096  }
7097  ii_buffer->lseg = lseg;
7098  ii_buffer->dseg = segment_get(ctx, ii_buffer->ii);
7099  GRN_IO_SEG_REF(ii_buffer->ii->seg, ii_buffer->dseg, term_buffer);
7100  ii_buffer->term_buffer = (buffer *)term_buffer;
7101  }
7102  return ii_buffer->term_buffer;
7103 }
7104 
7105 static grn_bool
7106 try_in_place_packing(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
7107  grn_id tid, ii_buffer_block *hits[], int nhits)
7108 {
7109  if (nhits == 1 && hits[0]->nrecs == 1 && hits[0]->nposts == 1) {
7110  grn_id rid;
7111  uint32_t sid = 1, tf, pos = 0, weight = 0;
7112  ii_buffer_block *block = hits[0];
7113  uint8_t *p = block->bufcur;
7114  uint32_t flags = ii_buffer->ii->header->flags;
7115  GRN_B_DEC(rid, p);
7116  if (flags & GRN_OBJ_WITH_SECTION) {
7117  GRN_B_DEC(sid, p);
7118  sid++;
7119  }
7120  GRN_B_DEC(tf, p);
7121  if (tf != 0) { GRN_LOG(ctx, GRN_LOG_WARNING, "tf=%d", tf); }
7122  if (flags & GRN_OBJ_WITH_WEIGHT) { GRN_B_DEC(weight, p); }
7123  if (flags & GRN_OBJ_WITH_POSITION) { GRN_B_DEC(pos, p); }
7124  if (!weight) {
7125  if (flags & GRN_OBJ_WITH_SECTION) {
7126  if (rid < 0x100000 && sid < 0x800) {
7127  uint32_t *a = array_get(ctx, ii_buffer->ii, tid);
7128  a[0] = (rid << 12) + (sid << 1) + 1;
7129  a[1] = pos;
7130  } else {
7131  return GRN_FALSE;
7132  }
7133  } else {
7134  uint32_t *a = array_get(ctx, ii_buffer->ii, tid);
7135  a[0] = (rid << 1) + 1;
7136  a[1] = pos;
7137  }
7138  block->rest -= (p - block->bufcur);
7139  block->bufcur = p;
7140  grn_ii_buffer_fetch(ctx, ii_buffer, block);
7141  return GRN_TRUE;
7142  }
7143  }
7144  return GRN_FALSE;
7145 }
7146 
7147 static void
7148 grn_ii_buffer_merge(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
7149  grn_id tid, ii_buffer_block *hits[], int nhits)
7150 {
7151  if (!try_in_place_packing(ctx, ii_buffer, tid, hits, nhits)) {
7152  size_t max_size = merge_hit_blocks(ctx, ii_buffer, hits, nhits);
7153  if (ii_buffer->packed_buf &&
7154  ii_buffer->packed_buf_size < ii_buffer->packed_len + max_size) {
7155  grn_ii_buffer_chunk_flush(ctx, ii_buffer);
7156  }
7157  if (!ii_buffer->packed_buf) {
7158  size_t buf_size = (max_size > II_BUFFER_PACKED_BUF_SIZE)
7159  ? max_size : II_BUFFER_PACKED_BUF_SIZE;
7160  if ((ii_buffer->packed_buf = GRN_MALLOC(buf_size))) {
7161  ii_buffer->packed_buf_size = buf_size;
7162  }
7163  }
7164  {
7165  uint16_t nterm;
7166  size_t packed_len;
7167  buffer_term *bt;
7168  uint32_t *a = array_get(ctx, ii_buffer->ii, tid);
7169  buffer *term_buffer = get_term_buffer(ctx, ii_buffer);
7170  if (!term_buffer) { return; }
7171  nterm = term_buffer->header.nterms++;
7172  bt = &term_buffer->terms[nterm];
7173  a[0] = SEG2POS(ii_buffer->lseg,
7174  (sizeof(buffer_header) + sizeof(buffer_term) * nterm));
7175  packed_len = grn_p_encv(ctx, ii_buffer->data_vectors,
7176  ii_buffer->ii->n_elements,
7177  ii_buffer->packed_buf +
7178  ii_buffer->packed_len);
7179  bt->tid = tid;
7180  bt->size_in_buffer = 0;
7181  bt->pos_in_buffer = 0;
7182  bt->size_in_chunk = packed_len;
7183  bt->pos_in_chunk = ii_buffer->packed_len;
7184  ii_buffer->packed_len += packed_len;
7185  if (((ii_buffer->curr_size * ii_buffer->update_buffer_size) +
7186  (ii_buffer->total_size * term_buffer->header.nterms * 16)) >=
7187  (ii_buffer->total_size * II_BUFFER_NTERMS_PER_BUFFER * 16)) {
7188  grn_ii_buffer_chunk_flush(ctx, ii_buffer);
7189  }
7190  }
7191  }
7192 }
7193 
7194 grn_ii_buffer *
7196  long long unsigned int update_buffer_size)
7197 {
7198  if (ii && ii->lexicon) {
7199  grn_ii_buffer *ii_buffer = GRN_MALLOCN(grn_ii_buffer, 1);
7200  if (ii_buffer) {
7201  ii_buffer->ii = ii;
7202  ii_buffer->lexicon = ii->lexicon;
7203  ii_buffer->tmp_lexicon = NULL;
7204  ii_buffer->nblocks = 0;
7205  ii_buffer->blocks = NULL;
7206  ii_buffer->ncounters = II_BUFFER_NCOUNTERS_MARGIN;
7207  ii_buffer->block_pos = 0;
7208  ii_buffer->filepos = 0;
7209  ii_buffer->curr_size = 0;
7210  ii_buffer->total_size = 0;
7211  ii_buffer->update_buffer_size = update_buffer_size;
7212  ii_buffer->counters = GRN_CALLOC(ii_buffer->ncounters *
7213  sizeof(ii_buffer_counter));
7214  ii_buffer->term_buffer = NULL;
7215  ii_buffer->packed_buf = NULL;
7216  ii_buffer->packed_len = 0;
7217  ii_buffer->packed_buf_size = 0;
7218  ii_buffer->total_chunk_size = 0;
7219  if (ii_buffer->counters) {
7220  ii_buffer->block_buf = GRN_MALLOCN(grn_id, II_BUFFER_BLOCK_SIZE);
7221  if (ii_buffer->block_buf) {
7222  snprintf(ii_buffer->tmpfpath, PATH_MAX,
7223  "%sXXXXXX", grn_io_path(ii->seg));
7224  ii_buffer->block_buf_size = II_BUFFER_BLOCK_SIZE;
7225  ii_buffer->tmpfd = GRN_MKOSTEMP(ii_buffer->tmpfpath,
7226  O_WRONLY|O_CREAT|O_TRUNC,
7227  S_IRUSR|S_IWUSR);
7228  if (ii_buffer->tmpfd != -1) {
7229  grn_obj_flags flags;
7230  grn_table_get_info(ctx, ii->lexicon, &flags, NULL, NULL, NULL);
7232  grn_pat_cache_enable(ctx, (grn_pat *)ii->lexicon,
7233  PAT_CACHE_SIZE);
7234  }
7235  return ii_buffer;
7236  } else {
7237  SERR("mkostemp");
7238  }
7239  GRN_FREE(ii_buffer->block_buf);
7240  }
7241  GRN_FREE(ii_buffer->counters);
7242  }
7243  GRN_FREE(ii_buffer);
7244  }
7245  } else {
7246  ERR(GRN_INVALID_ARGUMENT, "ii or ii->lexicon is NULL");
7247  }
7248  return NULL;
7249 }
7250 
7251 grn_rc
7253  grn_id rid, unsigned int sid, grn_obj *value)
7254 {
7255  grn_ii_buffer_tokenize(ctx, ii_buffer, rid, sid, 0,
7256  GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value));
7257  return ctx->rc;
7258 }
7259 
7260 grn_rc
7262 {
7263  if (ii_buffer->block_pos) {
7264  grn_ii_buffer_flush(ctx, ii_buffer);
7265  }
7266  if (ii_buffer->tmpfd != -1) {
7267  GRN_CLOSE(ii_buffer->tmpfd);
7268  }
7269  if (ii_buffer->block_buf) {
7270  GRN_FREE(ii_buffer->block_buf);
7271  ii_buffer->block_buf = NULL;
7272  }
7273  if (ii_buffer->counters) {
7274  GRN_FREE(ii_buffer->counters);
7275  ii_buffer->counters = NULL;
7276  }
7277 
7278  if (ii_buffer->update_buffer_size &&
7279  ii_buffer->update_buffer_size < 20) {
7280  if (ii_buffer->update_buffer_size < 10) {
7281  ii_buffer->update_buffer_size =
7282  ii_buffer->total_size >> (10 - ii_buffer->update_buffer_size);
7283  } else {
7284  ii_buffer->update_buffer_size =
7285  ii_buffer->total_size << (ii_buffer->update_buffer_size - 10);
7286  }
7287  }
7288 
7289  GRN_LOG(ctx, GRN_LOG_NOTICE,
7290  "nblocks=%d, update_buffer_size=%" GRN_FMT_INT64U,
7291  ii_buffer->nblocks, ii_buffer->update_buffer_size);
7292 
7293  datavec_init(ctx, ii_buffer->data_vectors, ii_buffer->ii->n_elements, 0, 0);
7294 #ifdef WIN32
7295  ii_buffer->tmpfd = GRN_OPEN(ii_buffer->tmpfpath, O_RDONLY|O_BINARY);
7296 #else /* WIN32 */
7297  ii_buffer->tmpfd = GRN_OPEN(ii_buffer->tmpfpath, O_RDONLY);
7298 #endif /* WIN32 */
7299  if (ii_buffer->tmpfd == -1) {
7300  SERR("oepn");
7301  return ctx->rc;
7302  }
7303  {
7304  uint32_t i;
7305  for (i = 0; i < ii_buffer->nblocks; i++) {
7306  grn_ii_buffer_fetch(ctx, ii_buffer, &ii_buffer->blocks[i]);
7307  }
7308  }
7309  {
7310  ii_buffer_block **hits;
7311  if ((hits = GRN_MALLOCN(ii_buffer_block *, ii_buffer->nblocks))) {
7312  grn_id tid;
7313  grn_table_cursor *tc;
7314  tc = grn_table_cursor_open(ctx, ii_buffer->lexicon,
7315  NULL, 0, NULL, 0, 0, -1, II_BUFFER_ORDER);
7316  if (tc) {
7317  while ((tid = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
7318  int nrests = 0;
7319  int nhits = 0;
7320  uint32_t i;
7321  for (i = 0; i < ii_buffer->nblocks; i++) {
7322  if (ii_buffer->blocks[i].tid == tid) {
7323  hits[nhits++] = &ii_buffer->blocks[i];
7324  }
7325  if (ii_buffer->blocks[i].tid) { nrests++; }
7326  }
7327  if (nhits) { grn_ii_buffer_merge(ctx, ii_buffer, tid, hits, nhits); }
7328  if (!nrests) { break; }
7329  }
7330  if (ii_buffer->packed_len) {
7331  grn_ii_buffer_chunk_flush(ctx, ii_buffer);
7332  }
7333  grn_table_cursor_close(ctx, tc);
7334  }
7335  GRN_FREE(hits);
7336  }
7337  }
7338  datavec_fin(ctx, ii_buffer->data_vectors);
7339  GRN_LOG(ctx, GRN_LOG_NOTICE,
7340  "tmpfile_size:%jd > total_chunk_size:%" GRN_FMT_INT64U,
7341  ii_buffer->filepos, ii_buffer->total_chunk_size);
7342  GRN_CLOSE(ii_buffer->tmpfd);
7343  unlink(ii_buffer->tmpfpath);
7344  ii_buffer->tmpfd = -1;
7345  return ctx->rc;
7346 }
7347 
7348 grn_rc
7350 {
7351  uint32_t i;
7352  grn_obj_flags flags;
7353  grn_table_get_info(ctx, ii_buffer->ii->lexicon, &flags, NULL, NULL, NULL);
7355  grn_pat_cache_disable(ctx, (grn_pat *)ii_buffer->ii->lexicon);
7356  }
7357  if (ii_buffer->tmp_lexicon) {
7358  grn_obj_close(ctx, ii_buffer->tmp_lexicon);
7359  }
7360  if (ii_buffer->tmpfd != -1) {
7361  GRN_CLOSE(ii_buffer->tmpfd);
7362  unlink(ii_buffer->tmpfpath);
7363  }
7364  if (ii_buffer->block_buf) {
7365  GRN_FREE(ii_buffer->block_buf);
7366  }
7367  if (ii_buffer->counters) {
7368  GRN_FREE(ii_buffer->counters);
7369  }
7370  if (ii_buffer->blocks) {
7371  for (i = 0; i < ii_buffer->nblocks; i++) {
7372  if (ii_buffer->blocks[i].buffer) {
7373  GRN_FREE(ii_buffer->blocks[i].buffer);
7374  }
7375  }
7376  GRN_FREE(ii_buffer->blocks);
7377  }
7378  GRN_FREE(ii_buffer);
7379  return ctx->rc;
7380 }
7381 
7382 static void
7383 grn_ii_buffer_parse(grn_ctx *ctx, grn_ii_buffer *ii_buffer,
7384  grn_obj *target, int ncols, grn_obj **cols)
7385 {
7386  grn_table_cursor *tc;
7387  if ((tc = grn_table_cursor_open(ctx, target,
7388  NULL, 0, NULL, 0, 0, -1,
7389  GRN_CURSOR_BY_ID))) {
7390  grn_id rid;
7391  grn_obj rv;
7392  GRN_TEXT_INIT(&rv, 0);
7393  while ((rid = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) {
7394  int sid;
7395  grn_obj **col;
7396  for (sid = 1, col = cols; sid <= ncols; sid++, col++) {
7397  grn_obj_reinit_for(ctx, &rv, *col);
7398  if (GRN_OBJ_TABLEP(*col)) {
7399  grn_table_get_key2(ctx, *col, rid, &rv);
7400  } else {
7401  grn_obj_get_value(ctx, *col, rid, &rv);
7402  }
7403  switch (rv.header.type) {
7404  case GRN_BULK :
7405  grn_ii_buffer_tokenize(ctx, ii_buffer, rid, sid, 0,
7406  GRN_TEXT_VALUE(&rv), GRN_TEXT_LEN(&rv));
7407  break;
7408  case GRN_VECTOR :
7409  if (rv.u.v.body) {
7410  int i;
7411  int n_sections = rv.u.v.n_sections;
7412  grn_section *sections = rv.u.v.sections;
7413  const char *head = GRN_BULK_HEAD(rv.u.v.body);
7414  for (i = 0; i < n_sections; i++) {
7415  grn_section *section = sections + i;
7416  if (section->length == 0) {
7417  continue;
7418  }
7419  grn_ii_buffer_tokenize(ctx, ii_buffer, rid,
7420  sid, section->weight,
7421  head + section->offset, section->length);
7422  }
7423  }
7424  break;
7425  default :
7426  ERR(GRN_INVALID_ARGUMENT, "[index] invalid object assigned as value");
7427  break;
7428  }
7429  }
7430  }
7431  GRN_OBJ_FIN(ctx, &rv);
7432  grn_table_cursor_close(ctx, tc);
7433  }
7434 }
7435 
7436 grn_rc
7437 grn_ii_build(grn_ctx *ctx, grn_ii *ii, uint64_t sparsity)
7438 {
7439  grn_ii_buffer *ii_buffer = grn_ii_buffer_open(ctx, ii, sparsity);
7440  if (ii_buffer) {
7441  grn_id *s = ii->obj.source;
7442  if ((ii->obj.source_size) && s) {
7443  int ncols = ii->obj.source_size / sizeof(grn_id);
7444  grn_obj **cols = GRN_MALLOCN(grn_obj *, ncols);
7445  if (cols) {
7446  int i;
7447  for (i = 0; i < ncols; i++) {
7448  if (!(cols[i] = grn_ctx_at(ctx, s[i]))) { break; }
7449  }
7450  if (i == ncols) {
7451  grn_obj *target = cols[0];
7452  if (!GRN_OBJ_TABLEP(target)) {
7453  target = grn_ctx_at(ctx, target->header.domain);
7454  }
7455  if (target) {
7456  grn_ii_buffer_parse(ctx, ii_buffer, target, ncols, cols);
7457  grn_ii_buffer_commit(ctx, ii_buffer);
7458  } else {
7459  ERR(GRN_INVALID_ARGUMENT, "failed to resolve the target");
7460  }
7461  } else {
7462  ERR(GRN_INVALID_ARGUMENT, "failed to resolve a column (%d)", i);
7463  }
7464  GRN_FREE(cols);
7465  }
7466  } else {
7467  ERR(GRN_INVALID_ARGUMENT, "ii->obj.source is void");
7468  }
7469  grn_ii_buffer_close(ctx, ii_buffer);
7470  }
7471  return ctx->rc;
7472 }