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