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: