Annotation of parser3/src/types/pa_vhashfile.C, revision 1.29

1.1       parser      1: /** @file
                      2:        Parser: @b table class.
                      3: 
1.20      paf         4:        Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
1.19      paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.1       parser      6: */
                      7: 
1.29    ! paf         8: static const char* IDENT="$Date: 2003/11/06 11:53:54 $";
1.1       parser      9: 
                     10: #include "pa_vtable.h"
                     11: #include "pa_vstring.h"
                     12: #include "pa_vhashfile.h"
                     13: #include "pa_threads.h"
1.8       parser     14: #include "pa_globals.h"
1.1       parser     15: 
                     16: // methods
                     17: 
1.22      paf        18: void check(const char *step, apr_status_t status) {
                     19:        if(status==APR_SUCCESS)
                     20:                return;
                     21: 
                     22:        throw Exception("todo.todo",
                     23:                0,
                     24:                "%s error: %d", step, status);
                     25: }
                     26: 
                     27: void VHashfile::open(const String& afile_name) {
1.27      paf        28:        check("apr_sdbm_open(shared)", apr_sdbm_open(&db, file_name=afile_name.cstr(String::L_FILE_SPEC), 
                     29:                                         APR_CREATE|APR_READ|APR_SHARELOCK, 
1.22      paf        30:                                         0664, 0));
                     31: }
                     32: 
1.27      paf        33: void VHashfile::make_writable() {
                     34:        if(db && apr_sdbm_rdonly(db)) {
                     35:                check("apr_sdbm_close", apr_sdbm_close(db));
                     36:                check("apr_sdbm_open(exclusive)", apr_sdbm_open(&db, file_name, 
                     37:                                                                                        APR_WRITE, 
                     38:                                                                                        0664, 0));
                     39:        }
                     40: }
                     41: 
1.22      paf        42: VHashfile::~VHashfile() {
                     43:        if(db)
                     44:                check("apr_sdbm_close", apr_sdbm_close(db));
                     45: }
                     46: 
1.27      paf        47: void VHashfile::put_field(const String& aname, Value *avalue) {
                     48:        make_writable();
1.22      paf        49: 
1.8       parser     50:        time_t time_to_die=0;
                     51:        const String *value_string;
                     52: 
1.23      paf        53:        if(HashStringValue *hash=avalue->get_hash()) {
                     54:                if(Value *value_value=hash->get(value_name)) {
1.9       parser     55:                        if(value_value->get_junction())
1.23      paf        56:                                throw Exception(0,
                     57:                                        0,
                     58:                                        VALUE_NAME" must not be code");
1.8       parser     59: 
                     60:                        value_string=&value_value->as_string();
                     61: 
1.23      paf        62:                        if(Value *expires_value=hash->get(expires_name))
1.8       parser     63:                                time_to_die=time(0)+(time_t)expires_value->as_double();
                     64:                } else
1.23      paf        65:                        throw Exception(0,
1.8       parser     66:                                &aname,
1.23      paf        67:                                "put hash value must contain ."VALUE_NAME);
1.8       parser     68:        } else
                     69:                value_string=&avalue->as_string();
1.5       parser     70: 
1.23      paf        71:        apr_sdbm_datum_t key;
                     72:        key.dptr=const_cast<char*>(aname.cstr());
1.24      paf        73:        key.dsize=aname.length();
1.23      paf        74: 
                     75:        apr_sdbm_datum_t value;
                     76:        value.dptr=const_cast<char*>(value_string->cstr());
1.24      paf        77:        value.dsize=value_string->length();
1.23      paf        78: 
                     79:        check("apr_sdbm_store", apr_sdbm_store(db, key, value, APR_SDBM_REPLACE));
1.1       parser     80: }
                     81: 
1.11      paf        82: Value *VHashfile::get_field(const String& aname) {
1.23      paf        83:        apr_sdbm_datum_t key;
                     84:        key.dptr=const_cast<char*>(aname.cstr());
1.24      paf        85:        key.dsize=aname.length();
1.23      paf        86: 
                     87:        apr_sdbm_datum_t value;
                     88: 
                     89:        check("apr_sdbm_fetch", apr_sdbm_fetch(db, &value, key));
                     90: 
1.28      paf        91:        return value.dptr?
                     92:                new VString(*new String(pa_strdup(value.dptr, value.dsize), true))
                     93:                : 0;
1.24      paf        94: }
                     95: 
                     96: void VHashfile::remove(const String& aname) {
1.27      paf        97:        make_writable();
                     98: 
1.24      paf        99:        apr_sdbm_datum_t key;
                    100:        key.dptr=const_cast<char*>(aname.cstr());
                    101:        key.dsize=aname.length();
                    102: 
                    103:        check("apr_sdbm_delete", apr_sdbm_delete(db, key));
1.1       parser    104: }
                    105: 
1.27      paf       106: void VHashfile::for_each(void callback(apr_sdbm_datum_t, void*), void* info) const {
1.25      paf       107:        check("apr_sdbm_lock", apr_sdbm_lock(db, APR_FLOCK_SHARED));
                    108:        try {
                    109:                apr_sdbm_datum_t apkey;
                    110:                if(apr_sdbm_firstkey(db, &apkey)==APR_SUCCESS)
                    111:                        do {
1.27      paf       112:                                callback(apkey, info);
1.25      paf       113:                        } while(apr_sdbm_nextkey(db, &apkey)==APR_SUCCESS);
                    114:        } catch(...) {
                    115:                        check("apr_sdbm_unlock", apr_sdbm_unlock(db));
                    116:                        rethrow;
1.4       parser    117:        }
                    118: 
1.25      paf       119:        check("apr_sdbm_unlock", apr_sdbm_unlock(db));
1.26      paf       120: }
1.27      paf       121: 
                    122: #ifndef DOXYGEN
                    123: struct For_each_string_callback_info {
                    124:        apr_sdbm_t *db;
                    125:        void* nested_info;
                    126:        void (*nested_callback)(const String::Body, const String&, void*);
                    127: };
                    128: #endif
                    129: static void for_each_string_callback(apr_sdbm_datum_t apkey, void* ainfo) {
                    130:        For_each_string_callback_info& info=*static_cast<For_each_string_callback_info *>(ainfo);
                    131: 
                    132:        apr_sdbm_datum_t apvalue;
                    133:        check("apr_sdbm_fetch", apr_sdbm_fetch(info.db, &apvalue, apkey));
                    134: 
                    135:        const char *clkey=pa_strdup(apkey.dptr, apkey.dsize);
                    136:        const char *clvalue=pa_strdup(apvalue.dptr, apvalue.dsize);
                    137:        const String& svalue=*new String(clvalue, true);
                    138:        info.nested_callback(clkey, svalue, info.nested_info);
                    139: }
                    140: void VHashfile::for_each(void callback(const String::Body, const String&, void*), void* ainfo) const {
                    141:        For_each_string_callback_info info;
                    142:        
                    143:        info.db=db;
                    144:        info.nested_info=ainfo;
                    145:        info.nested_callback=callback;
                    146: 
                    147:        for_each(for_each_string_callback, &info);
                    148: }
                    149: 
1.29    ! paf       150: typedef Array<apr_sdbm_datum_t> apr_sdbm_datum_array_t;
        !           151: static void clear_collect_key(apr_sdbm_datum_array_t::element_type key, 
        !           152:                                                          void* aapr_sdbm_datum_array) {
        !           153:        *static_cast<apr_sdbm_datum_array_t *>(aapr_sdbm_datum_array)+=key;
        !           154: }
        !           155: static void clear_delete_key(apr_sdbm_datum_t key, apr_sdbm_t *db) {
        !           156:        check("apr_sdbm_delete", apr_sdbm_delete(db, key));
1.27      paf       157: }
                    158: void VHashfile::clear() {
                    159:        make_writable();
                    160: 
1.29    ! paf       161:        apr_sdbm_datum_array_t keys;
        !           162:        for_each(clear_collect_key, &keys);
        !           163:        keys.for_each(clear_delete_key, db);
1.27      paf       164: }
                    165: 
1.26      paf       166: 
                    167: static void get_hash__put(const String::Body key, const String& value, void* aresult) {
                    168:        static_cast<HashStringValue*>(aresult)->put(key, new VString(value));
                    169: }
                    170: 
                    171: HashStringValue *VHashfile::get_hash() {
                    172:        HashStringValue& result=*new HashStringValue();
                    173: 
                    174:        for_each(get_hash__put, &result);
                    175:        return &result;
1.1       parser    176: }

E-mail: