1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
6 * \file zoom-memcached.c
7 * \brief Implements query/record caching using memcached
18 #include <yaz/yaz-util.h>
19 #include <yaz/xmalloc.h>
21 #include <yaz/diagbib1.h>
23 void ZOOM_memcached_init(ZOOM_connection c)
25 #if HAVE_LIBMEMCACHED_MEMCACHED_H
30 void ZOOM_memcached_destroy(ZOOM_connection c)
32 #if HAVE_LIBMEMCACHED_MEMCACHED_H
34 memcached_free(c->mc_st);
38 int ZOOM_memcached_configure(ZOOM_connection c)
41 #if HAVE_LIBMEMCACHED_MEMCACHED_H
44 memcached_free(c->mc_st);
48 val = ZOOM_options_get(c->options, "memcached");
51 #if HAVE_LIBMEMCACHED_MEMCACHED_H
52 c->mc_st = memcached(val, strlen(val));
55 ZOOM_set_error(c, ZOOM_ERROR_MEMCACHED, val);
58 memcached_behavior_set(c->mc_st, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
60 ZOOM_set_error(c, ZOOM_ERROR_MEMCACHED, "not enabled");
67 void ZOOM_memcached_resultset(ZOOM_resultset r, ZOOM_query q)
69 #if HAVE_LIBMEMCACHED_MEMCACHED_H
70 ZOOM_connection c = r->connection;
71 r->mc_key = wrbuf_alloc();
72 wrbuf_puts(r->mc_key, "0;");
73 wrbuf_puts(r->mc_key, c->host_port);
74 wrbuf_puts(r->mc_key, ";");
76 wrbuf_puts(r->mc_key, c->user);
77 wrbuf_puts(r->mc_key, ";");
79 wrbuf_puts(r->mc_key, c->group);
80 wrbuf_puts(r->mc_key, ";");
82 wrbuf_sha1_puts(r->mc_key, c->password, 1);
83 wrbuf_puts(r->mc_key, ";");
85 WRBUF w = wrbuf_alloc();
86 ZOOM_query_get_hash(q, w);
87 wrbuf_sha1_puts(r->mc_key, wrbuf_cstr(w), 1);
90 wrbuf_puts(r->mc_key, ";");
92 wrbuf_puts(r->mc_key, r->req_facets);
96 void ZOOM_memcached_search(ZOOM_connection c, ZOOM_resultset resultset)
98 #if HAVE_LIBMEMCACHED_MEMCACHED_H
99 if (c->mc_st && resultset->live_set == 0)
103 memcached_return_t rc;
104 char *v = memcached_get(c->mc_st, wrbuf_buf(resultset->mc_key),
105 wrbuf_len(resultset->mc_key),
106 &v_len, &flags, &rc);
107 /* count;precision (ASCII) + '\0' + BER buffer for otherInformation */
111 size_t lead_len = strlen(v) + 1;
113 resultset->size = odr_atoi(v);
115 yaz_log(YLOG_LOG, "For key %s got value %s lead_len=%d len=%d",
116 wrbuf_cstr(resultset->mc_key), v, (int) lead_len,
118 if (v_len > lead_len)
120 Z_OtherInformation *oi = 0;
121 int oi_len = v_len - lead_len;
122 odr_setbuf(resultset->odr, v + lead_len, oi_len, 0);
123 if (!z_OtherInformation(resultset->odr, &oi, 0, 0))
125 yaz_log(YLOG_WARN, "oi decoding failed");
129 ZOOM_handle_search_result(c, resultset, oi);
130 ZOOM_handle_facet_result(c, resultset, oi);
133 event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
134 ZOOM_connection_put_event(c, event);
135 resultset->live_set = 1;
141 void ZOOM_memcached_hitcount(ZOOM_connection c, ZOOM_resultset resultset,
142 Z_OtherInformation *oi, const char *precision)
144 #if HAVE_LIBMEMCACHED_MEMCACHED_H
145 if (c->mc_st && resultset->live_set == 0)
148 memcached_return_t rc;
149 time_t expiration = 36000;
151 ODR odr = odr_createmem(ODR_ENCODE);
156 str = odr_malloc(odr, 20 + strlen(precision));
157 /* count;precision (ASCII) + '\0' + BER buffer for otherInformation */
158 sprintf(str, ODR_INT_PRINTF ";%s", resultset->size, precision);
161 z_OtherInformation(odr, &oi, 0, 0);
162 oi_buf = odr_getbuf(odr, &oi_len, 0);
164 key = odr_malloc(odr, strlen(str) + 1 + oi_len);
167 memcpy(key + strlen(str) + 1, oi_buf, oi_len);
169 rc = memcached_set(c->mc_st,
170 wrbuf_buf(resultset->mc_key),
171 wrbuf_len(resultset->mc_key),
172 key, strlen(str) + 1 + oi_len, expiration, flags);
173 yaz_log(YLOG_LOG, "Store hit count key=%s value=%s oi_len=%d rc=%u %s",
174 wrbuf_cstr(resultset->mc_key), str, oi_len, (unsigned) rc,
175 memcached_last_error_message(c->mc_st));
181 void ZOOM_memcached_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
183 const char *syntax, const char *elementSetName,
185 Z_SRW_diagnostic *diag)
187 #if HAVE_LIBMEMCACHED_MEMCACHED_H
188 if (r->connection->mc_st &&
189 !diag && npr->which == Z_NamePlusRecord_databaseRecord)
191 WRBUF k = wrbuf_alloc();
192 WRBUF rec_sha1 = wrbuf_alloc();
194 memcached_return_t rc;
195 time_t expiration = 36000;
196 ODR odr = odr_createmem(ODR_ENCODE);
200 z_NamePlusRecord(odr, &npr, 0, 0);
201 rec_buf = odr_getbuf(odr, &rec_len, 0);
203 wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
204 wrbuf_printf(k, ";%d;%s;%s;%s", pos,
205 syntax ? syntax : "",
206 elementSetName ? elementSetName : "",
207 schema ? schema : "");
209 wrbuf_sha1_write(rec_sha1, rec_buf, rec_len, 1);
211 rc = memcached_set(r->connection->mc_st,
212 wrbuf_buf(k), wrbuf_len(k),
213 wrbuf_buf(rec_sha1), wrbuf_len(rec_sha1),
216 yaz_log(YLOG_LOG, "Store record key=%s val=%s rc=%u %s",
217 wrbuf_cstr(k), wrbuf_cstr(rec_sha1), (unsigned) rc,
218 memcached_last_error_message(r->connection->mc_st));
220 rc = memcached_add(r->connection->mc_st,
221 wrbuf_buf(rec_sha1), wrbuf_len(rec_sha1),
225 yaz_log(YLOG_LOG, "Add record key=%s rec_len=%d rc=%u %s",
226 wrbuf_cstr(rec_sha1), rec_len, (unsigned) rc,
227 memcached_last_error_message(r->connection->mc_st));
231 wrbuf_destroy(rec_sha1);
236 Z_NamePlusRecord *ZOOM_memcached_lookup(ZOOM_resultset r, int pos,
238 const char *elementSetName,
241 #if HAVE_LIBMEMCACHED_MEMCACHED_H
242 if (r->connection && r->connection->mc_st)
244 WRBUF k = wrbuf_alloc();
248 memcached_return_t rc;
250 wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
251 wrbuf_printf(k, ";%d;%s;%s;%s", pos,
252 syntax ? syntax : "",
253 elementSetName ? elementSetName : "",
254 schema ? schema : "");
256 yaz_log(YLOG_LOG, "Lookup record %s", wrbuf_cstr(k));
257 sha1_buf = memcached_get(r->connection->mc_st,
258 wrbuf_buf(k), wrbuf_len(k),
259 &sha1_len, &flags, &rc);
267 yaz_log(YLOG_LOG, "Lookup record %.*s", (int) sha1_len, sha1_buf);
268 v_buf = memcached_get(r->connection->mc_st, sha1_buf, sha1_len,
269 &v_len, &flags, &rc);
273 Z_NamePlusRecord *npr = 0;
275 odr_setbuf(r->odr, v_buf, v_len, 0);
276 z_NamePlusRecord(r->odr, &npr, 0, 0);
279 yaz_log(YLOG_LOG, "returned memcached copy");
291 * c-file-style: "Stroustrup"
292 * indent-tabs-mode: nil
294 * vim: shiftwidth=4 tabstop=8 expandtab