8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 02:03:04 +01:00

Refactored the global objects to be managed from a single place, this also removes code duplication

This commit is contained in:
Dmitry Yemanov 2020-04-16 17:34:33 +03:00
parent c9b57319e9
commit c31517b4c7
18 changed files with 344 additions and 421 deletions

View File

@ -86,22 +86,24 @@ namespace Jrd
return dbb_tip_cache->generateStatementId(); return dbb_tip_cache->generateStatementId();
} }
string Database::getUniqueFileId() const const Firebird::string& Database::getUniqueFileId()
{
if (dbb_file_id.isEmpty())
{ {
const PageSpace* const pageSpace = dbb_page_manager.findPageSpace(DB_PAGE_SPACE); const PageSpace* const pageSpace = dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
UCharBuffer buffer; UCharBuffer buffer;
os_utils::getUniqueFileId(pageSpace->file->fil_desc, buffer); os_utils::getUniqueFileId(pageSpace->file->fil_desc, buffer);
string file_id; auto ptr = dbb_file_id.getBuffer(2 * buffer.getCount());
char* s = file_id.getBuffer(2 * buffer.getCount()); for (const auto val : buffer)
for (FB_SIZE_T i = 0; i < buffer.getCount(); i++)
{ {
sprintf(s, "%02x", (int) buffer[i]); sprintf(ptr, "%02x", (int) val);
s += 2; ptr += 2;
}
} }
return file_id; return dbb_file_id;
} }
Database::~Database() Database::~Database()
@ -131,11 +133,6 @@ namespace Jrd
delete dbb_monitoring_data; delete dbb_monitoring_data;
delete dbb_backup_manager; delete dbb_backup_manager;
delete dbb_crypto_manager; delete dbb_crypto_manager;
fb_assert(!locked());
// This line decrements the usage counter and may cause the destructor to be called.
// It should happen with the dbb_sync unlocked.
LockManager::destroy(dbb_lock_mgr);
EventManager::destroy(dbb_event_mgr);
} }
void Database::deletePool(MemoryPool* pool) void Database::deletePool(MemoryPool* pool)
@ -277,6 +274,44 @@ namespace Jrd
dbb_modules.add(module); dbb_modules.add(module);
} }
void Database::ensureGuid(thread_db* tdbb)
{
if (readOnly())
return;
if (!dbb_guid.alignment) // hackery way to check whether it was loaded
{
GenerateGuid(&dbb_guid);
PAG_set_db_guid(tdbb, dbb_guid);
}
}
FB_UINT64 Database::getReplSequence(thread_db* tdbb)
{
USHORT length = sizeof(FB_UINT64);
if (!PAG_get_clump(tdbb, Ods::HDR_repl_seq, &length, (UCHAR*) &dbb_repl_sequence))
return 0;
return dbb_repl_sequence;
}
void Database::setReplSequence(thread_db* tdbb, FB_UINT64 sequence)
{
if (dbb_repl_sequence != sequence)
{
PAG_set_repl_sequence(tdbb, sequence);
dbb_repl_sequence = sequence;
}
}
void Database::initGlobalObjectHolder(thread_db* tdbb)
{
dbb_gblobj_holder =
GlobalObjectHolder::init(getUniqueFileId(), dbb_filename, dbb_config);
}
// Database::Linger class implementation
void Database::Linger::handler() void Database::Linger::handler()
{ {
JRD_shutdown_database(dbb, SHUT_DBB_RELEASE_POOLS); JRD_shutdown_database(dbb, SHUT_DBB_RELEASE_POOLS);
@ -321,34 +356,68 @@ namespace Jrd
reset(); reset();
} }
void Database::ensureGuid(thread_db* tdbb) // Database::GlobalObjectHolder class implementation
{
if (readOnly())
return;
if (!dbb_guid.alignment) // hackery way to check whether it was loaded Database::GlobalObjectHolder* Database::GlobalObjectHolder::init(const string& id,
const PathName& filename,
RefPtr<const Config> config)
{ {
GenerateGuid(&dbb_guid); MutexLockGuard guard(g_mutex, FB_FUNCTION);
PAG_set_db_guid(tdbb, dbb_guid);
} Database::GlobalObjectHolder::DbId* entry = g_hashTable->lookup(id);
if (!entry)
{
const auto holder = FB_NEW Database::GlobalObjectHolder(id, filename, config);
entry = FB_NEW Database::GlobalObjectHolder::DbId(id, holder);
g_hashTable->add(entry);
} }
FB_UINT64 Database::getReplSequence(thread_db* tdbb) return entry->holder;
{
USHORT length = sizeof(FB_UINT64);
if (!PAG_get_clump(tdbb, Ods::HDR_repl_seq, &length, (UCHAR*) &dbb_repl_sequence))
return 0;
return dbb_repl_sequence;
} }
void Database::setReplSequence(thread_db* tdbb, FB_UINT64 sequence) Database::GlobalObjectHolder::~GlobalObjectHolder()
{ {
if (dbb_repl_sequence != sequence) MutexLockGuard guard(g_mutex, FB_FUNCTION);
if (!g_hashTable->remove(m_id))
fb_assert(false);
}
LockManager* Database::GlobalObjectHolder::getLockManager()
{ {
PAG_set_repl_sequence(tdbb, sequence); MutexLockGuard guard(m_mutex, FB_FUNCTION);
dbb_repl_sequence = sequence;
if (!m_lockMgr)
m_lockMgr = FB_NEW LockManager(m_id, m_config);
return m_lockMgr;
} }
EventManager* Database::GlobalObjectHolder::getEventManager()
{
MutexLockGuard guard(m_mutex, FB_FUNCTION);
if (!m_eventMgr)
m_eventMgr = FB_NEW EventManager(m_id, m_config);
return m_eventMgr;
} }
Replication::Manager* Database::GlobalObjectHolder::getReplManager(const Guid& guid)
{
if (!m_replConfig)
return nullptr;
MutexLockGuard guard(m_mutex, FB_FUNCTION);
if (!m_replMgr)
m_replMgr = FB_NEW Replication::Manager(m_id, guid, m_replConfig);
return m_replMgr;
}
GlobalPtr<Database::GlobalObjectHolder::DbIdHash>
Database::GlobalObjectHolder::g_hashTable;
GlobalPtr<Mutex> Database::GlobalObjectHolder::g_mutex;
} // namespace } // namespace

View File

@ -46,6 +46,7 @@
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
#include "../common/classes/MetaName.h" #include "../common/classes/MetaName.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../common/classes/Hash.h"
#include "../common/classes/objects_array.h" #include "../common/classes/objects_array.h"
#include "../common/classes/stack.h" #include "../common/classes/stack.h"
#include "../common/classes/timestamp.h" #include "../common/classes/timestamp.h"
@ -66,6 +67,7 @@
#include "../common/config/config.h" #include "../common/config/config.h"
#include "../common/classes/SyncObject.h" #include "../common/classes/SyncObject.h"
#include "../common/classes/Synchronize.h" #include "../common/classes/Synchronize.h"
#include "../jrd/replication/Manager.h"
#include "fb_types.h" #include "fb_types.h"
namespace Jrd namespace Jrd
@ -235,6 +237,81 @@ const ULONG DBB_shutdown_single = 0x100L; // Database is in single-user mainten
class Database : public pool_alloc<type_dbb> class Database : public pool_alloc<type_dbb>
{ {
// This class is a reference-counted container for all "global"
// (shared among different dbb's) objects -- e.g. the lock manager.
// The contained objects are created on demand (upon the first reference).
// The container is destroyed by the last dbb going away and
// it automatically destroys all the objects it holds.
class GlobalObjectHolder : public Firebird::RefCounted, public Firebird::GlobalStorage
{
struct DbId;
typedef Firebird::HashTable<DbId, Firebird::DEFAULT_HASH_SIZE,
Firebird::string, DbId, DbId > DbIdHash;
struct DbId : public DbIdHash::Entry, public Firebird::GlobalStorage
{
DbId(const Firebird::string& x, GlobalObjectHolder* h)
: id(getPool(), x), holder(h)
{}
DbId* get()
{
return this;
}
bool isEqual(const Firebird::string& val) const
{
return val == id;
}
static const Firebird::string& generate(const DbId& item)
{
return item.id;
}
static FB_SIZE_T hash(const Firebird::string& value, FB_SIZE_T hashSize)
{
return Firebird::InternalHash::hash(value.length(),
(const UCHAR*) value.c_str(),
hashSize);
}
const Firebird::string id;
GlobalObjectHolder* const holder;
};
static Firebird::GlobalPtr<DbIdHash> g_hashTable;
static Firebird::GlobalPtr<Firebird::Mutex> g_mutex;
public:
static GlobalObjectHolder* init(const Firebird::string& id,
const Firebird::PathName& filename,
Firebird::RefPtr<const Config> config);
~GlobalObjectHolder();
LockManager* getLockManager();
EventManager* getEventManager();
Replication::Manager* getReplManager(const Firebird::Guid& guid);
private:
const Firebird::string m_id;
const Firebird::RefPtr<const Config> m_config;
const Firebird::AutoPtr<const Replication::Config> m_replConfig;
Firebird::AutoPtr<LockManager> m_lockMgr;
Firebird::AutoPtr<EventManager> m_eventMgr;
Firebird::AutoPtr<Replication::Manager> m_replMgr;
Firebird::Mutex m_mutex;
explicit GlobalObjectHolder(const Firebird::string& id,
const Firebird::PathName& filename,
Firebird::RefPtr<const Config> config)
: m_id(getPool(), id), m_config(config),
m_replConfig(Replication::Config::get(filename))
{}
};
public: public:
class ExistenceRefMutex : public Firebird::RefCounted class ExistenceRefMutex : public Firebird::RefCounted
{ {
@ -329,16 +406,13 @@ public:
return fb_utils::genUniqueId(); return fb_utils::genUniqueId();
} }
MemoryPool* dbb_permanent;
Firebird::Guid dbb_guid; // database GUID Firebird::Guid dbb_guid; // database GUID
Firebird::SyncObject dbb_sync; Firebird::SyncObject dbb_sync;
Firebird::SyncObject dbb_sys_attach; // synchronize operations with dbb_sys_attachments Firebird::SyncObject dbb_sys_attach; // synchronize operations with dbb_sys_attachments
MemoryPool* dbb_permanent;
LockManager* dbb_lock_mgr;
EventManager* dbb_event_mgr;
Firebird::ICryptKeyCallback* dbb_callback; // Parent's crypt callback Firebird::ICryptKeyCallback* dbb_callback; // Parent's crypt callback
Database* dbb_next; // Next database block in system Database* dbb_next; // Next database block in system
Attachment* dbb_attachments; // Active attachments Attachment* dbb_attachments; // Active attachments
@ -362,6 +436,8 @@ public:
MonitoringData* dbb_monitoring_data; // monitoring data MonitoringData* dbb_monitoring_data; // monitoring data
private: private:
Firebird::string dbb_file_id; // system-wide unique file ID
Firebird::RefPtr<GlobalObjectHolder> dbb_gblobj_holder;
Firebird::SyncObject dbb_modules_sync; Firebird::SyncObject dbb_modules_sync;
DatabaseModules dbb_modules; // external function/filter modules DatabaseModules dbb_modules; // external function/filter modules
@ -446,7 +522,7 @@ public:
bool onRawDevice() const; bool onRawDevice() const;
// returns an unique ID string for a database file // returns an unique ID string for a database file
Firebird::string getUniqueFileId() const; const Firebird::string& getUniqueFileId();
#ifdef DEV_BUILD #ifdef DEV_BUILD
// returns true if main lock is in exclusive state // returns true if main lock is in exclusive state
@ -483,6 +559,7 @@ private:
Database(MemoryPool* p, Firebird::IPluginConfig* pConf, bool shared) Database(MemoryPool* p, Firebird::IPluginConfig* pConf, bool shared)
: dbb_permanent(p), : dbb_permanent(p),
dbb_page_manager(this, *p), dbb_page_manager(this, *p),
dbb_file_id(*p),
dbb_modules(*p), dbb_modules(*p),
dbb_extManager(*p), dbb_extManager(*p),
dbb_flags(shared ? DBB_shared : 0), dbb_flags(shared ? DBB_shared : 0),
@ -546,6 +623,23 @@ public:
const CoercionArray *getBindings() const; const CoercionArray *getBindings() const;
void initGlobalObjectHolder(thread_db* tdbb);
LockManager* lockManager()
{
return dbb_gblobj_holder->getLockManager();
}
EventManager* eventManager()
{
return dbb_gblobj_holder->getEventManager();
}
Replication::Manager* replManager()
{
return dbb_gblobj_holder->getReplManager(dbb_guid);
}
private: private:
//static int blockingAstSharedCounter(void*); //static int blockingAstSharedCounter(void*);
static int blocking_ast_sweep(void* ast_object); static int blocking_ast_sweep(void* ast_object);

View File

@ -120,9 +120,9 @@ bool MonitoringTableScan::retrieveRecord(thread_db* tdbb, jrd_rel* relation,
// MonitoringData class // MonitoringData class
MonitoringData::MonitoringData(const Database* dbb) MonitoringData::MonitoringData(Database* dbb)
: PermanentStorage(*dbb->dbb_permanent), : PermanentStorage(*dbb->dbb_permanent),
m_dbId(getPool(), dbb->getUniqueFileId()) m_dbId(dbb->getUniqueFileId())
{ {
initSharedFile(); initSharedFile();
} }

View File

@ -327,7 +327,7 @@ public:
typedef Firebird::HalfStaticArray<AttNumber, 64> SessionList; typedef Firebird::HalfStaticArray<AttNumber, 64> SessionList;
explicit MonitoringData(const Database*); explicit MonitoringData(Database*);
~MonitoringData(); ~MonitoringData();
bool initialize(Firebird::SharedMemoryBase*, bool); bool initialize(Firebird::SharedMemoryBase*, bool);
@ -352,7 +352,7 @@ private:
void ensureSpace(ULONG); void ensureSpace(ULONG);
const Firebird::string m_dbId; const Firebird::string& m_dbId;
Firebird::AutoPtr<Firebird::SharedMemory<MonitoringHeader> > m_sharedMemory; Firebird::AutoPtr<Firebird::SharedMemory<MonitoringHeader> > m_sharedMemory;
Firebird::Mutex m_localMutex; Firebird::Mutex m_localMutex;
}; };

View File

@ -1606,7 +1606,8 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
case dfw_post_event: case dfw_post_event:
EventManager::init(transaction->tra_attachment); EventManager::init(transaction->tra_attachment);
dbb->dbb_event_mgr->postEvent(work->dfw_name.length(), work->dfw_name.c_str(), dbb->eventManager()->postEvent(work->dfw_name.length(),
work->dfw_name.c_str(),
work->dfw_count); work->dfw_count);
delete work; delete work;
@ -1624,7 +1625,7 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
if (pending_events) if (pending_events)
{ {
dbb->dbb_event_mgr->deliverEvents(); dbb->eventManager()->deliverEvents();
} }
} }

View File

@ -65,71 +65,21 @@ using namespace Firebird;
namespace Jrd { namespace Jrd {
GlobalPtr<EventManager::DbEventMgrMap> EventManager::g_emMap;
GlobalPtr<Mutex> EventManager::g_mapMutex;
void EventManager::init(Attachment* attachment) void EventManager::init(Attachment* attachment)
{ {
Database* const dbb = attachment->att_database; Database* const dbb = attachment->att_database;
EventManager* eventMgr = dbb->dbb_event_mgr;
if (!eventMgr)
{
const string id = dbb->getUniqueFileId();
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
eventMgr = dbb->dbb_event_mgr;
if (!eventMgr)
{
if (!g_emMap->get(id, eventMgr))
{
eventMgr = FB_NEW EventManager(id, dbb->dbb_config);
if (g_emMap->put(id, eventMgr))
{
fb_assert(false);
}
}
fb_assert(eventMgr);
eventMgr->addRef();
dbb->dbb_event_mgr = eventMgr;
}
}
if (!attachment->att_event_session) if (!attachment->att_event_session)
attachment->att_event_session = eventMgr->create_session(); attachment->att_event_session = dbb->eventManager()->create_session();
} }
void EventManager::destroy(EventManager* eventMgr) EventManager::EventManager(const string& id, const Config* conf)
{
if (eventMgr)
{
const Firebird::string id = eventMgr->m_dbId;
Firebird::MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
if (!eventMgr->release())
{
if (!g_emMap->remove(id))
{
fb_assert(false);
}
}
}
}
EventManager::EventManager(const Firebird::string& id, Firebird::RefPtr<const Config> conf)
: PID(getpid()), : PID(getpid()),
m_process(NULL), m_process(NULL),
m_processOffset(0), m_processOffset(0),
m_dbId(getPool(), id), m_dbId(id),
m_config(conf), m_config(conf),
m_cleanupSync(getPool(), watcher_thread, THREAD_medium), m_cleanupSync(getPool(), watcher_thread, THREAD_medium),
m_exiting(false) m_exiting(false)
@ -176,7 +126,7 @@ EventManager::~EventManager()
void EventManager::init_shared_file() void EventManager::init_shared_file()
{ {
Firebird::PathName name; PathName name;
name.printf(EVENT_FILE, m_dbId.c_str()); name.printf(EVENT_FILE, m_dbId.c_str());
SharedMemory<evh>* tmp = FB_NEW_POOL(*getDefaultMemoryPool()) SharedMemory<evh>* tmp = FB_NEW_POOL(*getDefaultMemoryPool())
@ -243,7 +193,7 @@ void EventManager::deleteSession(SLONG session_id)
SLONG EventManager::queEvents(SLONG session_id, SLONG EventManager::queEvents(SLONG session_id,
USHORT events_length, const UCHAR* events, USHORT events_length, const UCHAR* events,
Firebird::IEventCallback* ast) IEventCallback* ast)
{ {
/************************************** /**************************************
* *
@ -259,7 +209,7 @@ SLONG EventManager::queEvents(SLONG session_id,
if (events_length && (!events || events[0] != EPB_version1)) if (events_length && (!events || events[0] != EPB_version1))
{ {
Firebird::Arg::Gds(isc_bad_epb_form).raise(); Arg::Gds(isc_bad_epb_form).raise();
} }
acquire_shmem(); acquire_shmem();
@ -294,7 +244,7 @@ SLONG EventManager::queEvents(SLONG session_id,
if (count > end - events) if (count > end - events)
{ {
release_shmem(); release_shmem();
Firebird::Arg::Gds(isc_bad_epb_form).raise(); Arg::Gds(isc_bad_epb_form).raise();
} }
// 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.
@ -361,7 +311,7 @@ SLONG EventManager::queEvents(SLONG session_id,
if (!post_process((prb*) SRQ_ABS_PTR(m_processOffset))) if (!post_process((prb*) SRQ_ABS_PTR(m_processOffset)))
{ {
release_shmem(); release_shmem();
(Firebird::Arg::Gds(isc_random) << "post_process() failed").raise(); (Arg::Gds(isc_random) << "post_process() failed").raise();
} }
} }
@ -482,7 +432,7 @@ void EventManager::deliverEvents()
if (!post_process(process)) if (!post_process(process))
{ {
release_shmem(); release_shmem();
(Firebird::Arg::Gds(isc_random) << "post_process() failed").raise(); (Arg::Gds(isc_random) << "post_process() failed").raise();
} }
flag = true; flag = true;
break; break;
@ -659,7 +609,7 @@ void EventManager::create_process()
if (m_sharedMemory->eventInit(&process->prb_event) != FB_SUCCESS) if (m_sharedMemory->eventInit(&process->prb_event) != FB_SUCCESS)
{ {
release_shmem(); release_shmem();
(Firebird::Arg::Gds(isc_random) << "eventInit() failed").raise(); (Arg::Gds(isc_random) << "eventInit() failed").raise();
} }
m_processOffset = SRQ_REL_PTR(process); m_processOffset = SRQ_REL_PTR(process);
@ -895,10 +845,10 @@ void EventManager::deliver_request(evt_req* request)
* Clean up request. * Clean up request.
* *
**************************************/ **************************************/
Firebird::HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer; HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer;
UCHAR* p = buffer.getBuffer(1); UCHAR* p = buffer.getBuffer(1);
Firebird::IEventCallback* ast = request->req_ast; IEventCallback* ast = request->req_ast;
*p++ = EPB_version1; *p++ = EPB_version1;
@ -919,7 +869,7 @@ void EventManager::deliver_request(evt_req* request)
if (length + extent > MAX_USHORT) if (length + extent > MAX_USHORT)
{ {
Firebird::BadAlloc::raise(); BadAlloc::raise();
} }
buffer.grow(length + extent); buffer.grow(length + extent);
@ -935,7 +885,7 @@ void EventManager::deliver_request(evt_req* request)
*p++ = (UCHAR) (count >> 24); *p++ = (UCHAR) (count >> 24);
} }
} }
catch (const Firebird::BadAlloc&) catch (const BadAlloc&)
{ {
gds__log("Out of memory. Failed to post all events."); gds__log("Out of memory. Failed to post all events.");
} }
@ -1386,7 +1336,7 @@ void EventManager::watcher_thread()
(void) m_sharedMemory->eventWait(&m_process->prb_event, value, 0); (void) m_sharedMemory->eventWait(&m_process->prb_event, value, 0);
} }
} }
catch (const Firebird::Exception& ex) catch (const Exception& ex)
{ {
iscLogException("Error in event watcher thread\n", ex); iscLogException("Error in event watcher thread\n", ex);
} }
@ -1398,13 +1348,13 @@ void EventManager::watcher_thread()
m_startupSemaphore.release(); m_startupSemaphore.release();
} }
} }
catch (const Firebird::Exception& ex) catch (const Exception& ex)
{ {
exceptionHandler(ex, NULL); exceptionHandler(ex, NULL);
} }
} }
void EventManager::exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<EventManager*>::ThreadRoutine*) void EventManager::exceptionHandler(const Exception& ex, ThreadFinishSync<EventManager*>::ThreadRoutine*)
{ {
iscLogException("Error closing event watcher thread\n", ex); iscLogException("Error closing event watcher thread\n", ex);
} }

View File

@ -38,22 +38,16 @@ namespace Jrd {
class Attachment; class Attachment;
class EventManager : private Firebird::RefCounted, public Firebird::GlobalStorage, public Firebird::IpcObject class EventManager : public Firebird::GlobalStorage, public Firebird::IpcObject
{ {
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::string, EventManager*> > > DbEventMgrMap;
static Firebird::GlobalPtr<DbEventMgrMap> g_emMap;
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
const int PID; const int PID;
public: public:
static void init(Attachment*); EventManager(const Firebird::string& id, const Config* conf);
static void destroy(EventManager*);
EventManager(const Firebird::string& id, Firebird::RefPtr<const Config> conf);
~EventManager(); ~EventManager();
static void init(Attachment*);
void deleteSession(SLONG); void deleteSession(SLONG);
SLONG queEvents(SLONG, USHORT, const UCHAR*, Firebird::IEventCallback*); SLONG queEvents(SLONG, USHORT, const UCHAR*, Firebird::IEventCallback*);
@ -101,8 +95,8 @@ private:
prb* m_process; prb* m_process;
SLONG m_processOffset; SLONG m_processOffset;
Firebird::string m_dbId; const Firebird::string& m_dbId;
Firebird::RefPtr<const Config> m_config; const Config* const m_config;
Firebird::AutoPtr<Firebird::SharedMemory<evh> > m_sharedMemory; Firebird::AutoPtr<Firebird::SharedMemory<evh> > m_sharedMemory;
Firebird::Semaphore m_startupSemaphore; Firebird::Semaphore m_startupSemaphore;

View File

@ -1762,8 +1762,8 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
pageSpace->file = PIO_open(tdbb, expanded_name, org_filename); pageSpace->file = PIO_open(tdbb, expanded_name, org_filename);
// Initialize the lock manager // Initialize the global object holder
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId(), dbb->dbb_config); dbb->initGlobalObjectHolder(tdbb);
// Initialize locks // Initialize locks
LCK_init(tdbb, LCK_OWNER_database); LCK_init(tdbb, LCK_OWNER_database);
@ -1830,8 +1830,6 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
err.raise(); err.raise();
} }
fb_assert(dbb->dbb_lock_mgr);
LCK_init(tdbb, LCK_OWNER_attachment); LCK_init(tdbb, LCK_OWNER_attachment);
check_single_maintenance(tdbb); check_single_maintenance(tdbb);
jAtt->getStable()->manualAsyncUnlock(attachment->att_flags); jAtt->getStable()->manualAsyncUnlock(attachment->att_flags);
@ -2374,11 +2372,10 @@ void JEvents::freeEngineData(CheckStatusWrapper* user_status)
try try
{ {
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
Attachment* const attachment = tdbb->getAttachment();
if (dbb->dbb_event_mgr) if (attachment->att_event_session)
{ dbb->eventManager()->cancelEvents(id);
dbb->dbb_event_mgr->cancelEvents(id);
}
id = -1; id = -1;
} }
@ -2961,8 +2958,8 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
os_utils::getUniqueFileId(dbb->dbb_filename.c_str(), dbb->dbb_id); os_utils::getUniqueFileId(dbb->dbb_filename.c_str(), dbb->dbb_id);
#endif #endif
// Initialize the lock manager // Initialize the global object holder
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId(), dbb->dbb_config); dbb->initGlobalObjectHolder(tdbb);
// Initialize locks // Initialize locks
LCK_init(tdbb, LCK_OWNER_database); LCK_init(tdbb, LCK_OWNER_database);
@ -3007,6 +3004,9 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
dbb->dbb_page_manager.initTempPageSpace(tdbb); dbb->dbb_page_manager.initTempPageSpace(tdbb);
GenerateGuid(&dbb->dbb_guid);
PAG_set_db_guid(tdbb, dbb->dbb_guid);
if (options.dpb_set_page_buffers) if (options.dpb_set_page_buffers)
PAG_set_page_buffers(tdbb, options.dpb_page_buffers); PAG_set_page_buffers(tdbb, options.dpb_page_buffers);
@ -3747,11 +3747,13 @@ JEvents* JAttachment::queEvents(CheckStatusWrapper* user_status, IEventCallback*
try try
{ {
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
Attachment* const attachment = getHandle();
EventManager::init(getHandle()); EventManager::init(attachment);
int id = dbb->dbb_event_mgr->queEvents(getHandle()->att_event_session, const int id = dbb->eventManager()->queEvents(attachment->att_event_session,
length, events, callback); length, events, callback);
ev = FB_NEW JEvents(id, getStable(), callback); ev = FB_NEW JEvents(id, getStable(), callback);
ev->addRef(); ev->addRef();
} }
@ -7464,8 +7466,8 @@ void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
if (dbb->dbb_config->getServerMode() == MODE_SUPER) if (dbb->dbb_config->getServerMode() == MODE_SUPER)
attachment->releaseGTTs(tdbb); attachment->releaseGTTs(tdbb);
if (dbb->dbb_event_mgr && attachment->att_event_session) if (attachment->att_event_session)
dbb->dbb_event_mgr->deleteSession(attachment->att_event_session); dbb->eventManager()->deleteSession(attachment->att_event_session);
// CMP_release() changes att_requests. // CMP_release() changes att_requests.
while (attachment->att_requests.hasData()) while (attachment->att_requests.hasData())

View File

@ -156,7 +156,7 @@ inline bool CONVERT(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* loc
return lock->lck_compatible ? return lock->lck_compatible ?
internal_enqueue(tdbb, statusVector, lock, level, wait, true) : internal_enqueue(tdbb, statusVector, lock, level, wait, true) :
dbb->dbb_lock_mgr->convert(tdbb, statusVector, lock->lck_id, level, wait, lock->lck_ast, dbb->lockManager()->convert(tdbb, statusVector, lock->lck_id, level, wait, lock->lck_ast,
lock->lck_object); lock->lck_object);
} }
@ -167,7 +167,7 @@ inline void DEQUEUE(thread_db* tdbb, Lock* lock)
if (lock->lck_compatible) if (lock->lck_compatible)
internal_dequeue(tdbb, lock); internal_dequeue(tdbb, lock);
else else
dbb->dbb_lock_mgr->dequeue(lock->lck_id); dbb->lockManager()->dequeue(lock->lck_id);
} }
inline USHORT DOWNGRADE(thread_db* tdbb, Lock* lock) inline USHORT DOWNGRADE(thread_db* tdbb, Lock* lock)
@ -178,7 +178,7 @@ inline USHORT DOWNGRADE(thread_db* tdbb, Lock* lock)
USHORT ret = lock->lck_compatible ? USHORT ret = lock->lck_compatible ?
internal_downgrade(tdbb, &statusVector, lock) : internal_downgrade(tdbb, &statusVector, lock) :
dbb->dbb_lock_mgr->downgrade(tdbb, &statusVector, lock->lck_id); dbb->lockManager()->downgrade(tdbb, &statusVector, lock->lck_id);
fb_assert(statusVector.isEmpty()); fb_assert(statusVector.isEmpty());
@ -422,7 +422,7 @@ bool LCK_cancel_wait(Jrd::Attachment* attachment)
Database *dbb = attachment->att_database; Database *dbb = attachment->att_database;
if (attachment->att_wait_lock) if (attachment->att_wait_lock)
return dbb->dbb_lock_mgr->cancelWait(attachment->att_wait_lock->lck_owner_handle); return dbb->lockManager()->cancelWait(attachment->att_wait_lock->lck_owner_handle);
return false; return false;
} }
@ -496,7 +496,8 @@ void LCK_fini(thread_db* tdbb, enum lck_owner_t owner_type)
break; break;
} }
dbb->dbb_lock_mgr->shutdownOwner(tdbb, owner_handle_ptr); if (*owner_handle_ptr)
dbb->lockManager()->shutdownOwner(tdbb, owner_handle_ptr);
} }
@ -627,7 +628,7 @@ void LCK_init(thread_db* tdbb, enum lck_owner_t owner_type)
FbLocalStatus statusVector; FbLocalStatus statusVector;
if (!dbb->dbb_lock_mgr->initializeOwner(&statusVector, owner_id, owner_type, owner_handle_ptr)) if (!dbb->lockManager()->initializeOwner(&statusVector, owner_id, owner_type, owner_handle_ptr))
{ {
if (statusVector[1] == isc_lockmanerr) if (statusVector[1] == isc_lockmanerr)
{ {
@ -748,7 +749,7 @@ LOCK_DATA_T LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggrega
SET_TDBB(tdbb); SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
return dbb->dbb_lock_mgr->queryData(lock_type, aggregate); return dbb->lockManager()->queryData(lock_type, aggregate);
} }
@ -770,7 +771,7 @@ LOCK_DATA_T LCK_read_data(thread_db* tdbb, Lock* lock)
fb_assert(LCK_CHECK_LOCK(lock)); fb_assert(LCK_CHECK_LOCK(lock));
const LOCK_DATA_T data = const LOCK_DATA_T data =
dbb->dbb_lock_mgr->readData2(lock->lck_type, dbb->lockManager()->readData2(lock->lck_type,
lock->getKeyPtr(), lock->lck_length, lock->getKeyPtr(), lock->lck_length,
lock->lck_owner_handle); lock->lck_owner_handle);
fb_assert(LCK_CHECK_LOCK(lock)); fb_assert(LCK_CHECK_LOCK(lock));
@ -835,7 +836,7 @@ void LCK_re_post(thread_db* tdbb, Lock* lock)
return; return;
} }
dbb->dbb_lock_mgr->repost(tdbb, lock->lck_ast, lock->lck_object, lock->lck_owner_handle); dbb->lockManager()->repost(tdbb, lock->lck_ast, lock->lck_object, lock->lck_owner_handle);
fb_assert(LCK_CHECK_LOCK(lock)); fb_assert(LCK_CHECK_LOCK(lock));
} }
@ -858,7 +859,7 @@ void LCK_write_data(thread_db* tdbb, Lock* lock, LOCK_DATA_T data)
fb_assert(LCK_CHECK_LOCK(lock)); fb_assert(LCK_CHECK_LOCK(lock));
dbb->dbb_lock_mgr->writeData(lock->lck_id, data); dbb->lockManager()->writeData(lock->lck_id, data);
lock->lck_data = data; lock->lck_data = data;
fb_assert(LCK_CHECK_LOCK(lock)); fb_assert(LCK_CHECK_LOCK(lock));
@ -974,7 +975,7 @@ static void enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* loc
fb_assert(LCK_CHECK_LOCK(lock)); fb_assert(LCK_CHECK_LOCK(lock));
lock->lck_id = dbb->dbb_lock_mgr->enqueue(tdbb, statusVector, lock->lck_id, lock->lck_id = dbb->lockManager()->enqueue(tdbb, statusVector, lock->lck_id,
lock->lck_type, lock->getKeyPtr(), lock->lck_length, lock->lck_type, lock->getKeyPtr(), lock->lck_length,
level, lock->lck_ast, lock->lck_object, lock->lck_data, wait, level, lock->lck_ast, lock->lck_object, lock->lck_data, wait,
lock->lck_owner_handle); lock->lck_owner_handle);
@ -1316,7 +1317,7 @@ static void internal_dequeue(thread_db* tdbb, Lock* lock)
Lock* match; Lock* match;
if (hash_remove_lock(lock, &match)) if (hash_remove_lock(lock, &match))
{ {
if (!dbb->dbb_lock_mgr->dequeue(lock->lck_id)) if (!dbb->lockManager()->dequeue(lock->lck_id))
{ {
bug_lck("LOCK_deq() failed in Lock:internal_dequeue"); bug_lck("LOCK_deq() failed in Lock:internal_dequeue");
} }
@ -1364,7 +1365,7 @@ static USHORT internal_downgrade(thread_db* tdbb, CheckStatusWrapper* statusVect
if (level < first->lck_physical) if (level < first->lck_physical)
{ {
if (dbb->dbb_lock_mgr->convert(tdbb, statusVector, first->lck_id, level, LCK_NO_WAIT, if (dbb->lockManager()->convert(tdbb, statusVector, first->lck_id, level, LCK_NO_WAIT,
external_ast, first)) external_ast, first))
{ {
for (Lock* lock = first; lock; lock = lock->lck_identical) for (Lock* lock = first; lock; lock = lock->lck_identical)
@ -1431,7 +1432,7 @@ static bool internal_enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector,
if (level > match->lck_physical) if (level > match->lck_physical)
{ {
if (!dbb->dbb_lock_mgr->convert(tdbb, statusVector, match->lck_id, level, wait, if (!dbb->lockManager()->convert(tdbb, statusVector, match->lck_id, level, wait,
external_ast, lock)) external_ast, lock))
{ {
return false; return false;
@ -1460,7 +1461,7 @@ static bool internal_enqueue(thread_db* tdbb, CheckStatusWrapper* statusVector,
// enqueue the lock, but swap out the ast and the ast argument // enqueue the lock, but swap out the ast and the ast argument
// with the local ast handler, passing it the lock block itself // with the local ast handler, passing it the lock block itself
lock->lck_id = dbb->dbb_lock_mgr->enqueue(tdbb, statusVector, lock->lck_id, lock->lck_id = dbb->lockManager()->enqueue(tdbb, statusVector, lock->lck_id,
lock->lck_type, lock->getKeyPtr(), lock->lck_length, lock->lck_type, lock->getKeyPtr(), lock->lck_length,
level, external_ast, lock, lock->lck_data, wait, lock->lck_owner_handle); level, external_ast, lock, lock->lck_data, wait, lock->lck_owner_handle);

View File

@ -308,13 +308,12 @@ PathName ChangeLog::Segment::getFileName() const
ChangeLog::ChangeLog(MemoryPool& pool, ChangeLog::ChangeLog(MemoryPool& pool,
const string& dbId, const string& dbId,
const PathName& database,
const Guid& guid, const Guid& guid,
const FB_UINT64 sequence, const FB_UINT64 sequence,
const Replication::Config* config) const Replication::Config* config)
: PermanentStorage(pool), : PermanentStorage(pool),
m_dbId(pool, dbId), m_database(pool, database), m_dbId(dbId), m_config(config),
m_config(config), m_segments(pool), m_sequence(sequence), m_shutdown(false) m_segments(pool), m_sequence(sequence), m_shutdown(false)
{ {
memcpy(&m_guid, &guid, sizeof(Guid)); memcpy(&m_guid, &guid, sizeof(Guid));
@ -570,7 +569,7 @@ FB_UINT64 ChangeLog::write(ULONG length, const UCHAR* data, bool sync)
const string warningMsg = const string warningMsg =
"Out of available space in changelog segments, waiting for archiving..."; "Out of available space in changelog segments, waiting for archiving...";
logOriginMessage(m_database, warningMsg, WARNING_MSG); logOriginMessage(m_config->dbName, warningMsg, WARNING_MSG);
} }
{ // scope { // scope
@ -674,7 +673,7 @@ bool ChangeLog::archiveExecute(Segment* segment)
res, archiveCommand.c_str()); res, archiveCommand.c_str());
} }
logOriginMessage(m_database, errorMsg, ERROR_MSG); logOriginMessage(m_config->dbName, errorMsg, ERROR_MSG);
return false; return false;
} }
} }
@ -692,7 +691,7 @@ bool ChangeLog::archiveExecute(Segment* segment)
warningMsg.printf("Destination log file %s exists, it will be overwritten", warningMsg.printf("Destination log file %s exists, it will be overwritten",
archpathname.c_str()); archpathname.c_str());
logOriginMessage(m_database, warningMsg, WARNING_MSG); logOriginMessage(m_config->dbName, warningMsg, WARNING_MSG);
} }
} }
@ -714,13 +713,13 @@ bool ChangeLog::archiveExecute(Segment* segment)
errorMsg += temp; errorMsg += temp;
} }
logOriginMessage(m_database, errorMsg, ERROR_MSG); logOriginMessage(m_config->dbName, errorMsg, ERROR_MSG);
return false; return false;
} }
catch (...) catch (...)
{ {
const string errorMsg = "Cannot copy log segment (reason unknown)"; const string errorMsg = "Cannot copy log segment (reason unknown)";
logOriginMessage(m_database, errorMsg, ERROR_MSG); logOriginMessage(m_config->dbName, errorMsg, ERROR_MSG);
return false; return false;
} }
} }

View File

@ -199,7 +199,6 @@ namespace Replication
public: public:
ChangeLog(Firebird::MemoryPool& pool, ChangeLog(Firebird::MemoryPool& pool,
const Firebird::string& dbId, const Firebird::string& dbId,
const Firebird::PathName& database,
const Firebird::Guid& guid, const Firebird::Guid& guid,
const FB_UINT64 sequence, const FB_UINT64 sequence,
const Config* config); const Config* config);
@ -239,8 +238,7 @@ namespace Replication
void switchActiveSegment(); void switchActiveSegment();
const Firebird::string m_dbId; const Firebird::string& m_dbId;
const Firebird::PathName m_database;
const Config* const m_config; const Config* const m_config;
Firebird::Array<Segment*> m_segments; Firebird::Array<Segment*> m_segments;
Firebird::AutoPtr<Firebird::SharedMemory<State> > m_sharedMemory; Firebird::AutoPtr<Firebird::SharedMemory<State> > m_sharedMemory;

View File

@ -37,9 +37,6 @@ using namespace Replication;
namespace Replication namespace Replication
{ {
const size_t MAX_BG_WRITER_LAG = 10 * 1024 * 1024; // 10 MB const size_t MAX_BG_WRITER_LAG = 10 * 1024 * 1024; // 10 MB
GlobalPtr<Manager::DbReplMgrMap> Manager::g_rmMap;
GlobalPtr<Mutex> Manager::g_mapMutex;
} }
@ -98,86 +95,10 @@ bool TableMatcher::matchTable(const MetaName& tableName)
// Replication manager // Replication manager
Manager* Manager::create(const string& dbId,
const PathName& database,
const Guid& guid)
{
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
Manager* mgr = NULL;
if (!g_rmMap->get(dbId, mgr))
{
const auto config = Replication::Config::get(database);
if (config)
{
mgr = FB_NEW Manager(dbId, database, guid, config);
if (g_rmMap->put(dbId, mgr))
fb_assert(false);
guard.release();
mgr->init();
}
}
if (mgr)
{
mgr->addRef();
return mgr;
}
return NULL;
}
void Manager::destroy(Manager* mgr)
{
if (mgr)
{
const string dbId = mgr->m_dbId;
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
if (!mgr->release())
{
if (!g_rmMap->remove(dbId))
fb_assert(false);
}
}
}
TableMatcher* Manager::createMatcher(MemoryPool& pool, const string& dbId)
{
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
Manager* mgr = NULL;
if (g_rmMap->get(dbId, mgr))
{
const auto config = mgr->getConfig();
return FB_NEW_POOL(pool) TableMatcher(pool, config->includeFilter, config->excludeFilter);
}
return NULL;
}
void Manager::forceLogSwitch(const string& dbId)
{
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
Manager* mgr = NULL;
if (g_rmMap->get(dbId, mgr))
mgr->forceLogSwitch();
}
Manager::Manager(const string& dbId, Manager::Manager(const string& dbId,
const PathName& database,
const Guid& guid, const Guid& guid,
const Replication::Config* config) const Replication::Config* config)
: m_dbId(getPool(), dbId), : m_config(config),
m_database(getPool(), database),
m_config(config),
m_replicas(getPool()), m_replicas(getPool()),
m_buffers(getPool()), m_buffers(getPool()),
m_queue(getPool()), m_queue(getPool()),
@ -195,45 +116,9 @@ Manager::Manager(const string& dbId,
if (config->logDirectory.hasData()) if (config->logDirectory.hasData())
{ {
m_changeLog = FB_NEW_POOL(getPool()) m_changeLog = FB_NEW_POOL(getPool())
ChangeLog(getPool(), dbId, database, guid, m_sequence, config); ChangeLog(getPool(), dbId, guid, m_sequence, config);
} }
Thread::start(writer_thread, this, THREAD_medium, 0);
m_startupSemaphore.enter();
}
Manager::~Manager()
{
m_shutdown = true;
m_workingSemaphore.release();
m_cleanupSemaphore.enter();
MutexLockGuard guard(m_queueMutex, FB_FUNCTION);
// Detach from synchronous replicas
FbLocalStatus localStatus;
for (auto& iter : m_replicas)
{
iter->replicator->close(&localStatus);
iter->attachment->detach(&localStatus);
}
while (m_buffers.hasData())
delete m_buffers.pop();
}
void Manager::init()
{
MutexLockGuard guard(m_queueMutex, FB_FUNCTION);
// Check whether everything is already initialized
if (m_config->syncReplicas.isEmpty() || m_replicas.hasData())
return;
// Attach to synchronous replicas (if any) // Attach to synchronous replicas (if any)
FbLocalStatus localStatus; FbLocalStatus localStatus;
@ -290,6 +175,32 @@ void Manager::init()
m_replicas.add(FB_NEW_POOL(getPool()) SyncReplica(getPool(), attachment, replicator)); m_replicas.add(FB_NEW_POOL(getPool()) SyncReplica(getPool(), attachment, replicator));
} }
Thread::start(writer_thread, this, THREAD_medium, 0);
m_startupSemaphore.enter();
}
Manager::~Manager()
{
m_shutdown = true;
m_workingSemaphore.release();
m_cleanupSemaphore.enter();
MutexLockGuard guard(m_queueMutex, FB_FUNCTION);
// Detach from synchronous replicas
FbLocalStatus localStatus;
for (auto& iter : m_replicas)
{
iter->replicator->close(&localStatus);
iter->attachment->detach(&localStatus);
}
while (m_buffers.hasData())
delete m_buffers.pop();
} }
UCharBuffer* Manager::getBuffer() UCharBuffer* Manager::getBuffer()
@ -330,7 +241,7 @@ void Manager::logError(const IStatus* status)
message += temp; message += temp;
} }
logOriginMessage(m_database, message, ERROR_MSG); logOriginMessage(m_config->dbName, message, ERROR_MSG);
} }
void Manager::flush(UCharBuffer* buffer, bool sync) void Manager::flush(UCharBuffer* buffer, bool sync)

View File

@ -53,9 +53,8 @@ namespace Replication
TablePermissionMap m_tables; TablePermissionMap m_tables;
}; };
class Manager : public Firebird::RefCounted, protected Firebird::GlobalStorage class Manager : public Firebird::GlobalStorage
{ {
public:
struct SyncReplica struct SyncReplica
{ {
SyncReplica(Firebird::MemoryPool& pool, Firebird::IAttachment* att, Firebird::IReplicator* repl) SyncReplica(Firebird::MemoryPool& pool, Firebird::IAttachment* att, Firebird::IReplicator* repl)
@ -67,19 +66,17 @@ namespace Replication
Firebird::IReplicator* replicator; Firebird::IReplicator* replicator;
}; };
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::string, Manager*> > > DbReplMgrMap;
public: public:
Manager(const Firebird::string& dbId,
const Firebird::Guid& guid,
const Replication::Config* config);
~Manager(); ~Manager();
static Manager* create(const Firebird::string& dbId, TableMatcher* createTableMatcher(MemoryPool& pool)
const Firebird::PathName& database, {
const Firebird::Guid& guid); return FB_NEW_POOL(pool)
static void destroy(Manager* mgr); TableMatcher(pool, m_config->includeFilter, m_config->excludeFilter);
}
static TableMatcher* createMatcher(MemoryPool& pool, const Firebird::string& dbId);
static void forceLogSwitch(const Firebird::string& dbId);
Firebird::UCharBuffer* getBuffer(); Firebird::UCharBuffer* getBuffer();
@ -97,12 +94,6 @@ namespace Replication
} }
private: private:
Manager(const Firebird::string& dbId,
const Firebird::PathName& database,
const Firebird::Guid& guid,
const Replication::Config* config);
void init();
void logError(const Firebird::IStatus* status); void logError(const Firebird::IStatus* status);
void releaseBuffer(Firebird::UCharBuffer* buffer); void releaseBuffer(Firebird::UCharBuffer* buffer);
@ -119,9 +110,7 @@ namespace Replication
Firebird::Semaphore m_cleanupSemaphore; Firebird::Semaphore m_cleanupSemaphore;
Firebird::Semaphore m_workingSemaphore; Firebird::Semaphore m_workingSemaphore;
const Firebird::string m_dbId; const Replication::Config* const m_config;
const Firebird::PathName m_database;
const Firebird::AutoPtr<const Replication::Config> m_config;
Firebird::Array<SyncReplica*> m_replicas; Firebird::Array<SyncReplica*> m_replicas;
Firebird::Array<Firebird::UCharBuffer*> m_buffers; Firebird::Array<Firebird::UCharBuffer*> m_buffers;
Firebird::Mutex m_buffersMutex; Firebird::Mutex m_buffersMutex;
@ -136,9 +125,6 @@ namespace Replication
Firebird::AutoPtr<ChangeLog> m_changeLog; Firebird::AutoPtr<ChangeLog> m_changeLog;
Firebird::RWLock m_lock; Firebird::RWLock m_lock;
static Firebird::GlobalPtr<DbReplMgrMap> g_rmMap;
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
}; };
} }

View File

@ -262,19 +262,19 @@ void REPL_attach(thread_db* tdbb, bool cleanupTransactions)
dbb->ensureGuid(tdbb); dbb->ensureGuid(tdbb);
const string dbId = dbb->getUniqueFileId(); const auto replMgr = dbb->replManager();
const PathName& dbName = dbb->dbb_filename;
const Guid& dbGuid = dbb->dbb_guid;
const MetaName& currentUser = attachment->att_user->getUserName();
MemoryPool& pool = *attachment->att_pool; if (!replMgr)
return;
attachment->att_replicator = (IReplicatedSession*) const auto& dbGuid = dbb->dbb_guid;
Replicator::create(pool, dbId, dbName, dbGuid, currentUser, const auto& currentUser = attachment->att_user->getUserName();
cleanupTransactions); auto& pool = *attachment->att_pool;
if (attachment->att_replicator) attachment->att_replicator = (IReplicatedSession*) FB_NEW_POOL(pool)
attachment->att_repl_matcher = Manager::createMatcher(pool, dbId); Replicator(pool, replMgr, dbGuid, currentUser, cleanupTransactions);
attachment->att_repl_matcher = replMgr->createTableMatcher(pool);
} }
void REPL_trans_prepare(thread_db* tdbb, jrd_tra* transaction) void REPL_trans_prepare(thread_db* tdbb, jrd_tra* transaction)
@ -642,7 +642,10 @@ void REPL_log_switch(thread_db* tdbb)
const auto dbb = tdbb->getDatabase(); const auto dbb = tdbb->getDatabase();
fb_assert(dbb); fb_assert(dbb);
const string dbId = dbb->getUniqueFileId(); dbb->ensureGuid(tdbb);
Manager::forceLogSwitch(dbId); const auto replMgr = dbb->replManager();
if (replMgr)
replMgr->forceLogSwitch();
} }

View File

@ -32,45 +32,24 @@ using namespace Jrd;
using namespace Replication; using namespace Replication;
Replicator* Replicator::create(MemoryPool& pool,
const string& dbId,
const PathName& database,
const Guid& guid,
const MetaName& user,
bool cleanupTransactions)
{
const auto manager = Manager::create(dbId, database, guid);
return manager ? FB_NEW_POOL(pool)
Replicator(pool, manager, database, guid, user, cleanupTransactions) : NULL;
}
Replicator::Replicator(MemoryPool& pool, Replicator::Replicator(MemoryPool& pool,
Manager* manager, Manager* manager,
const PathName& database,
const Guid& guid, const Guid& guid,
const MetaName& user, const MetaName& user,
bool cleanupTransactions) bool cleanupTransactions)
: PermanentStorage(pool), : PermanentStorage(pool),
m_manager(manager), m_manager(manager),
m_guid(guid),
m_config(manager->getConfig()), m_config(manager->getConfig()),
m_database(pool, database),
m_user(user), m_user(user),
m_transactions(pool), m_transactions(pool),
m_generators(pool), m_generators(pool),
m_status(pool) m_status(pool)
{ {
memcpy(&m_guid, &guid, sizeof(Guid));
if (cleanupTransactions) if (cleanupTransactions)
cleanupTransaction(0); cleanupTransaction(0);
} }
Replicator::~Replicator()
{
Manager::destroy(m_manager);
}
void Replicator::flush(BatchBlock& block, FlushReason reason, ULONG flags) void Replicator::flush(BatchBlock& block, FlushReason reason, ULONG flags)
{ {
const auto traNumber = block.header.traNumber; const auto traNumber = block.header.traNumber;
@ -123,7 +102,7 @@ void Replicator::logError(const IStatus* status)
message += temp; message += temp;
} }
logOriginMessage(m_database, message, ERROR_MSG); logOriginMessage(m_config->dbName, message, ERROR_MSG);
} }
void Replicator::postError(const Exception& ex) void Replicator::postError(const Exception& ex)

View File

@ -218,13 +218,10 @@ namespace Replication
}; };
public: public:
virtual ~Replicator(); Replicator(Firebird::MemoryPool& pool,
Manager* manager,
static Replicator* create(Firebird::MemoryPool& pool, const Firebird::Guid& dbGuid,
const Firebird::string& dbId, const Firebird::MetaName& userName,
const Firebird::PathName& database,
const Firebird::Guid& guid,
const Firebird::MetaName& user,
bool cleanupTransactions); bool cleanupTransactions);
// IDisposable methods // IDisposable methods
@ -244,7 +241,6 @@ namespace Replication
private: private:
Manager* const m_manager; Manager* const m_manager;
const Config* const m_config; const Config* const m_config;
const Firebird::PathName m_database;
Firebird::Guid m_guid; Firebird::Guid m_guid;
const Firebird::MetaName m_user; const Firebird::MetaName m_user;
Firebird::Array<Transaction*> m_transactions; Firebird::Array<Transaction*> m_transactions;
@ -252,13 +248,6 @@ namespace Replication
Firebird::Mutex m_mutex; Firebird::Mutex m_mutex;
Firebird::FbLocalStatus m_status; Firebird::FbLocalStatus m_status;
Replicator(Firebird::MemoryPool& pool,
Manager* manager,
const Firebird::PathName& dbName,
const Firebird::Guid& dbGuid,
const Firebird::MetaName& userName,
bool cleanupTransactions);
void initialize(); void initialize();
void flush(BatchBlock& txnData, FlushReason reason, ULONG flags = 0); void flush(BatchBlock& txnData, FlushReason reason, ULONG flags = 0);
void logError(const Firebird::IStatus* status); void logError(const Firebird::IStatus* status);

View File

@ -163,52 +163,8 @@ static const bool compatibility[LCK_max][LCK_max] =
namespace Jrd { namespace Jrd {
GlobalPtr<LockManager::DbLockMgrMap> LockManager::g_lmMap;
GlobalPtr<Mutex> LockManager::g_mapMutex;
LockManager::LockManager(const string& id, const Config* conf)
LockManager* LockManager::create(const string& id, RefPtr<const Config> conf)
{
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
LockManager* lockMgr = NULL;
if (!g_lmMap->get(id, lockMgr))
{
lockMgr = FB_NEW LockManager(id, conf);
if (g_lmMap->put(id, lockMgr))
{
fb_assert(false);
}
}
fb_assert(lockMgr);
lockMgr->addRef();
return lockMgr;
}
void LockManager::destroy(LockManager* lockMgr)
{
if (lockMgr)
{
const string id = lockMgr->m_dbId;
MutexLockGuard guard(g_mapMutex, FB_FUNCTION);
if (!lockMgr->release())
{
if (!g_lmMap->remove(id))
{
fb_assert(false);
}
}
}
}
LockManager::LockManager(const string& id, RefPtr<const Config> conf)
: PID(getpid()), : PID(getpid()),
m_bugcheck(false), m_bugcheck(false),
m_process(NULL), m_process(NULL),
@ -216,7 +172,7 @@ LockManager::LockManager(const string& id, RefPtr<const Config> conf)
m_cleanupSync(getPool(), blocking_action_thread, THREAD_high), m_cleanupSync(getPool(), blocking_action_thread, THREAD_high),
m_sharedMemory(NULL), m_sharedMemory(NULL),
m_blockage(false), m_blockage(false),
m_dbId(getPool(), id), m_dbId(id),
m_config(conf), m_config(conf),
m_acquireSpins(m_config->getLockAcquireSpins()), m_acquireSpins(m_config->getLockAcquireSpins()),
m_memorySize(m_config->getLockMemSize()), m_memorySize(m_config->getLockMemSize()),

View File

@ -293,8 +293,7 @@ namespace Jrd {
class thread_db; class thread_db;
class LockManager : private Firebird::RefCounted, class LockManager : public Firebird::GlobalStorage,
public Firebird::GlobalStorage,
public Firebird::IpcObject public Firebird::IpcObject
{ {
class LockTableGuard class LockTableGuard
@ -391,16 +390,11 @@ class LockManager : private Firebird::RefCounted,
}; };
#undef FB_LOCKED_FROM #undef FB_LOCKED_FROM
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::string, LockManager*> > > DbLockMgrMap;
static Firebird::GlobalPtr<DbLockMgrMap> g_lmMap;
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
const int PID; const int PID;
public: public:
static LockManager* create(const Firebird::string&, Firebird::RefPtr<const Config>); explicit LockManager(const Firebird::string&, const Config* conf);
static void destroy(LockManager*); ~LockManager();
bool initializeOwner(Firebird::CheckStatusWrapper*, LOCK_OWNER_T, UCHAR, SRQ_PTR*); bool initializeOwner(Firebird::CheckStatusWrapper*, LOCK_OWNER_T, UCHAR, SRQ_PTR*);
void shutdownOwner(thread_db*, SRQ_PTR*); void shutdownOwner(thread_db*, SRQ_PTR*);
@ -422,9 +416,6 @@ public:
void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* routine); void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* routine);
private: private:
explicit LockManager(const Firebird::string&, Firebird::RefPtr<const Config>);
~LockManager();
void acquire_shmem(SRQ_PTR); void acquire_shmem(SRQ_PTR);
UCHAR* alloc(USHORT, Firebird::CheckStatusWrapper*); UCHAR* alloc(USHORT, Firebird::CheckStatusWrapper*);
lbl* alloc_lock(USHORT, Firebird::CheckStatusWrapper*); lbl* alloc_lock(USHORT, Firebird::CheckStatusWrapper*);
@ -498,8 +489,8 @@ public:
private: private:
bool m_blockage; bool m_blockage;
Firebird::string m_dbId; const Firebird::string& m_dbId;
Firebird::RefPtr<const Config> m_config; const Config* const m_config;
// configurations parameters - cached values // configurations parameters - cached values
const ULONG m_acquireSpins; const ULONG m_acquireSpins;