Fix a bug where second-half of block in leaf split could become
[idzebra-moved-to-github.git] / isamb / tstisamb.c
1 /* $Id: tstisamb.c,v 1.18 2005-03-18 12:05:11 adam Exp $
2    Copyright (C) 1995-2005
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 Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <yaz/log.h>
26 #include <yaz/xmalloc.h>
27 #include <idzebra/isamb.h>
28 #include <assert.h>
29
30 static void log_item(int level, const void *b, const char *txt)
31 {
32     int x;
33     memcpy(&x, b, sizeof(int));
34     yaz_log(YLOG_DEBUG, "%s %d", txt, x);
35 }
36
37 static void log_pr(const char *txt)
38 {
39     yaz_log(YLOG_DEBUG, "%s", txt);
40 }
41
42 int compare_item(const void *a, const void *b)
43 {
44     int ia, ib;
45
46     memcpy(&ia, a, sizeof(int));
47     memcpy(&ib, b, sizeof(int));
48     if (ia > ib)
49         return 1;
50     if (ia < ib)
51         return -1;
52    return 0;
53 }
54
55 void *code_start()
56 {
57     return 0;
58 }
59
60 void code_item(void *p, char **dst, const char **src)
61 {
62     memcpy (*dst, *src, sizeof(int));
63     (*dst) += sizeof(int);
64     (*src) += sizeof(int);
65 }
66
67 void code_reset(void *p)
68 {
69 }
70 void code_stop(void *p)
71 {
72 }
73
74 struct read_info {
75     int no;
76     int step;
77     int max;
78     int insertMode;
79 };
80
81 int code_read(void *vp, char **dst, int *insertMode)
82 {
83     struct read_info *ri = (struct read_info *)vp;
84     int x;
85
86     if (ri->no >= ri->max)
87         return 0;
88     x = ri->no;
89     memcpy (*dst, &x, sizeof(int));
90     (*dst)+=sizeof(int);
91
92     ri->no = ri->no + ri->step;
93     *insertMode = ri->insertMode;
94     return 1;
95 }
96
97 void tst_insert(ISAMB isb, int n)
98 {
99     ISAMC_I isamc_i;
100     ISAMC_P isamc_p;
101     struct read_info ri;
102     ISAMB_PP pp;
103     char key_buf[10];
104     int nerrs = 0;
105
106     /* insert a number of entries */
107     ri.no = 0;
108     ri.step = 1;
109     ri.max = n;
110     ri.insertMode = 1;
111
112     isamc_i.clientData = &ri;
113     isamc_i.read_item = code_read;
114     
115     isamc_p = isamb_merge (isb, 0 /* new list */ , &isamc_i);
116
117     /* read the entries */
118     pp = isamb_pp_open (isb, isamc_p, 1);
119
120     ri.no = 0;
121     while(isamb_pp_read (pp, key_buf))
122     {
123         int x;
124         memcpy (&x, key_buf, sizeof(int));
125         if (x != ri.no)
126         {
127             yaz_log(YLOG_WARN, "isamb_pp_read. n=%d Got %d (expected %d)",
128                     n, x, ri.no);
129             nerrs++;
130         }
131         else if (nerrs)
132             yaz_log(YLOG_LOG, "isamb_pp_read. n=%d Got %d",
133                     n, x);
134
135         ri.no++;
136     }
137     if (ri.no != ri.max)
138     {
139         yaz_log(YLOG_WARN, "ri.max != ri.max (%d != %d)", ri.no, ri.max);
140         nerrs++;
141     }
142     isamb_dump(isb, isamc_p, log_pr);
143     isamb_pp_close(pp);
144
145     if (nerrs)
146         exit(3);
147     /* delete a number of entries (even ones) */
148     ri.no = 0;
149     ri.step = 2;
150     ri.max = n;
151     ri.insertMode = 0;
152
153     isamc_i.clientData = &ri;
154     isamc_i.read_item = code_read;
155     
156     isamc_p = isamb_merge (isb, isamc_p , &isamc_i);
157
158     /* delete a number of entries (odd ones) */
159     ri.no = 1;
160     ri.step = 2;
161     ri.max = n;
162     ri.insertMode = 0;
163
164     isamc_i.clientData = &ri;
165     isamc_i.read_item = code_read;
166     
167     isamc_p = isamb_merge (isb, isamc_p , &isamc_i);
168
169     if (isamc_p)
170     {
171         yaz_log(YLOG_WARN, "isamb_merge did not return empty list");
172         exit(3);
173     }
174 }
175
176 void tst_forward(ISAMB isb, int n)
177 {
178     ISAMC_I isamc_i;
179     ISAMC_P isamc_p;
180     struct read_info ri;
181     int i;
182     ISAMB_PP pp;
183
184     /* insert a number of entries */
185     ri.no = 0;
186     ri.step = 1;
187     ri.max = n;
188     ri.insertMode = 1;
189
190     isamc_i.clientData = &ri;
191     isamc_i.read_item = code_read;
192     
193     isamc_p = isamb_merge (isb, 0 /* new list */ , &isamc_i);
194
195     /* read the entries */
196     pp = isamb_pp_open (isb, isamc_p, 1);
197     
198     for (i = 0; i<ri.max; i +=2 )
199     {
200         int x = -1;
201         int xu = i;
202         isamb_pp_forward(pp, &x, &xu);
203         if (x != xu && xu != x+1)
204         {
205             yaz_log(YLOG_WARN, "isamb_pp_forward (1). Got %d (expected %d)",
206                     x, xu);
207             exit(4);
208         }
209         ri.no++;
210     }
211     isamb_pp_close(pp);
212     
213     pp = isamb_pp_open (isb, isamc_p, 1);
214     for (i = 0; i<ri.max; i += 100)
215     {
216         int x = -1;
217         int xu = i;
218         isamb_pp_forward(pp, &x, &xu);
219         if (x != xu && xu != x+1)
220         {
221             yaz_log(YLOG_WARN, "isamb_pp_forward (2). Got %d (expected %d)",
222                     x, xu);
223             exit(4);
224         }
225         ri.no++;
226     }
227     isamb_pp_close(pp);
228
229     isamb_unlink(isb, isamc_p);
230 }
231
232 void tst_append(ISAMB isb, int n)
233 {
234     ISAMC_I isamc_i;
235     ISAMB_P isamb_p = 0;
236     struct read_info ri;
237     int i;
238     int chunk = 10;
239
240     for (i = 0; i < n; i += chunk)
241     {
242         /* insert a number of entries */
243         ri.no = 0;
244         ri.step = 1;
245         ri.max = i + chunk;
246         ri.insertMode = 1;
247         
248         isamc_i.clientData = &ri;
249         isamc_i.read_item = code_read;
250         
251         isamb_p = isamb_merge (isb, isamb_p , &isamc_i);
252     }
253 }
254
255 int main(int argc, char **argv)
256 {
257     BFiles bfs;
258     ISAMB isb;
259     ISAMC_M method;
260     
261     if (argc == 2)
262         yaz_log_init_level(YLOG_ALL);
263         
264     /* setup method (attributes) */
265     method.compare_item = compare_item;
266     method.log_item = log_item;
267     method.codec.start = code_start;
268     method.codec.encode = code_item;
269     method.codec.decode = code_item;
270     method.codec.reset = code_reset;
271     method.codec.stop = code_stop;
272
273     /* create block system */
274     bfs = bfs_create(0, 0);
275     if (!bfs)
276     {
277         yaz_log(YLOG_WARN, "bfs_create failed");
278         exit(1);
279     }
280
281     bf_reset(bfs);
282
283     /* create isam handle */
284     isb = isamb_open (bfs, "isamb", 1, &method, 0);
285     if (!isb)
286     {
287         yaz_log(YLOG_WARN, "isamb_open failed");
288         exit(2);
289     }
290     tst_insert(isb, 1);
291     tst_insert(isb, 2);
292     tst_insert(isb, 20);
293     tst_insert(isb, 100);
294     tst_insert(isb, 500);
295     tst_insert(isb, 10000);
296
297     tst_forward(isb, 10000);
298
299     tst_append(isb, 10000);
300     /* close isam handle */
301     isamb_close(isb);
302
303     /* exit block system */
304     bfs_destroy(bfs);
305     exit(0);
306     return 0;
307 }