IDZEBRA 2.2.8
rset.c
Go to the documentation of this file.
1/* This file is part of the Zebra server.
2 Copyright (C) Index Data
3
4Zebra is free software; you can redistribute it and/or modify it under
5the terms of the GNU General Public License as published by the Free
6Software Foundation; either version 2, or (at your option) any later
7version.
8
9Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18*/
19
20#if HAVE_CONFIG_H
21#include <config.h>
22#endif
23#include <stdio.h>
24#include <string.h>
25#include <idzebra/util.h>
26#include <assert.h>
27#include <yaz/nmem.h>
28#include <rset.h>
29
30static int log_level = 0;
31static int log_level_initialized = 0;
32
33
44{
45 RSFD rnew = rs->free_list;
46
47 if (rnew)
48 {
49 rs->free_list = rnew->next;
50 assert(rnew->rset==rs);
51 yaz_log(log_level, "rfd_create_base (fl): rfd=%p rs=%p fl=%p priv=%p",
52 rnew, rs, rs->free_list, rnew->priv);
53 }
54 else
55 {
56 rnew = nmem_malloc(rs->nmem, sizeof(*rnew));
57 rnew->counted_buf = nmem_malloc(rs->nmem, rs->keycontrol->key_size);
58 rnew->priv = 0;
59 rnew->rset = rs;
60 yaz_log(log_level, "rfd_create_base (new): rfd=%p rs=%p fl=%p priv=%p",
61 rnew, rs, rs->free_list, rnew->priv);
62 }
63 rnew->next = rs->use_list;
64 rs->use_list = rnew;
65 rnew->counted_items = 0;
66 return rnew;
67}
68
69static void rset_close_int(RSET rs, RSFD rfd)
70{
71 RSFD *pfd;
72 (*rs->control->f_close)(rfd);
73
74 yaz_log(log_level, "rfd_delete_base: rfd=%p rs=%p priv=%p fl=%p",
75 rfd, rs, rfd->priv, rs->free_list);
76 for (pfd = &rs->use_list; *pfd; pfd = &(*pfd)->next)
77 if (*pfd == rfd)
78 {
79 *pfd = (*pfd)->next;
80 rfd->next = rs->free_list;
81 rs->free_list = rfd;
82 return;
83 }
84 yaz_log(YLOG_WARN, "rset_close handle not found. type=%s",
85 rs->control->desc);
86}
87
89{
90 yaz_log(log_level, "rset_set_hits_limit %p l=" ZINT_FORMAT, rs, l);
91 rs->hits_limit = l;
92}
93
99{
100 RSET rs = rfd->rset;
101
102 if (rs->hits_count == 0)
103 {
104 TERMID termid;
105 char buf[100];
106
107 while (rfd->counted_items <= rs->hits_limit
108 && rset_default_read(rfd, buf, &termid))
109 ;
110
111 rs->hits_count = rfd->counted_items;
112 yaz_log(log_level, "rset_close rset=%p hits_count=" ZINT_FORMAT
113 " hits_limit=" ZINT_FORMAT,
114 rs, rs->hits_count, rs->hits_limit);
115 rs->hits_approx = 0;
116 if (rs->hits_count > rs->hits_limit && rs->hits_limit > 0)
117 {
118 double cur, tot;
119 zint est;
120 rset_pos(rfd, &cur, &tot);
121 if (tot > 0) {
122 int i;
123 double ratio = cur/tot;
124 est = (zint)(0.5 + rs->hits_count / ratio);
125 yaz_log(log_level, "Estimating hits (%s) "
126 "%0.1f->" ZINT_FORMAT
127 "; %0.1f->" ZINT_FORMAT,
128 rs->control->desc,
129 cur, rs->hits_count,
130 tot, est);
131 i = 0; /* round to significant digits */
132 while (est > rs->hits_round) {
133 est /= 10;
134 i++;
135 }
136 while (i--)
137 est *= 10;
138 rs->hits_count = est;
139 rs->hits_approx = 1;
140 }
141 }
142 yaz_log(log_level, "rset_close(%s) p=%p count=" ZINT_FORMAT,
143 rs->control->desc, rs,
144 rs->hits_count);
145 }
146 rset_close_int(rs, rfd);
147}
148
165 NMEM nmem, struct rset_key_control *kcontrol,
166 int scope, TERMID term,
167 int no_children, RSET *children)
168{
169 RSET rset;
170 assert(nmem);
172 {
173 log_level = yaz_log_module_level("rset");
175 }
176
177 rset = (RSET) nmem_malloc(nmem, sizeof(*rset));
178 yaz_log(log_level, "rs_create(%s) rs=%p (nm=%p)", sel->desc, rset, nmem);
179 yaz_log(log_level, " ref_id=%s",
180 (term && term->ref_id ? term->ref_id : "null"));
181 rset->nmem = nmem;
182 rset->control = sel;
183 rset->refcount = 1;
184 rset->priv = 0;
185 rset->free_list = NULL;
186 rset->use_list = NULL;
187 rset->hits_count = 0;
188 rset->hits_limit = 0;
189 rset->hits_round = 1000;
190 rset->keycontrol = kcontrol;
191
192 (*kcontrol->inc)(kcontrol);
193 rset->scope = scope;
194 rset->term = term;
195 if (term)
196 {
197 term->rset = rset;
198 rset->hits_limit = term->hits_limit;
199 }
200 rset->no_children = no_children;
201 rset->children = 0;
202 if (no_children)
203 {
204 rset->children = (RSET*)
205 nmem_malloc(rset->nmem, no_children*sizeof(RSET *));
206 memcpy(rset->children, children, no_children*sizeof(RSET *));
207 }
208 return rset;
209}
210
219{
220 (rs->refcount)--;
221 yaz_log(log_level, "rs_delete(%s), rs=%p, refcount=%d",
222 rs->control->desc, rs, rs->refcount);
223 if (!rs->refcount)
224 {
225 int i;
226 if (rs->use_list)
227 yaz_log(YLOG_WARN, "rs_delete(%s) still has RFDs in use",
228 rs->control->desc);
229 for (i = 0; i<rs->no_children; i++)
230 rset_delete(rs->children[i]);
231 (*rs->control->f_delete)(rs);
232 (*rs->keycontrol->dec)(rs->keycontrol);
233 }
234}
235
243{
244 if (rfd->rset->use_list == rfd && rfd->next == 0)
245 return 1;
246 return 0;
247}
248
256{
257 (rs->refcount)++;
258 yaz_log(log_level, "rs_dup(%s), rs=%p, refcount=%d",
259 rs->control->desc, rs, rs->refcount);
260 return rs;
261}
262
273{
274 double cur, tot;
275 RSFD rfd = rset_open(rs, 0);
276 rset_pos(rfd, &cur, &tot);
277 rset_close_int(rs, rfd);
278 return (zint) tot;
279}
280
291void rset_get_one_term(RSET ct, TERMID *terms, int maxterms, int *curterm)
292{
293 if (ct->term)
294 {
295 if (*curterm < maxterms)
296 terms[*curterm] = ct->term;
297 (*curterm)++;
298 }
299}
300
301struct ord_list *ord_list_create(NMEM nmem)
302{
303 return 0;
304}
305
306struct ord_list *ord_list_append(NMEM nmem, struct ord_list *list,
307 int ord)
308{
309 struct ord_list *n = nmem_malloc(nmem, sizeof(*n));
310 n->ord = ord;
311 n->next = list;
312 return n;
313}
314
315struct ord_list *ord_list_dup(NMEM nmem, struct ord_list *list)
316{
317 struct ord_list *n = ord_list_create(nmem);
318 for (; list; list = list->next)
319 n = ord_list_append(nmem, n, list->ord);
320 return n;
321}
322
323void ord_list_print(struct ord_list *list)
324{
325 for (; list; list = list->next)
326 yaz_log(YLOG_LOG, "ord_list %d", list->ord);
327}
340TERMID rset_term_create(const char *name, int length, const char *flags,
341 int type, NMEM nmem, struct ord_list *ol,
342 int reg_type,
343 zint hits_limit, const char *ref_id)
344
345{
346 TERMID t = (TERMID) nmem_malloc(nmem, sizeof(*t));
347
348 if (!name)
349 name = "";
350 if (length == -1)
351 t->name = nmem_strdup(nmem, name);
352 else
353 t->name = nmem_strdupn(nmem, name, length);
354 if (!ref_id)
355 t->ref_id = 0;
356 else
357 t->ref_id = nmem_strdup(nmem, ref_id);
358 if (!flags)
359 t->flags = NULL;
360 else
361 t->flags = nmem_strdup(nmem, flags);
362 t->hits_limit = hits_limit;
363 t->type = type;
364 t->reg_type = reg_type;
365 t->rankpriv = 0;
366 t->rset = 0;
367 t->ol = ord_list_dup(nmem, ol);
368 return t;
369}
370
371int rset_default_read(RSFD rfd, void *buf, TERMID *term)
372{
373 RSET rset = rfd->rset;
374 int rc = (*rset->control->f_read)(rfd, buf, term);
375 if (rc > 0)
376 {
377 int got_scope;
378 if (rfd->counted_items == 0)
379 got_scope = rset->scope+1;
380 else
381 got_scope = rset->keycontrol->cmp(buf, rfd->counted_buf);
382
383#if 0
384 key_logdump_txt(YLOG_LOG, buf, "rset_default_read");
385 yaz_log(YLOG_LOG, "rset_scope=%d got_scope=%d", rset->scope, got_scope);
386#endif
387 if (got_scope > rset->scope)
388 {
389 memcpy(rfd->counted_buf, buf, rset->keycontrol->key_size);
390 rfd->counted_items++;
391 }
392 }
393 return rc;
394}
395
396int rset_default_forward(RSFD rfd, void *buf, TERMID *term,
397 const void *untilbuf)
398{
399 RSET rset = rfd->rset;
400 int more;
401
402 if (rset->control->f_forward &&
404 {
406 return rset->control->f_forward(rfd, buf, term, untilbuf);
407 }
408
409 while ((more = rset_read(rfd, buf, term)) > 0)
410 {
411 if ((rfd->rset->keycontrol->cmp)(untilbuf, buf) < rset->scope)
412 break;
413 }
414 if (log_level)
415 yaz_log(log_level, "rset_default_forward exiting rfd=%p scope=%d m=%d c=%d",
416 rfd, rset->scope, more, rset->scope);
417
418 return more;
419}
420
421void rset_visit(RSET rset, int level)
422{
423 int i;
424 yaz_log(YLOG_LOG, "%*s%c " ZINT_FORMAT, level, "",
425 rset->hits_approx ? '~' : '=',
427 for (i = 0; i<rset->no_children; i++)
428 rset_visit(rset->children[i], level+1);
429}
430
431int rset_no_write(RSFD rfd, const void *buf)
432{
433 yaz_log(YLOG_FATAL, "%s set type is read-only", rfd->rset->control->desc);
434 return -1;
435}
436
437/*
438 * Local variables:
439 * c-basic-offset: 4
440 * c-file-style: "Stroustrup"
441 * indent-tabs-mode: nil
442 * End:
443 * vim: shiftwidth=4 tabstop=8 expandtab
444 */
445
void key_logdump_txt(int logmask, const void *p, const char *txt)
Definition it_key.c:38
int rfd_is_last(RSFD rfd)
Test for last use of RFD.
Definition rset.c:242
RSET rset_create_base(const struct rset_control *sel, NMEM nmem, struct rset_key_control *kcontrol, int scope, TERMID term, int no_children, RSET *children)
Common constuctor for RSETs.
Definition rset.c:164
void rset_delete(RSET rs)
Destructor RSETs.
Definition rset.c:218
void rset_set_hits_limit(RSET rs, zint l)
Definition rset.c:88
void ord_list_print(struct ord_list *list)
Definition rset.c:323
static void rset_close_int(RSET rs, RSFD rfd)
Definition rset.c:69
int rset_default_read(RSFD rfd, void *buf, TERMID *term)
Definition rset.c:371
RSET rset_dup(RSET rs)
Duplicate an RSET.
Definition rset.c:255
void rset_visit(RSET rset, int level)
Definition rset.c:421
int rset_default_forward(RSFD rfd, void *buf, TERMID *term, const void *untilbuf)
Definition rset.c:396
int rset_no_write(RSFD rfd, const void *buf)
Definition rset.c:431
struct ord_list * ord_list_create(NMEM nmem)
Definition rset.c:301
RSFD rfd_create_base(RSET rs)
Common constuctor for RFDs.
Definition rset.c:43
zint rset_count(RSET rs)
Estimates hit count for result set.
Definition rset.c:272
struct ord_list * ord_list_dup(NMEM nmem, struct ord_list *list)
Definition rset.c:315
TERMID rset_term_create(const char *name, int length, const char *flags, int type, NMEM nmem, struct ord_list *ol, int reg_type, zint hits_limit, const char *ref_id)
Creates a TERMID entry.
Definition rset.c:340
struct ord_list * ord_list_append(NMEM nmem, struct ord_list *list, int ord)
Definition rset.c:306
static int log_level
Definition rset.c:30
void rset_get_one_term(RSET ct, TERMID *terms, int maxterms, int *curterm)
is a getterms function for those that don't have any
Definition rset.c:291
void rset_close(RSFD rfd)
Closes a result set RFD handle.
Definition rset.c:98
static int log_level_initialized
Definition rset.c:31
#define rset_read(rfd, buf, term)
Definition rset.h:217
struct rset_term * TERMID
Definition rset.h:67
#define rset_pos(rfd, cur, tot)
Definition rset.h:213
struct rset * RSET
Definition rset.h:33
#define rset_open(rs, wflag)
Definition rset.h:202
int ord
Definition rset.h:36
struct ord_list * next
Definition rset.h:37
int(* f_read)(RSFD rfd, void *buf, TERMID *term)
Definition rset.h:107
void(* f_close)(RSFD rfd)
Definition rset.h:102
void(* f_delete)(RSET ct)
Definition rset.h:94
int(* f_forward)(RSFD rfd, void *buf, TERMID *term, const void *untilbuf)
Definition rset.h:104
char * desc
Definition rset.h:92
void(* dec)(struct rset_key_control *kc)
Definition rset.h:138
int(* cmp)(const void *p1, const void *p2)
Definition rset.h:131
void(* inc)(struct rset_key_control *kc)
Definition rset.h:137
int type
Definition rset.h:53
char * flags
Definition rset.h:52
struct ord_list * ol
Definition rset.h:64
char * ref_id
Definition rset.h:63
zint hits_limit
Definition rset.h:62
char * name
Definition rset.h:51
int reg_type
Definition rset.h:59
RSET rset
Definition rset.h:60
void * rankpriv
Definition rset.h:61
Definition rset.h:151
int hits_approx
Definition rset.h:166
zint hits_limit
Definition rset.h:163
RSFD free_list
Definition rset.h:157
TERMID term
Definition rset.h:160
zint hits_round
Definition rset.h:165
RSET * children
Definition rset.h:162
const struct rset_control * control
Definition rset.h:152
NMEM nmem
Definition rset.h:156
RSFD use_list
Definition rset.h:158
struct rset_key_control * keycontrol
Definition rset.h:153
zint hits_count
Definition rset.h:164
int scope
Definition rset.h:159
int no_children
Definition rset.h:161
void * priv
Definition rset.h:155
int refcount
Definition rset.h:154
Definition rset.h:73
zint counted_items
Definition rset.h:77
void * priv
Definition rset.h:75
RSFD next
Definition rset.h:76
RSET rset
Definition rset.h:74
char * counted_buf
Definition rset.h:78
const char * scope
long zint
Zebra integer.
Definition util.h:66
#define ZINT_FORMAT
Definition util.h:72