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