1 /* This file is part of the Zebra server.
2 Copyright (C) 1994-2009 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 <idzebra/isamb.h>
26 #include <yaz/yaz-util.h>
29 #define RIDX_CHUNK 128
39 struct record_index_entry {
40 zint next; /* first block of record info / next free entry */
41 int size; /* size of record or 0 if free entry */
45 static void rect_log_item(int level, const void *b, const char *txt)
51 memcpy(&sys, b, sizeof(sys));
52 len = ((const char *) b)[sizeof(sys)];
54 if (len == sizeof(struct record_index_entry))
56 memcpy(&ent, (const char *)b + sizeof(sys) + 1, len);
57 yaz_log(YLOG_LOG, "%s " ZINT_FORMAT " next=" ZINT_FORMAT " sz=%d", txt, sys,
62 yaz_log(YLOG_LOG, "%s " ZINT_FORMAT, txt, sys);
65 int rect_compare(const void *a, const void *b)
69 memcpy(&s_a, a, sizeof(s_a));
70 memcpy(&s_b, b, sizeof(s_b));
79 void *rect_code_start(void)
84 void rect_encode(void *p, char **dst, const char **src)
89 memcpy(&sys, *src, sizeof(sys));
90 zebra_zint_encode(dst, sys);
91 (*src) += sizeof(sys);
98 memcpy(*dst, *src, len);
103 void rect_decode(void *p, char **dst, const char **src)
108 zebra_zint_decode(src, &sys);
109 memcpy(*dst, &sys, sizeof(sys));
117 memcpy(*dst, *src, len);
122 void rect_code_reset(void *p)
126 void rect_code_stop(void *p)
131 recindex_t recindex_open(BFiles bfs, int rw, int use_isamb)
133 recindex_t p = xmalloc(sizeof(*p));
137 p->index_fname = "reci";
138 p->index_BFile = bf_open(bfs, p->index_fname, RIDX_CHUNK, rw);
139 if (p->index_BFile == NULL)
141 yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", p->index_fname);
148 int isam_block_size = 4096;
151 method.compare_item = rect_compare;
152 method.log_item = rect_log_item;
153 method.codec.start = rect_code_start;
154 method.codec.encode = rect_encode;
155 method.codec.decode = rect_decode;
156 method.codec.reset = rect_code_reset;
157 method.codec.stop = rect_code_stop;
159 p->index_fname = "rect";
160 p->isamb = isamb_open2(bfs, p->index_fname, rw, &method,
162 /* no_cat */ 1, &isam_block_size,
163 /* use_root_ptr */ 1);
167 p->isam_p = isamb_get_root_ptr(p->isamb);
173 static void log_pr(const char *txt)
175 yaz_log(YLOG_LOG, "%s", txt);
179 void recindex_close(recindex_t p)
184 bf_close(p->index_BFile);
187 isamb_set_root_ptr(p->isamb, p->isam_p);
188 isamb_dump(p->isamb, p->isam_p, log_pr);
189 isamb_close(p->isamb);
195 int recindex_read_head(recindex_t p, void *buf)
197 return bf_read(p->index_BFile, 0, 0, 0, buf);
200 const char *recindex_get_fname(recindex_t p)
202 return p->index_fname;
205 ZEBRA_RES recindex_write_head(recindex_t p, const void *buf, size_t len)
211 assert(p->index_BFile);
213 r = bf_write(p->index_BFile, 0, 0, len, buf);
216 yaz_log(YLOG_FATAL|YLOG_ERRNO, "write head of %s", p->index_fname);
222 int recindex_read_indx(recindex_t p, zint sysno, void *buf, int itemsize,
232 char untilbuf[sizeof(zint) + 1];
234 ISAMB_PP isam_pp = isamb_pp_open(p->isamb, p->isam_p, 1);
236 memcpy(untilbuf, &sysno, sizeof(sysno));
237 untilbuf[sizeof(sysno)] = 0;
238 r = isamb_pp_forward(isam_pp, st, untilbuf);
240 isamb_pp_close(isam_pp);
244 if (item[sizeof(sysno)] != itemsize)
246 yaz_log(YLOG_WARN, "unexpected entry size %d != %d",
247 item[sizeof(sysno)], itemsize);
250 memcpy(buf, item + sizeof(sysno) + 1, itemsize);
255 zint pos = (sysno-1)*itemsize;
256 int off = CAST_ZINT_TO_INT(pos%RIDX_CHUNK);
257 int sz1 = RIDX_CHUNK - off; /* sz1 is size of buffer to read.. */
260 sz1 = itemsize; /* no more than itemsize bytes */
262 r = bf_read(p->index_BFile, 1+pos/RIDX_CHUNK, off, sz1, buf);
263 if (r == 1 && sz1 < itemsize) /* boundary? - must read second part */
264 r = bf_read(p->index_BFile, 2+pos/RIDX_CHUNK, 0, itemsize - sz1,
266 if (r != 1 && !ignoreError)
268 yaz_log(YLOG_FATAL|YLOG_ERRNO, "read in %s at pos %ld",
269 p->index_fname, (long) pos);
274 struct record_index_entry *ep = buf;
275 yaz_log(YLOG_LOG, "read r=%d sysno=" ZINT_FORMAT " next=" ZINT_FORMAT
276 " sz=%d", r, sysno, ep->next, ep->size);
282 struct code_read_data {
290 int bt_code_read(void *vp, char **dst, int *insertMode)
292 struct code_read_data *s = (struct code_read_data *) vp;
299 memcpy(*dst, &s->sysno, sizeof(zint));
300 *dst += sizeof(zint);
303 memcpy(*dst, s->buf, s->itemsize);
305 *insertMode = s->insert_flag;
309 void recindex_write_indx(recindex_t p, zint sysno, void *buf, int itemsize)
312 yaz_log(YLOG_LOG, "write_indx sysno=" ZINT_FORMAT, sysno);
316 struct code_read_data input;
321 input.itemsize = itemsize;
323 isamc_i.clientData = &input;
324 isamc_i.read_item = bt_code_read;
327 input.insert_flag = 2;
328 isamb_merge(p->isamb, &p->isam_p, &isamc_i);
332 zint pos = (sysno-1)*itemsize;
333 int off = CAST_ZINT_TO_INT(pos%RIDX_CHUNK);
334 int sz1 = RIDX_CHUNK - off; /* sz1 is size of buffer to read.. */
337 sz1 = itemsize; /* no more than itemsize bytes */
339 bf_write(p->index_BFile, 1+pos/RIDX_CHUNK, off, sz1, buf);
340 if (sz1 < itemsize) /* boundary? must write second part */
341 bf_write(p->index_BFile, 2+pos/RIDX_CHUNK, 0, itemsize - sz1,
350 * c-file-style: "Stroustrup"
351 * indent-tabs-mode: nil
353 * vim: shiftwidth=4 tabstop=8 expandtab