Using a bit more of those nmems in rsets
[idzebra-moved-to-github.git] / index / trunc.c
1 /* $Id: trunc.c,v 1.38 2004-08-24 15:00:16 heikki Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24 #include <stdio.h>
25 #include <assert.h>
26
27 #define NEW_TRUNC 1
28
29 #include "index.h"
30 #include <rstemp.h>
31 #include <rsnull.h>
32 #include <rsisams.h>
33 #include <rsisamc.h>
34 #include <rsisamb.h>
35 #if NEW_TRUNC
36 #include <rsm_or.h>
37 #endif
38 #include <rsmultior.h>
39
40 struct trunc_info {
41     int  *ptr;
42     int  *indx;
43     char **heap;
44     int  heapnum;
45     int  (*cmp)(const void *p1, const void *p2);
46     int  keysize;
47     char *swapbuf;
48     char *tmpbuf;
49     char *buf;
50 };
51
52 static void heap_swap (struct trunc_info *ti, int i1, int i2)
53 {
54     int swap;
55
56     swap = ti->ptr[i1];
57     ti->ptr[i1] = ti->ptr[i2];
58     ti->ptr[i2] = swap;
59 }
60
61 static void heap_delete (struct trunc_info *ti)
62 {
63     int cur = 1, child = 2;
64
65     heap_swap (ti, 1, ti->heapnum--);
66     while (child <= ti->heapnum) {
67         if (child < ti->heapnum &&
68             (*ti->cmp)(ti->heap[ti->ptr[child]],
69                        ti->heap[ti->ptr[1+child]]) > 0)
70             child++;
71         if ((*ti->cmp)(ti->heap[ti->ptr[cur]],
72                        ti->heap[ti->ptr[child]]) > 0)
73         {
74             heap_swap (ti, cur, child);
75             cur = child;
76             child = 2*cur;
77         }
78         else
79             break;
80     }
81 }
82
83 static void heap_insert (struct trunc_info *ti, const char *buf, int indx)
84 {
85     int cur, parent;
86
87     cur = ++(ti->heapnum);
88     memcpy (ti->heap[ti->ptr[cur]], buf, ti->keysize);
89     ti->indx[ti->ptr[cur]] = indx;
90     parent = cur/2;
91     while (parent && (*ti->cmp)(ti->heap[ti->ptr[parent]],
92                                 ti->heap[ti->ptr[cur]]) > 0)
93     {
94         heap_swap (ti, cur, parent);
95         cur = parent;
96         parent = cur/2;
97     }
98 }
99
100 static struct trunc_info *heap_init (int size, int key_size,
101                                      int (*cmp)(const void *p1,
102                                                 const void *p2))
103 {
104     struct trunc_info *ti = (struct trunc_info *) xmalloc (sizeof(*ti));
105     int i;
106
107     ++size;
108     ti->heapnum = 0;
109     ti->keysize = key_size;
110     ti->cmp = cmp;
111     ti->indx = (int *) xmalloc (size * sizeof(*ti->indx));
112     ti->heap = (char **) xmalloc (size * sizeof(*ti->heap));
113     ti->ptr = (int *) xmalloc (size * sizeof(*ti->ptr));
114     ti->swapbuf = (char *) xmalloc (ti->keysize);
115     ti->tmpbuf = (char *) xmalloc (ti->keysize);
116     ti->buf = (char *) xmalloc (size * ti->keysize);
117     for (i = size; --i >= 0; )
118     {
119         ti->ptr[i] = i;
120         ti->heap[i] = ti->buf + ti->keysize * i;
121     }
122     return ti;
123 }
124
125 static void heap_close (struct trunc_info *ti)
126 {
127     xfree (ti->ptr);
128     xfree (ti->indx);
129     xfree (ti->heap);
130     xfree (ti->swapbuf);
131     xfree (ti->tmpbuf);
132     xfree (ti->buf);
133     xfree (ti);
134 }
135
136 static RSET rset_trunc_r (ZebraHandle zi, const char *term, int length,
137                           const char *flags, ISAMS_P *isam_p, int from, int to,
138                           int merge_chunk, int preserve_position,
139                           int term_type)
140 {
141     RSET result; 
142     RSFD result_rsfd;
143     int nn = 0;
144
145     /*
146     rset_temp_parms parms;
147     parms.cmp = key_compare_it;
148     parms.key_size = sizeof(struct it_key);
149     parms.temp_path = res_get (zi->res, "setTmpDir");
150     result = rset_create (rset_kind_temp, &parms);
151     */
152     result=rstemp_create(NULL, /* FIXME - use a proper nmem */
153             sizeof(struct it_key), key_compare_it, 
154             res_get (zi->res, "setTmpDir"));
155     result_rsfd = rset_open (result, RSETF_WRITE);
156
157     if (to - from > merge_chunk)
158     {
159         RSFD *rsfd;
160         RSET *rset;
161         int i, i_add = (to-from)/merge_chunk + 1;
162         struct trunc_info *ti;
163         int rscur = 0;
164         int rsmax = (to-from)/i_add + 1;
165         
166         rset = (RSET *) xmalloc (sizeof(*rset) * rsmax);
167         rsfd = (RSFD *) xmalloc (sizeof(*rsfd) * rsmax);
168         
169         for (i = from; i < to; i += i_add)
170         {
171             if (i_add <= to - i)
172                 rset[rscur] = rset_trunc_r (zi, term, length, flags,
173                                             isam_p, i, i+i_add,
174                                             merge_chunk, preserve_position,
175                                             term_type);
176             else
177                 rset[rscur] = rset_trunc_r (zi, term, length, flags,
178                                             isam_p, i, to,
179                                             merge_chunk, preserve_position,
180                                             term_type);
181             rscur++;
182         }
183         ti = heap_init (rscur, sizeof(struct it_key), key_compare_it);
184         for (i = rscur; --i >= 0; )
185         {
186             rsfd[i] = rset_open (rset[i], RSETF_READ);
187             if (rset_read (rset[i], rsfd[i], ti->tmpbuf))
188                 heap_insert (ti, ti->tmpbuf, i);
189             else
190             {
191                 rset_close (rset[i], rsfd[i]);
192                 rset_delete (rset[i]);
193             }
194         }
195         while (ti->heapnum)
196         {
197             int n = ti->indx[ti->ptr[1]];
198
199             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
200             nn++;
201
202             while (1)
203             {
204                 if (!rset_read (rset[n], rsfd[n], ti->tmpbuf))
205                 {
206                     heap_delete (ti);
207                     rset_close (rset[n], rsfd[n]);
208                     rset_delete (rset[n]);
209                     break;
210                 }
211                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
212                 {
213                     heap_delete (ti);
214                     heap_insert (ti, ti->tmpbuf, n);
215                     break;
216                 }
217             }
218         }
219         xfree (rset);
220         xfree (rsfd);
221         heap_close (ti);
222     }
223     else if (zi->reg->isamc)
224     {
225         ISAMC_PP *ispt;
226         int i;
227         struct trunc_info *ti;
228
229         ispt = (ISAMC_PP *) xmalloc (sizeof(*ispt) * (to-from));
230
231         ti = heap_init (to-from, sizeof(struct it_key),
232                         key_compare_it);
233         for (i = to-from; --i >= 0; )
234         {
235             ispt[i] = isc_pp_open (zi->reg->isamc, isam_p[from+i]);
236             if (isc_pp_read (ispt[i], ti->tmpbuf))
237                 heap_insert (ti, ti->tmpbuf, i);
238             else
239                 isc_pp_close (ispt[i]);
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             nn++;
247             if (preserve_position)
248             {
249                 heap_delete (ti);
250                 if (isc_pp_read (ispt[n], ti->tmpbuf))
251                     heap_insert (ti, ti->tmpbuf, n);
252                 else
253                     isc_pp_close (ispt[n]);
254             }
255             else
256             {
257                 while (1)
258                 {
259                     if (!isc_pp_read (ispt[n], ti->tmpbuf))
260                     {
261                         heap_delete (ti);
262                         isc_pp_close (ispt[n]);
263                         break;
264                     }
265                     if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
266                     {
267                         heap_delete (ti);
268                         heap_insert (ti, ti->tmpbuf, n);
269                         break;
270                     }
271                 }
272             }
273         }
274         heap_close (ti);
275         xfree (ispt);
276     }
277     else if (zi->reg->isams)
278     {
279         ISAMS_PP *ispt;
280         int i;
281         struct trunc_info *ti;
282         int nn = 0;
283
284         ispt = (ISAMS_PP *) xmalloc (sizeof(*ispt) * (to-from));
285
286         ti = heap_init (to-from, sizeof(struct it_key),
287                         key_compare_it);
288         for (i = to-from; --i >= 0; )
289         {
290             ispt[i] = isams_pp_open (zi->reg->isams, isam_p[from+i]);
291             if (isams_pp_read (ispt[i], ti->tmpbuf))
292                 heap_insert (ti, ti->tmpbuf, i);
293             else
294                 isams_pp_close (ispt[i]);
295         }
296         while (ti->heapnum)
297         {
298             int n = ti->indx[ti->ptr[1]];
299
300             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
301             nn++;
302             while (1)
303             {
304                 if (!isams_pp_read (ispt[n], ti->tmpbuf))
305                 {
306                     heap_delete (ti);
307                     isams_pp_close (ispt[n]);
308                     break;
309                 }
310                 if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
311                 {
312                     heap_delete (ti);
313                     heap_insert (ti, ti->tmpbuf, n);
314                     break;
315                 }
316             }
317         }
318         heap_close (ti);
319         xfree (ispt);
320     }
321     else if (zi->reg->isamb)
322     {
323         ISAMB_PP *ispt;
324         int i;
325         struct trunc_info *ti;
326
327         ispt = (ISAMB_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             if (isam_p[from+i]) {
334                 ispt[i] = isamb_pp_open (zi->reg->isamb, isam_p[from+i]);
335                 if (isamb_pp_read (ispt[i], ti->tmpbuf))
336                     heap_insert (ti, ti->tmpbuf, i);
337                 else
338                     isamb_pp_close (ispt[i]);
339             }
340         }
341         while (ti->heapnum)
342         {
343             int n = ti->indx[ti->ptr[1]];
344
345             rset_write (result, result_rsfd, ti->heap[ti->ptr[1]]);
346             nn++;
347
348             if (preserve_position)
349             {
350                 heap_delete (ti);
351                 if (isamb_pp_read (ispt[n], ti->tmpbuf))
352                     heap_insert (ti, ti->tmpbuf, n);
353                 else
354                     isamb_pp_close (ispt[n]);
355             }
356             else
357             {
358                 while (1)
359                 {
360                     if (!isamb_pp_read (ispt[n], ti->tmpbuf))
361                     {
362                         heap_delete (ti);
363                         isamb_pp_close (ispt[n]);
364                         break;
365                     }
366                     if ((*ti->cmp)(ti->tmpbuf, ti->heap[ti->ptr[1]]) > 1)
367                     {
368                         heap_delete (ti);
369                         heap_insert (ti, ti->tmpbuf, n);
370                         break;
371                     }
372                 }
373             }
374         }
375         heap_close (ti);
376         xfree (ispt);
377     }
378     else
379         logf (LOG_WARN, "Unknown isam set in rset_trunc_r");
380
381     rset_close (result, result_rsfd);
382     return result;
383 }
384
385 static int isams_trunc_cmp (const void *p1, const void *p2)
386 {
387     ISAMS_P i1 = *(ISAMS_P*) p1;
388     ISAMS_P i2 = *(ISAMS_P*) p2;
389
390     if (i1 > i2)
391         return 1;
392     else if (i1 < i2)
393         return -1;
394     return 0;
395 }
396
397 static int isamc_trunc_cmp (const void *p1, const void *p2)
398 {
399     ISAMC_P i1 = *(ISAMC_P*) p1;
400     ISAMC_P i2 = *(ISAMC_P*) p2;
401     zint d;
402
403     d = (isc_type (i1) - isc_type (i2));
404     if (d == 0)
405         d = isc_block (i1) - isc_block (i2);
406     if (d > 0)
407         return 1;
408     else if (d < 0)
409         return -1;
410     return 0;
411 }
412
413 RSET rset_trunc (ZebraHandle zi, ISAMS_P *isam_p, int no,
414                  const char *term, int length, const char *flags,
415                  int preserve_position, int term_type)
416 {
417     logf (LOG_DEBUG, "rset_trunc no=%d", no);
418     if (no < 1)
419         return rsnull_create (NULL); /* FIXME - use a proper nmem */
420     if (zi->reg->isams)
421     {
422         if (no == 1)
423             return rsisams_create(NULL, /* FIXME - use some nmem */
424                     sizeof(struct it_key), key_compare_it,
425                     zi->reg->isams, *isam_p);
426         /*
427         {
428             rset_isams_parms parms;
429
430             parms.pos = *isam_p;
431             parms.is = zi->reg->isams;
432             return rset_create (rset_kind_isams, &parms);
433         }
434         */
435         qsort (isam_p, no, sizeof(*isam_p), isams_trunc_cmp);
436     }
437     else if (zi->reg->isamc)
438     {
439         if (no == 1)
440             return rsisamc_create(NULL, /* FIXME - use some nmem */
441                     sizeof(struct it_key), key_compare_it,
442                     zi->reg->isamc, *isam_p);
443         /*
444         {
445             rset_isamc_parms parms;
446
447             parms.key_size = sizeof(struct it_key);
448             parms.cmp = key_compare_it;
449             parms.pos = *isam_p;
450             parms.is = zi->reg->isamc;
451             return rset_create (rset_kind_isamc, &parms);
452         }
453         */
454
455 #if 0 /* NEW_TRUNC */ /* FIXME - Use the new multi_or instead !! */
456         else if (no < 10000)
457         {
458             rset_m_or_parms parms;
459
460             parms.key_size = sizeof(struct it_key);
461             parms.cmp = key_compare_it;
462             parms.isc = zi->reg->isamc;
463             parms.isam_positions = isam_p;
464             parms.no_isam_positions = no;
465             parms.no_save_positions = 100000;
466             return rset_create (rset_kind_m_or, &parms);
467         }
468 #endif
469         qsort (isam_p, no, sizeof(*isam_p), isamc_trunc_cmp);
470     }
471     else if (zi->reg->isamb)
472     {
473         if (no == 1)
474             return rsisamb_create(NULL, /* FIXME - use some nmem */
475                     sizeof(struct it_key), key_compare_it,
476                     zi->reg->isamb, *isam_p);
477         /*
478         {
479             rset_isamb_parms parms;
480             parms.key_size = sizeof(struct it_key);
481             parms.cmp = key_compare_it;
482             parms.pos = *isam_p;
483             parms.is = zi->reg->isamb;
484             return rset_create (rset_kind_isamb, &parms);
485         }
486         */
487 #if 1
488         else if (no <10000 ) /* FIXME - hardcoded number */
489         {
490             RSET r;
491             RSET *rsets=xmalloc(no*sizeof(RSET)); /* use nmem! */
492             int i;
493             for (i=0;i<no;i++)
494                 rsets[i]=rsisamb_create(NULL, /* */
495                     sizeof(struct it_key), key_compare_it,
496                     zi->reg->isamb, isam_p[i] );
497             r=rsmultior_create( NULL, /* FIXME - use some nmem */
498                       sizeof(struct it_key), key_compare_it, 
499                       no, rsets);
500             xfree(rsets);
501             return r;
502             /*
503             rset_multior_parms m_parms;
504             rset_isamb_parms b_parms;
505             int i;
506             m_parms.key_size = sizeof(struct it_key);
507             m_parms.cmp = key_compare_it;
508             m_parms.no_rsets=no;
509             m_parms.rsets=xmalloc(sizeof(*m_parms.rsets)*no);
510             b_parms.key_size = sizeof(struct it_key);
511             b_parms.cmp = key_compare_it;
512             b_parms.is = zi->reg->isamb;
513             for (i=0;i<no;i++)
514             {
515                 b_parms.pos = isam_p[i];
516                 m_parms.rsets[i]=rset_create (rset_kind_isamb, &b_parms);
517             }
518             return rset_create (rset_kind_multior, &m_parms);
519             */
520         } /* <10000 - rs_multior */
521 #endif        
522         qsort (isam_p, no, sizeof(*isam_p), isamc_trunc_cmp);
523     }
524     else
525     {
526         logf (LOG_WARN, "Unknown isam set in rset_trunc");
527         return rsnull_create (NULL); /* FIXME - nmem */
528     }
529     return rset_trunc_r (zi, term, length, flags, isam_p, 0, no, 100,
530                          preserve_position, term_type);
531 }
532