Annotation of parser3/src/main/pa_db_connection.C, revision 1.13
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.13 ! paf 7: $Id: pa_db_connection.C,v 1.12 2001/10/26 07:07:01 paf Exp $
1.1 parser 8: */
9:
10: #include "pa_config_includes.h"
11: #ifdef HAVE_LIBDB
12:
13: #include "pa_db_connection.h"
1.11 paf 14: #include "pa_db_table.h"
1.1 parser 15: #include "pa_exception.h"
1.11 paf 16: #include "pa_threads.h"
17: #include "pa_stack.h"
18: #include "pa_common.h"
1.1 parser 19:
1.11 paf 20: // consts
21:
22: const int EXPIRE_UNUSED_TABLE_SECONDS=60;
23: const int CHECK_EXPIRED_TABLES_SECONDS=EXPIRE_UNUSED_TABLE_SECONDS*2;
24:
25: const char *DB_WARNING1="Finding last valid log LSN";
1.10 parser 26:
1.11 paf 27: // callbacks
1.10 parser 28:
1.11 paf 29: static void db_paniccall(DB_ENV *dbenv, int error) {
30: throw Exception(0, 0,
31: 0,
32: "db_panic: %s (%d)",
33: strerror(error), error);
34: }
35:
36: static void db_errcall(const char *, char *buffer) {
37: // were it warning?
38: if(strncmp(buffer, DB_WARNING1, strlen(DB_WARNING1))==0)
39: return;
1.5 parser 40:
1.11 paf 41: throw Exception(0, 0,
42: 0,
43: "db_err: %s",
44: buffer);
45: }
1.5 parser 46:
1.13 ! paf 47: static void expire_table(const Hash::Key& key, Hash::Val *& value, void *info) {
! 48: DB_Connection& table=*static_cast<DB_Connection *>(value);
1.11 paf 49: time_t older_dies=reinterpret_cast<time_t>(info);
1.5 parser 50:
1.13 ! paf 51: if(table.expired(older_dies)) {
! 52: table.~DB_Connection(); value=0;
! 53: }
1.11 paf 54: }
1.5 parser 55:
1.3 parser 56: // DB_Connection
57:
1.13 ! paf 58: DB_Connection::DB_Connection(Pool& apool, const String& adb_home) : Pooled(apool),
! 59: time_used(0),
! 60: fdb_home(adb_home),
! 61: table_cache(apool),
1.11 paf 62: prev_expiration_pass_time(0) {
63: //_asm int 3;
64: memset(&dbenv, 0, sizeof(dbenv));
65: dbenv.db_paniccall=db_paniccall;
66: dbenv.db_errcall=db_errcall;
67:
68: char DB_DATA_DIR__VALUE[MAX_STRING];
69: char DB_LOG_DIR__VALUE[MAX_STRING];
70: char DB_TMP_DIR__VALUE[MAX_STRING];
71:
72: const char *db_home_cstr=fdb_home.cstr(String::UL_FILE_SPEC);
73:
74: snprintf(DB_DATA_DIR__VALUE, MAX_STRING, "DB_DATA_DIR %s", db_home_cstr);
75: snprintf(DB_LOG_DIR__VALUE, MAX_STRING, "DB_LOG_DIR %s", db_home_cstr);
76: snprintf(DB_TMP_DIR__VALUE, MAX_STRING, "DB_TMP_DIR %s", db_home_cstr);
77:
78: char *db_config[] = {
79: DB_DATA_DIR__VALUE,
80: DB_LOG_DIR__VALUE,
81: DB_TMP_DIR__VALUE,
82: 0
83: };
84:
85: u_int32_t flags=
1.13 ! paf 86: DB_THREAD
! 87: | DB_CREATE
1.11 paf 88: | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN;
89:
1.12 paf 90: /* try {
1.11 paf 91: // 1: trying to open with SOFT RECOVER option set
92: check("db_appinit soft recover", &fdb_home, db_appinit(
93: db_home_cstr,
94: db_config,
95: &dbenv,
96: flags | DB_RECOVER
97: ));
98: } catch(...) {
1.12 paf 99: try {*/
1.11 paf 100: // 2: trying to open WITHOUT SOFT RECOVER option set
101: check("db_appinit no recover", &fdb_home, db_appinit(
102: db_home_cstr,
103: db_config,
104: &dbenv,
105: flags
106: ));
1.12 paf 107: /* } catch(...) {
1.11 paf 108: // 3: trying to open with FATAL RECOVER option set
109: check("db_appinit fatal recover", &fdb_home, db_appinit(
110: db_home_cstr,
111: db_config,
112: &dbenv,
113: flags | DB_RECOVER_FATAL
114: ));
115: }
1.12 paf 116: }*/
1.11 paf 117: }
118:
1.13 ! paf 119: DB_Connection::~DB_Connection() {
1.11 paf 120: // close tables
1.13 ! paf 121: table_cache.for_each(expire_table,
1.11 paf 122: reinterpret_cast<void *>(0/* =in the past = expire[close] all*/));
123:
124: // destroy connection data
1.13 ! paf 125: check("db_appexit", &fdb_home, db_appexit(&dbenv));
1.11 paf 126: }
127:
128:
1.1 parser 129: void DB_Connection::check(const char *operation, const String *source, int error) {
130: switch(error) {
131: case 0:
132: // no error
133: break;
134:
135: default:
136: throw Exception(0, 0,
1.3 parser 137: source,
1.11 paf 138: "db %s error: %s (%d)",
139: operation, strerror(error), error);
1.1 parser 140: }
141: }
142:
1.13 ! paf 143: DB_Table_ptr DB_Connection::get_table_ptr(const String& request_file_name, const String *origin) {
! 144: if(!used)
! 145: throw(0, 0,
! 146: origin,
! 147: "note to parser3 programmer: your forgot about DB_Connection_usage");
1.11 paf 148:
149: // first trying to get cached table
150: DB_Table *result=get_table_from_cache(request_file_name);
1.13 ! paf 151: if(!result) { // no cached table
1.11 paf 152: // make global_file_name C-string on global pool
1.13 ! paf 153: const char *request_file_name_cstr=request_file_name.cstr(String::UL_AS_IS);
1.11 paf 154: char *global_file_name_cstr=(char *)malloc(strlen(request_file_name_cstr)+1);
155: strcpy(global_file_name_cstr, request_file_name_cstr);
156: // make global_file_name string on global pool
157: String& global_file_name=*new(this->pool()) String(this->pool(), global_file_name_cstr);
158:
159: // allocate in global pool
160: // associate with services[request]
161: // NOTE: never freed up!
162: result=new(this->pool()) DB_Table(this->pool(), global_file_name, *this);
1.13 ! paf 163: // cache it
! 164: put_table_to_cache(global_file_name, *result);
1.4 parser 165: }
1.1 parser 166:
1.13 ! paf 167: // return auto-it
! 168: return DB_Table_ptr(result);
1.11 paf 169: }
170: void DB_Connection::clear_dbfile(const String& file_name) {
171: // open&clear
172: DB *db;
1.1 parser 173: DB_INFO dbinfo;
174: memset(&dbinfo, 0, sizeof(dbinfo));
1.11 paf 175: check("open(clear)", &file_name, db_open(
176: file_name.cstr(String::UL_FILE_SPEC),
1.1 parser 177: PA_DB_ACCESS_METHOD,
1.11 paf 178: DB_CREATE | DB_TRUNCATE/* used in single thread, no need for |DB_THREAD*/,
1.1 parser 179: 0666,
1.11 paf 180: &dbenv, &dbinfo, &db));
181:
182: check("close", &file_name, db->close(db, 0/*flags*/)); db=0;
1.1 parser 183: }
1.11 paf 184:
185: // table cache
186: /// @todo get rid of memory spending Stack [zeros deep inside got accumulated]
187: DB_Table *DB_Connection::get_table_from_cache(const String& file_name) {
188: SYNCHRONIZED;
189:
1.13 ! paf 190: return static_cast<DB_Table *>(table_cache.get(file_name));
1.3 parser 191: }
192:
1.13 ! paf 193: void DB_Connection::put_table_to_cache(const String& file_name, DB_Table& table) {
1.11 paf 194: SYNCHRONIZED;
1.3 parser 195:
1.13 ! paf 196: table_cache.put(file_name, &table);
1.3 parser 197: }
198:
1.11 paf 199: void DB_Connection::maybe_expire_table_cache() {
200: time_t now=time(0);
201:
202: if(prev_expiration_pass_time<now-CHECK_EXPIRED_TABLES_SECONDS) {
1.13 ! paf 203: table_cache.for_each(expire_table,
1.11 paf 204: reinterpret_cast<void *>(now-EXPIRE_UNUSED_TABLE_SECONDS));
1.3 parser 205:
1.11 paf 206: prev_expiration_pass_time=now;
1.9 parser 207: }
1.1 parser 208: }
209:
210: #endif
E-mail: