41d39a7feb2cc7316a273be95277b709856d0ec1
[idzebra-moved-to-github.git] / rset / rset.c
1 /* $Id: rset.c,v 1.43 2005-01-17 01:21:44 adam Exp $
2    Copyright (C) 1995-2005
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 #include <stdio.h>
24 #include <string.h>
25 #include <zebrautl.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 /** \fn rfd_create_base(RSET rs)
34  *
35  * creates an rfd. Either allocates a new one, in which case the priv 
36  * pointer is null, and will have to be filled in, or picks up one 
37  * from the freelist, in which case the priv is already allocated,
38  * and presumably everything that hangs from it as well 
39  */
40 RSFD rfd_create_base(RSET rs)
41 {
42     RSFD rnew = rs->free_list;
43
44     if (rnew) 
45     {
46         rs->free_list = rnew->next;
47         assert(rnew->rset==rs);
48         yaz_log(log_level, "rfd_create_base (fl): rfd=%p rs=%p fl=%p priv=%p", 
49                 rnew, rs, rs->free_list, rnew->priv); 
50     } 
51     else
52     {
53         rnew = nmem_malloc(rs->nmem, sizeof(*rnew));
54         rnew->priv = NULL;
55         rnew->rset = rs;
56         yaz_log(log_level, "rfd_create_base (new): rfd=%p rs=%p fl=%p priv=%p", 
57                 rnew, rs, rs->free_list, rnew->priv); 
58     }
59     rnew->next = rs->use_list;
60     rs->use_list = rnew;
61     return rnew;
62 }
63
64 /** \fn rfd_delete_base
65  *
66  * puts an rfd into the freelist of the rset. Only when the rset gets
67  * deleted, will all the nmem disappear */
68 void rfd_delete_base(RSFD rfd) 
69 {
70     RSFD *pfd;
71     RSET rs = rfd->rset;
72     yaz_log(log_level, "rfd_delete_base: rfd=%p rs=%p priv=%p fl=%p",
73             rfd, rs, rfd->priv, rs->free_list); 
74     for (pfd = &rs->use_list; *pfd; pfd = &(*pfd)->next)
75         if (*pfd == rfd)
76         {
77             *pfd = (*pfd)->next;
78             rfd->next = rs->free_list;
79             rs->free_list = rfd;
80             return;
81         }
82     yaz_log(YLOG_WARN, "rset_close handle not found. type=%s",
83             rs->control->desc);
84 }
85
86 RSET rset_create_base(const struct rset_control *sel, 
87                       NMEM nmem, const struct key_control *kcontrol,
88                       int scope, TERMID term)
89 {
90     RSET rnew;
91     NMEM M;
92     /* assert(nmem); */ /* can not yet be used, api/t4 fails */
93     if (!log_level_initialized) 
94     {
95         log_level = yaz_log_module_level("rset");
96         log_level_initialized = 1;
97     }
98
99     if (nmem) 
100         M = nmem;
101     else
102         M = nmem_create();
103     rnew = (RSET) nmem_malloc(M, sizeof(*rnew));
104     yaz_log(log_level, "rs_create(%s) rs=%p (nm=%p)", sel->desc, rnew, nmem); 
105     rnew->nmem = M;
106     if (nmem)
107         rnew->my_nmem = 0;
108     else 
109         rnew->my_nmem = 1;
110     rnew->control = sel;
111     rnew->count = 1; /* refcount! */
112     rnew->priv = 0;
113     rnew->free_list = NULL;
114     rnew->use_list = NULL;
115     rnew->keycontrol = kcontrol;
116     rnew->scope = scope;
117     rnew->term = term;
118     if (term)
119         term->rset = rnew;
120     return rnew;
121 }
122
123 void rset_delete (RSET rs)
124 {
125     (rs->count)--;
126     yaz_log(log_level, "rs_delete(%s), rs=%p, count=%d",
127             rs->control->desc, rs, rs->count); 
128     if (!rs->count)
129     {
130         if (rs->use_list)
131             yaz_log(YLOG_WARN, "rs_delete(%s) still has RFDs in use",
132                     rs->control->desc);
133         (*rs->control->f_delete)(rs);
134         if (rs->my_nmem)
135             nmem_destroy(rs->nmem);
136     }
137 }
138
139 int rfd_is_last(RSFD rfd)
140 {
141     if (rfd->rset->use_list == rfd && rfd->next == 0)
142         return 1;
143     return 0;
144 }
145
146 RSET rset_dup (RSET rs)
147 {
148     (rs->count)++;
149     yaz_log(log_level, "rs_dup(%s), rs=%p, count=%d",
150             rs->control->desc, rs, rs->count); 
151     return rs;
152 }
153
154 int rset_default_forward(RSFD rfd, void *buf, TERMID *term,
155                          const void *untilbuf)
156 {
157     int more = 1;
158     int cmp = rfd->rset->scope;
159     if (log_level)
160     {
161         yaz_log (log_level, "rset_default_forward starting '%s' (ct=%p rfd=%p)",
162                     rfd->rset->control->desc, rfd->rset, rfd);
163         /* key_logdump(log_level, untilbuf); */
164     }
165     while (cmp>=rfd->rset->scope && more)
166     {
167         if (log_level)  /* time-critical, check first */
168             yaz_log(log_level, "rset_default_forward looping m=%d c=%d",
169                     more, cmp);
170         more = rset_read(rfd, buf, term);
171         if (more)
172             cmp = (rfd->rset->keycontrol->cmp)(untilbuf, buf);
173     }
174     if (log_level)
175         yaz_log (log_level, "rset_default_forward exiting m=%d c=%d",
176                  more, cmp);
177
178     return more;
179 }
180
181 /** 
182  * rset_count uses rset_pos to get the total and returns that.
183  * This is ok for rsisamb/c/s, and for some other rsets, but in case of
184  * booleans etc it will give bad estimate, as nothing has been read
185  * from that rset
186  */
187 zint rset_count(RSET rs)
188 {
189     double cur, tot;
190     RSFD rfd = rset_open(rs, 0);
191     rset_pos(rfd, &cur, &tot);
192     rset_close(rfd);
193     return (zint) tot;
194 }
195
196
197 /** rset_get_no_terms is a getterms function for those that don't have any */
198 void rset_get_no_terms(RSET ct, TERMID *terms, int maxterms, int *curterm)
199 {
200     return;
201 }
202
203 /* rset_get_one_term gets that one term from an rset. Used by rsisamX */
204 void rset_get_one_term(RSET ct,TERMID *terms,int maxterms,int *curterm)
205 {
206     if (ct->term)
207     {
208         if (*curterm < maxterms)
209             terms[*curterm] = ct->term;
210         (*curterm)++;
211     }
212 }
213
214
215 TERMID rset_term_create (const char *name, int length, const char *flags,
216                                     int type, NMEM nmem)
217
218 {
219     TERMID t;
220     yaz_log (log_level, "term_create '%s' %d f=%s type=%d nmem=%p",
221             name, length, flags, type, nmem);
222     t= (TERMID) nmem_malloc(nmem, sizeof(*t));
223     if (!name)
224         t->name = NULL;
225     else if (length == -1)
226         t->name = nmem_strdup(nmem, name);
227     else
228     {
229         t->name = (char*) nmem_malloc(nmem, length+1);
230         memcpy (t->name, name, length);
231         t->name[length] = '\0';
232     }
233     if (!flags)
234         t->flags = NULL;
235     else
236         t->flags = nmem_strdup(nmem, flags);
237     t->type = type;
238     t->rankpriv = 0;
239     t->rset = 0;
240     return t;
241 }