5232aa061d69b3528a436d416cc5c1a4ca170749
[idzebra-moved-to-github.git] / rset / rsm_or.c
1 /*
2  * Copyright (C) 1994-2002, Index Data
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Id: rsm_or.c,v 1.11 2002-03-20 20:24:30 adam Exp $
7  *
8  */
9
10
11 #include <assert.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <zebrautl.h>
17 #if ZMBOL
18 #include <isam.h>
19 #include <isamc.h>
20 #include <rsm_or.h>
21
22 static void *r_create(RSET ct, const struct rset_control *sel, void *parms);
23 static RSFD r_open (RSET ct, int flag);
24 static void r_close (RSFD rfd);
25 static void r_delete (RSET ct);
26 static void r_rewind (RSFD rfd);
27 static int r_count (RSET ct);
28 static int r_read (RSFD rfd, void *buf, int *term_index);
29 static int r_write (RSFD rfd, const void *buf);
30
31 static const struct rset_control control = 
32 {
33     "multi-or",
34     r_create,
35     r_open,
36     r_close,
37     r_delete,
38     r_rewind,
39     r_count,
40     r_read,
41     r_write,
42 };
43
44 const struct rset_control *rset_kind_m_or = &control;
45
46 struct rset_mor_info {
47     int     key_size;
48     int     no_rec;
49     int     (*cmp)(const void *p1, const void *p2);
50     ISAMC   isc;
51     ISAM_P  *isam_positions;
52
53     int     no_isam_positions;
54     int     no_save_positions;
55     struct rset_mor_rfd *rfd_list;
56 };
57
58 struct trunc_info {
59     int  *ptr;
60     int  *indx;
61     char **heap;
62     int  heapnum;
63     int  (*cmp)(const void *p1, const void *p2);
64     int  keysize;
65     char *swapbuf;
66     char *tmpbuf;
67     char *buf;
68 };
69
70 struct rset_mor_rfd {
71     int flag;
72     int position;
73     int position_max;
74     ISAMC_PP *ispt;
75     struct rset_mor_rfd *next;
76     struct rset_mor_info *info;
77     struct trunc_info *ti;
78     int  *countp;
79     char *pbuf;
80 };
81
82 static void heap_swap (struct trunc_info *ti, int i1, int i2)
83 {
84     int swap;
85
86     swap = ti->ptr[i1];
87     ti->ptr[i1] = ti->ptr[i2];
88     ti->ptr[i2] = swap;
89 }
90
91 static void heap_delete (struct trunc_info *ti)
92 {
93     int cur = 1, child = 2;
94
95     heap_swap (ti, 1, ti->heapnum--);
96     while (child <= ti->heapnum) {
97         if (child < ti->heapnum &&
98             (*ti->cmp)(ti->heap[ti->ptr[child]],
99                        ti->heap[ti->ptr[1+child]]) > 0)
100             child++;
101         if ((*ti->cmp)(ti->heap[ti->ptr[cur]],
102                        ti->heap[ti->ptr[child]]) > 0)
103         {
104             heap_swap (ti, cur, child);
105             cur = child;
106             child = 2*cur;
107         }
108         else
109             break;
110     }
111 }
112
113 static void heap_insert (struct trunc_info *ti, const char *buf, int indx)
114 {
115     int cur, parent;
116
117     cur = ++(ti->heapnum);
118     memcpy (ti->heap[ti->ptr[cur]], buf, ti->keysize);
119     ti->indx[ti->ptr[cur]] = indx;
120     parent = cur/2;
121     while (parent && (*ti->cmp)(ti->heap[ti->ptr[parent]],
122                                 ti->heap[ti->ptr[cur]]) > 0)
123     {
124         heap_swap (ti, cur, parent);
125         cur = parent;
126         parent = cur/2;
127     }
128 }
129
130 static
131 struct trunc_info *heap_init (int size, int key_size,
132                               int (*cmp)(const void *p1, const void *p2))
133 {
134     struct trunc_info *ti = (struct trunc_info *) xmalloc (sizeof(*ti));
135     int i;
136
137     ++size;
138     ti->heapnum = 0;
139     ti->keysize = key_size;
140     ti->cmp = cmp;
141     ti->indx = (int *) xmalloc (size * sizeof(*ti->indx));
142     ti->heap = (char **) xmalloc (size * sizeof(*ti->heap));
143     ti->ptr = (int *) xmalloc (size * sizeof(*ti->ptr));
144     ti->swapbuf = (char *) xmalloc (ti->keysize);
145     ti->tmpbuf = (char *) xmalloc (ti->keysize);
146     ti->buf = (char *) xmalloc (size * ti->keysize);
147     for (i = size; --i >= 0; )
148     {
149         ti->ptr[i] = i;
150         ti->heap[i] = ti->buf + ti->keysize * i;
151     }
152     return ti;
153 }
154
155 static void heap_close (struct trunc_info *ti)
156 {
157     xfree (ti->buf);
158     xfree (ti->ptr);
159     xfree (ti->indx);
160     xfree (ti->heap);
161     xfree (ti->swapbuf);
162     xfree (ti->tmpbuf);
163     xfree (ti);
164 }
165
166 static void *r_create (RSET ct, const struct rset_control *sel, void *parms)
167 {
168     rset_m_or_parms *r_parms = (rset_m_or_parms *) parms;
169     struct rset_mor_info *info;
170
171     ct->flags |= RSET_FLAG_VOLATILE;
172     info = (struct rset_mor_info *) xmalloc (sizeof(*info));
173     info->key_size = r_parms->key_size;
174     assert (info->key_size > 1);
175     info->cmp = r_parms->cmp;
176     
177     info->no_save_positions = r_parms->no_save_positions;
178
179     info->isc = r_parms->isc;
180     info->no_isam_positions = r_parms->no_isam_positions;
181     info->isam_positions = (ISAM_P *)
182         xmalloc (sizeof(*info->isam_positions) * info->no_isam_positions);
183     memcpy (info->isam_positions, r_parms->isam_positions,
184             sizeof(*info->isam_positions) * info->no_isam_positions);
185     info->rfd_list = NULL;
186
187     ct->no_rset_terms = 1;
188     ct->rset_terms = (RSET_TERM *) xmalloc (sizeof(*ct->rset_terms));
189     ct->rset_terms[0] = r_parms->rset_term;
190     return info;
191 }
192
193 static RSFD r_open (RSET ct, int flag)
194 {
195     struct rset_mor_rfd *rfd;
196     struct rset_mor_info *info = (struct rset_mor_info *) ct->buf;
197     int i;
198
199     if (flag & RSETF_WRITE)
200     {
201         logf (LOG_FATAL, "m_or set type is read-only");
202         return NULL;
203     }
204     rfd = (struct rset_mor_rfd *) xmalloc (sizeof(*rfd));
205     rfd->flag = flag;
206     rfd->next = info->rfd_list;
207     rfd->info = info;
208     info->rfd_list = rfd;
209
210     rfd->ispt = (ISAMC_PP *)
211         xmalloc (sizeof(*rfd->ispt) * info->no_isam_positions);
212         
213     rfd->ti = heap_init (info->no_isam_positions, info->key_size, info->cmp);
214
215     ct->rset_terms[0]->nn = 0;
216     for (i = 0; i<info->no_isam_positions; i++)
217     {
218         rfd->ispt[i] = isc_pp_open (info->isc, info->isam_positions[i]);
219         
220         ct->rset_terms[0]->nn += isc_pp_num (rfd->ispt[i]);
221
222         if (isc_pp_read (rfd->ispt[i], rfd->ti->tmpbuf))
223             heap_insert (rfd->ti, rfd->ti->tmpbuf, i);
224         else
225         {
226             isc_pp_close (rfd->ispt[i]);
227             rfd->ispt[i] = NULL;
228         }
229     }
230     rfd->position = info->no_save_positions;
231
232     if (ct->no_rset_terms == 1)
233         rfd->countp = &ct->rset_terms[0]->count;
234     else
235         rfd->countp = 0;
236     rfd->pbuf = xmalloc (info->key_size);
237
238     r_rewind (rfd);
239     return rfd;
240 }
241
242 static void r_close (RSFD rfd)
243 {
244     struct rset_mor_info *info = ((struct rset_mor_rfd*)rfd)->info;
245     struct rset_mor_rfd **rfdp;
246     int i;
247     
248     for (rfdp = &info->rfd_list; *rfdp; rfdp = &(*rfdp)->next)
249         if (*rfdp == rfd)
250         {
251             *rfdp = (*rfdp)->next;
252         
253             heap_close (((struct rset_mor_rfd *) rfd)->ti);
254             for (i = 0; i<info->no_isam_positions; i++)
255                 if (((struct rset_mor_rfd *) rfd)->ispt[i])
256                     isc_pp_close (((struct rset_mor_rfd *) rfd)->ispt[i]);
257             xfree (((struct rset_mor_rfd *)rfd)->ispt);
258             xfree (((struct rset_mor_rfd *)rfd)->pbuf);
259             xfree (rfd);
260             return;
261         }
262     logf (LOG_FATAL, "r_close but no rfd match!");
263     assert (0);
264 }
265
266 static void r_delete (RSET ct)
267 {
268     struct rset_mor_info *info = (struct rset_mor_info *) ct->buf;
269     int i;
270
271     assert (info->rfd_list == NULL);
272     xfree (info->isam_positions);
273
274     for (i = 0; i<ct->no_rset_terms; i++)
275         rset_term_destroy (ct->rset_terms[i]);
276     xfree (ct->rset_terms);
277
278     xfree (info);
279 }
280
281 static void r_rewind (RSFD rfd)
282 {
283 }
284
285 static int r_count (RSET ct)
286 {
287     return 0;
288 }
289
290 static int r_read (RSFD rfd, void *buf, int *term_index)
291 {
292     struct rset_mor_rfd *mrfd = (struct rset_mor_rfd *) rfd;
293     struct trunc_info *ti = mrfd->ti;
294     int n = ti->indx[ti->ptr[1]];
295
296     if (!ti->heapnum)
297         return 0;
298     *term_index = 0;
299     memcpy (buf, ti->heap[ti->ptr[1]], ti->keysize);
300     if (((struct rset_mor_rfd *) rfd)->position)
301     {
302         if (isc_pp_read (((struct rset_mor_rfd *) rfd)->ispt[n], ti->tmpbuf))
303         {
304             heap_delete (ti);
305             if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
306                  ((struct rset_mor_rfd *) rfd)->position--;
307             heap_insert (ti, ti->tmpbuf, n);
308         }
309         else
310             heap_delete (ti);
311         if (mrfd->countp && (
312                 *mrfd->countp == 0 || (*ti->cmp)(buf, mrfd->pbuf) > 1))
313         {
314             memcpy (mrfd->pbuf, buf, ti->keysize);
315             (*mrfd->countp)++;
316         }
317         return 1;
318     }
319     while (1)
320     {
321         if (!isc_pp_read (((struct rset_mor_rfd *) rfd)->ispt[n], ti->tmpbuf))
322         {
323             heap_delete (ti);
324             break;
325         }
326         if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
327         {
328             heap_delete (ti);
329             heap_insert (ti, ti->tmpbuf, n);
330             break;
331         }
332     }
333     if (mrfd->countp && (
334             *mrfd->countp == 0 || (*ti->cmp)(buf, mrfd->pbuf) > 1))
335     {
336         memcpy (mrfd->pbuf, buf, ti->keysize);
337         (*mrfd->countp)++;
338     }
339     return 1;
340 }
341
342 static int r_write (RSFD rfd, const void *buf)
343 {
344     logf (LOG_FATAL, "mor set type is read-only");
345     return -1;
346 }
347 #endif