Annotation of parser3/src/main/pa_db_table.C, revision 1.1

1.1     ! paf         1: /** @file
        !             2:        Parser: Charset table implementation.
        !             3: 
        !             4:        Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
        !             5:        Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
        !             6: 
        !             7:        $Id: pa_db_table.C,v 1.10 2001/10/24 14:11:25 parser Exp $
        !             8: */
        !             9: 
        !            10: #include "pa_config_includes.h"
        !            11: #ifdef HAVE_LIBDB
        !            12: 
        !            13: #include "pa_db_table.h"
        !            14: #include "pa_exception.h"
        !            15: 
        !            16: // defines
        !            17: 
        !            18: #define READ_ADDITIONAL_FLAGS DB_RMW
        !            19: 
        !            20: // consts
        !            21: 
        !            22: const int DATA_STRING_SERIALIZED_VERSION=0x0100;
        !            23: 
        !            24: // helper types
        !            25: 
        !            26: #ifndef DOXYGEN
        !            27: struct Data_string_serialized_prolog {
        !            28:        int version;
        !            29:        time_t time_to_die;
        !            30: };
        !            31: #endif
        !            32: 
        !            33: // DB_Table
        !            34: 
        !            35: DB_Table::DB_Table(Pool& pool, const String& afile_spec, DB_Connection& aconnection) : Pooled(pool),
        !            36:        time_used(0), fservices_pool(0)        !            37:        fconnection(aconnection),
        !            38:        dbenv(aconnection.dbenv),
        !            39:        ffile_spec(afile_spec), file_spec_cstr(afile_spec.cstr(String::UL_FILE_SPEC)),
        !            40:        db(0), ftid(0), errors(0) {
        !            41: }
        !            42: 
        !            43: void DB_Table::check(const char *operation, const String *source, int error) {
        !            44:        switch(error) {
        !            45:        case 0: 
        !            46:                // no error
        !            47:                break; 
        !            48:        
        !            49:        case DB_KEYEXIST:
        !            50:                // DB_KEYEXIST is a "normal" return, so should not be
        !            51:                // thrown as an error
        !            52:                break; 
        !            53: 
        !            54:        case DB_RUNRECOVERY:
        !            55:                errors++;
        !            56:                throw Exception(0, 0, 
        !            57:                        source,
        !            58:                        "action failed, RUN RECOVERY UTILITY. db %s error, real filename '%s'", 
        !            59:                        operation, file_spec_cstr);
        !            60:                
        !            61:        default:
        !            62:                errors++;
        !            63:                throw Exception(0, 0, 
        !            64:                        source, 
        !            65:                        "action failed. db %s error: %s (%d), real filename '%s'", 
        !            66:                        operation, strerror(error), error, file_spec_cstr);
        !            67:        }
        !            68: }
        !            69: 
        !            70: void DB_Table::key_string_to_dbt(const String& key_string, DBT& key_result) {
        !            71:        memset(&key_result, 0, sizeof(key_result));
        !            72:        key_result.data=key_string.cstr(String::UL_AS_IS);
        !            73:        key_result.size=key_string.size();
        !            74: }
        !            75: 
        !            76: String& DB_Table::key_dbt_to_string(const DBT& key_dbt) {
        !            77:        String& result=*new(*fservices_pool) String(*fservices_pool);
        !            78:        if(key_dbt.size) {
        !            79:                char *request_data=(char *)malloc(key_dbt.size);
        !            80:                memcpy(request_data, key_dbt.data, key_dbt.size);
        !            81:                result.APPEND_TAINTED(request_data, key_dbt.size, file_spec_cstr, 0/*line*/);
        !            82:        }
        !            83:        return result;
        !            84: }
        !            85: 
        !            86: void DB_Table::data_string_to_dbt(const String& data_string, time_t time_to_die, 
        !            87:                                                                           DBT& data_result) {
        !            88:        memset(&data_result, 0, sizeof(data_result));
        !            89: 
        !            90:        data_string.serialize(
        !            91:                sizeof(Data_string_serialized_prolog), 
        !            92:                data_result.data, data_result.size);
        !            93: 
        !            94:        Data_string_serialized_prolog& prolog=
        !            95:                *static_cast<Data_string_serialized_prolog *>(data_result.data);
        !            96: 
        !            97:        prolog.version=DATA_STRING_SERIALIZED_VERSION;
        !            98:        prolog.time_to_die=time_to_die;
        !            99: }
        !           100: 
        !           101: String *DB_Table::data_dbt_to_string(const DBT& data_dbt) {
        !           102:        Data_string_serialized_prolog& prolog=
        !           103:                *static_cast<Data_string_serialized_prolog *>(data_dbt.data);
        !           104: 
        !           105:        if(prolog.version!=DATA_STRING_SERIALIZED_VERSION)
        !           106:                throw Exception(0, 0,
        !           107:                        &ffile_spec,
        !           108:                        "data string version 0x%04X not equal to 0x%04X, recreate file",
        !           109:                                prolog.version, DATA_STRING_SERIALIZED_VERSION);
        !           110: 
        !           111:        if(prolog.time_to_die/*specified*/ && prolog.time_to_die <= time(0)/*expired*/)
        !           112:                return 0;
        !           113: 
        !           114:        String& result=*new(*fservices_pool) String(*fservices_pool);
        !           115:        result.deserialize(
        !           116:                sizeof(Data_string_serialized_prolog), 
        !           117:                data_dbt.data, data_dbt.size, file_spec_cstr);
        !           118:        return &result;
        !           119: }
        !           120: 
        !           121: void DB_Table::connect() { 
        !           122:        // open
        !           123:        DB_INFO dbinfo;
        !           124:        memset(&dbinfo, 0, sizeof(dbinfo));
        !           125:        check("open/create", &ffile_spec, db_open(
        !           126:                file_spec_cstr, 
        !           127:                PA_DB_ACCESS_METHOD, 
        !           128:                DB_CREATE /* used in single thread, no need for |DB_THREAD*/,
        !           129:                0666, 
        !           130:                &dbenv, &dbinfo, &db));
        !           131: }
        !           132: /// @todo this one of reasons of not having ^try for now
        !           133: void DB_Table::disconnect() { 
        !           134:        check("close", &ffile_spec, db->close(db, 0/*flags*/));  db=0; 
        !           135: }
        !           136: 
        !           137: void DB_Table::put(const String& key, const String& data, time_t time_to_die) {
        !           138:        DBT dbt_key;  key_string_to_dbt(key, dbt_key);
        !           139:        DBT dbt_data;  data_string_to_dbt(data, time_to_die, dbt_data);
        !           140:        check("put", &key, db->put(db, ftid, &dbt_key, &dbt_data, 0/*flags*/));
        !           141: }
        !           142: 
        !           143: String *DB_Table::get(const String& key) {
        !           144:        DBT dbt_key;  key_string_to_dbt(key, dbt_key);
        !           145:        DBT dbt_data={0}; // must be zeroed
        !           146:        int error=db->get(db, ftid, &dbt_key, &dbt_data, READ_ADDITIONAL_FLAGS/*flags*/);
        !           147:        if(error==DB_NOTFOUND)
        !           148:                return 0;
        !           149:        else {
        !           150:                check("get", &key, error);
        !           151:                String *result=data_dbt_to_string(dbt_data);
        !           152:                if(!result) // save efforts by deleting expired keys
        !           153:                        check("del expired", &key, db->del(db, ftid, &dbt_key, 0/*flags*/));
        !           154:                return result;
        !           155:        }               
        !           156: }
        !           157: 
        !           158: void DB_Table::remove(const String& key) {
        !           159:        DBT dbt_key;  key_string_to_dbt(key, dbt_key);
        !           160: 
        !           161:        int error=db->del(db, ftid, &dbt_key, 0/*flags*/);
        !           162:        if(error!=DB_NOTFOUND)
        !           163:                check("del", &key, error);
        !           164: }
        !           165: 
        !           166: // DB_Cursor
        !           167: 
        !           168: DB_Cursor::DB_Cursor(
        !           169:                                         DB_Table& atable, 
        !           170:                                         const String *asource) : fsource(asource), ftable(atable), cursor(0) {
        !           171:        check("cursor", fsource, ftable.db->cursor(ftable.db,
        !           172:                ftable.ftid, &cursor, 0/*flags*/));
        !           173: }
        !           174: 
        !           175: DB_Cursor::~DB_Cursor() {
        !           176:        if(cursor) {
        !           177:                check("c_close", fsource, cursor->c_close(cursor));  cursor=0;
        !           178:        }
        !           179: }
        !           180: 
        !           181: bool DB_Cursor::get(String *& key, String *& data, u_int32_t flags) {
        !           182:        DBT dbt_key={0}; // must be zeroed
        !           183:        DBT dbt_data={0}; // must be zeroed
        !           184:        
        !           185:        int error=cursor->c_get(cursor, &dbt_key, &dbt_data, flags | READ_ADDITIONAL_FLAGS);
        !           186:        if(error==DB_NOTFOUND)
        !           187:                return false;
        !           188: 
        !           189:        check("c_get", fsource, error);
        !           190: 
        !           191:        if(data=data_dbt_to_string(dbt_data)) // not expired
        !           192:                key=&key_dbt_to_string(dbt_key);
        !           193:        else {
        !           194:                // save efforts by deleting expired keys
        !           195:                remove(0/*flags*/);
        !           196:                key=0;
        !           197:        }
        !           198:        return true;
        !           199: }
        !           200: 
        !           201: void DB_Cursor::remove(u_int32_t flags) {
        !           202:        check("c_del", fsource,  cursor->c_del(cursor, flags));
        !           203: }
        !           204: 
        !           205: #endif

E-mail: