Updated code to use new YAZ log functions/defines.
[idzebra-moved-to-github.git] / isams / isams.c
1 /* $Id: isams.c,v 1.5.2.3 2006-12-05 21:14:43 adam Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21 */
22
23
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include <yaz/xmalloc.h>
30 #include <yaz/log.h>
31 #include <isams.h>
32
33 typedef struct {
34     int last_offset;
35     int last_block;
36 } ISAMS_head;
37
38 typedef unsigned ISAMS_BLOCK_SIZE;
39
40 struct ISAMS_s {
41     ISAMS_M *method;
42     ISAMS_head head;
43     ISAMS_head head_old;
44     char *merge_buf;
45
46     int block_size;
47     int debug;
48     BFile bf;
49 }; 
50
51 struct ISAMS_PP_s {
52     ISAMS is;
53     char *buf;
54     int block_offset;
55     int block_no;
56     void *decodeClientData;
57     int numKeys;
58     int numRead;
59 };
60
61 void isams_getmethod (ISAMS_M *m)
62 {
63     m->code_start = NULL;
64     m->code_item = NULL;
65     m->code_stop = NULL;
66
67     m->compare_item = NULL;
68     m->log_item = NULL;
69
70     m->debug = 1;
71     m->block_size = 128;
72 }
73
74 ISAMS isams_open (BFiles bfs, const char *name, int writeflag,
75                   ISAMS_M *method)
76 {
77     ISAMS is = (ISAMS) xmalloc (sizeof(*is));
78
79     is->method = (ISAMS_M *) xmalloc (sizeof(*is->method));
80     memcpy (is->method, method, sizeof(*method));
81     is->block_size = is->method->block_size;
82     is->debug = is->method->debug;
83
84     is->bf = bf_open (bfs, name, is->block_size, writeflag);
85
86     if (!bf_read (is->bf, 0, 0, sizeof(ISAMS_head), &is->head))
87     {
88         is->head.last_block = 1;
89         is->head.last_offset = 0;
90     }
91     memcpy (&is->head_old, &is->head, sizeof(is->head));
92     is->merge_buf = (char *) xmalloc(2*is->block_size);
93     memset(is->merge_buf, 0, 2*is->block_size);
94     return is;
95 }
96
97 int isams_close (ISAMS is)
98 {
99     if (memcmp(&is->head, &is->head_old, sizeof(is->head)))
100     {
101         if (is->head.last_offset)
102             bf_write(is->bf, is->head.last_block, 0, is->head.last_offset,
103                      is->merge_buf);
104         bf_write (is->bf, 0, 0, sizeof(is->head), &is->head);
105     }
106     bf_close (is->bf);
107     xfree (is->merge_buf);
108     xfree (is->method);
109     xfree (is);
110     return 0;
111 }
112
113 ISAMS_P isams_merge (ISAMS is, ISAMS_I data)
114 {
115     char i_item[128], *i_item_ptr;
116     int i_more, i_mode;
117     void *r_clientData;
118     int first_block = is->head.last_block;
119     int first_offset = is->head.last_offset;
120     int count = 0;
121
122     r_clientData = (*is->method->code_start)(ISAMC_ENCODE);
123
124     is->head.last_offset += sizeof(int);
125     if (is->head.last_offset > is->block_size)
126     {
127         if (is->debug > 2)
128             yaz_log(YLOG_LOG, "first_block=%d", first_block);
129         bf_write(is->bf, is->head.last_block, 0, 0, is->merge_buf);
130         (is->head.last_block)++;
131         is->head.last_offset -= is->block_size;
132         memcpy (is->merge_buf, is->merge_buf + is->block_size,
133                 is->head.last_offset);
134     }
135     while (1)
136     {
137         i_item_ptr = i_item;
138         i_more = (*data->read_item)(data->clientData, &i_item_ptr, &i_mode);
139         assert (i_mode);
140         
141         if (!i_more)
142             break;
143         else
144         {
145             char *r_out_ptr = is->merge_buf + is->head.last_offset;
146             
147             i_item_ptr = i_item;
148             (*is->method->code_item)(ISAMC_ENCODE, r_clientData,
149                                      &r_out_ptr, &i_item_ptr);
150             is->head.last_offset = r_out_ptr - is->merge_buf;
151             if (is->head.last_offset > is->block_size)
152             {
153                 bf_write(is->bf, is->head.last_block, 0, 0, is->merge_buf);
154                 (is->head.last_block)++;
155                 is->head.last_offset -= is->block_size;
156                 memcpy (is->merge_buf, is->merge_buf + is->block_size,
157                         is->head.last_offset);
158             }
159             count++;
160         }
161     }
162     (*is->method->code_stop)(ISAMC_ENCODE, r_clientData);
163     if (first_block == is->head.last_block)
164         memcpy(is->merge_buf + first_offset, &count, sizeof(int));
165     else if (first_block == is->head.last_block-1)
166     {
167         int gap = first_offset + sizeof(int) - is->block_size;
168         assert (gap <= (int) sizeof(int));
169         if (gap > 0)
170         {
171             if (gap < (int) sizeof(int))
172                 bf_write(is->bf, first_block, first_offset, sizeof(int)-gap,
173                          &count);
174             memcpy (is->merge_buf, ((char*)&count)+(sizeof(int)-gap), gap);
175         }
176         else
177             bf_write(is->bf, first_block, first_offset, sizeof(int), &count);
178     }
179     else
180     {
181         bf_write(is->bf, first_block, first_offset, sizeof(int), &count);
182     }
183     return first_block * is->block_size + first_offset;
184 }
185
186 ISAMS_PP isams_pp_open (ISAMS is, ISAMS_P pos)
187 {
188     ISAMS_PP pp = (ISAMS_PP) xmalloc (sizeof(*pp));
189
190     if (is->debug > 1)
191         yaz_log(YLOG_LOG, "isams: isams_pp_open pos=%ld", (long) pos);
192     pp->is = is;
193     pp->decodeClientData = (*is->method->code_start)(ISAMC_DECODE);
194     pp->numKeys = 0;
195     pp->numRead = 0;
196     pp->buf = (char *) xmalloc(is->block_size*2);
197     pp->block_no = pos/is->block_size;
198     pp->block_offset = pos - pp->block_no * is->block_size;
199     if (is->debug)
200         yaz_log(YLOG_LOG, "isams: isams_pp_open off=%d no=%d",
201               pp->block_offset, pp->block_no);
202     if (pos)
203     {
204         bf_read (is->bf, pp->block_no, 0, 0, pp->buf);
205         bf_read (is->bf, pp->block_no+1, 0, 0, pp->buf + is->block_size);
206         memcpy(&pp->numKeys, pp->buf + pp->block_offset, sizeof(int));
207         if (is->debug)
208             yaz_log(YLOG_LOG, "isams: isams_pp_open numKeys=%d", pp->numKeys);
209         pp->block_offset += sizeof(int);
210     }
211     return pp;
212 }
213
214 void isams_pp_close (ISAMS_PP pp)
215 {
216     (*pp->is->method->code_stop)(ISAMC_DECODE, pp->decodeClientData);
217     xfree(pp->buf);
218     xfree(pp);
219 }
220
221 int isams_pp_num (ISAMS_PP pp)
222 {
223     return pp->numKeys;
224 }
225
226 int isams_pp_read (ISAMS_PP pp, void *buf)
227 {
228     char *buf_cp = buf;
229     return isams_read_item (pp, &buf_cp);
230 }
231
232 int isams_read_item (ISAMS_PP pp, char **dst)
233 {
234     char *src;
235     if (pp->numRead >= pp->numKeys)
236         return 0;
237     (pp->numRead)++;
238     if (pp->block_offset > pp->is->block_size)
239     {
240         pp->block_offset -= pp->is->block_size;
241         (pp->block_no)++;
242         memcpy (pp->buf, pp->buf + pp->is->block_size, pp->is->block_size);
243         bf_read (pp->is->bf, pp->block_no+1, 0, 0,
244                  pp->buf + pp->is->block_size);
245     }
246     src = pp->buf + pp->block_offset;
247     (*pp->is->method->code_item)(ISAMC_DECODE, pp->decodeClientData,
248                                  dst, &src);
249     pp->block_offset = src - pp->buf; 
250     return 1;
251 }
252
253