8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:03:02 +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();
}
string Database::getUniqueFileId() const
const Firebird::string& Database::getUniqueFileId()
{
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++)
if (dbb_file_id.isEmpty())
{
sprintf(s, "%02x", (int) buffer[i]);
s += 2;
const PageSpace* const pageSpace = dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
UCharBuffer buffer;
os_utils::getUniqueFileId(pageSpace->file->fil_desc, buffer);
auto ptr = dbb_file_id.getBuffer(2 * buffer.getCount());
for (const auto val : buffer)
{
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)
{
MutexLockGuard guard(g_mutex, FB_FUNCTION);
Database::GlobalObjectHolder::DbId* entry = g_hashTable->lookup(id);
if (!entry)
{
GenerateGuid(&dbb_guid);
PAG_set_db_guid(tdbb, dbb_guid);
const auto holder = FB_NEW Database::GlobalObjectHolder(id, filename, config);
entry = FB_NEW Database::GlobalObjectHolder::DbId(id, holder);
g_hashTable->add(entry);
}
return entry->holder;
}
FB_UINT64 Database::getReplSequence(thread_db* tdbb)
Database::GlobalObjectHolder::~GlobalObjectHolder()
{
USHORT length = sizeof(FB_UINT64);
if (!PAG_get_clump(tdbb, Ods::HDR_repl_seq, &length, (UCHAR*) &dbb_repl_sequence))
return 0;
MutexLockGuard guard(g_mutex, FB_FUNCTION);
return dbb_repl_sequence;
if (!g_hashTable->remove(m_id))
fb_assert(false);
}
void Database::setReplSequence(thread_db* tdbb, FB_UINT64 sequence)
LockManager* Database::GlobalObjectHolder::getLockManager()
{
if (dbb_repl_sequence != sequence)
{
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

View File

@ -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);

View File

@ -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();
}

View File

@ -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;
};

View File

@ -1606,8 +1606,9 @@ 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(),
work->dfw_count);
dbb->eventManager()->postEvent(work->dfw_name.length(),
work->dfw_name.c_str(),
work->dfw_count);
delete work;
pending_events = true;
@ -1624,7 +1625,7 @@ void DFW_perform_post_commit_work(jrd_tra* transaction)
if (pending_events)
{
dbb->dbb_event_mgr->deliverEvents();
dbb->eventManager()->deliverEvents();
}
}

View File

@ -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);
}

View File

@ -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;

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->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);
const int id = dbb->eventManager()->queEvents(attachment->att_event_session,
length, events, callback);
int id = dbb->dbb_event_mgr->queEvents(getHandle()->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())

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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;
};
}

View File

@ -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();
}

View File

@ -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)

View File

@ -218,14 +218,11 @@ 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,
bool cleanupTransactions);
Replicator(Firebird::MemoryPool& pool,
Manager* manager,
const Firebird::Guid& dbGuid,
const Firebird::MetaName& userName,
bool cleanupTransactions);
// IDisposable methods
void dispose();
@ -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);

View File

@ -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()),

View File

@ -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;