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: