Annotation of parser3/src/main/pa_db_connection.C, revision 1.5
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.5 ! parser 7: $Id: pa_db_connection.C,v 1.4 2001/10/24 09:03:42 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:
! 99: if(prolog.time_to_die/*specified*/ && prolog.time_to_die >= time(0)/*expired*/)
! 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:
132: /// @test string pieces [get/put preserve lang]
1.5 ! parser 133: void DB_Connection::put(const String& key, const String& data, time_t time_to_die) {
1.4 parser 134: DBT dbt_key; key_string_to_dbt(key, dbt_key);
1.5 ! parser 135: DBT dbt_data; data_string_to_dbt(data, time_to_die, dbt_data);
1.2 parser 136: check("put", &key, db->put(db, ftid, &dbt_key, &dbt_data, 0/*flags*/));
1.1 parser 137: }
138:
139: String *DB_Connection::get(const String& key) {
1.4 parser 140: DBT dbt_key; key_string_to_dbt(key, dbt_key);
1.1 parser 141: // data
142: DBT dbt_data={0}; // must be zeroed
1.2 parser 143: int error=db->get(db, ftid, &dbt_key, &dbt_data, 0/*flags*/);
144: if(error==DB_NOTFOUND)
145: return 0;
146: else {
147: check("get", &key, error);
1.5 ! parser 148: return data_dbt_to_string(dbt_data);
1.2 parser 149: }
150: }
151:
152: void DB_Connection::_delete(const String& key) {
1.4 parser 153: DBT dbt_key; key_string_to_dbt(key, dbt_key);
1.1 parser 154:
1.2 parser 155: int error=db->del(db, ftid, &dbt_key, 0/*flags*/);
156: if(error!=DB_NOTFOUND)
157: check("del", &key, error);
1.3 parser 158: }
159:
160: DB_Cursor DB_Connection::cursor(const String *source) {
161: return DB_Cursor(*this, source);
162: }
163:
164: // DB_Cursor
165:
166: DB_Cursor::DB_Cursor(
167: DB_Connection& aconnection,
168: const String *asource) : fsource(asource), fconnection(aconnection), cursor(0) {
169: check("cursor", fsource, fconnection.db->cursor(fconnection.db,
170: fconnection.ftid, &cursor, 0/*flags*/));
171: }
172:
173: DB_Cursor::~DB_Cursor() {
174: if(cursor) {
175: check("c_close", fsource, cursor->c_close(cursor)); cursor=0;
176: }
177: }
178:
1.5 ! parser 179: bool DB_Cursor::get(String *& key, String *& data, u_int32_t flags) {
1.3 parser 180: DBT dbt_key={0}; // must be zeroed
181: DBT dbt_data={0}; // must be zeroed
182:
183: int error=cursor->c_get(cursor, &dbt_key, &dbt_data, flags);
184: if(error==DB_NOTFOUND)
185: return false;
186:
187: check("c_get", fsource, error);
188:
1.5 ! parser 189: key=&key_dbt_to_string(dbt_key);
! 190: data=data_dbt_to_string(dbt_data);
1.3 parser 191: return true;
1.1 parser 192: }
193:
194: #endif
E-mail: