1 /* This file is part of the Zebra server.
2 Copyright (C) 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
28 #include <idzebra/isamb.h>
29 #include <yaz/yaz-util.h>
32 #define RIDX_CHUNK 128
42 struct record_index_entry {
43 zint next; /* first block of record info / next free entry */
44 int size; /* size of record or 0 if free entry */
48 static void rect_log_item(int level, const void *b, const char *txt)
54 memcpy(&sys, b, sizeof(sys));
55 len = ((const char *) b)[sizeof(sys)];
57 if (len == sizeof(struct record_index_entry))
59 memcpy(&ent, (const char *)b + sizeof(sys) + 1, len);
60 yaz_log(YLOG_LOG, "%s " ZINT_FORMAT " next=" ZINT_FORMAT " sz=%d", txt, sys,
65 yaz_log(YLOG_LOG, "%s " ZINT_FORMAT, txt, sys);
68 int rect_compare(const void *a, const void *b)
72 memcpy(&s_a, a, sizeof(s_a));
73 memcpy(&s_b, b, sizeof(s_b));
82 void *rect_code_start(void)
87 void rect_encode(void *p, char **dst, const char **src)
92 memcpy(&sys, *src, sizeof(sys));
93 zebra_zint_encode(dst, sys);
94 (*src) += sizeof(sys);
101 memcpy(*dst, *src, len);
106 void rect_decode(void *p, char **dst, const char **src)
111 zebra_zint_decode(src, &sys);
112 memcpy(*dst, &sys, sizeof(sys));
120 memcpy(*dst, *src, len);
125 void rect_code_reset(void *p)
129 void rect_code_stop(void *p)
134 recindex_t recindex_open(BFiles bfs, int rw, int use_isamb)
136 recindex_t p = xmalloc(sizeof(*p));
140 p->index_fname = "reci";
141 p->index_BFile = bf_open(bfs, p->index_fname, RIDX_CHUNK, rw);
142 if (p->index_BFile == NULL)
144 yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", p->index_fname);
151 int isam_block_size = 4096;
154 method.compare_item = rect_compare;
155 method.log_item = rect_log_item;
156 method.codec.start = rect_code_start;
157 method.codec.encode = rect_encode;
158 method.codec.decode = rect_decode;
159 method.codec.reset = rect_code_reset;
160 method.codec.stop = rect_code_stop;
162 p->index_fname = "rect";
163 p->isamb = isamb_open2(bfs, p->index_fname, rw, &method,
165 /* no_cat */ 1, &isam_block_size,
166 /* use_root_ptr */ 1);
170 p->isam_p = isamb_get_root_ptr(p->isamb);
176 static void log_pr(const char *txt)
178 yaz_log(YLOG_LOG, "%s", txt);
182 void recindex_close(recindex_t p)
187 bf_close(p->index_BFile);
190 isamb_set_root_ptr(p->isamb, p->isam_p);
191 isamb_dump(p->isamb, p->isam_p, log_pr);
192 isamb_close(p->isamb);
198 int recindex_read_head(recindex_t p, void *buf)
200 return bf_read(p->index_BFile, 0, 0, 0, buf);
203 const char *recindex_get_fname(recindex_t p)
205 return p->index_fname;
208 ZEBRA_RES recindex_write_head(recindex_t p, const void *buf, size_t len)
214 assert(p->index_BFile);
216 r = bf_write(p->index_BFile, 0, 0, len, buf);
219 yaz_log(YLOG_FATAL|YLOG_ERRNO, "write head of %s", p->index_fname);
225 int recindex_read_indx(recindex_t p, zint sysno, void *buf, int itemsize,
235 char untilbuf[sizeof(zint) + 1];
237 ISAMB_PP isam_pp = isamb_pp_open(p->isamb, p->isam_p, 1);
239 memcpy(untilbuf, &sysno, sizeof(sysno));
240 untilbuf[sizeof(sysno)] = 0;
241 r = isamb_pp_forward(isam_pp, st, untilbuf);
243 isamb_pp_close(isam_pp);
247 if (item[sizeof(sysno)] != itemsize)
249 yaz_log(YLOG_WARN, "unexpected entry size %d != %d",
250 item[sizeof(sysno)], itemsize);
253 memcpy(buf, item + sizeof(sysno) + 1, itemsize);
258 zint pos = (sysno-1)*itemsize;
259 int off = CAST_ZINT_TO_INT(pos%RIDX_CHUNK);
260 int sz1 = RIDX_CHUNK - off; /* sz1 is size of buffer to read.. */
263 sz1 = itemsize; /* no more than itemsize bytes */
265 r = bf_read(p->index_BFile, 1+pos/RIDX_CHUNK, off, sz1, buf);
266 if (r == 1 && sz1 < itemsize) /* boundary? - must read second part */
267 r = bf_read(p->index_BFile, 2+pos/RIDX_CHUNK, 0, itemsize - sz1,
269 if (r != 1 && !ignoreError)
271 yaz_log(YLOG_FATAL|YLOG_ERRNO, "read in %s at pos %ld",
272 p->index_fname, (long) pos);
277 struct record_index_entry *ep = buf;
278 yaz_log(YLOG_LOG, "read r=%d sysno=" ZINT_FORMAT " next=" ZINT_FORMAT
279 " sz=%d", r, sysno, ep->next, ep->size);
285 struct code_read_data {
293 int bt_code_read(void *vp, char **dst, int *insertMode)
295 struct code_read_data *s = (struct code_read_data *) vp;
302 memcpy(*dst, &s->sysno, sizeof(zint));
303 *dst += sizeof(zint);
306 memcpy(*dst, s->buf, s->itemsize);
308 *insertMode = s->insert_flag;
312 void recindex_write_indx(recindex_t p, zint sysno, void *buf, int itemsize)
315 yaz_log(YLOG_LOG, "write_indx sysno=" ZINT_FORMAT, sysno);
319 struct code_read_data input;
324 input.itemsize = itemsize;
326 isamc_i.clientData = &input;
327 isamc_i.read_item = bt_code_read;
330 input.insert_flag = 2;
331 isamb_merge(p->isamb, &p->isam_p, &isamc_i);
335 zint pos = (sysno-1)*itemsize;
336 int off = CAST_ZINT_TO_INT(pos%RIDX_CHUNK);
337 int sz1 = RIDX_CHUNK - off; /* sz1 is size of buffer to read.. */
340 sz1 = itemsize; /* no more than itemsize bytes */
342 bf_write(p->index_BFile, 1+pos/RIDX_CHUNK, off, sz1, buf);
343 if (sz1 < itemsize) /* boundary? must write second part */
344 bf_write(p->index_BFile, 2+pos/RIDX_CHUNK, 0, itemsize - sz1,
353 * c-file-style: "Stroustrup"
354 * indent-tabs-mode: nil
356 * vim: shiftwidth=4 tabstop=8 expandtab