IDZEBRA  2.1.2
rset.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, 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 
30 static int log_level = 0;
31 static 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 
69 static 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 
98 void rset_close(RSFD rfd)
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 
291 void 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 
301 struct ord_list *ord_list_create(NMEM nmem)
302 {
303  return 0;
304 }
305 
306 struct 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 
315 struct 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 
323 void 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 }
340 TERMID 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 
371 int 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 
396 int 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 &&
403  rfd->counted_items >= rset->hits_limit)
404  {
405  assert (rset->control->f_forward != rset_default_forward);
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 
421 void rset_visit(RSET rset, int level)
422 {
423  int i;
424  yaz_log(YLOG_LOG, "%*s%c " ZINT_FORMAT, level, "",
425  rset->hits_approx ? '~' : '=',
426  rset->hits_count);
427  for (i = 0; i<rset->no_children; i++)
428  rset_visit(rset->children[i], level+1);
429 }
430 
431 int 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 
struct ord_list * ord_list_dup(NMEM nmem, struct ord_list *list)
Definition: rset.c:315
zint hits_limit
Definition: rset.h:62
int type
Definition: rset.h:53
RSFD next
Definition: rset.h:76
void * rankpriv
Definition: rset.h:61
int(* f_read)(RSFD rfd, void *buf, TERMID *term)
Definition: rset.h:107
zint hits_limit
Definition: rset.h:163
static void rset_close_int(RSET rs, RSFD rfd)
Definition: rset.c:69
void(* inc)(struct rset_key_control *kc)
Definition: rset.h:137
TERMID term
Definition: rset.h:160
struct rset_key_control * keycontrol
Definition: rset.h:153
struct rset rset
void rset_close(RSFD rfd)
Closes a result set RFD handle.
Definition: rset.c:98
int rfd_is_last(RSFD rfd)
Test for last use of RFD.
Definition: rset.c:242
zint hits_round
Definition: rset.h:165
int ord
Definition: rset.h:36
int no_children
Definition: rset.h:161
RSFD rfd_create_base(RSET rs)
Common constuctor for RFDs.
Definition: rset.c:43
int scope
Definition: rset.h:159
zint rset_count(RSET rs)
Estimates hit count for result set.
Definition: rset.c:272
int rset_no_write(RSFD rfd, const void *buf)
Definition: rset.c:431
int hits_approx
Definition: rset.h:166
int key_size
Definition: rset.h:128
RSFD free_list
Definition: rset.h:157
#define rset_open(rs, wflag)
Definition: rset.h:202
void(* f_close)(RSFD rfd)
Definition: rset.h:102
const struct rset_control * control
Definition: rset.h:152
int refcount
Definition: rset.h:154
RSET rset
Definition: rset.h:74
void ord_list_print(struct ord_list *list)
Definition: rset.c:323
char * flags
Definition: rset.h:52
const char * scope
Definition: tstlockscope.c:40
int rset_default_forward(RSFD rfd, void *buf, TERMID *term, const void *untilbuf)
Definition: rset.c:396
void rset_visit(RSET rset, int level)
Definition: rset.c:421
#define rset_read(rfd, buf, term)
Definition: rset.h:217
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
int(* cmp)(const void *p1, const void *p2)
Definition: rset.h:131
struct ord_list * ol
Definition: rset.h:64
void * priv
Definition: rset.h:155
void rset_get_one_term(RSET ct, TERMID *terms, int maxterms, int *curterm)
is a getterms function for those that don&#39;t have any
Definition: rset.c:291
struct ord_list * ord_list_create(NMEM nmem)
Definition: rset.c:301
zint counted_items
Definition: rset.h:77
RSET * children
Definition: rset.h:162
zint hits_count
Definition: rset.h:164
void rset_delete(RSET rs)
Destructor RSETs.
Definition: rset.c:218
char * desc
Definition: rset.h:92
int rset_default_read(RSFD rfd, void *buf, TERMID *term)
Definition: rset.c:371
void(* dec)(struct rset_key_control *kc)
Definition: rset.h:138
struct rset * RSET
Definition: rset.h:33
struct ord_list * next
Definition: rset.h:37
char * ref_id
Definition: rset.h:63
int reg_type
Definition: rset.h:59
struct ord_list * ord_list_append(NMEM nmem, struct ord_list *list, int ord)
Definition: rset.c:306
RSFD use_list
Definition: rset.h:158
RSET rset_dup(RSET rs)
Duplicate an RSET.
Definition: rset.c:255
long zint
Zebra integer.
Definition: util.h:66
NMEM nmem
Definition: rset.h:156
char * counted_buf
Definition: rset.h:78
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
static int log_level_initialized
Definition: rset.c:31
int(* f_forward)(RSFD rfd, void *buf, TERMID *term, const void *untilbuf)
Definition: rset.h:104
Definition: rset.h:150
Definition: rset.h:73
RSET rset
Definition: rset.h:60
void(* f_delete)(RSET ct)
Definition: rset.h:94
void * priv
Definition: rset.h:75
Definition: rset.h:50
Definition: rset.h:35
#define rset_pos(rfd, cur, tot)
Definition: rset.h:213
struct rset_term * TERMID
Definition: rset.h:67
void rset_set_hits_limit(RSET rs, zint l)
Definition: rset.c:88
void key_logdump_txt(int logmask, const void *p, const char *txt)
Definition: it_key.c:37
char * name
Definition: rset.h:51
#define ZINT_FORMAT
Definition: util.h:72
static int log_level
Definition: rset.c:30