Refactor: all memcached stuff to zoom-memcached.c
[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     wrbuf_sha1_puts(r->mc_key, ZOOM_query_get_query_string(q), 1);
84     wrbuf_puts(r->mc_key, ";");
85 #endif
86 }
87
88 void ZOOM_memcached_search(ZOOM_connection c, ZOOM_resultset resultset)
89 {
90 #if HAVE_LIBMEMCACHED_MEMCACHED_H
91     /* TODO: add sorting */
92     if (c->mc_st && resultset->live_set == 0)
93     {
94         size_t v_len;
95         uint32_t flags;
96         memcached_return_t rc;
97         char *v = memcached_get(c->mc_st, wrbuf_buf(resultset->mc_key),
98                                 wrbuf_len(resultset->mc_key),
99                                 &v_len, &flags, &rc);
100         if (v)
101         {
102             ZOOM_Event event;
103             WRBUF w = wrbuf_alloc();
104
105             wrbuf_write(w, v, v_len);
106             free(v);
107             resultset->size = odr_atoi(wrbuf_cstr(w));
108
109             yaz_log(YLOG_LOG, "For key %s got value %s",
110                     wrbuf_cstr(resultset->mc_key), wrbuf_cstr(w));
111
112             wrbuf_destroy(w);
113             event = ZOOM_Event_create(ZOOM_EVENT_RECV_SEARCH);
114             ZOOM_connection_put_event(c, event);
115             resultset->live_set = 1;
116         }
117     }
118 #endif
119 }
120
121 void ZOOM_memcached_hitcount(ZOOM_connection c, ZOOM_resultset resultset)
122 {
123 #if HAVE_LIBMEMCACHED_MEMCACHED_H
124     if (c->mc_st && resultset->live_set == 0)
125     {
126         uint32_t flags = 0;
127         memcached_return_t rc;
128         time_t expiration = 36000;
129         char str[40];
130
131         sprintf(str, ODR_INT_PRINTF, resultset->size);
132         rc = memcached_set(c->mc_st,
133                            wrbuf_buf(resultset->mc_key),wrbuf_len(resultset->mc_key),
134                            str, strlen(str), expiration, flags);
135         yaz_log(YLOG_LOG, "Store SRU hit count key=%s value=%s rc=%u %s",
136                 wrbuf_cstr(resultset->mc_key), str, (unsigned) rc,
137                 memcached_last_error_message(c->mc_st));
138     }
139 #endif
140 }
141
142 void ZOOM_memcached_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
143                         int pos,
144                         const char *syntax, const char *elementSetName,
145                         const char *schema,
146                         Z_SRW_diagnostic *diag)
147 {
148 #if HAVE_LIBMEMCACHED_MEMCACHED_H
149     if (r->connection->mc_st &&
150         !diag && npr->which == Z_NamePlusRecord_databaseRecord)
151     {
152         WRBUF k = wrbuf_alloc();
153         uint32_t flags = 0;
154         memcached_return_t rc;
155         time_t expiration = 36000;
156         ODR odr = odr_createmem(ODR_ENCODE);
157         char *rec_buf;
158         int rec_len;
159
160         z_NamePlusRecord(odr, &npr, 0, 0);
161         rec_buf = odr_getbuf(odr, &rec_len, 0);
162
163         wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
164         wrbuf_printf(k, ";%d;%s;%s;%s", pos,
165                      syntax ? syntax : "",
166                      elementSetName ? elementSetName : "",
167                      schema ? schema : "");
168         rc = memcached_set(r->connection->mc_st,
169                            wrbuf_buf(k),wrbuf_len(k),
170                            rec_buf, rec_len,
171                            expiration, flags);
172
173         yaz_log(YLOG_LOG, "Store record lkey=%s len=%d rc=%u %s",
174                 wrbuf_cstr(k), rec_len, (unsigned) rc,
175                 memcached_last_error_message(r->connection->mc_st));
176         odr_destroy(odr);
177         wrbuf_destroy(k);
178     }
179 #endif
180 }
181
182 Z_NamePlusRecord *ZOOM_memcached_lookup(ZOOM_resultset r, int pos,
183                                         const char *syntax,
184                                         const char *elementSetName,
185                                         const char *schema)
186 {
187 #if HAVE_LIBMEMCACHED_MEMCACHED_H
188     if (r->connection && r->connection->mc_st)
189     {
190         WRBUF k = wrbuf_alloc();
191         size_t v_len;
192         char *v_buf;
193         uint32_t flags;
194         memcached_return_t rc;
195
196         wrbuf_write(k, wrbuf_buf(r->mc_key), wrbuf_len(r->mc_key));
197         wrbuf_printf(k, ";%d;%s;%s;%s", pos,
198                      syntax ? syntax : "",
199                      elementSetName ? elementSetName : "",
200                      schema ? schema : "");
201
202         yaz_log(YLOG_LOG, "Lookup record %s", wrbuf_cstr(k));
203         v_buf = memcached_get(r->connection->mc_st, wrbuf_buf(k), wrbuf_len(k),
204                               &v_len, &flags, &rc);
205         wrbuf_destroy(k);
206         if (v_buf)
207         {
208             Z_NamePlusRecord *npr = 0;
209
210             odr_setbuf(r->odr, v_buf, v_len, 0);
211             z_NamePlusRecord(r->odr, &npr, 0, 0);
212             free(v_buf);
213             if (npr)
214                 yaz_log(YLOG_LOG, "returned memcached copy");
215             return npr;
216         }
217     }
218 #endif
219     return 0;
220
221 }
222 /*
223  * Local variables:
224  * c-basic-offset: 4
225  * c-file-style: "Stroustrup"
226  * indent-tabs-mode: nil
227  * End:
228  * vim: shiftwidth=4 tabstop=8 expandtab
229  */
230