ZOOM: resultset setname managed by ODR
[yaz-moved-to-github.git] / src / zoom-memcached.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file zoom-memcached.c
7  * \brief Implements query/record caching using memcached
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/yaz-util.h>
19 #include <yaz/xmalloc.h>
20 #include <yaz/log.h>
21 #include <yaz/diagbib1.h>
22
23 void ZOOM_memcached_init(ZOOM_connection c)
24 {
25 #if HAVE_LIBMEMCACHED_MEMCACHED_H
26     c->mc_st = 0;
27 #endif
28 }
29
30 void ZOOM_memcached_destroy(ZOOM_connection c)
31 {
32 #if HAVE_LIBMEMCACHED_MEMCACHED_H
33     if (c->mc_st)
34         memcached_free(c->mc_st);
35 #endif
36 }
37
38 int ZOOM_memcached_configure(ZOOM_connection c)
39 {
40     const char *val;
41 #if HAVE_LIBMEMCACHED_MEMCACHED_H
42     if (c->mc_st)
43     {
44         memcached_free(c->mc_st);
45         c->mc_st = 0;
46     }
47 #endif
48     val = ZOOM_options_get(c->options, "memcached");
49     if (val && *val)
50     {
51 #if HAVE_LIBMEMCACHED_MEMCACHED_H
52         c->mc_st = memcached(val, strlen(val));
53         if (!c->mc_st)
54         {
55             ZOOM_set_error(c, ZOOM_ERROR_MEMCACHED, val);
56             return -1;
57         }
58 #else
59         ZOOM_set_error(c, ZOOM_ERROR_MEMCACHED, "not enabled");
60         return -1;
61 #endif
62     }
63     return 0;
64 }
65
66 void ZOOM_memcached_resultset(ZOOM_resultset r, ZOOM_query q)
67 {
68 #if HAVE_LIBMEMCACHED_MEMCACHED_H
69     ZOOM_connection c = r->connection;
70     r->mc_key = wrbuf_alloc();
71     wrbuf_puts(r->mc_key, "0;");
72     wrbuf_puts(r->mc_key, c->host_port);
73     wrbuf_puts(r->mc_key, ";");
74     if (c->user)
75         wrbuf_puts(r->mc_key, c->user);
76     wrbuf_puts(r->mc_key, ";");
77     if (c->group)
78         wrbuf_puts(r->mc_key, c->group);
79     wrbuf_puts(r->mc_key, ";");
80     if (c->password)
81         wrbuf_sha1_puts(r->mc_key, c->password, 1);
82     wrbuf_puts(r->mc_key, ";");
83     {
84         WRBUF w = wrbuf_alloc();
85         ZOOM_query_get_hash(q, w);
86         wrbuf_sha1_puts(r->mc_key, wrbuf_cstr(w), 1);
87         wrbuf_destroy(w);
88     }
89     wrbuf_puts(r->mc_key, ";");
90     if (r->req_facets)
91         wrbuf_puts(r->mc_key, r->req_facets);
92 #endif
93 }
94
95 void ZOOM_memcached_search(ZOOM_connection c, ZOOM_resultset resultset)
96 {
97 #if HAVE_LIBMEMCACHED_MEMCACHED_H
98     /* TODO: add sorting */
99     if (c->mc_st && resultset->live_set == 0)
100     {
101         size_t v_len;
102         uint32_t flags;
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         if (v)
108         {
109             ZOOM_Event event;
110             WRBUF w = wrbuf_alloc();
111
112             wrbuf_write(w, v, v_len);
113             free(v);
114             resultset->size = odr_atoi(wrbuf_cstr(w));
115
116             yaz_log(YLOG_LOG, "For key %s got value %s",
117                     wrbuf_cstr(resultset->mc_key), wrbuf_cstr(w));
118
119             wrbuf_destroy(w);
120             event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
121             ZOOM_connection_put_event(c, event);
122             resultset->live_set = 1;
123         }
124     }
125 #endif
126 }
127
128 void ZOOM_memcached_hitcount(ZOOM_connection c, ZOOM_resultset resultset)
129 {
130 #if HAVE_LIBMEMCACHED_MEMCACHED_H
131     if (c->mc_st && resultset->live_set == 0)
132     {
133         uint32_t flags = 0;
134         memcached_return_t rc;
135         time_t expiration = 36000;
136         char str[40];
137
138         sprintf(str, ODR_INT_PRINTF, resultset->size);
139         rc = memcached_set(c->mc_st,
140                            wrbuf_buf(resultset->mc_key),wrbuf_len(resultset->mc_key),
141                            str, strlen(str), expiration, flags);
142         yaz_log(YLOG_LOG, "Store hit count key=%s value=%s rc=%u %s",
143                 wrbuf_cstr(resultset->mc_key), str, (unsigned) rc,
144                 memcached_last_error_message(c->mc_st));
145     }
146 #endif
147 }
148
149 void ZOOM_memcached_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
150                         int pos,
151                         const char *syntax, const char *elementSetName,
152                         const char *schema,
153                         Z_SRW_diagnostic *diag)
154 {
155 #if HAVE_LIBMEMCACHED_MEMCACHED_H
156     if (r->connection->mc_st &&
157         !diag && npr->which == Z_NamePlusRecord_databaseRecord)
158     {
159         WRBUF k = wrbuf_alloc();
160         uint32_t flags = 0;
161         memcached_return_t rc;
162         time_t expiration = 36000;
163         ODR odr = odr_createmem(ODR_ENCODE);
164         char *rec_buf;
165         int rec_len;
166
167         z_NamePlusRecord(odr, &npr, 0, 0);
168         rec_buf = odr_getbuf(odr, &rec_len, 0);
169
170         wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
171         wrbuf_printf(k, ";%d;%s;%s;%s", pos,
172                      syntax ? syntax : "",
173                      elementSetName ? elementSetName : "",
174                      schema ? schema : "");
175         rc = memcached_set(r->connection->mc_st,
176                            wrbuf_buf(k),wrbuf_len(k),
177                            rec_buf, rec_len,
178                            expiration, flags);
179
180         yaz_log(YLOG_LOG, "Store record lkey=%s len=%d rc=%u %s",
181                 wrbuf_cstr(k), rec_len, (unsigned) rc,
182                 memcached_last_error_message(r->connection->mc_st));
183         odr_destroy(odr);
184         wrbuf_destroy(k);
185     }
186 #endif
187 }
188
189 Z_NamePlusRecord *ZOOM_memcached_lookup(ZOOM_resultset r, int pos,
190                                         const char *syntax,
191                                         const char *elementSetName,
192                                         const char *schema)
193 {
194 #if HAVE_LIBMEMCACHED_MEMCACHED_H
195     if (r->connection && r->connection->mc_st)
196     {
197         WRBUF k = wrbuf_alloc();
198         size_t v_len;
199         char *v_buf;
200         uint32_t flags;
201         memcached_return_t rc;
202
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 : "");
208
209         yaz_log(YLOG_LOG, "Lookup record %s", wrbuf_cstr(k));
210         v_buf = memcached_get(r->connection->mc_st, wrbuf_buf(k), wrbuf_len(k),
211                               &v_len, &flags, &rc);
212         wrbuf_destroy(k);
213         if (v_buf)
214         {
215             Z_NamePlusRecord *npr = 0;
216
217             odr_setbuf(r->odr, v_buf, v_len, 0);
218             z_NamePlusRecord(r->odr, &npr, 0, 0);
219             free(v_buf);
220             if (npr)
221                 yaz_log(YLOG_LOG, "returned memcached copy");
222             return npr;
223         }
224     }
225 #endif
226     return 0;
227
228 }
229 /*
230  * Local variables:
231  * c-basic-offset: 4
232  * c-file-style: "Stroustrup"
233  * indent-tabs-mode: nil
234  * End:
235  * vim: shiftwidth=4 tabstop=8 expandtab
236  */
237