Annotation of parser3/src/types/pa_vmemcached.C, revision 1.2

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.2     ! moko       16: volatile const char * IDENT_PA_VMEMCACHED_C="$Id: pa_vmemcached.C,v 1.1 2012-03-19 22:22:59 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.2     ! moko       35: void VMemcached::open(const String& connect_string, time_t attl){
1.1       moko       36:        const char *library = memcached_library;
                     37:        const char *memcached_status = memcached_load(library);
                     38: 
                     39:        if(memcached_status)
                     40:                throw Exception("memcached", 0, "failed to load memcached library %s: %s", library, memcached_status);
                     41: 
                     42:        if(connect_string.is_empty())
                     43:                throw Exception("memcached", 0, "server name must not be empty");
                     44: 
1.2     ! moko       45:        fttl=attl;
1.1       moko       46: 
                     47:        fm=f_memcached_create(NULL);
                     48: 
                     49:        memcached_server_st* fservers = f_memcached_servers_parse(connect_string.cstr());
                     50:        check("server_push", fm, f_memcached_server_push(fm, fservers));
                     51: }
                     52: 
1.2     ! moko       53: void VMemcached::flush(time_t attl){
        !            54:        check("flush", fm, f_memcached_flush(fm, attl));
        !            55: }
        !            56: 
1.1       moko       57: void VMemcached::remove(const String& aname){
                     58:        if(aname.is_empty())
                     59:                throw Exception("memcached", 0, "key must not be empty");
                     60:        const char* key_cstr=aname.cstr();
                     61: 
                     62:        memcached_return rc=f_memcached_delete(fm, key_cstr, strlen(key_cstr), (time_t)0);
                     63:        if(rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND)
                     64:                error("delete", fm, rc);
                     65: }
                     66: 
                     67: Value* VMemcached::get_element(const String& aname) {
                     68:        if(Value *result=VStateless_object::get_element(aname))
                     69:                return result;
                     70: 
1.2     ! moko       71:        if(aname.is_empty())
        !            72:                throw Exception("memcached", 0, "key must not be empty");
1.1       moko       73: 
                     74:        size_t length;
1.2     ! moko       75:        uint32_t flags;
1.1       moko       76:        memcached_return rc;
1.2     ! moko       77:        const char* val=f_memcached_get(fm, aname.cstr(), aname.length(), &length, &flags, &rc);
1.1       moko       78: 
                     79:        if(rc==MEMCACHED_SUCCESS)
1.2     ! moko       80:                // we can't use length from memcached as there can be '\0' inside
        !            81:                return new VString(*new String(val, String::L_TAINTED));
        !            82:        if(rc==MEMCACHED_NOTFOUND)
1.1       moko       83:                return new VVoid();
                     84: 
                     85:        error("get", fm, rc);
                     86:        return 0; // calm down compiler
                     87: }
                     88: 
1.2     ! moko       89: Value &VMemcached::mget(ArrayString& akeys) {
        !            90:        VHash &hresult = *new VHash();
        !            91:        
        !            92:        size_t kl = akeys.count();
        !            93:        
        !            94:        if(kl==0)
        !            95:                return hresult;
        !            96:        
        !            97:        const char **keys = new const char *[kl];
        !            98:        size_t *key_length = new size_t[kl];
        !            99:        
        !           100:        for(int i=0; i<kl; i++){
        !           101:                const String *skey = akeys[i];
        !           102:                if(skey->is_empty())
        !           103:                        throw Exception("memcached", 0, "key must not be empty");
        !           104:                keys[i] = skey->cstr();
        !           105:                key_length[i] = skey->length();
        !           106:        }
        !           107:        
        !           108:        check("mget", fm, f_memcached_mget(fm, keys, key_length, kl));
        !           109:        
        !           110:        memcached_result_st *results=f_memcached_result_create(fm, 0);
        !           111:        
        !           112:        for(;;){
        !           113:                memcached_return rc;
        !           114:                memcached_result_st *res = f_memcached_fetch_result(fm, results, &rc);
        !           115:                if (rc == MEMCACHED_SUCCESS){
        !           116:                        // we can't use length from memcached as there can be '\0' inside
        !           117:                        String::Body hkey(f_memcached_result_key_value(res), String::L_TAINTED);
        !           118:                        String &hvalue = *new String(f_memcached_result_value(res), String::L_TAINTED);
        !           119:                        hresult.hash().put(hkey, new VString(hvalue));
        !           120:                } else {
        !           121:                        if (rc != MEMCACHED_END)
        !           122:                                error("mget", fm, rc);
        !           123:                        break;
        !           124:                }
        !           125:        }
        !           126:        
        !           127: //     f_memcached_result_free(results);
        !           128: 
        !           129:        return hresult;
        !           130: }
1.1       moko      131: 
                    132: const VJunction* VMemcached::put_element(const String& aname, Value* avalue, bool /*replace*/){
                    133:        if(aname.is_empty())
                    134:                throw Exception("memcached", 0, "key must not be empty");
                    135: 
1.2     ! moko      136:        time_t ttl=fttl;
        !           137:        Value* lvalue;
1.1       moko      138: 
                    139:        if(HashStringValue* hash=avalue->get_hash()) {
                    140:                if(Value* ttl_value=hash->get(expires_name))
                    141:                        ttl=ttl_value->as_int();
                    142:                if(lvalue=hash->get(value_name)){
                    143:                        if(lvalue->get_junction())
                    144:                                throw Exception("memcached", 0, VALUE_NAME " must not be code");
                    145:                } else
1.2     ! moko      146:                        throw Exception("memcached", &aname, "value hash must contain ." VALUE_NAME);
1.1       moko      147:        } else {
                    148:                lvalue=avalue;
                    149:        }
                    150: 
                    151:        const char* key=aname.cstr();
1.2     ! moko      152:        size_t key_length=aname.length();
1.1       moko      153: 
1.2     ! moko      154:        if(key_length > MEMCACHED_MAX_KEY)
        !           155:                throw Exception("memcached", &aname, "key length %d exceeds limit (%d bytes)", key_length, MEMCACHED_MAX_KEY);
1.1       moko      156: 
1.2     ! moko      157:        const String &value=avalue->as_string();
1.1       moko      158: 
                    159:        check("set", fm, f_memcached_set(
                    160:                        fm,
                    161:                        key,
1.2     ! moko      162:                        key_length,
        !           163:                        value.cstr(),
        !           164:                        value.length(),
1.1       moko      165:                        ttl,
1.2     ! moko      166:                        0));
1.1       moko      167: 
                    168:        return PUT_ELEMENT_REPLACED_ELEMENT;
                    169: }
                    170: 

E-mail: