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