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