Annotation of parser3/src/main/pa_db_connection.C, revision 1.28
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)
1.28 ! paf 5: Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru)
1.1 parser 6:
1.28 ! paf 7: $Id: pa_db_connection.C,v 1.27 2001/10/31 15:00:05 paf Exp $
1.20 paf 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.28 ! paf 21: #include "pa_vtable.h"
1.1 parser 22:
1.14 paf 23: // defines
24:
1.11 paf 25: // consts
26:
1.15 paf 27: /// @test increase
28: const int DB_CHECKPOINT_MINUTES=1;
29:
1.11 paf 30: const int EXPIRE_UNUSED_TABLE_SECONDS=60;
31: const int CHECK_EXPIRED_TABLES_SECONDS=EXPIRE_UNUSED_TABLE_SECONDS*2;
32:
33: // callbacks
1.10 parser 34:
1.11 paf 35: static void db_paniccall(DB_ENV *dbenv, int error) {
36: throw Exception(0, 0,
37: 0,
38: "db_panic: %s (%d)",
39: strerror(error), error);
40: }
41:
42: static void db_errcall(const char *, char *buffer) {
43: throw Exception(0, 0,
44: 0,
1.23 paf 45: "db_err: %s",
1.11 paf 46: buffer);
47: }
1.5 parser 48:
1.13 paf 49: static void expire_table(const Hash::Key& key, Hash::Val *& value, void *info) {
1.22 paf 50: DB_Table& table=*static_cast<DB_Table *>(value);
1.11 paf 51: time_t older_dies=reinterpret_cast<time_t>(info);
1.5 parser 52:
1.13 paf 53: if(table.expired(older_dies)) {
1.22 paf 54: table.~DB_Table(); value=0;
1.13 paf 55: }
1.11 paf 56: }
1.5 parser 57:
1.3 parser 58: // DB_Connection
59:
1.13 paf 60: DB_Connection::DB_Connection(Pool& apool, const String& adb_home) : Pooled(apool),
61: time_used(0),
1.28 ! paf 62: fdb_home(adb_home), used(0),
1.13 paf 63: table_cache(apool),
1.11 paf 64: prev_expiration_pass_time(0) {
65: //_asm int 3;
66: char DB_DATA_DIR__VALUE[MAX_STRING];
67: char DB_LOG_DIR__VALUE[MAX_STRING];
68: char DB_TMP_DIR__VALUE[MAX_STRING];
69:
70: const char *db_home_cstr=fdb_home.cstr(String::UL_FILE_SPEC);
71:
72: snprintf(DB_DATA_DIR__VALUE, MAX_STRING, "DB_DATA_DIR %s", db_home_cstr);
73: snprintf(DB_LOG_DIR__VALUE, MAX_STRING, "DB_LOG_DIR %s", db_home_cstr);
74: snprintf(DB_TMP_DIR__VALUE, MAX_STRING, "DB_TMP_DIR %s", db_home_cstr);
75:
76: char *db_config[] = {
77: DB_DATA_DIR__VALUE,
78: DB_LOG_DIR__VALUE,
79: DB_TMP_DIR__VALUE,
80: 0
81: };
82:
83: u_int32_t flags=
1.25 paf 84: parser_multithreaded?DB_THREAD:0
1.13 paf 85: | DB_CREATE
1.11 paf 86: | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
87:
1.27 paf 88: // prepare dbenv structure
1.16 paf 89: memset(&dbenv, 0, sizeof(dbenv));
90:
1.14 paf 91: // error handlers
1.20 paf 92: #if DB_VERSION_MINOR >= 7
1.14 paf 93: dbenv.db_paniccall=db_paniccall;
1.20 paf 94: #endif
1.14 paf 95: dbenv.db_errcall=db_errcall;
1.26 paf 96:
97: // lockdetector flags
98: dbenv.lk_detect=DB_LOCK_RANDOM;
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.28 ! paf 107:
! 108: // after some hang noticed this to be null
! 109: if(!dbenv.tx_info)
! 110: throw Exception(0, 0,
! 111: &fdb_home,
! 112: "transaction system failed to initialize");
1.11 paf 113: }
114:
1.13 paf 115: DB_Connection::~DB_Connection() {
1.11 paf 116: // close tables
1.13 paf 117: table_cache.for_each(expire_table,
1.11 paf 118: reinterpret_cast<void *>(0/* =in the past = expire[close] all*/));
119:
120: // destroy connection data
1.13 paf 121: check("db_appexit", &fdb_home, db_appexit(&dbenv));
1.11 paf 122: }
123:
124:
1.1 parser 125: void DB_Connection::check(const char *operation, const String *source, int error) {
126: switch(error) {
127: case 0:
128: // no error
129: break;
130:
131: default:
1.21 paf 132: if(error<0)
133: throw Exception(0, 0,
134: source,
135: "db %s error: %d",
136: operation, error);
137: else
138: throw Exception(0, 0,
139: source,
140: "db %s error: %s (%d)",
141: operation, strerror(error), error);
1.1 parser 142: }
143: }
144:
1.15 paf 145: DB_Table_ptr DB_Connection::get_table_ptr(const String& request_file_name, const String *source) {
146: // checkpoint
1.28 ! paf 147: {
1.21 paf 148: int error=txn_checkpoint(dbenv.tx_info, 0/*kbyte*/, DB_CHECKPOINT_MINUTES/*min*/);
149: /*
150: DB_INCOMPLETE if there were pages that needed to be written
151: but that memp_sync was unable to write immediately.
152: In this case, the txn_checkpoint call should be retried.
153:
154: we'll just ignore that
155: */
156: if(error!=DB_INCOMPLETE)
157: check("checkpoint", source, error);
158: }
1.11 paf 159:
160: // first trying to get cached table
161: DB_Table *result=get_table_from_cache(request_file_name);
1.13 paf 162: if(!result) { // no cached table
1.11 paf 163: // make global_file_name C-string on global pool
1.24 paf 164: const char *request_file_name_cstr=request_file_name.cstr();
1.11 paf 165: char *global_file_name_cstr=(char *)malloc(strlen(request_file_name_cstr)+1);
166: strcpy(global_file_name_cstr, request_file_name_cstr);
167: // make global_file_name string on global pool
168: String& global_file_name=*new(this->pool()) String(this->pool(), global_file_name_cstr);
169:
170: // allocate in global pool
171: // associate with services[request]
172: // NOTE: never freed up!
173: result=new(this->pool()) DB_Table(this->pool(), global_file_name, *this);
1.13 paf 174: // cache it
175: put_table_to_cache(global_file_name, *result);
1.4 parser 176: }
1.1 parser 177:
1.13 paf 178: // return auto-it
179: return DB_Table_ptr(result);
1.1 parser 180: }
1.11 paf 181:
182: // table cache
183: /// @todo get rid of memory spending Stack [zeros deep inside got accumulated]
184: DB_Table *DB_Connection::get_table_from_cache(const String& file_name) {
185: SYNCHRONIZED;
1.17 paf 186:
187: maybe_expire_table_cache();
1.11 paf 188:
1.13 paf 189: return static_cast<DB_Table *>(table_cache.get(file_name));
1.3 parser 190: }
191:
1.13 paf 192: void DB_Connection::put_table_to_cache(const String& file_name, DB_Table& table) {
1.11 paf 193: SYNCHRONIZED;
1.3 parser 194:
1.13 paf 195: table_cache.put(file_name, &table);
1.3 parser 196: }
197:
1.11 paf 198: void DB_Connection::maybe_expire_table_cache() {
199: time_t now=time(0);
200:
201: if(prev_expiration_pass_time<now-CHECK_EXPIRED_TABLES_SECONDS) {
1.13 paf 202: table_cache.for_each(expire_table,
1.11 paf 203: reinterpret_cast<void *>(now-EXPIRE_UNUSED_TABLE_SECONDS));
1.3 parser 204:
1.11 paf 205: prev_expiration_pass_time=now;
1.9 parser 206: }
1.28 ! paf 207: }
! 208:
! 209: static void add_table_to_status_table(const Hash::Key& key, Hash::Val *& value, void *info) {
! 210: DB_Table& db_table=*static_cast<DB_Table *>(value);
! 211: Table& status_table=*static_cast<Table *>(info);
! 212: Pool& pool=status_table.pool();
! 213:
! 214: Array& row=*new(pool) Array(pool);
! 215:
! 216: // name
! 217: row+=&db_table.file_name();
! 218: // time
! 219: time_t time_stamp=db_table.get_time_used();
! 220: const char *unsafe_time_cstr=ctime(&time_stamp);
! 221: int time_buf_size=strlen(unsafe_time_cstr);
! 222: char *safe_time_buf=(char *)pool.malloc(time_buf_size);
! 223: memcpy(safe_time_buf, unsafe_time_cstr, time_buf_size);
! 224: row+=new(pool) String(pool, safe_time_buf, time_buf_size);
! 225: // users
! 226: char *users_buf=(char *)pool.malloc(MAX_NUMBER);
! 227: row+=new(pool) String(pool,
! 228: users_buf, snprintf(users_buf, MAX_NUMBER, "%d", db_table.get_users_count()));
! 229:
! 230: status_table+=&row;
! 231: }
! 232: Value& DB_Connection::get_status(Pool& pool, const String *source) {
! 233: Array& columns=*new(pool) Array(pool);
! 234: columns+=new(pool) String(pool, "name");
! 235: columns+=new(pool) String(pool, "time");
! 236: columns+=new(pool) String(pool, "users");
! 237: Table& table=*new(pool) Table(pool, 0, &columns, table_cache.size());
! 238:
! 239: table_cache.for_each(add_table_to_status_table, &table);
! 240:
! 241: return *new(pool) VTable(pool, &table);
1.1 parser 242: }
243:
244: #endif
E-mail: