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: