Fix term counters to be of type zint. Fix several printfs of zint.
[idzebra-moved-to-github.git] / index / zsets.c
1 /* $Id: zsets.c,v 1.53 2004-08-06 12:55:01 adam 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
24 #include <stdio.h>
25 #include <assert.h>
26 #ifdef WIN32
27 #include <io.h>
28 #else
29 #include <unistd.h>
30 #endif
31
32 #include "index.h"
33 #include <rstemp.h>
34
35 #define SORT_IDX_ENTRYSIZE 64
36 #define ZSET_SORT_MAX_LEVEL 3
37
38 struct zebra_set_term_entry {
39     int reg_type;
40     char *db;
41     int set;
42     int use;
43     char *term;
44 };
45 struct zebra_set {
46     char *name;
47     RSET rset;
48     NMEM nmem;
49     int hits;
50     int num_bases;
51     char **basenames;
52     Z_RPNQuery *rpn;
53     struct zset_sort_info *sort_info;
54     struct zebra_set_term_entry *term_entries;
55     int term_entries_max;
56     struct zebra_set *next;
57     int locked;
58 };
59
60 struct zset_sort_entry {
61     zint sysno;
62     int score;
63     char buf[ZSET_SORT_MAX_LEVEL][SORT_IDX_ENTRYSIZE];
64 };
65
66 struct zset_sort_info {
67     int max_entries;
68     int num_entries;
69     struct zset_sort_entry *all_entries;
70     struct zset_sort_entry **entries;
71 };
72
73 ZebraSet resultSetAddRPN (ZebraHandle zh, NMEM m,
74                           Z_RPNQuery *rpn, int num_bases,
75                           char **basenames, 
76                           const char *setname)
77 {
78     ZebraSet zebraSet;
79     int i;
80
81     zh->errCode = 0;
82     zh->errString = NULL;
83     zh->hits = 0;
84
85     zebraSet = resultSetAdd (zh, setname, 1);
86     if (!zebraSet)
87         return 0;
88     zebraSet->locked = 1;
89     zebraSet->rpn = 0;
90     zebraSet->nmem = m;
91
92     zebraSet->num_bases = num_bases;
93     zebraSet->basenames = 
94         nmem_malloc (zebraSet->nmem, num_bases * sizeof(*zebraSet->basenames));
95     for (i = 0; i<num_bases; i++)
96         zebraSet->basenames[i] = nmem_strdup (zebraSet->nmem, basenames[i]);
97
98
99     zebraSet->rset = rpn_search (zh, zebraSet->nmem, rpn,
100                                  zebraSet->num_bases,
101                                  zebraSet->basenames, zebraSet->name,
102                                  zebraSet);
103     zh->hits = zebraSet->hits;
104     if (zebraSet->rset)
105         zebraSet->rpn = rpn;
106     zebraSet->locked = 0;
107     return zebraSet;
108 }
109
110 void resultSetAddTerm (ZebraHandle zh, ZebraSet s, int reg_type,
111                        const char *db, int set,
112                        int use, const char *term)
113 {
114     if (!s->nmem)
115         s->nmem = nmem_create ();
116     if (!s->term_entries)
117     {
118         int i;
119         s->term_entries_max = 1000;
120         s->term_entries =
121             nmem_malloc (s->nmem, s->term_entries_max * 
122                          sizeof(*s->term_entries));
123         for (i = 0; i < s->term_entries_max; i++)
124             s->term_entries[i].term = 0;
125     }
126     if (s->hits < s->term_entries_max)
127     {
128         s->term_entries[s->hits].reg_type = reg_type;
129         s->term_entries[s->hits].db = nmem_strdup (s->nmem, db);
130         s->term_entries[s->hits].set = set;
131         s->term_entries[s->hits].use = use;
132         s->term_entries[s->hits].term = nmem_strdup (s->nmem, term);
133     }
134     (s->hits)++;
135 }
136
137
138 int zebra_resultSetTerms (ZebraHandle zh, const char *setname, 
139                           int no, int *count, 
140                           int *type, char *out, size_t *len)
141 {
142     ZebraSet s = resultSetGet (zh, setname);
143     int no_max = 0;
144
145     if (count)
146         *count = 0;
147     if (!s || !s->rset)
148         return 0;
149     no_max = s->rset->no_rset_terms;
150     if (no < 0 || no >= no_max)
151         return 0;
152     if (count)
153         *count = s->rset->rset_terms[no]->count;
154     if (type)
155         *type = s->rset->rset_terms[no]->type;
156     
157     if (out)
158     {
159         char *inbuf = s->rset->rset_terms[no]->name;
160         size_t inleft = strlen(inbuf);
161         size_t outleft = *len - 1;
162         int converted = 0;
163
164         if (zh->iconv_from_utf8 != 0)
165         {
166             char *outbuf = out;
167             size_t ret;
168             
169             ret = yaz_iconv(zh->iconv_from_utf8, &inbuf, &inleft,
170                         &outbuf, &outleft);
171             if (ret == (size_t)(-1))
172                 *len = 0;
173             else
174                 *len = outbuf - out;
175             converted = 1;
176         }
177         if (!converted)
178         {
179             if (inleft > outleft)
180                 inleft = outleft;
181             *len = inleft;
182             memcpy (out, inbuf, *len);
183         }
184         out[*len] = 0;
185     }
186     return no_max;
187 }
188
189
190 ZebraSet resultSetAdd (ZebraHandle zh, const char *name, int ov)
191 {
192     ZebraSet s;
193     int i;
194
195     for (s = zh->sets; s; s = s->next)
196         if (!strcmp (s->name, name))
197             break;
198     if (s)
199     {
200         yaz_log (LOG_DEBUG, "updating result set %s", name);
201         if (!ov || s->locked)
202             return NULL;
203         if (s->rset)
204             rset_delete (s->rset);
205         if (s->nmem)
206             nmem_destroy (s->nmem);
207     }
208     else
209     {
210         const char *sort_max_str = zebra_get_resource(zh, "sortmax", "1000");
211
212         yaz_log (LOG_DEBUG, "adding result set %s", name);
213         s = (ZebraSet) xmalloc (sizeof(*s));
214         s->next = zh->sets;
215         zh->sets = s;
216         s->name = (char *) xmalloc (strlen(name)+1);
217         strcpy (s->name, name);
218
219         s->sort_info = (struct zset_sort_info *)
220             xmalloc (sizeof(*s->sort_info));
221         s->sort_info->max_entries = atoi(sort_max_str);
222         if (s->sort_info->max_entries < 2)
223             s->sort_info->max_entries = 2;
224
225         s->sort_info->entries = (struct zset_sort_entry **)
226             xmalloc (sizeof(*s->sort_info->entries) *
227                      s->sort_info->max_entries);
228         s->sort_info->all_entries = (struct zset_sort_entry *)
229             xmalloc (sizeof(*s->sort_info->all_entries) *
230                      s->sort_info->max_entries);
231         for (i = 0; i < s->sort_info->max_entries; i++)
232             s->sort_info->entries[i] = s->sort_info->all_entries + i;
233     }
234     s->locked = 0;
235     s->term_entries = 0;
236     s->hits = 0;
237     s->rset = 0;
238     s->nmem = 0;
239     s->rpn = 0;
240     return s;
241 }
242
243 ZebraSet resultSetGet (ZebraHandle zh, const char *name)
244 {
245     ZebraSet s;
246
247     for (s = zh->sets; s; s = s->next)
248         if (!strcmp (s->name, name))
249         {
250             if (!s->term_entries && !s->rset && s->rpn)
251             {
252                 NMEM nmem = nmem_create ();
253                 yaz_log (LOG_LOG, "research %s", name);
254                 s->rset =
255                     rpn_search (zh, nmem, s->rpn, s->num_bases,
256                                 s->basenames, s->name, s);
257                 nmem_destroy (nmem);
258             }
259             return s;
260         }
261     return NULL;
262 }
263
264 void resultSetInvalidate (ZebraHandle zh)
265 {
266     ZebraSet s = zh->sets;
267     
268     for (; s; s = s->next)
269     {
270         if (s->rset)
271             rset_delete (s->rset);
272         s->rset = 0;
273     }
274 }
275
276 void resultSetDestroy (ZebraHandle zh, int num, char **names,int *statuses)
277 {
278     ZebraSet * ss = &zh->sets;
279     int i;
280     
281     if (statuses)
282         for (i = 0; i<num; i++)
283             statuses[i] = Z_DeleteStatus_resultSetDidNotExist;
284     zh->errCode = 0;
285     zh->errString = NULL;
286     while (*ss)
287     {
288         int i = -1;
289         ZebraSet s = *ss;
290         if (num >= 0)
291         {
292             for (i = 0; i<num; i++)
293                 if (!strcmp (s->name, names[i]))
294                 {
295                     if (statuses)
296                         statuses[i] = Z_DeleteStatus_success;
297                     i = -1;
298                     break;
299                 }
300         }
301         if (i < 0)
302         {
303             *ss = s->next;
304             
305             xfree (s->sort_info->all_entries);
306             xfree (s->sort_info->entries);
307             xfree (s->sort_info);
308             
309             if (s->nmem)
310                 nmem_destroy (s->nmem);
311             if (s->rset)
312                 rset_delete (s->rset);
313             xfree (s->name);
314             xfree (s);
315         }
316         else
317             ss = &s->next;
318     }
319 }
320
321 ZebraPosSet zebraPosSetCreate (ZebraHandle zh, const char *name, 
322                                int num, int *positions)
323 {
324     ZebraSet sset;
325     ZebraPosSet sr = 0;
326     RSET rset;
327     int i;
328     struct zset_sort_info *sort_info;
329
330     if (!(sset = resultSetGet (zh, name)))
331         return NULL;
332     if (!(rset = sset->rset))
333     {
334         if (!sset->term_entries)
335             return 0;
336         sr = (ZebraPosSet) xmalloc (sizeof(*sr) * num);
337         for (i = 0; i<num; i++)
338         {
339             sr[i].sysno = 0;
340             sr[i].score = -1;
341             sr[i].term = 0;
342             sr[i].db = 0;
343
344             if (positions[i] <= sset->term_entries_max)
345             {
346                 sr[i].term = sset->term_entries[positions[i]-1].term;
347                 sr[i].db = sset->term_entries[positions[i]-1].db;
348             }
349         }
350     }
351     else
352     {
353         sr = (ZebraPosSet) xmalloc (sizeof(*sr) * num);
354         for (i = 0; i<num; i++)
355         {
356             sr[i].sysno = 0;
357             sr[i].score = -1;
358             sr[i].term = 0;
359             sr[i].db = 0;
360         }
361         sort_info = sset->sort_info;
362         if (sort_info)
363         {
364             int position;
365             
366             for (i = 0; i<num; i++)
367             {
368                 position = positions[i];
369                 if (position > 0 && position <= sort_info->num_entries)
370                 {
371                     yaz_log (LOG_DEBUG, "got pos=%d (sorted)", position);
372                     sr[i].sysno = sort_info->entries[position-1]->sysno;
373                     sr[i].score = sort_info->entries[position-1]->score;
374                 }
375             }
376         }
377         /* did we really get all entries using sort ? */
378         for (i = 0; i<num; i++)
379         {
380             if (!sr[i].sysno)
381                 break;
382         }
383         if (i < num) /* nope, get the rest, unsorted - sorry */
384         {
385             int position = 0;
386             int num_i = 0;
387             zint psysno = 0;
388             int term_index;
389             RSFD rfd;
390             struct it_key key;
391             
392             if (sort_info)
393                 position = sort_info->num_entries;
394             while (num_i < num && positions[num_i] < position)
395                 num_i++;
396             rfd = rset_open (rset, RSETF_READ);
397             while (num_i < num && rset_read (rset, rfd, &key, &term_index))
398             {
399 #if IT_KEY_NEW
400                 zint this_sys = key.mem[0];
401 #else
402                 zint this_sys = key.sysno;
403 #endif
404                 if (this_sys != psysno)
405                 {
406                     psysno = this_sys;
407                     if (sort_info)
408                     {
409                         /* determine we alreay have this in our set */
410                         for (i = sort_info->num_entries; --i >= 0; )
411                             if (psysno == sort_info->entries[i]->sysno)
412                                 break;
413                         if (i >= 0)
414                             continue;
415                     }
416                     position++;
417                     assert (num_i < num);
418                     if (position == positions[num_i])
419                     {
420                         sr[num_i].sysno = psysno;
421                         yaz_log (LOG_DEBUG, "got pos=%d (unsorted)", position);
422                         sr[num_i].score = -1;
423                         num_i++;
424                     }
425                 }
426             }
427             rset_close (rset, rfd);
428         }
429     }
430     return sr;
431 }
432
433 void zebraPosSetDestroy (ZebraHandle zh, ZebraPosSet records, int num)
434 {
435     xfree (records);
436 }
437
438 struct sortKeyInfo {
439     int relation;
440     int attrUse;
441     int numerical;
442 };
443
444 void resultSetInsertSort (ZebraHandle zh, ZebraSet sset,
445                           struct sortKeyInfo *criteria, int num_criteria,
446                           zint sysno)
447 {
448     struct zset_sort_entry this_entry;
449     struct zset_sort_entry *new_entry = NULL;
450     struct zset_sort_info *sort_info = sset->sort_info;
451     int i, j;
452
453     sortIdx_sysno (zh->reg->sortIdx, sysno);
454     for (i = 0; i<num_criteria; i++)
455     {
456         sortIdx_type (zh->reg->sortIdx, criteria[i].attrUse);
457         sortIdx_read (zh->reg->sortIdx, this_entry.buf[i]);
458     }
459     i = sort_info->num_entries;
460     while (--i >= 0)
461     {
462         int rel = 0;
463         for (j = 0; j<num_criteria; j++)
464         {
465             if (criteria[j].numerical)
466             {
467                 double diff = atof(this_entry.buf[j]) -
468                               atof(sort_info->entries[i]->buf[j]);
469                 rel = 0;
470                 if (diff > 0.0)
471                     rel = 1;
472                 else if (diff < 0.0)
473                     rel = -1;
474             }
475             else
476             {
477                 rel = memcmp (this_entry.buf[j], sort_info->entries[i]->buf[j],
478                           SORT_IDX_ENTRYSIZE);
479             }
480             if (rel)
481                 break;
482         }       
483         if (!rel)
484             break;
485         if (criteria[j].relation == 'A')
486         {
487             if (rel > 0)
488                 break;
489         }
490         else if (criteria[j].relation == 'D')
491         {
492             if (rel < 0)
493                 break;
494         }
495     }
496     ++i;
497     j = sort_info->max_entries;
498     if (i == j)
499         return;
500
501     if (sort_info->num_entries == j)
502         --j;
503     else
504         j = (sort_info->num_entries)++;
505     new_entry = sort_info->entries[j];
506     while (j != i)
507     {
508         sort_info->entries[j] = sort_info->entries[j-1];
509         --j;
510     }
511     sort_info->entries[i] = new_entry;
512     assert (new_entry);
513     for (i = 0; i<num_criteria; i++)
514         memcpy (new_entry->buf[i], this_entry.buf[i], SORT_IDX_ENTRYSIZE);
515     new_entry->sysno = sysno;
516     new_entry->score = -1;
517 }
518
519 void resultSetInsertRank (ZebraHandle zh, struct zset_sort_info *sort_info,
520                           zint sysno, int score, int relation)
521 {
522     struct zset_sort_entry *new_entry = NULL;
523     int i, j;
524
525     i = sort_info->num_entries;
526     while (--i >= 0)
527     {
528         int rel = 0;
529
530         rel = score - sort_info->entries[i]->score;
531
532         if (relation == 'D')
533         {
534             if (rel >= 0)
535                 break;
536         }
537         else if (relation == 'A')
538         {
539             if (rel <= 0)
540                 break;
541         }
542     }
543     ++i;
544     j = sort_info->max_entries;
545     if (i == j)
546         return;
547
548     if (sort_info->num_entries == j)
549         --j;
550     else
551         j = (sort_info->num_entries)++;
552     
553     new_entry = sort_info->entries[j];
554     while (j != i)
555     {
556         sort_info->entries[j] = sort_info->entries[j-1];
557         --j;
558     }
559     sort_info->entries[i] = new_entry;
560     assert (new_entry);
561     new_entry->sysno = sysno;
562     new_entry->score = score;
563 }
564
565 void resultSetSort (ZebraHandle zh, NMEM nmem,
566                     int num_input_setnames, const char **input_setnames,
567                     const char *output_setname,
568                     Z_SortKeySpecList *sort_sequence, int *sort_status)
569 {
570     ZebraSet sset;
571     RSET rset;
572
573     if (num_input_setnames == 0)
574     {
575         zh->errCode = 208;
576         return ;
577     }
578     if (num_input_setnames > 1)
579     {
580         zh->errCode = 230;
581         return;
582     }
583     yaz_log (LOG_DEBUG, "result set sort input=%s output=%s",
584           *input_setnames, output_setname);
585     sset = resultSetGet (zh, input_setnames[0]);
586     if (!sset)
587     {
588         zh->errCode = 30;
589         zh->errString = nmem_strdup (nmem, input_setnames[0]);
590         return;
591     }
592     if (!(rset = sset->rset))
593     {
594         zh->errCode = 30;
595         zh->errString = nmem_strdup (nmem, input_setnames[0]);
596         return;
597     }
598     if (strcmp (output_setname, input_setnames[0]))
599     {
600         rset = rset_dup (rset);
601         sset = resultSetAdd (zh, output_setname, 1);
602         sset->rset = rset;
603     }
604     resultSetSortSingle (zh, nmem, sset, rset, sort_sequence, sort_status);
605 }
606
607 void resultSetSortSingle (ZebraHandle zh, NMEM nmem,
608                           ZebraSet sset, RSET rset,
609                           Z_SortKeySpecList *sort_sequence, int *sort_status)
610 {
611     int i;
612     zint psysno = 0;
613     struct it_key key;
614     struct sortKeyInfo sort_criteria[3];
615     int num_criteria;
616     int term_index;
617     RSFD rfd;
618
619     yaz_log (LOG_LOG, "resultSetSortSingle start");
620     sset->sort_info->num_entries = 0;
621
622     sset->hits = 0;
623     num_criteria = sort_sequence->num_specs;
624     if (num_criteria > 3)
625         num_criteria = 3;
626     for (i = 0; i < num_criteria; i++)
627     {
628         Z_SortKeySpec *sks = sort_sequence->specs[i];
629         Z_SortKey *sk;
630
631         if (*sks->sortRelation == Z_SortKeySpec_ascending)
632             sort_criteria[i].relation = 'A';
633         else if (*sks->sortRelation == Z_SortKeySpec_descending)
634             sort_criteria[i].relation = 'D';
635         else
636         {
637             zh->errCode = 214;
638             return;
639         }
640         if (sks->sortElement->which == Z_SortElement_databaseSpecific)
641         {
642             zh->errCode = 210;
643             return;
644         }
645         else if (sks->sortElement->which != Z_SortElement_generic)
646         {
647             zh->errCode = 237;
648             return;
649         }       
650         sk = sks->sortElement->u.generic;
651         switch (sk->which)
652         {
653         case Z_SortKey_sortField:
654             yaz_log (LOG_DEBUG, "Sort: key %d is of type sortField", i+1);
655             zh->errCode = 207;
656             return;
657         case Z_SortKey_elementSpec:
658             yaz_log (LOG_DEBUG, "Sort: key %d is of type elementSpec", i+1);
659             zh->errCode = 207;
660             return;
661         case Z_SortKey_sortAttributes:
662             yaz_log (LOG_DEBUG, "Sort: key %d is of type sortAttributes", i+1);
663             sort_criteria[i].attrUse =
664                 zebra_maps_sort (zh->reg->zebra_maps,
665                                  sk->u.sortAttributes,
666                                  &sort_criteria[i].numerical);
667             yaz_log (LOG_DEBUG, "use value = %d", sort_criteria[i].attrUse);
668             if (sort_criteria[i].attrUse == -1)
669             {
670                 zh->errCode = 116;
671                 return;
672             }
673             if (sortIdx_type (zh->reg->sortIdx, sort_criteria[i].attrUse))
674             {
675                 zh->errCode = 207;
676                 return;
677             }
678             break;
679         }
680     }
681     rfd = rset_open (rset, RSETF_READ);
682     while (rset_read (rset, rfd, &key, &term_index))
683     {
684 #if IT_KEY_NEW
685         zint this_sys = key.mem[0];
686 #else
687         zint this_sys = key.sysno;
688 #endif
689         if (this_sys != psysno)
690         {
691             (sset->hits)++;
692             psysno = this_sys;
693             resultSetInsertSort (zh, sset,
694                                  sort_criteria, num_criteria, psysno);
695         }
696     }
697     rset_close (rset, rfd);
698
699     for (i = 0; i < rset->no_rset_terms; i++)
700         yaz_log (LOG_LOG, "term=\"%s\" nn=" ZINT_FORMAT " type=%s count=" ZINT_FORMAT,
701                  rset->rset_terms[i]->name,
702                  rset->rset_terms[i]->nn,
703                  rset->rset_terms[i]->flags,
704                  rset->rset_terms[i]->count);
705
706     *sort_status = Z_SortResponse_success;
707     yaz_log (LOG_LOG, "resultSetSortSingle end");
708 }
709
710 RSET resultSetRef (ZebraHandle zh, const char *resultSetId)
711 {
712     ZebraSet s;
713
714     if ((s = resultSetGet (zh, resultSetId)))
715         return s->rset;
716     return NULL;
717 }
718
719 void resultSetRank (ZebraHandle zh, ZebraSet zebraSet, RSET rset)
720 {
721     zint kno = 0;
722     struct it_key key;
723     RSFD rfd;
724     int term_index, i;
725     ZebraRankClass rank_class;
726     struct rank_control *rc;
727     struct zset_sort_info *sort_info;
728     const char *rank_handler_name = res_get_def(zh->res, "rank", "rank-1");
729     double cur,tot; 
730     zint est=-2; /* -2 not done, -1 can't do, >0 actual estimate*/
731     zint esthits;
732
733     sort_info = zebraSet->sort_info;
734     sort_info->num_entries = 0;
735     zebraSet->hits = 0;
736     rfd = rset_open (rset, RSETF_READ);
737
738     yaz_log (LOG_LOG, "resultSetRank");
739
740     rank_class = zebraRankLookup (zh, rank_handler_name);
741     if (!rank_class)
742     {
743         yaz_log (LOG_WARN, "No such rank handler: %s", rank_handler_name);
744         return;
745     }
746     rc = rank_class->control;
747
748     if (rset_read (rset, rfd, &key, &term_index))
749     {
750 #if IT_KEY_NEW
751         zint psysno = key.mem[0];
752 #else
753         zint psysno = key.sysno;
754 #endif
755         int score;
756         void *handle =
757             (*rc->begin) (zh->reg, rank_class->class_handle, rset);
758         (zebraSet->hits)++;
759     esthits=atoi(res_get_def(zh->res,"estimatehits","0"));
760     if (!esthits) est=-1; /* can not do */
761         do
762         {
763 #if IT_KEY_NEW
764             zint this_sys = key.mem[0];
765 #else
766             zint this_sys = key.sysno;
767 #endif
768             kno++;
769             if (this_sys != psysno)
770             {
771                 score = (*rc->calc) (handle, psysno);
772
773                 resultSetInsertRank (zh, sort_info, psysno, score, 'A');
774                 (zebraSet->hits)++;
775                 psysno = this_sys;
776             }
777             (*rc->add) (handle, this_sys, term_index);
778         if ( (est==-2) && (zebraSet->hits==esthits))
779         { /* time to estimate the hits */
780             float f;
781             rset_pos(rset,rfd,&cur,&tot); 
782             if (tot>0) {
783                 f=1.0*cur/tot;
784                 est=(zint)(0.5+zebraSet->hits/f);
785                 /* FIXME - round the guess to 3 digits */
786                 logf(LOG_LOG, "Estimating hits (%s) "
787                               "%0.1f->%d"
788                               "; %0.1f->"ZINT_FORMAT,
789                               rset->control->desc,
790                               cur, zebraSet->hits,
791                               tot,est);
792                 zebraSet->hits=est;
793             }
794         }
795         }
796         while (rset_read (rset, rfd, &key, &term_index) && (est<0) );
797            
798         score = (*rc->calc) (handle, psysno);
799         resultSetInsertRank (zh, sort_info, psysno, score, 'A');
800         (*rc->end) (zh->reg, handle);
801     }
802     rset_close (rset, rfd);
803
804     for (i = 0; i < rset->no_rset_terms; i++)
805         yaz_log (LOG_LOG, "term=\"%s\" nn=" ZINT_FORMAT " type=%s count=" ZINT_FORMAT,
806                  rset->rset_terms[i]->name,
807                  rset->rset_terms[i]->nn,
808                  rset->rset_terms[i]->flags,
809                  rset->rset_terms[i]->count);
810     
811     yaz_log (LOG_LOG, ZINT_FORMAT " keys, %d distinct sysnos", 
812                     kno, zebraSet->hits);
813 }
814
815 ZebraRankClass zebraRankLookup (ZebraHandle zh, const char *name)
816 {
817     ZebraRankClass p = zh->reg->rank_classes;
818     while (p && strcmp (p->control->name, name))
819         p = p->next;
820     if (p && !p->init_flag)
821     {
822         if (p->control->create)
823             p->class_handle = (*p->control->create)(zh);
824         p->init_flag = 1;
825     }
826     return p;
827 }
828
829 void zebraRankInstall (struct zebra_register *reg, struct rank_control *ctrl)
830 {
831     ZebraRankClass p = (ZebraRankClass) xmalloc (sizeof(*p));
832     p->control = (struct rank_control *) xmalloc (sizeof(*p->control));
833     memcpy (p->control, ctrl, sizeof(*p->control));
834     p->control->name = xstrdup (ctrl->name);
835     p->init_flag = 0;
836     p->next = reg->rank_classes;
837     reg->rank_classes = p;
838 }
839
840 void zebraRankDestroy (struct zebra_register *reg)
841 {
842     ZebraRankClass p = reg->rank_classes;
843     while (p)
844     {
845         ZebraRankClass p_next = p->next;
846         if (p->init_flag && p->control->destroy)
847             (*p->control->destroy)(reg, p->class_handle);
848         xfree (p->control->name);
849         xfree (p->control);
850         xfree (p);
851         p = p_next;
852     }
853     reg->rank_classes = NULL;
854 }