X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=rset%2Frsmultiandor.c;h=b810c549c4584c91d2754c44cd0909783f548826;hb=810bce66201f40acfd7e8577d3997e6ea385f1cf;hp=0204cacedcb3f237a963d4468f7c5c9327099ade;hpb=8ed385caafd1d9695a5a9c0783f0dbe2a53f3e80;p=idzebra-moved-to-github.git diff --git a/rset/rsmultiandor.c b/rset/rsmultiandor.c index 0204cac..b810c54 100644 --- a/rset/rsmultiandor.c +++ b/rset/rsmultiandor.c @@ -1,4 +1,4 @@ -/* $Id: rsmultiandor.c,v 1.14 2005-03-08 14:02:15 adam Exp $ +/* $Id: rsmultiandor.c,v 1.19 2005-05-24 11:35:43 adam Exp $ Copyright (C) 1995-2005 Index Data ApS @@ -39,7 +39,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include #include -#include +#include #include #include @@ -69,6 +69,7 @@ static const struct rset_control control_or = r_read_or, r_write, }; + static const struct rset_control control_and = { "multi-and", @@ -82,9 +83,6 @@ static const struct rset_control control_and = r_write, }; -const struct rset_control *rset_kind_multior = &control_or; -const struct rset_control *rset_kind_multiand = &control_and; - /* The heap structure: * The rset contains a list or rsets we are ORing together * The rfd contains a heap of heap-items, which contain @@ -103,19 +101,18 @@ struct heap_item { struct heap { int heapnum; int heapmax; - const struct key_control *kctrl; + const struct rset_key_control *kctrl; struct heap_item **heap; /* ptrs to the rfd */ }; typedef struct heap *HEAP; -struct rset_multiandor_info { - int no_rsets; - RSET *rsets; +struct rset_private { + int dummy; }; -struct rset_multiandor_rfd { +struct rfd_private { int flag; struct heap_item *items; /* we alloc and free them here */ HEAP h; /* and move around here */ @@ -224,7 +221,7 @@ static void heap_insert (HEAP h, struct heap_item *hi) static -HEAP heap_create (NMEM nmem, int size, const struct key_control *kctrl) +HEAP heap_create (NMEM nmem, int size, const struct rset_key_control *kctrl) { HEAP h = (HEAP) nmem_malloc (nmem, sizeof(*h)); @@ -265,56 +262,51 @@ int compare_ands(const void *x, const void *y) /* Creating and deleting rsets ***********************/ -static RSET rsmulti_andor_create( NMEM nmem, const struct key_control *kcontrol, - int scope, int no_rsets, RSET* rsets, - const struct rset_control *ctrl) +static RSET rsmulti_andor_create(NMEM nmem, + struct rset_key_control *kcontrol, + int scope, TERMID termid, + int no_rsets, RSET* rsets, + const struct rset_control *ctrl) { - RSET rnew = rset_create_base(ctrl, nmem,kcontrol, scope,0); - struct rset_multiandor_info *info; + RSET rnew = rset_create_base(ctrl, nmem, kcontrol, scope, termid, + no_rsets, rsets); + struct rset_private *info; if (!log_level_initialized) { log_level = yaz_log_module_level("rsmultiandor"); log_level_initialized = 1; } - info = (struct rset_multiandor_info *) nmem_malloc(rnew->nmem,sizeof(*info)); - info->no_rsets = no_rsets; - info->rsets = (RSET*)nmem_malloc(rnew->nmem, no_rsets*sizeof(*rsets)); - memcpy(info->rsets,rsets,no_rsets*sizeof(*rsets)); + yaz_log(log_level, "rsmultiand_andor_create scope=%d", scope); + info = (struct rset_private *) nmem_malloc(rnew->nmem, sizeof(*info)); rnew->priv = info; return rnew; } -RSET rsmulti_or_create(NMEM nmem, const struct key_control *kcontrol, - int scope, int no_rsets, RSET* rsets) +RSET rsmulti_or_create(NMEM nmem, struct rset_key_control *kcontrol, + int scope, TERMID termid, int no_rsets, RSET* rsets) { - return rsmulti_andor_create(nmem, kcontrol, scope, + return rsmulti_andor_create(nmem, kcontrol, scope, termid, no_rsets, rsets, &control_or); } -RSET rsmulti_and_create(NMEM nmem, const struct key_control *kcontrol, +RSET rsmulti_and_create(NMEM nmem, struct rset_key_control *kcontrol, int scope, int no_rsets, RSET* rsets) { - return rsmulti_andor_create(nmem, kcontrol, scope, + return rsmulti_andor_create(nmem, kcontrol, scope, 0, no_rsets, rsets, &control_and); } static void r_delete (RSET ct) { - struct rset_multiandor_info *info = (struct rset_multiandor_info *) ct->priv; - int i; - for(i = 0; ino_rsets; i++) - rset_delete(info->rsets[i]); } - /* Opening and closing fd's on them *********************/ static RSFD r_open_andor (RSET ct, int flag, int is_and) { RSFD rfd; - struct rset_multiandor_rfd *p; - struct rset_multiandor_info *info = (struct rset_multiandor_info *) ct->priv; - const struct key_control *kctrl = ct->keycontrol; + struct rfd_private *p; + const struct rset_key_control *kctrl = ct->keycontrol; int i; if (flag & RSETF_WRITE) @@ -324,26 +316,27 @@ static RSFD r_open_andor (RSET ct, int flag, int is_and) } rfd = rfd_create_base(ct); if (rfd->priv) { - p = (struct rset_multiandor_rfd *)rfd->priv; + p = (struct rfd_private *)rfd->priv; if (!is_and) heap_clear(p->h); assert(p->items); /* all other pointers shouls already be allocated, in right sizes! */ } else { - p = (struct rset_multiandor_rfd *) nmem_malloc (ct->nmem,sizeof(*p)); + p = (struct rfd_private *) nmem_malloc (ct->nmem,sizeof(*p)); rfd->priv = p; p->h = 0; p->tailbits = 0; if (is_and) - p->tailbits = nmem_malloc(ct->nmem, info->no_rsets*sizeof(char) ); + p->tailbits = nmem_malloc(ct->nmem, ct->no_children*sizeof(char) ); else - p->h = heap_create( ct->nmem, info->no_rsets, kctrl); - p->items=(struct heap_item *) nmem_malloc(ct->nmem, - info->no_rsets*sizeof(*p->items)); - for (i = 0; ino_rsets; i++){ - p->items[i].rset = info->rsets[i]; - p->items[i].buf = nmem_malloc(ct->nmem,kctrl->key_size); + p->h = heap_create( ct->nmem, ct->no_children, kctrl); + p->items = (struct heap_item *) + nmem_malloc(ct->nmem, ct->no_children*sizeof(*p->items)); + for (i = 0; ino_children; i++) + { + p->items[i].rset = ct->children[i]; + p->items[i].buf = nmem_malloc(ct->nmem, kctrl->key_size); } } p->flag = flag; @@ -352,17 +345,17 @@ static RSFD r_open_andor (RSET ct, int flag, int is_and) p->tailcount = 0; if (is_and) { /* read the array and sort it */ - for (i = 0; ino_rsets; i++){ - p->items[i].fd = rset_open(info->rsets[i],RSETF_READ); + for (i = 0; ino_children; i++){ + p->items[i].fd = rset_open(ct->children[i], RSETF_READ); if (!rset_read(p->items[i].fd, p->items[i].buf, &p->items[i].term)) p->eof = 1; p->tailbits[i] = 0; } - qsort(p->items, info->no_rsets, sizeof(p->items[0]), compare_ands); + qsort(p->items, ct->no_children, sizeof(p->items[0]), compare_ands); } else { /* fill the heap for ORing */ - for (i = 0; ino_rsets; i++){ - p->items[i].fd = rset_open(info->rsets[i],RSETF_READ); + for (i = 0; ino_children; i++){ + p->items[i].fd = rset_open(ct->children[i],RSETF_READ); if ( rset_read(p->items[i].fd, p->items[i].buf, &p->items[i].term)) heap_insert(p->h, &(p->items[i])); } @@ -383,26 +376,23 @@ static RSFD r_open_and (RSET ct, int flag) static void r_close (RSFD rfd) { - struct rset_multiandor_info *info= - (struct rset_multiandor_info *)(rfd->rset->priv); - struct rset_multiandor_rfd *p=(struct rset_multiandor_rfd *)(rfd->priv); + struct rfd_private *p=(struct rfd_private *)(rfd->priv); int i; if (p->h) heap_destroy (p->h); - for (i = 0; ino_rsets; i++) + for (i = 0; irset->no_children; i++) if (p->items[i].fd) rset_close(p->items[i].fd); - rfd_delete_base(rfd); } static int r_forward_or(RSFD rfd, void *buf, - TERMID *term,const void *untilbuf) + TERMID *term, const void *untilbuf) { /* while heap head behind untilbuf, forward it and rebalance heap */ - struct rset_multiandor_rfd *p = rfd->priv; - const struct key_control *kctrl = rfd->rset->keycontrol; + struct rfd_private *p = rfd->priv; + const struct rset_key_control *kctrl = rfd->rset->keycontrol; if (heap_empty(p->h)) return 0; while ( (*kctrl->cmp)(p->h->heap[1]->buf,untilbuf) < -rfd->rset->scope ) @@ -418,22 +408,29 @@ static int r_forward_or(RSFD rfd, void *buf, } } - return r_read_or(rfd,buf,term); + return r_read_or(rfd, buf, term); } static int r_read_or (RSFD rfd, void *buf, TERMID *term) { - struct rset_multiandor_rfd *mrfd = rfd->priv; - const struct key_control *kctrl = rfd->rset->keycontrol; + RSET rset = rfd->rset; + struct rfd_private *mrfd = rfd->priv; + const struct rset_key_control *kctrl = rset->keycontrol; struct heap_item *it; int rdres; if (heap_empty(mrfd->h)) return 0; it = mrfd->h->heap[1]; - memcpy(buf,it->buf, kctrl->key_size); + memcpy(buf, it->buf, kctrl->key_size); if (term) - *term = it->term; + { + if (rset->term) + *term = rset->term; + else + *term = it->term; + assert(*term); + } (mrfd->hits)++; rdres = rset_read(it->fd, it->buf, &it->term); if ( rdres ) @@ -453,9 +450,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term) /* Once a hit has been found, scan all items for the smallest */ /* value. Mark all as being in the tail. Read next from that */ /* item, and if not in the same record, clear its tail bit */ - struct rset_multiandor_rfd *p = rfd->priv; - const struct key_control *kctrl = rfd->rset->keycontrol; - struct rset_multiandor_info *info = rfd->rset->priv; + struct rfd_private *p = rfd->priv; + RSET ct = rfd->rset; + const struct rset_key_control *kctrl = ct->keycontrol; int i, mintail; int cmp; @@ -463,9 +460,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term) if (p->tailcount) { /* we are tailing, find lowest tail and return it */ mintail = 0; - while ((mintailno_rsets) && !p->tailbits[mintail]) + while ((mintailno_children) && !p->tailbits[mintail]) mintail++; /* first tail */ - for (i = mintail+1; ino_rsets; i++) + for (i = mintail+1; ino_children; i++) { if (p->tailbits[i]) { @@ -482,16 +479,18 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term) &p->items[mintail].term)) { p->eof = 1; /* game over, once tails have been returned */ - p->tailbits[mintail]=0; + p->tailbits[mintail] = 0; (p->tailcount)--; + (p->hits)++; return 1; } /* still a tail? */ - cmp=(*kctrl->cmp)(p->items[mintail].buf,buf); + cmp = (*kctrl->cmp)(p->items[mintail].buf,buf); if (cmp >= rfd->rset->scope){ - p->tailbits[mintail]=0; + p->tailbits[mintail] = 0; (p->tailcount)--; } + (p->hits)++; return 1; } /* not tailing, forward until all reocrds match, and set up */ @@ -499,9 +498,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term) if (p->eof) return 0; /* nothing more to see */ i = 1; /* assume items[0] is highest up */ - while (ino_rsets) { - cmp=(*kctrl->cmp)(p->items[0].buf,p->items[i].buf); - if (cmp<=-rfd->rset->scope) { /* [0] was behind, forward it */ + while (ino_children) { + 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)) { @@ -523,9 +522,9 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term) /* 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; ino_rsets; i++) + for (i = 0; ino_children; i++) p->tailbits[i] = 1; - p->tailcount = info->no_rsets; + p->tailcount = ct->no_children; } /* while 1 */ } @@ -533,14 +532,14 @@ static int r_read_and (RSFD rfd, void *buf, TERMID *term) static int r_forward_and(RSFD rfd, void *buf, TERMID *term, const void *untilbuf) { - struct rset_multiandor_rfd *p = rfd->priv; - const struct key_control *kctrl = rfd->rset->keycontrol; - struct rset_multiandor_info *info = rfd->rset->priv; + struct rfd_private *p = rfd->priv; + RSET ct = rfd->rset; + const struct rset_key_control *kctrl = ct->keycontrol; int i; int cmp; int killtail = 0; - for (i = 0; ino_rsets; i++) + for (i = 0; ino_children; i++) { cmp = (*kctrl->cmp)(p->items[i].buf,untilbuf); if (cmp <= -rfd->rset->scope) @@ -557,7 +556,7 @@ static int r_forward_and(RSFD rfd, void *buf, TERMID *term, } if (killtail) { - for (i = 0; ino_rsets; i++) + for (i = 0; ino_children; i++) p->tailbits[i] = 0; p->tailcount = 0; } @@ -566,14 +565,13 @@ static int r_forward_and(RSFD rfd, void *buf, TERMID *term, static void r_pos (RSFD rfd, double *current, double *total) { - struct rset_multiandor_info *info = - (struct rset_multiandor_info *)(rfd->rset->priv); - struct rset_multiandor_rfd *mrfd = - (struct rset_multiandor_rfd *)(rfd->priv); + RSET ct = rfd->rset; + struct rfd_private *mrfd = + (struct rfd_private *)(rfd->priv); double cur, tot; double scur = 0.0, stot = 0.0; int i; - for (i = 0; ino_rsets; i++){ + for (i = 0; ino_children; i++){ rset_pos(mrfd->items[i].fd, &cur, &tot); yaz_log(log_level, "r_pos: %d %0.1f %0.1f", i, cur,tot); scur += cur; @@ -599,22 +597,27 @@ static int r_write (RSFD rfd, const void *buf) } static void r_get_terms(RSET ct, TERMID *terms, int maxterms, int *curterm) - /* Special case: Some multi-ors have all terms pointing to the same */ - /* term. We do not want to duplicate those. Other multiors (and ands) */ - /* have different terms under them. Those we want. */ { - struct rset_multiandor_info *info = - (struct rset_multiandor_info *) ct->priv; - int firstterm= *curterm; - int i; - for (i = 0; ino_rsets; i++) + if (ct->term) + rset_get_one_term(ct, terms, maxterms, curterm); + else { - rset_getterms(info->rsets[i], terms, maxterms, curterm); - if ( ( *curterm > firstterm+1 ) && - ( *curterm <= maxterms ) && - ( terms[(*curterm)-1] == terms[firstterm] ) - ) - (*curterm)--; /* forget the term, seen that before */ + /* Special case: Some multi-ors have all terms pointing to the same + term. We do not want to duplicate those. Other multiors (and ands) + have different terms under them. Those we want. + */ + int firstterm= *curterm; + int i; + + for (i = 0; ino_children; i++) + { + rset_getterms(ct->children[i], terms, maxterms, curterm); + if ( ( *curterm > firstterm+1 ) && + ( *curterm <= maxterms ) && + ( terms[(*curterm)-1] == terms[firstterm] ) + ) + (*curterm)--; /* forget the term, seen that before */ + } } }