0b22b33d3972acd57cb478dfa6371332c0cd9335
[yaz-moved-to-github.git] / src / zoom-record-cache.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file zoom-record-cache.c
7  * \brief Implements ZOOM record caching
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <assert.h>
14 #include <string.h>
15 #include <errno.h>
16 #include "zoom-p.h"
17
18 #include <yaz/diagbib1.h>
19 #include <yaz/record_render.h>
20 #include <yaz/shptr.h>
21
22 #if SHPTR
23 YAZ_SHPTR_TYPE(WRBUF)
24 #endif
25
26 struct ZOOM_record_p {
27     ODR odr;
28 #if SHPTR
29     struct WRBUF_shptr *record_wrbuf;
30 #else
31     WRBUF wrbuf;
32 #endif
33
34     Z_NamePlusRecord *npr;
35     const char *schema;
36
37     const char *diag_uri;
38     const char *diag_message;
39     const char *diag_details;
40     const char *diag_set;
41 };
42
43 struct ZOOM_record_cache_p {
44     struct ZOOM_record_p rec;
45     char *elementSetName;
46     char *syntax;
47     char *schema;
48     int pos;
49     ZOOM_record_cache next;
50 };
51
52 static size_t record_hash(int pos)
53 {
54     if (pos < 0)
55         pos = 0;
56     return pos % RECORD_HASH_SIZE;
57 }
58
59 void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
60                            int pos,
61                            const char *syntax, const char *elementSetName,
62                            const char *schema,
63                            Z_SRW_diagnostic *diag)
64 {
65     ZOOM_record_cache rc = 0;
66
67     ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
68     ZOOM_connection_put_event(r->connection, event);
69
70     for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
71     {
72         if (pos == rc->pos
73             && yaz_strcmp_null(r->schema, rc->schema) == 0
74             && yaz_strcmp_null(elementSetName,rc->elementSetName) == 0
75             && yaz_strcmp_null(syntax, rc->syntax) == 0)
76             break;
77     }
78     if (!rc)
79     {
80         rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
81         rc->rec.odr = 0;
82 #if SHPTR
83         YAZ_SHPTR_INC(r->record_wrbuf);
84         rc->rec.record_wrbuf = r->record_wrbuf;
85 #else
86         rc->rec.wrbuf = 0;
87 #endif
88         rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
89
90         rc->syntax = odr_strdup_null(r->odr, syntax);
91
92         rc->schema = odr_strdup_null(r->odr, r->schema);
93
94         rc->pos = pos;
95         rc->next = r->record_hash[record_hash(pos)];
96         r->record_hash[record_hash(pos)] = rc;
97     }
98     rc->rec.npr = npr;
99     rc->rec.schema = odr_strdup_null(r->odr, schema);
100     rc->rec.diag_set = 0;
101     rc->rec.diag_uri = 0;
102     rc->rec.diag_message = 0;
103     rc->rec.diag_details = 0;
104     if (diag)
105     {
106         if (diag->uri)
107         {
108             char *cp;
109             rc->rec.diag_set = odr_strdup(r->odr, diag->uri);
110             if ((cp = strrchr(rc->rec.diag_set, '/')))
111                 *cp = '\0';
112             rc->rec.diag_uri = odr_strdup(r->odr, diag->uri);
113         }
114         rc->rec.diag_message = odr_strdup_null(r->odr, diag->message);
115         rc->rec.diag_details = odr_strdup_null(r->odr, diag->details);
116     }
117 }
118
119 ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos,
120                                      const char *syntax,
121                                      const char *elementSetName)
122 {
123     ZOOM_record_cache rc;
124
125     for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
126     {
127         if (pos == rc->pos)
128         {
129             if (yaz_strcmp_null(r->schema, rc->schema))
130                 continue;
131             if (yaz_strcmp_null(elementSetName,rc->elementSetName))
132                 continue;
133             if (yaz_strcmp_null(syntax, rc->syntax))
134                 continue;
135             return &rc->rec;
136         }
137     }
138     return 0;
139 }
140
141 ZOOM_API(ZOOM_record)
142     ZOOM_record_clone(ZOOM_record srec)
143 {
144     char *buf;
145     int size;
146     ODR odr_enc;
147     ZOOM_record nrec;
148
149     odr_enc = odr_createmem(ODR_ENCODE);
150     if (!z_NamePlusRecord(odr_enc, &srec->npr, 0, 0))
151         return 0;
152     buf = odr_getbuf(odr_enc, &size, 0);
153
154     nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
155     nrec->odr = odr_createmem(ODR_DECODE);
156 #if SHPTR
157     nrec->record_wrbuf = 0;
158 #else
159     nrec->wrbuf = 0;
160 #endif
161     odr_setbuf(nrec->odr, buf, size, 0);
162     z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
163
164     nrec->schema = odr_strdup_null(nrec->odr, srec->schema);
165     nrec->diag_uri = odr_strdup_null(nrec->odr, srec->diag_uri);
166     nrec->diag_message = odr_strdup_null(nrec->odr, srec->diag_message);
167     nrec->diag_details = odr_strdup_null(nrec->odr, srec->diag_details);
168     nrec->diag_set = odr_strdup_null(nrec->odr, srec->diag_set);
169     odr_destroy(odr_enc);
170     return nrec;
171 }
172
173 static void ZOOM_record_release(ZOOM_record rec)
174 {
175     if (!rec)
176         return;
177
178 #if SHPTR
179     if (rec->record_wrbuf)
180         YAZ_SHPTR_DEC(rec->record_wrbuf, wrbuf_destroy);
181 #else
182     if (rec->wrbuf)
183         wrbuf_destroy(rec->wrbuf);
184 #endif
185
186     if (rec->odr)
187         odr_destroy(rec->odr);
188 }
189
190 ZOOM_API(void)
191     ZOOM_resultset_cache_reset(ZOOM_resultset r)
192 {
193     int i;
194     for (i = 0; i<RECORD_HASH_SIZE; i++)
195     {
196         ZOOM_record_cache rc;
197         for (rc = r->record_hash[i]; rc; rc = rc->next)
198         {
199             ZOOM_record_release(&rc->rec);
200         }
201         r->record_hash[i] = 0;
202     }
203 }
204
205
206 ZOOM_API(const char *)
207     ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
208 {
209     WRBUF wrbuf;
210
211     if (len)
212         *len = 0; /* default return */
213
214     if (!rec || !rec->npr)
215         return 0;
216
217 #if SHPTR
218     if (!rec->record_wrbuf)
219     {
220         WRBUF w = wrbuf_alloc();
221         YAZ_SHPTR_INIT(rec->record_wrbuf, w);
222     }
223     wrbuf = rec->record_wrbuf->ptr;
224 #else
225     if (!rec->wrbuf)
226         rec->wrbuf = wrbuf_alloc();
227     wrbuf = rec->wrbuf;
228 #endif
229     return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len);
230 }
231
232 ZOOM_API(int)
233     ZOOM_record_error(ZOOM_record rec, const char **cp,
234                       const char **addinfo, const char **diagset)
235 {
236     Z_NamePlusRecord *npr;
237
238     if (!rec)
239         return 0;
240
241     npr = rec->npr;
242     if (rec->diag_uri)
243     {
244         if (cp)
245             *cp = rec->diag_message;
246         if (addinfo)
247             *addinfo = rec->diag_details;
248         if (diagset)
249             *diagset = rec->diag_set;
250         return ZOOM_uri_to_code(rec->diag_uri);
251     }
252     if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic)
253     {
254         Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic;
255         int error = YAZ_BIB1_UNSPECIFIED_ERROR;
256         const char *add = 0;
257
258         if (diag_rec->which == Z_DiagRec_defaultFormat)
259         {
260             Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat;
261             oid_class oclass;
262
263             error = *ddf->condition;
264             switch (ddf->which)
265             {
266             case Z_DefaultDiagFormat_v2Addinfo:
267                 add = ddf->u.v2Addinfo;
268                 break;
269             case Z_DefaultDiagFormat_v3Addinfo:
270                 add = ddf->u.v3Addinfo;
271                 break;
272             }
273             if (diagset)
274                 *diagset =
275                     yaz_oid_to_string(yaz_oid_std(),
276                                       ddf->diagnosticSetId, &oclass);
277         }
278         else
279         {
280             if (diagset)
281                 *diagset = "Bib-1";
282         }
283         if (addinfo)
284             *addinfo = add ? add : "";
285         if (cp)
286             *cp = diagbib1_str(error);
287         return error;
288     }
289     return 0;
290 }
291
292 ZOOM_API(void)
293     ZOOM_record_destroy(ZOOM_record rec)
294 {
295     ZOOM_record_release(rec);
296     xfree(rec);
297 }
298
299 /*
300  * Local variables:
301  * c-basic-offset: 4
302  * c-file-style: "Stroustrup"
303  * indent-tabs-mode: nil
304  * End:
305  * vim: shiftwidth=4 tabstop=8 expandtab
306  */
307