Annotation of parser3/src/types/pa_vmemcached.C, revision 1.7
1.1 moko 1: /** @file
2: Parser: memcached class.
3:
4: Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com)
5: Authors:
6: Ivan Poluyanov <ivan-poluyanov@yandex.ru>
7: Artem Stepanov <timofei1394@thesecure.in>
8: */
9:
10: #include "pa_vmemcached.h"
11: #include "pa_value.h"
12: #include "pa_vstring.h"
1.2 moko 13: #include "pa_vhash.h"
1.1 moko 14: #include "pa_vvoid.h"
15:
1.7 ! moko 16: volatile const char * IDENT_PA_VMEMCACHED_C="$Id: pa_vmemcached.C,v 1.6 2012-04-13 22:59:36 moko Exp $" IDENT_PA_VMEMCACHED_H;
1.1 moko 17:
18: #ifdef WIN32
19: const char *memcached_library="libmemcached.dll";
20: #else
21: const char *memcached_library="libmemcached.so";
22: #endif
23:
24: void error(const char *step, memcached_st* m, memcached_return rc) {
25: const char* str=f_memcached_strerror(m, rc);
26: throw Exception("memcached", 0, "%s error: %s (%d)", step, str ? str : "<unknown>", rc);
27: }
28:
1.2 moko 29: inline void check(const char *action, memcached_st* m, memcached_return rc) {
1.1 moko 30: if(rc==MEMCACHED_SUCCESS)
31: return;
1.2 moko 32: error(action, m, rc);
1.1 moko 33: }
34:
1.6 moko 35: inline void check_key(const String& akey) {
36: if(akey.is_empty())
37: throw Exception("memcached", 0, "key must not be empty");
38: if(akey.length() > MEMCACHED_MAX_KEY)
39: throw Exception("memcached", &akey, "key length %d exceeds limit (%d bytes)", akey.length(), MEMCACHED_MAX_KEY);
40: }
41:
1.2 moko 42: void VMemcached::open(const String& connect_string, time_t attl){
1.1 moko 43: const char *library = memcached_library;
44: const char *memcached_status = memcached_load(library);
45:
46: if(memcached_status)
47: throw Exception("memcached", 0, "failed to load memcached library %s: %s", library, memcached_status);
48:
49: if(connect_string.is_empty())
50: throw Exception("memcached", 0, "server name must not be empty");
51:
1.2 moko 52: fttl=attl;
1.1 moko 53:
54: fm=f_memcached_create(NULL);
55:
56: memcached_server_st* fservers = f_memcached_servers_parse(connect_string.cstr());
57: check("server_push", fm, f_memcached_server_push(fm, fservers));
58: }
59:
1.6 moko 60: void VMemcached::flush(time_t attl) {
1.2 moko 61: check("flush", fm, f_memcached_flush(fm, attl));
62: }
63:
1.6 moko 64: void VMemcached::remove(const String& aname) {
65: check_key(aname);
66:
67: memcached_return rc=f_memcached_delete(fm, aname.cstr(), aname.length(), (time_t)0);
1.1 moko 68:
69: if(rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND)
70: error("delete", fm, rc);
71: }
72:
73: Value* VMemcached::get_element(const String& aname) {
74: if(Value *result=VStateless_object::get_element(aname))
75: return result;
76:
1.6 moko 77: check_key(aname);
1.1 moko 78:
79: memcached_return rc;
1.5 moko 80: Serialization_data data;
81: data.ptr=f_memcached_get(fm, aname.cstr(), aname.length(), &data.length, &data.flags, &rc);
1.1 moko 82:
1.5 moko 83: if(rc==MEMCACHED_SUCCESS){
84: data.ptr=pa_strdup(data.ptr, data.length);
85: return &memcached_deserialize(data);
86: }
1.4 moko 87:
1.2 moko 88: if(rc==MEMCACHED_NOTFOUND)
1.1 moko 89: return new VVoid();
90:
91: error("get", fm, rc);
92: return 0; // calm down compiler
93: }
94:
1.2 moko 95: Value &VMemcached::mget(ArrayString& akeys) {
96: VHash &hresult = *new VHash();
97:
98: size_t kl = akeys.count();
99:
100: if(kl==0)
101: return hresult;
102:
103: const char **keys = new const char *[kl];
1.3 moko 104: size_t *key_lengths = new size_t[kl];
1.2 moko 105:
1.6 moko 106: for(size_t i=0; i<kl; i++){
107: const String &skey = *(akeys[i]);
108: check_key(skey);
109: keys[i] = skey.cstr();
110: key_lengths[i] = skey.length();
1.2 moko 111: }
112:
1.3 moko 113: check("mget", fm, f_memcached_mget(fm, keys, key_lengths, kl));
1.2 moko 114:
1.7 ! moko 115: // memcached_fetch_result calls memcached_result_create and memcached_result_free, we don't need to do this.
! 116: memcached_result_st *results=0;
1.2 moko 117:
1.4 moko 118: memcached_return rc;
119:
1.7 ! moko 120: while((results=f_memcached_fetch_result(fm, results, &rc)) && (rc == MEMCACHED_SUCCESS)){
1.4 moko 121: const char *hkey = pa_strdup(f_memcached_result_key_value(results), f_memcached_result_key_length(results));
1.5 moko 122:
123: Serialization_data value(f_memcached_result_flags(results));
124: value.length = f_memcached_result_length(results);
125: value.ptr = pa_strdup(f_memcached_result_value(results), value.length);
126:
127: hresult.hash().put(hkey, &memcached_deserialize(value));
1.2 moko 128: }
1.4 moko 129:
130: if (rc != MEMCACHED_END && rc != MEMCACHED_NOTFOUND)
131: error("mget", fm, rc);
1.2 moko 132:
1.3 moko 133: delete keys;
134: delete key_lengths;
135:
1.2 moko 136: return hresult;
137: }
1.1 moko 138:
139: const VJunction* VMemcached::put_element(const String& aname, Value* avalue, bool /*replace*/){
1.6 moko 140: check_key(aname);
1.1 moko 141:
1.2 moko 142: time_t ttl=fttl;
143: Value* lvalue;
1.1 moko 144:
145: if(HashStringValue* hash=avalue->get_hash()) {
146: if(Value* ttl_value=hash->get(expires_name))
147: ttl=ttl_value->as_int();
148: if(lvalue=hash->get(value_name)){
149: if(lvalue->get_junction())
150: throw Exception("memcached", 0, VALUE_NAME " must not be code");
151: } else
1.2 moko 152: throw Exception("memcached", &aname, "value hash must contain ." VALUE_NAME);
1.1 moko 153: } else {
154: lvalue=avalue;
155: }
156:
1.5 moko 157: Serialization_data value;
158: avalue->serialize(value);
1.1 moko 159:
160: check("set", fm, f_memcached_set(
161: fm,
1.6 moko 162: aname.cstr(),
163: aname.length(),
1.5 moko 164: value.ptr,
165: value.length,
1.1 moko 166: ttl,
1.5 moko 167: value.flags));
1.1 moko 168:
169: return PUT_ELEMENT_REPLACED_ELEMENT;
170: }
171:
E-mail: