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