mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 22:43:03 +01:00
Refactored the global objects to be managed from a single place, this also removes code duplication
This commit is contained in:
parent
c9b57319e9
commit
c31517b4c7
@ -86,22 +86,24 @@ namespace Jrd
|
||||
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);
|
||||
|
||||
UCharBuffer buffer;
|
||||
os_utils::getUniqueFileId(pageSpace->file->fil_desc, buffer);
|
||||
|
||||
string file_id;
|
||||
char* s = file_id.getBuffer(2 * buffer.getCount());
|
||||
for (FB_SIZE_T i = 0; i < buffer.getCount(); i++)
|
||||
auto ptr = dbb_file_id.getBuffer(2 * buffer.getCount());
|
||||
for (const auto val : buffer)
|
||||
{
|
||||
sprintf(s, "%02x", (int) buffer[i]);
|
||||
s += 2;
|
||||
sprintf(ptr, "%02x", (int) val);
|
||||
ptr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return file_id;
|
||||
return dbb_file_id;
|
||||
}
|
||||
|
||||
Database::~Database()
|
||||
@ -131,11 +133,6 @@ namespace Jrd
|
||||
delete dbb_monitoring_data;
|
||||
delete dbb_backup_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)
|
||||
@ -277,6 +274,44 @@ namespace Jrd
|
||||
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()
|
||||
{
|
||||
JRD_shutdown_database(dbb, SHUT_DBB_RELEASE_POOLS);
|
||||
@ -321,34 +356,68 @@ namespace Jrd
|
||||
reset();
|
||||
}
|
||||
|
||||
void Database::ensureGuid(thread_db* tdbb)
|
||||
{
|
||||
if (readOnly())
|
||||
return;
|
||||
// Database::GlobalObjectHolder class implementation
|
||||
|
||||
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);
|
||||
PAG_set_db_guid(tdbb, dbb_guid);
|
||||
}
|
||||
MutexLockGuard guard(g_mutex, FB_FUNCTION);
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
return entry->holder;
|
||||
}
|
||||
|
||||
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);
|
||||
dbb_repl_sequence = sequence;
|
||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||
|
||||
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
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/classes/MetaName.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/Hash.h"
|
||||
#include "../common/classes/objects_array.h"
|
||||
#include "../common/classes/stack.h"
|
||||
#include "../common/classes/timestamp.h"
|
||||
@ -66,6 +67,7 @@
|
||||
#include "../common/config/config.h"
|
||||
#include "../common/classes/SyncObject.h"
|
||||
#include "../common/classes/Synchronize.h"
|
||||
#include "../jrd/replication/Manager.h"
|
||||
#include "fb_types.h"
|
||||
|
||||
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>
|
||||
{
|
||||
// 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:
|
||||
class ExistenceRefMutex : public Firebird::RefCounted
|
||||
{
|
||||
@ -329,16 +406,13 @@ public:
|
||||
return fb_utils::genUniqueId();
|
||||
}
|
||||
|
||||
MemoryPool* dbb_permanent;
|
||||
|
||||
Firebird::Guid dbb_guid; // database GUID
|
||||
|
||||
Firebird::SyncObject dbb_sync;
|
||||
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
|
||||
Database* dbb_next; // Next database block in system
|
||||
Attachment* dbb_attachments; // Active attachments
|
||||
@ -362,6 +436,8 @@ public:
|
||||
MonitoringData* dbb_monitoring_data; // monitoring data
|
||||
|
||||
private:
|
||||
Firebird::string dbb_file_id; // system-wide unique file ID
|
||||
Firebird::RefPtr<GlobalObjectHolder> dbb_gblobj_holder;
|
||||
Firebird::SyncObject dbb_modules_sync;
|
||||
DatabaseModules dbb_modules; // external function/filter modules
|
||||
|
||||
@ -446,7 +522,7 @@ public:
|
||||
bool onRawDevice() const;
|
||||
|
||||
// returns an unique ID string for a database file
|
||||
Firebird::string getUniqueFileId() const;
|
||||
const Firebird::string& getUniqueFileId();
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
// returns true if main lock is in exclusive state
|
||||
@ -483,6 +559,7 @@ private:
|
||||
Database(MemoryPool* p, Firebird::IPluginConfig* pConf, bool shared)
|
||||
: dbb_permanent(p),
|
||||
dbb_page_manager(this, *p),
|
||||
dbb_file_id(*p),
|
||||
dbb_modules(*p),
|
||||
dbb_extManager(*p),
|
||||
dbb_flags(shared ? DBB_shared : 0),
|
||||
@ -546,6 +623,23 @@ public:
|
||||
|
||||
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:
|
||||
//static int blockingAstSharedCounter(void*);
|
||||
static int blocking_ast_sweep(void* ast_object);
|
||||
|
@ -120,9 +120,9 @@ bool MonitoringTableScan::retrieveRecord(thread_db* tdbb, jrd_rel* relation,
|
||||
|
||||
// MonitoringData class
|
||||
|
||||
MonitoringData::MonitoringData(const Database* dbb)
|
||||
MonitoringData::MonitoringData(Database* dbb)
|
||||
: PermanentStorage(*dbb->dbb_permanent),
|
||||
m_dbId(getPool(), dbb->getUniqueFileId())
|
||||
m_dbId(dbb->getUniqueFileId())
|
||||
{
|
||||
initSharedFile();
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ public:
|
||||
|
||||
typedef Firebird::HalfStaticArray<AttNumber, 64> SessionList;
|
||||
|
||||
explicit MonitoringData(const Database*);
|
||||
explicit MonitoringData(Database*);
|
||||
~MonitoringData();
|
||||
|
||||
bool initialize(Firebird::SharedMemoryBase*, bool);
|
||||
@ -352,7 +352,7 @@ private:
|
||||
|
||||
void ensureSpace(ULONG);
|
||||
|
||||
const Firebird::string m_dbId;
|
||||
const Firebird::string& m_dbId;
|
||||
Firebird::AutoPtr<Firebird::SharedMemory<MonitoringHeader> > m_sharedMemory;
|
||||
Firebird::Mutex m_localMutex;
|
||||
};
|
||||
|
@ -1606,7 +1606,8 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
|
||||
case dfw_post_event:
|
||||
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);
|
||||
|
||||
delete work;
|
||||
@ -1624,7 +1625,7 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
|
||||
|
||||
if (pending_events)
|
||||
{
|
||||
dbb->dbb_event_mgr->deliverEvents();
|
||||
dbb->eventManager()->deliverEvents();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,71 +65,21 @@ using namespace Firebird;
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
GlobalPtr<EventManager::DbEventMgrMap> EventManager::g_emMap;
|
||||
GlobalPtr<Mutex> EventManager::g_mapMutex;
|
||||
|
||||
|
||||
void EventManager::init(Attachment* attachment)
|
||||
{
|
||||
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)
|
||||
attachment->att_event_session = eventMgr->create_session();
|
||||
attachment->att_event_session = dbb->eventManager()->create_session();
|
||||
}
|
||||
|
||||
|
||||
void EventManager::destroy(EventManager* eventMgr)
|
||||
{
|
||||
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)
|
||||
EventManager::EventManager(const string& id, const Config* conf)
|
||||
: PID(getpid()),
|
||||
m_process(NULL),
|
||||
m_processOffset(0),
|
||||
m_dbId(getPool(), id),
|
||||
m_dbId(id),
|
||||
m_config(conf),
|
||||
m_cleanupSync(getPool(), watcher_thread, THREAD_medium),
|
||||
m_exiting(false)
|
||||
@ -176,7 +126,7 @@ EventManager::~EventManager()
|
||||
|
||||
void EventManager::init_shared_file()
|
||||
{
|
||||
Firebird::PathName name;
|
||||
PathName name;
|
||||
name.printf(EVENT_FILE, m_dbId.c_str());
|
||||
|
||||
SharedMemory<evh>* tmp = FB_NEW_POOL(*getDefaultMemoryPool())
|
||||
@ -243,7 +193,7 @@ void EventManager::deleteSession(SLONG session_id)
|
||||
|
||||
SLONG EventManager::queEvents(SLONG session_id,
|
||||
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))
|
||||
{
|
||||
Firebird::Arg::Gds(isc_bad_epb_form).raise();
|
||||
Arg::Gds(isc_bad_epb_form).raise();
|
||||
}
|
||||
|
||||
acquire_shmem();
|
||||
@ -294,7 +244,7 @@ SLONG EventManager::queEvents(SLONG session_id,
|
||||
if (count > end - events)
|
||||
{
|
||||
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.
|
||||
@ -361,7 +311,7 @@ SLONG EventManager::queEvents(SLONG session_id,
|
||||
if (!post_process((prb*) SRQ_ABS_PTR(m_processOffset)))
|
||||
{
|
||||
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))
|
||||
{
|
||||
release_shmem();
|
||||
(Firebird::Arg::Gds(isc_random) << "post_process() failed").raise();
|
||||
(Arg::Gds(isc_random) << "post_process() failed").raise();
|
||||
}
|
||||
flag = true;
|
||||
break;
|
||||
@ -659,7 +609,7 @@ void EventManager::create_process()
|
||||
if (m_sharedMemory->eventInit(&process->prb_event) != FB_SUCCESS)
|
||||
{
|
||||
release_shmem();
|
||||
(Firebird::Arg::Gds(isc_random) << "eventInit() failed").raise();
|
||||
(Arg::Gds(isc_random) << "eventInit() failed").raise();
|
||||
}
|
||||
|
||||
m_processOffset = SRQ_REL_PTR(process);
|
||||
@ -895,10 +845,10 @@ void EventManager::deliver_request(evt_req* request)
|
||||
* Clean up request.
|
||||
*
|
||||
**************************************/
|
||||
Firebird::HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer;
|
||||
HalfStaticArray<UCHAR, BUFFER_MEDIUM> buffer;
|
||||
UCHAR* p = buffer.getBuffer(1);
|
||||
|
||||
Firebird::IEventCallback* ast = request->req_ast;
|
||||
IEventCallback* ast = request->req_ast;
|
||||
|
||||
*p++ = EPB_version1;
|
||||
|
||||
@ -919,7 +869,7 @@ void EventManager::deliver_request(evt_req* request)
|
||||
|
||||
if (length + extent > MAX_USHORT)
|
||||
{
|
||||
Firebird::BadAlloc::raise();
|
||||
BadAlloc::raise();
|
||||
}
|
||||
|
||||
buffer.grow(length + extent);
|
||||
@ -935,7 +885,7 @@ void EventManager::deliver_request(evt_req* request)
|
||||
*p++ = (UCHAR) (count >> 24);
|
||||
}
|
||||
}
|
||||
catch (const Firebird::BadAlloc&)
|
||||
catch (const BadAlloc&)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (const Firebird::Exception& ex)
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
iscLogException("Error in event watcher thread\n", ex);
|
||||
}
|
||||
@ -1398,13 +1348,13 @@ void EventManager::watcher_thread()
|
||||
m_startupSemaphore.release();
|
||||
}
|
||||
}
|
||||
catch (const Firebird::Exception& ex)
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -38,22 +38,16 @@ namespace Jrd {
|
||||
|
||||
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;
|
||||
|
||||
public:
|
||||
static void init(Attachment*);
|
||||
static void destroy(EventManager*);
|
||||
|
||||
EventManager(const Firebird::string& id, Firebird::RefPtr<const Config> conf);
|
||||
EventManager(const Firebird::string& id, const Config* conf);
|
||||
~EventManager();
|
||||
|
||||
static void init(Attachment*);
|
||||
|
||||
void deleteSession(SLONG);
|
||||
|
||||
SLONG queEvents(SLONG, USHORT, const UCHAR*, Firebird::IEventCallback*);
|
||||
@ -101,8 +95,8 @@ private:
|
||||
prb* m_process;
|
||||
SLONG m_processOffset;
|
||||
|
||||
Firebird::string m_dbId;
|
||||
Firebird::RefPtr<const Config> m_config;
|
||||
const Firebird::string& m_dbId;
|
||||
const Config* const m_config;
|
||||
Firebird::AutoPtr<Firebird::SharedMemory<evh> > m_sharedMemory;
|
||||
|
||||
Firebird::Semaphore m_startupSemaphore;
|
||||
|
@ -1762,8 +1762,8 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
||||
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
|
||||
pageSpace->file = PIO_open(tdbb, expanded_name, org_filename);
|
||||
|
||||
// Initialize the lock manager
|
||||
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId(), dbb->dbb_config);
|
||||
// Initialize the global object holder
|
||||
dbb->initGlobalObjectHolder(tdbb);
|
||||
|
||||
// Initialize locks
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
@ -1830,8 +1830,6 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
||||
err.raise();
|
||||
}
|
||||
|
||||
fb_assert(dbb->dbb_lock_mgr);
|
||||
|
||||
LCK_init(tdbb, LCK_OWNER_attachment);
|
||||
check_single_maintenance(tdbb);
|
||||
jAtt->getStable()->manualAsyncUnlock(attachment->att_flags);
|
||||
@ -2374,11 +2372,10 @@ void JEvents::freeEngineData(CheckStatusWrapper* user_status)
|
||||
try
|
||||
{
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
|
||||
if (dbb->dbb_event_mgr)
|
||||
{
|
||||
dbb->dbb_event_mgr->cancelEvents(id);
|
||||
}
|
||||
if (attachment->att_event_session)
|
||||
dbb->eventManager()->cancelEvents(id);
|
||||
|
||||
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);
|
||||
#endif
|
||||
|
||||
// Initialize the lock manager
|
||||
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId(), dbb->dbb_config);
|
||||
// Initialize the global object holder
|
||||
dbb->initGlobalObjectHolder(tdbb);
|
||||
|
||||
// Initialize locks
|
||||
LCK_init(tdbb, LCK_OWNER_database);
|
||||
@ -3007,6 +3004,9 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
|
||||
|
||||
dbb->dbb_page_manager.initTempPageSpace(tdbb);
|
||||
|
||||
GenerateGuid(&dbb->dbb_guid);
|
||||
PAG_set_db_guid(tdbb, dbb->dbb_guid);
|
||||
|
||||
if (options.dpb_set_page_buffers)
|
||||
PAG_set_page_buffers(tdbb, options.dpb_page_buffers);
|
||||
|
||||
@ -3747,11 +3747,13 @@ JEvents* JAttachment::queEvents(CheckStatusWrapper* user_status, IEventCallback*
|
||||
try
|
||||
{
|
||||
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);
|
||||
|
||||
ev = FB_NEW JEvents(id, getStable(), callback);
|
||||
ev->addRef();
|
||||
}
|
||||
@ -7464,8 +7466,8 @@ void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
||||
if (dbb->dbb_config->getServerMode() == MODE_SUPER)
|
||||
attachment->releaseGTTs(tdbb);
|
||||
|
||||
if (dbb->dbb_event_mgr && attachment->att_event_session)
|
||||
dbb->dbb_event_mgr->deleteSession(attachment->att_event_session);
|
||||
if (attachment->att_event_session)
|
||||
dbb->eventManager()->deleteSession(attachment->att_event_session);
|
||||
|
||||
// CMP_release() changes att_requests.
|
||||
while (attachment->att_requests.hasData())
|
||||
|
@ -156,7 +156,7 @@ inline bool CONVERT(thread_db* tdbb, CheckStatusWrapper* statusVector, Lock* loc
|
||||
|
||||
return lock->lck_compatible ?
|
||||
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);
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ inline void DEQUEUE(thread_db* tdbb, Lock* lock)
|
||||
if (lock->lck_compatible)
|
||||
internal_dequeue(tdbb, lock);
|
||||
else
|
||||
dbb->dbb_lock_mgr->dequeue(lock->lck_id);
|
||||
dbb->lockManager()->dequeue(lock->lck_id);
|
||||
}
|
||||
|
||||
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 ?
|
||||
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());
|
||||
|
||||
@ -422,7 +422,7 @@ bool LCK_cancel_wait(Jrd::Attachment* attachment)
|
||||
Database *dbb = attachment->att_database;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -496,7 +496,8 @@ void LCK_fini(thread_db* tdbb, enum lck_owner_t owner_type)
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
@ -748,7 +749,7 @@ LOCK_DATA_T LCK_query_data(thread_db* tdbb, enum lck_t lock_type, USHORT aggrega
|
||||
SET_TDBB(tdbb);
|
||||
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));
|
||||
|
||||
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->lck_owner_handle);
|
||||
fb_assert(LCK_CHECK_LOCK(lock));
|
||||
@ -835,7 +836,7 @@ void LCK_re_post(thread_db* tdbb, Lock* lock)
|
||||
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));
|
||||
}
|
||||
@ -858,7 +859,7 @@ void LCK_write_data(thread_db* tdbb, Lock* lock, LOCK_DATA_T data)
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
|
||||
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,
|
||||
level, lock->lck_ast, lock->lck_object, lock->lck_data, wait,
|
||||
lock->lck_owner_handle);
|
||||
@ -1316,7 +1317,7 @@ static void internal_dequeue(thread_db* tdbb, Lock* 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");
|
||||
}
|
||||
@ -1364,7 +1365,7 @@ static USHORT internal_downgrade(thread_db* tdbb, CheckStatusWrapper* statusVect
|
||||
|
||||
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))
|
||||
{
|
||||
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 (!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))
|
||||
{
|
||||
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
|
||||
// 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,
|
||||
level, external_ast, lock, lock->lck_data, wait, lock->lck_owner_handle);
|
||||
|
||||
|
@ -308,13 +308,12 @@ PathName ChangeLog::Segment::getFileName() const
|
||||
|
||||
ChangeLog::ChangeLog(MemoryPool& pool,
|
||||
const string& dbId,
|
||||
const PathName& database,
|
||||
const Guid& guid,
|
||||
const FB_UINT64 sequence,
|
||||
const Replication::Config* config)
|
||||
: PermanentStorage(pool),
|
||||
m_dbId(pool, dbId), m_database(pool, database),
|
||||
m_config(config), m_segments(pool), m_sequence(sequence), m_shutdown(false)
|
||||
m_dbId(dbId), m_config(config),
|
||||
m_segments(pool), m_sequence(sequence), m_shutdown(false)
|
||||
{
|
||||
memcpy(&m_guid, &guid, sizeof(Guid));
|
||||
|
||||
@ -570,7 +569,7 @@ FB_UINT64 ChangeLog::write(ULONG length, const UCHAR* data, bool sync)
|
||||
const string warningMsg =
|
||||
"Out of available space in changelog segments, waiting for archiving...";
|
||||
|
||||
logOriginMessage(m_database, warningMsg, WARNING_MSG);
|
||||
logOriginMessage(m_config->dbName, warningMsg, WARNING_MSG);
|
||||
}
|
||||
|
||||
{ // scope
|
||||
@ -674,7 +673,7 @@ bool ChangeLog::archiveExecute(Segment* segment)
|
||||
res, archiveCommand.c_str());
|
||||
}
|
||||
|
||||
logOriginMessage(m_database, errorMsg, ERROR_MSG);
|
||||
logOriginMessage(m_config->dbName, errorMsg, ERROR_MSG);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -692,7 +691,7 @@ bool ChangeLog::archiveExecute(Segment* segment)
|
||||
warningMsg.printf("Destination log file %s exists, it will be overwritten",
|
||||
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;
|
||||
}
|
||||
|
||||
logOriginMessage(m_database, errorMsg, ERROR_MSG);
|
||||
logOriginMessage(m_config->dbName, errorMsg, ERROR_MSG);
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
const string errorMsg = "Cannot copy log segment (reason unknown)";
|
||||
logOriginMessage(m_database, errorMsg, ERROR_MSG);
|
||||
logOriginMessage(m_config->dbName, errorMsg, ERROR_MSG);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +199,6 @@ namespace Replication
|
||||
public:
|
||||
ChangeLog(Firebird::MemoryPool& pool,
|
||||
const Firebird::string& dbId,
|
||||
const Firebird::PathName& database,
|
||||
const Firebird::Guid& guid,
|
||||
const FB_UINT64 sequence,
|
||||
const Config* config);
|
||||
@ -239,8 +238,7 @@ namespace Replication
|
||||
|
||||
void switchActiveSegment();
|
||||
|
||||
const Firebird::string m_dbId;
|
||||
const Firebird::PathName m_database;
|
||||
const Firebird::string& m_dbId;
|
||||
const Config* const m_config;
|
||||
Firebird::Array<Segment*> m_segments;
|
||||
Firebird::AutoPtr<Firebird::SharedMemory<State> > m_sharedMemory;
|
||||
|
@ -37,9 +37,6 @@ using namespace Replication;
|
||||
namespace Replication
|
||||
{
|
||||
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
|
||||
|
||||
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,
|
||||
const PathName& database,
|
||||
const Guid& guid,
|
||||
const Replication::Config* config)
|
||||
: m_dbId(getPool(), dbId),
|
||||
m_database(getPool(), database),
|
||||
m_config(config),
|
||||
: m_config(config),
|
||||
m_replicas(getPool()),
|
||||
m_buffers(getPool()),
|
||||
m_queue(getPool()),
|
||||
@ -195,45 +116,9 @@ Manager::Manager(const string& dbId,
|
||||
if (config->logDirectory.hasData())
|
||||
{
|
||||
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)
|
||||
|
||||
FbLocalStatus localStatus;
|
||||
@ -290,6 +175,32 @@ void Manager::init()
|
||||
|
||||
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()
|
||||
@ -330,7 +241,7 @@ void Manager::logError(const IStatus* status)
|
||||
message += temp;
|
||||
}
|
||||
|
||||
logOriginMessage(m_database, message, ERROR_MSG);
|
||||
logOriginMessage(m_config->dbName, message, ERROR_MSG);
|
||||
}
|
||||
|
||||
void Manager::flush(UCharBuffer* buffer, bool sync)
|
||||
|
@ -53,9 +53,8 @@ namespace Replication
|
||||
TablePermissionMap m_tables;
|
||||
};
|
||||
|
||||
class Manager : public Firebird::RefCounted, protected Firebird::GlobalStorage
|
||||
class Manager : public Firebird::GlobalStorage
|
||||
{
|
||||
public:
|
||||
struct SyncReplica
|
||||
{
|
||||
SyncReplica(Firebird::MemoryPool& pool, Firebird::IAttachment* att, Firebird::IReplicator* repl)
|
||||
@ -67,19 +66,17 @@ namespace Replication
|
||||
Firebird::IReplicator* replicator;
|
||||
};
|
||||
|
||||
typedef Firebird::GenericMap<Firebird::Pair<Firebird::Left<Firebird::string, Manager*> > > DbReplMgrMap;
|
||||
|
||||
public:
|
||||
Manager(const Firebird::string& dbId,
|
||||
const Firebird::Guid& guid,
|
||||
const Replication::Config* config);
|
||||
~Manager();
|
||||
|
||||
static Manager* create(const Firebird::string& dbId,
|
||||
const Firebird::PathName& database,
|
||||
const Firebird::Guid& guid);
|
||||
static void destroy(Manager* mgr);
|
||||
|
||||
static TableMatcher* createMatcher(MemoryPool& pool, const Firebird::string& dbId);
|
||||
|
||||
static void forceLogSwitch(const Firebird::string& dbId);
|
||||
TableMatcher* createTableMatcher(MemoryPool& pool)
|
||||
{
|
||||
return FB_NEW_POOL(pool)
|
||||
TableMatcher(pool, m_config->includeFilter, m_config->excludeFilter);
|
||||
}
|
||||
|
||||
Firebird::UCharBuffer* getBuffer();
|
||||
|
||||
@ -97,12 +94,6 @@ namespace Replication
|
||||
}
|
||||
|
||||
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 releaseBuffer(Firebird::UCharBuffer* buffer);
|
||||
|
||||
@ -119,9 +110,7 @@ namespace Replication
|
||||
Firebird::Semaphore m_cleanupSemaphore;
|
||||
Firebird::Semaphore m_workingSemaphore;
|
||||
|
||||
const Firebird::string m_dbId;
|
||||
const Firebird::PathName m_database;
|
||||
const Firebird::AutoPtr<const Replication::Config> m_config;
|
||||
const Replication::Config* const m_config;
|
||||
Firebird::Array<SyncReplica*> m_replicas;
|
||||
Firebird::Array<Firebird::UCharBuffer*> m_buffers;
|
||||
Firebird::Mutex m_buffersMutex;
|
||||
@ -136,9 +125,6 @@ namespace Replication
|
||||
|
||||
Firebird::AutoPtr<ChangeLog> m_changeLog;
|
||||
Firebird::RWLock m_lock;
|
||||
|
||||
static Firebird::GlobalPtr<DbReplMgrMap> g_rmMap;
|
||||
static Firebird::GlobalPtr<Firebird::Mutex> g_mapMutex;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -262,19 +262,19 @@ void REPL_attach(thread_db* tdbb, bool cleanupTransactions)
|
||||
|
||||
dbb->ensureGuid(tdbb);
|
||||
|
||||
const string dbId = dbb->getUniqueFileId();
|
||||
const PathName& dbName = dbb->dbb_filename;
|
||||
const Guid& dbGuid = dbb->dbb_guid;
|
||||
const MetaName& currentUser = attachment->att_user->getUserName();
|
||||
const auto replMgr = dbb->replManager();
|
||||
|
||||
MemoryPool& pool = *attachment->att_pool;
|
||||
if (!replMgr)
|
||||
return;
|
||||
|
||||
attachment->att_replicator = (IReplicatedSession*)
|
||||
Replicator::create(pool, dbId, dbName, dbGuid, currentUser,
|
||||
cleanupTransactions);
|
||||
const auto& dbGuid = dbb->dbb_guid;
|
||||
const auto& currentUser = attachment->att_user->getUserName();
|
||||
auto& pool = *attachment->att_pool;
|
||||
|
||||
if (attachment->att_replicator)
|
||||
attachment->att_repl_matcher = Manager::createMatcher(pool, dbId);
|
||||
attachment->att_replicator = (IReplicatedSession*) FB_NEW_POOL(pool)
|
||||
Replicator(pool, replMgr, dbGuid, currentUser, cleanupTransactions);
|
||||
|
||||
attachment->att_repl_matcher = replMgr->createTableMatcher(pool);
|
||||
}
|
||||
|
||||
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();
|
||||
fb_assert(dbb);
|
||||
|
||||
const string dbId = dbb->getUniqueFileId();
|
||||
dbb->ensureGuid(tdbb);
|
||||
|
||||
Manager::forceLogSwitch(dbId);
|
||||
const auto replMgr = dbb->replManager();
|
||||
|
||||
if (replMgr)
|
||||
replMgr->forceLogSwitch();
|
||||
}
|
||||
|
@ -32,45 +32,24 @@ using namespace Jrd;
|
||||
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,
|
||||
Manager* manager,
|
||||
const PathName& database,
|
||||
const Guid& guid,
|
||||
const MetaName& user,
|
||||
bool cleanupTransactions)
|
||||
: PermanentStorage(pool),
|
||||
m_manager(manager),
|
||||
m_guid(guid),
|
||||
m_config(manager->getConfig()),
|
||||
m_database(pool, database),
|
||||
m_user(user),
|
||||
m_transactions(pool),
|
||||
m_generators(pool),
|
||||
m_status(pool)
|
||||
{
|
||||
memcpy(&m_guid, &guid, sizeof(Guid));
|
||||
|
||||
if (cleanupTransactions)
|
||||
cleanupTransaction(0);
|
||||
}
|
||||
|
||||
Replicator::~Replicator()
|
||||
{
|
||||
Manager::destroy(m_manager);
|
||||
}
|
||||
|
||||
void Replicator::flush(BatchBlock& block, FlushReason reason, ULONG flags)
|
||||
{
|
||||
const auto traNumber = block.header.traNumber;
|
||||
@ -123,7 +102,7 @@ void Replicator::logError(const IStatus* status)
|
||||
message += temp;
|
||||
}
|
||||
|
||||
logOriginMessage(m_database, message, ERROR_MSG);
|
||||
logOriginMessage(m_config->dbName, message, ERROR_MSG);
|
||||
}
|
||||
|
||||
void Replicator::postError(const Exception& ex)
|
||||
|
@ -218,13 +218,10 @@ namespace Replication
|
||||
};
|
||||
|
||||
public:
|
||||
virtual ~Replicator();
|
||||
|
||||
static Replicator* create(Firebird::MemoryPool& pool,
|
||||
const Firebird::string& dbId,
|
||||
const Firebird::PathName& database,
|
||||
const Firebird::Guid& guid,
|
||||
const Firebird::MetaName& user,
|
||||
Replicator(Firebird::MemoryPool& pool,
|
||||
Manager* manager,
|
||||
const Firebird::Guid& dbGuid,
|
||||
const Firebird::MetaName& userName,
|
||||
bool cleanupTransactions);
|
||||
|
||||
// IDisposable methods
|
||||
@ -244,7 +241,6 @@ namespace Replication
|
||||
private:
|
||||
Manager* const m_manager;
|
||||
const Config* const m_config;
|
||||
const Firebird::PathName m_database;
|
||||
Firebird::Guid m_guid;
|
||||
const Firebird::MetaName m_user;
|
||||
Firebird::Array<Transaction*> m_transactions;
|
||||
@ -252,13 +248,6 @@ namespace Replication
|
||||
Firebird::Mutex m_mutex;
|
||||
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 flush(BatchBlock& txnData, FlushReason reason, ULONG flags = 0);
|
||||
void logError(const Firebird::IStatus* status);
|
||||
|
@ -163,52 +163,8 @@ static const bool compatibility[LCK_max][LCK_max] =
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
GlobalPtr<LockManager::DbLockMgrMap> LockManager::g_lmMap;
|
||||
GlobalPtr<Mutex> LockManager::g_mapMutex;
|
||||
|
||||
|
||||
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)
|
||||
LockManager::LockManager(const string& id, const Config* conf)
|
||||
: PID(getpid()),
|
||||
m_bugcheck(false),
|
||||
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_sharedMemory(NULL),
|
||||
m_blockage(false),
|
||||
m_dbId(getPool(), id),
|
||||
m_dbId(id),
|
||||
m_config(conf),
|
||||
m_acquireSpins(m_config->getLockAcquireSpins()),
|
||||
m_memorySize(m_config->getLockMemSize()),
|
||||
|
@ -293,8 +293,7 @@ namespace Jrd {
|
||||
|
||||
class thread_db;
|
||||
|
||||
class LockManager : private Firebird::RefCounted,
|
||||
public Firebird::GlobalStorage,
|
||||
class LockManager : public Firebird::GlobalStorage,
|
||||
public Firebird::IpcObject
|
||||
{
|
||||
class LockTableGuard
|
||||
@ -391,16 +390,11 @@ class LockManager : private Firebird::RefCounted,
|
||||
};
|
||||
#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;
|
||||
|
||||
public:
|
||||
static LockManager* create(const Firebird::string&, Firebird::RefPtr<const Config>);
|
||||
static void destroy(LockManager*);
|
||||
explicit LockManager(const Firebird::string&, const Config* conf);
|
||||
~LockManager();
|
||||
|
||||
bool initializeOwner(Firebird::CheckStatusWrapper*, LOCK_OWNER_T, UCHAR, SRQ_PTR*);
|
||||
void shutdownOwner(thread_db*, SRQ_PTR*);
|
||||
@ -422,9 +416,6 @@ public:
|
||||
void exceptionHandler(const Firebird::Exception& ex, ThreadFinishSync<LockManager*>::ThreadRoutine* routine);
|
||||
|
||||
private:
|
||||
explicit LockManager(const Firebird::string&, Firebird::RefPtr<const Config>);
|
||||
~LockManager();
|
||||
|
||||
void acquire_shmem(SRQ_PTR);
|
||||
UCHAR* alloc(USHORT, Firebird::CheckStatusWrapper*);
|
||||
lbl* alloc_lock(USHORT, Firebird::CheckStatusWrapper*);
|
||||
@ -498,8 +489,8 @@ public:
|
||||
private:
|
||||
bool m_blockage;
|
||||
|
||||
Firebird::string m_dbId;
|
||||
Firebird::RefPtr<const Config> m_config;
|
||||
const Firebird::string& m_dbId;
|
||||
const Config* const m_config;
|
||||
|
||||
// configurations parameters - cached values
|
||||
const ULONG m_acquireSpins;
|
||||
|
Loading…
Reference in New Issue
Block a user