Multiple registers (alpha early)
[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.21  2002-04-04 14:14:13  adam
8  * Multiple registers (alpha early)
9  *
10  * Revision 1.20  2002/03/20 20:24:29  adam
11  * Hits per term. Returned in SearchResult-1
12  *
13  * Revision 1.19  2001/01/16 16:56:15  heikki
14  * Searching in my isam-d
15  *
16  * Revision 1.18  2000/05/18 12:01:36  adam
17  * System call times(2) used again. More 64-bit fixes.
18  *
19  * Revision 1.17  2000/03/15 15:00:30  adam
20  * First work on threaded version.
21  *
22  * Revision 1.16  1999/11/30 13:48:03  adam
23  * Improved installation. Updated for inclusion of YAZ header files.
24  *
25  * Revision 1.15  1999/07/20 13:59:18  adam
26  * Fixed bug that occurred when phrases had 0 hits.
27  *
28  * Revision 1.14  1999/05/26 07:49:13  adam
29  * C++ compilation.
30  *
31  * Revision 1.13  1999/05/12 13:08:06  adam
32  * First version of ISAMS.
33  *
34  * Revision 1.12  1999/02/02 14:51:10  adam
35  * Updated WIN32 code specific sections. Changed header.
36  *
37  * Revision 1.11  1998/03/25 13:48:02  adam
38  * Fixed bug in rset_trunc_r.
39  *
40  * Revision 1.10  1998/03/05 08:45:13  adam
41  * New result set model and modular ranking system. Moved towards
42  * descent server API. System information stored as "SGML" records.
43  *
44  * Revision 1.9  1998/01/12 15:04:09  adam
45  * The test option (-s) only uses read-lock (and not write lock).
46  *
47  * Revision 1.8  1997/10/31 12:34:27  adam
48  * Bug fix: memory leak.
49  *
50  * Revision 1.7  1997/09/29 09:07:29  adam
51  * Minor change.
52  *
53  * Revision 1.6  1997/09/22 12:39:06  adam
54  * Added get_pos method for the ranked result sets.
55  *
56  * Revision 1.5  1997/09/17 12:19:17  adam
57  * Zebra version corresponds to YAZ version 1.4.
58  * Changed Zebra server so that it doesn't depend on global common_resource.
59  *
60  * Revision 1.4  1996/12/23 15:30:44  adam
61  * Work on truncation.
62  * Bug fix: result sets weren't deleted after server shut down.
63  *
64  * Revision 1.3  1996/12/20 11:07:14  adam
65  * Multi-or result set.
66  *
67  * Revision 1.2  1996/11/08 11:10:28  adam
68  * Buffers used during file match got bigger.
69  * Compressed ISAM support everywhere.
70  * Bug fixes regarding masking characters in queries.
71  * Redesigned Regexp-2 queries.
72  *
73  * Revision 1.1  1996/11/04 14:07:40  adam
74  * Moved truncation code to trunc.c.
75  *
76  */
77 #include <stdio.h>
78 #include <assert.h>
79
80 #define NEW_TRUNC 1
81
82 #include "index.h"
83 #include <rstemp.h>
84 #include <rsnull.h>
85 #include <rsisams.h>
86 #if ZMBOL
87 #include <rsisam.h>
88 #include <rsisamc.h>
89 #include <rsisamd.h>
90 #if NEW_TRUNC
91 #include <rsm_or.h>
92 #endif
93 #endif
94
95 struct trunc_info {
96     int  *ptr;
97     int  *indx;
98     char **heap;
99     int  heapnum;
100     int  (*cmp)(const void *p1, const void *p2);
101     int  keysize;
102     char *swapbuf;
103     char *tmpbuf;
104     char *buf;
105 };
106
107 static void heap_swap (struct trunc_info *ti, int i1, int i2)
108 {
109     int swap;
110
111     swap = ti->ptr[i1];
112     ti->ptr[i1] = ti->ptr[i2];
113     ti->ptr[i2] = swap;
114 }
115
116 static void heap_delete (struct trunc_info *ti)
117 {
118     int cur = 1, child = 2;
119
120     heap_swap (ti, 1, ti->heapnum--);
121     while (child <= ti->heapnum) {
122         if (child < ti->heapnum &&
123             (*ti->cmp)(ti->heap[ti->ptr[child]],
124                        ti->heap[ti->ptr[1+child]]) > 0)
125             child++;
126         if ((*ti->cmp)(ti->heap[ti->ptr[cur]],
127                        ti->heap[ti->ptr[child]]) > 0)
128         {
129             heap_swap (ti, cur, child);
130             cur = child;
131             child = 2*cur;
132         }
133         else
134             break;
135     }
136 }
137
138 static void heap_insert (struct trunc_info *ti, const char *buf, int indx)
139 {
140     int cur, parent;
141
142     cur = ++(ti->heapnum);
143     memcpy (ti->heap[ti->ptr[cur]], buf, ti->keysize);
144     ti->indx[ti->ptr[cur]] = indx;
145     parent = cur/2;
146     while (parent && (*ti->cmp)(ti->heap[ti->ptr[parent]],
147                                 ti->heap[ti->ptr[cur]]) > 0)
148     {
149         heap_swap (ti, cur, parent);
150         cur = parent;
151         parent = cur/2;
152     }
153 }
154
155 static struct trunc_info *heap_init (int size, int key_size,
156                                      int (*cmp)(const void *p1,
157                                                 const void *p2))
158 {
159     struct trunc_info *ti = (struct trunc_info *) xmalloc (sizeof(*ti));
160     int i;
161
162     ++size;
163     ti->heapnum = 0;
164     ti->keysize = key_size;
165     ti->cmp = cmp;
166     ti->indx = (int *) xmalloc (size * sizeof(*ti->indx));
167     ti->heap = (char **) xmalloc (size * sizeof(*ti->heap));
168     ti->ptr = (int *) xmalloc (size * sizeof(*ti->ptr));
169     ti->swapbuf = (char *) xmalloc (ti->keysize);
170     ti->tmpbuf = (char *) xmalloc (ti->keysize);
171     ti->buf = (char *) xmalloc (size * ti->keysize);
172     for (i = size; --i >= 0; )
173     {
174         ti->ptr[i] = i;
175         ti->heap[i] = ti->buf + ti->keysize * i;
176     }
177     return ti;
178 }
179
180 static void heap_close (struct trunc_info *ti)
181 {
182     xfree (ti->ptr);
183     xfree (ti->indx);
184     xfree (ti->heap);
185     xfree (ti->swapbuf);
186     xfree (ti->tmpbuf);
187     xfree (ti->buf);
188     xfree (ti);
189 }
190
191 static RSET rset_trunc_r (ZebraHandle zi, const char *term, int length,
192                          const char *flags, ISAMS_P *isam_p, int from, int to,
193                          int merge_chunk)
194 {
195     RSET result; 
196     RSFD result_rsfd;
197     rset_temp_parms parms;
198
199     parms.cmp = key_compare_it;
200     parms.key_size = sizeof(struct it_key);
201     parms.temp_path = res_get (zi->res, "setTmpDir");
202     parms.rset_term = rset_term_create (term, length, flags);
203     result = rset_create (rset_kind_temp, &parms);
204     result_rsfd = rset_open (result, RSETF_WRITE);
205
206     if (to - from > merge_chunk)
207     {
208         RSFD *rsfd;
209         RSET *rset;
210         int term_index;
211         int i, i_add = (to-from)/merge_chunk + 1;
212         struct trunc_info *ti;
213         int rscur = 0;
214         int rsmax = (to-from)/i_add + 1;
215         
216         rset = (RSET *) xmalloc (sizeof(*rset) * rsmax);
217         rsfd = (RSFD *) xmalloc (sizeof(*rsfd) * rsmax);
218         
219         for (i = from; i < to; i += i_add)
220         {
221             if (i_add <= to - i)
222                 rset[rscur] = rset_trunc_r (zi, term, length, flags,
223                                             isam_p, i, i+i_add, merge_chunk);
224             else
225                 rset[rscur] = rset_trunc_r (zi, term, length, flags,
226                                             isam_p, i, to, merge_chunk);
227             rscur++;
228         }
229         ti = heap_init (rscur, sizeof(struct it_key), key_compare_it);
230         for (i = rscur; --i >= 0; )
231         {
232             rsfd[i] = rset_open (rset[i], RSETF_READ);
233             if (rset_read (rset[i], rsfd[i], ti->tmpbuf, &term_index))
234                 heap_insert (ti, ti->tmpbuf, i);
235             else
236             {
237                 rset_close (rset[i], rsfd[i]);
238                 rset_delete (rset[i]);
239             }
240         }
241         while (ti->heapnum)
242         {
243             int n = ti->indx[ti->ptr[1]];
244
245             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
246
247             while (1)
248             {
249                 if (!rset_read (rset[n], rsfd[n], ti->tmpbuf, &term_index))
250                 {
251                     heap_delete (ti);
252                     rset_close (rset[n], rsfd[n]);
253                     rset_delete (rset[n]);
254                     break;
255                 }
256                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
257                 {
258                     heap_delete (ti);
259                     heap_insert (ti, ti->tmpbuf, n);
260                     break;
261                 }
262             }
263         }
264         xfree (rset);
265         xfree (rsfd);
266         heap_close (ti);
267     }
268 #if ZMBOL
269     else if (zi->reg->isam)
270     {
271         ISPT *ispt;
272         int i;
273         struct trunc_info *ti;
274
275         ispt = (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] = is_position (zi->reg->isam, isam_p[from+i]);
282             if (is_readkey (ispt[i], ti->tmpbuf))
283                 heap_insert (ti, ti->tmpbuf, i);
284             else
285                 is_pt_free (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 1
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                 is_pt_free (ispt[n]);
299 #else
300 /* section that preserve all keys with unique sysnos */
301             while (1)
302             {
303                 if (!is_readkey (ispt[n], ti->tmpbuf))
304                 {
305                     heap_delete (ti);
306                     is_pt_free (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     else if (zi->reg->isamc)
322     {
323         ISAMC_PP *ispt;
324         int i;
325         struct trunc_info *ti;
326
327         ispt = (ISAMC_PP *) xmalloc (sizeof(*ispt) * (to-from));
328
329         ti = heap_init (to-from, sizeof(struct it_key),
330                         key_compare_it);
331         for (i = to-from; --i >= 0; )
332         {
333             ispt[i] = isc_pp_open (zi->reg->isamc, isam_p[from+i]);
334             if (isc_pp_read (ispt[i], ti->tmpbuf))
335                 heap_insert (ti, ti->tmpbuf, i);
336             else
337                 isc_pp_close (ispt[i]);
338         }
339         while (ti->heapnum)
340         {
341             int n = ti->indx[ti->ptr[1]];
342
343             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
344 #if 0
345 /* section that preserve all keys */
346             heap_delete (ti);
347             if (isc_pp_read (ispt[n], ti->tmpbuf))
348                 heap_insert (ti, ti->tmpbuf, n);
349             else
350                 isc_pp_close (ispt[n]);
351 #else
352 /* section that preserve all keys with unique sysnos */
353             while (1)
354             {
355                 if (!isc_pp_read (ispt[n], ti->tmpbuf))
356                 {
357                     heap_delete (ti);
358                     isc_pp_close (ispt[n]);
359                     break;
360                 }
361                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
362                 {
363                     heap_delete (ti);
364                     heap_insert (ti, ti->tmpbuf, n);
365                     break;
366                 }
367             }
368 #endif
369         }
370         heap_close (ti);
371         xfree (ispt);
372     }
373
374     else if (zi->reg->isamd)
375     {
376         ISAMD_PP *ispt;
377         int i;
378         struct trunc_info *ti;
379
380         ispt = (ISAMD_PP *) xmalloc (sizeof(*ispt) * (to-from));
381
382         ti = heap_init (to-from, sizeof(struct it_key),
383                         key_compare_it);
384         for (i = to-from; --i >= 0; )
385         {
386             ispt[i] = isamd_pp_open (zi->reg->isamd, isam_p[from+i]);
387             if (isamd_pp_read (ispt[i], ti->tmpbuf))
388                 heap_insert (ti, ti->tmpbuf, i);
389             else
390                 isamd_pp_close (ispt[i]);
391         }
392         while (ti->heapnum)
393         {
394             int n = ti->indx[ti->ptr[1]];
395
396             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
397 #if 0
398 /* section that preserve all keys */
399             heap_delete (ti);
400             if (isamd_pp_read (ispt[n], ti->tmpbuf))
401                 heap_insert (ti, ti->tmpbuf, n);
402             else
403                 isamd_pp_close (ispt[n]);
404 #else
405 /* section that preserve all keys with unique sysnos */
406             while (1)
407             {
408                 if (!isamd_pp_read (ispt[n], ti->tmpbuf))
409                 {
410                     heap_delete (ti);
411                     isamd_pp_close (ispt[n]);
412                     break;
413                 }
414                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
415                 {
416                     heap_delete (ti);
417                     heap_insert (ti, ti->tmpbuf, n);
418                     break;
419                 }
420             }
421 #endif
422         }
423         heap_close (ti);
424         xfree (ispt);
425     }
426
427 #endif
428     else if (zi->reg->isams)
429     {
430         ISAMS_PP *ispt;
431         int i;
432         struct trunc_info *ti;
433
434         ispt = (ISAMS_PP *) xmalloc (sizeof(*ispt) * (to-from));
435
436         ti = heap_init (to-from, sizeof(struct it_key),
437                         key_compare_it);
438         for (i = to-from; --i >= 0; )
439         {
440             ispt[i] = isams_pp_open (zi->reg->isams, isam_p[from+i]);
441             if (isams_pp_read (ispt[i], ti->tmpbuf))
442                 heap_insert (ti, ti->tmpbuf, i);
443             else
444                 isams_pp_close (ispt[i]);
445         }
446         while (ti->heapnum)
447         {
448             int n = ti->indx[ti->ptr[1]];
449
450             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
451             while (1)
452             {
453                 if (!isams_pp_read (ispt[n], ti->tmpbuf))
454                 {
455                     heap_delete (ti);
456                     isams_pp_close (ispt[n]);
457                     break;
458                 }
459                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
460                 {
461                     heap_delete (ti);
462                     heap_insert (ti, ti->tmpbuf, n);
463                     break;
464                 }
465             }
466         }
467         heap_close (ti);
468         xfree (ispt);
469     }
470     else
471         logf (LOG_WARN, "Unknown isam set in rset_trunc_r");
472
473     rset_close (result, result_rsfd);
474     return result;
475 }
476
477 static int isams_trunc_cmp (const void *p1, const void *p2)
478 {
479     ISAMS_P i1 = *(ISAMS_P*) p1;
480     ISAMS_P i2 = *(ISAMS_P*) p2;
481
482     return i1 - i2;
483 }
484
485 #if ZMBOL
486 static int isam_trunc_cmp (const void *p1, const void *p2)
487 {
488     ISAM_P i1 = *(ISAM_P*) p1;
489     ISAM_P i2 = *(ISAM_P*) p2;
490     int d;
491
492     d = is_type (i1) - is_type (i2);
493     if (d)
494         return d;
495     return is_block (i1) - is_block (i2);
496 }
497
498 static int isamc_trunc_cmp (const void *p1, const void *p2)
499 {
500     ISAMC_P i1 = *(ISAMC_P*) p1;
501     ISAMC_P i2 = *(ISAMC_P*) p2;
502     int d;
503
504     d = isc_type (i1) - isc_type (i2);
505     if (d)
506         return d;
507     return isc_block (i1) - isc_block (i2);
508 }
509 static int isamd_trunc_cmp (const void *p1, const void *p2)
510 {
511     ISAMD_P i1 = *(ISAMD_P*) p1;
512     ISAMD_P i2 = *(ISAMD_P*) p2;
513     int d;
514
515     d = isamd_type (i1) - isamd_type (i2);
516     if (d)
517         return d;
518     return isamd_block (i1) - isamd_block (i2);
519 }
520 #endif
521
522 RSET rset_trunc (ZebraHandle zi, ISAMS_P *isam_p, int no,
523                  const char *term, int length, const char *flags)
524 {
525     logf (LOG_DEBUG, "rset_trunc no=%d", no);
526     if (no < 1)
527     {
528         rset_null_parms parms;
529         parms.rset_term = rset_term_create (term, length, flags);
530         return rset_create (rset_kind_null, &parms);
531     }
532     if (zi->reg->isams)
533     {
534         if (no == 1)
535         {
536             rset_isams_parms parms;
537
538             parms.pos = *isam_p;
539             parms.is = zi->reg->isams;
540             parms.rset_term = rset_term_create (term, length, flags);
541             return rset_create (rset_kind_isams, &parms);
542         }
543         qsort (isam_p, no, sizeof(*isam_p), isams_trunc_cmp);
544     }
545 #if ZMBOL
546     else if (zi->reg->isam)
547     {
548         if (no == 1)
549         {
550             rset_isam_parms parms;
551
552             parms.pos = *isam_p;
553             parms.is = zi->reg->isam;
554             parms.rset_term = rset_term_create (term, length, flags);
555             return rset_create (rset_kind_isam, &parms);
556         }
557         qsort (isam_p, no, sizeof(*isam_p), isam_trunc_cmp);
558     }
559     else if (zi->reg->isamc)
560     {
561         if (no == 1)
562         {
563             rset_isamc_parms parms;
564
565             parms.key_size = sizeof(struct it_key);
566             parms.cmp = key_compare_it;
567             parms.pos = *isam_p;
568             parms.is = zi->reg->isamc;
569             parms.rset_term = rset_term_create (term, length, flags);
570             return rset_create (rset_kind_isamc, &parms);
571         }
572 #if NEW_TRUNC
573         else if (no < 10000)
574         {
575             rset_m_or_parms parms;
576
577             parms.key_size = sizeof(struct it_key);
578             parms.cmp = key_compare_it;
579             parms.isc = zi->reg->isamc;
580             parms.isam_positions = isam_p;
581             parms.no_isam_positions = no;
582             parms.no_save_positions = 100000;
583             parms.rset_term = rset_term_create (term, length, flags);
584             return rset_create (rset_kind_m_or, &parms);
585         }
586 #endif
587         qsort (isam_p, no, sizeof(*isam_p), isamc_trunc_cmp);
588     }
589     else if (zi->reg->isamd)
590     {
591         if (no == 1)
592         {
593             rset_isamd_parms parms;
594
595             parms.pos = *isam_p;
596             parms.is = zi->reg->isamd;
597             parms.rset_term = rset_term_create (term, length, flags);
598             return rset_create (rset_kind_isamd, &parms);
599         }
600 #if NEW_TRUNC_NOT_DONE_FOR_ISAM_D
601         else if (no < 10000)
602         {
603             rset_m_or_parms parms;
604
605             parms.key_size = sizeof(struct it_key);
606             parms.cmp = key_compare_it;
607             parms.isc = 0;
608             parms.isamd=zi->reg->isamd;
609             parms.isam_positions = isam_p;
610             parms.no_isam_positions = no;
611             parms.no_save_positions = 100000;
612             parms.rset_term = rset_term_create (term, length, flags);
613             return rset_create (rset_kind_m_or, &parms);
614         }
615 #endif
616         qsort (isam_p, no, sizeof(*isam_p), isamd_trunc_cmp);
617     }
618 #endif
619     else
620     {
621         logf (LOG_WARN, "Unknown isam set in rset_trunc");
622         return rset_create (rset_kind_null, NULL);
623     }
624     return rset_trunc_r (zi, term, length, flags, isam_p, 0, no, 100);
625 }
626