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