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