1 /* This file is part of the Zebra server.
2 Copyright (C) 1994-2011 Index Data
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <yaz/xmalloc.h>
26 #include <idzebra/isamb.h>
27 #include <idzebra/bfile.h>
31 #define SORT_MAX_TERM 110
32 #define SORT_MAX_MULTI 4096
34 #define SORT_IDX_BLOCKSIZE 64
40 char term[SORT_MAX_MULTI];
44 static void sort_term_log_item(int level, const void *b, const char *txt)
48 memcpy(&a1, b, sizeof(a1));
50 yaz_log(level, "%s " ZINT_FORMAT " " ZINT_FORMAT " %.*s", txt, a1.sysno,
51 a1.section_id, (int) a1.length-1, a1.term);
54 static int sort_term_compare(const void *a, const void *b)
56 struct sort_term a1, b1;
58 memcpy(&a1, a, sizeof(a1));
59 memcpy(&b1, b, sizeof(b1));
61 if (a1.sysno > b1.sysno)
63 else if (a1.sysno < b1.sysno)
65 if (a1.section_id > b1.section_id)
67 else if (a1.section_id < b1.section_id)
73 static void *sort_term_code_start(void)
78 static void sort_term_encode1(void *p, char **dst, const char **src)
82 memcpy(&a1, *src, sizeof(a1));
85 zebra_zint_encode(dst, a1.sysno); /* encode record id */
86 strcpy(*dst, a1.term); /* then sort term, 0 terminated */
87 *dst += strlen(a1.term) + 1;
90 static void sort_term_encode2(void *p, char **dst, const char **src)
94 memcpy(&a1, *src, sizeof(a1));
97 zebra_zint_encode(dst, a1.sysno);
98 zebra_zint_encode(dst, a1.section_id);
99 zebra_zint_encode(dst, a1.length); /* encode length */
100 memcpy(*dst, a1.term, a1.length);
104 static void sort_term_decode1(void *p, char **dst, const char **src)
109 zebra_zint_decode(src, &a1.sysno);
112 strcpy(a1.term, *src);
113 slen = 1 + strlen(a1.term);
117 memcpy(*dst, &a1, sizeof(a1));
121 static void sort_term_decode2(void *p, char **dst, const char **src)
125 zebra_zint_decode(src, &a1.sysno);
126 zebra_zint_decode(src, &a1.section_id);
127 zebra_zint_decode(src, &a1.length);
129 memcpy(a1.term, *src, a1.length);
132 memcpy(*dst, &a1, sizeof(a1));
136 static void sort_term_code_reset(void *p)
140 static void sort_term_code_stop(void *p)
144 struct sort_term_stream {
150 static int sort_term_code_read(void *vp, char **dst, int *insertMode)
152 struct sort_term_stream *s = (struct sort_term_stream *) vp;
159 *insertMode = s->insert_flag;
160 memcpy(*dst, &s->st, sizeof(s->st));
161 *dst += sizeof(s->st);
165 struct sortFileHead {
177 struct sortFile *next;
178 struct sortFileHead head;
183 struct zebra_sort_index {
189 struct sortFile *current_file;
190 struct sortFile *files;
193 zebra_sort_index_t zebra_sort_open(BFiles bfs, int write_flag, int type)
195 zebra_sort_index_t si = (zebra_sort_index_t) xmalloc(sizeof(*si));
197 si->write_flag = write_flag;
198 si->current_file = NULL;
201 si->entry_buf = (char *) xmalloc(SORT_IDX_ENTRYSIZE);
205 void zebra_sort_close(zebra_sort_index_t si)
207 struct sortFile *sf = si->files;
210 struct sortFile *sf_next = sf->next;
213 case ZEBRA_SORT_TYPE_FLAT:
216 case ZEBRA_SORT_TYPE_ISAMB:
217 case ZEBRA_SORT_TYPE_MULTI:
219 isamb_pp_close(sf->isam_pp);
220 isamb_set_root_ptr(sf->u.isamb, sf->isam_p);
221 isamb_close(sf->u.isamb);
227 xfree(si->entry_buf);
231 int zebra_sort_type(zebra_sort_index_t si, int id)
233 int isam_block_size = 4096;
239 method.compare_item = sort_term_compare;
240 method.log_item = sort_term_log_item;
241 method.codec.reset = sort_term_code_reset;
242 method.codec.start = sort_term_code_start;
243 method.codec.stop = sort_term_code_stop;
245 if (si->current_file && si->current_file->id == id)
247 for (sf = si->files; sf; sf = sf->next)
250 si->current_file = sf;
253 sf = (struct sortFile *) xmalloc(sizeof(*sf));
258 case ZEBRA_SORT_TYPE_FLAT:
260 sprintf(fname, "sort%d", id);
261 yaz_log(YLOG_DEBUG, "sort idx %s wr=%d", fname, si->write_flag);
262 sf->u.bf = bf_open(si->bfs, fname, SORT_IDX_BLOCKSIZE, si->write_flag);
268 if (!bf_read(sf->u.bf, 0, 0, sizeof(sf->head), &sf->head))
270 sf->head.sysno_max = 0;
279 case ZEBRA_SORT_TYPE_ISAMB:
280 method.codec.encode = sort_term_encode1;
281 method.codec.decode = sort_term_decode1;
283 sprintf(fname, "sortb%d", id);
284 sf->u.isamb = isamb_open2(si->bfs, fname, si->write_flag, &method,
286 /* no_cat */ 1, &isam_block_size,
287 /* use_root_ptr */ 1);
295 sf->isam_p = isamb_get_root_ptr(sf->u.isamb);
298 case ZEBRA_SORT_TYPE_MULTI:
299 isam_block_size = 32768;
300 method.codec.encode = sort_term_encode2;
301 method.codec.decode = sort_term_decode2;
303 sprintf(fname, "sortm%d", id);
304 sf->u.isamb = isamb_open2(si->bfs, fname, si->write_flag, &method,
306 /* no_cat */ 1, &isam_block_size,
307 /* use_root_ptr */ 1);
315 sf->isam_p = isamb_get_root_ptr(sf->u.isamb);
322 sf->next = si->files;
323 si->current_file = si->files = sf;
327 static void zebra_sortf_rewind(struct sortFile *sf)
330 isamb_pp_close(sf->isam_pp);
336 void zebra_sort_sysno(zebra_sort_index_t si, zint sysno)
338 zint new_sysno = rec_sysno_to_int(sysno);
341 for (sf = si->files; sf; sf = sf->next)
343 if (sf->no_inserted || sf->no_deleted)
344 zebra_sortf_rewind(sf);
345 else if (sf->isam_pp && new_sysno <= si->sysno)
346 zebra_sortf_rewind(sf);
348 si->sysno = new_sysno;
352 void zebra_sort_delete(zebra_sort_index_t si, zint section_id)
354 struct sortFile *sf = si->current_file;
356 if (!sf || !sf->u.bf)
360 case ZEBRA_SORT_TYPE_FLAT:
361 memset(si->entry_buf, 0, SORT_IDX_ENTRYSIZE);
362 bf_write(sf->u.bf, si->sysno+1, 0, 0, si->entry_buf);
364 case ZEBRA_SORT_TYPE_ISAMB:
365 case ZEBRA_SORT_TYPE_MULTI:
367 if (sf->no_deleted == 0)
369 struct sort_term_stream s;
372 s.st.sysno = si->sysno;
373 s.st.section_id = section_id;
379 isamc_i.clientData = &s;
380 isamc_i.read_item = sort_term_code_read;
382 isamb_merge(sf->u.isamb, &sf->isam_p, &isamc_i);
389 void zebra_sort_add(zebra_sort_index_t si, zint section_id, WRBUF wrbuf)
391 struct sortFile *sf = si->current_file;
394 if (!sf || !sf->u.bf)
398 case ZEBRA_SORT_TYPE_FLAT:
399 /* take first entry from wrbuf - itself is 0-terminated */
400 len = strlen(wrbuf_buf(wrbuf));
401 if (len > SORT_IDX_ENTRYSIZE)
402 len = SORT_IDX_ENTRYSIZE;
404 memcpy(si->entry_buf, wrbuf_buf(wrbuf), len);
405 if (len < SORT_IDX_ENTRYSIZE-len)
406 memset(si->entry_buf+len, 0, SORT_IDX_ENTRYSIZE-len);
407 bf_write(sf->u.bf, si->sysno+1, 0, 0, si->entry_buf);
409 case ZEBRA_SORT_TYPE_ISAMB:
412 if (sf->no_inserted == 0)
414 struct sort_term_stream s;
416 /* take first entry from wrbuf - itself is 0-terminated */
418 len = wrbuf_len(wrbuf);
419 if (len > SORT_MAX_TERM)
422 wrbuf_buf(wrbuf)[len-1] = '\0';
424 memcpy(s.st.term, wrbuf_buf(wrbuf), len);
426 s.st.sysno = si->sysno;
430 isamc_i.clientData = &s;
431 isamc_i.read_item = sort_term_code_read;
433 isamb_merge(sf->u.isamb, &sf->isam_p, &isamc_i);
437 case ZEBRA_SORT_TYPE_MULTI:
439 if (sf->no_inserted == 0)
441 struct sort_term_stream s;
443 len = wrbuf_len(wrbuf);
444 if (len > SORT_MAX_MULTI)
446 len = SORT_MAX_MULTI;
447 wrbuf_buf(wrbuf)[len-1] = '\0';
449 memcpy(s.st.term, wrbuf_buf(wrbuf), len);
451 s.st.sysno = si->sysno;
452 s.st.section_id = section_id;
455 isamc_i.clientData = &s;
456 isamc_i.read_item = sort_term_code_read;
458 isamb_merge(sf->u.isamb, &sf->isam_p, &isamc_i);
466 int zebra_sort_read(zebra_sort_index_t si, zint *section_id, WRBUF w)
469 struct sortFile *sf = si->current_file;
470 char tbuf[SORT_IDX_ENTRYSIZE];
477 case ZEBRA_SORT_TYPE_FLAT:
478 r = bf_read(sf->u.bf, si->sysno+1, 0, 0, tbuf);
486 case ZEBRA_SORT_TYPE_ISAMB:
487 case ZEBRA_SORT_TYPE_MULTI:
492 sf->isam_pp = isamb_pp_open(sf->u.isamb, sf->isam_p, 1);
495 struct sort_term st, st_untilbuf;
497 st_untilbuf.sysno = si->sysno;
498 st_untilbuf.section_id = 0;
499 st_untilbuf.length = 0;
500 st_untilbuf.term[0] = '\0';
501 r = isamb_pp_forward(sf->isam_pp, &st, &st_untilbuf);
502 if (r && st.sysno == si->sysno)
504 wrbuf_write(w, st.term, st.length);
506 *section_id = st.section_id;
518 * c-file-style: "Stroustrup"
519 * indent-tabs-mode: nil
521 * vim: shiftwidth=4 tabstop=8 expandtab