Minor change.
[idzebra-moved-to-github.git] / index / trunc.c
1 /*
2  * Copyright (C) 1994-1997, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: trunc.c,v $
7  * Revision 1.7  1997-09-29 09:07:29  adam
8  * Minor change.
9  *
10  * Revision 1.6  1997/09/22 12:39:06  adam
11  * Added get_pos method for the ranked result sets.
12  *
13  * Revision 1.5  1997/09/17 12:19:17  adam
14  * Zebra version corresponds to YAZ version 1.4.
15  * Changed Zebra server so that it doesn't depend on global common_resource.
16  *
17  * Revision 1.4  1996/12/23 15:30:44  adam
18  * Work on truncation.
19  * Bug fix: result sets weren't deleted after server shut down.
20  *
21  * Revision 1.3  1996/12/20 11:07:14  adam
22  * Multi-or result set.
23  *
24  * Revision 1.2  1996/11/08 11:10:28  adam
25  * Buffers used during file match got bigger.
26  * Compressed ISAM support everywhere.
27  * Bug fixes regarding masking characters in queries.
28  * Redesigned Regexp-2 queries.
29  *
30  * Revision 1.1  1996/11/04 14:07:40  adam
31  * Moved truncation code to trunc.c.
32  *
33  */
34 #include <stdio.h>
35 #include <assert.h>
36
37 #include "zserver.h"
38 #include <rstemp.h>
39 #include <rsisam.h>
40 #include <rsisamc.h>
41 #include <rsnull.h>
42
43 #define NEW_TRUNC 1
44
45 #if NEW_TRUNC
46 #include <rsm_or.h>
47 #endif
48
49 struct trunc_info {
50     int  *ptr;
51     int  *indx;
52     char **heap;
53     int  heapnum;
54     int  (*cmp)(const void *p1, const void *p2);
55     int  keysize;
56     char *swapbuf;
57     char *tmpbuf;
58     char *buf;
59 };
60
61 static void heap_swap (struct trunc_info *ti, int i1, int i2)
62 {
63     int swap;
64
65     swap = ti->ptr[i1];
66     ti->ptr[i1] = ti->ptr[i2];
67     ti->ptr[i2] = swap;
68 }
69
70 static void heap_delete (struct trunc_info *ti)
71 {
72     int cur = 1, child = 2;
73
74     heap_swap (ti, 1, ti->heapnum--);
75     while (child <= ti->heapnum) {
76         if (child < ti->heapnum &&
77             (*ti->cmp)(ti->heap[ti->ptr[child]],
78                        ti->heap[ti->ptr[1+child]]) > 0)
79             child++;
80         if ((*ti->cmp)(ti->heap[ti->ptr[cur]],
81                        ti->heap[ti->ptr[child]]) > 0)
82         {
83             heap_swap (ti, cur, child);
84             cur = child;
85             child = 2*cur;
86         }
87         else
88             break;
89     }
90 }
91
92 static void heap_insert (struct trunc_info *ti, const char *buf, int indx)
93 {
94     int cur, parent;
95
96     cur = ++(ti->heapnum);
97     memcpy (ti->heap[ti->ptr[cur]], buf, ti->keysize);
98     ti->indx[ti->ptr[cur]] = indx;
99     parent = cur/2;
100     while (parent && (*ti->cmp)(ti->heap[ti->ptr[parent]],
101                                 ti->heap[ti->ptr[cur]]) > 0)
102     {
103         heap_swap (ti, cur, parent);
104         cur = parent;
105         parent = cur/2;
106     }
107 }
108
109 static struct trunc_info *heap_init (int size, int key_size,
110                                      int (*cmp)(const void *p1,
111                                                 const void *p2))
112 {
113     struct trunc_info *ti = xmalloc (sizeof(*ti));
114     int i;
115
116     ++size;
117     ti->heapnum = 0;
118     ti->keysize = key_size;
119     ti->cmp = cmp;
120     ti->indx = xmalloc (size * sizeof(*ti->indx));
121     ti->heap = xmalloc (size * sizeof(*ti->heap));
122     ti->ptr = xmalloc (size * sizeof(*ti->ptr));
123     ti->swapbuf = xmalloc (ti->keysize);
124     ti->tmpbuf = xmalloc (ti->keysize);
125     ti->buf = xmalloc (size * ti->keysize);
126     for (i = size; --i >= 0; )
127     {
128         ti->ptr[i] = i;
129         ti->heap[i] = ti->buf + ti->keysize * i;
130     }
131     return ti;
132 }
133
134 static void heap_close (struct trunc_info *ti)
135 {
136     xfree (ti->ptr);
137     xfree (ti->indx);
138     xfree (ti->heap);
139     xfree (ti->swapbuf);
140     xfree (ti->tmpbuf);
141     xfree (ti);
142 }
143
144 static RSET rset_trunc_r (ZServerInfo *zi, ISAM_P *isam_p, int from, int to,
145                          int merge_chunk)
146 {
147     RSET result; 
148     RSFD result_rsfd;
149     rset_temp_parms parms;
150
151     parms.key_size = sizeof(struct it_key);
152     parms.temp_path = res_get (zi->res, "setTmpDir");
153     result = rset_create (rset_kind_temp, &parms);
154     result_rsfd = rset_open (result, RSETF_WRITE|RSETF_SORT_SYSNO);
155
156     if (to - from > merge_chunk)
157     {
158         RSFD *rsfd;
159         RSET *rset;
160         int i, i_add = (to-from)/merge_chunk + 1;
161         struct trunc_info *ti;
162         int rscur = 0;
163         int rsmax = (to-from)/i_add + 1;
164         
165         rset = xmalloc (sizeof(*rset) * rsmax);
166         rsfd = xmalloc (sizeof(*rsfd) * rsmax);
167         
168         for (i = from; i < to; i += i_add)
169         {
170             if (i_add <= to - i)
171                 rset[rscur] = rset_trunc_r (zi, isam_p, i, i+i_add,
172                                             merge_chunk);
173             else
174                 rset[rscur] = rset_trunc_r (zi, isam_p, i, to,
175                                             merge_chunk);
176             rscur++;
177         }
178         ti = heap_init (rscur, sizeof(struct it_key), key_compare_it);
179         for (i = rscur; --i >= 0; )
180         {
181             rsfd[i] = rset_open (rset[i], RSETF_READ|RSETF_SORT_SYSNO);
182             if (rset_read (rset[i], rsfd[i], ti->tmpbuf))
183                 heap_insert (ti, ti->tmpbuf, i);
184             else
185             {
186                 rset_close (rset[i], rsfd[i]);
187                 rset_delete (rset[i]);
188             }
189         }
190         while (ti->heapnum)
191         {
192             int n = ti->indx[ti->ptr[1]];
193
194             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
195
196             while (1)
197             {
198                 if (!rset_read (rset[n], rsfd[n], ti->tmpbuf))
199                 {
200                     heap_delete (ti);
201                     rset_close (rset[n], rsfd[n]);
202                     rset_delete (rset[n]);
203                     break;
204                 }
205                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
206                 {
207                     heap_delete (ti);
208                     heap_insert (ti, ti->tmpbuf, n);
209                     break;
210                 }
211             }
212         }
213         xfree (rset);
214         xfree (rsfd);
215         heap_close (ti);
216     }
217     else if (zi->isam)
218     {
219         ISPT *ispt;
220         int i;
221         struct trunc_info *ti;
222
223         ispt = xmalloc (sizeof(*ispt) * (to-from));
224
225         ti = heap_init (to-from, sizeof(struct it_key),
226                         key_compare_it);
227         for (i = to-from; --i >= 0; )
228         {
229             ispt[i] = is_position (zi->isam, isam_p[from+i]);
230             if (is_readkey (ispt[i], ti->tmpbuf))
231                 heap_insert (ti, ti->tmpbuf, i);
232             else
233                 is_pt_free (ispt[i]);
234         }
235         while (ti->heapnum)
236         {
237             int n = ti->indx[ti->ptr[1]];
238
239             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
240 #if 1
241 /* section that preserve all keys */
242             heap_delete (ti);
243             if (is_readkey (ispt[n], ti->tmpbuf))
244                 heap_insert (ti, ti->tmpbuf, n);
245             else
246                 is_pt_free (ispt[n]);
247 #else
248 /* section that preserve all keys with unique sysnos */
249             while (1)
250             {
251                 if (!is_readkey (ispt[n], ti->tmpbuf))
252                 {
253                     heap_delete (ti);
254                     is_pt_free (ispt[n]);
255                     break;
256                 }
257                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
258                 {
259                     heap_delete (ti);
260                     heap_insert (ti, ti->tmpbuf, n);
261                     break;
262                 }
263             }
264 #endif
265         }
266         heap_close (ti);
267         xfree (ispt);
268     }
269     else
270     {
271         ISAMC_PP *ispt;
272         int i;
273         struct trunc_info *ti;
274
275         ispt = xmalloc (sizeof(*ispt) * (to-from));
276
277         ti = heap_init (to-from, sizeof(struct it_key),
278                         key_compare_it);
279         for (i = to-from; --i >= 0; )
280         {
281             ispt[i] = isc_pp_open (zi->isamc, isam_p[from+i]);
282             if (isc_pp_read (ispt[i], ti->tmpbuf))
283                 heap_insert (ti, ti->tmpbuf, i);
284             else
285                 isc_pp_close (ispt[i]);
286         }
287         while (ti->heapnum)
288         {
289             int n = ti->indx[ti->ptr[1]];
290
291             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
292 #if 0
293 /* section that preserve all keys */
294             heap_delete (ti);
295             if (is_readkey (ispt[n], ti->tmpbuf))
296                 heap_insert (ti, ti->tmpbuf, n);
297             else
298                 isc_pp_close (ispt[n]);
299 #else
300 /* section that preserve all keys with unique sysnos */
301             while (1)
302             {
303                 if (!isc_pp_read (ispt[n], ti->tmpbuf))
304                 {
305                     heap_delete (ti);
306                     isc_pp_close (ispt[n]);
307                     break;
308                 }
309                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
310                 {
311                     heap_delete (ti);
312                     heap_insert (ti, ti->tmpbuf, n);
313                     break;
314                 }
315             }
316 #endif
317         }
318         heap_close (ti);
319         xfree (ispt);
320     }
321     rset_close (result, result_rsfd);
322     return result;
323 }
324
325 static int isam_trunc_cmp (const void *p1, const void *p2)
326 {
327     ISAM_P i1 = *(ISAM_P*) p1;
328     ISAM_P i2 = *(ISAM_P*) p2;
329     int d;
330
331     d = is_type (i1) - is_type (i2);
332     if (d)
333         return d;
334     return is_block (i1) - is_block (i2);
335 }
336
337 static int isamc_trunc_cmp (const void *p1, const void *p2)
338 {
339     ISAMC_P i1 = *(ISAMC_P*) p1;
340     ISAMC_P i2 = *(ISAMC_P*) p2;
341     int d;
342
343     d = isc_type (i1) - isc_type (i2);
344     if (d)
345         return d;
346     return isc_block (i1) - isc_block (i2);
347 }
348
349 RSET rset_trunc (ZServerInfo *zi, ISAM_P *isam_p, int no)
350 {
351     logf (LOG_DEBUG, "rset_trunc no=%d", no);
352     if (zi->isam)
353     {
354         if (no < 1)
355             return rset_create (rset_kind_null, NULL);
356         else if (no == 1)
357         {
358             rset_isam_parms parms;
359
360             parms.pos = *isam_p;
361             parms.is = zi->isam;
362             return rset_create (rset_kind_isam, &parms);
363         }
364         qsort (isam_p, no, sizeof(*isam_p), isam_trunc_cmp);
365     }
366     else if (zi->isamc)
367     {
368         if (no < 1)
369             return rset_create (rset_kind_null, NULL);
370         else if (no == 1)
371         {
372             rset_isamc_parms parms;
373
374             parms.pos = *isam_p;
375             parms.is = zi->isamc;
376             return rset_create (rset_kind_isamc, &parms);
377         }
378 #if NEW_TRUNC
379         else if (no < 200)
380         {
381             rset_m_or_parms parms;
382
383             logf (LOG_LOG, "new_trunc");
384             parms.key_size = sizeof(struct it_key);
385             parms.cmp = key_compare_it;
386             parms.isc = zi->isamc;
387             parms.isam_positions = isam_p;
388             parms.no_isam_positions = no;
389             parms.no_save_positions = 100;
390             return rset_create (rset_kind_m_or, &parms);
391         }
392 #endif
393         qsort (isam_p, no, sizeof(*isam_p), isamc_trunc_cmp);
394     }
395     else
396         logf (LOG_FATAL, "Neither isam nor isamc set in rset_trunc");
397     return rset_trunc_r (zi, isam_p, 0, no, 100);
398 }
399