ZOOM_record_cache_lookup makes RECV_RECORD event
[yaz-moved-to-github.git] / src / zoom-record-cache.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 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 static ZOOM_record record_cache_add(ZOOM_resultset r,
60                                     Z_NamePlusRecord *npr,
61                                     int pos,
62                                     const char *syntax,
63                                     const char *elementSetName,
64                                     const char *schema,
65                                     Z_SRW_diagnostic *diag)
66 {
67     ZOOM_record_cache rc = 0;
68
69     ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
70     ZOOM_connection_put_event(r->connection, event);
71
72     for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
73     {
74         if (pos == rc->pos
75             && yaz_strcmp_null(schema, rc->schema) == 0
76             && yaz_strcmp_null(elementSetName,rc->elementSetName) == 0
77             && yaz_strcmp_null(syntax, rc->syntax) == 0)
78             break;
79     }
80     if (!rc)
81     {
82         rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
83         rc->rec.odr = 0;
84 #if SHPTR
85         YAZ_SHPTR_INC(r->record_wrbuf);
86         rc->rec.record_wrbuf = r->record_wrbuf;
87 #else
88         rc->rec.wrbuf = 0;
89 #endif
90         rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
91
92         rc->syntax = odr_strdup_null(r->odr, syntax);
93
94         rc->schema = odr_strdup_null(r->odr, schema);
95
96         rc->pos = pos;
97         rc->next = r->record_hash[record_hash(pos)];
98         r->record_hash[record_hash(pos)] = rc;
99
100     }
101
102     rc->rec.npr = npr;
103     rc->rec.schema = odr_strdup_null(r->odr, schema);
104     rc->rec.diag_set = 0;
105     rc->rec.diag_uri = 0;
106     rc->rec.diag_message = 0;
107     rc->rec.diag_details = 0;
108     if (diag)
109     {
110         if (diag->uri)
111         {
112             char *cp;
113             rc->rec.diag_set = odr_strdup(r->odr, diag->uri);
114             if ((cp = strrchr(rc->rec.diag_set, '/')))
115                 *cp = '\0';
116             rc->rec.diag_uri = odr_strdup(r->odr, diag->uri);
117         }
118         rc->rec.diag_message = odr_strdup_null(r->odr, diag->message);
119         rc->rec.diag_details = odr_strdup_null(r->odr, diag->details);
120     }
121     return &rc->rec;
122 }
123
124 void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
125                            int pos,
126                            const char *syntax, const char *elementSetName,
127                            const char *schema,
128                            Z_SRW_diagnostic *diag)
129 {
130     record_cache_add(r, npr, pos, syntax, elementSetName, schema, diag);
131     ZOOM_memcached_add(r, npr, pos, syntax, elementSetName, schema, diag);
132 }
133
134 ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos,
135                                      const char *syntax,
136                                      const char *elementSetName,
137                                      const char *schema)
138 {
139     ZOOM_record_cache rc;
140     Z_NamePlusRecord *npr;
141
142     for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
143     {
144         if (pos == rc->pos)
145         {
146             ZOOM_Event event;
147             if (yaz_strcmp_null(schema, rc->schema))
148                 continue;
149             if (yaz_strcmp_null(elementSetName,rc->elementSetName))
150                 continue;
151             if (yaz_strcmp_null(syntax, rc->syntax))
152                 continue;
153             event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
154             ZOOM_connection_put_event(r->connection, event);
155
156             return &rc->rec;
157         }
158     }
159     npr = ZOOM_memcached_lookup(r, pos, syntax, elementSetName, schema);
160     if (npr)
161         return record_cache_add(r, npr, pos, syntax, elementSetName,
162                                 schema, 0);
163     return 0;
164 }
165
166 ZOOM_API(ZOOM_record)
167     ZOOM_record_clone(ZOOM_record srec)
168 {
169     char *buf;
170     int size;
171     ODR odr_enc;
172     ZOOM_record nrec;
173
174     odr_enc = odr_createmem(ODR_ENCODE);
175     if (!z_NamePlusRecord(odr_enc, &srec->npr, 0, 0))
176         return 0;
177     buf = odr_getbuf(odr_enc, &size, 0);
178
179     nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
180     nrec->odr = odr_createmem(ODR_DECODE);
181 #if SHPTR
182     nrec->record_wrbuf = 0;
183 #else
184     nrec->wrbuf = 0;
185 #endif
186     odr_setbuf(nrec->odr, buf, size, 0);
187     z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
188
189     nrec->schema = odr_strdup_null(nrec->odr, srec->schema);
190     nrec->diag_uri = odr_strdup_null(nrec->odr, srec->diag_uri);
191     nrec->diag_message = odr_strdup_null(nrec->odr, srec->diag_message);
192     nrec->diag_details = odr_strdup_null(nrec->odr, srec->diag_details);
193     nrec->diag_set = odr_strdup_null(nrec->odr, srec->diag_set);
194     odr_destroy(odr_enc);
195     return nrec;
196 }
197
198 static void ZOOM_record_release(ZOOM_record rec)
199 {
200     if (!rec)
201         return;
202
203 #if SHPTR
204     if (rec->record_wrbuf)
205         YAZ_SHPTR_DEC(rec->record_wrbuf, wrbuf_destroy);
206 #else
207     if (rec->wrbuf)
208         wrbuf_destroy(rec->wrbuf);
209 #endif
210
211     if (rec->odr)
212         odr_destroy(rec->odr);
213 }
214
215 ZOOM_API(void)
216     ZOOM_resultset_cache_reset(ZOOM_resultset r)
217 {
218     int i;
219     for (i = 0; i<RECORD_HASH_SIZE; i++)
220     {
221         ZOOM_record_cache rc;
222         for (rc = r->record_hash[i]; rc; rc = rc->next)
223         {
224             ZOOM_record_release(&rc->rec);
225         }
226         r->record_hash[i] = 0;
227     }
228 }
229
230
231 ZOOM_API(const char *)
232     ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
233 {
234     WRBUF wrbuf;
235
236     if (len)
237         *len = 0; /* default return */
238
239     if (!rec || !rec->npr)
240         return 0;
241
242 #if SHPTR
243     if (!rec->record_wrbuf)
244     {
245         WRBUF w = wrbuf_alloc();
246         YAZ_SHPTR_INIT(rec->record_wrbuf, w);
247     }
248     wrbuf = rec->record_wrbuf->ptr;
249 #else
250     if (!rec->wrbuf)
251         rec->wrbuf = wrbuf_alloc();
252     wrbuf = rec->wrbuf;
253 #endif
254     return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len);
255 }
256
257 ZOOM_API(int)
258     ZOOM_record_error(ZOOM_record rec, const char **cp,
259                       const char **addinfo, const char **diagset)
260 {
261     Z_NamePlusRecord *npr;
262
263     if (!rec)
264         return 0;
265
266     npr = rec->npr;
267     if (rec->diag_uri)
268     {
269         if (cp)
270             *cp = rec->diag_message;
271         if (addinfo)
272             *addinfo = rec->diag_details;
273         if (diagset)
274             *diagset = rec->diag_set;
275         return ZOOM_uri_to_code(rec->diag_uri);
276     }
277     if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic)
278     {
279         Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic;
280         int error = YAZ_BIB1_UNSPECIFIED_ERROR;
281         const char *add = 0;
282
283         if (diag_rec->which == Z_DiagRec_defaultFormat)
284         {
285             Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat;
286             oid_class oclass;
287
288             error = *ddf->condition;
289             switch (ddf->which)
290             {
291             case Z_DefaultDiagFormat_v2Addinfo:
292                 add = ddf->u.v2Addinfo;
293                 break;
294             case Z_DefaultDiagFormat_v3Addinfo:
295                 add = ddf->u.v3Addinfo;
296                 break;
297             }
298             if (diagset)
299                 *diagset =
300                     yaz_oid_to_string(yaz_oid_std(),
301                                       ddf->diagnosticSetId, &oclass);
302         }
303         else
304         {
305             if (diagset)
306                 *diagset = "Bib-1";
307         }
308         if (addinfo)
309             *addinfo = add ? add : "";
310         if (cp)
311             *cp = diagbib1_str(error);
312         return error;
313     }
314     return 0;
315 }
316
317 ZOOM_API(void)
318     ZOOM_record_destroy(ZOOM_record rec)
319 {
320     ZOOM_record_release(rec);
321     xfree(rec);
322 }
323
324 /*
325  * Local variables:
326  * c-basic-offset: 4
327  * c-file-style: "Stroustrup"
328  * indent-tabs-mode: nil
329  * End:
330  * vim: shiftwidth=4 tabstop=8 expandtab
331  */
332