1 /* $Id: rsbool.c,v 1.45 2004-08-31 10:43:39 heikki Exp $
2 Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004
5 This file is part of the Zebra server.
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
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
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
36 static RSFD r_open (RSET ct, int flag);
37 static void r_close (RSFD rfd);
38 static void r_delete (RSET ct);
39 static void r_rewind (RSFD rfd);
40 static int r_forward(RSFD rfd, void *buf,
41 int (*cmpfunc)(const void *p1, const void *p2),
42 const void *untilbuf);
43 static void r_pos (RSFD rfd, double *current, double *total);
44 static int r_read_and (RSFD rfd, void *buf);
45 static int r_read_or (RSFD rfd, void *buf);
46 static int r_read_not (RSFD rfd, void *buf);
47 static int r_write (RSFD rfd, const void *buf);
49 static const struct rset_control control_and =
62 static const struct rset_control control_or =
75 static const struct rset_control control_not =
89 const struct rset_control *rset_kind_and = &control_and;
90 const struct rset_control *rset_kind_or = &control_or;
91 const struct rset_control *rset_kind_not = &control_not;
93 struct rset_bool_info {
97 int (*cmp)(const void *p1, const void *p2);
98 void (*log_item)(int logmask, const void *p, const char *txt);
101 struct rset_bool_rfd {
110 struct rset_bool_rfd *next;
111 struct rset_bool_info *info;
114 static RSET rsbool_create_base( const struct rset_control *ctrl,
115 NMEM nmem, int key_size,
116 int (*cmp)(const void *p1, const void *p2),
117 RSET rset_l, RSET rset_r,
118 void (*log_item)(int logmask, const void *p, const char *txt) )
120 RSET rnew=rset_create_base(ctrl, nmem);
121 struct rset_bool_info *info;
122 info = (struct rset_bool_info *) nmem_malloc(rnew->nmem,sizeof(*info));
123 info->key_size = key_size;
124 info->rset_l = rset_l;
125 info->rset_r = rset_r;
127 info->log_item = log_item;
134 RSET rsbool_create_and( NMEM nmem, int key_size,
135 int (*cmp)(const void *p1, const void *p2),
136 RSET rset_l, RSET rset_r,
137 void (*log_item)(int logmask, const void *p, const char *txt) )
139 return rsbool_create_base(rset_kind_and, nmem, key_size, cmp,
140 rset_l, rset_r, log_item);
143 RSET rsbool_create_or( NMEM nmem, int key_size,
144 int (*cmp)(const void *p1, const void *p2),
145 RSET rset_l, RSET rset_r,
146 void (*log_item)(int logmask, const void *p, const char *txt) )
148 return rsbool_create_base(rset_kind_or, nmem, key_size, cmp,
149 rset_l, rset_r, log_item);
152 RSET rsbool_create_not( NMEM nmem, int key_size,
153 int (*cmp)(const void *p1, const void *p2),
154 RSET rset_l, RSET rset_r,
155 void (*log_item)(int logmask, const void *p, const char *txt) )
157 return rsbool_create_base(rset_kind_not, nmem, key_size, cmp,
158 rset_l, rset_r, log_item);
161 static void r_delete (RSET ct)
163 struct rset_bool_info *info = (struct rset_bool_info *) ct->priv;
164 rset_delete (info->rset_l);
165 rset_delete (info->rset_r);
169 static RSFD r_open (RSET ct, int flag)
171 struct rset_bool_info *info = (struct rset_bool_info *) ct->priv;
173 struct rset_bool_rfd *p;
176 if (flag & RSETF_WRITE)
178 logf (LOG_FATAL, "bool set type is read-only");
181 rfd = rfd_create_base(ct);
183 p=(struct rset_bool_rfd *)rfd->priv;
185 p=nmem_malloc(ct->nmem,sizeof(*p));
187 p->buf_l = nmem_malloc(ct->nmem, info->key_size);
188 p->buf_r = nmem_malloc(ct->nmem, info->key_size);
191 logf(LOG_DEBUG,"rsbool (%s) open [%p]", ct->control->desc, rfd);
194 p->rfd_l = rset_open (info->rset_l, RSETF_READ);
195 p->rfd_r = rset_open (info->rset_r, RSETF_READ);
196 p->more_l = rset_read (p->rfd_l, p->buf_l);
197 p->more_r = rset_read (p->rfd_r, p->buf_r);
202 static void r_close (RSFD rfd)
204 /* struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv); */
205 struct rset_bool_rfd *prfd=(struct rset_bool_rfd *)rfd->priv;
207 rset_close (prfd->rfd_l);
208 rset_close (prfd->rfd_r);
209 rfd_delete_base(rfd);
213 static void r_rewind (RSFD rfd)
215 /* struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv); */
216 struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
218 logf (LOG_DEBUG, "rsbool_rewind");
219 rset_rewind (p->rfd_l);
220 rset_rewind (p->rfd_r);
221 p->more_l = rset_read (p->rfd_l, p->buf_l);
222 p->more_r = rset_read (p->rfd_r, p->buf_r);
226 static int r_forward (RSFD rfd, void *buf,
227 int (*cmpfunc)(const void *p1, const void *p2),
228 const void *untilbuf)
230 struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv);
231 struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
234 if ( p->more_l && ((cmpfunc)(untilbuf,p->buf_l)==2) )
235 p->more_l = rset_forward(p->rfd_l, p->buf_l,
236 info->cmp, untilbuf);
237 if ( p->more_r && ((cmpfunc)(untilbuf,p->buf_r)==2))
238 p->more_r = rset_forward(p->rfd_r, p->buf_r,
239 info->cmp, untilbuf);
241 rc = rset_read(rfd,buf);
261 static int r_read_and (RSFD rfd, void *buf)
263 struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv);
264 struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
266 while (p->more_l || p->more_r)
270 if (p->more_l && p->more_r)
271 cmp = (*info->cmp)(p->buf_l, p->buf_r);
277 logf (LOG_DEBUG, "r_read_and [%p] looping: m=%d/%d c=%d t=%d",
278 rfd, p->more_l, p->more_r, cmp, p->tail);
279 (*info->log_item)(LOG_DEBUG, p->buf_l, "left ");
280 (*info->log_item)(LOG_DEBUG, p->buf_r, "right ");
284 memcpy (buf, p->buf_l, info->key_size);
285 p->more_l = rset_read (p->rfd_l, p->buf_l);
290 memcpy (buf, p->buf_r, info->key_size);
291 p->more_r = rset_read (p->rfd_r, p->buf_r);
294 logf (LOG_DEBUG, "r_read_and [%p] returning R m=%d/%d c=%d",
295 rfd, p->more_l, p->more_r, cmp);
296 key_logdump(LOG_DEBUG,buf);
297 (*info->log_item)(LOG_DEBUG, buf, "");
304 memcpy (buf, p->buf_l, info->key_size);
305 p->more_l = rset_read (p->rfd_l, p->buf_l);
308 logf (LOG_DEBUG, "r_read_and [%p] returning L m=%d/%d c=%d",
309 rfd, p->more_l, p->more_r, cmp);
310 (*info->log_item)(LOG_DEBUG, buf, "");
315 else if (cmp > 1) /* cmp == 2 */
319 memcpy (buf, p->buf_r, info->key_size);
321 p->more_r = rset_read (p->rfd_r, p->buf_r);
324 if (!p->more_r || (*info->cmp)(p->buf_r, buf) > 1)
327 logf (LOG_DEBUG, "r_read_and returning C m=%d/%d c=%d",
328 p->more_l, p->more_r, cmp);
329 (*info->log_item)(LOG_DEBUG, buf, "");
338 memcpy (buf, p->buf_r, info->key_size);
339 p->more_r = rset_read (p->rfd_r, p->buf_r);
340 if (!p->more_r || (*info->cmp)(p->buf_r, buf) > 1)
343 logf (LOG_DEBUG, "r_read_and [%p] returning R tail m=%d/%d c=%d",
344 rfd, p->more_l, p->more_r, cmp);
345 (*info->log_item)(LOG_DEBUG, buf, "");
353 logf (LOG_DEBUG, "r_read_and [%p] about to forward R m=%d/%d c=%d",
354 rfd, p->more_l, p->more_r, cmp);
356 if (p->more_r && p->more_l)
357 p->more_r = rset_forward( p->rfd_r,
358 p->buf_r, (info->cmp), p->buf_l);
360 return 0; /* no point in reading further */
367 memcpy (buf, p->buf_l, info->key_size);
368 p->more_l = rset_read (p->rfd_l, p->buf_l);
371 if (!p->more_l || (*info->cmp)(p->buf_l, buf) > 1)
374 logf (LOG_DEBUG, "r_read_and [%p] returning R tail m=%d/%d c=%d",
375 rfd, p->more_l, p->more_r, cmp);
376 (*info->log_item)(LOG_DEBUG, buf, "");
384 memcpy (buf, p->buf_l, info->key_size);
385 p->more_l = rset_read (p->rfd_l, p->buf_l);
386 if (!p->more_l || (*info->cmp)(p->buf_l, buf) > 1)
389 logf (LOG_DEBUG, "r_read_and [%p] returning L tail m=%d/%d c=%d",
390 rfd, p->more_l, p->more_r, cmp);
391 (*info->log_item)(LOG_DEBUG, buf, "");
399 logf (LOG_DEBUG, "r_read_and [%p] about to forward L m=%d/%d c=%d",
400 rfd, p->more_l, p->more_r, cmp);
402 if (p->more_r && p->more_l)
403 p->more_l = rset_forward(p->rfd_l,
404 p->buf_l, (info->cmp), p->buf_r);
406 return 0; /* no point in reading further */
412 logf (LOG_DEBUG, "r_read_and [%p] reached its end",rfd);
417 static int r_read_or (RSFD rfd, void *buf)
419 struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv);
420 struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
422 while (p->more_l || p->more_r)
426 if (p->more_l && p->more_r)
427 cmp = (*info->cmp)(p->buf_l, p->buf_r);
434 memcpy (buf, p->buf_l, info->key_size);
435 p->more_l = rset_read (p->rfd_l, p->buf_l);
436 p->more_r = rset_read (p->rfd_r, p->buf_r);
438 logf (LOG_DEBUG, "r_read_or returning A m=%d/%d c=%d",
439 p->more_l, p->more_r, cmp);
440 (*info->log_item)(LOG_DEBUG, buf, "");
447 memcpy (buf, p->buf_r, info->key_size);
448 p->more_r = rset_read (p->rfd_r, p->buf_r);
450 logf (LOG_DEBUG, "r_read_or returning B m=%d/%d c=%d",
451 p->more_l, p->more_r, cmp);
452 (*info->log_item)(LOG_DEBUG, buf, "");
459 memcpy (buf, p->buf_l, info->key_size);
460 p->more_l = rset_read ( p->rfd_l, p->buf_l);
462 logf (LOG_DEBUG, "r_read_or returning C m=%d/%d c=%d",
463 p->more_l, p->more_r, cmp);
464 (*info->log_item)(LOG_DEBUG, buf, "");
473 static int r_read_not (RSFD rfd, void *buf)
475 struct rset_bool_info *info = (struct rset_bool_info*)(rfd->rset->priv);
476 struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
478 while (p->more_l || p->more_r)
482 if (p->more_l && p->more_r)
483 cmp = (*info->cmp)(p->buf_l, p->buf_r);
490 memcpy (buf, p->buf_l, info->key_size);
491 p->more_l = rset_read (p->rfd_l, p->buf_l);
497 p->more_r = rset_forward( p->rfd_r,
498 p->buf_r, (info->cmp), p->buf_l);
502 memcpy (buf, p->buf_l, info->key_size);
505 p->more_l = rset_read (p->rfd_l, p->buf_l);
508 cmp = (*info->cmp)(p->buf_l, buf);
509 } while (cmp >= -1 && cmp <= 1);
512 p->more_r = rset_read (p->rfd_r, p->buf_r);
515 cmp = (*info->cmp)(p->buf_r, buf);
516 } while (cmp >= -1 && cmp <= 1);
523 static int r_write (RSFD rfd, const void *buf)
525 logf (LOG_FATAL, "bool set type is read-only");
529 static void r_pos (RSFD rfd, double *current, double *total)
531 struct rset_bool_rfd *p=(struct rset_bool_rfd *)rfd->priv;
536 rset_pos(p->rfd_l, &lcur, <ot);
537 rset_pos(p->rfd_r, &rcur, &rtot);
538 if ( (rtot<0) && (ltot<0)) { /*no position */
539 *current=rcur; /* return same as you got */
540 *total=rtot; /* probably -1 for not available */
542 if ( rtot<0) { rtot=0; rcur=0;} /* if only one useful, use it */
543 if ( ltot<0) { ltot=0; lcur=0;}
544 if ( rtot+ltot < 1 ) { /* empty rset */
549 r=1.0*(lcur+rcur)/(ltot+rtot); /* weighed average of l and r */
550 *current=(double) (p->hits);
553 yaz_log(LOG_DEBUG,"bool_pos: (%s/%s) %0.1f/%0.1f= %0.4f ",
554 info->rset_l->control->desc, info->rset_r->control->desc,
555 *current, *total, r);