Annotation of parser3/src/main/pa_db_connection.C, revision 1.8

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

E-mail: