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