From 1b3927b02602ff1c6e64d6be860d783023f88060 Mon Sep 17 00:00:00 2001 From: dimitr Date: Wed, 28 Jan 2009 12:27:18 +0000 Subject: [PATCH] 1) Globally named per-database shmem regions. 2) Slightly reworked monitoring internals. 3) Encapsulated the event manager, many internal changes there. 4) Various cleanup, etc. --- src/jrd/Database.cpp | 29 +- src/jrd/Database.h | 19 +- src/jrd/DatabaseSnapshot.cpp | 108 ++- src/jrd/DatabaseSnapshot.h | 65 +- src/jrd/dfw.epp | 12 +- src/jrd/event.cpp | 1188 +++++++++++++++++---------------- src/jrd/event.h | 27 +- src/jrd/event_proto.h | 101 ++- src/jrd/file_params.h | 28 +- src/jrd/gds.cpp | 2 +- src/jrd/intl.cpp | 14 - src/jrd/intl_proto.h | 1 - src/jrd/isc.h | 2 +- src/jrd/isc_s_proto.h | 8 +- src/jrd/isc_sync.cpp | 217 +++--- src/jrd/jrd.cpp | 90 +-- src/jrd/os/thd_priority.h | 1 + src/jrd/pag.h | 1 + src/lock/lock.cpp | 92 ++- src/lock/lock.h | 20 +- src/lock/lock_proto.h | 19 +- src/utilities/guard/guard.cpp | 2 + src/utilities/guard/util.cpp | 5 +- 23 files changed, 1040 insertions(+), 1011 deletions(-) diff --git a/src/jrd/Database.cpp b/src/jrd/Database.cpp index 096e67f151..8f75f0beb6 100644 --- a/src/jrd/Database.cpp +++ b/src/jrd/Database.cpp @@ -54,6 +54,28 @@ namespace Jrd #endif } + const Firebird::string& Database::getUniqueFileId() const + { + static Firebird::GlobalPtr file_id; + + if (file_id->empty()) + { + const PageSpace* const pageSpace = dbb_page_manager.findPageSpace(DB_PAGE_SPACE); + + Firebird::UCharBuffer buffer; + PIO_get_unique_file_id(pageSpace->file, buffer); + + for (size_t i = 0; i < buffer.getCount(); i++) + { + TEXT hex[3]; + sprintf(hex, "%02x", (int) buffer[i]); + file_id->append(hex); + } + } + + return file_id; + } + Database::~Database() { delete dbb_sys_trans; @@ -66,9 +88,14 @@ namespace Jrd MemoryPool::deletePool(dbb_pools[i]); } + delete dbb_monitoring_data; + dbb_flags |= DBB_destroying; + Checkout dcoHolder(this); - dbb_lock_mgr->release(); + // This line decrements the usage counter and may cause the destructor to be called. + // It should happen with the dbb_sync unlocked. + dbb_lock_mgr = NULL; } void Database::deletePool(MemoryPool* pool) diff --git a/src/jrd/Database.h b/src/jrd/Database.h index 7c35673dde..ec375a0c50 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -57,19 +57,20 @@ #include "../common/classes/PublicHandle.h" #include "../common/classes/semaphore.h" #include "../common/utils_proto.h" +#include "../jrd/DatabaseSnapshot.h" #include "../jrd/RandomGenerator.h" #include "../jrd/os/guid.h" #include "../jrd/sbm.h" #include "../jrd/flu.h" #include "../jrd/RuntimeStatistics.h" -#include "../lock/lock_proto.h" #include "../jrd/os/thd_priority.h" +#include "../jrd/event_proto.h" +#include "../lock/lock_proto.h" class CharSetContainer; namespace Jrd { - class Trigger; template class vec; class jrd_prc; @@ -326,10 +327,10 @@ public: return TypedHandle::checkHandle(); } - mutable Sync* dbb_sync; // Database sync primitive - Firebird::Reference dbb_sync_ref; // Database reference to dbb_sync + mutable Firebird::RefPtr dbb_sync; // Database sync primitive - LockManager* dbb_lock_mgr; + Firebird::RefPtr dbb_lock_mgr; + Firebird::RefPtr dbb_event_mgr; Database* dbb_next; // Next database block in system Attachment* dbb_attachments; // Active attachments @@ -342,10 +343,8 @@ public: SLONG dbb_sh_counter_curr; // current value of shared counter lock SLONG dbb_sh_counter_max; // maximum cached value of shared counter lock jrd_tra* dbb_sys_trans; // system transaction -// jrd_file* dbb_file; // files for I/O operations Shadow* dbb_shadow; // shadow control block Lock* dbb_shadow_lock; // lock for synchronizing addition of shadows - //SLONG dbb_shadow_sync_count; // to synchronize changes to shadows Lock* dbb_retaining_lock; // lock for preserving commit retaining snapshot Lock* dbb_monitor_lock; // lock for monitoring purposes PageManager dbb_page_manager; @@ -354,6 +353,8 @@ public: BlobFilter* dbb_blob_filters; // known blob filters trig_vec* dbb_triggers[DB_TRIGGER_MAX]; + DatabaseSnapshot::SharedData* dbb_monitoring_data; // monitoring data + DatabaseModules dbb_modules; // external function/filter modules Firebird::Mutex dbb_meta_mutex; // Mutex to protect metadata changes while dbb_sync is unlocked @@ -447,6 +448,9 @@ public: // returns true if primary file is located on raw device bool onRawDevice() const; + // returns an unique ID string for a database file + const Firebird::string& getUniqueFileId() const; + MemoryPool* createPool() { MemoryPool* const pool = MemoryPool::createPool(dbb_permanent, dbb_memory_stats); @@ -459,7 +463,6 @@ public: private: explicit Database(MemoryPool* p) : dbb_sync(FB_NEW(*getDefaultMemoryPool()) Sync), - dbb_sync_ref(*dbb_sync), dbb_page_manager(*p), dbb_modules(*p), dbb_filename(*p), diff --git a/src/jrd/DatabaseSnapshot.cpp b/src/jrd/DatabaseSnapshot.cpp index e8ccf167fb..7f5cde870a 100644 --- a/src/jrd/DatabaseSnapshot.cpp +++ b/src/jrd/DatabaseSnapshot.cpp @@ -72,35 +72,40 @@ const UCHAR TAG_RECORD = MAX_UCHAR; // SharedMemory class -const ULONG DatabaseSnapshot::SharedMemory::VERSION = 2; -const ULONG DatabaseSnapshot::SharedMemory::DEFAULT_SIZE = 1048576; - - -DatabaseSnapshot::SharedMemory::SharedMemory() +DatabaseSnapshot::SharedData::SharedData(const Database* dbb) + : process_id(getpid()), local_id(dbb->dbb_monitoring_id) { - TEXT filename[MAXPATHLEN]; - gds__prefix_lock(filename, MONITOR_FILE); + Firebird::string name; + name.printf(MONITOR_FILE, dbb->getUniqueFileId().c_str()); ISC_STATUS_ARRAY statusVector; - base = (Header*) ISC_map_file(statusVector, filename, init, this, DEFAULT_SIZE, &handle); + base = (Header*) ISC_map_file(statusVector, name.c_str(), init, this, DEFAULT_SIZE, &handle); if (!base) { iscLogStatus("Cannot initialize the shared memory region", statusVector); status_exception::raise(statusVector); } - fb_assert(base->version == VERSION); + fb_assert(base->version == MONITOR_VERSION); } -DatabaseSnapshot::SharedMemory::~SharedMemory() +DatabaseSnapshot::SharedData::~SharedData() { + cleanup(); + +#ifdef WIN_NT + ISC_mutex_fini(&mutex); +#else + ISC_mutex_fini(&base->mutex); +#endif + ISC_STATUS_ARRAY statusVector; ISC_unmap_file(statusVector, &handle); } -void DatabaseSnapshot::SharedMemory::acquire() +void DatabaseSnapshot::SharedData::acquire() { #ifdef WIN_NT checkMutex("lock", ISC_mutex_lock(&mutex)); @@ -123,7 +128,7 @@ void DatabaseSnapshot::SharedMemory::acquire() } -void DatabaseSnapshot::SharedMemory::release() +void DatabaseSnapshot::SharedData::release() { #ifdef WIN_NT checkMutex("unlock", ISC_mutex_unlock(&mutex)); @@ -133,13 +138,8 @@ void DatabaseSnapshot::SharedMemory::release() } -UCHAR* DatabaseSnapshot::SharedMemory::readData(thread_db* tdbb, MemoryPool& pool, ULONG& resultSize) +UCHAR* DatabaseSnapshot::SharedData::read(MemoryPool& pool, ULONG& resultSize) { - fb_assert(tdbb); - - const Database* const dbb = tdbb->getDatabase(); - fb_assert(dbb); - DumpGuard guard(this); ULONG self_dbb_offset = 0; @@ -157,7 +157,7 @@ UCHAR* DatabaseSnapshot::SharedMemory::readData(thread_db* tdbb, MemoryPool& poo const Element* const element = (Element*) ptr; const ULONG length = sizeof(Element) + element->length; - if (element->processId == getpid() && element->localId == dbb->dbb_monitoring_id) + if (element->processId == process_id && element->localId == local_id) { self_dbb_offset = offset; } @@ -206,17 +206,12 @@ UCHAR* DatabaseSnapshot::SharedMemory::readData(thread_db* tdbb, MemoryPool& poo } -void DatabaseSnapshot::SharedMemory::writeData(thread_db* tdbb, ULONG length, const UCHAR* buffer) +void DatabaseSnapshot::SharedData::write(ULONG length, const UCHAR* buffer) { - fb_assert(tdbb); - - const Database* const dbb = tdbb->getDatabase(); - fb_assert(dbb); - DumpGuard guard(this); // Remove old copies of our element, if any - doCleanup(dbb); + cleanup(); // Do we need to extend the allocated memory? while (base->used + sizeof(Element) + length > base->allocated) @@ -227,37 +222,24 @@ void DatabaseSnapshot::SharedMemory::writeData(thread_db* tdbb, ULONG length, co // Put an up-to-date element at the tail UCHAR* const ptr = (UCHAR*) base + base->used; Element* const element = (Element*) ptr; - element->processId = getpid(); - element->localId = dbb->dbb_monitoring_id; + element->processId = process_id; + element->localId = local_id; element->length = length; memcpy(ptr + sizeof(Element), buffer, length); base->used += sizeof(Element) + length; } -void DatabaseSnapshot::SharedMemory::cleanup(thread_db* tdbb) +void DatabaseSnapshot::SharedData::cleanup() { - fb_assert(tdbb); - - const Database* const dbb = tdbb->getDatabase(); - fb_assert(dbb); - - DumpGuard guard(this); - // Remove information about our dbb - doCleanup(dbb); -} - - -void DatabaseSnapshot::SharedMemory::doCleanup(const Database* const dbb) -{ for (ULONG offset = sizeof(Header); offset < base->used;) { UCHAR* const ptr = (UCHAR*) base + offset; const Element* const element = (Element*) ptr; const ULONG length = sizeof(Element) + element->length; - if (element->processId == getpid() && element->localId == dbb->dbb_monitoring_id) + if (element->processId == process_id && element->localId == local_id) { fb_assert(base->used >= offset + length); memmove(ptr, ptr + length, base->used - offset - length); @@ -271,7 +253,7 @@ void DatabaseSnapshot::SharedMemory::doCleanup(const Database* const dbb) } -void DatabaseSnapshot::SharedMemory::extend() +void DatabaseSnapshot::SharedData::extend() { const ULONG newSize = handle.sh_mem_length_mapped + DEFAULT_SIZE; @@ -289,7 +271,7 @@ void DatabaseSnapshot::SharedMemory::extend() } -void DatabaseSnapshot::SharedMemory::checkMutex(const TEXT* string, int state) +void DatabaseSnapshot::SharedData::checkMutex(const TEXT* string, int state) { if (state) { @@ -304,15 +286,13 @@ void DatabaseSnapshot::SharedMemory::checkMutex(const TEXT* string, int state) } -void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool initialize) +void DatabaseSnapshot::SharedData::init(void* arg, SH_MEM_T* shmemData, bool initialize) { - SharedMemory* const shmem = (SharedMemory*) arg; + SharedData* const shmem = (SharedData*) arg; fb_assert(shmem); #ifdef WIN_NT - char buffer[MAXPATHLEN]; - gds__prefix_lock(buffer, MONITOR_FILE); - checkMutex("init", ISC_mutex_init(&shmem->mutex, buffer)); + checkMutex("init", ISC_mutex_init(&shmem->mutex, shmemData->sh_mem_name)); #endif if (!initialize) @@ -320,7 +300,7 @@ void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool i // Initialize the shared data header Header* const header = (Header*) shmemData->sh_mem_address; - header->version = VERSION; + header->version = MONITOR_VERSION; header->used = sizeof(Header); header->allocated = shmemData->sh_mem_length_mapped; @@ -332,9 +312,6 @@ void DatabaseSnapshot::SharedMemory::init(void* arg, SH_MEM_T* shmemData, bool i // DatabaseSnapshot class -DatabaseSnapshot::SharedMemory* DatabaseSnapshot::dump = NULL; -InitMutex DatabaseSnapshot::startup; - DatabaseSnapshot* DatabaseSnapshot::create(thread_db* tdbb) { @@ -355,17 +332,6 @@ DatabaseSnapshot* DatabaseSnapshot::create(thread_db* tdbb) } -void DatabaseSnapshot::cleanup(thread_db* tdbb) -{ - SET_TDBB(tdbb); - - if (dump) - { - dump->cleanup(tdbb); - } -} - - int DatabaseSnapshot::blockingAst(void* ast_object) { Database* dbb = static_cast(ast_object); @@ -458,9 +424,9 @@ DatabaseSnapshot::DatabaseSnapshot(thread_db* tdbb, MemoryPool& pool) dbb->dbb_ast_flags |= DBB_monitor_off; // Read the shared memory - fb_assert(dump); + fb_assert(dbb->dbb_monitoring_data); ULONG dataSize = 0; - AutoPtr > data(dump->readData(tdbb, pool, dataSize)); + AutoPtr > data(dbb->dbb_monitoring_data->read(pool, dataSize)); fb_assert(dataSize); ClumpletReader reader(ClumpletReader::WideUnTagged, data, dataSize); @@ -899,10 +865,12 @@ void DatabaseSnapshot::dumpData(thread_db* tdbb) } } - startup.init(); + if (!dbb->dbb_monitoring_data) + { + dbb->dbb_monitoring_data = FB_NEW(*dbb->dbb_permanent) SharedData(dbb); + } - fb_assert(dump); - dump->writeData(tdbb, writer.getBufferLength(), writer.getBuffer()); + dbb->dbb_monitoring_data->write(writer.getBufferLength(), writer.getBuffer()); } diff --git a/src/jrd/DatabaseSnapshot.h b/src/jrd/DatabaseSnapshot.h index 7b59b124e7..e1576c03e5 100644 --- a/src/jrd/DatabaseSnapshot.h +++ b/src/jrd/DatabaseSnapshot.h @@ -30,6 +30,11 @@ namespace Jrd { +// forward declarations +class jrd_rel; +class RecordBuffer; +class RuntimeStatistics; + class DatabaseSnapshot { struct RelationData @@ -38,10 +43,18 @@ class DatabaseSnapshot RecordBuffer* data; }; - class SharedMemory + struct Element { - static const ULONG VERSION; - static const ULONG DEFAULT_SIZE; + SLONG processId; + SLONG localId; + ULONG length; + }; + +public: + class SharedData + { + static const ULONG MONITOR_VERSION = 2; + static const ULONG DEFAULT_SIZE = 1048576; struct Header { @@ -56,42 +69,40 @@ class DatabaseSnapshot class DumpGuard { public: - explicit DumpGuard(SharedMemory* ptr) - : dump(ptr) + explicit DumpGuard(SharedData* ptr) + : data(ptr) { - dump->acquire(); + data->acquire(); } ~DumpGuard() { - dump->release(); + data->release(); } private: DumpGuard(const DumpGuard&); DumpGuard& operator=(const DumpGuard&); - SharedMemory* dump; + SharedData* const data; }; public: - SharedMemory(); - ~SharedMemory(); + explicit SharedData(const Database*); + ~SharedData(); void acquire(); void release(); - UCHAR* readData(thread_db*, MemoryPool&, ULONG&); - void writeData(thread_db*, ULONG, const UCHAR*); - - void cleanup(thread_db*); + UCHAR* read(MemoryPool&, ULONG&); + void write(ULONG, const UCHAR*); private: // copying is prohibited - SharedMemory(const SharedMemory&); - SharedMemory& operator =(const SharedMemory&); + SharedData(const SharedData&); + SharedData& operator =(const SharedData&); - void doCleanup(const Database* const dbb); + void cleanup(); void extend(); static void checkMutex(const TEXT*, int); @@ -102,29 +113,18 @@ class DatabaseSnapshot struct mtx mutex; #endif Header* base; + + const SLONG process_id; + const SLONG local_id; }; - struct Element - { - SLONG processId; - SLONG localId; - ULONG length; - }; - -public: ~DatabaseSnapshot(); RecordBuffer* getData(const jrd_rel*) const; static DatabaseSnapshot* create(thread_db*); - static void cleanup(thread_db*); static int blockingAst(void*); - static void init() - { - dump = FB_NEW(*getDefaultMemoryPool()) SharedMemory; - } - protected: DatabaseSnapshot(thread_db*, MemoryPool&); @@ -147,9 +147,6 @@ private: static void putContextVars(Firebird::StringMap&, Firebird::ClumpletWriter&, int, bool); static void putMemoryUsage(const Firebird::MemoryStats&, Firebird::ClumpletWriter&, int, int); - static SharedMemory* dump; - static Firebird::InitMutex startup; - Firebird::Array snapshot; Firebird::GenericMap > > idMap; int idCounter; diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 9709238e90..0a3c4a1183 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -634,8 +634,12 @@ void DFW_perform_post_commit_work(jrd_tra* transaction) switch (work->dfw_type) { case dfw_post_event: - EVENT_post(lock->lck_length, (const TEXT*) &lock->lck_key, - work->dfw_name.length(), work->dfw_name.c_str(), work->dfw_count); + EventManager::init(dbb); + + dbb->dbb_event_mgr->postEvent(lock->lck_length, (const TEXT*) &lock->lck_key, + work->dfw_name.length(), work->dfw_name.c_str(), + work->dfw_count); + *ptr = work->dfw_next; delete work; pending_events = true; @@ -651,7 +655,9 @@ void DFW_perform_post_commit_work(jrd_tra* transaction) } if (pending_events) - EVENT_deliver(); + { + dbb->dbb_event_mgr->deliverEvents(); + } } diff --git a/src/jrd/event.cpp b/src/jrd/event.cpp index 370fa1a550..ca5f797a3e 100644 --- a/src/jrd/event.cpp +++ b/src/jrd/event.cpp @@ -20,10 +20,7 @@ * All Rights Reserved. * Contributor(s): ______________________________________. * - * 23-Feb-2002 Dmitry Yemanov - Events wildcarding - * * 2002.10.29 Sean Leyne - Removed obsolete "Netware" port - * */ #include "firebird.h" @@ -32,6 +29,8 @@ #include #include "../jrd/common.h" #include "gen/iberror.h" +#include "../common/classes/init.h" +#include "../common/config/config.h" #include "../jrd/ThreadStart.h" #include "../jrd/event.h" #include "../jrd/gdsassert.h" @@ -42,9 +41,8 @@ #include "../jrd/thread_proto.h" #include "../jrd/err_proto.h" #include "../jrd/os/isc_i_proto.h" -#include "../common/classes/init.h" -#include "../common/config/config.h" #include "../common/utils_proto.h" +#include "../jrd/Database.h" #ifdef HAVE_SYS_TYPES_H #include @@ -61,141 +59,119 @@ #ifdef WIN_NT #include #include - -#define MUTEX event_mutex +#define MUTEX &m_mutex +#else +#define MUTEX &m_header->evh_mutex #endif -#ifndef MUTEX -#define MUTEX EVENT_header->evh_mutex -#endif +#define SRQ_BASE ((UCHAR*) m_header) -#define SRQ_BASE ((UCHAR *) EVENT_header) +namespace Jrd { -const int MAX_EVENT_BUFFER = 65500; +Firebird::GlobalPtr EventManager::g_emMap; +Firebird::GlobalPtr EventManager::g_mapMutex; -static EVH acquire(); -static FRB alloc_global(UCHAR type, ULONG length, bool recurse); -static SLONG create_process(); -static void delete_event(EVNT); -static void delete_process(SLONG); -static void delete_request(EVT_REQ); -static void delete_session(SLONG); -static void deliver(); -static void deliver_request(EVT_REQ); -static void exit_handler(void *); -static EVNT find_event(USHORT, const TEXT*, EVNT); -static void free_global(FRB); -static RINT historical_interest(SES, SLONG); -static void init_shmem(void*, SH_MEM, bool); -static void insert_tail(srq *, srq *); -static EVNT make_event(USHORT, const TEXT*, SLONG); -static void mutex_bugcheck(const TEXT*, int); -static void post_process(PRB); -static void probe_processes(); -static void punt(const TEXT*); -static void release(); -static void remove_que(srq *); -static bool request_completed(EVT_REQ); -static THREAD_ENTRY_DECLARE watcher_thread(THREAD_ENTRY_PARAM); - -namespace +void EventManager::init(Database* dbb) { - EVH EVENT_header = NULL; - SLONG EVENT_process_offset = 0; -#ifdef SOLARIS_MT - PRB EVENT_process = NULL; -#endif - SH_MEM_T EVENT_data; - -#if defined(WIN_NT) - struct mtx event_mutex; -#endif - - class EventStartup + if (!dbb->dbb_event_mgr) { - public: - static void init() + const Firebird::string id = dbb->getUniqueFileId(); + + Firebird::MutexLockGuard guard(g_mapMutex); + + EventManager* eventMgr = NULL; + if (!g_emMap->get(id, eventMgr)) { - TEXT event_file[MAXPATHLEN]; - gds__prefix_lock(event_file, EVENT_FILE); - - ISC_STATUS_ARRAY local_status; - if (!(EVENT_header = (EVH) ISC_map_file(local_status, event_file, init_shmem, 0, - Config::getEventMemSize(), &EVENT_data))) - { - Firebird::status_exception::raise(local_status); - } - - gds__register_cleanup(exit_handler, NULL); + eventMgr = new EventManager(id); } - static void cleanup() - { - if (EVENT_process_offset) - { - if (EVENT_header->evh_current_process != EVENT_process_offset) - acquire(); - delete_process(EVENT_process_offset); - release(); - } + fb_assert(eventMgr); - ISC_STATUS_ARRAY local_status; -#ifdef SOLARIS_MT - ISC_unmap_object(local_status, &EVENT_data, (UCHAR**) &EVENT_process, sizeof(prb)); -#endif - ISC_unmap_file(local_status, &EVENT_data); - - EVENT_header = NULL; - } - }; - - Firebird::InitMutex eventStartup; + dbb->dbb_event_mgr = eventMgr; + } } -void EVENT_cancel(SLONG request_id) +EventManager::EventManager(const Firebird::string& id) + : PID(getpid()), + m_header(NULL), + m_process(NULL), + m_processOffset(0), + m_dbId(getPool(), id) { -/************************************** - * - * E V E N T _ c a n c e l - * - ************************************** - * - * Functional description - * Cancel an outstanding event. - * - **************************************/ - if (!EVENT_header) - return; + Firebird::string name; + name.printf(EVENT_FILE, m_dbId.c_str()); - acquire(); - - PRB process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); - - srq* que2; - SRQ_LOOP(process->prb_sessions, que2) { - SES session = (SES) ((UCHAR *) que2 - OFFSET(SES, ses_sessions)); - srq* event_srq; - SRQ_LOOP(session->ses_requests, event_srq) { - EVT_REQ request = (EVT_REQ) ((UCHAR *) event_srq - OFFSET(EVT_REQ, req_requests)); - if (request->req_request_id == request_id) { - delete_request(request); - release(); - return; - } - } + ISC_STATUS_ARRAY local_status; + if (!(m_header = (evh*) ISC_map_file(local_status, + name.c_str(), + init_shmem, this, + Config::getEventMemSize(), + &m_shmemData))) + { + Firebird::status_exception::raise(local_status); } - release(); + fb_assert(m_header->evh_version == EVENT_VERSION); + + Firebird::MutexLockGuard guard(g_mapMutex); + + if (g_emMap->put(m_dbId, this)) + { + fb_assert(false); + } } -SLONG EVENT_create_session() +EventManager::~EventManager() +{ + const SLONG process_offset = m_processOffset; + m_processOffset = 0; + + ISC_STATUS_ARRAY local_status; + + if (m_process) + { + // Terminate the event watcher thread + m_startupSemaphore.tryEnter(5); + ISC_event_post(&m_process->prb_event); + m_cleanupSemaphore.tryEnter(5); + +#if (defined HAVE_MMAP || defined WIN_NT) + ISC_unmap_object(local_status, &m_shmemData, (UCHAR**) &m_process, sizeof(prb)); +#else + m_process = NULL; +#endif + } + + if (process_offset) + { + acquire_shmem(); + delete_process(process_offset); + release_shmem(); + } + + if (m_header) + { + ISC_mutex_fini(MUTEX); + ISC_unmap_file(local_status, &m_shmemData); + } + + Firebird::MutexLockGuard guard(g_mapMutex); + + if (!g_emMap->remove(m_dbId)) + { + fb_assert(false); + } +} + + +SLONG EventManager::createSession() { /************************************** * - * E V E N T _ c r e a t e _ s e s s i o n + * c r e a t e S e s s i o n * ************************************** * @@ -203,33 +179,32 @@ SLONG EVENT_create_session() * Create session. * **************************************/ - - eventStartup.init(); - - if (!EVENT_process_offset) + if (!m_processOffset) { create_process(); } - acquire(); - SES session = (SES) alloc_global(type_ses, (SLONG) sizeof(ses), false); - PRB process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + acquire_shmem(); + + ses* const session = (ses*) alloc_global(type_ses, sizeof(ses), false); + prb* const process = (prb*) SRQ_ABS_PTR(m_processOffset); session->ses_flags = 0; insert_tail(&process->prb_sessions, &session->ses_sessions); SRQ_INIT(session->ses_requests); const SLONG id = SRQ_REL_PTR(session); - release(); + + release_shmem(); return id; } -void EVENT_delete_session(SLONG session_id) +void EventManager::deleteSession(SLONG session_id) { /************************************** * - * E V E N T _ d e l e t e _ s e s s i o n + * d e l e t e S e s s i o n * ************************************** * @@ -237,147 +212,55 @@ void EVENT_delete_session(SLONG session_id) * Delete a session. * **************************************/ - - if (!EVENT_header) - return; - - acquire(); + acquire_shmem(); delete_session(session_id); - release(); + release_shmem(); } -void EVENT_deliver() +SLONG EventManager::queEvents(SLONG session_id, + USHORT string_length, const TEXT* string, + USHORT events_length, const UCHAR* events, + FPTR_EVENT_CALLBACK ast_routine, void* ast_arg) { /************************************** * - * E V E N T _ d e l i v e r - * - ************************************** - * - * Functional description - * Post an event (step 2). - * - * This code was primarily located in - * EVENT_post (see above). This - * routine is called by DFW_perform_post_commit_work - * once all pending events are prepared - * for delivery with EVENT_post. - * - **************************************/ - - if (!EVENT_header) - return; - - acquire(); - - /* Deliver requests for posted events */ - - bool flag = true; - - while (flag) { - flag = false; - srq* event_srq; - SRQ_LOOP (EVENT_header->evh_processes, event_srq) { - PRB process = (PRB) ((UCHAR*) event_srq - OFFSET (PRB, prb_processes)); - if (process->prb_flags & PRB_wakeup) { - post_process(process); - flag = true; - break; - } - } - } - - release(); -} - - -void EVENT_post(USHORT major_length, - const TEXT * major_code, - USHORT minor_length, - const TEXT * minor_code, - USHORT count) -{ -/************************************** - * - * E V E N T _ p o s t - * - ************************************** - * - * Functional description - * Post an event. - * - **************************************/ - - eventStartup.init(); - - acquire(); - - EVNT event; - EVNT parent = find_event(major_length, major_code, 0); - if (parent && (event = find_event(minor_length, minor_code, parent))) - { - event->evnt_count += count; - srq* event_srq; - SRQ_LOOP(event->evnt_interests, event_srq) { - RINT interest = (RINT) ((UCHAR *) event_srq - OFFSET(RINT, rint_interests)); - if (interest->rint_request) { - EVT_REQ request = (EVT_REQ) SRQ_ABS_PTR(interest->rint_request); - - if (interest->rint_count <= event->evnt_count) { - PRB process = (PRB) SRQ_ABS_PTR(request->req_process); - process->prb_flags |= PRB_wakeup; - } - } - } - } - - release(); -} - - -SLONG EVENT_que(SLONG session_id, - USHORT string_length, - const TEXT* string, - USHORT events_length, - const UCHAR* events, - FPTR_EVENT_CALLBACK ast_routine, void* ast_arg) -{ -/************************************** - * - * E V E N T _ q u e + * q u e E v e n t s * ************************************** * * Functional description * **************************************/ -// Allocate request block + acquire_shmem(); - acquire(); - EVT_REQ request = (EVT_REQ) alloc_global(type_reqb, sizeof(evt_req), false); - SES session = (SES) SRQ_ABS_PTR(session_id); + // Allocate request block + + evt_req* request = (evt_req*) alloc_global(type_reqb, sizeof(evt_req), false); + ses* session = (ses*) SRQ_ABS_PTR(session_id); insert_tail(&session->ses_requests, &request->req_requests); request->req_session = session_id; - request->req_process = EVENT_process_offset; + request->req_process = m_processOffset; request->req_ast = ast_routine; request->req_ast_arg = ast_arg; - const SLONG id = ++EVENT_header->evh_request_id; + const SLONG id = ++m_header->evh_request_id; request->req_request_id = id; const SLONG request_offset = SRQ_REL_PTR(request); -/* Find parent block */ - EVNT parent = find_event(string_length, string, 0); - if (!parent) { + // Find parent block + + evnt* parent = find_event(string_length, string, 0); + if (!parent) + { parent = make_event(string_length, string, 0); - request = (EVT_REQ) SRQ_ABS_PTR(request_offset); - session = (SES) SRQ_ABS_PTR(session_id); + request = (evt_req*) SRQ_ABS_PTR(request_offset); + session = (ses*) SRQ_ABS_PTR(session_id); } const SLONG parent_offset = SRQ_REL_PTR(parent); -/* Process event block */ + // Process event block SRQ_PTR* ptr = &request->req_interests; SLONG ptr_offset = SRQ_REL_PTR(ptr); @@ -385,74 +268,208 @@ SLONG EVENT_que(SLONG session_id, const UCHAR* const end = events + events_length; bool flag = false; - while (p < end) { - + while (p < end) + { const USHORT count = *p++; - /* The data in the event block may have trailing blanks. Strip them off. */ + // The data in the event block may have trailing blanks. Strip them off. const UCHAR* find_end = p + count; while (--find_end >= p && *find_end == ' ') ; // nothing to do. const USHORT len = find_end - p + 1; - EVNT event = find_event(len, reinterpret_cast(p), parent); - if (!event) { + + evnt* event = find_event(len, reinterpret_cast(p), parent); + if (!event) + { event = make_event(len, reinterpret_cast(p), parent_offset); - parent = (EVNT) SRQ_ABS_PTR(parent_offset); - session = (SES) SRQ_ABS_PTR(session_id); - request = (EVT_REQ) SRQ_ABS_PTR(request_offset); + parent = (evnt*) SRQ_ABS_PTR(parent_offset); + session = (ses*) SRQ_ABS_PTR(session_id); + request = (evt_req*) SRQ_ABS_PTR(request_offset); ptr = (SRQ_PTR *) SRQ_ABS_PTR(ptr_offset); } + p += count; const SLONG event_offset = SRQ_REL_PTR(event); - RINT interest, prior; - if (interest = historical_interest(session, event_offset)) { + + req_int* interest, *prior; + if (interest = historical_interest(session, event_offset)) + { for (SRQ_PTR* ptr2 = &session->ses_interests; - *ptr2 && (prior = (RINT) SRQ_ABS_PTR(*ptr2)); + *ptr2 && (prior = (req_int*) SRQ_ABS_PTR(*ptr2)); ptr2 = &prior->rint_next) { - if (prior == interest) { + if (prior == interest) + { *ptr2 = interest->rint_next; interest->rint_next = 0; break; } } } - else { - interest = (RINT) alloc_global(type_rint, (SLONG) sizeof(req_int), false); - event = (EVNT) SRQ_ABS_PTR(event_offset); + else + { + interest = (req_int*) alloc_global(type_rint, sizeof(req_int), false); + event = (evnt*) SRQ_ABS_PTR(event_offset); insert_tail(&event->evnt_interests, &interest->rint_interests); interest->rint_event = event_offset; - parent = (EVNT) SRQ_ABS_PTR(parent_offset); - request = (EVT_REQ) SRQ_ABS_PTR(request_offset); + parent = (evnt*) SRQ_ABS_PTR(parent_offset); + request = (evt_req*) SRQ_ABS_PTR(request_offset); ptr = (SRQ_PTR *) SRQ_ABS_PTR(ptr_offset); - session = (SES) SRQ_ABS_PTR(session_id); + session = (ses*) SRQ_ABS_PTR(session_id); } + *ptr = SRQ_REL_PTR(interest); ptr = &interest->rint_next; ptr_offset = SRQ_REL_PTR(ptr); + interest->rint_request = request_offset; interest->rint_count = gds__vax_integer(p, 4); p += 4; if (interest->rint_count <= event->evnt_count) + { flag = true; + } } if (flag) - post_process((PRB) SRQ_ABS_PTR(EVENT_process_offset)); + { + post_process((prb*) SRQ_ABS_PTR(m_processOffset)); + } - release(); + release_shmem(); return id; } -static EVH acquire() +void EventManager::cancelEvents(SLONG request_id) { /************************************** * - * a c q u i r e + * c a n c e l E v e n t s + * + ************************************** + * + * Functional description + * Cancel an outstanding event. + * + **************************************/ + acquire_shmem(); + + prb* const process = (prb*) SRQ_ABS_PTR(m_processOffset); + + srq* que2; + SRQ_LOOP(process->prb_sessions, que2) + { + ses* const session = (ses*) ((UCHAR*) que2 - OFFSET(ses*, ses_sessions)); + srq* event_srq; + SRQ_LOOP(session->ses_requests, event_srq) + { + evt_req* const request = (evt_req*) ((UCHAR*) event_srq - OFFSET(evt_req*, req_requests)); + if (request->req_request_id == request_id) + { + delete_request(request); + release_shmem(); + return; + } + } + } + + release_shmem(); +} + + +void EventManager::postEvent(USHORT major_length, const TEXT* major_code, + USHORT minor_length, const TEXT* minor_code, + USHORT count) +{ +/************************************** + * + * p o s t E v e n t + * + ************************************** + * + * Functional description + * Post an event. + * + **************************************/ + acquire_shmem(); + + evnt* event; + evnt* const parent = find_event(major_length, major_code, 0); + if (parent && (event = find_event(minor_length, minor_code, parent))) + { + event->evnt_count += count; + srq* event_srq; + SRQ_LOOP(event->evnt_interests, event_srq) + { + req_int* const interest = (req_int*) ((UCHAR*) event_srq - OFFSET(req_int*, rint_interests)); + if (interest->rint_request) + { + evt_req* const request = (evt_req*) SRQ_ABS_PTR(interest->rint_request); + + if (interest->rint_count <= event->evnt_count) + { + prb* const process = (prb*) SRQ_ABS_PTR(request->req_process); + process->prb_flags |= PRB_wakeup; + } + } + } + } + + release_shmem(); +} + + +void EventManager::deliverEvents() +{ +/************************************** + * + * d e l i v e r E v e n t s + * + ************************************** + * + * Functional description + * Post an event (step 2). + * + * This routine is called by DFW_perform_post_commit_work() + * once all pending events are prepared + * for delivery with postEvent(). + * + **************************************/ + acquire_shmem(); + + // Deliver requests for posted events + + bool flag = true; + + while (flag) + { + flag = false; + srq* event_srq; + SRQ_LOOP (m_header->evh_processes, event_srq) + { + prb* const process = (prb*) ((UCHAR*) event_srq - OFFSET (prb*, prb_processes)); + if (process->prb_flags & PRB_wakeup) + { + post_process(process); + flag = true; + break; + } + } + } + + release_shmem(); +} + + +evh* EventManager::acquire_shmem() +{ +/************************************** + * + * a c q u i r e _ s h m e m * ************************************** * @@ -462,65 +479,62 @@ static EVH acquire() **************************************/ int mutex_state; - if (mutex_state = ISC_mutex_lock(&MUTEX)) + if (mutex_state = ISC_mutex_lock(MUTEX)) mutex_bugcheck("mutex lock", mutex_state); - EVENT_header->evh_current_process = EVENT_process_offset; - if (EVENT_header->evh_length > EVENT_data.sh_mem_length_mapped) + m_header->evh_current_process = m_processOffset; + + if (m_header->evh_length > m_shmemData.sh_mem_length_mapped) { -#if (!(defined SUPERSERVER) && (defined HAVE_MMAP)) - const SLONG length = EVENT_header->evh_length; -#endif + const ULONG length = m_header->evh_length; -#ifdef WIN_NT - /* Before remapping the memory, wakeup the watcher thread. - * Then remap the shared memory and allow the watcher thread - * to remap. - */ - /* Need to make the following code generic to all SUPERSERVER - * platforms. Postponed for now. B.Sriram, 10-Jul-1997 - */ +#if (defined HAVE_MMAP || defined WIN_NT) + // Before remapping the memory, wakeup the watcher thread. + // Then remap the shared memory and allow the watcher thread to remap. - PRB process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + prb* process = (prb*) SRQ_ABS_PTR(m_processOffset); process->prb_flags |= PRB_remap; - //event_t* event = &process->prb_event; post_process(process); - while (true) { - release(); - Sleep(3); - acquire(); + while (true) + { + release_shmem(); + THREAD_YIELD(); + acquire_shmem(); - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + process = (prb*) SRQ_ABS_PTR(m_processOffset); if (!(process->prb_flags & PRB_remap)) break; } -#endif /* WIN_NT */ - - EVH header = NULL; -#if (!(defined SUPERSERVER) && (defined HAVE_MMAP)) - ISC_STATUS_ARRAY local_status; - header = (evh*) ISC_remap_file(local_status, &EVENT_data, length, false); #endif - if (!header) { - release(); - gds__log("acquire: Event table remap failed"); + + evh* header = NULL; + +#if (defined HAVE_MMAP || defined WIN_NT) + ISC_STATUS_ARRAY local_status; + header = (evh*) ISC_remap_file(local_status, &m_shmemData, length, false); +#endif + if (!header) + { + release_shmem(); + gds__log("Event table remap failed"); exit(FINI_ERROR); } - EVENT_header = header; -#ifdef WIN_NT - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + m_header = header; + +#if (defined HAVE_MMAP || defined WIN_NT) + process = (prb*) SRQ_ABS_PTR(m_processOffset); process->prb_flags &= ~PRB_remap_over; -#endif /* WIN_NT */ +#endif } - return EVENT_header; + return m_header; } -static FRB alloc_global(UCHAR type, ULONG length, bool recurse) +frb* EventManager::alloc_global(UCHAR type, ULONG length, bool recurse) { /************************************** * @@ -533,90 +547,96 @@ static FRB alloc_global(UCHAR type, ULONG length, bool recurse) * **************************************/ SRQ_PTR *ptr; - FRB free; + frb* free; SLONG best_tail = MAX_SLONG; - length = ROUNDUP(length, sizeof(IPTR)); + length = FB_ALIGN(length, FB_ALIGNMENT); SRQ_PTR* best = NULL; - for (ptr = &EVENT_header->evh_free; (free = (FRB) SRQ_ABS_PTR(*ptr)) && *ptr; + for (ptr = &m_header->evh_free; (free = (frb*) SRQ_ABS_PTR(*ptr)) && *ptr; ptr = &free->frb_next) { const SLONG tail = free->frb_header.hdr_length - length; - if (tail >= 0 && (!best || tail < best_tail)) { + if (tail >= 0 && (!best || tail < best_tail)) + { best = ptr; best_tail = tail; } } - if (!best && !recurse) { - const SLONG old_length = EVENT_data.sh_mem_length_mapped; - const SLONG ev_length = old_length + EVENT_EXTEND_SIZE; + if (!best && !recurse) + { + const ULONG old_length = m_shmemData.sh_mem_length_mapped; + const ULONG ev_length = old_length + Config::getEventMemSize(); -#ifdef WIN_NT +#if (defined HAVE_MMAP || defined WIN_NT) + // Before remapping the memory, wakeup the watcher thread. + // Then remap the shared memory and allow the watcher thread to remap. - /* Before remapping the memory, wakeup the watcher thread. - * Then remap the shared memory and allow the watcher thread - * to remap. - */ - - PRB process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + prb* process = (prb*) SRQ_ABS_PTR(m_processOffset); process->prb_flags |= PRB_remap; - //event_t* event = &process->prb_event; + post_process(process); - while (true) { - release(); - Sleep(3); - acquire(); + while (true) + { + release_shmem(); + THREAD_YIELD(); + acquire_shmem(); - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + process = (prb*) SRQ_ABS_PTR(m_processOffset); if (!(process->prb_flags & PRB_remap)) break; } -#endif /* WIN_NT */ - - EVH header = 0; -#if !((defined SUPERSERVER) && (defined HAVE_MMAP)) - ISC_STATUS_ARRAY local_status; - header = reinterpret_cast(ISC_remap_file(local_status, &EVENT_data, ev_length, true)); #endif - if (header) { - free = (FRB) ((UCHAR *) header + old_length); + + evh* header = NULL; + +#if (defined HAVE_MMAP || defined WIN_NT) + ISC_STATUS_ARRAY local_status; + header = (evh*) ISC_remap_file(local_status, &m_shmemData, ev_length, true); +#endif + if (header) + { + free = (frb*) ((UCHAR*) header + old_length); /** free->frb_header.hdr_length = EVENT_EXTEND_SIZE - sizeof (struct evh); **/ - free->frb_header.hdr_length = EVENT_data.sh_mem_length_mapped - old_length; + free->frb_header.hdr_length = m_shmemData.sh_mem_length_mapped - old_length; free->frb_header.hdr_type = type_frb; free->frb_next = 0; - EVENT_header = header; - EVENT_header->evh_length = EVENT_data.sh_mem_length_mapped; + m_header = header; + m_header->evh_length = m_shmemData.sh_mem_length_mapped; free_global(free); -#ifdef WIN_NT - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); +#if (defined HAVE_MMAP || defined WIN_NT) + process = (prb*) SRQ_ABS_PTR(m_processOffset); process->prb_flags &= ~PRB_remap_over; -#endif /* WIN_NT */ +#endif return alloc_global(type, length, true); } } - if (!best) { - release(); - gds__log("alloc_global: Event table space exhausted"); + if (!best) + { + release_shmem(); + gds__log("Event table space exhausted"); exit(FINI_ERROR); } - free = (FRB) SRQ_ABS_PTR(*best); + free = (frb*) SRQ_ABS_PTR(*best); if (best_tail < (SLONG) sizeof(frb)) + { *best = free->frb_next; - else { + } + else + { free->frb_header.hdr_length -= length; - free = (FRB) ((UCHAR *) free + free->frb_header.hdr_length); + free = (frb*) ((UCHAR*) free + free->frb_header.hdr_length); free->frb_header.hdr_length = length; } @@ -627,7 +647,7 @@ static FRB alloc_global(UCHAR type, ULONG length, bool recurse) } -static SLONG create_process() +void EventManager::create_process() { /************************************** * @@ -639,35 +659,39 @@ static SLONG create_process() * Create process block unless it already exists. * **************************************/ - if (EVENT_process_offset) - return EVENT_process_offset; + acquire_shmem(); - acquire(); - PRB process = (PRB) alloc_global(type_prb, (SLONG) sizeof(prb), false); - insert_tail(&EVENT_header->evh_processes, &process->prb_processes); + prb* const process = (prb*) alloc_global(type_prb, sizeof(prb), false); + process->prb_process_id = PID; + insert_tail(&m_header->evh_processes, &process->prb_processes); SRQ_INIT(process->prb_sessions); - EVENT_process_offset = SRQ_REL_PTR(process); ISC_event_init(&process->prb_event); -#ifdef SOLARIS_MT + m_processOffset = SRQ_REL_PTR(process); + +#if (defined HAVE_MMAP || defined WIN_NT) ISC_STATUS_ARRAY local_status; - EVENT_process = (PRB) ISC_map_object(local_status, &EVENT_data, EVENT_process_offset, sizeof(prb)); + m_process = (prb*) ISC_map_object(local_status, &m_shmemData, m_processOffset, sizeof(prb)); +#else + m_process = process; #endif - process->prb_process_id = getpid(); + if (!m_process) + { + release_shmem(); + Firebird::status_exception::raise(local_status); + } probe_processes(); - release(); - if (gds__thread_start(watcher_thread, NULL, THREAD_medium, 0, 0)) - ERR_bugcheck_msg("cannot start thread"); + release_shmem(); - return EVENT_process_offset; + ThreadStart::start(watcher_thread, this, THREAD_medium, NULL); } -static void delete_event(EVNT event) +void EventManager::delete_event(evnt* event) { /************************************** * @@ -681,17 +705,20 @@ static void delete_event(EVNT event) **************************************/ remove_que(&event->evnt_events); - if (event->evnt_parent) { - EVNT parent = (EVNT) SRQ_ABS_PTR(event->evnt_parent); + if (event->evnt_parent) + { + evnt* const parent = (evnt*) SRQ_ABS_PTR(event->evnt_parent); if (!--parent->evnt_count) + { delete_event(parent); + } } - free_global((FRB) event); + free_global((frb*) event); } -static void delete_process(SLONG process_offset) +void EventManager::delete_process(SLONG process_offset) { /************************************** * @@ -703,48 +730,26 @@ static void delete_process(SLONG process_offset) * Delete a process block including friends and relations. * **************************************/ - PRB process = (PRB) SRQ_ABS_PTR(process_offset); + prb* const process = (prb*) SRQ_ABS_PTR(process_offset); -/* Delete any open sessions */ + // Delete any open sessions - while (!SRQ_EMPTY(process->prb_sessions)) { - SES session = (SES) ((UCHAR *) SRQ_NEXT(process->prb_sessions) - OFFSET(SES, ses_sessions)); + while (!SRQ_EMPTY(process->prb_sessions)) + { + ses* const session = (ses*) ((UCHAR*) SRQ_NEXT(process->prb_sessions) - OFFSET(ses*, ses_sessions)); delete_session(SRQ_REL_PTR(session)); } -/* Untangle and release process block */ + ISC_event_fini(&process->prb_event); + + // Untangle and release process block remove_que(&process->prb_processes); - free_global((FRB) process); - - if (EVENT_process_offset == process_offset) { - /* Terminate the event watcher thread */ - /* When we come through the exit handler, the event semaphore might - have already been released by another exit handler. So we cannot - use that semaphore to post the event. Besides, the watcher thread - would be terminated anyway because the whole NLM is being unloaded. */ - // CVC: NLM??? is this Novell Netware specific code??? - - process->prb_flags |= PRB_exiting; - bool timeout = false; - while (process->prb_flags & PRB_exiting && !timeout) { - ISC_event_post(&process->prb_event); - const SLONG value = ISC_event_clear(&process->prb_event); - release(); -#ifdef SOLARIS_MT - event_t* event = &EVENT_process->prb_event; -#else - event_t* event = &process->prb_event; -#endif - timeout = ISC_event_wait(event, value, 5 * 1000000) == FB_FAILURE; - acquire(); - } - EVENT_process_offset = 0; - } + free_global((frb*) process); } -static void delete_request(EVT_REQ request) +void EventManager::delete_request(evt_req* request) { /************************************** * @@ -756,17 +761,20 @@ static void delete_request(EVT_REQ request) * Release an unwanted and unloved request. * **************************************/ - SES session = (SES) SRQ_ABS_PTR(request->req_session); + ses* const session = (ses*) SRQ_ABS_PTR(request->req_session); - while (request->req_interests) { - RINT interest = (RINT) SRQ_ABS_PTR(request->req_interests); + while (request->req_interests) + { + req_int* const interest = (req_int*) SRQ_ABS_PTR(request->req_interests); request->req_interests = interest->rint_next; - if (historical_interest(session, interest->rint_event)) { + if (historical_interest(session, interest->rint_event)) + { remove_que(&interest->rint_interests); - free_global((FRB) interest); + free_global((frb*) interest); } - else { + else + { interest->rint_next = session->ses_interests; session->ses_interests = SRQ_REL_PTR(interest); interest->rint_request = (SRQ_PTR)0; @@ -774,11 +782,11 @@ static void delete_request(EVT_REQ request) } remove_que(&request->req_requests); - free_global((FRB) request); + free_global((frb*) request); } -static void delete_session(SLONG session_id) +void EventManager::delete_session(SLONG session_id) { /************************************** * @@ -790,7 +798,7 @@ static void delete_session(SLONG session_id) * Delete a session. * **************************************/ - SES session = (SES) SRQ_ABS_PTR(session_id); + ses* session = (ses*) SRQ_ABS_PTR(session_id); // if session currently delivered events, delay its deletion until deliver ends if (session->ses_flags & SES_delivering) @@ -798,39 +806,43 @@ static void delete_session(SLONG session_id) session->ses_flags |= SES_purge; // give a chance for delivering thread to detect SES_purge flag we just set - release(); + release_shmem(); THREAD_SLEEP(100); - acquire(); + acquire_shmem(); return; } -/* Delete all requests */ + // Delete all requests - while (!SRQ_EMPTY(session->ses_requests)) { + while (!SRQ_EMPTY(session->ses_requests)) + { srq requests = session->ses_requests; - EVT_REQ request = (EVT_REQ) ((UCHAR *) SRQ_NEXT(requests) - OFFSET(EVT_REQ, req_requests)); + evt_req* request = (evt_req*) ((UCHAR*) SRQ_NEXT(requests) - OFFSET(evt_req*, req_requests)); delete_request(request); } -/* Delete any historical interests */ + // Delete any historical interests - while (session->ses_interests) { - RINT interest = (RINT) SRQ_ABS_PTR(session->ses_interests); - EVNT event = (EVNT) SRQ_ABS_PTR(interest->rint_event); + while (session->ses_interests) + { + req_int* interest = (req_int*) SRQ_ABS_PTR(session->ses_interests); + evnt* event = (evnt*) SRQ_ABS_PTR(interest->rint_event); session->ses_interests = interest->rint_next; remove_que(&interest->rint_interests); - free_global((FRB) interest); + free_global((frb*) interest); if (SRQ_EMPTY(event->evnt_interests)) + { delete_event(event); + } } remove_que(&session->ses_sessions); - free_global((FRB) session); + free_global((frb*) session); } -static void deliver() +void EventManager::deliver() { /************************************** * @@ -842,26 +854,28 @@ static void deliver() * We've been poked -- deliver any satisfying requests. * **************************************/ - acquire(); - PRB process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); + prb* process = (prb*) SRQ_ABS_PTR(m_processOffset); process->prb_flags &= ~PRB_pending; srq* que2 = SRQ_NEXT(process->prb_sessions); while (que2 != &process->prb_sessions) { - SES session = (SES) ((UCHAR *) que2 - OFFSET(SES, ses_sessions)); + ses* session = (ses*) ((UCHAR*) que2 - OFFSET(ses*, ses_sessions)); session->ses_flags |= SES_delivering; const SLONG session_offset = SRQ_REL_PTR(session); const SLONG que2_offset = SRQ_REL_PTR(que2); - for (bool flag = true; flag;) { + for (bool flag = true; flag;) + { flag = false; srq* event_srq; - SRQ_LOOP(session->ses_requests, event_srq) { - EVT_REQ request = (EVT_REQ) ((UCHAR *) event_srq - OFFSET(EVT_REQ, req_requests)); - if (request_completed(request)) { + SRQ_LOOP(session->ses_requests, event_srq) + { + evt_req* request = (evt_req*) ((UCHAR*) event_srq - OFFSET(evt_req*, req_requests)); + if (request_completed(request)) + { deliver_request(request); - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); - session = (SES) SRQ_ABS_PTR(session_offset); + process = (prb*) SRQ_ABS_PTR(m_processOffset); + session = (ses*) SRQ_ABS_PTR(session_offset); que2 = (srq *) SRQ_ABS_PTR(que2_offset); flag = !(session->ses_flags & SES_purge); break; @@ -876,14 +890,14 @@ static void deliver() break; } else + { que2 = SRQ_NEXT((*que2)); + } } - - release(); } -static void deliver_request(EVT_REQ request) +void EventManager::deliver_request(evt_req* request) { /************************************** * @@ -896,85 +910,60 @@ static void deliver_request(EVT_REQ request) * Clean up request. * **************************************/ - UCHAR buffer[512]; + Firebird::HalfStaticArray buffer; + UCHAR* p = buffer.getBuffer(1); FPTR_EVENT_CALLBACK ast = request->req_ast; void* arg = request->req_ast_arg; - UCHAR* event_buffer = buffer; - UCHAR* p = buffer; - const UCHAR* end = buffer + sizeof(buffer); + *p++ = EPB_version1; -/* Loop thru interest block picking up event name, counts, and unlinking - stuff */ + // Loop thru interest block picking up event name, counts, and unlinking stuff - RINT interest; - for (SRQ_PTR next = request->req_interests; - next && (interest = (RINT) SRQ_ABS_PTR(next)); - next = interest->rint_next) + try { - interest = (RINT) SRQ_ABS_PTR(next); - EVNT event = (EVNT) SRQ_ABS_PTR(interest->rint_event); - if (end < p + event->evnt_length + 5) + req_int* interest; + for (SRQ_PTR next = request->req_interests; + next && (interest = (req_int*) SRQ_ABS_PTR(next)); + next = interest->rint_next) { - /* Running out of space - allocate some more and copy it over */ - fb_assert(event_buffer == buffer); /* we're in this block only once */ - // CVC: We don't check at run-time in the release version, it's - // likely to produce a buffer overrun if we reach MAX_EVENT_BUFFER, - // since new_buffer will be again and again this number. FIXED. - UCHAR* new_buffer = 0; - if (event_buffer == buffer) - new_buffer = (UCHAR*) gds__alloc((SLONG) MAX_EVENT_BUFFER); - /* FREE: at procedure exit */ - if (!new_buffer) - { /* NOMEM: */ - gds__log("failed to post all events"); - break; /* exit loop and send what we have */ + interest = (req_int*) SRQ_ABS_PTR(next); + evnt* event = (evnt*) SRQ_ABS_PTR(interest->rint_event); + + const size_t length = buffer.getCount(); + const size_t extent = event->evnt_length + sizeof(UCHAR) + sizeof(SLONG); + + if (length + extent > MAX_USHORT) + { + Firebird::BadAlloc::raise(); } - event_buffer = new_buffer; - memcpy(event_buffer, buffer, p - buffer); - p = event_buffer + (p - buffer); - end = event_buffer + MAX_EVENT_BUFFER; + + buffer.grow(length + extent); + p = buffer.begin() + length; + + *p++ = event->evnt_length; + memcpy(p, event->evnt_name, event->evnt_length); + p += event->evnt_length; + const SLONG count = event->evnt_count + 1; + *p++ = (UCHAR) (count); + *p++ = (UCHAR) (count >> 8); + *p++ = (UCHAR) (count >> 16); + *p++ = (UCHAR) (count >> 24); } - *p++ = event->evnt_length; - memcpy(p, event->evnt_name, event->evnt_length); - p += event->evnt_length; - const SLONG count = event->evnt_count + 1; - *p++ = (UCHAR) (count); - *p++ = (UCHAR) (count >> 8); - *p++ = (UCHAR) (count >> 16); - *p++ = (UCHAR) (count >> 24); + } + catch (const Firebird::BadAlloc&) + { + gds__log("Out of memory. Failed to post all events."); } delete_request(request); - release(); - (*ast)(arg, p - event_buffer, event_buffer); - if (event_buffer != buffer) - { - gds__free(event_buffer); - } - acquire(); + release_shmem(); + (*ast)(arg, p - buffer.begin(), buffer.begin()); + acquire_shmem(); } -static void exit_handler(void* arg) -{ -/************************************** - * - * e x i t _ h a n d l e r - * - ************************************** - * - * Functional description - * Cleanup on exit. - * - **************************************/ - - eventStartup.cleanup(); -} - - -static EVNT find_event(USHORT length, const TEXT* string, EVNT parent) +evnt* EventManager::find_event(USHORT length, const TEXT* string, evnt* parent) { /************************************** * @@ -986,11 +975,12 @@ static EVNT find_event(USHORT length, const TEXT* string, EVNT parent) * Lookup an event. * **************************************/ - SRQ_PTR parent_offset = (parent) ? SRQ_REL_PTR(parent) : 0; + const SRQ_PTR parent_offset = (parent) ? SRQ_REL_PTR(parent) : 0; srq* event_srq; - SRQ_LOOP(EVENT_header->evh_events, event_srq) { - EVNT event = (EVNT) ((UCHAR *) event_srq - OFFSET(EVNT, evnt_events)); + SRQ_LOOP(m_header->evh_events, event_srq) + { + evnt* const event = (evnt*) ((UCHAR*) event_srq - OFFSET(evnt*, evnt_events)); if (event->evnt_parent == parent_offset && event->evnt_length == length && !memcmp(string, event->evnt_name, length)) { @@ -1002,7 +992,7 @@ static EVNT find_event(USHORT length, const TEXT* string, EVNT parent) } -static void free_global(FRB block) +void EventManager::free_global(frb* block) { /************************************** * @@ -1015,32 +1005,32 @@ static void free_global(FRB block) * **************************************/ SRQ_PTR *ptr; - FRB free; + frb* free; - FRB prior = NULL; + frb* prior = NULL; SRQ_PTR offset = SRQ_REL_PTR(block); block->frb_header.hdr_type = type_frb; - for (ptr = &EVENT_header->evh_free; (free = (FRB) SRQ_ABS_PTR(*ptr)) && *ptr; + for (ptr = &m_header->evh_free; (free = (frb*) SRQ_ABS_PTR(*ptr)) && *ptr; prior = free, ptr = &free->frb_next) { if ((SCHAR *) block < (SCHAR *) free) break; } - if (offset <= 0 || offset > EVENT_header->evh_length || + if (offset <= 0 || offset > m_header->evh_length || (prior && (UCHAR*) block < (UCHAR*) prior + prior->frb_header.hdr_length)) { punt("free_global: bad block"); return; } -/* Start by linking block into chain */ + // Start by linking block into chain block->frb_next = *ptr; *ptr = offset; -/* Try to merge free block with next block */ + // Try to merge free block with next block if (free && (SCHAR *) block + block->frb_header.hdr_length == (SCHAR *) free) { @@ -1048,7 +1038,7 @@ static void free_global(FRB block) block->frb_next = free->frb_next; } -/* Next, try to merge the free block with the prior block */ + // Next, try to merge the free block with the prior block if (prior && (SCHAR *) prior + prior->frb_header.hdr_length == (SCHAR *) block) { @@ -1058,7 +1048,7 @@ static void free_global(FRB block) } -static RINT historical_interest(SES session, SRQ_PTR event) +req_int* EventManager::historical_interest(ses* session, SRQ_PTR event_offset) { /************************************** * @@ -1070,12 +1060,12 @@ static RINT historical_interest(SES session, SRQ_PTR event) * Find a historical interest, if any, of an event with a session. * **************************************/ - RINT interest; + req_int* interest; for (SRQ_PTR ptr = session->ses_interests; - ptr && (interest = (RINT) SRQ_ABS_PTR(ptr)); ptr = interest->rint_next) + ptr && (interest = (req_int*) SRQ_ABS_PTR(ptr)); ptr = interest->rint_next) { - if (interest->rint_event == event) + if (interest->rint_event == event_offset) return interest; } @@ -1083,7 +1073,7 @@ static RINT historical_interest(SES session, SRQ_PTR event) } -static void init_shmem(void* arg, SH_MEM shmem_data, bool initialize) +void EventManager::init_shmem(SH_MEM shmem_data, bool initialize) { /************************************** * @@ -1097,38 +1087,37 @@ static void init_shmem(void* arg, SH_MEM shmem_data, bool initialize) **************************************/ int mutex_state; -#if defined(WIN_NT) - char buffer[MAXPATHLEN]; - gds__prefix_lock(buffer, EVENT_FILE); - if ( (mutex_state = ISC_mutex_init(&MUTEX, buffer)) ) +#ifdef WIN_NT + if ( (mutex_state = ISC_mutex_init(MUTEX, shmem_data->sh_mem_name)) ) mutex_bugcheck("mutex init", mutex_state); #endif if (!initialize) return; - EVENT_header = (EVH) shmem_data->sh_mem_address; - EVENT_header->evh_length = EVENT_data.sh_mem_length_mapped; - EVENT_header->evh_version = EVENT_VERSION; - EVENT_header->evh_request_id = 0; - SRQ_INIT(EVENT_header->evh_processes); - SRQ_INIT(EVENT_header->evh_events); + m_header = (evh*) shmem_data->sh_mem_address; + m_header->evh_length = m_shmemData.sh_mem_length_mapped; + m_header->evh_version = EVENT_VERSION; + m_header->evh_request_id = 0; -#if !defined(WIN_NT) - if ( (mutex_state = ISC_mutex_init(&MUTEX)) ) + SRQ_INIT(m_header->evh_processes); + SRQ_INIT(m_header->evh_events); + +#ifndef WIN_NT + if ( (mutex_state = ISC_mutex_init(MUTEX)) ) mutex_bugcheck("mutex init", mutex_state); #endif - FRB free = (FRB) ((UCHAR*) EVENT_header + sizeof(evh)); - free->frb_header.hdr_length = EVENT_data.sh_mem_length_mapped - sizeof(evh); + frb* const free = (frb*) ((UCHAR*) m_header + sizeof(evh)); + free->frb_header.hdr_length = m_shmemData.sh_mem_length_mapped - sizeof(evh); free->frb_header.hdr_type = type_frb; free->frb_next = 0; - EVENT_header->evh_free = (UCHAR *) free - (UCHAR *) EVENT_header; + m_header->evh_free = (UCHAR*) free - (UCHAR*) m_header; } -static void insert_tail(srq * event_srq, srq * node) +void EventManager::insert_tail(srq * event_srq, srq * node) { /************************************** * @@ -1143,13 +1132,13 @@ static void insert_tail(srq * event_srq, srq * node) node->srq_forward = SRQ_REL_PTR(event_srq); node->srq_backward = event_srq->srq_backward; - srq* prior = (srq *) SRQ_ABS_PTR(event_srq->srq_backward); + srq* const prior = (srq *) SRQ_ABS_PTR(event_srq->srq_backward); prior->srq_forward = SRQ_REL_PTR(node); event_srq->srq_backward = SRQ_REL_PTR(node); } -static EVNT make_event(USHORT length, const TEXT* string, SLONG parent_offset) +evnt* EventManager::make_event(USHORT length, const TEXT* string, SLONG parent_offset) { /************************************** * @@ -1161,13 +1150,14 @@ static EVNT make_event(USHORT length, const TEXT* string, SLONG parent_offset) * Allocate an link in an event. * **************************************/ - EVNT event = (EVNT) alloc_global(type_evnt, (SLONG) (sizeof(evnt) + length), false); - insert_tail(&EVENT_header->evh_events, &event->evnt_events); + evnt* const event = (evnt*) alloc_global(type_evnt, sizeof(evnt) + length, false); + insert_tail(&m_header->evh_events, &event->evnt_events); SRQ_INIT(event->evnt_interests); - if (parent_offset) { + if (parent_offset) + { event->evnt_parent = parent_offset; - EVNT parent = (EVNT) SRQ_ABS_PTR(parent_offset); + evnt* parent = (evnt*) SRQ_ABS_PTR(parent_offset); ++parent->evnt_count; } @@ -1178,7 +1168,7 @@ static EVNT make_event(USHORT length, const TEXT* string, SLONG parent_offset) } -static void mutex_bugcheck(const TEXT* string, int mutex_state) +void EventManager::mutex_bugcheck(const TEXT* string, int mutex_state) { /************************************** * @@ -1191,7 +1181,7 @@ static void mutex_bugcheck(const TEXT* string, int mutex_state) * Post the bugcheck. * **************************************/ - TEXT msg[128]; + TEXT msg[BUFFER_TINY]; sprintf(msg, "EVENT: %s error, status = %d", string, mutex_state); gds__log(msg); @@ -1201,7 +1191,7 @@ static void mutex_bugcheck(const TEXT* string, int mutex_state) } -static void post_process(PRB process) +void EventManager::post_process(prb* process) { /************************************** * @@ -1213,16 +1203,13 @@ static void post_process(PRB process) * Wakeup process. * **************************************/ - process->prb_flags &= ~PRB_wakeup; process->prb_flags |= PRB_pending; - release(); ISC_event_post(&process->prb_event); - acquire(); } -static void probe_processes() +void EventManager::probe_processes() { /************************************** * @@ -1231,16 +1218,16 @@ static void probe_processes() ************************************** * * Functional description - * Probe a process to see if it still exists. If it doesn't, get - * rid of it. + * Probe a process to see if it still exists. + * If it doesn't, get rid of it. * **************************************/ srq* event_srq; - - SRQ_LOOP(EVENT_header->evh_processes, event_srq) { - PRB process = (PRB) ((UCHAR *) event_srq - OFFSET(PRB, prb_processes)); + SRQ_LOOP(m_header->evh_processes, event_srq) + { + prb* const process = (prb*) ((UCHAR*) event_srq - OFFSET(prb*, prb_processes)); const SLONG process_offset = SRQ_REL_PTR(process); - if (process_offset != EVENT_process_offset && + if (process_offset != m_processOffset && !ISC_check_process_existence(process->prb_process_id)) { event_srq = (srq *) SRQ_ABS_PTR(event_srq->srq_backward); @@ -1250,7 +1237,7 @@ static void probe_processes() } -static void punt(const TEXT* string) +void EventManager::punt(const TEXT* string) { /************************************** * @@ -1266,11 +1253,11 @@ static void punt(const TEXT* string) } -static void release() +void EventManager::release_shmem() { /************************************** * - * r e l e a s e + * r e l e a s e _ s h m e m * ************************************** * @@ -1284,13 +1271,14 @@ static void release() validate(); #endif - EVENT_header->evh_current_process = 0; - if (mutex_state = ISC_mutex_unlock(&MUTEX)) + m_header->evh_current_process = 0; + + if (mutex_state = ISC_mutex_unlock(MUTEX)) mutex_bugcheck("mutex lock", mutex_state); } -static void remove_que(srq* node) +void EventManager::remove_que(srq* node) { /************************************** * @@ -1311,7 +1299,7 @@ static void remove_que(srq* node) } -static bool request_completed(EVT_REQ request) +bool EventManager::request_completed(evt_req* request) { /************************************** * @@ -1323,10 +1311,11 @@ static bool request_completed(EVT_REQ request) * See if request is completed. * **************************************/ - RINT interest; - for (SRQ_PTR next = request->req_interests; next; next = interest->rint_next) { - interest = (RINT) SRQ_ABS_PTR(next); - EVNT event = (EVNT) SRQ_ABS_PTR(interest->rint_event); + req_int* interest; + for (SRQ_PTR next = request->req_interests; next; next = interest->rint_next) + { + interest = (req_int*) SRQ_ABS_PTR(next); + evnt* event = (evnt*) SRQ_ABS_PTR(interest->rint_event); if (interest->rint_count <= event->evnt_count) return true; } @@ -1336,7 +1325,7 @@ static bool request_completed(EVT_REQ request) #ifdef DEBUG_EVENT -static int validate() +int EventManager::validate() { /************************************** * @@ -1351,9 +1340,9 @@ static int validate() // Check consistency of global region (debugging only) SRQ_PTR next_free = 0; - SLONG offset; + ULONG offset; - for (offset = sizeof(evh); offset < EVENT_header->evh_length; + for (offset = sizeof(evh); offset < m_header->evh_length; offset += block->frb_header.hdr_length) { const event_hdr* block = (event_hdr*) SRQ_ABS_PTR(offset); @@ -1371,19 +1360,19 @@ static int validate() punt("bad free chain"); } if (block->frb_header.hdr_type == type_frb) { - next_free = ((FRB) block)->frb_next; - if (next_free >= EVENT_header->evh_length) + next_free = ((frb*) block)->frb_next; + if (next_free >= m_header->evh_length) punt("bad frb_next"); } } - if (offset != EVENT_header->evh_length) + if (offset != m_header->evh_length) punt("bad block length"); } #endif -static THREAD_ENTRY_DECLARE watcher_thread(THREAD_ENTRY_PARAM) +void EventManager::watcher_thread() { /************************************** * @@ -1395,47 +1384,64 @@ static THREAD_ENTRY_DECLARE watcher_thread(THREAD_ENTRY_PARAM) * Wait for something to happen. * **************************************/ - while (EVENT_process_offset) { - acquire(); - PRB process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); - process->prb_flags &= ~PRB_wakeup; + bool startup = true; - if (process->prb_flags & PRB_exiting) { - process->prb_flags &= ~PRB_exiting; - ISC_event_post(&process->prb_event); - release(); - break; - } -#ifdef WIN_NT - if (process->prb_flags & PRB_remap) { - process->prb_flags |= PRB_remap_over; - process->prb_flags &= ~PRB_remap; - release(); - while (true) { - Sleep(3); - acquire(); - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); - release(); - if (!(process->prb_flags & PRB_remap_over)) - break; + try + { + while (m_processOffset) + { + acquire_shmem(); + + prb* process = (prb*) SRQ_ABS_PTR(m_processOffset); + process->prb_flags &= ~PRB_wakeup; + +#if (defined HAVE_MMAP || defined WIN_NT) + if (process->prb_flags & PRB_remap) + { + process->prb_flags |= PRB_remap_over; + process->prb_flags &= ~PRB_remap; + + while (true) + { + release_shmem(); + THREAD_YIELD(); + acquire_shmem(); + + process = (prb*) SRQ_ABS_PTR(m_processOffset); + if (!(process->prb_flags & PRB_remap_over)) + break; + } } - acquire(); - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); - } #endif - const SLONG value = ISC_event_clear(&process->prb_event); - release(); - deliver(); - acquire(); - process = (PRB) SRQ_ABS_PTR(EVENT_process_offset); - release(); -#ifdef SOLARIS_MT - event_t* event = &EVENT_process->prb_event; -#else - event_t* event = &process->prb_event; -#endif - ISC_event_wait(event, value, 0); + const SLONG value = ISC_event_clear(&process->prb_event); + + if (process->prb_flags & PRB_pending) + { + deliver(); + } + + release_shmem(); + + if (startup) + { + startup = false; + m_startupSemaphore.release(); + } + + if (!m_processOffset) + break; + + event_t* event_ptr = &m_process->prb_event; + ISC_event_wait(event_ptr, value, 0); + } + + m_cleanupSemaphore.release(); + } + catch (const Firebird::Exception& ex) + { + iscLogException("Error in event watcher thread\n", ex); } - return 0; } + +} // namespace diff --git a/src/jrd/event.h b/src/jrd/event.h index f77ccfefc9..10a1f991d6 100644 --- a/src/jrd/event.h +++ b/src/jrd/event.h @@ -20,11 +20,7 @@ * All Rights Reserved. * Contributor(s): ______________________________________. * - * 23-Feb-2002 Dmitry Yemanov - Events wildcarding - * - * * 2002-02-23 Sean Leyne - Code Cleanup, removed old Win3.1 port (Windows_Only) - * */ #ifndef JRD_EVENT_H @@ -36,16 +32,11 @@ // Global section header -const int EVENT_VERSION = 4; - -const int EVENT_HASH_SIZE = 7; - -const int EVENT_DEFAULT_SIZE = 32768; -const int EVENT_EXTEND_SIZE = 32768; +const int EVENT_VERSION = 4; struct evh { - SLONG evh_length; // Current length of global section + ULONG evh_length; // Current length of global section UCHAR evh_version; // Version number of global section srq evh_events; // Known events srq evh_processes; // Known processes @@ -53,11 +44,8 @@ struct evh SRQ_PTR evh_current_process; // Current process, if any struct mtx evh_mutex; // Mutex controlling access SLONG evh_request_id; // Next request id - SRQ_PTR evh_hash_table[EVENT_HASH_SIZE]; }; -typedef evh *EVH; - // Common block header const int type_hdr = 1; // Event header @@ -71,7 +59,7 @@ const int type_max = 8; struct event_hdr // CVC: previous clash with ods.h's hdr { - SLONG hdr_length; // Length of block + ULONG hdr_length; // Length of block UCHAR hdr_type; // Type of block }; @@ -82,7 +70,6 @@ struct frb event_hdr frb_header; SLONG frb_next; // Next block }; -typedef frb *FRB; // Process blocks @@ -95,13 +82,13 @@ struct prb event_t prb_event; // Event on which to wait USHORT prb_flags; }; -typedef prb *PRB; const int PRB_wakeup = 1; // Schedule a wakeup for process const int PRB_pending = 2; // Wakeup has been requested, and is dangling +#if (defined HAVE_MMAP || defined WIN_NT) const int PRB_remap = 4; // need to remap shared memory const int PRB_remap_over= 8; // remap is over -const int PRB_exiting = 16; // Process is exiting +#endif // Session block @@ -113,7 +100,6 @@ struct ses SRQ_PTR ses_interests; // Historical interests USHORT ses_flags; }; -typedef ses *SES; const int SES_delivering = 1; // Watcher thread is delivering an event const int SES_purge = 2; // delete session after delivering an event @@ -130,7 +116,6 @@ struct evnt USHORT evnt_length; // Length of event name TEXT evnt_name[1]; // Event name }; -typedef evnt *EVNT; // Request block @@ -145,7 +130,6 @@ struct evt_req void *req_ast_arg; // Argument for ast SLONG req_request_id; // Request id, dummy }; -typedef evt_req *EVT_REQ; // Request interest block @@ -158,7 +142,6 @@ struct req_int SRQ_PTR rint_next; // Next interest of request SLONG rint_count; // Threshold count }; -typedef req_int *RINT; const int EPB_version1 = 1; diff --git a/src/jrd/event_proto.h b/src/jrd/event_proto.h index 6ce0d1e2af..07243c3808 100644 --- a/src/jrd/event_proto.h +++ b/src/jrd/event_proto.h @@ -19,21 +19,102 @@ * * All Rights Reserved. * Contributor(s): ______________________________________. - * - * 23-Feb-2002 Dmitry Yemanov - Events wildcarding - * */ #ifndef JRD_EVENT_PROTO_H #define JRD_EVENT_PROTO_H -void EVENT_cancel(SLONG); -SLONG EVENT_create_session(); -void EVENT_delete_session(SLONG); -void EVENT_deliver(); -void EVENT_post(USHORT, const TEXT*, USHORT, const TEXT*, USHORT); -SLONG EVENT_que(SLONG, USHORT, const TEXT*, USHORT, const UCHAR*, - FPTR_EVENT_CALLBACK, void*); +#include "../common/classes/init.h" +#include "../common/classes/semaphore.h" +#include "../common/classes/GenericMap.h" +#include "../common/classes/RefCounted.h" +#include "../jrd/ThreadData.h" +#include "../jrd/event.h" + +namespace Jrd { + +class Database; + +class EventManager: public Firebird::RefCounted, public Firebird::GlobalStorage +{ + typedef Firebird::GenericMap > > DbEventMgrMap; + + static Firebird::GlobalPtr g_emMap; + static Firebird::GlobalPtr g_mapMutex; + + const int PID; + +public: + static void init(Database*); + + explicit EventManager(const Firebird::string&); + ~EventManager(); + + SLONG createSession(); + void deleteSession(SLONG); + + SLONG queEvents(SLONG, USHORT, const TEXT*, USHORT, const UCHAR*, + FPTR_EVENT_CALLBACK, void*); + void cancelEvents(SLONG); + void postEvent(USHORT, const TEXT*, USHORT, const TEXT*, USHORT); + void deliverEvents(); + +private: + evh* acquire_shmem(); + frb* alloc_global(UCHAR type, ULONG length, bool recurse); + void create_process(); + void delete_event(evnt*); + void delete_process(SLONG); + void delete_request(evt_req*); + void delete_session(SLONG); + void deliver(); + void deliver_request(evt_req*); + void exit_handler(void *); + evnt* find_event(USHORT, const TEXT*, evnt*); + void free_global(frb*); + req_int* historical_interest(ses*, SLONG); + void init_shmem(SH_MEM, bool); + void insert_tail(srq*, srq*); + evnt* make_event(USHORT, const TEXT*, SLONG); + void post_process(prb*); + void probe_processes(); + void release_shmem(); + void remove_que(srq*); + bool request_completed(evt_req*); + void watcher_thread(); + + static THREAD_ENTRY_DECLARE watcher_thread(THREAD_ENTRY_PARAM arg) + { + EventManager* const eventMgr = static_cast(arg); + eventMgr->watcher_thread(); + return 0; + } + + static void init_shmem(void* arg, SH_MEM shmem, bool init) + { + EventManager* const eventMgr = static_cast(arg); + eventMgr->init_shmem(shmem, init); + } + + static void mutex_bugcheck(const TEXT*, int); + static void punt(const TEXT*); + + evh* m_header; + prb* m_process; + SLONG m_processOffset; + SH_MEM_T m_shmemData; + + Firebird::string m_dbId; + + Firebird::Semaphore m_startupSemaphore; + Firebird::Semaphore m_cleanupSemaphore; + +#ifdef WIN_NT + struct mtx m_mutex; +#endif +}; + +} // namespace #endif // JRD_EVENT_PROTO_H diff --git a/src/jrd/file_params.h b/src/jrd/file_params.h index 0e3d9f5397..db8547ad84 100644 --- a/src/jrd/file_params.h +++ b/src/jrd/file_params.h @@ -32,27 +32,13 @@ #ifndef JRD_FILE_PARAMS_H #define JRD_FILE_PARAMS_H -#ifdef NOHOSTNAME -static const char* EVENT_FILE = "isc_event1"; -static const char* LOCK_FILE = "isc_lock1.gbl"; -static const char* INIT_FILE = "isc_init1"; -static const char* GUARD_FILE = "isc_guard1"; -static const char* MONITOR_FILE = "isc_monitor1"; -static const char* SEM_FILE = "isc_sem1"; -#elif defined(WIN_NT) -static const char* EVENT_FILE = "%s.evn"; -static const char* LOCK_FILE = "%s.lck"; -static const char* INIT_FILE = "%s.int"; -static const char* GUARD_FILE = "%s.grd"; -static const char* MONITOR_FILE = "%s.mon"; -static const char* SEM_FILE = "%s.sem"; -#else -static const char* EVENT_FILE = "isc_event1.%s"; -static const char* LOCK_FILE = "isc_lock1.%s"; -static const char* INIT_FILE = "isc_init1.%s"; -static const char* GUARD_FILE = "isc_guard1.%s"; -static const char* MONITOR_FILE = "isc_monitor1.%s"; -static const char* SEM_FILE = "isc_sem1.%s"; +static const char* EVENT_FILE = "fb_event_%s"; +static const char* LOCK_FILE = "fb_lock_%s"; +static const char* MONITOR_FILE = "fb_monitor_%s"; + +#ifdef UNIX +static const char* INIT_FILE = "fb_init"; +static const char* SEM_FILE = "fb_sem"; #endif // CVC: Do we really need this information here after using autoconf? diff --git a/src/jrd/gds.cpp b/src/jrd/gds.cpp index 774ab84981..8561380ec3 100644 --- a/src/jrd/gds.cpp +++ b/src/jrd/gds.cpp @@ -3648,7 +3648,7 @@ public: Firebird::PathName lockPrefix; if (!fb_utils::readenv(FB_LOCK_ENV, lockPrefix)) { - lockPrefix = prefix; + lockPrefix = tempDir; } lockPrefix.copyTo(fb_prefix_lock_val, sizeof(fb_prefix_lock_val)); fb_prefix_lock = fb_prefix_lock_val; diff --git a/src/jrd/intl.cpp b/src/jrd/intl.cpp index cd2a56a9a3..5b87242cdf 100644 --- a/src/jrd/intl.cpp +++ b/src/jrd/intl.cpp @@ -880,20 +880,6 @@ bool INTL_defined_type(thread_db* tdbb, USHORT t_type) } -void INTL_init(thread_db* tdbb) -{ -/************************************** - * - * I N T L _ i n i t - * - ************************************** - * - * Functional description - * - **************************************/ -} - - USHORT INTL_key_length(thread_db* tdbb, USHORT idxType, USHORT iLength) { /************************************** diff --git a/src/jrd/intl_proto.h b/src/jrd/intl_proto.h index a971a593bb..2b0f6e1b05 100644 --- a/src/jrd/intl_proto.h +++ b/src/jrd/intl_proto.h @@ -43,7 +43,6 @@ int INTL_convert_string(dsc*, const dsc*, ErrorFunction); int INTL_data(const dsc*); int INTL_data_or_binary(const dsc*); bool INTL_defined_type(Jrd::thread_db*, USHORT); -void INTL_init(Jrd::thread_db*); USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT); Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1); Jrd::Collation* INTL_texttype_lookup(Jrd::thread_db* tdbb, USHORT parm1); diff --git a/src/jrd/isc.h b/src/jrd/isc.h index a9f1a40464..186b981e31 100644 --- a/src/jrd/isc.h +++ b/src/jrd/isc.h @@ -153,7 +153,7 @@ struct sh_mem void* sh_mem_object; void* sh_mem_interest; void* sh_mem_hdr_object; - SLONG* sh_mem_hdr_address; + ULONG* sh_mem_hdr_address; TEXT sh_mem_name[MAXPATHLEN]; }; typedef sh_mem SH_MEM_T; diff --git a/src/jrd/isc_s_proto.h b/src/jrd/isc_s_proto.h index 8bb3f7466c..da81a332b8 100644 --- a/src/jrd/isc_s_proto.h +++ b/src/jrd/isc_s_proto.h @@ -45,7 +45,7 @@ void* ISC_make_signal(bool, bool, int, int); typedef void (*FPTR_INIT_GLOBAL_REGION)(void*, struct sh_mem*, bool); UCHAR* ISC_map_file(ISC_STATUS*, const TEXT*, FPTR_INIT_GLOBAL_REGION, - void*, SLONG, struct sh_mem*); + void*, ULONG, struct sh_mem*); #if defined(WIN_NT) int ISC_mutex_init(struct mtx*, const TEXT*); #else @@ -58,8 +58,8 @@ int ISC_mutex_unlock(struct mtx *); void ISC_mutex_fini(struct mtx *); #if defined HAVE_MMAP || defined WIN_NT -UCHAR* ISC_map_object(ISC_STATUS *, SH_MEM, SLONG, SLONG); -void ISC_unmap_object(ISC_STATUS *, SH_MEM, UCHAR **, SLONG); +UCHAR* ISC_map_object(ISC_STATUS *, SH_MEM, ULONG, ULONG); +void ISC_unmap_object(ISC_STATUS *, SH_MEM, UCHAR **, ULONG); #endif #ifdef UNIX @@ -72,7 +72,7 @@ void ISC_sync_signals_reset(); ULONG ISC_exception_post(ULONG, const TEXT*); #endif -UCHAR* ISC_remap_file(ISC_STATUS *, struct sh_mem *, SLONG, bool); +UCHAR* ISC_remap_file(ISC_STATUS *, struct sh_mem *, ULONG, bool); void ISC_reset_timer(FPTR_VOID_PTR, void *, SLONG *, void **); void ISC_set_timer(SLONG, FPTR_VOID_PTR, void *, SLONG *, void **); void ISC_unmap_file(ISC_STATUS *, struct sh_mem *); diff --git a/src/jrd/isc_sync.cpp b/src/jrd/isc_sync.cpp index 87cb78fba5..cf36fa5cf8 100644 --- a/src/jrd/isc_sync.cpp +++ b/src/jrd/isc_sync.cpp @@ -131,7 +131,7 @@ union semun ushort *array; }; #endif -#endif /* UNIX */ +#endif // UNIX #ifdef HAVE_SYS_PARAM_H #include @@ -1889,7 +1889,9 @@ void *ISC_make_signal(bool create_flag, bool manual_reset, int process_idL, int UCHAR* ISC_map_file(ISC_STATUS* status_vector, const TEXT* filename, FPTR_INIT_GLOBAL_REGION init_routine, - void* init_arg, SLONG length, SH_MEM shmem_data) + void* init_arg, + ULONG length, + SH_MEM shmem_data) { /************************************** * @@ -1903,25 +1905,20 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, * routine (if given) or punt (leaving the file unmapped). * **************************************/ - TEXT expanded_filename[MAXPATHLEN], hostname[64]; - sprintf(expanded_filename, filename, ISC_get_host(hostname, sizeof(hostname))); + + TEXT expanded_filename[MAXPATHLEN]; + gds__prefix_lock(expanded_filename, filename); /* make the complete filename for the init file this file is to be used as a master lock to eliminate possible race conditions with just a single file locking. The race condition is caused as the conversion of a EXCLUSIVE lock to a SHARED lock is not atomic*/ - TEXT tmp[MAXPATHLEN]; - gds__prefix_lock(tmp, INIT_FILE); - string init_filename; /* to hold the complete filename of the init file. */ - init_filename.printf(tmp, hostname); /* already have the hostname! */ + TEXT init_filename[MAXPATHLEN]; + gds__prefix_lock(init_filename, INIT_FILE); const int oldmask = umask(0); - bool trunc_flag = true; - if (length < 0) { - length = -length; - trunc_flag = false; - } + const bool trunc_flag = (length != 0); /* open the init lock file */ MutexLockGuard guard(openFdInit); @@ -1931,7 +1928,7 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, #else int #endif - fd_init = open(init_filename.c_str(), O_RDWR | O_CREAT, 0666); + fd_init = open(init_filename, O_RDWR | O_CREAT, 0666); if (fd_init == -1) { error(status_vector, "open", errno); return NULL; @@ -1950,10 +1947,9 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, #ifdef USE_SYS5SEMAPHORE if (fdSem < 0) { - string semFileName; - gds__prefix_lock(tmp, SEM_FILE); - semFileName.printf(tmp, hostname); - int f = open(semFileName.c_str(), O_RDWR | O_CREAT, 0666); + TEXT sem_filename[MAXPATHLEN]; + gds__prefix_lock(sem_filename, SEM_FILE); + int f = open(sem_filename, O_RDWR | O_CREAT, 0666); if (f == -1) { error(status_vector, "open", errno); return NULL; @@ -2098,7 +2094,9 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, UCHAR* ISC_map_file(ISC_STATUS* status_vector, const TEXT* filename, FPTR_INIT_GLOBAL_REGION init_routine, - void* init_arg, SLONG length, SH_MEM shmem_data) + void* init_arg, + ULONG length, + SH_MEM shmem_data) { /************************************** * @@ -2112,18 +2110,12 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, * routine (if given) or punt (leaving the file unmapped). * **************************************/ - //SSHORT count; - TEXT expanded_filename[512]; -#ifdef NOHOSTNAME - strcpy(expanded_filename, filename); -#else - TEXT hostname[64]; - sprintf(expanded_filename, filename, ISC_get_host(hostname, sizeof(hostname))); -#endif + + TEXT expanded_filename[MAXPATHLEN]; + gds__prefix_lock(expanded_filename, filename); + const int oldmask = umask(0); bool init_flag = false; - if (length < 0) - length = -length; /* Produce shared memory key for file */ @@ -2383,13 +2375,12 @@ UCHAR* ISC_map_file(ISC_STATUS* status_vector, #ifdef WIN_NT -UCHAR* ISC_map_file( - ISC_STATUS* status_vector, - const TEXT* filename, - FPTR_INIT_GLOBAL_REGION init_routine, - void* init_arg, - SLONG length, - SH_MEM shmem_data) +UCHAR* ISC_map_file(ISC_STATUS* status_vector, + const TEXT* filename, + FPTR_INIT_GLOBAL_REGION init_routine, + void* init_arg, + ULONG length, + SH_MEM shmem_data) { /************************************** * @@ -2403,17 +2394,14 @@ UCHAR* ISC_map_file( * routine (if given) or punt (leaving the file unmapped). * **************************************/ - TEXT expanded_filename[MAXPATHLEN], hostname[64]; - TEXT map_file[MAXPATHLEN]; + TEXT object_name[MAXPATHLEN]; HANDLE file_handle, event_handle; int retry_count = 0; - bool trunc_flag = true; - if (length < 0) { - length = -length; - fb_assert(length > 0); // Was someone so crazy as to pass a bigger value than MAX_SLONG? - trunc_flag = false; - } + TEXT expanded_filename[MAXPATHLEN]; + gds__prefix_lock(expanded_filename, filename); + + const bool trunc_flag = (length != 0); /* retry to attach to mmapped file if the process initializing * dies during initialization. @@ -2422,16 +2410,13 @@ UCHAR* ISC_map_file( retry: retry_count++; - ISC_get_host(hostname, sizeof(hostname)); - sprintf(map_file, filename, hostname); - - file_handle = CreateFile(map_file, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); + file_handle = CreateFile(expanded_filename, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); if (file_handle == INVALID_HANDLE_VALUE) { error(status_vector, "CreateFile", GetLastError()); return NULL; @@ -2444,14 +2429,14 @@ UCHAR* ISC_map_file( // Create an event that can be used to determine if someone has already // initialized shared memory. - if (!make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_event")) + if (!make_object_name(object_name, sizeof(object_name), filename, "_event")) { error(status_vector, "make_object_name", GetLastError()); CloseHandle(file_handle); return NULL; } - event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, expanded_filename); + event_handle = CreateEvent(ISC_get_security_desc(), TRUE, FALSE, object_name); if (!event_handle) { error(status_vector, "CreateEvent", GetLastError()); CloseHandle(file_handle); @@ -2512,13 +2497,13 @@ UCHAR* ISC_map_file( else fdw_create = OPEN_ALWAYS; - file_handle = CreateFile(map_file, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - fdw_create, - FILE_ATTRIBUTE_NORMAL, - NULL); + file_handle = CreateFile(expanded_filename, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + fdw_create, + FILE_ATTRIBUTE_NORMAL, + NULL); if (file_handle == INVALID_HANDLE_VALUE) { CloseHandle(event_handle); error(status_vector, "CreateFile", GetLastError()); @@ -2528,7 +2513,7 @@ UCHAR* ISC_map_file( /* Create a file mapping object that will be used to make remapping possible. The current length of real mapped file and its name are saved in it. */ - if (!make_object_name(expanded_filename, sizeof(expanded_filename), filename, "_mapping")) + if (!make_object_name(object_name, sizeof(object_name), filename, "_mapping")) { error(status_vector, "make_object_name", GetLastError()); CloseHandle(event_handle); @@ -2536,12 +2521,11 @@ UCHAR* ISC_map_file( return NULL; } - HANDLE header_obj = CreateFileMapping ((HANDLE) -1, - ISC_get_security_desc(), - PAGE_READWRITE, - 0, - 2 * sizeof (SLONG), - expanded_filename); + HANDLE header_obj = CreateFileMapping(INVALID_HANDLE_VALUE, + ISC_get_security_desc(), + PAGE_READWRITE, + 0, 2 * sizeof(ULONG), + object_name); if (header_obj == NULL) { error(status_vector, "CreateFileMapping", GetLastError()); @@ -2561,7 +2545,7 @@ UCHAR* ISC_map_file( goto retry; } - SLONG* const header_address = (SLONG*) MapViewOfFile(header_obj, FILE_MAP_WRITE, 0, 0, 0); + ULONG* const header_address = (ULONG*) MapViewOfFile(header_obj, FILE_MAP_WRITE, 0, 0, 0); if (header_address == NULL) { error(status_vector, "MapViewOfFile", GetLastError()); @@ -2583,16 +2567,14 @@ UCHAR* ISC_map_file( /* Create the real file mapping object. */ - TEXT mapping_filename[sizeof(expanded_filename) + 15]; // enough for int32 as text - sprintf(mapping_filename, "%s%"SLONGFORMAT, expanded_filename, header_address[1]); + TEXT mapping_name[MAXPATHLEN + 15]; // enough for int32 as text + sprintf(mapping_name, "%s_mapping_%"ULONGFORMAT, filename, header_address[1]); - HANDLE file_obj = - CreateFileMapping(file_handle, - ISC_get_security_desc(), - PAGE_READWRITE, - 0, - length, - mapping_filename); + HANDLE file_obj = CreateFileMapping(file_handle, + ISC_get_security_desc(), + PAGE_READWRITE, + 0, length, + mapping_name); if (file_obj == NULL) { error(status_vector, "CreateFileMapping", GetLastError()); UnmapViewOfFile(header_address); @@ -2628,7 +2610,7 @@ UCHAR* ISC_map_file( shmem_data->sh_mem_interest = event_handle; shmem_data->sh_mem_hdr_object = header_obj; shmem_data->sh_mem_hdr_address = header_address; - strcpy(shmem_data->sh_mem_name, expanded_filename); + strcpy(shmem_data->sh_mem_name, filename); if (init_routine) (*init_routine) (init_arg, shmem_data, init_flag); @@ -2636,7 +2618,7 @@ UCHAR* ISC_map_file( if (init_flag) { FlushViewOfFile(address, 0); SetEvent(event_handle); - if (SetFilePointer(shmem_data->sh_mem_handle, length, NULL, FILE_BEGIN) == 0xFFFFFFFF || + if (SetFilePointer(shmem_data->sh_mem_handle, length, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER || !SetEndOfFile(shmem_data->sh_mem_handle) || !FlushViewOfFile(shmem_data->sh_mem_address, 0)) { @@ -2651,9 +2633,10 @@ UCHAR* ISC_map_file( #ifdef HAVE_MMAP -UCHAR *ISC_map_object(ISC_STATUS * status_vector, +UCHAR* ISC_map_object(ISC_STATUS* status_vector, SH_MEM shmem_data, - SLONG object_offset, SLONG object_length) + ULONG object_offset, + ULONG object_length) { /************************************** * @@ -2668,13 +2651,13 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector, /* Get system page size as this is the unit of mapping. */ #ifdef SOLARIS - const SLONG page_size = sysconf(_SC_PAGESIZE); + const ULONG page_size = sysconf(_SC_PAGESIZE); if (page_size == -1) { error(status_vector, "sysconf", errno); return NULL; } #else - const SLONG page_size = (int) getpagesize(); + const ULONG page_size = (int) getpagesize(); if (page_size == -1) { error(status_vector, "getpagesize", errno); return NULL; @@ -2684,9 +2667,9 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector, /* Compute the start and end page-aligned offsets which contain the object being mapped. */ - const SLONG start = (object_offset / page_size) * page_size; - const SLONG end = (((object_offset + object_length) / page_size) + 1) * page_size; - const SLONG length = end - start; + const ULONG start = (object_offset / page_size) * page_size; + const ULONG end = FB_ALIGN(object_offset + object_length, page_size); + const ULONG length = end - start; int fd = shmem_data->sh_mem_handle; UCHAR* address = (UCHAR*) mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, start); @@ -2706,7 +2689,8 @@ UCHAR *ISC_map_object(ISC_STATUS * status_vector, void ISC_unmap_object(ISC_STATUS* status_vector, SH_MEM shmem_data, - UCHAR** object_pointer, SLONG object_length) + UCHAR** object_pointer, + ULONG object_length) { /************************************** * @@ -2722,13 +2706,13 @@ void ISC_unmap_object(ISC_STATUS* status_vector, /* Get system page size as this is the unit of mapping. */ #ifdef SOLARIS - const SLONG page_size = sysconf(_SC_PAGESIZE); + const ULONG page_size = sysconf(_SC_PAGESIZE); if (page_size == -1) { error(status_vector, "sysconf", errno); return; // false; } #else - const SLONG page_size = (int) getpagesize(); + const ULONG page_size = (int) getpagesize(); if (page_size == -1) { error(status_vector, "getpagesize", errno); return; // false; @@ -2741,7 +2725,7 @@ void ISC_unmap_object(ISC_STATUS* status_vector, UCHAR* start = (UCHAR *) ((U_IPTR) * object_pointer & ~(page_size - 1)); const UCHAR* end = (UCHAR*) ((U_IPTR) ((*object_pointer + object_length) + (page_size - 1)) & ~(page_size - 1)); - const SLONG length = end - start; + const ULONG length = end - start; if (munmap((char *) start, length) == -1) { error(status_vector, "munmap", errno); @@ -2757,7 +2741,8 @@ void ISC_unmap_object(ISC_STATUS* status_vector, #ifdef WIN_NT UCHAR* ISC_map_object(ISC_STATUS* status_vector, SH_MEM shmem_data, - SLONG object_offset, SLONG object_length) + ULONG object_offset, + ULONG object_length) { /************************************** * @@ -2772,14 +2757,14 @@ UCHAR* ISC_map_object(ISC_STATUS* status_vector, SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); - const SLONG page_size = sys_info.dwAllocationGranularity; + const ULONG page_size = sys_info.dwAllocationGranularity; // Compute the start and end page-aligned offsets which // contain the object being mapped. - const SLONG start = (object_offset / page_size) * page_size; - const SLONG end = (((object_offset + object_length) / page_size) + 1) * page_size; - const SLONG length = end - start; + const ULONG start = (object_offset / page_size) * page_size; + const ULONG end = FB_ALIGN(object_offset + object_length, page_size); + const ULONG length = end - start; const HANDLE handle = shmem_data->sh_mem_object; UCHAR* address = (UCHAR*) MapViewOfFile(handle, FILE_MAP_WRITE, 0, start, length); @@ -2797,7 +2782,8 @@ UCHAR* ISC_map_object(ISC_STATUS* status_vector, void ISC_unmap_object(ISC_STATUS* status_vector, SH_MEM shmem_data, - UCHAR** object_pointer, SLONG object_length) + UCHAR** object_pointer, + ULONG object_length) { /************************************** * @@ -2812,7 +2798,7 @@ void ISC_unmap_object(ISC_STATUS* status_vector, **************************************/ SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); - const SLONG page_size = sys_info.dwAllocationGranularity; + const ULONG page_size = sys_info.dwAllocationGranularity; // Compute the start and end page-aligned offsets which // contain the object being mapped. @@ -3623,8 +3609,10 @@ void ISC_mutex_set_spin_count (struct mtx *mutex, ULONG spins) #ifdef UNIX #ifdef HAVE_MMAP #define ISC_REMAP_FILE_DEFINED -UCHAR *ISC_remap_file(ISC_STATUS * status_vector, - SH_MEM shmem_data, SLONG new_length, bool flag) +UCHAR *ISC_remap_file(ISC_STATUS* status_vector, + SH_MEM shmem_data, + ULONG new_length, + bool flag) { /************************************** * @@ -3669,9 +3657,9 @@ UCHAR *ISC_remap_file(ISC_STATUS * status_vector, #ifdef WIN_NT #define ISC_REMAP_FILE_DEFINED UCHAR* ISC_remap_file(ISC_STATUS * status_vector, - SH_MEM shmem_data, - SLONG new_length, - bool flag) + SH_MEM shmem_data, + ULONG new_length, + bool flag) { /************************************** * @@ -3686,7 +3674,7 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector, if (flag) { - if (SetFilePointer(shmem_data->sh_mem_handle, new_length, NULL, FILE_BEGIN) == 0xFFFFFFFF || + if (SetFilePointer(shmem_data->sh_mem_handle, new_length, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER || !SetEndOfFile(shmem_data->sh_mem_handle) || !FlushViewOfFile(shmem_data->sh_mem_address, 0)) { @@ -3709,16 +3697,15 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector, HANDLE file_obj; while (true) { - TEXT expanded_filename[MAXPATHLEN]; - sprintf(expanded_filename, "%s%"SLONGFORMAT, shmem_data->sh_mem_name, - shmem_data->sh_mem_hdr_address[1] + 1); + TEXT mapping_name[MAXPATHLEN + 15]; // enough for int32 as text + sprintf(mapping_name, "%s_mapping_%"ULONGFORMAT, + shmem_data->sh_mem_name, shmem_data->sh_mem_hdr_address[1] + 1); file_obj = CreateFileMapping(shmem_data->sh_mem_handle, - ISC_get_security_desc(), - PAGE_READWRITE, - 0, - new_length, - expanded_filename); + ISC_get_security_desc(), + PAGE_READWRITE, + 0, new_length, + mapping_name); if (!((GetLastError() == ERROR_ALREADY_EXISTS) && flag)) break; @@ -3766,7 +3753,7 @@ UCHAR* ISC_remap_file(ISC_STATUS * status_vector, #ifndef ISC_REMAP_FILE_DEFINED UCHAR* ISC_remap_file(ISC_STATUS * status_vector, SH_MEM shmem_data, - SLONG new_length, + ULONG new_length, bool flag) { /************************************** diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index b674a1043e..136d2dca7e 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -861,9 +861,6 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status, bool first = false; - LCK_init(tdbb, LCK_OWNER_attachment); // For the attachment - attachment->att_flags |= ATT_lck_init_done; - if (dbb->dbb_filename.empty()) { #if defined(DEV_BUILD) && defined(SUPERSERVER) @@ -891,19 +888,22 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status, else dbb->dbb_database_name = expanded_name; - // Extra LCK_init() done to keep the lock table until the - // database is shutdown() after the last detach. + PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); + pageSpace->file = PIO_open(dbb, expanded_name, file_name, false); + + // Initialize the lock manager + dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId()); + LCK_init(tdbb, LCK_OWNER_database); dbb->dbb_flags |= DBB_lck_init_done; - INI_init(tdbb); - - PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); - pageSpace->file = PIO_open(dbb, expanded_name, file_name, false); + LCK_init(tdbb, LCK_OWNER_attachment); + attachment->att_flags |= ATT_lck_init_done; // Initialize locks init_database_locks(tdbb); + INI_init(tdbb); SHUT_init(tdbb); PAG_header_init(tdbb); INI_init2(tdbb); @@ -939,6 +939,11 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status, // looks like someone tries to attach incompatibly status_exception::raise(Arg::Gds(isc_bad_dpb_content)); } + + fb_assert(dbb->dbb_lock_mgr); + + LCK_init(tdbb, LCK_OWNER_attachment); + attachment->att_flags |= ATT_lck_init_done; } // Attachments to a ReadOnly database need NOT do garbage collection @@ -1361,9 +1366,7 @@ ISC_STATUS GDS_CANCEL_BLOB(ISC_STATUS* user_status, blb** blob_handle) } -ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status, - Attachment** handle, - SLONG* id) +ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status, Attachment** handle, SLONG* id) { /************************************** * @@ -1383,7 +1386,12 @@ ISC_STATUS GDS_CANCEL_EVENTS(ISC_STATUS* user_status, DatabaseContextHolder dbbHolder(tdbb); check_database(tdbb); - EVENT_cancel(*id); + Database* const dbb = tdbb->getDatabase(); + + if (dbb->dbb_event_mgr) + { + dbb->dbb_event_mgr->cancelEvents(*id); + } } catch (const Exception& ex) { @@ -1823,19 +1831,6 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status, dbb->dbb_page_size = (page_size > MAX_PAGE_SIZE) ? MAX_PAGE_SIZE : page_size; - LCK_init(tdbb, LCK_OWNER_attachment); // For the attachment - attachment->att_flags |= ATT_lck_init_done; - // Extra LCK_init() done to keep the lock table until the - // database is shutdown() after the last detach. - LCK_init(tdbb, LCK_OWNER_database); - dbb->dbb_flags |= DBB_lck_init_done; - - INI_init(tdbb); - PAG_init(tdbb); - initing_security = true; - - SCL_init(tdbb, true, userId); - initing_security = false; PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); @@ -1885,9 +1880,24 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status, const jrd_file* const first_dbb_file = pageSpace->file; + // Initialize the lock manager + dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId()); + + LCK_init(tdbb, LCK_OWNER_database); + dbb->dbb_flags |= DBB_lck_init_done; + + LCK_init(tdbb, LCK_OWNER_attachment); + attachment->att_flags |= ATT_lck_init_done; + // Initialize locks init_database_locks(tdbb); + INI_init(tdbb); + PAG_init(tdbb); + initing_security = true; + + SCL_init(tdbb, true, userId); + if (options.dpb_set_page_buffers) dbb->dbb_page_buffers = options.dpb_page_buffers; @@ -2524,13 +2534,17 @@ ISC_STATUS GDS_QUE_EVENTS(ISC_STATUS* user_status, Database* const dbb = tdbb->getDatabase(); Lock* const lock = dbb->dbb_lock; + EventManager::init(dbb); + if (!attachment->att_event_session) { - attachment->att_event_session = EVENT_create_session(); + attachment->att_event_session = dbb->dbb_event_mgr->createSession(); } - *id = EVENT_que(attachment->att_event_session, lock->lck_length, - (const TEXT*) &lock->lck_key, length, items, ast, arg); + *id = dbb->dbb_event_mgr->queEvents(attachment->att_event_session, + lock->lck_length, (const TEXT*) &lock->lck_key, + length, items, + ast, arg); } catch (const Exception& ex) { @@ -4654,10 +4668,6 @@ static Database* init(thread_db* tdbb, } } - // Initialize the lock manager - - dbb->dbb_lock_mgr = LockManager::create(expanded_filename); - // Initialize a number of subsystems TRA_init(dbb); @@ -4672,8 +4682,6 @@ static Database* init(thread_db* tdbb, dbb->dbb_decrypt = (Database::crypt_routine) crypt_lib.lookupSymbol(decrypt_entrypoint); } - INTL_init(tdbb); - return dbb; } @@ -4838,8 +4846,10 @@ static void release_attachment(thread_db* tdbb, Attachment* attachment, ISC_STAT } #endif - if (attachment->att_event_session) - EVENT_delete_session(attachment->att_event_session); + if (dbb->dbb_event_mgr && attachment->att_event_session) + { + dbb->dbb_event_mgr->deleteSession(attachment->att_event_session); + } if (attachment->att_id_lock) LCK_release(tdbb, attachment->att_id_lock); @@ -4870,7 +4880,7 @@ static void release_attachment(thread_db* tdbb, Attachment* attachment, ISC_STAT detachLocksFromAttachment(attachment); if (attachment->att_flags & ATT_lck_init_done) { - LCK_fini(tdbb, LCK_OWNER_attachment); // For the attachment + LCK_fini(tdbb, LCK_OWNER_attachment); attachment->att_flags &= ~ATT_lck_init_done; } @@ -5088,8 +5098,6 @@ static void shutdown_database(Database* dbb, const bool release_pools) CMP_fini(tdbb); CCH_fini(tdbb); - DatabaseSnapshot::cleanup(tdbb); - if (dbb->dbb_backup_manager) dbb->dbb_backup_manager->shutdown(tdbb); @@ -5150,7 +5158,7 @@ static void shutdown_database(Database* dbb, const bool release_pools) if (dbb->dbb_flags & DBB_lck_init_done) { dbb->dbb_page_manager.releaseLocks(); - LCK_fini(tdbb, LCK_OWNER_database); // For the database + LCK_fini(tdbb, LCK_OWNER_database); dbb->dbb_flags &= ~DBB_lck_init_done; } diff --git a/src/jrd/os/thd_priority.h b/src/jrd/os/thd_priority.h index 7b6fdc16e2..7c2a216689 100644 --- a/src/jrd/os/thd_priority.h +++ b/src/jrd/os/thd_priority.h @@ -39,6 +39,7 @@ #include "../common/classes/alloc.h" #include "../common/classes/init.h" #include "../common/classes/array.h" +#include "../jrd/ThreadStart.h" #include #include diff --git a/src/jrd/pag.h b/src/jrd/pag.h index 1fe96ecc17..139e9783c1 100644 --- a/src/jrd/pag.h +++ b/src/jrd/pag.h @@ -36,6 +36,7 @@ #include "../include/fb_blk.h" #include "../common/classes/array.h" +#include "../jrd/ods.h" namespace Jrd { diff --git a/src/lock/lock.cpp b/src/lock/lock.cpp index ac26393096..ce5d2061ec 100644 --- a/src/lock/lock.cpp +++ b/src/lock/lock.cpp @@ -96,7 +96,7 @@ #include #define MUTEX &m_shmemMutex #else -#define MUTEX m_header->lhb_mutex +#define MUTEX &m_header->lhb_mutex #endif #ifdef DEV_BUILD @@ -159,17 +159,12 @@ static const bool compatibility[LCK_max][LCK_max] = namespace Jrd { -const char* LockManager::PATTERN = "firebird_db_%d_lock"; - Firebird::GlobalPtr LockManager::g_lmMap; Firebird::GlobalPtr LockManager::g_mapMutex; -LockManager* LockManager::create(const Firebird::PathName& filename) +LockManager* LockManager::create(const Firebird::string& id) { - //const size_t HASH_SIZE = 997; - const int id = 0;//filename.hash(HASH_SIZE); - Firebird::MutexLockGuard guard(g_mapMutex); LockManager* lockMgr = NULL; @@ -180,26 +175,24 @@ LockManager* LockManager::create(const Firebird::PathName& filename) fb_assert(lockMgr); - lockMgr->addRef(); return lockMgr; } -LockManager::LockManager(int dbId) + +LockManager::LockManager(const Firebird::string& id) : PID(getpid()), m_bugcheck(false), m_header(NULL), m_process(NULL), m_processOffset(0), - m_dbId(dbId), - m_lockFile(getPool()) + m_dbId(getPool(), id) { -// m_lockFile.printf(PATTERN, m_dbId); - TEXT buffer[MAXPATHLEN]; - gds__prefix_lock(buffer, LOCK_FILE); - m_lockFile = buffer; + Firebird::string name; + name.printf(LOCK_FILE, m_dbId.c_str()); ISC_STATUS_ARRAY local_status; - if (!(m_header = (lhb*) ISC_map_file(local_status, m_lockFile.c_str(), + if (!(m_header = (lhb*) ISC_map_file(local_status, + name.c_str(), initialize, this, Config::getLockMemSize(), &m_shmem))) @@ -207,6 +200,8 @@ LockManager::LockManager(int dbId) Firebird::status_exception::raise(local_status); } + fb_assert(m_header->lhb_version == LHB_VERSION); + Firebird::MutexLockGuard guard(g_mapMutex); if (g_lmMap->put(m_dbId, this)) @@ -251,10 +246,9 @@ LockManager::~LockManager() release_mutex(); } - ISC_mutex_fini(MUTEX); - if (m_header) { + ISC_mutex_fini(MUTEX); ISC_unmap_file(local_status, &m_shmem); } @@ -507,7 +501,7 @@ SRQ_PTR LockManager::enqueue(thread_db* tdbb, else { ++m_header->lhb_operations[0]; } - + insert_tail(&lock->lbl_requests, &request->lrq_lbl_requests); request->lrq_data = data; const SRQ_PTR lock_id = grant_or_que(tdbb, request, lock, lck_wait); @@ -1062,7 +1056,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset) #endif ) { - const SLONG length = m_header->lhb_length; + const ULONG new_length = m_header->lhb_length; #if (defined HAVE_MMAP || defined WIN_NT) Firebird::WriteLockGuard guard(m_remapSync); @@ -1070,7 +1064,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset) remap_local_owners(); // Remap the shared memory region ISC_STATUS_ARRAY status_vector; - lhb* const header = (lhb*) ISC_remap_file(status_vector, &m_shmem, length, false); + lhb* const header = (lhb*) ISC_remap_file(status_vector, &m_shmem, new_length, false); if (header) m_header = header; else @@ -1109,7 +1103,7 @@ void LockManager::acquire_shmem(SRQ_PTR owner_offset) } -UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector) +UCHAR* LockManager::alloc(USHORT size, ISC_STATUS* status_vector) { /************************************** * @@ -1124,32 +1118,22 @@ UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector) size = FB_ALIGN(size, FB_ALIGNMENT); ASSERT_ACQUIRED; const ULONG block = m_header->lhb_used; - m_header->lhb_used += size; // Make sure we haven't overflowed the lock table. If so, bump the size of the table. - if (m_header->lhb_used > m_header->lhb_length -#ifdef LOCK_DEBUG_REMAP - // If we're debugging remaps, force a remap every-so-often. - || ((debug_remap_count++ % DEBUG_REMAP_INTERVAL) == 0 && m_processOffset) -#endif - ) + if (m_header->lhb_used + size > m_header->lhb_length) { - const bool extend = (m_header->lhb_used > m_header->lhb_length); - m_header->lhb_used -= size; - #if (defined HAVE_MMAP || defined WIN_NT) Firebird::WriteLockGuard guard(m_remapSync); // Post remapping notifications remap_local_owners(); // Remap the shared memory region - const ULONG length = m_shmem.sh_mem_length_mapped + (extend ? Config::getLockMemSize() : 0); - lhb* header = (lhb*) ISC_remap_file(status_vector, &m_shmem, length, true); + const ULONG new_length = m_shmem.sh_mem_length_mapped + Config::getLockMemSize(); + lhb* header = (lhb*) ISC_remap_file(status_vector, &m_shmem, new_length, true); if (header) { m_header = header; ASSERT_ACQUIRED; m_header->lhb_length = m_shmem.sh_mem_length_mapped; - m_header->lhb_used += size; } else #endif @@ -1169,6 +1153,8 @@ UCHAR* LockManager::alloc(SSHORT size, ISC_STATUS* status_vector) } } + m_header->lhb_used += size; + #ifdef DEV_BUILD // This version of alloc() doesn't initialize memory. To shake out // any bugs, in DEV_BUILD we initialize it to a "funny" pattern. @@ -1299,14 +1285,6 @@ void LockManager::blocking_action(thread_db* tdbb, } -THREAD_ENTRY_DECLARE LockManager::blocking_action_thread(THREAD_ENTRY_PARAM arg) -{ - LockManager* const lockMgr = static_cast(arg); - lockMgr->blocking_action_thread(); - return 0; -} - - void LockManager::blocking_action_thread() { /************************************** @@ -1334,14 +1312,12 @@ void LockManager::blocking_action_thread() try { - SRQ_PTR* process_offset_ptr = (SRQ_PTR*) &m_processOffset; - while (true) { m_localMutex.enter(); // See if the main thread has requested us to go away - if (!*process_offset_ptr || m_process->prc_process_id != PID) + if (!m_processOffset || m_process->prc_process_id != PID) { if (atStartup) { @@ -1357,7 +1333,7 @@ void LockManager::blocking_action_thread() Firebird::HalfStaticArray blocking_owners; acquire_shmem(DUMMY_OWNER); - const prc* const process = (prc*) SRQ_ABS_PTR(*process_offset_ptr); + const prc* const process = (prc*) SRQ_ABS_PTR(m_processOffset); srq* lock_srq; SRQ_LOOP(process->prc_owners, lock_srq) @@ -1368,7 +1344,7 @@ void LockManager::blocking_action_thread() release_mutex(); - while (blocking_owners.getCount() && *process_offset_ptr) + while (blocking_owners.getCount() && m_processOffset) { const SRQ_PTR owner_offset = blocking_owners.pop(); acquire_shmem(owner_offset); @@ -1466,6 +1442,18 @@ void LockManager::bug(ISC_STATUS* status_vector, const TEXT* string) { m_bugcheck = true; + // The lock table has some problem - copy it for later analysis + + TEXT buffer[MAXPATHLEN]; + gds__prefix(buffer, "lock_table.dump"); + const TEXT* const lock_file = buffer; + FILE* const fd = fopen(lock_file, "wb"); + if (fd) + { + fwrite(m_header, 1, m_header->lhb_used, fd); + fclose(fd); + } + // If the current mutex acquirer is in the same process, release the mutex if (m_header && (m_header->lhb_active_owner > 0)) { @@ -1519,8 +1507,7 @@ bool LockManager::create_owner(ISC_STATUS* status_vector, if (m_header->lhb_version != LHB_VERSION) { TEXT bug_buffer[BUFFER_TINY]; - sprintf(bug_buffer, - "inconsistent lock table version number; found %d, expected %d", + sprintf(bug_buffer, "inconsistent lock table version number; found %d, expected %d", m_header->lhb_version, LHB_VERSION); bug(status_vector, bug_buffer); return false; @@ -2152,6 +2139,7 @@ void LockManager::init_owner_block(own* owner, UCHAR owner_type, LOCK_OWNER_T ow owner->own_count = 1; owner->own_owner_id = owner_id; owner->own_process = m_processOffset; + owner->own_thread_id = 0; SRQ_INIT(owner->own_lhb_owners); SRQ_INIT(owner->own_prc_owners); SRQ_INIT(owner->own_requests); @@ -2177,7 +2165,7 @@ void LockManager::initialize(SH_MEM shmem_data, bool initialize) * **************************************/ #ifdef WIN_NT - if (ISC_mutex_init(MUTEX, m_lockFile.c_str())) { + if (ISC_mutex_init(MUTEX, shmem_data->sh_mem_name)) { bug(NULL, "mutex init failed"); } #endif @@ -2236,7 +2224,7 @@ void LockManager::initialize(SH_MEM shmem_data, bool initialize) if (Config::getLockGrantOrder()) m_header->lhb_flags |= LHB_lock_ordering; - const SLONG length = sizeof(lhb) + (m_header->lhb_hash_slots * sizeof(m_header->lhb_hash[0])); + const ULONG length = sizeof(lhb) + (m_header->lhb_hash_slots * sizeof(m_header->lhb_hash[0])); m_header->lhb_length = shmem_data->sh_mem_length_mapped; m_header->lhb_used = FB_ALIGN(length, FB_ALIGNMENT); diff --git a/src/lock/lock.h b/src/lock/lock.h index 18eec94322..e1b4b126ad 100644 --- a/src/lock/lock.h +++ b/src/lock/lock.h @@ -90,14 +90,12 @@ const SSHORT LCK_NO_WAIT = 0; const UCHAR type_null = 0; const UCHAR type_lhb = 1; -const UCHAR type_prb = 2; -const UCHAR type_lrq = 3; -const UCHAR type_lbl = 4; -const UCHAR type_his = 5; -const UCHAR type_smbx = 6; -const UCHAR type_shb = 7; -const UCHAR type_own = 8; -const UCHAR type_lpr = 9; +const UCHAR type_lrq = 2; +const UCHAR type_lbl = 3; +const UCHAR type_his = 4; +const UCHAR type_shb = 5; +const UCHAR type_own = 6; +const UCHAR type_lpr = 7; const UCHAR type_MAX = type_lpr; // Version number of the lock table. @@ -134,11 +132,11 @@ struct lhb srq lhb_free_owners; // Free owner blocks srq lhb_free_locks; // Free lock blocks srq lhb_free_requests; // Free lock requests - SLONG lhb_length; // Size of lock table - SLONG lhb_used; // Bytes of lock table in use + ULONG lhb_length; // Size of lock table + ULONG lhb_used; // Bytes of lock table in use USHORT lhb_hash_slots; // Number of hash slots allocated USHORT lhb_flags; // Miscellaneous info - mtx lhb_mutex[1]; // Mutex controlling access + struct mtx lhb_mutex; // Mutex controlling access SRQ_PTR lhb_history; ULONG lhb_scan_interval; // Deadlock scan interval (secs) ULONG lhb_acquire_spins; diff --git a/src/lock/lock_proto.h b/src/lock/lock_proto.h index eb9b91a686..0797feca5f 100644 --- a/src/lock/lock_proto.h +++ b/src/lock/lock_proto.h @@ -43,16 +43,15 @@ class thread_db; class LockManager : public Firebird::RefCounted, public Firebird::GlobalStorage { - typedef Firebird::GenericMap > > DbLockMgrMap; + typedef Firebird::GenericMap > > DbLockMgrMap; static Firebird::GlobalPtr g_lmMap; static Firebird::GlobalPtr g_mapMutex; - static const char* PATTERN; const int PID; public: - static LockManager* create(const Firebird::PathName&); + static LockManager* create(const Firebird::string&); bool initializeOwner(thread_db*, LOCK_OWNER_T, UCHAR, SRQ_PTR*); void shutdownOwner(thread_db*, SRQ_PTR*); @@ -72,7 +71,7 @@ public: SLONG writeData(SRQ_PTR, SLONG); private: - explicit LockManager(int); + explicit LockManager(const Firebird::string&); ~LockManager(); bool lockOrdering() const @@ -81,7 +80,7 @@ private: } void acquire_shmem(SRQ_PTR); - UCHAR* alloc(SSHORT, ISC_STATUS*); + UCHAR* alloc(USHORT, ISC_STATUS*); lbl* alloc_lock(USHORT, ISC_STATUS*); void blocking_action(thread_db*, SRQ_PTR, SRQ_PTR); void blocking_action_thread(); @@ -133,7 +132,12 @@ private: #endif USHORT wait_for_request(thread_db*, lrq*, SSHORT); - static THREAD_ENTRY_DECLARE blocking_action_thread(THREAD_ENTRY_PARAM); + static THREAD_ENTRY_DECLARE blocking_action_thread(THREAD_ENTRY_PARAM arg) + { + LockManager* const lockMgr = static_cast(arg); + lockMgr->blocking_action_thread(); + return 0; + } static void initialize(void* arg, SH_MEM shmem, bool init) { @@ -155,8 +159,7 @@ private: Firebird::Semaphore m_cleanupSemaphore; Firebird::Semaphore m_startupSemaphore; - const int m_dbId; - Firebird::PathName m_lockFile; + Firebird::string m_dbId; #ifdef WIN_NT struct mtx m_shmemMutex; diff --git a/src/utilities/guard/guard.cpp b/src/utilities/guard/guard.cpp index 288108a35a..1404d4aba2 100644 --- a/src/utilities/guard/guard.cpp +++ b/src/utilities/guard/guard.cpp @@ -67,6 +67,8 @@ const char* INTERBASE_USER = "interbase"; const char* FIREBIRD_USER = "firebird"; const char* INTERBASE_USER_SHORT= "interbas"; +const char* GUARD_FILE = "fb_guard"; + volatile sig_atomic_t shutting_down; diff --git a/src/utilities/guard/util.cpp b/src/utilities/guard/util.cpp index 7f851cdd2a..4f6c578114 100644 --- a/src/utilities/guard/util.cpp +++ b/src/utilities/guard/util.cpp @@ -256,11 +256,10 @@ int UTIL_ex_lock(const TEXT* file) * **************************************/ - TEXT expanded_filename[MAXPATHLEN], tmp[MAXPATHLEN], hostname[64]; + TEXT expanded_filename[MAXPATHLEN]; /* get the file name and prepend the complete path etc */ - gds__prefix_lock(tmp, file); - sprintf(expanded_filename, tmp, ISC_get_host(hostname, sizeof(hostname))); + gds__prefix(expanded_filename, file); /* file fd for the opened and locked file */ int fd_file = open(expanded_filename, O_RDWR | O_CREAT, 0666);