574f782375e8e26c9564cfa5bd89ef8573a9d388
[idzebra-moved-to-github.git] / rset / rsbool.c
1 /* $Id: rsbool.c,v 1.46 2004-09-01 15:01:32 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 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27
28 #include <zebrautl.h>
29 #include <rset.h>
30
31 #ifndef RSET_DEBUG
32 #define RSET_DEBUG 0
33 #endif
34
35 static RSFD r_open (RSET ct, int flag);
36 static void r_close (RSFD rfd);
37 static void r_delete (RSET ct);
38 static void r_rewind (RSFD rfd);
39 static int r_forward(RSFD rfd, void *buf, const void *untilbuf);
40 static void r_pos (RSFD rfd, double *current, double *total); 
41 static int r_read_and (RSFD rfd, void *buf);
42 static int r_read_or (RSFD rfd, void *buf);
43 static int r_read_not (RSFD rfd, void *buf);
44 static int r_write (RSFD rfd, const void *buf);
45
46 static const struct rset_control control_and = 
47 {
48     "and",
49     r_delete,
50     r_open,
51     r_close,
52     r_rewind,
53     r_forward, 
54     r_pos,    
55     r_read_and,
56     r_write,
57 };
58
59 static const struct rset_control control_or = 
60 {
61     "or",
62     r_delete,
63     r_open,
64     r_close,
65     r_rewind,
66     r_forward, 
67     r_pos,
68     r_read_or,
69     r_write,
70 };
71
72 static const struct rset_control control_not = 
73 {
74     "not",
75     r_delete,
76     r_open,
77     r_close,
78     r_rewind,
79     r_forward, 
80     r_pos,
81     r_read_not,
82     r_write,
83 };
84
85
86 const struct rset_control *rset_kind_and = &control_and;
87 const struct rset_control *rset_kind_or  = &control_or;
88 const struct rset_control *rset_kind_not = &control_not;
89
90 struct rset_bool_info {
91     RSET rset_l;
92     RSET rset_r;
93 };
94
95 struct rset_bool_rfd {
96     zint hits;
97     RSFD rfd_l;
98     RSFD rfd_r;
99     int  more_l;
100     int  more_r;
101     void *buf_l;
102     void *buf_r;
103     int tail;
104 };    
105
106 static RSET rsbool_create_base( const struct rset_control *ctrl,
107             NMEM nmem, const struct key_control *kcontrol,
108             RSET rset_l, RSET rset_r)
109 {
110     RSET rnew=rset_create_base(ctrl, nmem, kcontrol);
111     struct rset_bool_info *info;
112     info = (struct rset_bool_info *) nmem_malloc(rnew->nmem,sizeof(*info));
113     info->rset_l = rset_l;
114     info->rset_r = rset_r;
115     rnew->priv=info;
116     return rnew;
117 }
118
119
120 RSET rsbool_create_and( NMEM nmem, const struct key_control *kcontrol,
121                         RSET rset_l, RSET rset_r)
122 {
123     return rsbool_create_base(rset_kind_and, nmem, kcontrol,
124                               rset_l, rset_r);
125 }
126
127 RSET rsbool_create_or( NMEM nmem, const struct key_control *kcontrol,
128                        RSET rset_l, RSET rset_r)
129 {
130     return rsbool_create_base(rset_kind_or, nmem, kcontrol,
131                               rset_l, rset_r);
132 }
133
134 RSET rsbool_create_not( NMEM nmem, const struct key_control *kcontrol,
135                         RSET rset_l, RSET rset_r)
136 {
137     return rsbool_create_base(rset_kind_not, nmem, kcontrol,
138                               rset_l, rset_r);
139 }
140
141 static void r_delete (RSET ct)
142 {
143     struct rset_bool_info *info = (struct rset_bool_info *) ct->priv;
144     rset_delete (info->rset_l);
145     rset_delete (info->rset_r);
146 }
147
148
149 static RSFD r_open (RSET ct, int flag)
150 {
151     struct rset_bool_info *info = (struct rset_bool_info *) ct->priv;
152     RSFD rfd;
153     struct rset_bool_rfd *p;
154    
155
156     if (flag & RSETF_WRITE)
157     {
158         logf (LOG_FATAL, "bool set type is read-only");
159         return NULL;
160     }
161     rfd = rfd_create_base(ct);
162     if (rfd->priv)
163         p=(struct rset_bool_rfd *)rfd->priv;
164     else {
165         p=nmem_malloc(ct->nmem,sizeof(*p));
166         rfd->priv=p;
167         p->buf_l = nmem_malloc(ct->nmem, ct->keycontrol->key_size);
168         p->buf_r = nmem_malloc(ct->nmem, ct->keycontrol->key_size);
169     }
170
171     logf(LOG_DEBUG,"rsbool (%s) open [%p]", ct->control->desc, rfd);
172     p->hits=0;
173
174     p->rfd_l = rset_open (info->rset_l, RSETF_READ);
175     p->rfd_r = rset_open (info->rset_r, RSETF_READ);
176     p->more_l = rset_read (p->rfd_l, p->buf_l);
177     p->more_r = rset_read (p->rfd_r, p->buf_r);
178     p->tail = 0;
179     return rfd;
180 }
181
182 static void r_close (RSFD rfd)
183 {
184  /* struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv); */
185     struct rset_bool_rfd *prfd=(struct rset_bool_rfd *)rfd->priv;
186
187     rset_close (prfd->rfd_l);
188     rset_close (prfd->rfd_r);
189     rfd_delete_base(rfd);
190 }
191
192
193 static void r_rewind (RSFD rfd)
194 {
195  /* struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv); */
196     struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
197
198     logf (LOG_DEBUG, "rsbool_rewind");
199     rset_rewind (p->rfd_l);
200     rset_rewind (p->rfd_r);
201     p->more_l = rset_read (p->rfd_l, p->buf_l);
202     p->more_r = rset_read (p->rfd_r, p->buf_r);
203     p->hits=0;
204 }
205
206 static int r_forward (RSFD rfd, void *buf,
207                      const void *untilbuf)
208 {
209     struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
210     const struct key_control *kctrl=rfd->rset->keycontrol;
211
212     if ( p->more_l && ((kctrl->cmp)(untilbuf,p->buf_l)==2) )
213         p->more_l = rset_forward(p->rfd_l, p->buf_l, untilbuf);
214     if ( p->more_r && ((kctrl->cmp)(untilbuf,p->buf_r)==2))
215         p->more_r = rset_forward(p->rfd_r, p->buf_r, untilbuf);
216     p->tail=0; 
217     return rset_read(rfd,buf); 
218 }
219
220
221 /*
222     1,1         1,3
223     1,9         2,1
224     1,11        3,1
225     2,9
226
227   1,1     1,1
228   1,3     1,3
229           1,9
230           1,11
231   2,1     2,1
232           2,9
233           3,1
234 */
235
236 static int r_read_and (RSFD rfd, void *buf)
237 {
238     struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
239     const struct key_control *kctrl=rfd->rset->keycontrol;
240
241     while (p->more_l || p->more_r)
242     {
243         int cmp;
244
245         if (p->more_l && p->more_r)
246             cmp = (*kctrl->cmp)(p->buf_l, p->buf_r);
247         else if (p->more_l)
248             cmp = -2;
249         else
250             cmp = 2;
251 #if RSET_DEBUG
252         logf (LOG_DEBUG, "r_read_and [%p] looping: m=%d/%d c=%d t=%d",
253                         rfd, p->more_l, p->more_r, cmp, p->tail);
254         (*kctrl->log_item)(LOG_DEBUG, p->buf_l, "left ");
255         (*kctrl->log_item)(LOG_DEBUG, p->buf_r, "right ");
256 #endif
257         if (!cmp)
258         {
259             memcpy (buf, p->buf_l, kctrl->key_size);
260             p->more_l = rset_read (p->rfd_l, p->buf_l);
261             p->tail = 1;
262         }
263         else if (cmp == 1)
264         {
265             memcpy (buf, p->buf_r, kctrl->key_size);
266             p->more_r = rset_read (p->rfd_r, p->buf_r);
267             p->tail = 1;
268 #if RSET_DEBUG
269             logf (LOG_DEBUG, "r_read_and [%p] returning R m=%d/%d c=%d",
270                     rfd, p->more_l, p->more_r, cmp);
271             key_logdump(LOG_DEBUG,buf);
272             (*kctrl->log_item)(LOG_DEBUG, buf, "");
273 #endif
274             p->hits++;
275             return 1;
276         }
277         else if (cmp == -1)
278         {
279             memcpy (buf, p->buf_l, kctrl->key_size);
280             p->more_l = rset_read (p->rfd_l, p->buf_l);
281             p->tail = 1;
282 #if RSET_DEBUG
283             logf (LOG_DEBUG, "r_read_and [%p] returning L m=%d/%d c=%d",
284                     rfd, p->more_l, p->more_r, cmp);
285             (*kctrl->log_item)(LOG_DEBUG, buf, "");
286 #endif
287             p->hits++;
288             return 1;
289         }
290         else if (cmp > 1)  /* cmp == 2 */
291         {
292             if (p->tail)
293             {
294                 memcpy (buf, p->buf_r, kctrl->key_size);
295                 p->more_r = rset_read (p->rfd_r, p->buf_r);
296                 if (!p->more_r || (*kctrl->cmp)(p->buf_r, buf) > 1)
297                     p->tail = 0;
298 #if RSET_DEBUG
299                 logf (LOG_DEBUG, "r_read_and [%p] returning R tail m=%d/%d c=%d",
300                         rfd, p->more_l, p->more_r, cmp);
301                 (*kctrl->log_item)(LOG_DEBUG, buf, "");
302 #endif
303                 p->hits++;
304                 return 1;
305             }
306             else
307             {
308 #if RSET_DEBUG
309                 logf (LOG_DEBUG, "r_read_and [%p] about to forward R "
310                                  "m=%d/%d c=%d",
311                         rfd, p->more_l, p->more_r, cmp);
312 #endif
313                 if (p->more_r && p->more_l)
314                     p->more_r = rset_forward( p->rfd_r, p->buf_r, p->buf_l);
315                 else 
316                     return 0; /* no point in reading further */
317             }
318         }
319         else  /* cmp == -2 */
320         {
321             if (p->tail)
322             {
323                 memcpy (buf, p->buf_l, kctrl->key_size);
324                 p->more_l = rset_read (p->rfd_l, p->buf_l);
325                 if (!p->more_l || (*kctrl->cmp)(p->buf_l, buf) > 1)
326                     p->tail = 0;
327 #if RSET_DEBUG
328                 logf (LOG_DEBUG, "r_read_and [%p] returning L tail m=%d/%d c=%d",
329                         rfd, p->more_l, p->more_r, cmp);
330                 (*kctrl->log_item)(LOG_DEBUG, buf, "");
331 #endif
332                 p->hits++;
333                 return 1;
334             }
335             else
336             {
337 #if RSET_DEBUG
338                 logf (LOG_DEBUG, "r_read_and [%p] about to forward L "
339                                  "m=%d/%d c=%d",
340                         rfd, p->more_l, p->more_r, cmp);
341 #endif
342                 if (p->more_r && p->more_l)
343                     p->more_l = rset_forward(p->rfd_l, p->buf_l, p->buf_r);
344                 else 
345                     return 0; /* no point in reading further */
346             }
347         }
348     }
349 #if RSET_DEBUG
350     logf (LOG_DEBUG, "r_read_and [%p] reached its end",rfd);
351 #endif
352     return 0;
353 }
354
355 static int r_read_or (RSFD rfd, void *buf)
356 {
357     struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
358     const struct key_control *kctrl=rfd->rset->keycontrol;
359
360     while (p->more_l || p->more_r)
361     {
362         int cmp;
363
364         if (p->more_l && p->more_r)
365             cmp = (*kctrl->cmp)(p->buf_l, p->buf_r);
366         else if (p->more_r)
367             cmp = 2;
368         else
369             cmp = -2;
370         if (!cmp)
371         {
372             memcpy (buf, p->buf_l, kctrl->key_size);
373             p->more_l = rset_read (p->rfd_l, p->buf_l);
374             p->more_r = rset_read (p->rfd_r, p->buf_r);
375 #if RSET_DEBUG
376             logf (LOG_DEBUG, "r_read_or returning A m=%d/%d c=%d",
377                     p->more_l, p->more_r, cmp);
378             (*kctrl->log_item)(LOG_DEBUG, buf, "");
379 #endif
380             p->hits++;
381             return 1;
382         }
383         else if (cmp > 0)
384         {
385             memcpy (buf, p->buf_r, kctrl->key_size);
386             p->more_r = rset_read (p->rfd_r, p->buf_r);
387 #if RSET_DEBUG
388             logf (LOG_DEBUG, "r_read_or returning B m=%d/%d c=%d",
389                     p->more_l, p->more_r, cmp);
390             (*kctrl->log_item)(LOG_DEBUG, buf, "");
391 #endif
392             p->hits++;
393             return 1;
394         }
395         else
396         {
397             memcpy (buf, p->buf_l, kctrl->key_size);
398             p->more_l = rset_read ( p->rfd_l, p->buf_l);
399 #if RSET_DEBUG
400             logf (LOG_DEBUG, "r_read_or returning C m=%d/%d c=%d",
401                     p->more_l, p->more_r, cmp);
402             (*kctrl->log_item)(LOG_DEBUG, buf, "");
403 #endif
404             p->hits++;
405             return 1;
406         }
407     }
408     return 0;
409 }
410
411 static int r_read_not (RSFD rfd, void *buf)
412 {
413     struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
414     const struct key_control *kctrl=rfd->rset->keycontrol;
415
416     while (p->more_l || p->more_r)
417     {
418         int cmp;
419
420         if (p->more_l && p->more_r)
421             cmp = (*kctrl->cmp)(p->buf_l, p->buf_r);
422         else if (p->more_r)
423             cmp = 2;
424         else
425             cmp = -2;
426         if (cmp < -1)
427         {
428             memcpy (buf, p->buf_l, kctrl->key_size);
429             p->more_l = rset_read (p->rfd_l, p->buf_l);
430             p->hits++;
431             return 1;
432         }
433         else if (cmp > 1)
434             p->more_r = rset_forward( p->rfd_r, p->buf_r, p->buf_l);
435         else
436         {
437             memcpy (buf, p->buf_l, kctrl->key_size);
438             do
439             { 
440                 p->more_l = rset_read (p->rfd_l, p->buf_l);
441                 if (!p->more_l)
442                     break;
443                 cmp = (*kctrl->cmp)(p->buf_l, buf);
444             } while (cmp >= -1 && cmp <= 1);
445             do
446             {
447                 p->more_r = rset_read (p->rfd_r, p->buf_r);
448                 if (!p->more_r)
449                     break;
450                 cmp = (*kctrl->cmp)(p->buf_r, buf);
451             } while (cmp >= -1 && cmp <= 1);
452         }
453     }
454     return 0;
455 }
456
457
458 static int r_write (RSFD rfd, const void *buf)
459 {
460     logf (LOG_FATAL, "bool set type is read-only");
461     return -1;
462 }
463
464 static void r_pos (RSFD rfd, double *current, double *total)
465 {
466     struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
467     double lcur,ltot;
468     double rcur,rtot;
469     double r;
470     ltot=-1; rtot=-1;
471     rset_pos(p->rfd_l,  &lcur, &ltot);
472     rset_pos(p->rfd_r,  &rcur, &rtot);
473     if ( (rtot<0) && (ltot<0)) { /*no position */
474         *current=rcur;  /* return same as you got */
475         *total=rtot;    /* probably -1 for not available */
476     }
477     if ( rtot<0) { rtot=0; rcur=0;} /* if only one useful, use it */
478     if ( ltot<0) { ltot=0; lcur=0;}
479     if ( rtot+ltot < 1 ) { /* empty rset */
480         *current=0;
481         *total=0;
482         return;
483     }
484     r=1.0*(lcur+rcur)/(ltot+rtot); /* weighed average of l and r */
485     *current=(double) (p->hits);
486     *total=*current/r ; 
487 #if RSET_DEBUG
488     yaz_log(LOG_DEBUG,"bool_pos: (%s/%s) %0.1f/%0.1f= %0.4f ",
489                     info->rset_l->control->desc, info->rset_r->control->desc,
490                     *current, *total, r);
491 #endif
492 }