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)
135 WRBUF k = wrbuf_alloc();
137 memcached_return_t rc;
138 time_t expiration = 36000;
139 ODR odr = odr_createmem(ODR_ENCODE);
143 z_NamePlusRecord(odr, &npr, 0, 0);
144 rec_buf = odr_getbuf(odr, &rec_len, 0);
146 wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
147 wrbuf_printf(k, ";%d;%s;%s;%s", pos,
148 syntax ? syntax : "",
149 elementSetName ? elementSetName : "",
150 schema ? schema : "");
151 rc = memcached_set(r->connection->mc_st,
152 wrbuf_buf(k),wrbuf_len(k),
156 yaz_log(YLOG_LOG, "Store record lkey=%s len=%d rc=%u %s",
157 wrbuf_cstr(k), rec_len, (unsigned) rc,
158 memcached_last_error_message(r->connection->mc_st));
166 ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos,
168 const char *elementSetName,
171 ZOOM_record_cache rc;
173 for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
177 if (yaz_strcmp_null(schema, rc->schema))
179 if (yaz_strcmp_null(elementSetName,rc->elementSetName))
181 if (yaz_strcmp_null(syntax, rc->syntax))
186 #if HAVE_LIBMEMCACHED_MEMCACHED_H
187 if (r->connection && r->connection->mc_st)
189 WRBUF k = wrbuf_alloc();
193 memcached_return_t rc;
195 wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
196 wrbuf_printf(k, ";%d;%s;%s;%s", pos,
197 syntax ? syntax : "",
198 elementSetName ? elementSetName : "",
199 schema ? schema : "");
201 yaz_log(YLOG_LOG, "Lookup record %s", wrbuf_cstr(k));
202 v_buf = memcached_get(r->connection->mc_st, wrbuf_buf(k), wrbuf_len(k),
203 &v_len, &flags, &rc);
207 Z_NamePlusRecord *npr = 0;
209 odr_setbuf(r->odr, v_buf, v_len, 0);
211 z_NamePlusRecord(r->odr, &npr, 0, 0);
215 yaz_log(YLOG_LOG, "returned memcached copy");
216 return record_cache_add(r, npr, pos, syntax, elementSetName,
219 yaz_log(YLOG_WARN, "memcached_get npr failed v_len=%ld",
227 ZOOM_API(ZOOM_record)
228 ZOOM_record_clone(ZOOM_record srec)
235 odr_enc = odr_createmem(ODR_ENCODE);
236 if (!z_NamePlusRecord(odr_enc, &srec->npr, 0, 0))
238 buf = odr_getbuf(odr_enc, &size, 0);
240 nrec = (ZOOM_record) xmalloc(sizeof(*nrec));
241 nrec->odr = odr_createmem(ODR_DECODE);
243 nrec->record_wrbuf = 0;
247 odr_setbuf(nrec->odr, buf, size, 0);
248 z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0);
250 nrec->schema = odr_strdup_null(nrec->odr, srec->schema);
251 nrec->diag_uri = odr_strdup_null(nrec->odr, srec->diag_uri);
252 nrec->diag_message = odr_strdup_null(nrec->odr, srec->diag_message);
253 nrec->diag_details = odr_strdup_null(nrec->odr, srec->diag_details);
254 nrec->diag_set = odr_strdup_null(nrec->odr, srec->diag_set);
255 odr_destroy(odr_enc);
259 static void ZOOM_record_release(ZOOM_record rec)
265 if (rec->record_wrbuf)
266 YAZ_SHPTR_DEC(rec->record_wrbuf, wrbuf_destroy);
269 wrbuf_destroy(rec->wrbuf);
273 odr_destroy(rec->odr);
277 ZOOM_resultset_cache_reset(ZOOM_resultset r)
280 for (i = 0; i<RECORD_HASH_SIZE; i++)
282 ZOOM_record_cache rc;
283 for (rc = r->record_hash[i]; rc; rc = rc->next)
285 ZOOM_record_release(&rc->rec);
287 r->record_hash[i] = 0;
292 ZOOM_API(const char *)
293 ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
298 *len = 0; /* default return */
300 if (!rec || !rec->npr)
304 if (!rec->record_wrbuf)
306 WRBUF w = wrbuf_alloc();
307 YAZ_SHPTR_INIT(rec->record_wrbuf, w);
309 wrbuf = rec->record_wrbuf->ptr;
312 rec->wrbuf = wrbuf_alloc();
315 return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len);
319 ZOOM_record_error(ZOOM_record rec, const char **cp,
320 const char **addinfo, const char **diagset)
322 Z_NamePlusRecord *npr;
331 *cp = rec->diag_message;
333 *addinfo = rec->diag_details;
335 *diagset = rec->diag_set;
336 return ZOOM_uri_to_code(rec->diag_uri);
338 if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic)
340 Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic;
341 int error = YAZ_BIB1_UNSPECIFIED_ERROR;
344 if (diag_rec->which == Z_DiagRec_defaultFormat)
346 Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat;
349 error = *ddf->condition;
352 case Z_DefaultDiagFormat_v2Addinfo:
353 add = ddf->u.v2Addinfo;
355 case Z_DefaultDiagFormat_v3Addinfo:
356 add = ddf->u.v3Addinfo;
361 yaz_oid_to_string(yaz_oid_std(),
362 ddf->diagnosticSetId, &oclass);
370 *addinfo = add ? add : "";
372 *cp = diagbib1_str(error);
379 ZOOM_record_destroy(ZOOM_record rec)
381 ZOOM_record_release(rec);
388 * c-file-style: "Stroustrup"
389 * indent-tabs-mode: nil
391 * vim: shiftwidth=4 tabstop=8 expandtab