-/* $Id: rsmultiandor.c,v 1.22 2006-07-04 10:25:22 adam Exp $
- Copyright (C) 1995-2006
- Index Data ApS
-
-This file is part of the Zebra server.
+/* This file is part of the Zebra server.
+ Copyright (C) 1994-2011 Index Data
Zebra is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
for more details.
You should have received a copy of the GNU General Public License
-along with Zebra; see the file LICENSE.zebra. If not, write to the
-Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
*/
*/
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
const void *untilbuf);
static int r_forward_or(RSFD rfd, void *buf, TERMID *term,
const void *untilbuf);
-static void r_pos (RSFD rfd, double *current, double *total);
+static void r_pos_and(RSFD rfd, double *current, double *total);
+static void r_pos_or(RSFD rfd, double *current, double *total);
static void r_get_terms(RSET ct, TERMID *terms, int maxterms, int *curterm);
static const struct rset_control control_or =
r_open_or,
r_close,
r_forward_or,
- r_pos,
+ r_pos_or,
r_read_or,
r_write,
};
r_open_and,
r_close,
r_forward_and,
- r_pos,
+ r_pos_and,
r_read_and,
r_write,
};
zint hits; /* returned so far */
int eof; /* seen the end of it */
int tailcount; /* how many items are tailing */
+ zint segment;
+ int skip;
char *tailbits;
};
*term = rset->term;
else
*term = it->term;
- assert(*term);
}
(mrfd->hits)++;
rdres = rset_read(it->fd, it->buf, &it->term);
{ struct rfd_private *p = rfd->priv;
RSET ct = rfd->rset;
const struct rset_key_control *kctrl = ct->keycontrol;
- int i, mintail;
- int cmp;
+ int i;
while (1) {
if (p->tailcount)
{ /* we are tailing, find lowest tail and return it */
- mintail = 0;
- while ((mintail<ct->no_children) && !p->tailbits[mintail])
- mintail++; /* first tail */
- for (i = mintail+1; i<ct->no_children; i++)
+ int mintail = -1;
+ int cmp;
+
+ for (i = 0; i<ct->no_children; i++)
{
if (p->tailbits[i])
{
- cmp=(*kctrl->cmp)(p->items[i].buf,p->items[mintail].buf);
- if (cmp<0)
+ if (mintail >= 0)
+ cmp = (*kctrl->cmp)
+ (p->items[i].buf, p->items[mintail].buf);
+ else
+ cmp = -1;
+ if (cmp < 0)
mintail = i;
+
+ if (kctrl->get_segment)
+ { /* segments enabled */
+ zint segment = kctrl->get_segment(p->items[i].buf);
+ /* store segment if not stored already */
+ if (!p->segment && segment)
+ p->segment = segment;
+
+ /* skip rest entirely if segments don't match */
+ if (p->segment && segment && p->segment != segment)
+ p->skip = 1;
+ }
}
}
/* return the lowest tail */
p->eof = 1; /* game over, once tails have been returned */
p->tailbits[mintail] = 0;
(p->tailcount)--;
- (p->hits)++;
- return 1;
}
- /* still a tail? */
- cmp = (*kctrl->cmp)(p->items[mintail].buf,buf);
- if (cmp >= rfd->rset->scope){
- p->tailbits[mintail] = 0;
- (p->tailcount)--;
+ else
+ {
+ /* still a tail? */
+ cmp = (*kctrl->cmp)(p->items[mintail].buf,buf);
+ if (cmp >= rfd->rset->scope)
+ {
+ p->tailbits[mintail] = 0;
+ (p->tailcount)--;
+ }
}
- (p->hits)++;
+ if (p->skip)
+ continue; /* skip again.. eventually tailcount will be 0 */
+ if (p->tailcount == 0)
+ (p->hits)++;
return 1;
}
- /* not tailing, forward until all reocrds match, and set up */
+ /* not tailing, forward until all records match, and set up */
/* as tails. the earlier 'if' will then return the hits */
if (p->eof)
return 0; /* nothing more to see */
i = 1; /* assume items[0] is highest up */
- while (i<ct->no_children) {
- cmp = (*kctrl->cmp)(p->items[0].buf, p->items[i].buf);
+ while (i < ct->no_children)
+ {
+ int cmp = (*kctrl->cmp)(p->items[0].buf, p->items[i].buf);
if (cmp <= -rfd->rset->scope) { /* [0] was behind, forward it */
if (!rset_forward(p->items[0].fd, p->items[0].buf,
&p->items[0].term, p->items[i].buf))
p->eof = 1; /* game over */
return 0;
}
- i = 0; /* start frowarding from scratch */
+ i = 0; /* start forwarding from scratch */
}
else if (cmp>=rfd->rset->scope)
{ /* [0] was ahead, forward i */
/* if we get this far, all rsets are now within +- scope of [0] */
/* ergo, we have a hit. Mark them all as tailing, and let the */
/* upper 'if' return the hits in right order */
- for (i = 0; i<ct->no_children; i++)
+ for (i = 0; i < ct->no_children; i++)
p->tailbits[i] = 1;
p->tailcount = ct->no_children;
+ p->segment = 0;
+ p->skip = 0;
} /* while 1 */
}
return r_read_and(rfd,buf,term);
}
-static void r_pos (RSFD rfd, double *current, double *total)
+static void r_pos_x(RSFD rfd, double *current, double *total, int and_op)
{
RSET ct = rfd->rset;
struct rfd_private *mrfd =
(struct rfd_private *)(rfd->priv);
- double cur, tot;
- double scur = 0.0, stot = 0.0;
+ double ratio = and_op ? 0.0 : 1.0;
int i;
+ double sum_cur = 0.0;
+ double sum_tot = 0.0;
for (i = 0; i<ct->no_children; i++){
+ double nratio, cur, tot;
rset_pos(mrfd->items[i].fd, &cur, &tot);
- yaz_log(log_level, "r_pos: %d %0.1f %0.1f", i, cur,tot);
- scur += cur;
- stot += tot;
+ yaz_log(log_level, "r_pos: %d %0.1f %0.1f", i, cur,tot);
+ nratio = cur / tot;
+ if (and_op)
+ {
+ if (nratio > ratio)
+ ratio = nratio;
+ }
+ else
+ {
+ sum_cur += cur;
+ sum_tot += tot;
+ }
}
- if (stot < 1.0) { /* nothing there */
+ if (!and_op)
+ ratio = sum_cur / sum_tot;
+ if (ratio == 0.0 || ratio == 1.0) { /* nothing there */
*current = 0;
*total = 0;
yaz_log(log_level, "r_pos: NULL %0.1f %0.1f", *current, *total);
else
{
*current = (double) (mrfd->hits);
- *total = *current*stot/scur;
+ *total = *current / ratio;
yaz_log(log_level, "r_pos: = %0.1f %0.1f", *current, *total);
}
}
+static void r_pos_and(RSFD rfd, double *current, double *total)
+{
+ r_pos_x(rfd, current, total, 1);
+}
+
+static void r_pos_or(RSFD rfd, double *current, double *total)
+{
+ r_pos_x(rfd, current, total, 0);
+}
+
static int r_write (RSFD rfd, const void *buf)
{
yaz_log (YLOG_FATAL, "multior set type is read-only");
/*
* Local variables:
* c-basic-offset: 4
+ * c-file-style: "Stroustrup"
* indent-tabs-mode: nil
* End:
* vim: shiftwidth=4 tabstop=8 expandtab