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
27 #include <yaz/xmalloc.h>
28 #include <idzebra/isams.h>
35 typedef unsigned ISAMS_BLOCK_SIZE;
53 void *decodeClientData;
58 void isams_getmethod (ISAMS_M *m)
60 m->codec.start = NULL;
61 m->codec.decode = NULL;
62 m->codec.encode = NULL;
64 m->codec.reset = NULL;
66 m->compare_item = NULL;
73 ISAMS isams_open (BFiles bfs, const char *name, int writeflag,
76 ISAMS is = (ISAMS) xmalloc (sizeof(*is));
78 is->method = (ISAMS_M *) xmalloc (sizeof(*is->method));
79 memcpy (is->method, method, sizeof(*method));
80 is->block_size = is->method->block_size;
81 is->debug = is->method->debug;
83 is->bf = bf_open (bfs, name, is->block_size, writeflag);
85 if (!bf_read (is->bf, 0, 0, sizeof(ISAMS_head), &is->head))
87 is->head.last_block = 1;
88 is->head.last_offset = 0;
90 memcpy (&is->head_old, &is->head, sizeof(is->head));
91 is->merge_buf = (char *) xmalloc(2*is->block_size);
92 memset(is->merge_buf, 0, 2*is->block_size);
96 int isams_close (ISAMS is)
98 if (memcmp(&is->head, &is->head_old, sizeof(is->head)))
100 if (is->head.last_offset)
101 bf_write(is->bf, is->head.last_block, 0, is->head.last_offset,
103 bf_write (is->bf, 0, 0, sizeof(is->head), &is->head);
106 xfree (is->merge_buf);
112 ISAM_P isams_merge (ISAMS is, ISAMS_I data)
117 int first_block = is->head.last_block;
118 int first_offset = is->head.last_offset;
121 r_clientData = (*is->method->codec.start)();
123 is->head.last_offset += sizeof(int);
124 if (is->head.last_offset > is->block_size)
127 yaz_log (YLOG_LOG, "first_block=%d", first_block);
128 bf_write(is->bf, is->head.last_block, 0, 0, is->merge_buf);
129 (is->head.last_block)++;
130 is->head.last_offset -= is->block_size;
131 memcpy (is->merge_buf, is->merge_buf + is->block_size,
132 is->head.last_offset);
136 char *tmp_ptr = i_item;
137 i_more = (*data->read_item)(data->clientData, &tmp_ptr, &i_mode);
144 char *r_out_ptr = is->merge_buf + is->head.last_offset;
146 const char *i_item_ptr = i_item;
147 (*is->method->codec.encode)(r_clientData, &r_out_ptr, &i_item_ptr);
148 is->head.last_offset = r_out_ptr - is->merge_buf;
149 if (is->head.last_offset > is->block_size)
151 bf_write(is->bf, is->head.last_block, 0, 0, is->merge_buf);
152 (is->head.last_block)++;
153 is->head.last_offset -= is->block_size;
154 memcpy (is->merge_buf, is->merge_buf + is->block_size,
155 is->head.last_offset);
160 (*is->method->codec.stop)(r_clientData);
161 if (first_block == is->head.last_block)
162 memcpy(is->merge_buf + first_offset, &count, sizeof(int));
163 else if (first_block == is->head.last_block-1)
165 int gap = first_offset + sizeof(int) - is->block_size;
166 assert (gap <= (int) sizeof(int));
169 if (gap < (int) sizeof(int))
170 bf_write(is->bf, first_block, first_offset, sizeof(int)-gap,
172 memcpy (is->merge_buf, ((char*)&count)+(sizeof(int)-gap), gap);
175 bf_write(is->bf, first_block, first_offset, sizeof(int), &count);
179 bf_write(is->bf, first_block, first_offset, sizeof(int), &count);
181 return first_block * is->block_size + first_offset;
184 ISAMS_PP isams_pp_open (ISAMS is, ISAM_P pos)
186 ISAMS_PP pp = (ISAMS_PP) xmalloc (sizeof(*pp));
189 yaz_log (YLOG_LOG, "isams: isams_pp_open pos=%ld", (long) pos);
191 pp->decodeClientData = (*is->method->codec.start)();
194 pp->buf = (char *) xmalloc(is->block_size*2);
195 pp->block_no = (int) (pos/is->block_size);
196 pp->block_offset = (int) (pos - pp->block_no * is->block_size);
198 yaz_log (YLOG_LOG, "isams: isams_pp_open off=%d no=%d",
199 pp->block_offset, pp->block_no);
202 bf_read (is->bf, pp->block_no, 0, 0, pp->buf);
203 bf_read (is->bf, pp->block_no+1, 0, 0, pp->buf + is->block_size);
204 memcpy(&pp->numKeys, pp->buf + pp->block_offset, sizeof(int));
206 yaz_log (YLOG_LOG, "isams: isams_pp_open numKeys=%d", pp->numKeys);
207 pp->block_offset += sizeof(int);
212 void isams_pp_close (ISAMS_PP pp)
214 (*pp->is->method->codec.stop)(pp->decodeClientData);
219 int isams_pp_num (ISAMS_PP pp)
224 int isams_pp_read (ISAMS_PP pp, void *buf)
227 return isams_read_item (pp, &cp);
230 int isams_read_item (ISAMS_PP pp, char **dst)
233 if (pp->numRead >= pp->numKeys)
236 if (pp->block_offset > pp->is->block_size)
238 pp->block_offset -= pp->is->block_size;
240 memcpy (pp->buf, pp->buf + pp->is->block_size, pp->is->block_size);
241 bf_read (pp->is->bf, pp->block_no+1, 0, 0,
242 pp->buf + pp->is->block_size);
244 src = pp->buf + pp->block_offset;
245 (*pp->is->method->codec.decode)(pp->decodeClientData, dst, &src);
246 pp->block_offset = src - pp->buf;
254 * c-file-style: "Stroustrup"
255 * indent-tabs-mode: nil
257 * vim: shiftwidth=4 tabstop=8 expandtab