1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
6 * \file zoom-record-cache.c
7 * \brief Implements ZOOM record caching
18 #include <yaz/diagbib1.h>
19 #include <yaz/record_render.h>
20 #include <yaz/shptr.h>
26 struct ZOOM_record_p {
29 struct WRBUF_shptr *record_wrbuf;
34 Z_NamePlusRecord *npr;
38 const char *diag_message;
39 const char *diag_details;
43 struct ZOOM_record_cache_p {
44 struct ZOOM_record_p rec;
49 ZOOM_record_cache next;
52 static size_t record_hash(int pos)
56 return pos % RECORD_HASH_SIZE;
59 static ZOOM_record record_cache_add(ZOOM_resultset r,
60 Z_NamePlusRecord *npr,
63 const char *elementSetName,
65 Z_SRW_diagnostic *diag)
67 ZOOM_record_cache rc = 0;
69 ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
70 ZOOM_connection_put_event(r->connection, event);
72 for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
75 && yaz_strcmp_null(schema, rc->schema) == 0
76 && yaz_strcmp_null(elementSetName,rc->elementSetName) == 0
77 && yaz_strcmp_null(syntax, rc->syntax) == 0)
82 rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
85 YAZ_SHPTR_INC(r->record_wrbuf);
86 rc->rec.record_wrbuf = r->record_wrbuf;
90 rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
92 rc->syntax = odr_strdup_null(r->odr, syntax);
94 rc->schema = odr_strdup_null(r->odr, schema);
97 rc->next = r->record_hash[record_hash(pos)];
98 r->record_hash[record_hash(pos)] = rc;
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;
113 rc->rec.diag_set = odr_strdup(r->odr, diag->uri);
114 if ((cp = strrchr(rc->rec.diag_set, '/')))
116 rc->rec.diag_uri = odr_strdup(r->odr, diag->uri);
118 rc->rec.diag_message = odr_strdup_null(r->odr, diag->message);
119 rc->rec.diag_details = odr_strdup_null(r->odr, diag->details);
124 void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
126 const char *syntax, const char *elementSetName,
128 Z_SRW_diagnostic *diag)
130 record_cache_add(r, npr, pos, syntax, elementSetName, schema, diag);
131 #if HAVE_LIBMEMCACHED_MEMCACHED_H
132 if (r->connection->mc_st &&
133 !diag && npr->which == Z_NamePlusRecord_databaseRecord &&
134 npr->u.databaseRecord->which == Z_External_octet)
136 WRBUF k = wrbuf_alloc();
138 memcached_return_t rc;
139 time_t expiration = 36000;
141 wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
142 wrbuf_printf(k, ";%d;%s;%s;%s", pos,
143 syntax ? syntax : "",
144 elementSetName ? elementSetName : "",
145 schema ? schema : "");
146 rc = memcached_set(r->connection->mc_st,
147 wrbuf_buf(k),wrbuf_len(k),
148 npr->u.databaseRecord->u.octet_aligned->buf,
149 npr->u.databaseRecord->u.octet_aligned->len,
152 yaz_log(YLOG_LOG, "Store record key=%s rc=%u %s",
153 wrbuf_cstr(k), (unsigned) rc,
154 memcached_last_error_message(r->connection->mc_st));
161 ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos,
163 const char *elementSetName,
166 ZOOM_record_cache rc;
168 for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
172 if (yaz_strcmp_null(schema, rc->schema))
174 if (yaz_strcmp_null(elementSetName,rc->elementSetName))
176 if (yaz_strcmp_null(syntax, rc->syntax))
181 #if HAVE_LIBMEMCACHED_MEMCACHED_H
182 if (r->connection && r->connection->mc_st)
184 WRBUF k = wrbuf_alloc();
188 memcached_return_t rc;
190 wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
191 wrbuf_printf(k, ";%d;%s;%s;%s", pos,
192 syntax ? syntax : "",
193 elementSetName ? elementSetName : "",
194 schema ? schema : "");
196 v = memcached_get(r->connection->mc_st, wrbuf_buf(k), wrbuf_len(k),
197 &v_len, &flags, &rc);
201 yaz_log(YLOG_LOG, "Building record from memcached!! syntax=%s",
203 Z_NamePlusRecord *npr = (Z_NamePlusRecord *)
204 odr_malloc(r->odr, sizeof(Z_NamePlusRecord));
205 npr->databaseName = 0;
206 npr->which = Z_NamePlusRecord_databaseRecord;
207 npr->u.databaseRecord = (Z_External *)
208 odr_malloc(r->odr, sizeof(Z_External));
209 npr->u.databaseRecord->descriptor = 0;
210 npr->u.databaseRecord->direct_reference =
212 yaz_string_to_oid_odr(yaz_oid_std(), CLASS_RECSYN,
214 npr->u.databaseRecord->indirect_reference = 0;
215 npr->u.databaseRecord->which = Z_External_octet;
216 npr->u.databaseRecord->u.octet_aligned =
217 odr_create_Odr_oct(r->odr, v, v_len);
221 return record_cache_add(r, npr, pos, syntax, elementSetName,
229 ZOOM_API(ZOOM_record)
230 ZOOM_record_clone(ZOOM_record srec)
237 odr_enc = odr_createmem(ODR_ENCODE);
238 if (!z_NamePlusRecord(odr_enc, &srec->npr, 0, 0))
240 buf = odr_getbuf(odr_enc, &size, 0);
242 nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
243 nrec->odr = odr_createmem(ODR_DECODE);
245 nrec->record_wrbuf = 0;
249 odr_setbuf(nrec->odr, buf, size, 0);
250 z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
252 nrec->schema = odr_strdup_null(nrec->odr, srec->schema);
253 nrec->diag_uri = odr_strdup_null(nrec->odr, srec->diag_uri);
254 nrec->diag_message = odr_strdup_null(nrec->odr, srec->diag_message);
255 nrec->diag_details = odr_strdup_null(nrec->odr, srec->diag_details);
256 nrec->diag_set = odr_strdup_null(nrec->odr, srec->diag_set);
257 odr_destroy(odr_enc);
261 static void ZOOM_record_release(ZOOM_record rec)
267 if (rec->record_wrbuf)
268 YAZ_SHPTR_DEC(rec->record_wrbuf, wrbuf_destroy);
271 wrbuf_destroy(rec->wrbuf);
275 odr_destroy(rec->odr);
279 ZOOM_resultset_cache_reset(ZOOM_resultset r)
282 for (i = 0; i<RECORD_HASH_SIZE; i++)
284 ZOOM_record_cache rc;
285 for (rc = r->record_hash[i]; rc; rc = rc->next)
287 ZOOM_record_release(&rc->rec);
289 r->record_hash[i] = 0;
294 ZOOM_API(const char *)
295 ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
300 *len = 0; /* default return */
302 if (!rec || !rec->npr)
306 if (!rec->record_wrbuf)
308 WRBUF w = wrbuf_alloc();
309 YAZ_SHPTR_INIT(rec->record_wrbuf, w);
311 wrbuf = rec->record_wrbuf->ptr;
314 rec->wrbuf = wrbuf_alloc();
317 return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len);
321 ZOOM_record_error(ZOOM_record rec, const char **cp,
322 const char **addinfo, const char **diagset)
324 Z_NamePlusRecord *npr;
333 *cp = rec->diag_message;
335 *addinfo = rec->diag_details;
337 *diagset = rec->diag_set;
338 return ZOOM_uri_to_code(rec->diag_uri);
340 if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic)
342 Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic;
343 int error = YAZ_BIB1_UNSPECIFIED_ERROR;
346 if (diag_rec->which == Z_DiagRec_defaultFormat)
348 Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat;
351 error = *ddf->condition;
354 case Z_DefaultDiagFormat_v2Addinfo:
355 add = ddf->u.v2Addinfo;
357 case Z_DefaultDiagFormat_v3Addinfo:
358 add = ddf->u.v3Addinfo;
363 yaz_oid_to_string(yaz_oid_std(),
364 ddf->diagnosticSetId, &oclass);
372 *addinfo = add ? add : "";
374 *cp = diagbib1_str(error);
381 ZOOM_record_destroy(ZOOM_record rec)
383 ZOOM_record_release(rec);
390 * c-file-style: "Stroustrup"
391 * indent-tabs-mode: nil
393 * vim: shiftwidth=4 tabstop=8 expandtab