--- parser3/src/main/Attic/pa_db_connection.C 2001/10/27 10:14:45 1.18 +++ parser3/src/main/Attic/pa_db_connection.C 2001/11/05 14:19:55 1.30 @@ -2,13 +2,15 @@ Parser: sql driver connection implementation. Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - Author: Alexander Petrosyan (http://design.ru/paf) + Author: Alexander Petrosyan (http://paf.design.ru) - $Id: pa_db_connection.C,v 1.18 2001/10/27 10:14:45 paf Exp $ + $Id: pa_db_connection.C,v 1.30 2001/11/05 14:19:55 paf Exp $ + + developed with LIBDB 2.7.4 */ #include "pa_config_includes.h" -#ifdef HAVE_LIBDB +#ifdef DB2 #include "pa_db_connection.h" #include "pa_db_table.h" @@ -16,13 +18,10 @@ #include "pa_threads.h" #include "pa_stack.h" #include "pa_common.h" +#include "pa_vtable.h" // defines -#define DB_ERROR_PREFIX "db_err: " -#define DB_EXCEPTION_NO_LOG_MESSAGE1 DB_ERROR_PREFIX"Ignoring log file" -#define DB_EXCEPTION_NO_LOG_MESSAGE2 DB_ERROR_PREFIX"log_get: unable to find checkpoint record" - // consts /// @test increase @@ -43,16 +42,17 @@ static void db_paniccall(DB_ENV *dbenv, static void db_errcall(const char *, char *buffer) { throw Exception(0, 0, 0, - DB_ERROR_PREFIX "%s", + "db_err: %s", buffer); } static void expire_table(const Hash::Key& key, Hash::Val *& value, void *info) { - DB_Connection& table=*static_cast(value); - time_t older_dies=reinterpret_cast(info); + if(DB_Table *table=static_cast(value)) { + time_t older_dies=reinterpret_cast(info); - if(table.expired(older_dies)) { - table.~DB_Connection(); value=0; + if(table->expired(older_dies)) { + table->~DB_Table(); value=0; + } } } @@ -60,7 +60,7 @@ static void expire_table(const Hash::Key DB_Connection::DB_Connection(Pool& apool, const String& adb_home) : Pooled(apool), time_used(0), - fdb_home(adb_home), + fdb_home(adb_home), used(0), table_cache(apool), prev_expiration_pass_time(0) { //_asm int 3; @@ -82,17 +82,22 @@ DB_Connection::DB_Connection(Pool& apool }; u_int32_t flags= - DB_THREAD + (parser_multithreaded?DB_THREAD:0) | DB_CREATE | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN; - // trying to open with SOFT RECOVER option set + // prepare dbenv structure memset(&dbenv, 0, sizeof(dbenv)); // error handlers +#if DB_VERSION_MINOR >= 7 dbenv.db_paniccall=db_paniccall; +#endif dbenv.db_errcall=db_errcall; + // lockdetector flags + dbenv.lk_detect=DB_LOCK_RANDOM; + // init check("db_appinit", &fdb_home, db_appinit( db_home_cstr, @@ -100,6 +105,12 @@ DB_Connection::DB_Connection(Pool& apool &dbenv, flags )); + + // after some hang noticed this to be null + if(!dbenv.tx_info) + throw Exception(0, 0, + &fdb_home, + "transaction system failed to initialize"); } DB_Connection::~DB_Connection() { @@ -119,23 +130,39 @@ void DB_Connection::check(const char *op break; default: - throw Exception(0, 0, - source, - "db %s error: %s (%d)", - operation, strerror(error), error); + if(error<0) + throw Exception(0, 0, + source, + "db %s error: %d", + operation, error); + else + throw Exception(0, 0, + source, + "db %s error: %s (%d)", + operation, strerror(error), error); } } DB_Table_ptr DB_Connection::get_table_ptr(const String& request_file_name, const String *source) { // checkpoint - check("checkpoint", source, - txn_checkpoint(dbenv.tx_info, 0/*kbyte*/, DB_CHECKPOINT_MINUTES/*min*/)); + { + int error=txn_checkpoint(dbenv.tx_info, 0/*kbyte*/, DB_CHECKPOINT_MINUTES/*min*/); + /* + DB_INCOMPLETE if there were pages that needed to be written + but that memp_sync was unable to write immediately. + In this case, the txn_checkpoint call should be retried. + + we'll just ignore that + */ + if(error!=DB_INCOMPLETE) + check("checkpoint", source, error); + } // first trying to get cached table DB_Table *result=get_table_from_cache(request_file_name); if(!result) { // no cached table // make global_file_name C-string on global pool - const char *request_file_name_cstr=request_file_name.cstr(String::UL_AS_IS); + const char *request_file_name_cstr=request_file_name.cstr(); char *global_file_name_cstr=(char *)malloc(strlen(request_file_name_cstr)+1); strcpy(global_file_name_cstr, request_file_name_cstr); // make global_file_name string on global pool @@ -180,4 +207,40 @@ void DB_Connection::maybe_expire_table_c } } +static void add_table_to_status_table(const Hash::Key& key, Hash::Val *& value, void *info) { + if(DB_Table *db_table=static_cast(value)) { + Table& status_table=*static_cast(info); + Pool& pool=status_table.pool(); + + Array& row=*new(pool) Array(pool); + + // name + row+=&db_table->file_name(); + // time + time_t time_stamp=db_table->get_time_used(); + const char *unsafe_time_cstr=ctime(&time_stamp); + int time_buf_size=strlen(unsafe_time_cstr); + char *safe_time_buf=(char *)pool.malloc(time_buf_size); + memcpy(safe_time_buf, unsafe_time_cstr, time_buf_size); + row+=new(pool) String(pool, safe_time_buf, time_buf_size); + // users + char *users_buf=(char *)pool.malloc(MAX_NUMBER); + row+=new(pool) String(pool, + users_buf, snprintf(users_buf, MAX_NUMBER, "%d", db_table->get_users_count())); + + status_table+=&row; + } +} +Value& DB_Connection::get_status(Pool& pool, const String *source) { + Array& columns=*new(pool) Array(pool); + columns+=new(pool) String(pool, "name"); + columns+=new(pool) String(pool, "time"); + columns+=new(pool) String(pool, "users"); + Table& table=*new(pool) Table(pool, 0, &columns, table_cache.size()); + + table_cache.for_each(add_table_to_status_table, &table); + + return *new(pool) VTable(pool, &table); +} + #endif