root/lang/perl/Cache-Memcached-LibMemcached/trunk/perl-libmemcached.c @ 4513

Revision 4513, 7.0 kB (checked in by daisuke, 5 years ago)

lang/perl/Cache-Memcached-LibMemcached?; implement get_multi()

Line 
1/* $Id$
2 *
3 * Copyright (c) 2008 Daisuke Maki <daisuke@endeworks.jp>
4 * All rights reserved
5 */
6
7#ifndef __PERL_LIBMEMCACHED_C__
8#define __PERL_LIBMEMCACHED_C__
9#include "perl-libmemcached.h"
10
11#define CONSTSUBi(name, x) \
12    newCONSTSUB(stash, name, newSViv(x));
13
14static void
15Cache_LibMemcached_uncompress(cache, value, value_len, flags)
16        Cache_LibMemcached *cache;
17        char **value;
18        size_t *value_len;
19        uint16_t flags;
20{
21    if (MEMCACHED_HAVE_ZLIB(cache) && (flags & F_COMPRESS)) {
22        SV *sv;
23        dSP;
24
25        ENTER;
26        SAVETMPS;
27
28        PUSHMARK(SP);
29        EXTEND(SP, 1);
30        PUSHs(sv_2mortal(newSVpv(*value, *value_len)));
31        PUTBACK;
32
33        if (call_pv("Compress::Zlib::memGunzip", G_SCALAR) <= 0) {
34            croak("Compress::Zlib::memGunzip did not return a proper value");
35        }
36        SPAGAIN;
37
38        sv = POPs;
39        *value = SvPV(sv, *value_len);
40
41        FREETMPS;
42        LEAVE;
43    }
44}
45
46static void
47Cache_LibMemcached_thaw(cache, sv, flags)
48        Cache_LibMemcached *cache;
49        SV *sv;
50        uint16_t flags;
51{
52    if (flags & F_STORABLE) {
53        SV *rv;
54        dSP;
55        ENTER;
56        SAVETMPS;
57
58        PUSHMARK(SP);
59        EXTEND(SP, 1);
60        PUSHs(sv);
61        PUTBACK;
62
63        if (call_pv("Storable::thaw", G_SCALAR) <= 0) {
64            croak("Storable::thaw did not return a proper value");
65        }
66        SPAGAIN;
67
68        rv = POPs;
69       
70        SvSetSV(sv, rv);
71
72        FREETMPS;
73        LEAVE;
74    }
75}
76
77
78void
79Cache_LibMemcached_bootstrap()
80{
81    HV *stash;
82
83    stash = gv_stashpv("Cache::Memcached::LibMemcached", 1);
84
85    CONSTSUBi( "F_STORABLE", F_STORABLE );
86    CONSTSUBi( "F_COMPRESS", F_COMPRESS );
87
88    /* There has to be an easier way, eh? */
89    CONSTSUBi( "MEMCACHED_SUCCESS", MEMCACHED_SUCCESS );
90    CONSTSUBi( "MEMCACHED_FAILURE", MEMCACHED_FAILURE );
91    CONSTSUBi( "MEMCACHED_HOST_LOOKUP_FAILURE", MEMCACHED_HOST_LOOKUP_FAILURE );
92    CONSTSUBi( "MEMCACHED_CONNECTION_BIND_FAILURE", MEMCACHED_CONNECTION_BIND_FAILURE );
93    CONSTSUBi( "MEMCACHED_WRITE_FAILURE", MEMCACHED_WRITE_FAILURE );
94    CONSTSUBi( "MEMCACHED_READ_FAILURE", MEMCACHED_READ_FAILURE );
95    CONSTSUBi( "MEMCACHED_UNKNOWN_READ_FAILURE", MEMCACHED_UNKNOWN_READ_FAILURE );
96    CONSTSUBi( "MEMCACHED_PROTOCOL_ERROR", MEMCACHED_PROTOCOL_ERROR );
97    CONSTSUBi( "MEMCACHED_CLIENT_ERROR", MEMCACHED_CLIENT_ERROR );
98    CONSTSUBi( "MEMCACHED_SERVER_ERROR", MEMCACHED_SERVER_ERROR );
99    CONSTSUBi( "MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE", MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE );
100    CONSTSUBi( "MEMCACHED_DATA_EXISTS", MEMCACHED_DATA_EXISTS );
101    CONSTSUBi( "MEMCACHED_DATA_DOES_NOT_EXIST", MEMCACHED_DATA_DOES_NOT_EXIST );
102    CONSTSUBi( "MEMCACHED_NOTSTORED", MEMCACHED_NOTSTORED );
103    CONSTSUBi( "MEMCACHED_STORED", MEMCACHED_STORED );
104    CONSTSUBi( "MEMCACHED_NOTFOUND", MEMCACHED_NOTFOUND );
105    CONSTSUBi( "MEMCACHED_MEMORY_ALLOCATION_FAILURE", MEMCACHED_MEMORY_ALLOCATION_FAILURE );
106    CONSTSUBi( "MEMCACHED_PARTIAL_READ", MEMCACHED_PARTIAL_READ );
107    CONSTSUBi( "MEMCACHED_SOME_ERRORS", MEMCACHED_SOME_ERRORS );
108    CONSTSUBi( "MEMCACHED_NO_SERVERS", MEMCACHED_NO_SERVERS );
109    CONSTSUBi( "MEMCACHED_END", MEMCACHED_END );
110    CONSTSUBi( "MEMCACHED_DELETED", MEMCACHED_DELETED );
111    CONSTSUBi( "MEMCACHED_VALUE", MEMCACHED_VALUE );
112    CONSTSUBi( "MEMCACHED_STAT", MEMCACHED_STAT );
113    CONSTSUBi( "MEMCACHED_ERRNO", MEMCACHED_ERRNO );
114    CONSTSUBi( "MEMCACHED_FAIL_UNIX_SOCKET", MEMCACHED_FAIL_UNIX_SOCKET );
115    CONSTSUBi( "MEMCACHED_NOT_SUPPORTED", MEMCACHED_NOT_SUPPORTED );
116    CONSTSUBi( "MEMCACHED_NO_KEY_PROVIDED", MEMCACHED_NO_KEY_PROVIDED );
117    CONSTSUBi( "MEMCACHED_FETCH_NOTFINISHED", MEMCACHED_FETCH_NOTFINISHED );
118    CONSTSUBi( "MEMCACHED_TIMEOUT", MEMCACHED_TIMEOUT );
119    CONSTSUBi( "MEMCACHED_MAXIMUM_RETURN", MEMCACHED_MAXIMUM_RETURN );
120}
121
122SV *
123Cache_LibMemcached_create(pkg, have_zlib)
124        char *pkg;
125{
126    SV *sv;
127    Cache_LibMemcached *xs;
128    memcached_st *cache;
129
130    Newxz(xs, 1, Cache_LibMemcached);
131
132    MEMCACHED_CACHE(xs) =  memcached_create(NULL);
133    MEMCACHED_HAVE_ZLIB(xs) = have_zlib;
134    XS_STRUCT2OBJ(sv, "Cache::Memcached::LibMemcached::Backend", xs);
135
136    return sv;
137}
138
139void
140Cache_LibMemcached_DESTROY(cache)
141        Cache_LibMemcached *cache;
142{
143    memcached_free(MEMCACHED_CACHE(cache));
144}
145
146memcached_return
147Cache_LibMemcached_server_add(cache, hostname, port)
148        Cache_LibMemcached *cache;
149        char *hostname;
150        unsigned int port;
151{
152    return memcached_server_add(MEMCACHED_CACHE(cache), hostname, port);
153}
154
155memcached_return
156Cache_LibMemcached_server_add_unix_socket(cache, filename)
157        Cache_LibMemcached *cache;
158        char *filename;
159{
160    return memcached_server_add_unix_socket(MEMCACHED_CACHE(cache), filename);
161}
162
163memcached_return
164Cache_LibMemcached_set_raw(cache, key, value, expires, flags)
165        Cache_LibMemcached *cache;
166        SV *key;
167        SV *value;
168        time_t expires;
169        unsigned int flags;
170{
171    STRLEN key_len, value_len;
172    char *key_char;
173    char *value_char;
174
175    key_char = SvPVbyte(key, key_len);
176    value_char = SvPVbyte(value, value_len);
177
178    return memcached_set(MEMCACHED_CACHE(cache), key_char, key_len, value_char, value_len, expires, flags);
179}
180
181SV *
182Cache_LibMemcached_get(cache, key)
183        Cache_LibMemcached *cache;
184        SV *key;
185{
186    STRLEN key_len;
187    size_t value_len = 0;
188    char *key_char, *value;
189    Cache_LibMemcached_rc rc;
190    uint16_t flags;
191    SV *sv;
192
193    key_char = SvPVbyte(key, key_len);
194   
195    value = memcached_get(MEMCACHED_CACHE(cache), key_char, key_len, &value_len, &flags, &rc);
196    if (!value || rc != MEMCACHED_SUCCESS) {
197        return &PL_sv_undef;
198    }
199
200    Cache_LibMemcached_uncompress( cache, &value, &value_len, flags );
201    sv = newSVpv(value, value_len);
202
203    Cache_LibMemcached_thaw( cache, sv, flags );
204
205    return sv;
206}
207
208SV *
209Cache_LibMemcached_mget(cache, keys, key_len_list, keys_len)
210        Cache_LibMemcached *cache;
211        char **keys;
212        size_t *key_len_list;
213        unsigned int keys_len;
214{
215    Cache_LibMemcached_rc rc;
216    HV *hv;
217    unsigned int i;
218
219    rc = memcached_mget(MEMCACHED_CACHE(cache), keys, key_len_list, keys_len);
220    if (rc != MEMCACHED_SUCCESS) {
221        memcached_quit(MEMCACHED_CACHE(cache));
222        croak("memcached_mget failed :(");
223    }
224
225    hv = newHV();
226    while (1) {
227        char *value;
228        char *key;
229        size_t key_length;
230        size_t value_length;
231        uint16_t flags;
232        Cache_LibMemcached_rc rc;
233        SV *sv;
234
235        value = memcached_fetch(MEMCACHED_CACHE(cache), key, &key_length, &value_length, &flags, &rc);
236        if (value == NULL) {
237            break;
238        }
239
240        Cache_LibMemcached_uncompress( cache, &value, &value_length, flags );
241
242        sv = newSVpv(value, value_length);
243
244        Cache_LibMemcached_thaw( cache, sv, flags );
245
246        SvREFCNT_inc(sv);
247        if (hv_store_ent(hv, newSVpv(key, key_length), sv, 0) == NULL) {
248            croak("Failed to insert into hash");
249        }
250    }
251
252    return newRV_noinc(hv);
253}
254
255#endif /* __PERL_LIBMEMCACHED_C__ */
Note: See TracBrowser for help on using the browser.