/* This file is part of the YAZ toolkit. * Copyright (C) Index Data * See the file LICENSE for details. */ /** * \file zoom-record-cache.c * \brief Implements ZOOM record caching */ #if HAVE_CONFIG_H #include #endif #include #include #include #include "zoom-p.h" #include #include #include #if SHPTR YAZ_SHPTR_TYPE(WRBUF) #endif struct ZOOM_record_p { ODR odr; #if SHPTR struct WRBUF_shptr *record_wrbuf; #else WRBUF wrbuf; #endif Z_NamePlusRecord *npr; const char *schema; const char *diag_uri; const char *diag_message; const char *diag_details; const char *diag_set; }; struct ZOOM_record_cache_p { struct ZOOM_record_p rec; char *elementSetName; char *syntax; char *schema; int pos; ZOOM_record_cache next; }; static size_t record_hash(int pos) { if (pos < 0) pos = 0; return pos % RECORD_HASH_SIZE; } static ZOOM_record record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr, int pos, const char *syntax, const char *elementSetName, const char *schema, Z_SRW_diagnostic *diag) { ZOOM_record_cache rc = 0; ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD); ZOOM_connection_put_event(r->connection, event); for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next) { if (pos == rc->pos && yaz_strcmp_null(schema, rc->schema) == 0 && yaz_strcmp_null(elementSetName,rc->elementSetName) == 0 && yaz_strcmp_null(syntax, rc->syntax) == 0) break; } if (!rc) { rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc)); rc->rec.odr = 0; #if SHPTR YAZ_SHPTR_INC(r->record_wrbuf); rc->rec.record_wrbuf = r->record_wrbuf; #else rc->rec.wrbuf = 0; #endif rc->elementSetName = odr_strdup_null(r->odr, elementSetName); rc->syntax = odr_strdup_null(r->odr, syntax); rc->schema = odr_strdup_null(r->odr, schema); rc->pos = pos; rc->next = r->record_hash[record_hash(pos)]; r->record_hash[record_hash(pos)] = rc; } rc->rec.npr = npr; rc->rec.schema = odr_strdup_null(r->odr, schema); rc->rec.diag_set = 0; rc->rec.diag_uri = 0; rc->rec.diag_message = 0; rc->rec.diag_details = 0; if (diag) { if (diag->uri) { char *cp; rc->rec.diag_set = odr_strdup(r->odr, diag->uri); if ((cp = strrchr(rc->rec.diag_set, '/'))) *cp = '\0'; rc->rec.diag_uri = odr_strdup(r->odr, diag->uri); } rc->rec.diag_message = odr_strdup_null(r->odr, diag->message); rc->rec.diag_details = odr_strdup_null(r->odr, diag->details); } return &rc->rec; } void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr, int pos, const char *syntax, const char *elementSetName, const char *schema, Z_SRW_diagnostic *diag) { record_cache_add(r, npr, pos, syntax, elementSetName, schema, diag); ZOOM_memcached_add(r, npr, pos, syntax, elementSetName, schema, diag); } ZOOM_record ZOOM_record_cache_lookup_i(ZOOM_resultset r, int pos, const char *syntax, const char *elementSetName, const char *schema) { ZOOM_record_cache rc; for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next) { if (pos == rc->pos) { if (yaz_strcmp_null(schema, rc->schema)) continue; if (yaz_strcmp_null(elementSetName,rc->elementSetName)) continue; if (yaz_strcmp_null(syntax, rc->syntax)) continue; return &rc->rec; } } return 0; } ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos, const char *syntax, const char *elementSetName, const char *schema) { Z_NamePlusRecord *npr; ZOOM_record rec = ZOOM_record_cache_lookup_i(r, pos, syntax, elementSetName, schema); if (rec) { ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD); ZOOM_connection_put_event(r->connection, event); return rec; } npr = ZOOM_memcached_lookup(r, pos, syntax, elementSetName, schema); if (npr) return record_cache_add(r, npr, pos, syntax, elementSetName, schema, 0); return 0; } ZOOM_API(ZOOM_record) ZOOM_record_clone(ZOOM_record srec) { char *buf; int size; ODR odr_enc; ZOOM_record nrec; odr_enc = odr_createmem(ODR_ENCODE); if (!z_NamePlusRecord(odr_enc, &srec->npr, 0, 0)) return 0; buf = odr_getbuf(odr_enc, &size, 0); nrec = (ZOOM_record) xmalloc(sizeof(*nrec)); nrec->odr = odr_createmem(ODR_DECODE); #if SHPTR nrec->record_wrbuf = 0; #else nrec->wrbuf = 0; #endif odr_setbuf(nrec->odr, buf, size, 0); z_NamePlusRecord(nrec->odr, &nrec->npr, 0, 0); nrec->schema = odr_strdup_null(nrec->odr, srec->schema); nrec->diag_uri = odr_strdup_null(nrec->odr, srec->diag_uri); nrec->diag_message = odr_strdup_null(nrec->odr, srec->diag_message); nrec->diag_details = odr_strdup_null(nrec->odr, srec->diag_details); nrec->diag_set = odr_strdup_null(nrec->odr, srec->diag_set); odr_destroy(odr_enc); return nrec; } static void ZOOM_record_release(ZOOM_record rec) { if (!rec) return; #if SHPTR if (rec->record_wrbuf) YAZ_SHPTR_DEC(rec->record_wrbuf, wrbuf_destroy); #else if (rec->wrbuf) wrbuf_destroy(rec->wrbuf); #endif if (rec->odr) odr_destroy(rec->odr); } ZOOM_API(void) ZOOM_resultset_cache_reset(ZOOM_resultset r) { int i; for (i = 0; irecord_hash[i]; rc; rc = rc->next) { ZOOM_record_release(&rc->rec); } r->record_hash[i] = 0; } } ZOOM_API(const char *) ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len) { WRBUF wrbuf; if (len) *len = 0; /* default return */ if (!rec || !rec->npr) return 0; #if SHPTR if (!rec->record_wrbuf) { WRBUF w = wrbuf_alloc(); YAZ_SHPTR_INIT(rec->record_wrbuf, w); } wrbuf = rec->record_wrbuf->ptr; #else if (!rec->wrbuf) rec->wrbuf = wrbuf_alloc(); wrbuf = rec->wrbuf; #endif return yaz_record_render(rec->npr, rec->schema, wrbuf, type_spec, len); } ZOOM_API(int) ZOOM_record_error(ZOOM_record rec, const char **cp, const char **addinfo, const char **diagset) { Z_NamePlusRecord *npr; if (!rec) return 0; npr = rec->npr; if (rec->diag_uri) { if (cp) *cp = rec->diag_message; if (addinfo) *addinfo = rec->diag_details; if (diagset) *diagset = rec->diag_set; return ZOOM_uri_to_code(rec->diag_uri); } if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic) { Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic; int error = YAZ_BIB1_UNSPECIFIED_ERROR; const char *add = 0; if (diag_rec->which == Z_DiagRec_defaultFormat) { Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat; oid_class oclass; error = *ddf->condition; switch (ddf->which) { case Z_DefaultDiagFormat_v2Addinfo: add = ddf->u.v2Addinfo; break; case Z_DefaultDiagFormat_v3Addinfo: add = ddf->u.v3Addinfo; break; } if (diagset) *diagset = yaz_oid_to_string(yaz_oid_std(), ddf->diagnosticSetId, &oclass); } else { if (diagset) *diagset = "Bib-1"; } if (addinfo) *addinfo = add ? add : ""; if (cp) *cp = diagbib1_str(error); return error; } return 0; } ZOOM_API(void) ZOOM_record_destroy(ZOOM_record rec) { ZOOM_record_release(rec); xfree(rec); } /* * Local variables: * c-basic-offset: 4 * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab */