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