Annotation of parser3/src/main/pa_db_connection.C, revision 1.20
1.1 parser 1: /** @file
1.11 paf 2: Parser: sql driver connection implementation.
1.1 parser 3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
5: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
6:
1.20 ! paf 7: $Id: pa_db_connection.C,v 1.19 2001/10/27 13:00:09 paf Exp $
! 8:
! 9: developed with LIBDB 2.7.4
1.1 parser 10: */
11:
12: #include "pa_config_includes.h"
1.19 paf 13: #ifdef DB2
1.1 parser 14:
15: #include "pa_db_connection.h"
1.11 paf 16: #include "pa_db_table.h"
1.1 parser 17: #include "pa_exception.h"
1.11 paf 18: #include "pa_threads.h"
19: #include "pa_stack.h"
20: #include "pa_common.h"
1.1 parser 21:
1.14 paf 22: // defines
23:
24: #define DB_ERROR_PREFIX "db_err: "
25: #define DB_EXCEPTION_NO_LOG_MESSAGE1 DB_ERROR_PREFIX"Ignoring log file"
26: #define DB_EXCEPTION_NO_LOG_MESSAGE2 DB_ERROR_PREFIX"log_get: unable to find checkpoint record"
27:
1.11 paf 28: // consts
29:
1.15 paf 30: /// @test increase
31: const int DB_CHECKPOINT_MINUTES=1;
32:
1.11 paf 33: const int EXPIRE_UNUSED_TABLE_SECONDS=60;
34: const int CHECK_EXPIRED_TABLES_SECONDS=EXPIRE_UNUSED_TABLE_SECONDS*2;
35:
36: // callbacks
1.10 parser 37:
1.11 paf 38: static void db_paniccall(DB_ENV *dbenv, int error) {
39: throw Exception(0, 0,
40: 0,
41: "db_panic: %s (%d)",
42: strerror(error), error);
43: }
44:
45: static void db_errcall(const char *, char *buffer) {
46: throw Exception(0, 0,
47: 0,
1.14 paf 48: DB_ERROR_PREFIX "%s",
1.11 paf 49: buffer);
50: }
1.5 parser 51:
1.13 paf 52: static void expire_table(const Hash::Key& key, Hash::Val *& value, void *info) {
53: DB_Connection& table=*static_cast<DB_Connection *>(value);
1.11 paf 54: time_t older_dies=reinterpret_cast<time_t>(info);
1.5 parser 55:
1.13 paf 56: if(table.expired(older_dies)) {
57: table.~DB_Connection(); value=0;
58: }
1.11 paf 59: }
1.5 parser 60:
1.3 parser 61: // DB_Connection
62:
1.13 paf 63: DB_Connection::DB_Connection(Pool& apool, const String& adb_home) : Pooled(apool),
64: time_used(0),
65: fdb_home(adb_home),
66: table_cache(apool),
1.11 paf 67: prev_expiration_pass_time(0) {
68: //_asm int 3;
69: char DB_DATA_DIR__VALUE[MAX_STRING];
70: char DB_LOG_DIR__VALUE[MAX_STRING];
71: char DB_TMP_DIR__VALUE[MAX_STRING];
72:
73: const char *db_home_cstr=fdb_home.cstr(String::UL_FILE_SPEC);
74:
75: snprintf(DB_DATA_DIR__VALUE, MAX_STRING, "DB_DATA_DIR %s", db_home_cstr);
76: snprintf(DB_LOG_DIR__VALUE, MAX_STRING, "DB_LOG_DIR %s", db_home_cstr);
77: snprintf(DB_TMP_DIR__VALUE, MAX_STRING, "DB_TMP_DIR %s", db_home_cstr);
78:
79: char *db_config[] = {
80: DB_DATA_DIR__VALUE,
81: DB_LOG_DIR__VALUE,
82: DB_TMP_DIR__VALUE,
83: 0
84: };
85:
86: u_int32_t flags=
1.13 paf 87: DB_THREAD
88: | DB_CREATE
1.11 paf 89: | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
90:
1.16 paf 91: // trying to open with SOFT RECOVER option set
92: memset(&dbenv, 0, sizeof(dbenv));
93:
1.14 paf 94: // error handlers
1.20 ! paf 95: #if DB_VERSION_MINOR >= 7
1.14 paf 96: dbenv.db_paniccall=db_paniccall;
1.20 ! paf 97: #endif
1.14 paf 98: dbenv.db_errcall=db_errcall;
1.16 paf 99:
100: // init
101: check("db_appinit", &fdb_home, db_appinit(
102: db_home_cstr,
103: db_config,
104: &dbenv,
105: flags
106: ));
1.11 paf 107: }
108:
1.13 paf 109: DB_Connection::~DB_Connection() {
1.11 paf 110: // close tables
1.13 paf 111: table_cache.for_each(expire_table,
1.11 paf 112: reinterpret_cast<void *>(0/* =in the past = expire[close] all*/));
113:
114: // destroy connection data
1.13 paf 115: check("db_appexit", &fdb_home, db_appexit(&dbenv));
1.11 paf 116: }
117:
118:
1.1 parser 119: void DB_Connection::check(const char *operation, const String *source, int error) {
120: switch(error) {
121: case 0:
122: // no error
123: break;
124:
125: default:
126: throw Exception(0, 0,
1.3 parser 127: source,
1.11 paf 128: "db %s error: %s (%d)",
129: operation, strerror(error), error);
1.1 parser 130: }
131: }
132:
1.15 paf 133: DB_Table_ptr DB_Connection::get_table_ptr(const String& request_file_name, const String *source) {
134: // checkpoint
135: check("checkpoint", source,
136: txn_checkpoint(dbenv.tx_info, 0/*kbyte*/, DB_CHECKPOINT_MINUTES/*min*/));
1.11 paf 137:
138: // first trying to get cached table
139: DB_Table *result=get_table_from_cache(request_file_name);
1.13 paf 140: if(!result) { // no cached table
1.11 paf 141: // make global_file_name C-string on global pool
1.13 paf 142: const char *request_file_name_cstr=request_file_name.cstr(String::UL_AS_IS);
1.11 paf 143: char *global_file_name_cstr=(char *)malloc(strlen(request_file_name_cstr)+1);
144: strcpy(global_file_name_cstr, request_file_name_cstr);
145: // make global_file_name string on global pool
146: String& global_file_name=*new(this->pool()) String(this->pool(), global_file_name_cstr);
147:
148: // allocate in global pool
149: // associate with services[request]
150: // NOTE: never freed up!
151: result=new(this->pool()) DB_Table(this->pool(), global_file_name, *this);
1.13 paf 152: // cache it
153: put_table_to_cache(global_file_name, *result);
1.4 parser 154: }
1.1 parser 155:
1.13 paf 156: // return auto-it
157: return DB_Table_ptr(result);
1.1 parser 158: }
1.11 paf 159:
160: // table cache
161: /// @todo get rid of memory spending Stack [zeros deep inside got accumulated]
162: DB_Table *DB_Connection::get_table_from_cache(const String& file_name) {
163: SYNCHRONIZED;
1.17 paf 164:
165: maybe_expire_table_cache();
1.11 paf 166:
1.13 paf 167: return static_cast<DB_Table *>(table_cache.get(file_name));
1.3 parser 168: }
169:
1.13 paf 170: void DB_Connection::put_table_to_cache(const String& file_name, DB_Table& table) {
1.11 paf 171: SYNCHRONIZED;
1.3 parser 172:
1.13 paf 173: table_cache.put(file_name, &table);
1.3 parser 174: }
175:
1.11 paf 176: void DB_Connection::maybe_expire_table_cache() {
177: time_t now=time(0);
178:
179: if(prev_expiration_pass_time<now-CHECK_EXPIRED_TABLES_SECONDS) {
1.13 paf 180: table_cache.for_each(expire_table,
1.11 paf 181: reinterpret_cast<void *>(now-EXPIRE_UNUSED_TABLE_SECONDS));
1.3 parser 182:
1.11 paf 183: prev_expiration_pass_time=now;
1.9 parser 184: }
1.1 parser 185: }
186:
187: #endif
E-mail: