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

Shared page cache implementation

This commit is contained in:
hvlad 2011-05-09 10:15:19 +00:00
parent 62a80a1aa6
commit fef1f49c94
73 changed files with 3108 additions and 2660 deletions

View File

@ -660,11 +660,11 @@
# The value is taken from a bit map in which each bit represents a CPU.
# Thus, to use only the first processor, the value is 1. To use both
# CPU 1 and CPU 2, the value is 3. To use CPU 2 and CPU 3, the value
# is 6. The default value is 1.
# is 6. The default value is 0 - no affinity will be set.
#
# Type: integer
#
#CpuAffinityMask = 1
#CpuAffinityMask = 0
# ----------------------------
@ -838,3 +838,16 @@
# 16 16777216 320 335544320 896 939524096
# 32 33554432 384 402653184 1024 1073741824
#
# Type: boolean
#SharedCache = true
# Type: boolean
#SharedDatabase = false
# SharedCache SharedDatabase Mode
# false false Classic with exlusive access // single attachment only ?
# false true Classic with shared access // traditional CS\SC
# true false Super with exlusive access // traditional SS
# true true Super with shared access //

View File

@ -173,6 +173,11 @@ public:
syncObject = obj;
}
SyncType getState() const
{
return state;
}
protected:
SyncType state;
SyncType request;
@ -199,27 +204,28 @@ public:
}
};
class SyncUnlockGuard : public Sync
class SyncUnlockGuard
{
public:
SyncUnlockGuard(SyncObject* obj, const char* fromWhere)
: Sync(obj, fromWhere)
SyncUnlockGuard(Sync& _sync) :
sync(_sync)
{
oldState = state;
oldState = sync.getState();
fb_assert(oldState != SYNC_NONE);
if (oldState != SYNC_NONE)
unlock();
sync.unlock();
}
~SyncUnlockGuard()
{
if (oldState != SYNC_NONE)
lock(oldState);
sync.lock(oldState);
}
private:
SyncType oldState;
Sync& sync;
};
} // namespace Firebird

View File

@ -378,6 +378,49 @@ private:
Mutex* lock;
};
class MutexUnlockGuard
{
public:
explicit MutexUnlockGuard(Mutex &aLock)
: lock(&aLock)
{
try {
lock->leave();
}
catch (const Exception&)
{
DtorException::devHalt();
}
}
~MutexUnlockGuard()
{
lock->enter();
}
private:
// Forbid copying
MutexUnlockGuard(const MutexUnlockGuard&);
MutexUnlockGuard& operator=(const MutexUnlockGuard&);
Mutex* lock;
};
class MutexCheckoutGuard
{
public:
MutexCheckoutGuard(Mutex& mtxCout, Mutex& mtxLock) :
unlock(mtxCout),
lock(mtxLock)
{
}
private:
MutexUnlockGuard unlock;
MutexLockGuard lock;
};
} //namespace Firebird
#endif // CLASSES_LOCKS_H

View File

@ -115,7 +115,7 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
{TYPE_INTEGER, "TempCacheLimit", (ConfigValue) -1}, // bytes
{TYPE_BOOLEAN, "RemoteFileOpenAbility", (ConfigValue) false},
{TYPE_INTEGER, "GuardianOption", (ConfigValue) 1},
{TYPE_INTEGER, "CpuAffinityMask", (ConfigValue) 1},
{TYPE_INTEGER, "CpuAffinityMask", (ConfigValue) 0},
{TYPE_INTEGER, "TcpRemoteBufferSize", (ConfigValue) 8192}, // bytes
{TYPE_BOOLEAN, "TcpNoNagle", (ConfigValue) true},
{TYPE_INTEGER, "DefaultDbCachePages", (ConfigValue) -1}, // pages
@ -171,7 +171,9 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
{TYPE_STRING, "AuthClient", (ConfigValue) "Legacy_Auth, Win_Sspi"},
{TYPE_STRING, "UserManager", (ConfigValue) "Legacy_Auth"},
{TYPE_STRING, "TracePlugin", (ConfigValue) "fbtrace"},
{TYPE_STRING, "SecurityDatabase", (ConfigValue) "$(root)/security3.fdb"} // security database name
{TYPE_STRING, "SecurityDatabase", (ConfigValue) "$(root)/security3.fdb"}, // security database name
{TYPE_BOOLEAN, "SharedCache", (ConfigValue) true},
{TYPE_BOOLEAN, "SharedDatabase", (ConfigValue) false}
};
/******************************************************************************
@ -668,20 +670,12 @@ int Config::getMaxUserTraceLogSize()
bool Config::getSharedCache()
{
#ifdef SUPERSERVER
return true;
#else
return false;
#endif
return (bool) getDefaultConfig()->values[KEY_SHARED_CACHE];
}
bool Config::getSharedDatabase()
{
#ifdef SUPERSERVER
return false;
#else
return true;
#endif
return (bool) getDefaultConfig()->values[KEY_SHARED_DATABASE];
}
bool Config::getMultiClientServer()

View File

@ -135,6 +135,8 @@ public:
KEY_PLUG_AUTH_MANAGE,
KEY_PLUG_TRACE,
KEY_SECURITY_DATABASE,
KEY_SHARED_CACHE,
KEY_SHARED_DATABASE,
MAX_CONFIG_KEY // keep it last
};

View File

@ -1334,13 +1334,9 @@ int ISC_event_init(event_t* event)
*
**************************************/
#ifdef SUPERSERVER
event->event_id = 0;
#else
static int idCounter = 0; // Should it be AtomicCounter? AP-2008
static AtomicCounter idCounter;
event->event_id = ++idCounter;
#endif
event->event_pid = process_id = getpid();
event->event_count = 0;
@ -2745,16 +2741,12 @@ static inline BOOL switchToThread()
BOOL res = FALSE;
if (fnSwitchToThread)
{
#if !defined SUPERSERVER
const HANDLE hThread = GetCurrentThread();
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
#endif
res = (*fnSwitchToThread)();
#if !defined SUPERSERVER
SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
#endif
}
return res;

View File

@ -322,7 +322,7 @@ void AggNode::aggInit(thread_db* /*tdbb*/, jrd_req* request) const
asbImpure->iasb_sort = NULL;
asbImpure->iasb_sort = FB_NEW(request->req_sorts.getPool()) Sort(
database, &request->req_sorts, asb->length,
request->req_attachment, &request->req_sorts, asb->length,
asb->keyItems.getCount(), 1, asb->keyItems.begin(),
RecordSource::rejectDuplicate, 0);
}

View File

@ -1381,10 +1381,9 @@ static dsql_dbb* init(thread_db* tdbb, Jrd::Attachment* attachment)
if (attachment->att_dsql_instance)
return attachment->att_dsql_instance;
MemoryPool& pool = *attachment->att_database->createPool();
MemoryPool& pool = *attachment->createPool();
dsql_dbb* const database = FB_NEW(pool) dsql_dbb(pool);
database->dbb_attachment = attachment;
database->dbb_database = attachment->att_database;
attachment->att_dsql_instance = database;
INI_init_dsql(tdbb, database);

View File

@ -37,7 +37,7 @@
#include "../common/common.h"
#include "../jrd/RuntimeStatistics.h"
#include "../jrd/val.h" // Get rid of duplicated FUN_T enum.
#include "../jrd/Database.h"
#include "../jrd/Attachment.h"
#include "../dsql/BlrWriter.h"
#include "../common/classes/array.h"
#include "../common/classes/GenericMap.h"
@ -146,7 +146,6 @@ public:
Firebird::string, class dsql_req*> > > dbb_cursors; // known cursors in database
MemoryPool& dbb_pool; // The current pool for the dbb
Database* dbb_database;
Attachment* dbb_attachment;
dsql_str* dbb_dfl_charset;
bool dbb_no_charset;
@ -170,12 +169,12 @@ public:
MemoryPool* createPool()
{
return dbb_database->createPool();
return dbb_attachment->createPool();
}
void deletePool(MemoryPool* pool)
{
dbb_database->deletePool(pool);
dbb_attachment->deletePool(pool);
}
};

View File

@ -25,6 +25,7 @@
#include "firebird.h"
#include "../jrd/Attachment.h"
#include "../jrd/Database.h"
#include "../jrd/Function.h"
#include "../jrd/nbak.h"
#include "../jrd/trace/TraceManager.h"
#include "../jrd/PreparedStatement.h"
@ -95,6 +96,29 @@ void Jrd::Attachment::destroy(Attachment* const attachment)
}
MemoryPool* Jrd::Attachment::createPool()
{
MemoryPool* const pool = MemoryPool::createPool(att_pool, att_memory_stats);
att_pools.add(pool);
return pool;
}
void Jrd::Attachment::deletePool(MemoryPool* pool)
{
if (pool)
{
size_t pos;
if (att_pools.find(pool, pos))
{
att_pools.remove(pos);
}
MemoryPool::deletePool(pool);
}
}
bool Jrd::Attachment::backupStateWriteLock(thread_db* tdbb, SSHORT wait)
{
if (att_backup_state_counter++)
@ -157,15 +181,29 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
att_ext_call_depth(0),
att_trace_manager(FB_NEW(*att_pool) TraceManager(this)),
att_interface(NULL),
att_public_interface(NULL)
att_public_interface(NULL),
att_functions(*pool),
att_internal(*pool),
att_dyn_req(*pool),
att_charsets(*pool),
att_charset_ids(*pool),
att_pools(*pool)
{
att_internal.grow(irq_MAX);
att_dyn_req.grow(drq_MAX);
}
Jrd::Attachment::~Attachment()
{
destroyIntlObjects();
delete att_trace_manager;
while (att_pools.getCount())
{
deletePool(att_pools.pop());
}
// For normal attachments that happens in release_attachment(),
// but for special ones like GC should be done also in dtor -
// they do not (and should not) call release_attachment().
@ -326,6 +364,12 @@ void Jrd::Attachment::detachLocksFromAttachment()
* block doesn't get dereferenced after it is released
*
**************************************/
if (!att_long_locks)
return;
Sync lckSync(&att_database->dbb_lck_sync, "Attachment::detachLocksFromAttachment");
lckSync.lock(SYNC_EXCLUSIVE);
Lock* long_lock = att_long_locks;
while (long_lock)
{
@ -337,3 +381,134 @@ void Jrd::Attachment::detachLocksFromAttachment()
}
att_long_locks = NULL;
}
// Find an inactive incarnation of a system request. If necessary, clone it.
jrd_req* Jrd::Attachment::findSystemRequest(thread_db* tdbb, USHORT id, USHORT which)
{
static const int MAX_RECURSION = 100;
// If the request hasn't been compiled or isn't active, there're nothing to do.
//Database::CheckoutLockGuard guard(this, dbb_cmp_clone_mutex);
fb_assert(which == IRQ_REQUESTS || which == DYN_REQUESTS);
JrdStatement* statement = (which == IRQ_REQUESTS ? att_internal[id] : att_dyn_req[id]);
if (!statement)
return NULL;
// Look for requests until we find one that is available.
for (int n = 0;; ++n)
{
if (n > MAX_RECURSION)
{
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_req_depth_exceeded) << Arg::Num(MAX_RECURSION));
// Msg363 "request depth exceeded. (Recursive definition?)"
}
jrd_req* clone = statement->getRequest(tdbb, n);
if (!(clone->req_flags & (req_active | req_reserved)))
{
clone->req_flags |= req_reserved;
return clone;
}
}
}
void Jrd::Attachment::shutdown(thread_db* tdbb)
{
// go through relations and indices and release
// all existence locks that might have been taken
vec<jrd_rel*>* rvector = att_relations;
if (rvector)
{
vec<jrd_rel*>::iterator ptr, end;
for (ptr = rvector->begin(), end = rvector->end(); ptr < end; ++ptr)
{
jrd_rel* relation = *ptr;
if (relation)
{
if (relation->rel_existence_lock)
{
LCK_release(tdbb, relation->rel_existence_lock);
relation->rel_flags |= REL_check_existence;
relation->rel_use_count = 0;
}
if (relation->rel_partners_lock)
{
LCK_release(tdbb, relation->rel_partners_lock);
relation->rel_flags |= REL_check_partners;
}
if (relation->rel_rescan_lock)
{
LCK_release(tdbb, relation->rel_rescan_lock);
relation->rel_flags &= ~REL_scanned;
}
for (IndexLock* index = relation->rel_index_locks; index; index = index->idl_next)
{
if (index->idl_lock)
{
index->idl_count = 0;
LCK_release(tdbb, index->idl_lock);
}
}
}
}
}
// release all procedure existence locks that might have been taken
vec<jrd_prc*>* pvector = att_procedures;
if (pvector)
{
vec<jrd_prc*>::iterator pptr, pend;
for (pptr = pvector->begin(), pend = pvector->end(); pptr < pend; ++pptr)
{
jrd_prc* procedure = *pptr;
if (procedure)
{
if (procedure->prc_existence_lock)
{
LCK_release(tdbb, procedure->prc_existence_lock);
procedure->prc_flags |= PRC_check_existence;
procedure->prc_use_count = 0;
}
}
}
}
// release all function existence locks that might have been taken
for (Function** iter = att_functions.begin(); iter < att_functions.end(); ++iter)
{
Function* const function = *iter;
if (function)
{
function->releaseLocks(tdbb);
}
}
// release collation existence locks
releaseIntlObjects();
// And release the system requests.
for (JrdStatement** itr = att_internal.begin(); itr != att_internal.end(); ++itr)
{
if (*itr)
(*itr)->release(tdbb);
}
for (JrdStatement** itr = att_dyn_req.begin(); itr != att_dyn_req.end(); ++itr)
{
if (*itr)
(*itr)->release(tdbb);
}
}

View File

@ -45,6 +45,8 @@ namespace EDS {
class Connection;
}
class CharSetContainer;
namespace Jrd
{
class thread_db;
@ -71,6 +73,12 @@ namespace Jrd
class PreparedStatement;
class TraceManager;
template <typename T> class vec;
class jrd_rel;
class jrd_prc;
class Trigger;
typedef Firebird::ObjectsArray<Trigger> trig_vec;
class Function;
class JrdStatement;
struct DSqlCacheItem
{
@ -120,6 +128,95 @@ struct bid;
//
class Attachment : public pool_alloc<type_att>
{
public:
class SyncGuard
{
public:
SyncGuard(Attachment* att, bool optional = false) :
m_mutex(NULL)
{
if (att && att->att_interface)
m_mutex = att->att_interface->getMutex();
fb_assert(optional || m_mutex);
if (m_mutex)
m_mutex->enter();
}
~SyncGuard()
{
if (m_mutex)
m_mutex->leave();
}
private:
// copying is prohibited
SyncGuard(const SyncGuard&);
SyncGuard& operator=(const SyncGuard&);
Firebird::Mutex* m_mutex;
};
class Checkout
{
public:
Checkout(Attachment* att, bool optional = false) :
m_mutex(NULL)
{
if (att && att->att_interface)
{
m_ref = att->att_interface;
m_mutex = att->att_interface->getMutex();
}
fb_assert(optional || m_mutex);
if (m_mutex)
m_mutex->leave();
}
~Checkout()
{
if (m_mutex)
m_mutex->enter();
}
private:
// copying is prohibited
Checkout(const Checkout&);
Checkout& operator=(const Checkout&);
Firebird::Mutex* m_mutex;
Firebird::RefPtr<JAttachment> m_ref;
};
class CheckoutLockGuard
{
public:
CheckoutLockGuard(Attachment* att, Firebird::Mutex& mutex, bool optional = false) :
m_mutex(mutex)
{
if (!m_mutex.tryEnter())
{
Checkout attCout(att, optional);
m_mutex.enter();
}
}
~CheckoutLockGuard()
{
m_mutex.leave();
}
private:
// copying is prohibited
CheckoutLockGuard(const CheckoutLockGuard&);
CheckoutLockGuard& operator=(const CheckoutLockGuard&);
Firebird::Mutex& m_mutex;
};
public:
static Attachment* create(Database* dbb);
static void destroy(Attachment* const attachment);
@ -170,6 +267,7 @@ public:
Firebird::SortedArray<void*> att_udf_pointers;
dsql_dbb* att_dsql_instance;
bool att_in_use; // attachment in use (can't be detached or dropped)
int att_use_count; // number of API calls running except of asyncronous ones
EDS::Connection* att_ext_connection; // external connection executed by this attachment
ULONG att_ext_call_depth; // external connection call depth, 0 for user attachment
@ -178,6 +276,35 @@ public:
JAttachment* att_interface;
Firebird::IAttachment* att_public_interface;
/// former Database members
vec<jrd_rel*>* att_relations; // relation vector
vec<jrd_prc*>* att_procedures; // scanned procedures
trig_vec* att_triggers[DB_TRIGGER_MAX];
trig_vec* att_ddl_triggers;
Firebird::Array<Function*> att_functions; // User defined functions
Firebird::Array<JrdStatement*> att_internal; // internal statements
Firebird::Array<JrdStatement*> att_dyn_req; // internal dyn statements
jrd_req* findSystemRequest(thread_db* tdbb, USHORT id, USHORT which);
Firebird::Array<CharSetContainer*> att_charsets; // intl character set descriptions
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
Firebird::MetaName, USHORT> > > att_charset_ids; // Character set ids
void releaseIntlObjects(); // defined in intl.cpp
void destroyIntlObjects(); // defined in intl.cpp
// from CMP_shutdown_database and CMP_fini
void shutdown(thread_db* tdbb);
Firebird::Array<MemoryPool*> att_pools; // pools
MemoryPool* createPool();
void deletePool(MemoryPool* pool);
/// former Database members
bool locksmith() const;
jrd_tra* getSysTransaction();
void setSysTransaction(jrd_tra* trans); // used only by TRA_init

View File

@ -77,12 +77,14 @@ namespace Jrd
Database::~Database()
{
destroyIntlObjects();
fb_assert(dbb_pools[0] == dbb_permanent);
for (size_t i = 1; i < dbb_pools.getCount(); ++i)
{
MemoryPool::deletePool(dbb_pools[i]);
Firebird::SyncLockGuard guard(&dbb_pools_sync, SYNC_EXCLUSIVE, "Database::~Database");
fb_assert(dbb_pools[0] == dbb_permanent);
for (size_t i = 1; i < dbb_pools.getCount(); ++i)
{
MemoryPool::deletePool(dbb_pools[i]);
}
}
delete dbb_monitoring_data;
@ -90,7 +92,8 @@ namespace Jrd
dbb_flags |= DBB_destroying;
Checkout dcoHolder(this);
// Checkout dcoHolder(this);
// 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);
@ -101,57 +104,19 @@ namespace Jrd
{
if (pool)
{
size_t pos;
if (dbb_pools.find(pool, pos))
{
dbb_pools.remove(pos);
Firebird::SyncLockGuard guard(&dbb_pools_sync, SYNC_EXCLUSIVE, "Database::deletePool");
size_t pos;
if (dbb_pools.find(pool, pos))
{
dbb_pools.remove(pos);
}
}
MemoryPool::deletePool(pool);
}
}
// Find an inactive incarnation of a system request. If necessary, clone it.
jrd_req* Database::findSystemRequest(thread_db* tdbb, USHORT id, USHORT which)
{
static const int MAX_RECURSION = 100;
// If the request hasn't been compiled or isn't active, there're nothing to do.
Database::CheckoutLockGuard guard(this, dbb_cmp_clone_mutex);
fb_assert(which == IRQ_REQUESTS || which == DYN_REQUESTS);
JrdStatement* statement = (which == IRQ_REQUESTS ? dbb_internal[id] : dbb_dyn_req[id]);
if (!statement)
return NULL;
// Look for requests until we find one that is available.
for (int n = 0;; ++n)
{
if (n > MAX_RECURSION)
{
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_req_depth_exceeded) << Arg::Num(MAX_RECURSION));
// Msg363 "request depth exceeded. (Recursive definition?)"
}
jrd_req* clone = statement->getRequest(tdbb, n);
if (!(clone->req_flags & (req_active | req_reserved)))
{
clone->req_flags |= req_reserved;
clone->setAttachment(tdbb->getAttachment());
fb_assert(clone->req_attachment);
return clone;
}
}
}
// Database::SharedCounter implementation
Database::SharedCounter::SharedCounter()
{
memset(m_counters, 0, sizeof(m_counters));
@ -180,6 +145,8 @@ namespace Jrd
ValueCache* const counter = &m_counters[space];
Database* const dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::SharedCounter::generate");
if (!counter->lock)
{
Lock* const lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock();
@ -225,11 +192,13 @@ namespace Jrd
try
{
Database::SyncGuard dsGuard(dbb, true);
if (dbb->dbb_flags & DBB_not_in_use)
return 0;
SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::blockingAstSharedCounter");
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
// tdbb->setAttachment(counter->lock->lck_attachment);
Jrd::ContextPoolHolder context(tdbb, dbb->dbb_permanent);

View File

@ -62,23 +62,19 @@
#include "../jrd/event_proto.h"
#include "../lock/lock_proto.h"
#include "../common/config/config.h"
class CharSetContainer;
#include "../common/classes/SyncObject.h"
#include "../common/classes/Synchronize.h"
namespace Jrd
{
class Trigger;
template <typename T> class vec;
class jrd_prc;
class jrd_rel;
class Shadow;
class BlobFilter;
class TxPageCache;
class BackupManager;
class ExternalFileDirectoryList;
class MonitoringData;
typedef Firebird::ObjectsArray<Trigger> trig_vec;
template <typename T> class vec;
class jrd_rel;
class Shadow;
class BlobFilter;
class TipCache;
class BackupManager;
class ExternalFileDirectoryList;
class MonitoringData;
// general purpose vector
@ -238,150 +234,7 @@ const ULONG DBB_monitor_off = 0x400L; // Database has the monitoring lock rele
class Database : public pool_alloc<type_dbb>
{
class Sync : public Firebird::RefCounted
{
public:
Sync() : threadId(0)
{}
void lock()
{
ThreadPriorityScheduler::enter();
++waiters;
syncMutex.enter();
--waiters;
threadId = getThreadId();
}
void unlock()
{
ThreadPriorityScheduler::exit();
threadId = 0;
syncMutex.leave();
}
bool hasContention() const
{
return (waiters.value() > 0);
}
private:
~Sync()
{
if (threadId)
{
syncMutex.leave();
}
}
// copying is prohibited
Sync(const Sync&);
Sync& operator=(const Sync&);
Firebird::Mutex syncMutex;
Firebird::AtomicCounter waiters;
FB_THREAD_ID threadId;
};
public:
class SyncGuard
{
public:
explicit SyncGuard(Database* dbb, bool ast = false)
: sync(*dbb->dbb_sync)
{
if (!dbb)
{
Firebird::status_exception::raise(Firebird::Arg::Gds(isc_bad_db_handle));
}
sync.addRef();
sync.lock();
if (ast && dbb->dbb_flags & DBB_destroying)
{
sync.unlock();
sync.release();
Firebird::LongJump::raise();
}
}
~SyncGuard()
{
try
{
sync.unlock();
}
catch (const Firebird::Exception&)
{
DtorException::devHalt();
}
sync.release();
}
private:
// copying is prohibited
SyncGuard(const SyncGuard&);
SyncGuard& operator=(const SyncGuard&);
Sync& sync;
};
class Checkout
{
public:
explicit Checkout(Database* dbb)
: sync(*dbb->dbb_sync)
{
sync.unlock();
}
~Checkout()
{
sync.lock();
}
private:
// copying is prohibited
Checkout(const Checkout&);
Checkout& operator=(const Checkout&);
Sync& sync;
};
class CheckoutLockGuard
{
public:
CheckoutLockGuard(Database* dbb, Firebird::Mutex& m)
: mutex(m)
{
if (!mutex.tryEnter())
{
Checkout dcoHolder(dbb);
mutex.enter();
}
}
~CheckoutLockGuard()
{
try {
mutex.leave();
}
catch (const Firebird::Exception&)
{
DtorException::devHalt();
}
}
private:
// copying is prohibited
CheckoutLockGuard(const CheckoutLockGuard&);
CheckoutLockGuard& operator=(const CheckoutLockGuard&);
Firebird::Mutex& mutex;
};
class SharedCounter
{
static const ULONG DEFAULT_CACHE_SIZE = 16;
@ -452,7 +305,9 @@ public:
return fb_utils::genUniqueId();
}
mutable Firebird::RefPtr<Sync> dbb_sync; // Database sync primitive
Firebird::SyncObject dbb_sync;
Firebird::SyncObject dbb_lck_sync; // syncronize operations with att_long_locks at different attachments
LockManager* dbb_lock_mgr;
EventManager* dbb_event_mgr;
@ -460,36 +315,32 @@ public:
Database* dbb_next; // Next database block in system
Attachment* dbb_attachments; // Active attachments
BufferControl* dbb_bcb; // Buffer control block
vec<jrd_rel*>* dbb_relations; // relation vector
vec<jrd_prc*>* dbb_procedures; // scanned procedures
int dbb_monitoring_id; // dbb monitoring identifier
Lock* dbb_lock; // granddaddy lock
Firebird::SyncObject dbb_sh_counter_sync;
Firebird::SyncObject dbb_shadow_sync;
Shadow* dbb_shadow; // shadow control block
Lock* dbb_shadow_lock; // lock for synchronizing addition of shadows
Lock* dbb_retaining_lock; // lock for preserving commit retaining snapshot
Lock* dbb_monitor_lock; // lock for monitoring purposes
PageManager dbb_page_manager;
vcl* dbb_t_pages; // pages number for transactions
vcl* dbb_gen_id_pages; // known pages for gen_id
BlobFilter* dbb_blob_filters; // known blob filters
trig_vec* dbb_triggers[DB_TRIGGER_MAX];
trig_vec* dbb_ddl_triggers;
MonitoringData* dbb_monitoring_data; // monitoring data
Firebird::SyncObject dbb_mon_sync; // syncronize operations with dbb_monitor_lock
MonitoringData* dbb_monitoring_data; // monitoring data
DatabaseModules dbb_modules; // external function/filter modules
ExtEngineManager dbb_extManager; // external engine manager
ExtEngineManager dbb_extManager; // external engine manager
Firebird::Mutex dbb_meta_mutex; // Mutex to protect metadata changes while dbb_sync is unlocked
Firebird::Mutex dbb_cmp_clone_mutex;
Firebird::Mutex dbb_exe_clone_mutex;
Firebird::Mutex dbb_flush_count_mutex;
Firebird::Mutex dbb_dyn_mutex;
Firebird::SyncObject dbb_flush_count_mutex;
//SLONG dbb_sort_size; // Size of sort space per sort, unused for now
ULONG dbb_ast_flags; // flags modified at AST level
ULONG dbb_flags;
Firebird::AtomicCounter dbb_ast_flags; // flags modified at AST level
Firebird::AtomicCounter dbb_flags;
USHORT dbb_ods_version; // major ODS version number
USHORT dbb_minor_version; // minor ODS version number
USHORT dbb_page_size; // page size
@ -508,30 +359,17 @@ public:
Firebird::string dbb_encrypt_key; // encryption key
MemoryPool* dbb_permanent;
MemoryPool* dbb_bufferpool;
Firebird::Array<MemoryPool*> dbb_pools; // pools
Firebird::Array<JrdStatement*> dbb_internal; // internal statements
Firebird::Array<JrdStatement*> dbb_dyn_req; // internal dyn statements
Firebird::SyncObject dbb_pools_sync;
Firebird::Array<MemoryPool*> dbb_pools; // pools
SLONG dbb_oldest_active; // Cached "oldest active" transaction
SLONG dbb_oldest_transaction; // Cached "oldest interesting" transaction
SLONG dbb_oldest_snapshot; // Cached "oldest snapshot" of all active transactions
SLONG dbb_next_transaction; // Next transaction id used by NETWARE
SLONG dbb_attachment_id; // Next attachment id for ReadOnly DB's
SLONG dbb_page_incarnation; // Cache page incarnation counter
ULONG dbb_page_buffers; // Page buffers from header page
Firebird::Semaphore dbb_writer_sem; // Wake up cache writer
Firebird::Semaphore dbb_writer_init;// Cache writer initialization
Firebird::Semaphore dbb_writer_fini;// Cache writer finalization
#ifdef SUPERSERVER_V2
// the code in cch.cpp is not tested for semaphore instead event !!!
Firebird::Semaphore dbb_reader_sem; // Wake up cache reader
Firebird::Semaphore dbb_reader_init;// Cache reader initialization
Firebird::Semaphore dbb_reader_fini;// Cache reader finalization
#endif
#ifdef GARBAGE_THREAD
Firebird::Semaphore dbb_gc_sem; // Event to wake up garbage collector
@ -554,14 +392,10 @@ public:
crypt_routine dbb_encrypt; // External encryption routine
crypt_routine dbb_decrypt; // External decryption routine
Firebird::Array<CharSetContainer*> dbb_charsets; // intl character set descriptions
TxPageCache* dbb_tip_cache; // cache of latest known state of all transactions in system
TipCache* dbb_tip_cache; // cache of latest known state of all transactions in system
TransactionsVector* dbb_pc_transactions; // active precommitted transactions
BackupManager* dbb_backup_manager; // physical backup manager
Firebird::TimeStamp dbb_creation_date; // creation date
Firebird::Array<Function*> dbb_functions; // User defined functions
Firebird::GenericMap<Firebird::Pair<Firebird::Left<
Firebird::MetaName, USHORT> > > dbb_charset_ids; // Character set ids
ExternalFileDirectoryList* dbb_external_file_directory_list;
Firebird::RefPtr<Config> dbb_config;
@ -576,6 +410,8 @@ public:
MemoryPool* createPool()
{
MemoryPool* const pool = MemoryPool::createPool(dbb_permanent, dbb_memory_stats);
Firebird::SyncLockGuard guard(&dbb_pools_sync, Firebird::SYNC_EXCLUSIVE, "Database::createPool");
dbb_pools.add(pool);
return pool;
}
@ -584,8 +420,7 @@ public:
private:
explicit Database(MemoryPool* p)
: dbb_sync(FB_NEW(*getDefaultMemoryPool()) Sync),
dbb_page_manager(this, *p),
: dbb_page_manager(this, *p),
dbb_modules(*p),
dbb_extManager(*p),
dbb_filename(*p),
@ -593,31 +428,18 @@ private:
dbb_encrypt_key(*p),
dbb_permanent(p),
dbb_pools(*p, 4),
dbb_internal(*p),
dbb_dyn_req(*p),
dbb_stats(*p),
dbb_lock_owner_id(getLockOwnerId()),
dbb_charsets(*p),
dbb_creation_date(Firebird::TimeStamp::getCurrentTimeStamp()),
dbb_functions(*p),
dbb_charset_ids(*p),
dbb_tip_cache(NULL),
dbb_external_file_directory_list(NULL)
{
dbb_pools.add(p);
dbb_internal.grow(irq_MAX);
dbb_dyn_req.grow(drq_MAX);
}
~Database();
public:
// temporary measure to avoid unstable state of lock file -
// this is anyway called in ~Database(), and in theory should be private
void releaseIntlObjects(); // defined in intl.cpp
void destroyIntlObjects(); // defined in intl.cpp
jrd_req* findSystemRequest(thread_db* tdbb, USHORT id, USHORT which);
SLONG generateAttachmentId(thread_db* tdbb)
{
return dbb_shared_counter.generate(tdbb, SharedCounter::ATTACHMENT_ID_SPACE, 1);

View File

@ -350,32 +350,33 @@ int DatabaseSnapshot::blockingAst(void* ast_object)
{
Lock* const lock = dbb->dbb_monitor_lock;
Database::SyncGuard dsGuard(dbb, true);
ThreadContextHolder tdbb;
tdbb->setDatabase(lock->lck_dbb);
tdbb->setAttachment(lock->lck_attachment);
ContextPoolHolder context(tdbb, dbb->dbb_permanent);
if (!(dbb->dbb_ast_flags & DBB_monitor_off))
{
// Write the data to the shared memory
if (!(dbb->dbb_flags & DBB_not_in_use))
{
try
{
dumpData(tdbb);
}
catch (const Exception& ex)
{
iscLogException("Cannot dump the monitoring data", ex);
}
}
SyncLockGuard monGuard(&dbb->dbb_mon_sync, SYNC_EXCLUSIVE, "DatabaseSnapshot::blockingAst");
// Release the lock and mark dbb as requesting a new one
LCK_release(tdbb, lock);
dbb->dbb_ast_flags |= DBB_monitor_off;
if (!(dbb->dbb_ast_flags & DBB_monitor_off))
{
// Write the data to the shared memory
if (!(dbb->dbb_flags & DBB_not_in_use))
{
ContextPoolHolder context(tdbb, dbb->dbb_permanent);
try
{
dumpData(tdbb);
}
catch (const Exception& ex)
{
iscLogException("Cannot dump the monitoring data", ex);
}
}
// Release the lock and mark dbb as requesting a new one
LCK_release(tdbb, lock);
dbb->dbb_ast_flags |= DBB_monitor_off;
}
}
}
catch (const Exception&)
@ -406,17 +407,21 @@ DatabaseSnapshot::DatabaseSnapshot(thread_db* tdbb, MemoryPool& pool)
RecordBuffer* const ctx_var_buffer = allocBuffer(tdbb, pool, rel_mon_ctx_vars);
RecordBuffer* const mem_usage_buffer = allocBuffer(tdbb, pool, rel_mon_mem_usage);
// Release our own lock
LCK_release(tdbb, dbb->dbb_monitor_lock);
dbb->dbb_ast_flags &= ~DBB_monitor_off;
{
SyncLockGuard monGuard(&dbb->dbb_mon_sync, SYNC_EXCLUSIVE, "DatabaseSnapshot::DatabaseSnapshot");
{ // scope for the RAII object
// Release our own lock
LCK_release(tdbb, dbb->dbb_monitor_lock);
dbb->dbb_ast_flags &= ~DBB_monitor_off;
// Ensure we'll be dealing with a valid backup state inside the call below
BackupManager::StateReadGuard holder(tdbb);
{ // scope for the RAII object
// Dump our own data
dumpData(tdbb);
// Ensure we'll be dealing with a valid backup state inside the call below
BackupManager::StateReadGuard holder(tdbb);
// Dump our own data
dumpData(tdbb);
}
}
// Signal other processes to dump their data
@ -770,9 +775,15 @@ void DatabaseSnapshot::dumpData(thread_db* tdbb)
putDatabase(dbb, writer, fb_utils::genUniqueId());
// Attachment information
Attachment* old_attachment = tdbb->getAttachment();
Attachment::Checkout attCout(old_attachment, true);
for (Attachment* attachment = dbb->dbb_attachments; attachment; attachment = attachment->att_next)
{
Attachment::SyncGuard attGuard(attachment);
tdbb->setAttachment(attachment);
if (!putAttachment(tdbb, attachment, writer, fb_utils::genUniqueId()))
continue;
@ -823,6 +834,8 @@ void DatabaseSnapshot::dumpData(thread_db* tdbb)
}
}
}
tdbb->setAttachment(old_attachment);
}

View File

@ -134,7 +134,7 @@ private:
Utf8 charSetName[MAX_SQL_IDENTIFIER_SIZE];
{ // scope
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(attachment);
obj->getCharSet(RaiseError(), attInfo->context, charSetName, MAX_SQL_IDENTIFIER_LEN);
charSetName[MAX_SQL_IDENTIFIER_LEN] = '\0';
@ -299,7 +299,7 @@ ExtEngineManager::Function::Function(thread_db* tdbb, ExtEngineManager* aExtMana
ExtEngineManager::Function::~Function()
{
Database::Checkout dcoHolder(database);
// Database::Checkout dcoHolder(database);
function->dispose(LogError());
}
@ -358,7 +358,7 @@ void ExtEngineManager::Function::execute(thread_db* tdbb, const NestValueArray&
}
{ // scope
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
function->execute(RaiseError(), attInfo->context, &params, &result);
}
}
@ -397,7 +397,7 @@ ExtEngineManager::Procedure::Procedure(thread_db* tdbb, ExtEngineManager* aExtMa
ExtEngineManager::Procedure::~Procedure()
{
Database::Checkout dcoHolder(database);
//Database::Checkout dcoHolder(database);
procedure->dispose(LogError());
}
@ -415,7 +415,7 @@ ExtEngineManager::ResultSet* ExtEngineManager::Procedure::open(thread_db* tdbb,
ExtEngineManager::ResultSet::ResultSet(thread_db* tdbb, ValuesImpl* inputParams,
ValuesImpl* outputParams, const ExtEngineManager::Procedure* aProcedure)
: procedure(aProcedure),
database(tdbb->getDatabase()),
attachment(tdbb->getAttachment()),
firstFetch(true)
{
attInfo = procedure->extManager->getEngineAttachment(tdbb, procedure->engine);
@ -423,11 +423,10 @@ ExtEngineManager::ResultSet::ResultSet(thread_db* tdbb, ValuesImpl* inputParams,
(procedure->prc->getName().package.isEmpty() ?
CallerName(obj_procedure, procedure->prc->getName().identifier) :
CallerName(obj_package_header, procedure->prc->getName().package)));
Attachment* attachment = tdbb->getAttachment();
charSet = attachment->att_charset;
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(attachment);
resultSet = procedure->procedure->open(RaiseError(), attInfo->context, inputParams,
outputParams);
@ -438,7 +437,8 @@ ExtEngineManager::ResultSet::~ResultSet()
{
if (resultSet)
{
Database::Checkout dcoHolder(database);
fb_assert(attachment == JRD_get_thread_data()->getAttachment());
Attachment::Checkout attCout(attachment);
resultSet->dispose(LogError());
}
}
@ -457,7 +457,8 @@ bool ExtEngineManager::ResultSet::fetch(thread_db* tdbb)
CallerName(obj_procedure, procedure->prc->getName().identifier) :
CallerName(obj_package_header, procedure->prc->getName().package)));
Database::Checkout dcoHolder(tdbb->getDatabase());
fb_assert(attachment == tdbb->getAttachment());
Attachment::Checkout attCout(attachment);
return resultSet->fetch(RaiseError());
}
@ -479,6 +480,7 @@ ExtEngineManager::Trigger::Trigger(thread_db* tdbb, ExtEngineManager* aExtManage
ExtEngineManager::Trigger::~Trigger()
{
// hvlad: shouldn't we call trigger->dispose() here ?
}
@ -504,7 +506,7 @@ void ExtEngineManager::Trigger::execute(thread_db* tdbb, ExternalTrigger::Action
valueNewCount = setValues(tdbb, pool, newValues, descs, newRpb);
{ // scope
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
trigger->execute(RaiseError(), attInfo->context, action, oldValues, newValues);
@ -605,7 +607,7 @@ void ExtEngineManager::initialize()
}
void ExtEngineManager::closeAttachment(thread_db* tdbb, Attachment* /*attachment*/)
void ExtEngineManager::closeAttachment(thread_db* tdbb, Attachment* attachment)
{
Array<ExternalEngine*> enginesCopy;
@ -617,7 +619,7 @@ void ExtEngineManager::closeAttachment(thread_db* tdbb, Attachment* /*attachment
enginesCopy.add(accessor.current()->second);
}
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(attachment, true);
for (Array<ExternalEngine*>::iterator i = enginesCopy.begin(); i != enginesCopy.end(); ++i)
{
@ -652,7 +654,7 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons
ExternalFunction* externalFunction;
{ // scope
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
externalFunction = attInfo->engine->makeFunction(RaiseError(),
attInfo->context, udf->getName().package.nullStr(), udf->getName().identifier.c_str(),
@ -672,7 +674,7 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons
}
catch (...)
{
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
externalFunction->dispose(LogError());
throw;
}
@ -694,7 +696,7 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co
ExternalProcedure* externalProcedure;
{ // scope
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
externalProcedure = attInfo->engine->makeProcedure(RaiseError(),
attInfo->context, prc->getName().package.nullStr(), prc->getName().identifier.c_str(),
@ -714,7 +716,7 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co
}
catch (...)
{
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
externalProcedure->dispose(LogError());
throw;
}
@ -738,7 +740,7 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
ExternalTrigger* externalTrigger;
{ // scope
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context,
trg->name.c_str(), entryPointTrimmed.nullStr(), body.nullStr(),
@ -757,7 +759,7 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
}
catch (...)
{
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
externalTrigger->dispose(LogError());
throw;
}
@ -786,7 +788,7 @@ ExternalEngine* ExtEngineManager::getEngine(thread_db* tdbb, const MetaName& nam
try
{
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
engine = engineControl.plugin();
if (engine)
@ -799,7 +801,7 @@ ExternalEngine* ExtEngineManager::getEngine(thread_db* tdbb, const MetaName& nam
Arg::Num(version) << name);
}
Database::SyncGuard dsGuard(tdbb->getDatabase());
Attachment::SyncGuard attGuard(tdbb->getAttachment());
key = EngineAttachment(engine, tdbb->getAttachment());
attInfo = FB_NEW(getPool()) EngineAttachmentInfo();
@ -874,7 +876,7 @@ ExtEngineManager::EngineAttachmentInfo* ExtEngineManager::getEngineAttachment(
enginesAttachments.put(key, attInfo);
ContextManager<ExternalFunction> ctxManager(tdbb, attInfo, attInfo->adminCharSet);
Database::Checkout dcoHolder(tdbb->getDatabase());
Attachment::Checkout attCout(tdbb->getAttachment());
engine->openAttachment(LogError(), attInfo->context);
}

View File

@ -179,7 +179,7 @@ public:
private:
const Procedure* procedure;
Database* database;
Attachment* attachment;
bool firstFetch;
EngineAttachmentInfo* attInfo;
Firebird::ExternalResultSet* resultSet;

View File

@ -65,7 +65,7 @@ Function* Function::lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool
Database* const dbb = tdbb->getDatabase();
Function* check_function = NULL;
Function* function = (id < dbb->dbb_functions.getCount()) ? dbb->dbb_functions[id] : NULL;
Function* function = (id < attachment->att_functions.getCount()) ? attachment->att_functions[id] : NULL;
if (function && function->getId() == id &&
!(function->fun_flags & FUN_being_scanned) &&
@ -117,7 +117,7 @@ Function* Function::lookup(thread_db* tdbb, const QualifiedName& name, bool nosc
// See if we already know the function by name
for (Function** iter = dbb->dbb_functions.begin(); iter < dbb->dbb_functions.end(); ++iter)
for (Function** iter = attachment->att_functions.begin(); iter < attachment->att_functions.end(); ++iter)
{
Function* const function = *iter;
@ -174,14 +174,12 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
jrd_tra* sysTransaction = attachment->getSysTransaction();
Database* const dbb = tdbb->getDatabase();
if (id >= dbb->dbb_functions.getCount())
if (id >= attachment->att_functions.getCount())
{
dbb->dbb_functions.grow(id + 1);
attachment->att_functions.grow(id + 1);
}
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
Function* function = dbb->dbb_functions[id];
Function* function = attachment->att_functions[id];
if (function && !(function->fun_flags & FUN_obsolete))
{
@ -196,7 +194,7 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
if (!function)
{
function = FB_NEW(*dbb->dbb_permanent) Function(*dbb->dbb_permanent);
function = FB_NEW(*attachment->att_pool) Function(*attachment->att_pool);
}
try
@ -205,11 +203,11 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
function->fun_flags &= ~FUN_obsolete;
function->setId(id);
dbb->dbb_functions[id] = function;
attachment->att_functions[id] = function;
if (!function->fun_existence_lock)
{
Lock* const lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock;
Lock* const lock = FB_NEW_RPT(*attachment->att_pool, 0) Lock;
function->fun_existence_lock = lock;
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
@ -328,7 +326,7 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
{
function->fun_defaults++;
MemoryPool* const csb_pool = dbb->createPool();
MemoryPool* const csb_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, csb_pool);
try
@ -338,7 +336,7 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
}
catch (const Exception&)
{
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
throw; // an explicit error message would be better
}
}
@ -403,7 +401,7 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
}
else if (!X.RDB$FUNCTION_BLR.NULL)
{
MemoryPool* const csb_pool = dbb->createPool();
MemoryPool* const csb_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, csb_pool);
try
@ -427,7 +425,7 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
}
catch (const Exception&)
{
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
throw;
}
@ -513,8 +511,9 @@ int Function::blockingAst(void* ast_object)
try
{
Database* const dbb = function->fun_existence_lock->lck_dbb;
Jrd::Attachment* att = function->fun_existence_lock->lck_attachment;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment::SyncGuard guard(att);
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
@ -624,8 +623,8 @@ void Function::release(thread_db* tdbb)
{
fun_use_count--;
Database* const dbb = tdbb->getDatabase();
if (fun_use_count == 0 && dbb->dbb_functions[getId()] != this)
Jrd::Attachment* attachment = tdbb->getAttachment();
if (fun_use_count == 0 && attachment->att_functions[getId()] != this)
{
if (getStatement())
{

View File

@ -35,6 +35,7 @@
#include "jrd.h"
#include "lck_proto.h"
#include "err_proto.h"
#include "Attachment.h"
#include "../common/classes/rwlock.h"
#include "../common/classes/condition.h"
@ -43,6 +44,7 @@
IMPLEMENT_TRACE_ROUTINE(cos_trace, "COS")
#endif
namespace Jrd {
int GlobalRWLock::blocking_ast_cached_lock(void* ast_object)
@ -56,8 +58,6 @@ int GlobalRWLock::blocking_ast_cached_lock(void* ast_object)
return 0;
Database* dbb = globalRWLock->cachedLock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
@ -101,7 +101,7 @@ void GlobalRWLock::shutdownLock()
{
thread_db* tdbb = JRD_get_thread_data();
Database::CheckoutLockGuard counterGuard(tdbb->getDatabase(), counterMutex);
Attachment::CheckoutLockGuard counterGuard(tdbb->getAttachment(), counterMutex, true);
COS_TRACE(("(%p)->shutdownLock readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)",
this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical));
@ -119,11 +119,10 @@ bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Attachment* att = tdbb->getAttachment();
{ // scope 1
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
COS_TRACE(("(%p)->lockWrite stage 1 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)",
this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical));
@ -131,7 +130,7 @@ bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait)
while (readers > 0 )
{
Database::Checkout checkoutDbb(dbb);
Attachment::Checkout attCout(att, true);
noReaders.wait(counterMutex);
}
@ -140,7 +139,7 @@ bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait)
while (currentWriter || pendingLock)
{
Database::Checkout checkoutDbb(dbb);
Attachment::Checkout attCout(att, true);
writerFinished.wait(counterMutex);
}
@ -164,7 +163,7 @@ bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait)
if (!LCK_lock(tdbb, cachedLock, LCK_write, wait))
{
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
--pendingLock;
if (--pendingWriters)
{
@ -175,8 +174,7 @@ bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait)
}
{ // scope 2
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
--pendingLock;
--pendingWriters;
@ -196,9 +194,8 @@ void GlobalRWLock::unlockWrite(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment* att = tdbb->getAttachment();
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
COS_TRACE(("(%p)->unlockWrite readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)",
this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical));
@ -225,12 +222,12 @@ bool GlobalRWLock::lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Attachment* att = tdbb->getAttachment();
bool needFetch;
{ // scope 1
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
COS_TRACE(("(%p)->lockRead stage 1 readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)",
this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical));
@ -246,7 +243,7 @@ bool GlobalRWLock::lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump)
while (pendingWriters > 0 || currentWriter)
{
Database::Checkout checkoutDbb(dbb);
Attachment::Checkout attCout(att, true);
writerFinished.wait(counterMutex);
}
@ -256,9 +253,9 @@ bool GlobalRWLock::lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump)
if (!pendingLock)
break;
counterMutex.leave();
Database::Checkout checkoutDbb(dbb);
counterMutex.enter();
Firebird::MutexUnlockGuard cout(counterMutex);
Attachment::Checkout attCout(att, true);
THD_yield();
}
needFetch = cachedLock->lck_physical < LCK_read;
@ -275,14 +272,13 @@ bool GlobalRWLock::lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump)
if (!LCK_lock(tdbb, cachedLock, LCK_read, wait))
{
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
--pendingLock;
return false;
}
{ // scope 2
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
--pendingLock;
++readers;
@ -297,9 +293,8 @@ void GlobalRWLock::unlockRead(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Database::CheckoutLockGuard counterGuard(dbb, counterMutex);
Attachment* att = tdbb->getAttachment();
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
COS_TRACE(("(%p)->unlockRead readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)",
this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical));
@ -321,7 +316,8 @@ void GlobalRWLock::unlockRead(thread_db* tdbb)
bool GlobalRWLock::tryReleaseLock(thread_db* tdbb)
{
Database::CheckoutLockGuard counterGuard(tdbb->getDatabase(), counterMutex);
Attachment* att = tdbb->getAttachment();
Attachment::CheckoutLockGuard counterGuard(att, counterMutex, true);
COS_TRACE(("(%p)->tryReleaseLock readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)",
this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical));

View File

@ -87,8 +87,9 @@ protected:
virtual void blockingAstHandler(thread_db* tdbb);
private:
Firebird::Mutex counterMutex; // Protects counter and blocking flag
private:
ULONG pendingLock;
ULONG readers;

View File

@ -288,8 +288,6 @@ jrd_req* JrdStatement::findRequest(thread_db* tdbb)
if (!this)
BUGCHECK(167); /* msg 167 invalid SEND request */
Database::CheckoutLockGuard guard(dbb, dbb->dbb_exe_clone_mutex);
// Search clones for one request in use by this attachment.
// If not found, return first inactive request.
@ -539,7 +537,8 @@ void JrdStatement::release(thread_db* tdbb)
sqlText = NULL;
dbb->deletePool(pool);
Jrd::Attachment* const att = tdbb->getAttachment();
att->deletePool(pool);
}
// Check that we have enough rights to access all resources this list of triggers touches.

View File

@ -137,10 +137,8 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, SLONG tran, bool alloc
else
inst_id = PAG_attachment_id(tdbb);
if (!rel_pages_inst)
{
MemoryPool& pool = *dbb->dbb_permanent;
rel_pages_inst = FB_NEW(pool) RelationPagesInstances(pool);
if (!rel_pages_inst) {
rel_pages_inst = FB_NEW(*rel_pool) RelationPagesInstances(*rel_pool);
}
size_t pos;
@ -155,7 +153,7 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, SLONG tran, bool alloc
const size_t BULK_ALLOC = 8;
RelationPages* allocatedPages = newPages =
FB_NEW(*dbb->dbb_permanent) RelationPages[BULK_ALLOC];
FB_NEW(*rel_pool) RelationPages[BULK_ALLOC];
rel_pages_free = ++allocatedPages;
for (size_t i = 1; i < BULK_ALLOC - 1; i++, allocatedPages++)

View File

@ -25,6 +25,7 @@
#include "../jrd/jrd.h"
#include "../jrd/pag.h"
#include "../jrd/val.h"
#include "../jrd/Attachment.h"
namespace Jrd
{
@ -179,6 +180,7 @@ struct frgn
class jrd_rel : public pool_alloc<type_rel>
{
public:
MemoryPool* rel_pool;
USHORT rel_id;
USHORT rel_current_fmt; // Current format number
ULONG rel_flags;
@ -278,7 +280,7 @@ private:
public:
explicit jrd_rel(MemoryPool& p)
: rel_name(p), rel_owner_name(p), rel_view_contexts(p), rel_security_name(p)
: rel_pool(&p), rel_name(p), rel_owner_name(p), rel_view_contexts(p), rel_security_name(p)
{ }
bool hasTriggers() const;

View File

@ -226,7 +226,7 @@ void RuntimeStatistics::addRelCounts(const RelCounters& other, bool add)
}
}
PerformanceInfo* RuntimeStatistics::computeDifference(Database* dbb,
PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
const RuntimeStatistics& new_stat,
PerformanceInfo& dest,
TraceCountsArray& temp)
@ -262,8 +262,8 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Database* dbb,
// Point TraceCounts to counts array from baseline object
if (!all_zeros)
{
jrd_rel* relation = size_t(new_cnts->rlc_relation_id) < dbb->dbb_relations->count() ?
(*dbb->dbb_relations)[new_cnts->rlc_relation_id] : NULL;
jrd_rel* relation = size_t(new_cnts->rlc_relation_id) < att->att_relations->count() ?
(*att->att_relations)[new_cnts->rlc_relation_id] : NULL;
TraceCounts traceCounts;
traceCounts.trc_relation_id = new_cnts->rlc_relation_id;
traceCounts.trc_counters = base_cnts->rlc_counter;
@ -276,8 +276,8 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Database* dbb,
}
else
{
jrd_rel* relation = size_t(new_cnts->rlc_relation_id) < dbb->dbb_relations->count() ?
(*dbb->dbb_relations)[new_cnts->rlc_relation_id] : NULL;
jrd_rel* relation = size_t(new_cnts->rlc_relation_id) < att->att_relations->count() ?
(*att->att_relations)[new_cnts->rlc_relation_id] : NULL;
// Point TraceCounts to counts array from object with updated counters
TraceCounts traceCounts;

View File

@ -35,6 +35,7 @@ namespace Jrd {
// #define REL_COUNTS_TREE
// #define REL_COUNTS_PTR
class Attachment;
class Database;
// Performance counters for individual table
@ -135,7 +136,7 @@ public:
// Calculate difference between counts stored in this object and current
// counts of given request. Counts stored in object are destroyed.
PerformanceInfo* computeDifference(Database* dbb, const RuntimeStatistics& new_stat,
PerformanceInfo* computeDifference(Attachment* att, const RuntimeStatistics& new_stat,
PerformanceInfo& dest, TraceCountsArray& temp);
// bool operator==(const RuntimeStatistics& other) const;

View File

@ -45,7 +45,7 @@ USHORT ValueMover::getClientCharSet() const
void ValueMover::getClientCharSetName(Firebird::MetaName& name) const
{
thread_db* tdbb = getThreadData();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Attachment::SyncGuard attGuard(tdbb->getAttachment());
CharSet* cs = INTL_charset_lookup(tdbb, tdbb->getAttachment()->att_charset);
name = cs->getName();
@ -55,7 +55,7 @@ void ValueMover::getClientCharSetName(Firebird::MetaName& name) const
int ValueMover::getMaxBytesPerChar(USHORT charSet) const
{
thread_db* tdbb = getThreadData();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Attachment::SyncGuard attGuard(tdbb->getAttachment());
return DataTypeUtil(tdbb).maxBytesPerChar(charSet);
}
@ -76,7 +76,7 @@ const char* ValueMover::getString(const ValueImpl* value, const dsc* desc, MoveB
*isNull = false;
thread_db* tdbb = getThreadData();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Attachment::SyncGuard attGuard(tdbb->getAttachment());
USHORT charSet = tdbb->getAttachment()->att_charset;
UCHAR* temp = NULL;
@ -111,7 +111,7 @@ void ValueMover::getValue(const ValueImpl* value, const dsc* desc, dsc* target,
*isNull = false;
thread_db* tdbb = getThreadData();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Attachment::SyncGuard attGuard(tdbb->getAttachment());
MOV_move(tdbb, const_cast<dsc*>(desc), target);
}
@ -121,7 +121,7 @@ void ValueMover::getValue(const ValueImpl* value, const dsc* desc, dsc* target,
void ValueMover::setValue(dsc* desc, USHORT* nullFlag, dsc* from) const
{
thread_db* tdbb = getThreadData();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Attachment::SyncGuard attGuard(tdbb->getAttachment());
MOV_move(tdbb, from, desc);
*nullFlag &= ~DSC_null;

View File

@ -1350,7 +1350,7 @@ blb* BLB_open2(thread_db* tdbb,
// know about the relation, the blob id has got to be invalid
// anyway.
vec<jrd_rel*>* vector = dbb->dbb_relations;
vec<jrd_rel*>* vector = tdbb->getAttachment()->att_relations;
if (blob_id->bid_internal.bid_relation_id >= vector->count() ||
!(blob->blb_relation = (*vector)[blob_id->bid_internal.bid_relation_id] ) )

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,10 @@
#define JRD_CCH_H
#include "../include/fb_blk.h"
#include "../jrd/os/pio.h"
#include "../common/classes/alloc.h"
#include "../common/classes/RefCounted.h"
#include "../common/classes/semaphore.h"
#include "../common/classes/SyncObject.h"
#ifdef SUPERSERVER_V2
#include "../jrd/sbm.h"
#include "../jrd/pag.h"
@ -78,27 +80,86 @@ struct bcb_repeat
que bcb_page_mod; // Que of buffers with page mod n
};
class BufferControl : public pool_alloc_rpt<bcb_repeat, type_bcb>
class BufferControl : public pool_alloc<type_bcb>
{
explicit BufferControl(MemoryPool& p) :
bcb_bufferpool(&p),
bcb_memory(p)
{
bcb_database = NULL;
QUE_INIT(bcb_in_use);
QUE_INIT(bcb_pending);
QUE_INIT(bcb_empty);
QUE_INIT(bcb_dirty);
bcb_dirty_count = 0;
bcb_free = NULL;
bcb_flags = 0;
bcb_free_minimum = 0;
bcb_count = 0;
bcb_inuse = 0;
bcb_checkpoint = 0;
bcb_prec_walk_mark = 0;
bcb_page_size = 0;
bcb_page_incarnation = 0;
#ifdef SUPERSERVER_V2
bcb_prefetch = NULL;
#endif
}
public:
explicit BufferControl(MemoryPool& p) : bcb_memory(p) { }
static BufferControl* create();
static void destroy(BufferControl*);
Firebird::MemoryPool* bcb_bufferpool;
Firebird::MemoryStats bcb_memory_stats;
// To be deleted when PAG will be not coupled with Database.
// Used only in CS mode when each BufferControl have one Database .
Database* bcb_database;
UCharStack bcb_memory; // Large block partitioned into buffers
que bcb_in_use; // Que of buffers in use
que bcb_in_use; // Que of buffers in use, main LRU que
que bcb_pending; // Que of buffers which are going to be freed and reassigned
que bcb_empty; // Que of empty buffers
// Recently used buffer put there without locking common LRU que (bcb_in_use).
// When bcb_syncLRU is locked this chain is merged into bcb_in_use. See also
// requeueRecentlyUsed() and recentlyUsed()
Firebird::AtomicPointer<BufferDesc> bcb_lru_chain;
que bcb_dirty; // que of dirty buffers
SLONG bcb_dirty_count; // count of pages in dirty page btree
Precedence* bcb_free; // Free precedence blocks
que bcb_free_lwt; // Free latch wait blocks
que bcb_free_slt; // Free shared latch blocks
SSHORT bcb_flags; // see below
SSHORT bcb_free_minimum; // Threshold to activate cache writer
ULONG bcb_count; // Number of buffers allocated
ULONG bcb_inuse; // Number of buffers in use
ULONG bcb_checkpoint; // Count of buffers to checkpoint
ULONG bcb_prec_walk_mark; // mark value used in precedence graph walk
ULONG bcb_page_size; // Database page size in bytes
ULONG bcb_page_incarnation; // Cache page incarnation counter
Firebird::SyncObject bcb_syncObject;
Firebird::SyncObject bcb_syncDirtyBdbs;
Firebird::SyncObject bcb_syncPrecedence;
Firebird::SyncObject bcb_syncLRU;
//Firebird::SyncObject bcb_syncPageWrite;
Firebird::Semaphore bcb_writer_sem; // Wake up cache writer
Firebird::Semaphore bcb_writer_init;// Cache writer initialization
Firebird::Semaphore bcb_writer_fini;// Cache writer finalization
#ifdef SUPERSERVER_V2
// the code in cch.cpp is not tested for semaphore instead event !!!
Firebird::Semaphore bcb_reader_sem; // Wake up cache reader
Firebird::Semaphore bcb_reader_init;// Cache reader initialization
Firebird::Semaphore bcb_reader_fini;// Cache reader finalization
PageBitmap* bcb_prefetch; // Bitmap of pages to prefetch
#endif
bcb_repeat bcb_rpt[1];
bcb_repeat* bcb_rpt;
};
const int BCB_keep_pages = 1; // set during btc_flush(), pages not removed from dirty binary tree
@ -110,66 +171,115 @@ const int BCB_cache_reader = 16; // cache reader thread has been started
const int BCB_reader_active = 32; // cache reader not blocked on event
#endif
const int BCB_free_pending = 64; // request cache writer to free pages
const int BCB_exclusive = 128; // there is only BCB in whole system
// BufferDesc -- Buffer descriptor block
const int BDB_max_shared = 20; // maximum number of shared latch owners per BufferDesc
class BufferDesc : public pool_alloc<type_bdb>
{
public:
BufferDesc() : bdb_page(0, 0) {}
BufferDesc(BufferControl* bcb) :
bdb_bcb(bcb),
bdb_page(0, 0),
bdb_pending_page(0, 0)
{
bdb_lock = NULL;
QUE_INIT(bdb_que);
QUE_INIT(bdb_in_use);
QUE_INIT(bdb_dirty);
bdb_buffer = NULL;
bdb_incarnation = 0;
bdb_transactions = 0;
bdb_mark_transaction = 0;
QUE_INIT(bdb_lower);
QUE_INIT(bdb_higher);
bdb_exclusive = NULL;
bdb_io = NULL;
bdb_writers = 0;
bdb_scan_count = 0;
bdb_difference_page = 0;
bdb_prec_walk_mark = 0;
}
Database* bdb_dbb; // Database block (for ASTs)
void addRef(thread_db* tdbb, Firebird::SyncType syncType);
bool addRefConditional(thread_db* tdbb, Firebird::SyncType syncType);
void downgrade(Firebird::SyncType syncType);
void release(thread_db* tdbb);
void lockIO(thread_db*);
void unLockIO(thread_db*);
bool isLocked() const
{
return bdb_syncPage.isLocked();
}
bool ourExclusiveLock() const
{
return bdb_syncPage.ourExclusiveLock();
}
bool ourIOLock() const
{
return bdb_syncIO.ourExclusiveLock();
}
BufferControl* bdb_bcb;
Firebird::SyncObject bdb_syncPage;
Lock* bdb_lock; // Lock block for buffer
que bdb_que; // Buffer que
que bdb_que; // Either mod que in hash table or bcb_pending que if BDB_free_pending flag is set
que bdb_in_use; // queue of buffers in use
que bdb_dirty; // dirty pages LRU queue
BufferDesc* bdb_lru_chain; // pending LRU chain
Ods::pag* bdb_buffer; // Actual buffer
PageNumber bdb_page; // Database page number in buffer
SLONG bdb_incarnation;
PageNumber bdb_pending_page; // Database page number to be
ULONG bdb_incarnation;
ULONG bdb_transactions; // vector of dirty flags to reduce commit overhead
SLONG bdb_mark_transaction; // hi-water mark transaction to defer header page I/O
que bdb_lower; // lower precedence que
que bdb_higher; // higher precedence que
que bdb_waiters; // latch wait que
thread_db* bdb_exclusive; // thread holding exclusive latch
thread_db* bdb_io; // thread holding io latch
ULONG bdb_ast_flags; // flags manipulated at AST level
USHORT bdb_flags;
SSHORT bdb_use_count; // Number of active users
private:
thread_db* bdb_io; // thread holding io latch
Firebird::SyncObject bdb_syncIO;
public:
Firebird::AtomicCounter bdb_ast_flags; // flags manipulated at AST level
Firebird::AtomicCounter bdb_flags;
Firebird::AtomicCounter bdb_use_count; // Number of active users
SSHORT bdb_writers; // Number of recursively taken exclusive locks
SSHORT bdb_io_locks; // Number of recursively taken IO locks
SSHORT bdb_scan_count; // concurrent sequential scans
ULONG bdb_difference_page; // Number of page in difference file, NBAK
ULONG bdb_prec_walk_mark; // mark value used in precedence graph walk
que bdb_shared; // shared latches queue
};
// bdb_flags
// to set/clear BDB_dirty use set_dirty_flag()/clear_dirty_flag()
// These constants should really be of type USHORT.
const int BDB_dirty = 1; // page has been updated but not written yet
const int BDB_garbage_collect = 2; // left by scan for garbage collector
const int BDB_writer = 4; // someone is updating the page
const int BDB_marked = 8; // page has been updated
const int BDB_must_write = 16; // forces a write as soon as the page is released
const int BDB_faked = 32; // page was just allocated
//const int BDB_merge = 64;
const int BDB_system_dirty = 128; // system transaction has marked dirty
const int BDB_io_error = 256; // page i/o error
const int BDB_read_pending = 512; // read is pending
const int BDB_free_pending = 1024; // buffer being freed for reuse
const int BDB_not_valid = 2048; // i/o error invalidated buffer
const int BDB_db_dirty = 4096; // page must be written to database
const int BDB_checkpoint = 8192; // page must be written by next checkpoint
const int BDB_prefetch = 16384; // page has been prefetched but not yet referenced
const int BDB_no_blocking_ast = 32768; // No blocking AST registered with page lock
// CVC: There's no more room for flags unless you change bdb_flags from USHORT to ULONG.
const int BDB_dirty = 0x0001; // page has been updated but not written yet
const int BDB_garbage_collect = 0x0002; // left by scan for garbage collector
const int BDB_writer = 0x0004; // someone is updating the page
const int BDB_marked = 0x0008; // page has been updated
const int BDB_must_write = 0x0010; // forces a write as soon as the page is released
const int BDB_faked = 0x0020; // page was just allocated
//const int BDB_merge = 0x0040;
const int BDB_system_dirty = 0x0080; // system transaction has marked dirty
const int BDB_io_error = 0x0100; // page i/o error
const int BDB_read_pending = 0x0200; // read is pending
const int BDB_free_pending = 0x0400; // buffer being freed for reuse
const int BDB_not_valid = 0x0800; // i/o error invalidated buffer
const int BDB_db_dirty = 0x1000; // page must be written to database
const int BDB_checkpoint = 0x2000; // page must be written by next checkpoint
const int BDB_prefetch = 0x4000; // page has been prefetched but not yet referenced
const int BDB_no_blocking_ast = 0x8000; // No blocking AST registered with page lock
const int BDB_lru_chained = 0x10000; // buffer is in pending LRU chain
// bdb_ast_flags
const ULONG BDB_blocking = 1; // a blocking ast was sent while page locked
const int BDB_blocking = 0x01; // a blocking ast was sent while page locked
// PRE -- Precedence block
@ -221,29 +331,6 @@ enum LATCH
LATCH_mark
};
// LWT -- Latch wait block
class LatchWait : public pool_alloc<type_lwt>
{
public:
thread_db* lwt_tdbb;
LATCH lwt_latch; // latch type requested
que lwt_waiters; // latch queue
Firebird::Semaphore lwt_sem; // grant event to wait on
USHORT lwt_flags;
};
const int LWT_pending = 1; // latch request is pending
// Shared Latch
class SharedLatch
{
public:
thread_db* slt_tdbb; // thread holding latch
BufferDesc* slt_bdb; // buffer for which is this latch
que slt_tdbb_que; // thread's latches queue
que slt_bdb_que; // buffer's latches queue
};
#ifdef SUPERSERVER_V2
@ -277,6 +364,7 @@ const int PRF_active = 1; // prefetch block currently in use
typedef Firebird::SortedArray<SLONG, Firebird::InlineStorage<SLONG, 256>, SLONG> PagesArray;
} //namespace Jrd
#endif // JRD_CCH_H

View File

@ -28,29 +28,37 @@ namespace Ods {
struct pag;
}
enum LockState {
lsLatchTimeout = -2, // was -2 *** now unused ***
lsLockTimeout, // was -1
lsLockedHavePage, // was 0
lsLocked, // was 1
lsError
};
void CCH_shutdown_database(Jrd::Database*);
int CCH_down_grade_dbb(void*);
bool CCH_exclusive(Jrd::thread_db*, USHORT, SSHORT);
bool CCH_exclusive_attachment(Jrd::thread_db*, USHORT, SSHORT);
void CCH_expand(Jrd::thread_db*, ULONG);
Ods::pag* CCH_fake(Jrd::thread_db*, Jrd::win*, SSHORT);
Ods::pag* CCH_fetch(Jrd::thread_db*, Jrd::win*, USHORT, SCHAR, SSHORT, const bool);
SSHORT CCH_fetch_lock(Jrd::thread_db*, Jrd::win*, USHORT, SSHORT, SCHAR);
Ods::pag* CCH_fake(Jrd::thread_db*, Jrd::win*, int);
Ods::pag* CCH_fetch(Jrd::thread_db*, Jrd::win*, int, SCHAR, int, const bool);
LockState CCH_fetch_lock(Jrd::thread_db*, Jrd::win*, int, int, SCHAR);
void CCH_fetch_page(Jrd::thread_db*, Jrd::win*, const bool);
void CCH_forget_page(Jrd::thread_db*, Jrd::win*);
void CCH_fini(Jrd::thread_db*);
void CCH_forget_page(Jrd::thread_db*, Jrd::win*);
void CCH_flush(Jrd::thread_db*, USHORT, SLONG);
bool CCH_free_page(Jrd::thread_db*);
SLONG CCH_get_incarnation(Jrd::win*);
void CCH_get_related(Jrd::thread_db*, Jrd::PageNumber, Jrd::PagesArray&);
Ods::pag* CCH_handoff(Jrd::thread_db*, Jrd::win*, ULONG, SSHORT, SCHAR, SSHORT, const bool);
void CCH_init(Jrd::thread_db*, ULONG);
void CCH_mark(Jrd::thread_db*, Jrd::win*, USHORT, USHORT);
void CCH_must_write(Jrd::win*);
Ods::pag* CCH_handoff(Jrd::thread_db*, Jrd::win*, ULONG, int, SCHAR, int, const bool);
void CCH_init(Jrd::thread_db*, ULONG, bool);
void CCH_mark(Jrd::thread_db*, Jrd::win*, bool, bool);
void CCH_must_write(Jrd::thread_db*, Jrd::win*);
void CCH_precedence(Jrd::thread_db*, Jrd::win*, ULONG);
void CCH_tra_precedence(Jrd::thread_db*, Jrd::win*, SLONG);
void CCH_precedence(Jrd::thread_db*, Jrd::win*, Jrd::PageNumber);
void CCH_tra_precedence(Jrd::thread_db*, Jrd::win*, SLONG);
#ifdef SUPERSERVER_V2
void CCH_prefetch(Jrd::thread_db*, SLONG*, SSHORT);
bool CCH_prefetch_pages(Jrd::thread_db*);
@ -81,16 +89,6 @@ inline Ods::pag* CCH_FETCH_TIMEOUT(Jrd::thread_db* tdbb, Jrd::win* window, USHOR
return CCH_fetch (tdbb, window, lock_type, page_type, latch_wait, true);
}
inline SSHORT CCH_FETCH_LOCK(Jrd::thread_db* tdbb, Jrd::win* window, USHORT lock_type, SSHORT wait, SCHAR page_type)
{
return CCH_fetch_lock(tdbb, window, lock_type, wait, page_type);
}
inline void CCH_FETCH_PAGE(Jrd::thread_db* tdbb, Jrd::win* window, bool read_shadow)
{
CCH_fetch_page(tdbb, window, read_shadow);
}
inline void CCH_RELEASE(Jrd::thread_db* tdbb, Jrd::win* window)
{
CCH_release(tdbb, window, false);

View File

@ -163,10 +163,11 @@ jrd_req* CMP_compile2(thread_db* tdbb, const UCHAR* blr, ULONG blr_length, bool
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
// 26.09.2002 Nickolay Samofatov: default memory pool will become statement pool
// and will be freed by CMP_release
MemoryPool* const new_pool = dbb->createPool();
MemoryPool* const new_pool = att->createPool();
try
{
@ -208,7 +209,7 @@ jrd_req* CMP_compile2(thread_db* tdbb, const UCHAR* blr, ULONG blr_length, bool
if (request)
CMP_release(tdbb, request);
else
dbb->deletePool(new_pool);
att->deletePool(new_pool);
ERR_punt();
}
@ -254,22 +255,6 @@ void CMP_fini(thread_db* tdbb)
Database* const dbb = tdbb->getDatabase();
CMP_shutdown_database(tdbb); // Shutdown shared database locks.
// And release the system requests.
fb_assert(tdbb->getAttachment() == NULL);
for (JrdStatement** itr = dbb->dbb_internal.begin(); itr != dbb->dbb_internal.end(); ++itr)
{
if (*itr)
(*itr)->release(tdbb);
}
for (JrdStatement** itr = dbb->dbb_dyn_req.begin(); itr != dbb->dbb_dyn_req.end(); ++itr)
{
if (*itr)
(*itr)->release(tdbb);
}
}
@ -343,14 +328,14 @@ IndexLock* CMP_get_index_lock(thread_db* tdbb, jrd_rel* relation, USHORT id)
}
}
IndexLock* index = FB_NEW(*dbb->dbb_permanent) IndexLock();
IndexLock* index = FB_NEW(*relation->rel_pool) IndexLock();
index->idl_next = relation->rel_index_locks;
relation->rel_index_locks = index;
index->idl_relation = relation;
index->idl_id = id;
index->idl_count = 0;
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock;
Lock* lock = FB_NEW_RPT(*relation->rel_pool, 0) Lock;
index->idl_lock = lock;
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
@ -519,7 +504,7 @@ void CMP_decrement_prc_use_count(thread_db* tdbb, jrd_prc* procedure)
// The procedure will be different than in dbb_procedures only if it is a
// floating copy, i.e. an old copy or a deleted procedure.
if ((procedure->prc_use_count == 0) &&
( (*tdbb->getDatabase()->dbb_procedures)[procedure->getId()] != procedure))
( (*tdbb->getAttachment()->att_procedures)[procedure->getId()] != procedure))
{
if (procedure->getStatement())
{
@ -568,83 +553,6 @@ void CMP_shutdown_database(thread_db* tdbb)
CHECK_DBB(dbb);
DEV_BLKCHK(dbb, type_dbb);
// go through relations and indices and release
// all existence locks that might have been taken
vec<jrd_rel*>* rvector = dbb->dbb_relations;
if (rvector)
{
vec<jrd_rel*>::iterator ptr, end;
for (ptr = rvector->begin(), end = rvector->end(); ptr < end; ++ptr)
{
jrd_rel* relation = *ptr;
if (relation)
{
if (relation->rel_existence_lock)
{
LCK_release(tdbb, relation->rel_existence_lock);
relation->rel_flags |= REL_check_existence;
relation->rel_use_count = 0;
}
if (relation->rel_partners_lock)
{
LCK_release(tdbb, relation->rel_partners_lock);
relation->rel_flags |= REL_check_partners;
}
if (relation->rel_rescan_lock)
{
LCK_release(tdbb, relation->rel_rescan_lock);
relation->rel_flags &= ~REL_scanned;
}
for (IndexLock* index = relation->rel_index_locks; index; index = index->idl_next)
{
if (index->idl_lock)
{
index->idl_count = 0;
LCK_release(tdbb, index->idl_lock);
}
}
}
}
}
// release all procedure existence locks that might have been taken
vec<jrd_prc*>* pvector = dbb->dbb_procedures;
if (pvector)
{
vec<jrd_prc*>::iterator pptr, pend;
for (pptr = pvector->begin(), pend = pvector->end(); pptr < pend; ++pptr)
{
jrd_prc* procedure = *pptr;
if (procedure)
{
if (procedure->prc_existence_lock)
{
LCK_release(tdbb, procedure->prc_existence_lock);
procedure->prc_flags |= PRC_check_existence;
procedure->prc_use_count = 0;
}
}
}
}
// release all function existence locks that might have been taken
for (Function** iter = dbb->dbb_functions.begin(); iter < dbb->dbb_functions.end(); ++iter)
{
Function* const function = *iter;
if (function)
{
function->releaseLocks(tdbb);
}
}
// release collation existence locks
dbb->releaseIntlObjects();
}

View File

@ -2934,12 +2934,12 @@ static bool create_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
if ((arg->dfw_id & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DB)
{
MET_load_trigger(tdbb, NULL, work->dfw_name,
&tdbb->getDatabase()->dbb_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB]);
&tdbb->getAttachment()->att_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB]);
}
else if ((arg->dfw_id & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DDL)
{
MET_load_trigger(tdbb, NULL, work->dfw_name,
&tdbb->getDatabase()->dbb_ddl_triggers);
&tdbb->getAttachment()->att_ddl_triggers);
}
}
}
@ -3264,13 +3264,13 @@ static bool create_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
if (!validation.isEmpty())
{
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, NULL, NULL, 0, NULL, &validation,
NULL, NULL, depName, obj_validation, 0, transaction, depName);
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
}
}
// fall through
@ -3428,13 +3428,13 @@ static bool modify_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
if (!validation.isEmpty())
{
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_get_dependencies(tdbb, NULL, NULL, 0, NULL, &validation,
NULL, NULL, depName, obj_validation, 0, transaction, depName);
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
}
}
// fall through
@ -3510,8 +3510,8 @@ static void check_partners(thread_db* tdbb, const USHORT rel_id)
* Used when FK index was dropped
*
**************************************/
const Database* dbb = tdbb->getDatabase();
vec<jrd_rel*>* relations = dbb->dbb_relations;
const Jrd::Attachment* att = tdbb->getAttachment();
vec<jrd_rel*>* relations = att->att_relations;
fb_assert(relations);
fb_assert(rel_id < relations->count());
@ -3619,7 +3619,8 @@ static bool delete_function(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
LCK_release(tdbb, function->fun_existence_lock);
}
dbb->dbb_functions[function->getId()] = NULL;
Jrd::Attachment* attachment = tdbb->getAttachment();
attachment->att_functions[function->getId()] = NULL;
return false;
}
@ -3978,7 +3979,7 @@ static bool delete_procedure(thread_db* tdbb, SSHORT phase, DeferredWork* work,
if (procedure->prc_existence_lock) {
LCK_release(tdbb, procedure->prc_existence_lock);
}
(*tdbb->getDatabase()->dbb_procedures)[procedure->getId()] = NULL;
(*tdbb->getAttachment()->att_procedures)[procedure->getId()] = NULL;
return false;
}
@ -4127,9 +4128,8 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
// garbage collector threads working on relation can skip over it
relation->rel_flags |= REL_deleting;
{ // scope
Database::Checkout dcoHolder(dbb);
Jrd::Attachment::Checkout attCout(attachment);
relation->rel_drop_mutex.enter();
}
@ -4156,7 +4156,7 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
break;
}
Database::Checkout dcoHolder(dbb);
Jrd::Attachment::Checkout attCout(attachment);
THREAD_SLEEP(1 * 1000);
}
@ -4440,7 +4440,7 @@ static bool delete_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
if (arg && (arg->dfw_id & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DB)
{
MET_release_trigger(tdbb,
&tdbb->getDatabase()->dbb_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB],
&tdbb->getAttachment()->att_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB],
work->dfw_name);
}
}
@ -4689,7 +4689,7 @@ static void get_function_dependencies(DeferredWork* work, bool compile, jrd_tra*
{
JrdStatement* statement = NULL;
MemoryPool* const new_pool = dbb->createPool();
MemoryPool* const new_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, new_pool);
const Firebird::MetaName depName(work->dfw_package.isEmpty() ?
@ -4703,7 +4703,7 @@ static void get_function_dependencies(DeferredWork* work, bool compile, jrd_tra*
if (statement)
statement->release(tdbb);
else
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
}
}
@ -4756,7 +4756,7 @@ static void get_procedure_dependencies(DeferredWork* work, bool compile, jrd_tra
{
JrdStatement* statement = NULL;
// Nickolay Samofatov: allocate statement memory pool...
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = attachment->createPool();
// block is used to ensure MET_verify_cache
// works in not deleted context
{
@ -4772,7 +4772,7 @@ static void get_procedure_dependencies(DeferredWork* work, bool compile, jrd_tra
if (statement)
statement->release(tdbb);
else
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
}
#ifdef DEV_BUILD
@ -4827,7 +4827,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra*
{
JrdStatement* statement = NULL;
// Nickolay Samofatov: allocate statement memory pool...
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = attachment->createPool();
const USHORT par_flags = (USHORT) (type & 1) ? csb_pre_trigger : csb_post_trigger;
Jrd::ContextPoolHolder context(tdbb, new_pool);
@ -4838,7 +4838,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra*
if (statement)
statement->release(tdbb);
else
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
}
}
@ -4994,7 +4994,7 @@ static Format* make_format(thread_db* tdbb, jrd_rel* relation, USHORT* version,
// Link the format block into the world
vec<Format*>* vector = relation->rel_formats =
vec<Format*>::newVector(*dbb->dbb_permanent, relation->rel_formats, format->fmt_version + 1);
vec<Format*>::newVector(*relation->rel_pool, relation->rel_formats, format->fmt_version + 1);
(*vector)[format->fmt_version] = format;
// Store format in system relation
@ -5282,7 +5282,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
if (notNull && !defaultValue->isEmpty())
{
Jrd::ContextPoolHolder context(tdbb, dbb->createPool());
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
JrdStatement* defaultStatement = NULL;
try
{
@ -5502,6 +5502,7 @@ static bool modify_function(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
const QualifiedName name(work->dfw_name, work->dfw_package);
@ -5561,7 +5562,6 @@ static bool modify_function(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
}
{ // guard scope
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
// Do not allow to modify function used by user requests
if (function->isUsed())
@ -5580,7 +5580,8 @@ static bool modify_function(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
LCK_release(tdbb, function->fun_existence_lock);
}
dbb->dbb_functions[function->getId()] = NULL;
Jrd::Attachment* attachment = tdbb->getAttachment();
attachment->att_functions[function->getId()] = NULL;
if (!(function = Function::lookup(tdbb, work->dfw_id, false,
true, FUN_being_altered)))
@ -5650,7 +5651,7 @@ static bool modify_function(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
{
bool valid_blr = false;
MemoryPool* const csb_pool = dbb->createPool();
MemoryPool* const csb_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, csb_pool);
try
@ -5669,11 +5670,11 @@ static bool modify_function(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
}
catch (const Firebird::Exception&)
{
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
throw;
}
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
MODIFY FUN USING
FUN.RDB$VALID_BLR = valid_blr ? TRUE : FALSE;
@ -5705,6 +5706,7 @@ static bool modify_procedure(thread_db* tdbb, SSHORT phase, DeferredWork* work,
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
const QualifiedName name(work->dfw_name, work->dfw_package);
switch (phase)
@ -5758,7 +5760,6 @@ static bool modify_procedure(thread_db* tdbb, SSHORT phase, DeferredWork* work,
}
{ // guard scope
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
// Do not allow to modify procedure used by user requests
if (procedure->prc_use_count && MET_procedure_in_use(tdbb, procedure))
@ -5782,7 +5783,7 @@ static bool modify_procedure(thread_db* tdbb, SSHORT phase, DeferredWork* work,
if (procedure->prc_existence_lock) {
LCK_release(tdbb, procedure->prc_existence_lock);
}
(*tdbb->getDatabase()->dbb_procedures)[procedure->getId()] = NULL;
(*tdbb->getAttachment()->att_procedures)[procedure->getId()] = NULL;
if (!(procedure = MET_lookup_procedure_id(tdbb, work->dfw_id, false,
true, PRC_being_altered)))
@ -5843,7 +5844,7 @@ static bool modify_procedure(thread_db* tdbb, SSHORT phase, DeferredWork* work,
{
SSHORT valid_blr = FALSE;
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = attachment->createPool();
try
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
@ -5857,7 +5858,7 @@ static bool modify_procedure(thread_db* tdbb, SSHORT phase, DeferredWork* work,
fb_utils::init_status(tdbb->tdbb_status_vector);
}
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
AutoCacheRequest request(tdbb, irq_prc_validate, IRQ_REQUESTS);
@ -5895,6 +5896,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
switch (phase)
{
@ -5924,11 +5926,11 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
if (arg && (arg->dfw_id & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DB)
{
MET_release_trigger(tdbb,
&tdbb->getDatabase()->dbb_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB],
&tdbb->getAttachment()->att_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB],
work->dfw_name);
MET_load_trigger(tdbb, NULL, work->dfw_name,
&tdbb->getDatabase()->dbb_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB]);
&tdbb->getAttachment()->att_triggers[arg->dfw_id & ~TRIGGER_TYPE_DB]);
}
}
}
@ -5955,7 +5957,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
for (int i = 0; i < TRIGGER_MAX; ++i)
triggers[i] = NULL;
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = attachment->createPool();
try
{
Jrd::ContextPoolHolder context(tdbb, new_pool);
@ -5977,7 +5979,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
}
catch (const Firebird::Exception&)
{
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
throw;
}

View File

@ -1208,7 +1208,7 @@ SINT64 DPM_gen_id(thread_db* tdbb, SLONG generator, bool initialize, SINT64 val)
generator_page* page = (generator_page*) DPM_allocate(tdbb, &window);
page->gpg_header.pag_type = pag_ids;
page->gpg_sequence = sequence;
CCH_must_write(&window);
CCH_must_write(tdbb, &window);
CCH_RELEASE(tdbb, &window);
DPM_pages(tdbb, 0, pag_ids, (ULONG) sequence, window.win_page.getPageNum());
vector = dbb->dbb_gen_id_pages =
@ -2700,7 +2700,7 @@ static void extend_relation(thread_db* tdbb, jrd_rel* relation, WIN* window, USH
ppage->ppg_relation = relation->rel_id;
ppage->ppg_sequence = ++pp_sequence;
slot = 0;
CCH_must_write(&new_pp_window);
CCH_must_write(tdbb, &new_pp_window);
CCH_RELEASE(tdbb, &new_pp_window);
vcl* vector = relPages->rel_pages =

View File

@ -119,6 +119,7 @@ void DYN_ddl(jrd_tra* transaction, ULONG length, const UCHAR* ddl, const string&
thread_db* const tdbb = JRD_get_thread_data();
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
const UCHAR* ptr = ddl;
@ -132,12 +133,10 @@ void DYN_ddl(jrd_tra* transaction, ULONG length, const UCHAR* ddl, const string&
// Create a pool for DYN to operate in. It will be released when
// the routine exits.
MemoryPool* const tempPool = dbb->createPool();
MemoryPool* const tempPool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, tempPool);
try {
Database::CheckoutLockGuard guard(dbb, dbb->dbb_dyn_mutex);
VIO_start_save_point(tdbb, transaction);
transaction->tra_save_point->sav_verb_count++;
@ -164,12 +163,12 @@ void DYN_ddl(jrd_tra* transaction, ULONG length, const UCHAR* ddl, const string&
}
}
dbb->deletePool(tempPool);
attachment->deletePool(tempPool);
ERR_punt();
}
dbb->deletePool(tempPool);
attachment->deletePool(tempPool);
}

View File

@ -490,8 +490,10 @@ void EXE_execute_db_triggers(thread_db* tdbb, jrd_tra* transaction, jrd_req::req
* Execute database triggers
*
**************************************/
Jrd::Attachment* attachment = tdbb->getAttachment();
// do nothing if user doesn't want database triggers
if (tdbb->getAttachment()->att_flags & ATT_no_db_triggers)
if (attachment->att_flags & ATT_no_db_triggers)
return;
int type = 0;
@ -523,14 +525,14 @@ void EXE_execute_db_triggers(thread_db* tdbb, jrd_tra* transaction, jrd_req::req
return;
}
if (tdbb->getDatabase()->dbb_triggers[type])
if (attachment->att_triggers[type])
{
jrd_tra* old_transaction = tdbb->getTransaction();
tdbb->setTransaction(transaction);
try
{
EXE_execute_triggers(tdbb, &tdbb->getDatabase()->dbb_triggers[type],
EXE_execute_triggers(tdbb, &attachment->att_triggers[type],
NULL, NULL, trigger_action, StmtNode::ALL_TRIGS);
tdbb->setTransaction(old_transaction);
}
@ -546,9 +548,11 @@ void EXE_execute_db_triggers(thread_db* tdbb, jrd_tra* transaction, jrd_req::req
// Execute DDL triggers.
void EXE_execute_ddl_triggers(thread_db* tdbb, jrd_tra* transaction, bool preTriggers, int action)
{
Jrd::Attachment* attachment = tdbb->getAttachment();
// Our caller verifies (ATT_no_db_triggers) if DDL triggers should not run.
if (tdbb->getDatabase()->dbb_ddl_triggers)
if (attachment->att_ddl_triggers)
{
jrd_tra* const oldTransaction = tdbb->getTransaction();
tdbb->setTransaction(transaction);
@ -558,8 +562,8 @@ void EXE_execute_ddl_triggers(thread_db* tdbb, jrd_tra* transaction, bool preTri
trig_vec triggers;
trig_vec* triggersPtr = &triggers;
for (trig_vec::iterator i = tdbb->getDatabase()->dbb_ddl_triggers->begin();
i != tdbb->getDatabase()->dbb_ddl_triggers->end();
for (trig_vec::iterator i = attachment->att_ddl_triggers->begin();
i != attachment->att_ddl_triggers->end();
++i)
{
if ((i->type & (1LL << action)) &&

View File

@ -63,7 +63,7 @@ namespace Jrd
AutoCacheRequest(thread_db* tdbb, USHORT aId, USHORT aWhich)
: id(aId),
which(aWhich),
request(tdbb->getDatabase()->findSystemRequest(tdbb, id, which))
request(tdbb->getAttachment()->findSystemRequest(tdbb, id, which))
{
}
@ -86,7 +86,7 @@ namespace Jrd
id = aId;
which = aWhich;
request = tdbb->getDatabase()->findSystemRequest(tdbb, id, which);
request = tdbb->getAttachment()->findSystemRequest(tdbb, id, which);
}
void compile(thread_db* tdbb, const UCHAR* blr, ULONG blrLength)
@ -125,12 +125,12 @@ namespace Jrd
inline void cacheRequest()
{
Database* dbb = JRD_get_thread_data()->getDatabase();
Jrd::Attachment* att = JRD_get_thread_data()->getAttachment();
if (which == IRQ_REQUESTS)
dbb->dbb_internal[id] = request->getStatement();
att->att_internal[id] = request->getStatement();
else if (which == DYN_REQUESTS)
dbb->dbb_dyn_req[id] = request->getStatement();
att->att_dyn_req[id] = request->getStatement();
else
{
fb_assert(false);

View File

@ -264,7 +264,7 @@ ExternalFile* EXT_file(jrd_rel* relation, const TEXT* file_name) //, bid* descri
file_name = path.c_str();
}
ExternalFile* file = FB_NEW_RPT(*dbb->dbb_permanent, (strlen(file_name) + 1)) ExternalFile();
ExternalFile* file = FB_NEW_RPT(*relation->rel_pool, (strlen(file_name) + 1)) ExternalFile();
relation->rel_file = file;
strcpy(file->ext_filename, file_name);
file->ext_flags = 0;

View File

@ -105,7 +105,7 @@ Connection* Manager::getConnection(thread_db* tdbb, const string& dataSource,
{
if (!m_initialized)
{
Database::CheckoutLockGuard guard(tdbb->getDatabase(), m_mutex);
MutexLockGuard guard(m_mutex);
if (!m_initialized)
{
m_initialized = true;
@ -186,7 +186,7 @@ Connection* Provider::getConnection(thread_db* tdbb, const string& dbName,
ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded));
{ // m_mutex scope
Database::CheckoutLockGuard guard(tdbb->getDatabase(), m_mutex);
MutexLockGuard guard(m_mutex);
Connection** conn_ptr = m_connections.begin();
Connection** end = m_connections.end();
@ -216,7 +216,7 @@ Connection* Provider::getConnection(thread_db* tdbb, const string& dbName,
}
{ // m_mutex scope
Database::CheckoutLockGuard guard(tdbb->getDatabase(), m_mutex);
MutexLockGuard guard(m_mutex);
m_connections.add(conn);
}
@ -228,7 +228,7 @@ Connection* Provider::getConnection(thread_db* tdbb, const string& dbName,
void Provider::releaseConnection(thread_db* tdbb, Connection& conn, bool /*inPool*/)
{
{ // m_mutex scope
Database::CheckoutLockGuard guard(tdbb->getDatabase(), m_mutex);
MutexLockGuard guard(m_mutex);
conn.m_boundAtt = NULL;
@ -1597,9 +1597,8 @@ void EngineCallbackGuard::init(thread_db* tdbb, Connection& conn)
{
m_saveConnection = attachment->att_ext_connection;
attachment->att_ext_connection = &conn;
attachment->att_interface->getMutex()->leave();
}
m_tdbb->getDatabase()->dbb_sync->unlock();
}
if (m_mutex) {
@ -1615,17 +1614,17 @@ EngineCallbackGuard::~EngineCallbackGuard()
if (m_tdbb)
{
m_tdbb->getDatabase()->dbb_sync->lock();
Jrd::Attachment* attachment = m_tdbb->getAttachment();
if (attachment)
{
attachment->att_interface->getMutex()->enter();
attachment->att_ext_connection = m_saveConnection;
}
jrd_tra* transaction = m_tdbb->getTransaction();
if (transaction) {
transaction->tra_callback_count--;
}
Jrd::Attachment* attachment = m_tdbb->getAttachment();
if (attachment) {
attachment->att_ext_connection = m_saveConnection;
}
}
}

View File

@ -209,9 +209,9 @@ bool IbUtil::free(void* ptr)
typedef void* UDF_ARG;
template <typename T>
T CALL_UDF(Database* dbb, int (*entrypoint)(), UDF_ARG* args)
T CALL_UDF(Jrd::Attachment* att, int (*entrypoint)(), UDF_ARG* args)
{
Database::Checkout dcoHolder(dbb);
Jrd::Attachment::Checkout attCout(att);
return ((T (*)(UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG, UDF_ARG))(entrypoint)) (args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
}
@ -757,7 +757,7 @@ static SLONG blob_lseek(blb* blob, USHORT mode, SLONG offset)
**************************************/
// As this is a call-back from a UDF, must reacquire the engine mutex
thread_db* tdbb = JRD_get_thread_data();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Jrd::Attachment::SyncGuard guard(tdbb->getAttachment());
return BLB_lseek(blob, mode, offset);
}
@ -777,7 +777,7 @@ static void blob_put_segment(blb* blob, const UCHAR* buffer, USHORT length)
**************************************/
// As this is a call-back from a UDF, must reacquire the engine mutex
thread_db* tdbb = JRD_get_thread_data();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Jrd::Attachment::SyncGuard guard(tdbb->getAttachment());
BLB_put_segment(tdbb, blob, buffer, length);
}
@ -801,7 +801,7 @@ static SSHORT blob_get_segment(blb* blob, UCHAR* buffer, USHORT length, USHORT*
**************************************/
// As this is a call-back from a UDF, must reacquire the engine mutex
thread_db* tdbb = JRD_get_thread_data();
Database::SyncGuard dsGuard(tdbb->getDatabase());
Jrd::Attachment::SyncGuard guard(tdbb->getAttachment());
*return_length = BLB_get_segment(tdbb, blob, buffer, length);
@ -921,11 +921,12 @@ static void invoke(thread_db* tdbb,
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* att = tdbb->getAttachment();
START_CHECK_FOR_EXCEPTIONS(function->fun_exception_message.c_str());
if (function->fun_return_arg)
{
CALL_UDF<void>(dbb, function->fun_entrypoint, args);
CALL_UDF<void>(att, function->fun_entrypoint, args);
result_is_null = return_ptr->fun_mechanism == FUN_descriptor &&
(value->vlu_desc.dsc_flags & DSC_null) ||
return_ptr->fun_mechanism == FUN_blob_struct && return_blob_struct &&
@ -940,7 +941,7 @@ static void invoke(thread_db* tdbb,
case dtype_sql_time:
case dtype_sql_date:
case dtype_long:
value->vlu_misc.vlu_long = CALL_UDF<SLONG>(dbb, function->fun_entrypoint, args);
value->vlu_misc.vlu_long = CALL_UDF<SLONG>(att, function->fun_entrypoint, args);
break;
case dtype_short:
@ -948,7 +949,7 @@ static void invoke(thread_db* tdbb,
// must always be returned as a LONG. See v3.2 release notes
// 1994-September-28 David Schnepper
value->vlu_misc.vlu_short = (SSHORT) CALL_UDF<SLONG>(dbb, function->fun_entrypoint, args);
value->vlu_misc.vlu_short = (SSHORT) CALL_UDF<SLONG>(att, function->fun_entrypoint, args);
break;
case dtype_real:
@ -956,15 +957,15 @@ static void invoke(thread_db* tdbb,
// must always be returned as a DOUBLE. See v3.2 release notes
// 1994-September-28 David Schnepper
value->vlu_misc.vlu_float = (float) CALL_UDF<double>(dbb, function->fun_entrypoint, args);
value->vlu_misc.vlu_float = (float) CALL_UDF<double>(att, function->fun_entrypoint, args);
break;
case dtype_int64:
value->vlu_misc.vlu_int64 = CALL_UDF<SINT64>(dbb, function->fun_entrypoint, args);
value->vlu_misc.vlu_int64 = CALL_UDF<SINT64>(att, function->fun_entrypoint, args);
break;
case dtype_double:
value->vlu_misc.vlu_double = CALL_UDF<double>(dbb, function->fun_entrypoint, args);
value->vlu_misc.vlu_double = CALL_UDF<double>(att, function->fun_entrypoint, args);
break;
case dtype_timestamp:
@ -975,7 +976,7 @@ static void invoke(thread_db* tdbb,
}
else
{
UCHAR* temp_ptr = CALL_UDF<UCHAR*>(dbb, function->fun_entrypoint, args);
UCHAR* temp_ptr = CALL_UDF<UCHAR*>(att, function->fun_entrypoint, args);
if (temp_ptr != NULL)
{

View File

@ -232,6 +232,7 @@ void IDX_create_index(thread_db* tdbb,
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
if (relation->rel_file)
{
@ -308,7 +309,7 @@ void IDX_create_index(thread_db* tdbb,
void* callback_arg = (idx->idx_flags & idx_unique) ? &ifl_data : NULL;
AutoPtr<Sort> scb(FB_NEW(transaction->tra_sorts.getPool())
Sort(dbb, &transaction->tra_sorts, key_length + sizeof(index_sort_record),
Sort(attachment, &transaction->tra_sorts, key_length + sizeof(index_sort_record),
2, 1, key_desc, callback, callback_arg));
jrd_rel* partner_relation = NULL;
@ -328,7 +329,6 @@ void IDX_create_index(thread_db* tdbb,
// Unless this is the only attachment or a database restore, worry about
// preserving the page working sets of other attachments.
Jrd::Attachment* attachment = tdbb->getAttachment();
if (attachment && (attachment != dbb->dbb_attachments || attachment->att_next))
{
if (attachment->att_flags & ATT_gbak_attachment ||
@ -539,7 +539,7 @@ IndexBlock* IDX_create_index_block(thread_db* tdbb, jrd_rel* relation, USHORT id
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
IndexBlock* index_block = FB_NEW(*dbb->dbb_permanent) IndexBlock();
IndexBlock* index_block = FB_NEW(*relation->rel_pool) IndexBlock();
index_block->idb_id = id;
// link the block in with the relation linked list
@ -551,7 +551,7 @@ IndexBlock* IDX_create_index_block(thread_db* tdbb, jrd_rel* relation, USHORT id
// any modification to the index so that the cached information
// about the index will be discarded
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock;
Lock* lock = FB_NEW_RPT(*relation->rel_pool, 0) Lock;
index_block->idb_lock = lock;
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
@ -1491,12 +1491,12 @@ static int index_block_flush(void* ast_object)
Lock* lock = index_block->idb_lock;
Database* dbb = lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(lock->lck_attachment);
Jrd::Attachment::SyncGuard guard(lock->lck_attachment);
release_index_block(tdbb, index_block);
}
catch (const Firebird::Exception&)

View File

@ -587,25 +587,31 @@ void INF_database_info(thread_db* tdbb,
continue;
}
for (const Jrd::Attachment* att = dbb->dbb_attachments; att; att = att->att_next)
{
if (att->att_flags & ATT_shutdown)
continue;
const UserId* user = att->att_user;
if (user)
SyncLockGuard sync(&dbb->dbb_sync, SYNC_SHARED, "INF_database_info");
for (const Jrd::Attachment* att = dbb->dbb_attachments; att; att = att->att_next)
{
const char* user_name = user->usr_user_name.hasData() ?
user->usr_user_name.c_str() : "(Firebird Worker Thread)";
p = buffer;
const SSHORT len = strlen(user_name);
*p++ = len;
memcpy(p, user_name, len);
if (!(info = INF_put_item(item, len + 1, buffer, info, end)))
if (att->att_flags & ATT_shutdown)
continue;
const UserId* user = att->att_user;
if (user)
{
if (transaction)
TRA_commit(tdbb, transaction, false);
return;
const char* user_name = user->usr_user_name.hasData() ?
user->usr_user_name.c_str() : "(Firebird Worker Thread)";
p = buffer;
const SSHORT len = strlen(user_name);
*p++ = len;
memcpy(p, user_name, len);
if (!(info = INF_put_item(item, len + 1, buffer, info, end)))
{
if (transaction)
{
sync.unlock();
TRA_commit(tdbb, transaction, false);
}
return;
}
}
}
}

View File

@ -518,6 +518,9 @@ void INI_init(thread_db* tdbb)
Database* const dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
Jrd::Attachment* attachment = tdbb->getAttachment();
MemoryPool* pool = attachment->att_pool;
const int* fld;
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
{
@ -541,12 +544,12 @@ void INI_init(thread_db* tdbb)
}
}
vec<jrd_fld*>* fields = vec<jrd_fld*>::newVector(*dbb->dbb_permanent, n);
vec<jrd_fld*>* fields = vec<jrd_fld*>::newVector(*pool, n);
relation->rel_fields = fields;
vec<jrd_fld*>::iterator itr = fields->begin();
Format* format = Format::newFormat(*dbb->dbb_permanent, n);
Format* format = Format::newFormat(*pool, n);
relation->rel_current_format = format;
vec<Format*>* formats = vec<Format*>::newVector(*dbb->dbb_permanent, 1);
vec<Format*>* formats = vec<Format*>::newVector(*pool, 1);
relation->rel_formats = formats;
(*formats)[0] = format;
Format::fmt_desc_iterator desc = format->fmt_desc.begin();
@ -575,7 +578,7 @@ void INI_init(thread_db* tdbb)
if (desc->dsc_dtype == dtype_blob && desc->dsc_sub_type == isc_blob_text)
desc->dsc_scale = CS_METADATA; // blob charset
jrd_fld* field = FB_NEW(*dbb->dbb_permanent) jrd_fld(*dbb->dbb_permanent);
jrd_fld* field = FB_NEW(*pool) jrd_fld(*pool);
*itr = field;
field->fld_name = names[fld[RFLD_F_NAME]];
}
@ -602,7 +605,7 @@ void INI_init2(thread_db* tdbb)
const USHORT major_version = dbb->dbb_ods_version;
const USHORT minor_version = dbb->dbb_minor_version;
vec<jrd_rel*>* vector = dbb->dbb_relations;
vec<jrd_rel*>* vector = tdbb->getAttachment()->att_relations;
const int* fld;
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)

View File

@ -207,16 +207,17 @@ CharSetContainer* CharSetContainer::lookupCharset(thread_db* tdbb, USHORT ttype)
CharSetContainer* cs = NULL;
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
fb_assert(attachment);
USHORT id = TTYPE_TO_CHARSET(ttype);
if (id == CS_dynamic)
id = tdbb->getCharSet();
if (id >= dbb->dbb_charsets.getCount())
dbb->dbb_charsets.resize(id + 10);
if (id >= attachment->att_charsets.getCount())
attachment->att_charsets.resize(id + 10);
else
cs = dbb->dbb_charsets[id];
cs = attachment->att_charsets[id];
// allocate a new character set object if we couldn't find one.
if (!cs)
@ -225,8 +226,8 @@ CharSetContainer* CharSetContainer::lookupCharset(thread_db* tdbb, USHORT ttype)
if (lookupInternalCharSet(id, &info) || MET_get_char_coll_subtype_info(tdbb, id, &info))
{
dbb->dbb_charsets[id] = cs =
FB_NEW(*dbb->dbb_permanent) CharSetContainer(*dbb->dbb_permanent, id, &info);
attachment->att_charsets[id] = cs =
FB_NEW(*attachment->att_pool) CharSetContainer(*attachment->att_pool, id, &info);
}
else
ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(ttype));
@ -347,8 +348,8 @@ Collation* CharSetContainer::lookupCollation(thread_db* tdbb, USHORT tt_id)
return charset_collations[id];
}
Database* dbb = tdbb->getDatabase();
Database::CheckoutLockGuard guard(dbb, createCollationMtx);
Jrd::Attachment* att = tdbb->getAttachment();
Jrd::Attachment::CheckoutLockGuard guard(att, createCollationMtx); // are we need it ?
Collation* to_delete = NULL;
if (id < charset_collations.getCount() && charset_collations[id] != NULL)
@ -503,26 +504,26 @@ static INTL_BOOL lookup_texttype(texttype* tt, const SubtypeInfo* info)
}
void Database::releaseIntlObjects()
void Jrd::Attachment::releaseIntlObjects()
{
for (size_t i = 0; i < dbb_charsets.getCount(); i++)
for (size_t i = 0; i < att_charsets.getCount(); i++)
{
if (dbb_charsets[i])
if (att_charsets[i])
{
dbb_charsets[i]->release();
att_charsets[i]->release();
}
}
}
void Database::destroyIntlObjects()
void Jrd::Attachment::destroyIntlObjects()
{
for (size_t i = 0; i < dbb_charsets.getCount(); i++)
for (size_t i = 0; i < att_charsets.getCount(); i++)
{
if (dbb_charsets[i])
if (att_charsets[i])
{
dbb_charsets[i]->destroy();
dbb_charsets[i] = NULL;
att_charsets[i]->destroy();
att_charsets[i] = NULL;
}
}
}
@ -1390,13 +1391,13 @@ static int blocking_ast_collation(void* ast_object)
try
{
Database* dbb = tt->existenceLock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = tt->existenceLock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(tt->existenceLock->lck_attachment);
tdbb->setAttachment(att);
Jrd::Attachment::SyncGuard guard(att);
Jrd::ContextPoolHolder context(tdbb, 0);
tt->obsolete = true;

View File

@ -104,6 +104,7 @@
#include "../jrd/sdw_proto.h"
#include "../jrd/shut_proto.h"
#include "../jrd/thread_proto.h"
#include "../jrd/tpc_proto.h"
#include "../jrd/tra_proto.h"
#include "../jrd/val_proto.h"
#include "../jrd/vio_proto.h"
@ -434,12 +435,12 @@ namespace
{
public:
AttachmentHolder(thread_db* tdbb, JAttachment* ja, bool lockAsync)
: mutex(ja->getMutex(lockAsync))
: mutex(ja->getMutex(lockAsync)),
attachment(ja->getHandle()),
async(lockAsync)
{
mutex->enter();
Jrd::Attachment* attachment = ja->getHandle();
try
{
if (!attachment || engineShuttingDown)
@ -447,6 +448,10 @@ namespace
tdbb->setAttachment(attachment);
tdbb->setDatabase(attachment->att_database);
if (!lockAsync)
{
attachment->att_use_count++;
}
}
catch (const Firebird::Exception&)
{
@ -457,11 +462,17 @@ namespace
~AttachmentHolder()
{
if (!async)
{
attachment->att_use_count--;
}
mutex->leave();
}
private:
Firebird::Mutex* mutex;
bool async;
Jrd::Attachment* attachment;
private:
// copying is prohibited
@ -469,12 +480,11 @@ namespace
AttachmentHolder& operator =(const AttachmentHolder&);
};
class DatabaseContextHolder : private Database::SyncGuard, public Jrd::ContextPoolHolder
class DatabaseContextHolder : public Jrd::ContextPoolHolder
{
public:
DatabaseContextHolder(thread_db* tdbb)
: Database::SyncGuard(tdbb->getDatabase()),
Jrd::ContextPoolHolder(tdbb, tdbb->getDatabase()->dbb_permanent),
: Jrd::ContextPoolHolder(tdbb, tdbb->getDatabase()->dbb_permanent),
savedTdbb(tdbb)
{
Database* dbb = tdbb->getDatabase();
@ -539,19 +549,18 @@ void Trigger::compile(thread_db* tdbb)
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
if (engine.isEmpty() && !extTrigger)
{
if (!statement /*&& !compile_in_progress*/)
{
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
if (statement)
return;
compile_in_progress = true;
// Allocate statement memory pool
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = att->createPool();
// Trigger request is not compiled yet. Lets do it now
USHORT par_flags = (USHORT) (flags & TRG_ignore_perm) ? csb_ignore_perm : 0;
if (type & 1)
@ -586,7 +595,7 @@ void Trigger::compile(thread_db* tdbb)
statement = NULL;
}
else {
dbb->deletePool(new_pool);
att->deletePool(new_pool);
}
throw;
@ -817,7 +826,7 @@ static void cancel_attachments(thread_db* tdbb)
{
if ( !(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use | DBB_security_db)) )
{
Database::SyncGuard dsGuard(dbb);
SyncLockGuard guard(&dbb->dbb_sync, SYNC_EXCLUSIVE, "cancel_attachments");
Jrd::Attachment* lockedAtt = NULL;
Jrd::Attachment* att = dbb->dbb_attachments;
@ -827,36 +836,51 @@ static void cancel_attachments(thread_db* tdbb)
// deleted while waiting for lock.
RefPtr<JAttachment> jAtt(att->att_interface);
MutexLockGuard asyncGuard(*(jAtt->getMutex(true)));
att->att_flags |= ATT_shutdown;
while (true)
{
if (att->att_interface->getMutex()->tryEnter() || (att->att_flags & ATT_purge_error))
if (att->att_interface->getMutex()->tryEnter())
{
if (att->att_use_count)
{
att->att_interface->getMutex()->leave();
}
else
{
jAtt->cancel();
lockedAtt = att;
break;
}
}
if (att->att_flags & ATT_purge_error)
{
lockedAtt = att;
break;
}
{ // scope
const bool cancel_disable = (att->att_flags & ATT_cancel_disable);
Database::Checkout dcoHolder(dbb);
if (!cancel_disable)
{
ThreadStatusGuard temp_status(tdbb);
JRD_cancel_operation(tdbb, att, fb_cancel_enable);
JRD_cancel_operation(tdbb, att, fb_cancel_raise);
}
THREAD_YIELD();
THREAD_YIELD();
} // end scope
//{ // scope
// const bool cancel_disable = (att->att_flags & ATT_cancel_disable);
// SyncUnlockGuard cout(guard);
// if (!cancel_disable)
// {
// ThreadStatusGuard temp_status(tdbb);
// JRD_cancel_operation(tdbb, att, fb_cancel_enable);
// JRD_cancel_operation(tdbb, att, fb_cancel_raise);
// }
// THREAD_YIELD();
//} // end scope
// check if attachment still exist
if (lockedAtt && lockedAtt->att_next != att) {
break;
}
if (dbb->dbb_attachments != att) {
if (!lockedAtt && dbb->dbb_attachments != att) {
break;
}
}
jAtt->cancel();
}
att = lockedAtt ? lockedAtt->att_next : dbb->dbb_attachments;
}
}
@ -1170,6 +1194,8 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
dbb = init(tdbb, expanded_name, config, true);
fb_assert(dbb);
Sync dbbGuard(&dbb->dbb_sync, "attachDatabase");
dbbGuard.lock(SYNC_EXCLUSIVE);
tdbb->setDatabase(dbb);
DatabaseContextHolder dbbHolder(tdbb);
@ -1217,6 +1243,12 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
}
attachment = Jrd::Attachment::create(dbb);
RefPtr<JAttachment> jAtt(new JAttachment(attachment));
jAtt->addRef();
attachment->att_interface = jAtt;
MutexLockGuard guard(*(jAtt->getMutex()));
tdbb->setAttachment(attachment);
attachment->att_filename = is_alias ? file_name : expanded_name;
attachment->att_network_protocol = options.dpb_network_protocol;
@ -1255,13 +1287,16 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
if (dbb->dbb_filename.empty())
{
#if defined(DEV_BUILD) && defined(SHARED_METADATA_CACHE)
#if defined(DEV_BUILD)
// make sure we do not reopen same DB twice
for (Database* d = databases; d; d = d->dbb_next)
if (config->getSharedCache())
{
if (d->dbb_filename == expanded_name)
for (Database* d = databases; d; d = d->dbb_next)
{
fatal_exception::raise(("Attempt to reopen " + expanded_name).c_str());
if (d->dbb_filename == expanded_name)
{
fatal_exception::raise(("Attempt to reopen " + expanded_name).c_str());
}
}
}
#endif
@ -1313,7 +1348,9 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
}
options.setBuffers(dbb->dbb_config);
CCH_init(tdbb, options.dpb_buffers);
CCH_init(tdbb, options.dpb_buffers, config->getSharedCache() && !config->getSharedDatabase());
dbb->dbb_tip_cache = FB_NEW(*dbb->dbb_permanent) TipCache(dbb);
// Initialize backup difference subsystem. This must be done before WAL and shadowing
// is enabled because nbackup it is a lower level subsystem
@ -1338,6 +1375,10 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
LCK_init(tdbb, LCK_OWNER_attachment);
attachment->att_flags |= ATT_lck_init_done;
INI_init(tdbb);
INI_init2(tdbb);
PAG_header(tdbb, true);
}
// Attachments to a ReadOnly database need NOT do garbage collection
@ -1471,6 +1512,7 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
attachment_succeeded = CCH_exclusive_attachment(tdbb, LCK_none, -1);
else
CCH_exclusive_attachment(tdbb, LCK_none, LCK_WAIT);
if (attachment->att_flags & ATT_shutdown)
{
if (dbb->dbb_ast_flags & DBB_shutdown) {
@ -1651,11 +1693,6 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
// Recover database after crash during backup difference file merge
dbb->dbb_backup_manager->endBackup(tdbb, true); // true = do recovery
RefPtr<JAttachment> jAtt(new JAttachment(attachment));
attachment->att_interface = jAtt;
MutexLockGuard guard(*(jAtt->getMutex()));
if (attachment->att_trace_manager->needs(TRACE_EVENT_ATTACH))
{
TraceConnectionImpl conn(attachment);
@ -1679,7 +1716,7 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
// load DDL triggers
MET_load_ddl_triggers(tdbb);
const trig_vec* trig_connect = dbb->dbb_triggers[DB_TRIGGER_CONNECT];
const trig_vec* trig_connect = attachment->att_triggers[DB_TRIGGER_CONNECT];
if (trig_connect && !trig_connect->isEmpty())
{
// Start a transaction to execute ON CONNECT triggers.
@ -1707,7 +1744,6 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
// guardDatabases.leave();
jAtt->addRef();
return jAtt;
} // try
catch (const Exception& ex)
@ -1717,6 +1753,9 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
trace_failed_attach(attachment ? attachment->att_trace_manager : NULL,
filename, options, false, no_priv);
dbb->dbb_sync.lock(NULL, SYNC_EXCLUSIVE);
dbbGuard.unlock();
attachment->att_interface = NULL;
unwindAttach(tdbb, ex, user_status, attachment, dbb);
}
}
@ -2249,6 +2288,8 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
dbb = init(tdbb, expanded_name, config, false);
fb_assert(dbb);
Sync dbbGuard(&dbb->dbb_sync, "createDatabase");
dbbGuard.lock(SYNC_EXCLUSIVE);
tdbb->setDatabase(dbb);
DatabaseContextHolder dbbHolder(tdbb);
@ -2267,6 +2308,12 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
}
attachment = Jrd::Attachment::create(dbb);
RefPtr<JAttachment> jAtt(new JAttachment(attachment));
jAtt->addRef();
attachment->att_interface = jAtt;
MutexLockGuard guard(*(jAtt->getMutex()));
tdbb->setAttachment(attachment);
attachment->att_filename = is_alias ? file_name : expanded_name;
attachment->att_network_protocol = options.dpb_network_protocol;
@ -2396,15 +2443,15 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
if (options.dpb_set_page_buffers)
dbb->dbb_page_buffers = options.dpb_page_buffers;
options.setBuffers(dbb->dbb_config);
CCH_init(tdbb, options.dpb_buffers, config->getSharedCache() && !config->getSharedDatabase());
#ifdef WIN_NT
dbb->dbb_filename.assign(first_dbb_file->fil_string);
#else
dbb->dbb_filename = expanded_name;
#endif
options.setBuffers(dbb->dbb_config);
CCH_init(tdbb, options.dpb_buffers);
// NS: Use alias as database ID only if accessing database using file name is not possible.
//
// This way we:
@ -2416,6 +2463,8 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
else
dbb->dbb_database_name = dbb->dbb_filename;
dbb->dbb_tip_cache = FB_NEW(*dbb->dbb_permanent) TipCache(dbb);
// Initialize backup difference subsystem. This must be done before WAL and shadowing
// is enabled because nbackup it is a lower level subsystem
dbb->dbb_backup_manager = FB_NEW(*dbb->dbb_permanent) BackupManager(tdbb, dbb, nbak_state_normal);
@ -2460,16 +2509,16 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
VIO_init(tdbb);
#endif
if (options.dpb_set_db_readonly)
{
if (!CCH_exclusive (tdbb, LCK_EX, WAIT_PERIOD))
{
ERR_post(Arg::Gds(isc_lock_timeout) <<
if (options.dpb_set_db_readonly)
{
if (!CCH_exclusive (tdbb, LCK_EX, WAIT_PERIOD))
{
ERR_post(Arg::Gds(isc_lock_timeout) <<
Arg::Gds(isc_obj_in_use) << Arg::Str(file_name));
}
PAG_set_db_readonly(tdbb, options.dpb_db_readonly);
}
PAG_set_db_readonly(tdbb, options.dpb_db_readonly);
}
PAG_attachment_id(tdbb);
@ -2492,10 +2541,6 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
guardDatabases.leave();
JAttachment* jAtt = new JAttachment(attachment);
jAtt->addRef();
attachment->att_interface = jAtt;
return jAtt;
} // try
catch (const Exception& ex)
@ -2505,6 +2550,10 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
trace_failed_attach(attachment ? attachment->att_trace_manager : NULL,
filename, options, true, no_priv);
dbb->dbb_sync.lock(NULL, SYNC_EXCLUSIVE);
dbbGuard.unlock();
attachment->att_interface = NULL;
unwindAttach(tdbb, ex, user_status, attachment, dbb);
}
}
@ -2616,15 +2665,25 @@ void JAttachment::freeEngineData(IStatus* user_status)
JRD_cancel_operation(tdbb, getHandle(), fb_cancel_raise);
MutexLockGuard guard(*getMutex());
{
while (att->att_use_count)
{
MutexUnlockGuard cout(*getMutex());
THD_sleep(10);
}
}
Database* dbb = tdbb->getDatabase();
// if this is the last attachment, mark dbb as not in use
if (dbb->dbb_attachments == getHandle() && !getHandle()->att_next &&
!(dbb->dbb_flags & DBB_being_opened))
{
dbb->dbb_flags |= DBB_not_in_use;
SyncLockGuard sync(&dbb->dbb_sync, SYNC_SHARED, "JAttachment::freeEngineData");
if (dbb->dbb_attachments == getHandle() && !getHandle()->att_next &&
!(dbb->dbb_flags & DBB_being_opened))
{
dbb->dbb_flags |= DBB_not_in_use;
}
}
try
@ -3964,12 +4023,13 @@ void JAttachment::transactRequest(IStatus* user_status, ITransaction* tra,
{
Database* const dbb = tdbb->getDatabase();
jrd_tra* const transaction = find_transaction(tdbb, isc_req_wrong_db);
Jrd::Attachment* const att = transaction->tra_attachment;
const MessageNode* inMessage = NULL;
const MessageNode* outMessage = NULL;
jrd_req* request = NULL;
MemoryPool* new_pool = dbb->createPool();
MemoryPool* new_pool = att->createPool();
try
{
@ -3999,7 +4059,7 @@ void JAttachment::transactRequest(IStatus* user_status, ITransaction* tra,
if (request)
CMP_release(tdbb, request);
else
dbb->deletePool(new_pool);
att->deletePool(new_pool);
throw;
}
@ -4759,10 +4819,11 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
*
**************************************/
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* att= tdbb->getAttachment();
if (dbb->dbb_sync->hasContention())
//if (dbb->dbb_sync->hasContention())
{
Database::Checkout dcoHolder(dbb);
Jrd::Attachment::Checkout cout(att);
THREAD_YIELD();
}
@ -4789,19 +4850,22 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
}
// Enable signal handler for the monitoring stuff
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
dbb->dbb_ast_flags &= ~DBB_monitor_off;
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
// While waiting for return from LCK_lock call above, the blocking AST (see
// DatabaseSnapshot::blockingAst) was called and set DBB_monitor_off flag
// again. But it do not released lock as lck_id was unknown at that moment.
// Do it now to not block another process waiting for a monitoring lock.
SyncLockGuard monGuard(&dbb->dbb_mon_sync, SYNC_EXCLUSIVE, "JRD_reschedule");
if (dbb->dbb_ast_flags & DBB_monitor_off)
LCK_release(tdbb, dbb->dbb_monitor_lock);
{
dbb->dbb_ast_flags &= ~DBB_monitor_off;
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
// While waiting for return from LCK_lock call above, the blocking AST (see
// DatabaseSnapshot::blockingAst) was called and set DBB_monitor_off flag
// again. But it do not released lock as lck_id was unknown at that moment.
// Do it now to not block another process waiting for a monitoring lock.
if (dbb->dbb_ast_flags & DBB_monitor_off)
LCK_release(tdbb, dbb->dbb_monitor_lock);
}
}
tdbb->tdbb_quantum = (tdbb->tdbb_quantum <= 0) ?
@ -4863,12 +4927,21 @@ static void check_database(thread_db* tdbb)
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
const Jrd::Attachment* attach = dbb->dbb_attachments;
while (attach && attach != attachment)
attach = attach->att_next;
if (!attach)
status_exception::raise(Arg::Gds(isc_bad_db_handle));
// hvlad: i think the check below is unnecessary as attachment pointer is
// already validated at AttachmentHolder. If i'm wrong and check is must be
// then it should be moved into AttachmentHolder or even into
// DatabaseContexHolder to not lock dbb_sync with attachment mutex locked.
//
//{
// SyncLockGuard dbbGuard(&dbb->dbb_sync, SYNC_SHARED, "check_database");
//
// const Jrd::Attachment* attach = dbb->dbb_attachments;
// while (attach && attach != attachment)
// attach = attach->att_next;
//
// if (!attach)
// status_exception::raise(Arg::Gds(isc_bad_db_handle));
//}
if (dbb->dbb_flags & DBB_bugcheck)
{
@ -4902,11 +4975,15 @@ static void check_database(thread_db* tdbb)
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
dbb->dbb_ast_flags &= ~DBB_monitor_off;
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
SyncLockGuard monGuard(&dbb->dbb_mon_sync, SYNC_EXCLUSIVE, "check_database");
if (dbb->dbb_ast_flags & DBB_monitor_off)
LCK_release(tdbb, dbb->dbb_monitor_lock);
{
dbb->dbb_ast_flags &= ~DBB_monitor_off;
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
if (dbb->dbb_ast_flags & DBB_monitor_off)
LCK_release(tdbb, dbb->dbb_monitor_lock);
}
}
}
@ -5146,6 +5223,8 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
ERR_post(Arg::Gds(isc_bad_dpb_content));
}
}
else
rdr.getInt();
break;
case isc_dpb_page_size:
@ -5497,27 +5576,26 @@ static Database* init(thread_db* tdbb,
// Check to see if the database is already actively attached
#ifdef SHARED_METADATA_CACHE
for (dbb = databases; dbb; dbb = dbb->dbb_next)
if (config->getSharedCache())
{
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use)) &&
(dbb->dbb_filename == expanded_filename))
for (dbb = databases; dbb; dbb = dbb->dbb_next)
{
if (attach_flag)
return dbb;
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use)) &&
(dbb->dbb_filename == expanded_filename))
{
if (attach_flag)
return dbb;
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_obj_in_use) << Arg::Str("DATABASE"));
ERR_post(Arg::Gds(isc_no_meta_update) <<
Arg::Gds(isc_obj_in_use) << Arg::Str("DATABASE"));
}
}
}
#endif
dbb = Database::create();
dbb->dbb_config = config;
tdbb->setDatabase(dbb);
dbb->dbb_bufferpool = dbb->createPool();
// provide context pool for the rest stuff
Jrd::ContextPoolHolder context(tdbb, dbb->dbb_permanent);
@ -5705,9 +5783,9 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
dbb->dbb_extManager.closeAttachment(tdbb, attachment);
if (dbb->dbb_config->getSharedCache() && dbb->dbb_relations)
if (!dbb->dbb_config->getSharedDatabase() && attachment->att_relations)
{
vec<jrd_rel*>& rels = *dbb->dbb_relations;
vec<jrd_rel*>& rels = *attachment->att_relations;
for (size_t i = 1; i < rels.count(); i++)
{
jrd_rel* relation = rels[i];
@ -5724,6 +5802,8 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
dbb->dbb_event_mgr->deleteSession(attachment->att_event_session);
}
attachment->shutdown(tdbb);
if (attachment->att_id_lock)
LCK_release(tdbb, attachment->att_id_lock);
@ -5764,7 +5844,7 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
{
MemoryPool* const pool = &attachment->att_dsql_instance->dbb_pool;
delete attachment->att_dsql_instance;
dbb->deletePool(pool);
attachment->deletePool(pool);
}
// remove the attachment block from the dbb linked list
@ -5781,8 +5861,8 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
// CMP_release() changes att_requests.
while (!attachment->att_requests.isEmpty())
CMP_release(tdbb, attachment->att_requests.back());
for (JrdStatement** i = dbb->dbb_internal.begin(); i != dbb->dbb_internal.end(); ++i)
/**
for (JrdStatement** i = attachment->att_internal.begin(); i != attachment->att_internal.end(); ++i)
{
if (*i)
{
@ -5790,13 +5870,16 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
for (jrd_req** j = stmt->requests.begin(); j != stmt->requests.end(); ++j)
{
if (*j && (*j)->req_attachment == attachment)
if (*j)
{
fb_assert(!(*j)->req_attachment || (*j)->req_attachment == attachment);
EXE_release(tdbb, *j);
}
}
}
}
for (JrdStatement** i = dbb->dbb_dyn_req.begin(); i != dbb->dbb_dyn_req.end(); ++i)
for (JrdStatement** i = attachment->att_dyn_req.begin(); i != attachment->att_dyn_req.end(); ++i)
{
if (*i)
{
@ -5804,8 +5887,43 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
for (jrd_req** j = stmt->requests.begin(); j != stmt->requests.end(); ++j)
{
if (*j && (*j)->req_attachment == attachment)
if (*j)
{
fb_assert(!(*j)->req_attachment || (*j)->req_attachment == attachment);
EXE_release(tdbb, *j);
}
}
}
}
**/
MET_clear_cache(tdbb);
// Shut down any extern relations
if (attachment->att_relations)
{
vec<jrd_rel*>* vector = attachment->att_relations;
vec<jrd_rel*>::iterator ptr = vector->begin(), end = vector->end();
while (ptr < end)
{
jrd_rel* relation = *ptr++;
if (relation)
{
if (relation->rel_file)
{
EXT_fini(relation, false);
}
for (IndexBlock* index_block = relation->rel_index_blocks; index_block;
index_block = index_block->idb_next)
{
if (index_block->idb_lock)
LCK_release(tdbb, index_block->idb_lock);
}
delete relation;
}
}
}
@ -5917,8 +6035,6 @@ static void shutdown_database(Database* dbb, const bool release_pools)
TRA_header_write(tdbb, dbb, 0L); // Update transaction info on header page.
#endif
MET_clear_cache(tdbb);
#ifdef GARBAGE_THREAD
VIO_fini(tdbb);
#endif
@ -5938,36 +6054,6 @@ static void shutdown_database(Database* dbb, const bool release_pools)
LCK_release(tdbb, dbb->dbb_retaining_lock);
dbb->dbb_shared_counter.shutdown(tdbb);
dbb->destroyIntlObjects();
// Shut down any extern relations
if (dbb->dbb_relations)
{
vec<jrd_rel*>* vector = dbb->dbb_relations;
vec<jrd_rel*>::iterator ptr = vector->begin(), end = vector->end();
while (ptr < end)
{
jrd_rel* relation = *ptr++;
if (relation)
{
if (relation->rel_file)
{
EXT_fini(relation, false);
}
for (IndexBlock* index_block = relation->rel_index_blocks; index_block;
index_block = index_block->idb_next)
{
if (index_block->idb_lock)
LCK_release(tdbb, index_block->idb_lock);
}
delete relation;
}
}
}
if (dbb->dbb_lock)
LCK_release(tdbb, dbb->dbb_lock);
@ -6138,7 +6224,7 @@ UCHAR* JRD_num_attachments(UCHAR* const buf, USHORT buf_len, JRD_info_tag flag,
for (Database* dbb = databases; dbb; dbb = dbb->dbb_next)
{
Database::SyncGuard dsGuard(dbb);
SyncLockGuard guard(&dbb->dbb_sync, SYNC_SHARED, "JRD_num_attachments");
#ifdef WIN_NT
// Get drive letters for db files
@ -6420,7 +6506,7 @@ static void purge_attachment(thread_db* tdbb, Jrd::Attachment* attachment, const
{
try
{
const trig_vec* trig_disconnect = dbb->dbb_triggers[DB_TRIGGER_DISCONNECT];
const trig_vec* trig_disconnect = attachment->att_triggers[DB_TRIGGER_DISCONNECT];
if (!(attachment->att_flags & ATT_no_db_triggers) &&
!(attachment->att_flags & ATT_shutdown) &&
trig_disconnect && !trig_disconnect->isEmpty())
@ -7173,8 +7259,7 @@ static void start_transaction(thread_db* tdbb, bool transliterate, jrd_tra** tra
transliterateException(tdbb, ex, &tempStatus);
status_exception::raise(tempStatus.get());
}
else
throw;
throw;
}
}
catch (const Exception&)
@ -7326,7 +7411,7 @@ namespace
#endif
void JRD_shutdown_attachments(const Database* dbb)
void JRD_shutdown_attachments(Database* dbb)
{
/**************************************
*
@ -7346,6 +7431,10 @@ void JRD_shutdown_attachments(const Database* dbb)
MemoryPool& pool = *getDefaultMemoryPool();
PingQueue* const queue = FB_NEW(pool) PingQueue(pool);
Sync guard(&dbb->dbb_sync, "JRD_shutdown_attachments");
if (!dbb->dbb_sync.ourExclusiveLock())
guard.lock(SYNC_SHARED);
for (const Jrd::Attachment* attachment = dbb->dbb_attachments;
attachment; attachment = attachment->att_next)
{

View File

@ -48,6 +48,7 @@
#include "../common/classes/stack.h"
#include "../common/classes/timestamp.h"
#include "../common/classes/GenericMap.h"
#include "../common/classes/Synchronize.h"
#include "../common/utils_proto.h"
#include "../common/StatusHolder.h"
#include "../jrd/RandomGenerator.h"
@ -123,7 +124,7 @@ class JrdStatement;
class Lock;
class jrd_file;
class Format;
class BufferControl;
class BufferDesc;
class SparseBitmap;
class jrd_rel;
class ExternalFile;
@ -179,7 +180,6 @@ public:
};
//
// Flags to indicate normal internal requests vs. dyn internal requests
//
@ -407,7 +407,8 @@ private:
public:
explicit thread_db(ISC_STATUS* status)
: ThreadData(ThreadData::tddDBB)
: ThreadData(ThreadData::tddDBB),
tdbb_bdbs(*getDefaultMemoryPool())
{
tdbb_default = NULL;
database = NULL;
@ -417,19 +418,33 @@ public:
tdbb_quantum = QUANTUM;
tdbb_flags = 0;
tdbb_temp_traid = 0;
QUE_INIT(tdbb_latches);
reqStat = traStat = attStat = dbbStat = RuntimeStatistics::getDummy();
tdbb_status_vector = status;
fb_utils::init_status(tdbb_status_vector);
tdbb_thread = Firebird::ThreadSync::getThread("thread_db");
}
~thread_db()
{
#ifdef DEV_BUILD
for (size_t n = 0; n < tdbb_bdbs.getCount(); n++)
{
fb_assert(tdbb_bdbs[n] == NULL);
}
#endif
}
ISC_STATUS* tdbb_status_vector;
SSHORT tdbb_quantum; // Cycles remaining until voluntary schedule
USHORT tdbb_flags;
SLONG tdbb_temp_traid; // current temporary table scope
que tdbb_latches; // shared latches held by thread
// BDB's held by thread
Firebird::HalfStaticArray<BufferDesc*, 16> tdbb_bdbs;
Firebird::ThreadSync* tdbb_thread;
MemoryPool* getDefaultPool()
{
@ -507,6 +522,44 @@ public:
}
bool checkCancelState(bool punt);
void registerBdb(BufferDesc* bdb)
{
size_t pos;
if (tdbb_bdbs.find(NULL, pos))
tdbb_bdbs[pos] = bdb;
else
tdbb_bdbs.add(bdb);
}
void clearBdb(BufferDesc* bdb)
{
size_t pos;
if (tdbb_bdbs.find(bdb, pos))
{
tdbb_bdbs[pos] = NULL;
if (pos == tdbb_bdbs.getCount() - 1)
{
while (true)
{
if (tdbb_bdbs[pos] != NULL)
{
tdbb_bdbs.shrink(pos + 1);
break;
}
if (pos == 0)
{
tdbb_bdbs.shrink(0);
break;
}
pos--;
}
}
}
else
fb_assert(false);
}
};
// tdbb_flags

View File

@ -86,6 +86,6 @@ void JRD_compile(Jrd::thread_db* tdbb, Jrd::Attachment* attachment, Jrd::jrd_req
ULONG blr_length, const UCHAR* blr, Firebird::RefStrPtr,
ULONG dbginfo_length, const UCHAR* dbginfo, bool isInternalRequest);
bool JRD_verify_database_access(const Firebird::PathName&);
void JRD_shutdown_attachments(const Jrd::Database* dbb);
void JRD_shutdown_attachments(Jrd::Database* dbb);
void JRD_cancel_operation(Jrd::thread_db* tdbb, Jrd::Attachment* attachment, int option);
#endif /* JRD_JRD_PROTO_H */

View File

@ -74,6 +74,26 @@ static bool internal_enqueue(thread_db*, Arg::StatusVector&, Lock*, USHORT, SSHO
static void set_lock_attachment(Lock*, Jrd::Attachment*);
#ifdef DEBUG_LCK
class LckSync
{
public:
LckSync(Lock* lock, const char* sWhere) :
m_sync(&lock->lck_sync, sWhere)
{
ThreadSync *thd = ThreadSync::getThread(NULL);
m_sync.lock(SYNC_EXCLUSIVE);
}
~LckSync()
{
}
private:
Sync m_sync;
};
#endif
// globals and macros
inline LOCK_OWNER_T LCK_OWNER_ID_DBB(thread_db* tdbb)
@ -83,11 +103,10 @@ inline LOCK_OWNER_T LCK_OWNER_ID_DBB(thread_db* tdbb)
inline LOCK_OWNER_T LCK_OWNER_ID_ATT(thread_db* tdbb)
{
#ifdef SHARED_METADATA_CACHE
return (LOCK_OWNER_T) getpid() << 32 | tdbb->getAttachment()->att_lock_owner_id;
#else
return (LOCK_OWNER_T) getpid() << 32 | tdbb->getDatabase()->dbb_lock_owner_id;
#endif
if (tdbb->getDatabase()->dbb_config->getSharedCache())
return (LOCK_OWNER_T) getpid() << 32 | tdbb->getAttachment()->att_lock_owner_id;
else
return (LOCK_OWNER_T) getpid() << 32 | tdbb->getDatabase()->dbb_lock_owner_id;
}
inline SLONG* LCK_OWNER_HANDLE_DBB(thread_db* tdbb)
@ -97,11 +116,10 @@ inline SLONG* LCK_OWNER_HANDLE_DBB(thread_db* tdbb)
inline SLONG* LCK_OWNER_HANDLE_ATT(thread_db* tdbb)
{
#ifdef SHARED_METADATA_CACHE
return &tdbb->getAttachment()->att_lock_owner_handle;
#else
return &tdbb->getDatabase()->dbb_lock_owner_handle;
#endif
if (tdbb->getDatabase()->dbb_config->getSharedCache())
return &tdbb->getAttachment()->att_lock_owner_handle;
else
return &tdbb->getDatabase()->dbb_lock_owner_handle;
}
@ -134,10 +152,11 @@ inline void ENQUEUE(thread_db* tdbb, Arg::StatusVector& statusVector, Lock* lock
inline bool CONVERT(thread_db* tdbb, Arg::StatusVector& statusVector, Lock* lock, USHORT level, SSHORT wait)
{
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
return lock->lck_compatible ?
internal_enqueue(tdbb, statusVector, lock, level, wait, true) :
dbb->dbb_lock_mgr->convert(dbb, statusVector, lock->lck_id, level, wait, lock->lck_ast,
dbb->dbb_lock_mgr->convert(att, statusVector, lock->lck_id, level, wait, lock->lck_ast,
lock->lck_object);
}
@ -154,12 +173,13 @@ inline void DEQUEUE(thread_db* tdbb, Lock* lock)
inline USHORT DOWNGRADE(thread_db* tdbb, Lock* lock)
{
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
Arg::StatusVector statusVector;
USHORT ret = lock->lck_compatible ?
internal_downgrade(tdbb, statusVector, lock) :
dbb->dbb_lock_mgr->downgrade(dbb, statusVector, lock->lck_id);
dbb->dbb_lock_mgr->downgrade(att, statusVector, lock->lck_id);
fb_assert(statusVector.isEmpty());
@ -192,7 +212,7 @@ inline bool checkLock(const Lock* l)
/* The following check should be part of LCK_CHECK_LOCK, but it fails
when the exclusive attachment to a database is changed to a shared
attachment. When that occurs we fb_assert all our internal locks, but
attachment. When that occurs we assert all our internal locks, but
while we are in the process of asserting DBB_assert_locks is set, but
we haven't gotten physical locks yet.
@ -221,7 +241,7 @@ public:
m_save_lock(NULL)
{
Jrd::Attachment* att = m_tdbb->getAttachment();
m_save_lock = att->att_wait_lock;
m_save_lock = att ? att->att_wait_lock : NULL;
m_cancel_disabled = (m_tdbb->tdbb_flags & TDBB_wait_cancel_disable);
m_tdbb->tdbb_flags |= TDBB_wait_cancel_disable;
@ -231,15 +251,23 @@ public:
if (lock->lck_type == LCK_tra)
{
fb_assert(att);
m_tdbb->tdbb_flags &= ~TDBB_wait_cancel_disable;
att->att_wait_lock = lock;
if (att)
{
att->att_wait_lock = lock;
}
}
}
~WaitCancelGuard()
{
Jrd::Attachment* att = m_tdbb->getAttachment();
att->att_wait_lock = m_save_lock;
if (att)
{
att->att_wait_lock = m_save_lock;
}
if (m_cancel_disabled)
m_tdbb->tdbb_flags |= TDBB_wait_cancel_disable;
@ -298,6 +326,10 @@ bool LCK_convert(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
SET_TDBB(tdbb);
fb_assert(LCK_CHECK_LOCK(lock));
#ifdef DEBUG_LCK
LckSync sync(lock, "LCK_convert");
#endif
Database* dbb = lock->lck_dbb;
Jrd::Attachment* const old_attachment = lock->lck_attachment;
@ -305,6 +337,7 @@ bool LCK_convert(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
WaitCancelGuard guard(tdbb, lock, wait);
Arg::StatusVector statusVector;
const bool result = CONVERT(tdbb, statusVector, lock, level, wait);
if (!result)
@ -401,6 +434,10 @@ void LCK_downgrade(thread_db* tdbb, Lock* lock)
SET_TDBB(tdbb);
fb_assert(LCK_CHECK_LOCK(lock));
#ifdef DEBUG_LCK
LckSync sync(lock, "LCK_downgrade");
#endif
if (lock->lck_id && lock->lck_physical != LCK_none)
{
const USHORT level = DOWNGRADE(tdbb, lock);
@ -434,6 +471,7 @@ void LCK_fini(thread_db* tdbb, enum lck_owner_t owner_type)
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
switch (owner_type)
{
@ -450,7 +488,7 @@ void LCK_fini(thread_db* tdbb, enum lck_owner_t owner_type)
break;
}
dbb->dbb_lock_mgr->shutdownOwner(dbb, owner_handle_ptr);
dbb->dbb_lock_mgr->shutdownOwner(att, owner_handle_ptr);
}
@ -607,6 +645,10 @@ bool LCK_lock(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
SET_TDBB(tdbb);
fb_assert(LCK_CHECK_LOCK(lock));
#ifdef DEBUG_LCK
LckSync sync(lock, "LCK_lock");
#endif
Database* dbb = lock->lck_dbb;
set_lock_attachment(lock, tdbb->getAttachment());
@ -615,6 +657,7 @@ bool LCK_lock(thread_db* tdbb, Lock* lock, USHORT level, SSHORT wait)
ENQUEUE(tdbb, statusVector, lock, level, wait);
fb_assert(LCK_CHECK_LOCK(lock));
if (!lock->lck_id)
{
set_lock_attachment(lock, NULL);
@ -752,6 +795,10 @@ void LCK_release(thread_db* tdbb, Lock* lock)
SET_TDBB(tdbb);
fb_assert(LCK_CHECK_LOCK(lock));
#ifdef DEBUG_LCK
LckSync sync(lock, "LCK_release");
#endif
if (lock->lck_physical != LCK_none) {
DEQUEUE(tdbb, lock);
}
@ -779,6 +826,7 @@ void LCK_re_post(thread_db* tdbb, Lock* lock)
**************************************/
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
fb_assert(LCK_CHECK_LOCK(lock));
@ -790,7 +838,7 @@ void LCK_re_post(thread_db* tdbb, Lock* lock)
return;
}
dbb->dbb_lock_mgr->repost(dbb, lock->lck_ast, lock->lck_object, lock->lck_owner_handle);
dbb->dbb_lock_mgr->repost(att, lock->lck_ast, lock->lck_object, lock->lck_owner_handle);
fb_assert(LCK_CHECK_LOCK(lock));
}
@ -892,11 +940,12 @@ static void enqueue(thread_db* tdbb, Arg::StatusVector& statusVector, Lock* lock
**************************************/
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
fb_assert(LCK_CHECK_LOCK(lock));
Lock* parent = lock->lck_parent;
lock->lck_id = dbb->dbb_lock_mgr->enqueue(dbb, statusVector, lock->lck_id,
lock->lck_id = dbb->dbb_lock_mgr->enqueue(att, statusVector, lock->lck_id,
(parent ? parent->lck_id : 0), lock->lck_type, (const UCHAR*) &lock->lck_key,
lock->lck_length, level, lock->lck_ast, lock->lck_object, lock->lck_data, wait,
lock->lck_owner_handle);
@ -1306,6 +1355,7 @@ static USHORT internal_downgrade(thread_db* tdbb, Arg::StatusVector& statusVecto
**************************************/
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
fb_assert(LCK_CHECK_LOCK(first));
fb_assert(first->lck_compatible);
@ -1320,7 +1370,7 @@ static USHORT internal_downgrade(thread_db* tdbb, Arg::StatusVector& statusVecto
if (level < first->lck_physical)
{
if (dbb->dbb_lock_mgr->convert(dbb, statusVector, first->lck_id, level, LCK_NO_WAIT,
if (dbb->dbb_lock_mgr->convert(att, statusVector, first->lck_id, level, LCK_NO_WAIT,
external_ast, first))
{
for (Lock* lock = first; lock; lock = lock->lck_identical)
@ -1357,6 +1407,7 @@ static bool internal_enqueue(thread_db* tdbb, Arg::StatusVector& statusVector, L
**************************************/
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const att = tdbb->getAttachment();
fb_assert(LCK_CHECK_LOCK(lock));
fb_assert(lock->lck_compatible);
@ -1387,7 +1438,7 @@ static bool internal_enqueue(thread_db* tdbb, Arg::StatusVector& statusVector, L
if (level > match->lck_physical)
{
if (!dbb->dbb_lock_mgr->convert(dbb, statusVector, match->lck_id, level, wait,
if (!dbb->dbb_lock_mgr->convert(att, statusVector, match->lck_id, level, wait,
external_ast, lock))
{
return false;
@ -1416,7 +1467,7 @@ static bool internal_enqueue(thread_db* tdbb, Arg::StatusVector& statusVector, L
// 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(dbb, statusVector, lock->lck_id,
lock->lck_id = dbb->dbb_lock_mgr->enqueue(att, statusVector, lock->lck_id,
(lock->lck_parent ? lock->lck_parent->lck_id : 0), lock->lck_type,
(const UCHAR*) &lock->lck_key, lock->lck_length, level, external_ast, lock, lock->lck_data,
wait, lock->lck_owner_handle);
@ -1446,6 +1497,16 @@ static void set_lock_attachment(Lock* lock, Jrd::Attachment* attachment)
if (lock->lck_attachment == attachment)
return;
Database* dbb = attachment ? attachment->att_database :
(lock->lck_attachment ? lock->lck_attachment->att_database : NULL);
fb_assert(dbb);
if (!dbb)
return;
Sync lckSync(&dbb->dbb_lck_sync, "set_lock_attachment");
lckSync.lock(SYNC_EXCLUSIVE);
// If lock has an attachment it must not be a part of linked list
fb_assert(!lock->lck_attachment ? !lock->lck_prior && !lock->lck_next : true);

View File

@ -24,6 +24,12 @@
#ifndef JRD_LCK_H
#define JRD_LCK_H
//#define DEBUG_LCK
#ifdef DEBUG_LCK
#include "../common/classes/SyncObject.h"
#endif
namespace Jrd {
class Database;
@ -93,6 +99,10 @@ public:
lck_tail[0] = 0;
}
#ifdef DEBUG_LCK
Firebird::SyncObject lck_sync;
#endif
Lock* lck_parent;
Lock* lck_next; // lck_next and lck_prior form a doubly linked list of locks

View File

@ -222,7 +222,7 @@ void MET_get_domain(thread_db* tdbb, const MetaName& name, dsc* desc, FieldInfo*
{
fieldInfo->nullable = FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0;
MemoryPool* csb_pool = dbb->createPool();
MemoryPool* csb_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, csb_pool);
try
{
@ -245,7 +245,7 @@ void MET_get_domain(thread_db* tdbb, const MetaName& name, dsc* desc, FieldInfo*
}
catch (const Exception&)
{
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
throw;
}
}
@ -308,7 +308,7 @@ MetaName MET_get_relation_field(thread_db* tdbb,
fieldInfo->nullable = RFL.RDB$NULL_FLAG.NULL ?
(FLD.RDB$NULL_FLAG.NULL || FLD.RDB$NULL_FLAG == 0) : RFL.RDB$NULL_FLAG == 0;
MemoryPool* csb_pool = dbb->createPool();
MemoryPool* csb_pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, csb_pool);
try
{
@ -338,7 +338,7 @@ MetaName MET_get_relation_field(thread_db* tdbb,
}
catch (const Exception&)
{
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
throw;
}
}
@ -371,9 +371,9 @@ void MET_update_partners(thread_db* tdbb)
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
vec<jrd_rel*>* relations = dbb->dbb_relations;
vec<jrd_rel*>* relations = attachment->att_relations;
vec<jrd_rel*>::iterator ptr = relations->begin();
for (const vec<jrd_rel*>::const_iterator end = relations->end(); ptr < end; ++ptr)
@ -435,9 +435,11 @@ void MET_verify_cache(thread_db* tdbb)
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* att = tdbb->getAttachment();
if (!att)
return;
vec<jrd_prc*>* procedures = dbb->dbb_procedures;
vec<jrd_prc*>* procedures = att->att_procedures;
if (procedures)
{
jrd_prc* procedure;
@ -538,12 +540,13 @@ void MET_clear_cache(thread_db* tdbb)
#endif
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* att = tdbb->getAttachment();
for (int i = 0; i < DB_TRIGGER_MAX; i++) {
release_cached_triggers(tdbb, dbb->dbb_triggers[i]);
release_cached_triggers(tdbb, att->att_triggers[i]);
}
vec<jrd_rel*>* relations = dbb->dbb_relations;
vec<jrd_rel*>* relations = att->att_relations;
if (relations)
{ // scope
vec<jrd_rel*>::iterator ptr, end;
@ -561,7 +564,7 @@ void MET_clear_cache(thread_db* tdbb)
}
} // scope
vec<jrd_prc*>* procedures = dbb->dbb_procedures;
vec<jrd_prc*>* procedures = att->att_procedures;
if (procedures)
{
jrd_prc* procedure;
@ -645,14 +648,15 @@ bool MET_procedure_in_use(thread_db* tdbb, jrd_prc* proc)
MET_verify_cache(tdbb);
#endif
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* att = tdbb->getAttachment();
// This should not really happen
vec<jrd_prc*>* procedures = dbb->dbb_procedures;
vec<jrd_prc*>* procedures = att->att_procedures;
if (!procedures) {
return false;
}
vec<jrd_rel*>* relations = dbb->dbb_relations;
vec<jrd_rel*>* relations = att->att_relations;
{ // scope
vec<jrd_rel*>::iterator ptr, end;
for (ptr = relations->begin(), end = relations->end(); ptr < end; ++ptr)
@ -1230,7 +1234,7 @@ Format* MET_format(thread_db* tdbb, jrd_rel* relation, USHORT number)
unsigned bufferPos = 2;
USHORT count = buffer[0] | (buffer[1] << 8);
format = Format::newFormat(*dbb->dbb_permanent, count);
format = Format::newFormat(*relation->rel_pool, count);
Array<Ods::Descriptor> odsDescs;
Ods::Descriptor* odsDesc = odsDescs.getBuffer(count);
@ -1266,14 +1270,14 @@ Format* MET_format(thread_db* tdbb, jrd_rel* relation, USHORT number)
END_FOR
if (!format)
format = Format::newFormat(*dbb->dbb_permanent);
format = Format::newFormat(*relation->rel_pool);
format->fmt_version = number;
// Link the format block into the world
formats = relation->rel_formats =
vec<Format*>::newVector(*dbb->dbb_permanent, relation->rel_formats, number + 1);
vec<Format*>::newVector(*relation->rel_pool, relation->rel_formats, number + 1);
(*formats)[number] = format;
return format;
@ -1596,14 +1600,14 @@ void MET_load_db_triggers(thread_db* tdbb, int type)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
if ((tdbb->getAttachment()->att_flags & ATT_no_db_triggers) ||
tdbb->getDatabase()->dbb_triggers[type] != NULL)
if ((attachment->att_flags & ATT_no_db_triggers) ||
attachment->att_triggers[type] != NULL)
{
return;
}
tdbb->getDatabase()->dbb_triggers[type] = FB_NEW(*tdbb->getDatabase()->dbb_permanent)
trig_vec(*tdbb->getDatabase()->dbb_permanent);
attachment->att_triggers[type] = FB_NEW(*attachment->att_pool)
trig_vec(*attachment->att_pool);
AutoRequest trigger_request;
int encoded_type = type | TRIGGER_TYPE_DB;
@ -1615,7 +1619,7 @@ void MET_load_db_triggers(thread_db* tdbb, int type)
TRG.RDB$TRIGGER_INACTIVE EQ 0
SORTED BY TRG.RDB$TRIGGER_SEQUENCE
{
MET_load_trigger(tdbb, NULL, TRG.RDB$TRIGGER_NAME, &tdbb->getDatabase()->dbb_triggers[type]);
MET_load_trigger(tdbb, NULL, TRG.RDB$TRIGGER_NAME, &attachment->att_triggers[type]);
}
END_FOR
}
@ -1629,13 +1633,13 @@ void MET_load_ddl_triggers(thread_db* tdbb)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
if ((tdbb->getAttachment()->att_flags & ATT_no_db_triggers) ||
tdbb->getDatabase()->dbb_ddl_triggers != NULL)
if ((attachment->att_flags & ATT_no_db_triggers) ||
attachment->att_ddl_triggers != NULL)
{
return;
}
tdbb->getDatabase()->dbb_ddl_triggers = FB_NEW(*tdbb->getDatabase()->dbb_permanent)
attachment->att_ddl_triggers = FB_NEW(*tdbb->getDatabase()->dbb_permanent)
trig_vec(*tdbb->getDatabase()->dbb_permanent);
AutoRequest trigger_request;
@ -1649,7 +1653,7 @@ void MET_load_ddl_triggers(thread_db* tdbb)
if ((TRG.RDB$TRIGGER_TYPE & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DDL)
{
MET_load_trigger(tdbb, NULL, TRG.RDB$TRIGGER_NAME,
&tdbb->getDatabase()->dbb_ddl_triggers);
&attachment->att_ddl_triggers);
}
}
END_FOR
@ -2196,7 +2200,6 @@ bool MET_lookup_partner(thread_db* tdbb, jrd_rel* relation, index_desc* idx, con
SET_TDBB(tdbb);
Jrd::Attachment* attachment = tdbb->getAttachment();
Database* dbb = tdbb->getDatabase();
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
if (relation->rel_flags & REL_check_partners) {
scan_partners(tdbb, relation);
@ -2297,7 +2300,7 @@ jrd_prc* MET_lookup_procedure(thread_db* tdbb, const QualifiedName& name, bool n
jrd_prc* check_procedure = NULL;
// See if we already know the procedure by name
vec<jrd_prc*>* procedures = dbb->dbb_procedures;
vec<jrd_prc*>* procedures = attachment->att_procedures;
if (procedures)
{
vec<jrd_prc*>::iterator ptr = procedures->begin();
@ -2373,7 +2376,7 @@ jrd_prc* MET_lookup_procedure_id(thread_db* tdbb, SSHORT id,
jrd_prc* procedure;
vec<jrd_prc*>* procedures = dbb->dbb_procedures;
vec<jrd_prc*>* procedures = attachment->att_procedures;
if (procedures && id < (SSHORT) procedures->count() && (procedure = (*procedures)[id]) &&
procedure->getId() == id &&
!(procedure->prc_flags & PRC_being_scanned) &&
@ -2437,7 +2440,7 @@ jrd_rel* MET_lookup_relation(thread_db* tdbb, const MetaName& name)
// See if we already know the relation by name
vec<jrd_rel*>* relations = dbb->dbb_relations;
vec<jrd_rel*>* relations = attachment->att_relations;
jrd_rel* check_relation = NULL;
vec<jrd_rel*>::iterator ptr = relations->begin();
@ -2447,9 +2450,8 @@ jrd_rel* MET_lookup_relation(thread_db* tdbb, const MetaName& name)
if (relation)
{
if (relation->rel_flags & REL_deleting)
{
Database::CheckoutLockGuard guard(dbb, relation->rel_drop_mutex);
if (relation->rel_flags & REL_deleting) {
Jrd::Attachment::CheckoutLockGuard guard(attachment, relation->rel_drop_mutex);
}
if (!(relation->rel_flags & REL_deleted))
@ -2537,12 +2539,11 @@ jrd_rel* MET_lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted)
jrd_rel* check_relation = NULL;
jrd_rel* relation;
vec<jrd_rel*>* vector = dbb->dbb_relations;
vec<jrd_rel*>* vector = attachment->att_relations;
if (vector && (id < (SLONG) vector->count()) && (relation = (*vector)[id]))
{
if (relation->rel_flags & REL_deleting)
{
Database::CheckoutLockGuard guard(dbb, relation->rel_drop_mutex);
if (relation->rel_flags & REL_deleting) {
Jrd::Attachment::CheckoutLockGuard guard(attachment, relation->rel_drop_mutex);
}
if (relation->rel_flags & REL_deleted)
@ -2739,7 +2740,7 @@ void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation)
JrdStatement* statement = NULL;
{
Jrd::ContextPoolHolder context(tdbb, dbb->createPool());
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
PAR_blr(tdbb, relation, blr.begin(), length, NULL, NULL, &statement, true, par_flags);
}
@ -2828,18 +2829,16 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
Jrd::Attachment* attachment = tdbb->getAttachment();
Database* dbb = tdbb->getDatabase();
vec<jrd_prc*>* vector = dbb->dbb_procedures;
vec<jrd_prc*>* vector = attachment->att_procedures;
if (!vector)
{
vector = dbb->dbb_procedures = vec<jrd_prc*>::newVector(*dbb->dbb_permanent, id + 10);
vector = attachment->att_procedures = vec<jrd_prc*>::newVector(*attachment->att_pool, id + 10);
}
else if (id >= (int) vector->count())
{
vector->resize(id + 10);
}
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
jrd_prc* procedure = (*vector)[id];
if (procedure && !(procedure->prc_flags & PRC_obsolete))
@ -2983,7 +2982,7 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
(fb_utils::implicit_domain(F.RDB$FIELD_NAME) && !F.RDB$DEFAULT_VALUE.NULL)))
{
procedure->prc_defaults++;
MemoryPool* pool = dbb->createPool();
MemoryPool* pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, pool);
try
@ -2996,7 +2995,7 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
// Here we lose pools created for previous defaults.
// Probably we should use common pool for defaults and procedure itself.
dbb->deletePool(pool);
attachment->deletePool(pool);
throw;
}
}
@ -3034,7 +3033,7 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
prc_t prc_type = prc_legacy;
const bool external = !P.RDB$ENGINE_NAME.NULL; // ODS_12_0
MemoryPool* csb_pool = dbb->createPool();
MemoryPool* csb_pool = attachment->createPool();
{ // scope
Jrd::ContextPoolHolder context(tdbb, csb_pool);
@ -3063,7 +3062,7 @@ jrd_prc* MET_procedure(thread_db* tdbb, int id, bool noscan, USHORT flags)
procedure->setStatement(NULL);
}
else {
dbb->deletePool(csb_pool);
attachment->deletePool(csb_pool);
}
ERR_post(Arg::Gds(isc_bad_proc_BLR) << Arg::Str(procedure->getName().toString()));
@ -3166,11 +3165,13 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
vec<jrd_rel*>* vector = dbb->dbb_relations;
Jrd::Attachment* attachment = tdbb->getAttachment();
vec<jrd_rel*>* vector = attachment->att_relations;
MemoryPool* pool = attachment->att_pool;
if (!vector)
{
vector = dbb->dbb_relations = vec<jrd_rel*>::newVector(*dbb->dbb_permanent, id + 10);
vector = attachment->att_relations = vec<jrd_rel*>::newVector(*pool, id + 10);
}
else if (id >= vector->count())
{
@ -3186,12 +3187,12 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
// reserved for system relations
const USHORT max_sys_rel = USER_DEF_REL_INIT_ID - 1;
relation = FB_NEW(*dbb->dbb_permanent) jrd_rel(*dbb->dbb_permanent);
relation = FB_NEW(*pool) jrd_rel(*pool);
(*vector)[id] = relation;
relation->rel_id = id;
{ // Scope block.
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock;
Lock* lock = FB_NEW_RPT(*pool, 0) Lock;
relation->rel_partners_lock = lock;
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
@ -3204,7 +3205,7 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
}
{ // Scope block.
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock;
Lock* lock = FB_NEW_RPT(*pool, 0) Lock;
relation->rel_rescan_lock = lock;
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
@ -3222,7 +3223,7 @@ jrd_rel* MET_relation(thread_db* tdbb, USHORT id)
}
{ // Scope block.
Lock* lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock;
Lock* lock = FB_NEW_RPT(*pool, 0) Lock;
relation->rel_existence_lock = lock;
lock->lck_parent = dbb->dbb_lock;
lock->lck_dbb = dbb;
@ -3286,8 +3287,9 @@ void MET_remove_procedure(thread_db* tdbb, int id, jrd_prc* procedure)
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* att = tdbb->getAttachment();
vec<jrd_prc*>* pvector = dbb->dbb_procedures;
vec<jrd_prc*>* pvector = att->att_procedures;
if (!pvector) {
return;
}
@ -3440,7 +3442,6 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation)
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
if (relation->rel_flags & REL_check_partners)
{
@ -3480,8 +3481,6 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
try {
Database::CheckoutLockGuard guard(dbb, dbb->dbb_meta_mutex);
if (relation->rel_flags & REL_scanned || relation->rel_flags & REL_deleted)
{
return;
@ -3507,7 +3506,7 @@ void MET_scan_relation(thread_db* tdbb, jrd_rel* relation)
// Pick up relation level stuff
relation->rel_current_fmt = REL.RDB$FORMAT;
vec<jrd_fld*>* vector = relation->rel_fields =
vec<jrd_fld*>::newVector(*dbb->dbb_permanent, relation->rel_fields, REL.RDB$FIELD_ID + 1);
vec<jrd_fld*>::newVector(*relation->rel_pool, relation->rel_fields, REL.RDB$FIELD_ID + 1);
if (!REL.RDB$SECURITY_CLASS.NULL) {
relation->rel_security_name = REL.RDB$SECURITY_CLASS;
}
@ -3930,14 +3929,14 @@ static int blocking_ast_dsql_cache(void* ast_object)
try
{
Database* dbb = item->lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = item->lock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(item->lock->lck_attachment);
tdbb->setAttachment(att);
Jrd::ContextPoolHolder context(tdbb, 0);
Jrd::Attachment::SyncGuard guard(att);
item->obsolete = true;
item->locked = false;
@ -4010,14 +4009,14 @@ static int blocking_ast_procedure(void* ast_object)
try
{
Database* dbb = procedure->prc_existence_lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = procedure->prc_existence_lock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(procedure->prc_existence_lock->lck_attachment);
tdbb->setAttachment(att);
Jrd::ContextPoolHolder context(tdbb, 0);
Jrd::Attachment::SyncGuard guard(att);
if (procedure->prc_existence_lock) {
LCK_release(tdbb, procedure->prc_existence_lock);
@ -4052,14 +4051,14 @@ static int blocking_ast_relation(void* ast_object)
try
{
Database* dbb = relation->rel_existence_lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = relation->rel_existence_lock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(relation->rel_existence_lock->lck_attachment);
tdbb->setAttachment(att);
Jrd::ContextPoolHolder context(tdbb, 0);
Jrd::Attachment::SyncGuard guard(att);
if (relation->rel_use_count) {
relation->rel_flags |= REL_blocking;
@ -4086,14 +4085,14 @@ static int partners_ast_relation(void* ast_object)
try
{
Database* dbb = relation->rel_partners_lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = relation->rel_partners_lock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(relation->rel_partners_lock->lck_attachment);
tdbb->setAttachment(att);
Jrd::ContextPoolHolder context(tdbb, 0);
Jrd::Attachment::SyncGuard guard(att);
LCK_release(tdbb, relation->rel_partners_lock);
relation->rel_flags |= REL_check_partners;
@ -4112,14 +4111,14 @@ static int rescan_ast_relation(void* ast_object)
try
{
Database* dbb = relation->rel_rescan_lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = relation->rel_rescan_lock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(relation->rel_rescan_lock->lck_attachment);
tdbb->setAttachment(att);
Jrd::ContextPoolHolder context(tdbb, 0);
Jrd::Attachment::SyncGuard guard(att);
LCK_release(tdbb, relation->rel_rescan_lock);
relation->rel_flags &= ~REL_scanned;
@ -4708,13 +4707,13 @@ static bool resolve_charset_and_collation(thread_db* tdbb,
if (charset == NULL)
charset = (const UCHAR*) DEFAULT_CHARACTER_SET_NAME;
if (dbb->dbb_charset_ids.get((const TEXT*) charset, *id))
if (attachment->att_charset_ids.get((const TEXT*) charset, *id))
return true;
USHORT charset_id = 0;
if (get_type(tdbb, &charset_id, charset, "RDB$CHARACTER_SET_NAME"))
{
dbb->dbb_charset_ids.put((const TEXT*) charset, charset_id);
attachment->att_charset_ids.put((const TEXT*) charset, charset_id);
*id = charset_id;
return true;
}
@ -4727,7 +4726,7 @@ static bool resolve_charset_and_collation(thread_db* tdbb,
WITH CS.RDB$CHARACTER_SET_NAME EQ charset
{
found = true;
dbb->dbb_charset_ids.put((const TEXT*) charset, CS.RDB$CHARACTER_SET_ID);
attachment->att_charset_ids.put((const TEXT*) charset, CS.RDB$CHARACTER_SET_ID);
*id = CS.RDB$CHARACTER_SET_ID;
}
END_FOR
@ -4759,7 +4758,7 @@ static bool resolve_charset_and_collation(thread_db* tdbb,
AND AL1.RDB$TYPE EQ CS.RDB$CHARACTER_SET_ID
{
found = true;
dbb->dbb_charset_ids.put((const TEXT*) charset, CS.RDB$CHARACTER_SET_ID);
attachment->att_charset_ids.put((const TEXT*) charset, CS.RDB$CHARACTER_SET_ID);
*id = CS.RDB$CHARACTER_SET_ID | (COL.RDB$COLLATION_ID << 8);
}
END_FOR
@ -4790,8 +4789,7 @@ static void save_trigger_data(thread_db* tdbb, trig_vec** ptr, jrd_rel* relation
if (!vector)
{
vector = FB_NEW(*tdbb->getDatabase()->dbb_permanent)
trig_vec(*tdbb->getDatabase()->dbb_permanent);
vector = FB_NEW(*relation->rel_pool) trig_vec(*relation->rel_pool);
*ptr = vector;
}
@ -4898,19 +4896,19 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation)
{
// This seems a good candidate for vcl.
references->frgn_reference_ids =
vec<int>::newVector(*dbb->dbb_permanent, references->frgn_reference_ids,
vec<int>::newVector(*relation->rel_pool, references->frgn_reference_ids,
index_number + 1);
(*references->frgn_reference_ids)[index_number] = IDX.RDB$INDEX_ID - 1;
references->frgn_relations =
vec<int>::newVector(*dbb->dbb_permanent, references->frgn_relations,
vec<int>::newVector(*relation->rel_pool, references->frgn_relations,
index_number + 1);
(*references->frgn_relations)[index_number] = partner_relation->rel_id;
references->frgn_indexes =
vec<int>::newVector(*dbb->dbb_permanent, references->frgn_indexes,
vec<int>::newVector(*relation->rel_pool, references->frgn_indexes,
index_number + 1);
(*references->frgn_indexes)[index_number] = IND.RDB$INDEX_ID - 1;
@ -4954,19 +4952,19 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation)
if (partner_relation && !IDX.RDB$INDEX_INACTIVE && !IND.RDB$INDEX_INACTIVE)
{
dependencies->prim_reference_ids =
vec<int>::newVector(*dbb->dbb_permanent, dependencies->prim_reference_ids,
vec<int>::newVector(*relation->rel_pool, dependencies->prim_reference_ids,
index_number + 1);
(*dependencies->prim_reference_ids)[index_number] = IDX.RDB$INDEX_ID - 1;
dependencies->prim_relations =
vec<int>::newVector(*dbb->dbb_permanent, dependencies->prim_relations,
vec<int>::newVector(*relation->rel_pool, dependencies->prim_relations,
index_number + 1);
(*dependencies->prim_relations)[index_number] = partner_relation->rel_id;
dependencies->prim_indexes =
vec<int>::newVector(*dbb->dbb_permanent, dependencies->prim_indexes,
vec<int>::newVector(*relation->rel_pool, dependencies->prim_indexes,
index_number + 1);
(*dependencies->prim_indexes)[index_number] = IND.RDB$INDEX_ID - 1;

View File

@ -107,6 +107,8 @@ void NBackupStateLock::blockingAstHandler(thread_db* tdbb)
{
backup_manager->beginFlush();
NBAK_TRACE_AST( ("backup_manager->beginFlush()") );
Firebird::MutexUnlockGuard counterGuard(counterMutex);
CCH_flush_ast(tdbb);
NBAK_TRACE_AST(("database FLUSHED"));
}
@ -263,9 +265,8 @@ void BackupManager::beginBackup(thread_db* tdbb)
#endif
// Zero out first page (empty allocation table)
BufferDesc temp_bdb;
BufferDesc temp_bdb(database->dbb_bcb);
temp_bdb.bdb_page = 0;
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = reinterpret_cast<Ods::pag*>(alloc_buffer);
memset(alloc_buffer, 0, database->dbb_page_size);
if (!PIO_write(diff_file, &temp_bdb, temp_bdb.bdb_buffer, tdbb->tdbb_status_vector))
@ -314,10 +315,9 @@ ULONG BackupManager::getPageCount()
PageSpace* pageSpace;
public:
explicit PioCount(Database* d)
explicit PioCount(Database* d) : temp_bdb(d->dbb_bcb)
{
fb_assert(d);
temp_bdb.bdb_dbb = d;
pageSpace = d->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
fb_assert(pageSpace);
}
@ -515,14 +515,13 @@ bool BackupManager::actualizeAlloc(thread_db* tdbb)
alloc_table = FB_NEW(*database->dbb_permanent) AllocItemTree(database->dbb_permanent);
while (true)
{
BufferDesc temp_bdb;
BufferDesc temp_bdb(database->dbb_bcb);
// Difference file pointer pages have one ULONG as number of pages allocated on the page and
// then go physical numbers of pages from main database file. Offsets of numbers correspond
// to difference file pages.
// Get offset of pointer page. We can do so because page sizes are powers of 2
temp_bdb.bdb_page = last_allocated_page & ~(database->dbb_page_size / sizeof(ULONG) - 1);
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = reinterpret_cast<Ods::pag*>(alloc_buffer);
if (!PIO_read(diff_file, &temp_bdb, temp_bdb.bdb_buffer, status_vector)) {
@ -585,9 +584,8 @@ ULONG BackupManager::allocateDifferencePage(thread_db* tdbb, ULONG db_page)
// Grow file first. This is done in such order to keep difference
// file consistent in case of write error. We should always be able
// to read next alloc page when previous one is full.
BufferDesc temp_bdb;
BufferDesc temp_bdb(database->dbb_bcb);
temp_bdb.bdb_page = last_allocated_page + 1;
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = reinterpret_cast<Ods::pag*>(empty_buffer);
if (!PIO_write(diff_file, &temp_bdb, (Ods::pag*)empty_buffer, status_vector)) {
return 0;
@ -598,7 +596,6 @@ ULONG BackupManager::allocateDifferencePage(thread_db* tdbb, ULONG db_page)
{
// Pointer page is full. Its time to create new one.
temp_bdb.bdb_page = last_allocated_page + 2;
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = reinterpret_cast<Ods::pag*>(empty_buffer);
if (!PIO_write(diff_file, &temp_bdb, (Ods::pag*)empty_buffer, status_vector)) {
return 0;
@ -607,7 +604,6 @@ ULONG BackupManager::allocateDifferencePage(thread_db* tdbb, ULONG db_page)
// Write new item to the allocation table
temp_bdb.bdb_page = last_allocated_page & ~(database->dbb_page_size / sizeof(ULONG) - 1);
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = reinterpret_cast<Ods::pag*>(alloc_buffer);
alloc_buffer[++alloc_buffer[0]] = db_page;
if (!PIO_write(diff_file, &temp_bdb, temp_bdb.bdb_buffer, status_vector)) {
@ -640,10 +636,9 @@ ULONG BackupManager::allocateDifferencePage(thread_db* tdbb, ULONG db_page)
bool BackupManager::writeDifference(ISC_STATUS* status, ULONG diff_page, Ods::pag* page)
{
NBAK_TRACE(("write_diff"));
BufferDesc temp_bdb;
NBAK_TRACE(("write_diff page=%d, diff=%d", page->pag_pageno, diff_page));
BufferDesc temp_bdb(database->dbb_bcb);
temp_bdb.bdb_page = diff_page;
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = page;
// Check that diff page is not allocation page
fb_assert(diff_page % (database->dbb_page_size / sizeof(ULONG)));
@ -654,13 +649,12 @@ bool BackupManager::writeDifference(ISC_STATUS* status, ULONG diff_page, Ods::pa
bool BackupManager::readDifference(thread_db* tdbb, ULONG diff_page, Ods::pag* page)
{
NBAK_TRACE(("read_diff"));
BufferDesc temp_bdb;
BufferDesc temp_bdb(database->dbb_bcb);
temp_bdb.bdb_page = diff_page;
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = page;
if (!PIO_read(diff_file, &temp_bdb, page, tdbb->tdbb_status_vector))
return false;
NBAK_TRACE(("read_diff page=%d, diff=%d", page->pag_pageno, diff_page));
return true;
}
@ -737,9 +731,8 @@ bool BackupManager::actualizeState(thread_db* tdbb)
// Read original page from database file or shadows.
SSHORT retryCount = 0;
Ods::header_page* header = reinterpret_cast<Ods::header_page*>(spare_buffer);
BufferDesc temp_bdb;
BufferDesc temp_bdb(database->dbb_bcb);
temp_bdb.bdb_page = HEADER_PAGE_NUMBER;
temp_bdb.bdb_dbb = database;
temp_bdb.bdb_buffer = reinterpret_cast<Ods::pag*>(header);
PageSpace* pageSpace = database->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
fb_assert(pageSpace);

View File

@ -310,12 +310,18 @@ public:
// State Lock member functions
bool lockStateWrite(thread_db* tdbb, SSHORT wait)
{
fb_assert(!(tdbb->tdbb_flags & TDBB_backup_write_locked));
tdbb->tdbb_flags |= TDBB_backup_write_locked;
return stateLock->lockWrite(tdbb, wait);
if (stateLock->lockWrite(tdbb, wait))
return true;
tdbb->tdbb_flags &= ~TDBB_backup_write_locked;
return false;
}
void unlockStateWrite(thread_db* tdbb)
{
fb_assert(tdbb->tdbb_flags & TDBB_backup_write_locked);
tdbb->tdbb_flags &= ~TDBB_backup_write_locked;
stateLock->unlockWrite(tdbb);
}

View File

@ -78,9 +78,9 @@ public:
USHORT fil_fudge; // Fudge factor for page relocation
HANDLE fil_desc; // File descriptor
//int *fil_trace; // Trace file, if any
Firebird::Mutex fil_mutex;
Firebird::RWLock* fil_ext_lock; // file extend lock
#ifdef SUPERSERVER_V2
Firebird::Mutex fil_mutex;
void* fil_io_events[MAX_FILE_IO]; // Overlapped I/O events
#endif
USHORT fil_flags;
@ -93,6 +93,7 @@ public:
const USHORT FIL_force_write = 1;
const USHORT FIL_no_fs_cache = 2; // not using file system cache
const USHORT FIL_readonly = 4; // file opened in readonly mode
const USHORT FIL_sh_write = 8; // file opened in shared write mode
// Physical IO trace events

View File

@ -115,7 +115,7 @@ static void release_io_event(jrd_file*, OVERLAPPED*);
#endif
static bool maybeCloseFile(HANDLE&);
static jrd_file* seek_file(jrd_file*, BufferDesc*, ISC_STATUS*, OVERLAPPED*, OVERLAPPED**);
static jrd_file* setup_file(Database*, const Firebird::PathName&, HANDLE, bool);
static jrd_file* setup_file(Database*, const Firebird::PathName&, HANDLE, bool, bool);
static bool nt_error(const TEXT*, const jrd_file*, ISC_STATUS, ISC_STATUS* const);
static void adjustFileSystemCacheSize();
@ -126,9 +126,8 @@ struct AdjustFsCache
static InitMutex<AdjustFsCache> adjustFsCacheOnce;
inline static DWORD getShareFlags(bool temporary = false)
inline static DWORD getShareFlags(const bool shared_access, bool temporary = false)
{
static bool shared_access = Config::getSharedDatabase();
return FILE_SHARE_READ | ((!temporary && shared_access) ? FILE_SHARE_WRITE : 0);
}
@ -224,8 +223,9 @@ jrd_file* PIO_create(Database* dbb, const Firebird::PathName& string,
adjustFsCacheOnce.init();
const TEXT* file_name = string.c_str();
const bool shareMode = dbb->dbb_config->getSharedDatabase();
DWORD dwShareMode = getShareFlags(temporary);
DWORD dwShareMode = getShareFlags(shareMode, temporary);
if (share_delete)
dwShareMode |= FILE_SHARE_DELETE;
@ -253,7 +253,7 @@ jrd_file* PIO_create(Database* dbb, const Firebird::PathName& string,
Firebird::PathName workspace(string);
ISC_expand_filename(workspace, false);
return setup_file(dbb, workspace, desc, false);
return setup_file(dbb, workspace, desc, false, shareMode);
}
@ -299,7 +299,7 @@ void PIO_extend(Database* dbb, jrd_file* main_file, const ULONG extPages, const
if (!main_file->fil_ext_lock)
return;
Database::Checkout dcoHolder(dbb);
// Database::Checkout dcoHolder(dbb);
FileExtendLockGuard extLock(main_file->fil_ext_lock, true);
ULONG leftPages = extPages;
@ -343,7 +343,7 @@ void PIO_flush(Database* dbb, jrd_file* main_file)
* Flush the operating system cache back to good, solid oxide.
*
**************************************/
Database::Checkout dcoHolder(dbb);
// Database::Checkout dcoHolder(dbb);
for (jrd_file* file = main_file; file; file = file->fil_next)
{
FlushFileBuffers(file->fil_desc);
@ -372,12 +372,13 @@ void PIO_force_write(jrd_file* file, const bool forceWrite, const bool notUseFSC
const int force = forceWrite ? FILE_FLAG_WRITE_THROUGH : 0;
const int fsCache = notUseFSCache ? FILE_FLAG_NO_BUFFERING : 0;
const int writeMode = (file->fil_flags & FIL_readonly) ? 0 : GENERIC_WRITE;
const bool sharedMode = (file->fil_flags & FIL_sh_write);
HANDLE& hFile = file->fil_desc;
maybeCloseFile(hFile);
hFile = CreateFile(file->fil_string,
GENERIC_READ | writeMode,
getShareFlags(),
getShareFlags(sharedMode),
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | force | fsCache | g_dwExtraFlags,
@ -494,13 +495,12 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
const char* const zero_buff = zeros().getBuffer();
const size_t zero_buff_size = zeros().getSize();
Database::Checkout dcoHolder(dbb);
// Database::Checkout dcoHolder(dbb);
FileExtendLockGuard extLock(main_file->fil_ext_lock, false);
// Fake buffer, used in seek_file. Page space ID doesn't matter there
// as we already know file to work with
BufferDesc bdb;
bdb.bdb_dbb = dbb;
BufferDesc bdb(dbb->dbb_bcb);
bdb.bdb_page = PageNumber(0, startPage);
OVERLAPPED overlapped;
@ -525,7 +525,8 @@ USHORT PIO_init_data(Database* dbb, jrd_file* main_file, ISC_STATUS* status_vect
if (write_pages > leftPages)
write_pages = leftPages;
seek_file(main_file, &bdb, status_vector, &overlapped, &overlapped_ptr);
jrd_file* file1 = seek_file(main_file, &bdb, status_vector, &overlapped, &overlapped_ptr);
fb_assert(file1 == file);
const DWORD to_write = (DWORD) write_pages * dbb->dbb_page_size;
DWORD written;
@ -562,12 +563,13 @@ jrd_file* PIO_open(Database* dbb,
**************************************/
const TEXT* const ptr = (string.hasData() ? string : file_name).c_str();
bool readOnly = false;
const bool shareMode = dbb->dbb_config->getSharedDatabase();
adjustFsCacheOnce.init();
HANDLE desc = CreateFile(ptr,
GENERIC_READ | GENERIC_WRITE,
getShareFlags() | (share_delete ? FILE_SHARE_DELETE : 0),
getShareFlags(shareMode) | (share_delete ? FILE_SHARE_DELETE : 0),
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
@ -604,7 +606,7 @@ jrd_file* PIO_open(Database* dbb,
}
}
return setup_file(dbb, string, desc, readOnly);
return setup_file(dbb, string, desc, readOnly, shareMode);
}
@ -620,10 +622,11 @@ bool PIO_read(jrd_file* file, BufferDesc* bdb, Ods::pag* page, ISC_STATUS* statu
* Read a data page.
*
**************************************/
Database* const dbb = bdb->bdb_dbb;
const DWORD size = dbb->dbb_page_size;
BufferControl *bcb = bdb->bdb_bcb;
const DWORD size = bcb->bcb_page_size;
Database::Checkout dcoHolder(dbb);
Database* const dbb = bcb->bcb_database;
// Database::Checkout dcoHolder(dbb);
FileExtendLockGuard extLock(file->fil_ext_lock, false);
OVERLAPPED overlapped, *overlapped_ptr;
@ -694,7 +697,7 @@ bool PIO_read_ahead(Database* dbb,
**************************************/
OVERLAPPED overlapped, *overlapped_ptr;
Database::Checkout dcoHolder(dbb);
// Database::Checkout dcoHolder(dbb);
// If an I/O status block was passed the caller wants to queue an asynchronous I/O.
@ -782,7 +785,7 @@ bool PIO_status(Database* dbb, phys_io_blk* piob, ISC_STATUS* status_vector)
* Check the status of an asynchronous I/O.
*
**************************************/
Database::Checkout dcoHolder(dbb);
// Database::Checkout dcoHolder(dbb);
if (!(piob->piob_flags & PIOB_success))
{
@ -822,10 +825,11 @@ bool PIO_write(jrd_file* file, BufferDesc* bdb, Ods::pag* page, ISC_STATUS* stat
**************************************/
OVERLAPPED overlapped, *overlapped_ptr;
Database* const dbb = bdb->bdb_dbb;
const DWORD size = dbb->dbb_page_size;
BufferControl *bcb = bdb->bdb_bcb;
const DWORD size = bcb->bcb_page_size;
Database::Checkout dcoHolder(dbb);
Database* const dbb = bcb->bcb_database;
// Database::Checkout dcoHolder(dbb);
FileExtendLockGuard extLock(file->fil_ext_lock, false);
file = seek_file(file, bdb, status_vector, &overlapped, &overlapped_ptr);
@ -985,7 +989,7 @@ static jrd_file* seek_file(jrd_file* file,
* file block and seek to the proper page in that file.
*
**************************************/
Database* const dbb = bdb->bdb_dbb;
BufferControl *bcb = bdb->bdb_bcb;
ULONG page = bdb->bdb_page.getPageNum();
for (;; file = file->fil_next)
@ -1001,7 +1005,7 @@ static jrd_file* seek_file(jrd_file* file,
page -= file->fil_min_page - file->fil_fudge;
LARGE_INTEGER liOffset;
liOffset.QuadPart = UInt32x32To64((DWORD) page, (DWORD) dbb->dbb_page_size);
liOffset.QuadPart = UInt32x32To64((DWORD) page, (DWORD) bcb->bcb_page_size);
overlapped->Offset = liOffset.LowPart;
overlapped->OffsetHigh = liOffset.HighPart;
@ -1011,8 +1015,6 @@ static jrd_file* seek_file(jrd_file* file,
*overlapped_ptr = overlapped;
fb_assert(dbb == bdb->bdb_dbb);
#ifdef SUPERSERVER_V2
Firebird::MutexLockGuard guard(file->fil_mutex);
@ -1027,7 +1029,7 @@ static jrd_file* seek_file(jrd_file* file,
if (!overlapped->hEvent && !(overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
{
nt_error("CreateEvent", file, isc_io_access_err, status_vector);
nt_error("CreateEvent", file, isc_io_access_err, NULL/*status_vector*/);
return 0;
}
@ -1041,7 +1043,8 @@ static jrd_file* seek_file(jrd_file* file,
static jrd_file* setup_file(Database* dbb,
const Firebird::PathName& file_name,
HANDLE desc,
bool read_only)
bool read_only,
bool shareMode)
{
/**************************************
*
@ -1067,6 +1070,8 @@ static jrd_file* setup_file(Database* dbb,
if (read_only)
file->fil_flags |= FIL_readonly;
if (shareMode)
file->fil_flags |= FIL_sh_write;
// If this isn't the primary file, we're done

View File

@ -551,7 +551,7 @@ PAG PAG_allocate(thread_db* tdbb, WIN* window)
const ULONG pageNum = relative_bit + sequence * pageMgr.pagesPerPIP;
window->win_page = pageNum;
new_page = CCH_fake(tdbb, window, 0); // don't wait on latch
new_page = CCH_fake(tdbb, window, 1); // don't wait on latch ?
if (new_page)
{
BackupManager::StateReadGuard stateGuard(tdbb);
@ -605,7 +605,7 @@ PAG PAG_allocate(thread_db* tdbb, WIN* window)
// PIO_init_data returns zero - perhaps it is not supported,
// no space left on disk or IO error occurred. Try to write
// one page and handle IO errors if any.
CCH_must_write(window);
CCH_must_write(tdbb, window);
try
{
CCH_RELEASE(tdbb, window);
@ -683,9 +683,9 @@ PAG PAG_allocate(thread_db* tdbb, WIN* window)
page->scn_header.pag_type = pag_scns;
page->scn_sequence = scn_page / pageMgr.pagesPerSCN;
CCH_must_write(window);
CCH_must_write(tdbb, window);
CCH_RELEASE(tdbb, window);
CCH_must_write(&pip_window);
CCH_must_write(tdbb, &pip_window);
CCH_RELEASE(tdbb, &pip_window);
return PAG_allocate(tdbb, window);
@ -712,9 +712,9 @@ PAG PAG_allocate(thread_db* tdbb, WIN* window)
const UCHAR* end = (UCHAR*) new_pip_page + dbb->dbb_page_size;
memset(new_pip_page->pip_bits, 0xff, end - new_pip_page->pip_bits);
CCH_must_write(window);
CCH_must_write(tdbb, window);
CCH_RELEASE(tdbb, window);
CCH_must_write(&pip_window);
CCH_must_write(tdbb, &pip_window);
CCH_RELEASE(tdbb, &pip_window);
return PAG_allocate(tdbb, window);
@ -1298,7 +1298,7 @@ void PAG_init2(thread_db* tdbb, USHORT shadow_number)
window.win_page = file->fil_min_page;
USHORT file_length = 0;
ULONG last_page = 0;
BufferDesc temp_bdb;
BufferDesc temp_bdb(dbb->dbb_bcb);
SLONG next_page = 0;
do {
// note that we do not have to get a read lock on
@ -1315,7 +1315,6 @@ void PAG_init2(thread_db* tdbb, USHORT shadow_number)
header_page* header = (header_page*) temp_page;
temp_bdb.bdb_buffer = (PAG) header;
temp_bdb.bdb_page = window.win_page;
temp_bdb.bdb_dbb = dbb;
// Read the required page into the local buffer
PIO_read(file, &temp_bdb, (PAG) header, status);
@ -1717,13 +1716,13 @@ static int blocking_ast_attachment(void* ast_object)
try
{
Database* const dbb = attachment->att_database;
Database::SyncGuard dsGuard(dbb, true);
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
tdbb->setAttachment(attachment);
Jrd::ContextPoolHolder context(tdbb, dbb->dbb_permanent);
Jrd::Attachment::SyncGuard guard(attachment);
attachment->att_flags |= ATT_shutdown;
attachment->cancelExternalConnection(tdbb);
@ -2175,12 +2174,12 @@ void PageManager::releaseLocks()
USHORT PageManager::getTempPageSpaceID(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
USHORT result;
if (Config::getSharedDatabase())
if (dbb->dbb_config->getSharedDatabase())
{
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const attachment = tdbb->getAttachment();
if (!attachment->att_temp_pg_lock)

View File

@ -126,7 +126,7 @@ void PCMET_expression_index(thread_db* tdbb, const MetaName& name, USHORT id, jr
CompilerScratch* csb = 0;
// allocate a new pool to contain the expression tree for the expression index
new_pool = dbb->createPool();
new_pool = attachment->createPool();
{ // scope
Jrd::ContextPoolHolder context(tdbb, new_pool);
MET_scan_relation(tdbb, relation);
@ -181,7 +181,7 @@ void PCMET_expression_index(thread_db* tdbb, const MetaName& name, USHORT id, jr
// Get rid of the pool containing the expression tree
dbb->deletePool(new_pool);
attachment->deletePool(new_pool);
}
@ -243,7 +243,7 @@ void PCMET_lookup_index(thread_db* tdbb, jrd_rel* relation, index_desc* idx)
// with the index block in the "permanent" metadata cache
{ // scope
Jrd::ContextPoolHolder context(tdbb, dbb->createPool());
Jrd::ContextPoolHolder context(tdbb, attachment->createPool());
idx->idx_expression = static_cast<ValueExprNode*>(MET_parse_blob(
tdbb, relation, &IDX.RDB$EXPRESSION_BLR, &csb,
&idx->idx_expression_statement, false, false));

View File

@ -172,7 +172,7 @@ Sort* SortedStream::init(thread_db* tdbb) const
// establish a callback routine to reject duplicate records.
AutoPtr<Sort> scb(FB_NEW(request->req_sorts.getPool())
Sort(tdbb->getDatabase(), &request->req_sorts,
Sort(tdbb->getAttachment(), &request->req_sorts,
m_map->length, m_map->keyItems.getCount(), m_map->keyItems.getCount(),
m_map->keyItems.begin(),
((m_map->flags & FLAG_PROJECT) ? rejectDuplicate : NULL), 0));

View File

@ -99,6 +99,8 @@ void SDW_add(thread_db* tdbb, const TEXT* file_name, USHORT shadow_number, USHOR
dbb->dbb_flags & DBB_no_fs_cache);
}
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_add");
Shadow* shadow = allocate_shadow(shadow_file, shadow_number, file_flags);
// dump out the header page, even if it is a conditional
@ -132,6 +134,8 @@ int SDW_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start, USHORT sha
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_add_file");
// Find the file to be extended
jrd_file* shadow_file = 0;
@ -202,9 +206,8 @@ int SDW_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start, USHORT sha
header->hdr_next_page = 0;
// fool PIO_write into writing the scratch page into the correct place
BufferDesc temp_bdb;
BufferDesc temp_bdb(dbb->dbb_bcb);
temp_bdb.bdb_page = next->fil_min_page;
temp_bdb.bdb_dbb = dbb;
temp_bdb.bdb_buffer = (PAG) header;
header->hdr_header.pag_pageno = temp_bdb.bdb_page.getPageNum();
if (!PIO_write(shadow_file, &temp_bdb, reinterpret_cast<Ods::pag*>(header), 0))
@ -296,6 +299,8 @@ void SDW_check(thread_db* tdbb)
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_check");
// first get rid of any shadows that need to be
// deleted or shutdown; deleted shadows must also be shutdown
@ -362,6 +367,8 @@ bool SDW_check_conditional(thread_db* tdbb)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_check_conditional");
// first get rid of any shadows that need to be
// deleted or shutdown; deleted shadows must also be shutdown
@ -424,6 +431,7 @@ void SDW_close()
*
**************************************/
Database* dbb = GET_DBB();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_SHARED, "SDW_close");
for (Shadow* shadow = dbb->dbb_shadow; shadow; shadow = shadow->sdw_next)
PIO_close(shadow->sdw_file);
@ -446,6 +454,8 @@ void SDW_dump_pages(thread_db* tdbb)
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_dump_pages");
gds__log("conditional shadow dumped for database %s", dbb->dbb_filename.c_str());
const SLONG max = PAG_last_page(tdbb);
@ -529,6 +539,8 @@ void SDW_get_shadows(thread_db* tdbb)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_get_shadows");
// unless we have one, get a shared lock to ensure that we don't miss any signals
dbb->dbb_ast_flags &= ~DBB_get_shadows;
@ -574,6 +586,8 @@ void SDW_init(thread_db* tdbb, bool activate, bool delete_files)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_init");
// set up the lock block for synchronizing addition of new shadows
header_page* header; // for sizeof here, used later
@ -629,6 +643,9 @@ bool SDW_lck_update(thread_db* tdbb, SLONG sdw_update_flags)
*
**************************************/
Database* dbb = GET_DBB();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_lck_update");
Lock* lock = dbb->dbb_shadow_lock;
if (!lock)
return false;
@ -672,6 +689,8 @@ void SDW_notify(thread_db* tdbb)
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_notify");
// get current shadow lock count from database header page --
// note that since other processes need the header page to issue locks
// on the shadow count, this is effectively an uninterruptible operation
@ -728,6 +747,8 @@ bool SDW_rollover_to_shadow(thread_db* tdbb, jrd_file* file, const bool inAst)
if (file != pageSpace->file)
return true;
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_rollover_to_shadow");
Lock temp_lock;
Lock* update_lock = &temp_lock;
update_lock->lck_dbb = dbb;
@ -914,6 +935,8 @@ void SDW_start(thread_db* tdbb, const TEXT* file_name,
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "SDW_start");
USHORT header_fetched = 0;
// check that this shadow has not already been started,
@ -1165,22 +1188,22 @@ static int blocking_ast_shadowing(void* ast_object)
* new shadow files before doing the next physical write.
*
**************************************/
Database* new_dbb = static_cast<Database*>(ast_object);
Database* dbb = static_cast<Database*>(ast_object);
try
{
Database::SyncGuard dsGuard(new_dbb, true);
SyncLockGuard guard(&dbb->dbb_shadow_sync, SYNC_EXCLUSIVE, "blocking_ast_shadowing");
Lock* lock = new_dbb->dbb_shadow_lock;
Lock* lock = dbb->dbb_shadow_lock;
// Since this routine will be called asynchronously,
// we must establish a thread context
ThreadContextHolder tdbb;
tdbb->setDatabase(new_dbb);
tdbb->setDatabase(dbb);
new_dbb->dbb_ast_flags |= DBB_get_shadows;
dbb->dbb_ast_flags |= DBB_get_shadows;
if (LCK_read_data(tdbb, lock) & SDW_rollover)
update_dbb_to_sdw(new_dbb);
update_dbb_to_sdw(dbb);
LCK_release(tdbb, lock);
}
@ -1316,7 +1339,7 @@ static void update_dbb_to_sdw(Database* dbb)
return; // should be a BUGCHECK
// close the main database file if possible and release all file blocks
// hvlad: need sync for this code
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
PIO_close(pageSpace->file);

View File

@ -567,7 +567,6 @@ static bool shutdown_locks(thread_db* tdbb, SSHORT flag)
for (int retry = 0; retry < 10 && dbb->dbb_use_count; retry++)
{
// Let active database threads rundown
Database::Checkout dcoHolder(dbb);
THREAD_SLEEP(1 * 100);
}

View File

@ -158,7 +158,7 @@ namespace
} // namespace
Sort::Sort(Database* dbb,
Sort::Sort(Jrd::Attachment* attachment,
SortOwner* owner,
USHORT record_length,
size_t keys,
@ -187,7 +187,7 @@ Sort::Sort(Database* dbb,
* includes index key (which must be unique) and record numbers.
*
**************************************/
fb_assert(dbb && owner);
fb_assert(attachment && owner);
fb_assert(unique_keys <= keys);
try
@ -198,7 +198,7 @@ Sort::Sort(Database* dbb,
MemoryPool& pool = owner->getPool();
m_dbb = dbb;
m_attachment = attachment;
m_longs = ROUNDUP(record_length + SIZEOF_SR_BCKPTR, FB_ALIGNMENT) >> SHIFTLONG;
m_dup_callback = call_back;
m_dup_callback_arg = user_arg;
@ -1735,8 +1735,6 @@ void Sort::orderAndSave()
* scratch file as one big chunk
*
**************************************/
Database::Checkout dcoHolder(m_dbb);
run_control* run = m_runs;
run->run_records = 0;
@ -1831,7 +1829,6 @@ void Sort::sort()
* been requested, detect and handle them.
*
**************************************/
Database::Checkout dcoHolder(m_dbb);
// First, insert a pointer to the high key

View File

@ -213,7 +213,7 @@ typedef bool (*FPTR_REJECT_DUP_CALLBACK)(const UCHAR*, const UCHAR*, void*);
class Sort
{
public:
Sort(Database*, SortOwner*,
Sort(Jrd::Attachment*, SortOwner*,
USHORT, size_t, size_t, const sort_key_def*,
FPTR_REJECT_DUP_CALLBACK, void*, FB_UINT64 = 0);
~Sort();
@ -254,7 +254,7 @@ private:
static void quick(SLONG, SORTP**, ULONG);
Database* m_dbb; // Database
Attachment* m_attachment; // Attachment
SortOwner* m_owner; // Sort owner
UCHAR* m_memory; // ALLOC: Memory for sort
UCHAR* m_end_memory; // End of memory

View File

@ -22,33 +22,35 @@
*/
#include "firebird.h"
#include <string.h>
#include "../common/common.h"
#include "../jrd/jrd.h"
#include "../jrd/tpc.h"
#include "../jrd/ods.h"
#include "../jrd/tra.h"
#include "../jrd/lck.h"
#include "../jrd/pag.h"
#include "gen/iberror.h"
#include "../jrd/cch_proto.h"
#include "../jrd/err_proto.h"
#include "../yvalve/gds_proto.h"
#include "../jrd/lck_proto.h"
#include "../jrd/mov_proto.h"
#include "../jrd/tpc_proto.h"
#include "../jrd/tra_proto.h"
#include "../common/classes/auto.h"
#include "../common/utils_proto.h"
using namespace Jrd;
static TxPageCache* allocate_tpc(thread_db*, SLONG);
static SLONG cache_transactions(thread_db*, TxPageCache**, SLONG);
static int extend_cache(thread_db*, SLONG);
int TPC_cache_state(thread_db* tdbb, SLONG number)
using namespace Firebird;
namespace Jrd {
TipCache::TipCache(Database* dbb) :
m_dbb(dbb),
m_cache(*m_dbb->dbb_permanent)
{
}
TipCache::~TipCache()
{
clearCache();
}
int TipCache::CacheState(thread_db* tdbb, SLONG number)
{
/**************************************
*
@ -60,38 +62,43 @@ int TPC_cache_state(thread_db* tdbb, SLONG number)
* Get the current state of a transaction in the cache.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
const TxPageCache* tip_cache = dbb->dbb_tip_cache;
if (!tip_cache)
{
TPC_initialize_tpc(tdbb, number);
tip_cache = dbb->dbb_tip_cache;
}
if (number && dbb->dbb_pc_transactions)
if (number && m_dbb->dbb_pc_transactions)
{
if (TRA_precommited(tdbb, number, number))
return tra_precommitted;
}
SyncLockGuard sync(&m_sync, SYNC_SHARED, "TipCache::CacheState");
if (!m_cache.getCount())
{
SyncUnlockGuard unlock(sync);
InitializeTpc(tdbb, number);
}
// if the transaction is older than the oldest
// transaction in our tip cache, it must be committed
// hvlad: system transaction always committed too
TxPage* tip_cache = m_cache[m_cache.getCount() - 1];
if (number < tip_cache->tpc_base || number == 0)
return tra_committed;
// locate the specific TIP cache block for the transaction
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
for (; tip_cache; tip_cache = tip_cache->tpc_next)
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const SLONG base = number - number % trans_per_tip;
size_t pos;
if (m_cache.find(base, pos))
{
if ((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip)) {
return TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number);
}
tip_cache = m_cache[pos];
fb_assert(number >= tip_cache->tpc_base);
fb_assert((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip));
return TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number);
}
// Cover all possibilities by returning active
@ -100,7 +107,7 @@ int TPC_cache_state(thread_db* tdbb, SLONG number)
}
void TPC_initialize_tpc(thread_db* tdbb, SLONG number)
void TipCache::InitializeTpc(thread_db* tdbb, SLONG number)
{
/**************************************
*
@ -113,14 +120,13 @@ void TPC_initialize_tpc(thread_db* tdbb, SLONG number)
* number. This is used at TRA_start () time.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
TxPageCache* tip_cache = dbb->dbb_tip_cache;
if (!tip_cache)
SyncLockGuard sync(&m_sync, SYNC_EXCLUSIVE, "TipCache::InitializeTpc");
if (!m_cache.getCount())
{
cache_transactions(tdbb, NULL, 0);
sync.unlock();
cacheTransactions(tdbb, 0);
return;
}
@ -128,24 +134,25 @@ void TPC_initialize_tpc(thread_db* tdbb, SLONG number)
// find the end of the linked list, and cache
// all transactions from that point up to the most recent transaction
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
TxPageCache** tip_cache_ptr;
for (tip_cache_ptr = &dbb->dbb_tip_cache; *tip_cache_ptr;
tip_cache_ptr = &(*tip_cache_ptr)->tpc_next)
{
tip_cache = *tip_cache_ptr;
}
const TxPage* tip_cache = m_cache[m_cache.getCount() - 1];
if ((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip))
return;
if (tip_cache->tpc_base < MAX_TRA_NUMBER - trans_per_tip)
cache_transactions(tdbb, tip_cache_ptr, tip_cache->tpc_base + trans_per_tip);
{
// ensure last_known calculated *before* unlock !!!
const SLONG last_known = tip_cache->tpc_base;
sync.unlock();
cacheTransactions(tdbb, last_known + trans_per_tip);
}
}
void TPC_set_state(thread_db* tdbb, SLONG number, SSHORT state)
void TipCache::SetState(thread_db* tdbb, SLONG number, SSHORT state)
{
/**************************************
*
@ -158,23 +165,26 @@ void TPC_set_state(thread_db* tdbb, SLONG number, SSHORT state)
* in the TIP cache.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const SLONG base = number - number % trans_per_tip;
const SLONG byte = TRANS_OFFSET(number % trans_per_tip);
const SSHORT shift = TRANS_SHIFT(number);
for (TxPageCache* tip_cache = dbb->dbb_tip_cache; tip_cache; tip_cache = tip_cache->tpc_next)
SyncLockGuard sync(&m_sync, SYNC_EXCLUSIVE, "TipCache::SetState");
size_t pos = 0;
if (m_cache.find(base, pos))
{
if ((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip))
{
UCHAR* address = tip_cache->tpc_transactions + byte;
*address &= ~(TRA_MASK << shift);
*address |= state << shift;
break;
}
TxPage* tip_cache = m_cache[pos];
fb_assert(number >= tip_cache->tpc_base);
fb_assert((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip));
UCHAR* address = tip_cache->tpc_transactions + byte;
*address &= ~(TRA_MASK << shift);
*address |= state << shift;
return;
}
// right now we don't set the state of a transaction on a page
@ -182,7 +192,7 @@ void TPC_set_state(thread_db* tdbb, SLONG number, SSHORT state)
}
int TPC_snapshot_state(thread_db* tdbb, SLONG number)
int TipCache::SnapshotState(thread_db* tdbb, SLONG number)
{
/**************************************
*
@ -197,85 +207,92 @@ int TPC_snapshot_state(thread_db* tdbb, SLONG number)
* further checking to see if it really is.
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
const TxPageCache* tip_cache = dbb->dbb_tip_cache;
if (!tip_cache)
{
cache_transactions(tdbb, NULL, 0);
tip_cache = dbb->dbb_tip_cache;
}
if (number && dbb->dbb_pc_transactions)
if (number && m_dbb->dbb_pc_transactions)
{
if (TRA_precommited(tdbb, number, number)) {
return tra_precommitted;
}
}
SyncLockGuard sync(&m_sync, SYNC_SHARED, "TipCache::SnapshotState");
if (!m_cache.getCount())
{
sync.unlock();
cacheTransactions(tdbb, 0);
sync.lock(SYNC_SHARED, "TipCache::SnapshotState");
}
// if the transaction is older than the oldest
// transaction in our tip cache, it must be committed
// hvlad: system transaction always committed too
TxPage* tip_cache = m_cache[0];
if (number < tip_cache->tpc_base || number == 0) {
return tra_committed;
}
// locate the specific TIP cache block for the transaction
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
for (; tip_cache; tip_cache = tip_cache->tpc_next)
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const SLONG base = number - number % trans_per_tip;
size_t pos;
if (m_cache.find(base, pos))
{
if ((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip))
{
const USHORT state = TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number);
tip_cache = m_cache[pos];
// committed or dead transactions always stay that
// way, so no need to check their current state
fb_assert(number >= tip_cache->tpc_base);
fb_assert((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip));
if (state == tra_committed || state == tra_dead) {
return state;
}
const USHORT state = TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number);
// see if we can get a lock on the transaction; if we can't
// then we know it is still active
Lock temp_lock;
temp_lock.lck_dbb = dbb;
temp_lock.lck_type = LCK_tra;
temp_lock.lck_owner_handle = LCK_get_owner_handle(tdbb, temp_lock.lck_type);
temp_lock.lck_parent = dbb->dbb_lock;
temp_lock.lck_length = sizeof(SLONG);
temp_lock.lck_key.lck_long = number;
sync.unlock();
// If we can't get a lock on the transaction, it must be active.
// committed or dead transactions always stay that
// way, so no need to check their current state
if (!LCK_lock(tdbb, &temp_lock, LCK_read, LCK_NO_WAIT))
{
fb_utils::init_status(tdbb->tdbb_status_vector);
return tra_active;
}
fb_utils::init_status(tdbb->tdbb_status_vector);
LCK_release(tdbb, &temp_lock);
// as a last resort we must look at the TIP page to see
// whether the transaction is committed or dead; to minimize
// having to do this again we will check the state of all
// other transactions on that page
return TRA_fetch_state(tdbb, number);
if (state == tra_committed || state == tra_dead) {
return state;
}
// see if we can get a lock on the transaction; if we can't
// then we know it is still active
Lock temp_lock;
temp_lock.lck_dbb = m_dbb;
temp_lock.lck_type = LCK_tra;
temp_lock.lck_owner_handle = LCK_get_owner_handle(tdbb, temp_lock.lck_type);
temp_lock.lck_parent = m_dbb->dbb_lock;
temp_lock.lck_length = sizeof(SLONG);
temp_lock.lck_key.lck_long = number;
// If we can't get a lock on the transaction, it must be active.
if (!LCK_lock(tdbb, &temp_lock, LCK_read, LCK_NO_WAIT))
{
fb_utils::init_status(tdbb->tdbb_status_vector);
return tra_active;
}
fb_utils::init_status(tdbb->tdbb_status_vector);
LCK_release(tdbb, &temp_lock);
// as a last resort we must look at the TIP page to see
// whether the transaction is committed or dead; to minimize
// having to do this again we will check the state of all
// other transactions on that page
return TRA_fetch_state(tdbb, number);
}
// if the transaction has been started since we last looked, extend the cache upward
return extend_cache(tdbb, number);
sync.unlock();
return extendCache(tdbb, number);
}
void TPC_update_cache(thread_db* tdbb, const Ods::tx_inv_page* tip_page, SLONG sequence)
void TipCache::UpdateCache(thread_db* tdbb, const Ods::tx_inv_page* tip_page, SLONG sequence)
{
/**************************************
*
@ -291,23 +308,22 @@ void TPC_update_cache(thread_db* tdbb, const Ods::tx_inv_page* tip_page, SLONG s
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
const SLONG first_trans = sequence * trans_per_tip;
// while we're in the area we can check to see if there are
// any tip cache pages we can release--this is cheaper and
// easier than finding out when a TIP page is dropped
TxPageCache* tip_cache;
while ( (tip_cache = dbb->dbb_tip_cache) )
SyncLockGuard sync(&m_sync, SYNC_EXCLUSIVE, "TipCache::UpdateCache");
TxPage* tip_cache = NULL;
while (m_cache.getCount())
{
if ((ULONG) dbb->dbb_oldest_transaction >= (ULONG) (tip_cache->tpc_base + trans_per_tip))
tip_cache = m_cache[0];
if ((ULONG) m_dbb->dbb_oldest_transaction >= (ULONG) (tip_cache->tpc_base + trans_per_tip))
{
dbb->dbb_tip_cache = tip_cache->tpc_next;
m_cache.remove((size_t)0);
delete tip_cache;
}
else
@ -317,25 +333,22 @@ void TPC_update_cache(thread_db* tdbb, const Ods::tx_inv_page* tip_page, SLONG s
// find the appropriate page in the TIP cache and assign all transaction
// bits -- it's not worth figuring out which ones are actually used
for (; tip_cache; tip_cache = tip_cache->tpc_next)
{
if (first_trans == tip_cache->tpc_base)
{
const USHORT l = TRANS_OFFSET(trans_per_tip);
memcpy(tip_cache->tpc_transactions, tip_page->tip_transactions, l);
break;
}
size_t pos;
if (m_cache.find(first_trans, pos)) {
tip_cache = m_cache[pos];
}
else {
tip_cache = allocTxPage(tdbb, first_trans);
m_cache.insert(pos, tip_cache);
}
fb_assert(first_trans == tip_cache->tpc_base);
// note that a potential optimization here would be to extend the cache
// if the fetched page is not already in cache; it would involve a little
// extra effort to make sure the pages remained in order, and since there
// is a fetched page passed to us we can't fetch any other pages in this
// routine, so I just decided not to do it - djb
const USHORT l = TRANS_OFFSET(trans_per_tip);
memcpy(tip_cache->tpc_transactions, tip_page->tip_transactions, l);
}
static TxPageCache* allocate_tpc(thread_db* tdbb, SLONG base)
TipCache::TxPage* TipCache::allocTxPage(thread_db* tdbb, SLONG base)
{
/**************************************
*
@ -348,19 +361,20 @@ static TxPageCache* allocate_tpc(thread_db* tdbb, SLONG base)
* of all transactions on one page.
*
**************************************/
Database* dbb = tdbb->getDatabase();
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
fb_assert(m_sync.ourExclusiveLock());
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
// allocate a TIP cache block with enough room for all desired transactions
TxPageCache* tip_cache = FB_NEW_RPT(*dbb->dbb_permanent, trans_per_tip / 4) TxPageCache();
TxPage* tip_cache = FB_NEW_RPT(*m_dbb->dbb_permanent, trans_per_tip / 4) TxPage();
tip_cache->tpc_base = base;
return tip_cache;
}
static SLONG cache_transactions(thread_db* tdbb, TxPageCache** tip_cache_ptr, SLONG oldest)
SLONG TipCache::cacheTransactions(thread_db* tdbb, SLONG oldest)
{
/**************************************
*
@ -374,14 +388,14 @@ static SLONG cache_transactions(thread_db* tdbb, TxPageCache** tip_cache_ptr, SL
* the oldest interesting transaction.
*
**************************************/
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);
// m_sync should be unlocked here !
// check the header page for the oldest and newest transaction numbers
#ifdef SUPERSERVER_V2
const SLONG top = dbb->dbb_next_transaction;
const ULONG hdr_oldest = dbb->dbb_oldest_transaction;
const SLONG top = m_dbb->dbb_next_transaction;
const ULONG hdr_oldest = m_dbb->dbb_oldest_transaction;
#else
WIN window(HEADER_PAGE_NUMBER);
const Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
@ -389,46 +403,56 @@ static SLONG cache_transactions(thread_db* tdbb, TxPageCache** tip_cache_ptr, SL
const SLONG hdr_oldest = header->hdr_oldest_transaction;
CCH_RELEASE(tdbb, &window);
#endif
oldest = MAX(oldest, hdr_oldest);
// allocate TxPageCache blocks to hold all transaction states --
// assign one TxPageCache block per page to simplify cache maintenance
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
if (!tip_cache_ptr)
tip_cache_ptr = &dbb->dbb_tip_cache;
for (SLONG base = oldest - oldest % trans_per_tip; base <= top; base += trans_per_tip)
{
*tip_cache_ptr = allocate_tpc(tdbb, base);
tip_cache_ptr = &(*tip_cache_ptr)->tpc_next;
if (base >= MAX_TRA_NUMBER - trans_per_tip)
break;
}
// now get the inventory of all transactions, which will
// automatically fill in the tip cache pages
TRA_get_inventory(tdbb, NULL, oldest, top);
// hvlad: No need to cache TIP pages below hdr_oldest just refreshed from
// header page. Moreover out tip cache can now contain an gap between last
// cached tip page and new pages if our process was idle for long time
for (TxPageCache* tip_cache = dbb->dbb_tip_cache;
tip_cache && ((ULONG) (tip_cache->tpc_base + trans_per_tip) < (ULONG) hdr_oldest);
tip_cache = dbb->dbb_tip_cache)
oldest = MAX(oldest, hdr_oldest);
// now get the inventory of all transactions, which will automatically
// fill in the tip cache pages
// hvlad: note, call below will call UpdateCache() which will acquire m_sync
// in exclusive mode. This is the reason why m_sync must be unlocked at the
// entry of this routine
TRA_get_inventory(tdbb, NULL, oldest, top);
SyncLockGuard sync(&m_sync, SYNC_EXCLUSIVE, "TipCache::UpdateCache");
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
while (m_cache.getCount())
{
dbb->dbb_tip_cache = tip_cache->tpc_next;
delete tip_cache;
TxPage* tip_cache = m_cache[0];
if ((ULONG) (tip_cache->tpc_base + trans_per_tip) < (ULONG) hdr_oldest)
{
m_cache.remove((size_t)0);
delete tip_cache;
}
else
break;
}
return hdr_oldest;
}
static int extend_cache(thread_db* tdbb, SLONG number)
void TipCache::clearCache()
{
fb_assert(m_sync.ourExclusiveLock());
while (m_cache.getCount())
{
const size_t pos = m_cache.getCount() - 1;
TxPage* tip_page = m_cache[pos];
m_cache.remove(pos);
delete tip_page;
}
}
int TipCache::extendCache(thread_db* tdbb, SLONG number)
{
/**************************************
*
@ -443,34 +467,46 @@ static int extend_cache(thread_db* tdbb, SLONG number)
* the state of the passed transaction.
*
**************************************/
Database* dbb = tdbb->getDatabase();
const SLONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
// m_sync should be unlocked here !
const SLONG trans_per_tip = m_dbb->dbb_page_manager.transPerTIP;
// find the end of the linked list, and cache
// all transactions from that point up to the
// most recent transaction
TxPageCache* tip_cache = 0;
TxPageCache** tip_cache_ptr;
for (tip_cache_ptr = &dbb->dbb_tip_cache; *tip_cache_ptr;
tip_cache_ptr = &(*tip_cache_ptr)->tpc_next)
{
tip_cache = *tip_cache_ptr;
}
Sync sync(&m_sync, "extendCache");
sync.lock(SYNC_SHARED);
fb_assert(m_cache.getCount() > 0);
TxPage* tip_cache = m_cache[m_cache.getCount() - 1];
if (tip_cache->tpc_base < MAX_TRA_NUMBER - trans_per_tip)
{
const SLONG oldest = cache_transactions(tdbb, tip_cache_ptr, tip_cache->tpc_base + trans_per_tip);
// ensure last_known calculated *before* unlock !!!
const SLONG last_known = tip_cache->tpc_base;
sync.unlock();
const SLONG oldest = cacheTransactions(tdbb, last_known + trans_per_tip);
if (number < oldest)
return tra_committed;
sync.lock(SYNC_SHARED);
}
// find the right block for this transaction and return the state
for (tip_cache = dbb->dbb_tip_cache; tip_cache; tip_cache = tip_cache->tpc_next)
const SLONG base = number - number % trans_per_tip;
size_t pos;
if (m_cache.find(base, pos))
{
if ((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip))
return TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number);
tip_cache = m_cache[pos];
fb_assert(number >= tip_cache->tpc_base);
fb_assert((ULONG) number < (ULONG) (tip_cache->tpc_base + trans_per_tip));
return TRA_state(tip_cache->tpc_transactions, tip_cache->tpc_base, number);
}
// we should never get to this point, but if we do the
@ -479,3 +515,4 @@ static int extend_cache(thread_db* tdbb, SLONG number)
return tra_active;
}
} // namespace Jrd

View File

@ -24,11 +24,77 @@
#ifndef JRD_TPC_PROTO_H
#define JRD_TPC_PROTO_H
int TPC_cache_state(Jrd::thread_db*, SLONG);
void TPC_initialize_tpc(Jrd::thread_db*, SLONG);
void TPC_set_state(Jrd::thread_db*, SLONG, SSHORT);
int TPC_snapshot_state(Jrd::thread_db*, SLONG);
void TPC_update_cache(Jrd::thread_db*, const Ods::tx_inv_page*, SLONG);
#include "../common/classes/array.h"
#include "../common/classes/SyncObject.h"
namespace Ods {
struct tx_inv_page;
};
namespace Jrd {
class Database;
class thread_db;
class TipCache
{
public:
TipCache(Database* dbb);
~TipCache();
int CacheState(thread_db*, SLONG number);
void InitializeTpc(thread_db*, SLONG number);
void SetState(thread_db*, SLONG number, SSHORT state);
int SnapshotState(thread_db*, SLONG number);
void UpdateCache(thread_db*, const Ods::tx_inv_page* tip_page, SLONG sequence);
private:
class TxPage : public pool_alloc_rpt<SCHAR, type_tpc>
{
public:
SLONG tpc_base; // id of first transaction in this block
UCHAR tpc_transactions[1]; // two bits per transaction
static const SLONG generate(const void*, const TxPage* item)
{ return item->tpc_base; }
};
TxPage* allocTxPage(thread_db* tdbb, SLONG base);
SLONG cacheTransactions(thread_db* tdbb, SLONG oldest);
int extendCache(thread_db* tdbb, SLONG number);
void clearCache();
Database* m_dbb;
Firebird::SyncObject m_sync;
Firebird::SortedArray<TxPage*, Firebird::EmptyStorage<TxPage*>, SLONG, TxPage> m_cache;
};
inline int TPC_cache_state(thread_db* tdbb, SLONG number)
{
return tdbb->getDatabase()->dbb_tip_cache->CacheState(tdbb, number);
}
inline void TPC_initialize_tpc(thread_db* tdbb, SLONG number)
{
tdbb->getDatabase()->dbb_tip_cache->InitializeTpc(tdbb, number);
}
inline void TPC_set_state(thread_db* tdbb, SLONG number, SSHORT state)
{
tdbb->getDatabase()->dbb_tip_cache->SetState(tdbb, number, state);
}
inline int TPC_snapshot_state(thread_db* tdbb, SLONG number)
{
return tdbb->getDatabase()->dbb_tip_cache->SnapshotState(tdbb, number);
}
inline void TPC_update_cache(thread_db* tdbb, const Ods::tx_inv_page* tip_page, SLONG sequence)
{
tdbb->getDatabase()->dbb_tip_cache->UpdateCache(tdbb, tip_page, sequence);
}
} // namespace Jrd
#endif // JRD_TPC_PROTO_H

View File

@ -521,7 +521,7 @@ void TRA_extend_tip(thread_db* tdbb, ULONG sequence) //, WIN* precedence_window)
tx_inv_page* tip = (tx_inv_page*) DPM_allocate(tdbb, &window);
tip->tip_header.pag_type = pag_transactions;
CCH_must_write(&window);
CCH_must_write(tdbb, &window);
CCH_RELEASE(tdbb, &window);
// Release prior page
@ -778,9 +778,12 @@ void TRA_invalidate(Database* database, ULONG mask)
* modified a page that couldn't be written.
*
**************************************/
SyncLockGuard dbbGuard(&database->dbb_sync, SYNC_EXCLUSIVE, "TRA_invalidate");
for (Jrd::Attachment* attachment = database->dbb_attachments; attachment;
attachment = attachment->att_next)
{
Jrd::Attachment::SyncGuard attGuard(attachment);
for (jrd_tra* transaction = attachment->att_transactions; transaction;
transaction = transaction->tra_next)
{
@ -1069,7 +1072,7 @@ jrd_tra* TRA_reconnect(thread_db* tdbb, const UCHAR* id, USHORT length)
Arg::Gds(isc_tra_state) << Arg::Num(number) << Arg::Str(text));
}
MemoryPool* const pool = dbb->createPool();
MemoryPool* const pool = attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, pool);
jrd_tra* const trans = jrd_tra::create(pool, attachment, NULL);
trans->tra_number = number;
@ -1160,7 +1163,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction)
}
{ // scope
vec<jrd_rel*>& rels = *dbb->dbb_relations;
vec<jrd_rel*>& rels = *attachment->att_relations;
for (size_t i = 0; i < rels.count(); i++)
{
jrd_rel* relation = rels[i];
@ -1228,7 +1231,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction)
// Release the transaction and its pool
jrd_tra::destroy(dbb, transaction);
jrd_tra::destroy(attachment, transaction);
}
@ -1418,7 +1421,6 @@ void TRA_set_state(thread_db* tdbb, jrd_tra* transaction, SLONG number, SSHORT s
const ULONG trans_per_tip = dbb->dbb_page_manager.transPerTIP;
const SLONG sequence = number / trans_per_tip;
//trans_per_tip = dbb->dbb_page_manager.transPerTIP;
const ULONG byte = TRANS_OFFSET(number % trans_per_tip);
const SSHORT shift = TRANS_SHIFT(number);
@ -1427,7 +1429,7 @@ void TRA_set_state(thread_db* tdbb, jrd_tra* transaction, SLONG number, SSHORT s
#ifdef SUPERSERVER_V2
CCH_MARK(tdbb, &window);
const ULONG generation = tip->pag_generation;
const ULONG generation = tip->tip_header.pag_generation;
#else
CCH_MARK_MUST_WRITE(tdbb, &window);
#endif
@ -1459,7 +1461,7 @@ void TRA_set_state(thread_db* tdbb, jrd_tra* transaction, SLONG number, SSHORT s
THREAD_YIELD();
}
tip = reinterpret_cast<tx_inv_page*>(CCH_FETCH(tdbb, &window, LCK_write, pag_transactions));
if (generation == tip->pag_generation)
if (generation == tip->tip_header.pag_generation)
CCH_MARK_MUST_WRITE(tdbb, &window);
CCH_RELEASE(tdbb, &window);
#endif
@ -1597,7 +1599,7 @@ jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout, Jrd::jrd_t
// To handle the problems of relation locks, allocate a temporary
// transaction block first, seize relation locks, then go ahead and
// make up the real transaction block.
MemoryPool* const pool = outer ? outer->tra_pool : dbb->createPool();
MemoryPool* const pool = outer ? outer->tra_pool : attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, pool);
jrd_tra* const temp = jrd_tra::create(pool, attachment, outer);
@ -1612,7 +1614,7 @@ jrd_tra* TRA_start(thread_db* tdbb, ULONG flags, SSHORT lock_timeout, Jrd::jrd_t
}
catch (const Exception&)
{
jrd_tra::destroy(dbb, temp);
jrd_tra::destroy(attachment, temp);
throw;
}
@ -1652,7 +1654,7 @@ jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const UCHAR* tpb, Jrd::jrd_t
// To handle the problems of relation locks, allocate a temporary
// transaction block first, seize relation locks, then go ahead and
// make up the real transaction block.
MemoryPool* const pool = outer ? outer->tra_pool : dbb->createPool();
MemoryPool* const pool = outer ? outer->tra_pool : attachment->createPool();
Jrd::ContextPoolHolder context(tdbb, pool);
jrd_tra* const temp = jrd_tra::create(pool, attachment, outer);
@ -1665,7 +1667,7 @@ jrd_tra* TRA_start(thread_db* tdbb, int tpb_length, const UCHAR* tpb, Jrd::jrd_t
}
catch (const Exception&)
{
jrd_tra::destroy(dbb, temp);
jrd_tra::destroy(attachment, temp);
throw;
}
@ -1967,15 +1969,14 @@ static int blocking_ast_transaction(void* ast_object)
try
{
Database* dbb = transaction->tra_cancel_lock->lck_dbb;
Database::SyncGuard dsGuard(dbb, true);
Jrd::Attachment* att = transaction->tra_cancel_lock->lck_attachment;
ThreadContextHolder tdbb;
tdbb->setDatabase(dbb);
Jrd::Attachment* att = transaction->tra_cancel_lock->lck_attachment;
tdbb->setAttachment(att);
Jrd::ContextPoolHolder context(tdbb, 0);
Jrd::Attachment::SyncGuard guard(att);
if (transaction->tra_cancel_lock)
LCK_release(tdbb, transaction->tra_cancel_lock);
@ -3335,7 +3336,7 @@ static jrd_tra* transaction_start(thread_db* tdbb, jrd_tra* temp)
if (!(dbb->dbb_flags & DBB_read_only))
CCH_RELEASE(tdbb, &window);
#endif
jrd_tra::destroy(dbb, trans);
jrd_tra::destroy(attachment, trans);
ERR_post(Arg::Gds(isc_lock_conflict));
}

View File

@ -192,11 +192,11 @@ public:
return transaction;
}
static void destroy(Database* const dbb, jrd_tra* const transaction)
static void destroy(Attachment* const attachment, jrd_tra* const transaction)
{
if (transaction)
{
if (!dbb || transaction->tra_outer)
if (!attachment || transaction->tra_outer)
delete transaction;
else
{
@ -204,7 +204,7 @@ public:
Firebird::MemoryStats temp_stats;
pool->setStatsGroup(temp_stats);
delete transaction;
dbb->deletePool(pool);
attachment->deletePool(pool);
}
}
}

View File

@ -146,7 +146,7 @@ public:
return;
}
TraceRuntimeStats stats(m_attachment->att_database, m_request->req_fetch_baseline,
TraceRuntimeStats stats(m_attachment, m_request->req_fetch_baseline,
&m_request->req_request->req_stats,
fb_utils::query_performance_counter() - m_start_clock,
m_request->req_fetch_rowcount);
@ -210,7 +210,7 @@ public:
return;
}
TraceRuntimeStats stats(m_attachment->att_database, m_request->req_fetch_baseline,
TraceRuntimeStats stats(m_attachment, m_request->req_fetch_baseline,
&m_request->req_request->req_stats, m_request->req_fetch_elapsed,
m_request->req_fetch_rowcount);

View File

@ -64,9 +64,9 @@ public:
m_need_trace = false;
const Attachment* attachment = m_transaction->tra_attachment;
Attachment* attachment = m_transaction->tra_attachment;
TraceRuntimeStats stats(attachment->att_database, m_baseline, &m_transaction->tra_stats,
TraceRuntimeStats stats(attachment, m_baseline, &m_transaction->tra_stats,
fb_utils::query_performance_counter() - m_start_clock, 0);
TraceConnectionImpl conn(attachment);
@ -137,8 +137,7 @@ public:
return;
}
Database* dbb = m_tdbb->getDatabase();
TraceRuntimeStats stats(dbb, m_request->req_fetch_baseline, &m_request->req_stats,
TraceRuntimeStats stats(m_tdbb->getAttachment(), m_request->req_fetch_baseline, &m_request->req_stats,
fb_utils::query_performance_counter() - m_start_clock,
m_request->req_fetch_rowcount);
@ -197,8 +196,7 @@ public:
return;
}
Database* dbb = m_tdbb->getDatabase();
TraceRuntimeStats stats(dbb, m_request->req_fetch_baseline, &m_request->req_stats,
TraceRuntimeStats stats(m_tdbb->getAttachment(), m_request->req_fetch_baseline, &m_request->req_stats,
m_request->req_fetch_elapsed, m_request->req_fetch_rowcount);
TraceConnectionImpl conn(m_tdbb->getAttachment());
@ -260,8 +258,7 @@ public:
m_need_trace = false;
Database* dbb = m_tdbb->getDatabase();
TraceRuntimeStats stats(dbb, m_request->req_fetch_baseline, &m_request->req_stats,
TraceRuntimeStats stats(m_tdbb->getAttachment(), m_request->req_fetch_baseline, &m_request->req_stats,
fb_utils::query_performance_counter() - m_start_clock, 0);
TraceConnectionImpl conn(m_tdbb->getAttachment());
@ -388,8 +385,7 @@ public:
m_need_trace = false;
Database* dbb = m_tdbb->getDatabase();
TraceRuntimeStats stats(dbb, m_request->req_fetch_baseline, &m_request->req_stats,
TraceRuntimeStats stats(m_tdbb->getAttachment(), m_request->req_fetch_baseline, &m_request->req_stats,
fb_utils::query_performance_counter() - m_start_clock,
m_request->req_fetch_rowcount);

View File

@ -563,14 +563,14 @@ const char* TraceServiceImpl::getRemoteProcessName()
/// TraceRuntimeStats
TraceRuntimeStats::TraceRuntimeStats(Database* dbb, RuntimeStatistics* baseline, RuntimeStatistics* stats,
TraceRuntimeStats::TraceRuntimeStats(Attachment* att, RuntimeStatistics* baseline, RuntimeStatistics* stats,
SINT64 clock, SINT64 records_fetched)
{
m_info.pin_time = clock * 1000 / fb_utils::query_performance_frequency();
m_info.pin_records_fetched = records_fetched;
if (baseline)
baseline->computeDifference(dbb, *stats, m_info, m_counts);
baseline->computeDifference(att, *stats, m_info, m_counts);
else
{
// Report all zero counts for the moment.

View File

@ -328,7 +328,7 @@ private:
class TraceRuntimeStats
{
public:
TraceRuntimeStats(Database* dbb, RuntimeStatistics* baseline, RuntimeStatistics* stats,
TraceRuntimeStats(Attachment* att, RuntimeStatistics* baseline, RuntimeStatistics* stats,
SINT64 clock, SINT64 records_fetched);
PerformanceInfo* getPerf() { return &m_info; }

View File

@ -617,7 +617,7 @@ enum RTN {
#pragma FB_COMPILER_MESSAGE("This table goes to gds__log and it's not localized")
static const TEXT msg_table[VAL_MAX_ERROR][66] =
static const TEXT msg_table[VAL_MAX_ERROR][80] =
{
"Page %ld wrong type (expected %d encountered %d)", // 0
"Checksum error on page %ld",
@ -630,7 +630,7 @@ static const TEXT msg_table[VAL_MAX_ERROR][66] =
"Chain for record %ld is broken",
"Data page %ld (sequence %ld) is confused",
"Data page %ld (sequence %ld), line %ld is bad", // 10
"Index %d is corrupt on page %ld level %d. File: %s, line: %d\n\t",
"Index %d is corrupt on page %ld level %d at offset %d. File: %s, line: %d\n\t",
"Pointer page (sequence %ld) lost",
"Pointer page (sequence %ld) inconsistent",
"Record %ld is marked as damaged",
@ -1174,7 +1174,7 @@ static void walk_database(thread_db* tdbb, vdr* control)
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
#ifdef DEBUG_VAL_VERBOSE
if (VAL_debug_level)
@ -1199,7 +1199,7 @@ static void walk_database(thread_db* tdbb, vdr* control)
walk_generators(tdbb, control);
vec<jrd_rel*>* vector;
for (USHORT i = 0; (vector = dbb->dbb_relations) && i < vector->count(); i++)
for (USHORT i = 0; (vector = attachment->att_relations) && i < vector->count(); i++)
{
#ifdef DEBUG_VAL_VERBOSE
if (i >= 32 /* rel_MAX */ ) // Why not system flag instead?
@ -1487,7 +1487,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
(page->btr_header.pag_flags & BTR_FLAG_COPY_MASK) != (flags & BTR_FLAG_COPY_MASK))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, 0, __FILE__, __LINE__);
}
flags = page->btr_header.pag_flags;
const bool leafPage = (page->btr_level == 0);
@ -1496,7 +1496,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
if (page->btr_relation != relation->rel_id || page->btr_id != (UCHAR) (id % 256))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation, id + 1,
next, page->btr_level, __FILE__, __LINE__);
next, page->btr_level, 0, __FILE__, __LINE__);
CCH_RELEASE(tdbb, &window);
return rtn_corrupt;
}
@ -1511,7 +1511,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
(jumpInfo.firstNodeOffset > page->btr_length))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, pointer - (UCHAR*)page, __FILE__, __LINE__);
}
USHORT n = jumpInfo.jumpers;
@ -1527,7 +1527,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
(jumpNode.offset > page->btr_length))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, pointer - (UCHAR*)page, __FILE__, __LINE__);
}
else
{
@ -1535,7 +1535,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
BTreeNode::readNode(&checknode, (UCHAR*) page + jumpNode.offset, leafPage);
if ((jumpNode.prefix + jumpNode.length) != checknode.prefix) {
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, jumpNode.offset, __FILE__, __LINE__);
}
}
n--;
@ -1573,7 +1573,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
{
duplicateNode = false;
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, q - (UCHAR*)page, __FILE__, __LINE__);
}
else if (*p < *q)
{
@ -1598,7 +1598,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
(node.recordNumber < lastNode.recordNumber))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, node.nodePointer - (UCHAR*)page, __FILE__, __LINE__);
}
}
@ -1658,7 +1658,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
if (*p < *q)
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, node.nodePointer - (UCHAR*)page, __FILE__, __LINE__);
}
else if (*p > *q) {
break;
@ -1679,7 +1679,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
(downNode.recordNumber < down_record_number))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, node.nodePointer - (UCHAR*)page, __FILE__, __LINE__);
}
}
@ -1687,7 +1687,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
if (previous_number != down_page->btr_left_sibling)
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, node.nodePointer - (UCHAR*)page, __FILE__, __LINE__);
}
BTreeNode::readNode(&downNode, pointer, leafPage);
@ -1697,7 +1697,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
(next_number != down_page->btr_sibling))
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation,
id + 1, next, page->btr_level, __FILE__, __LINE__);
id + 1, next, page->btr_level, node.nodePointer - (UCHAR*)page, __FILE__, __LINE__);
}
if (downNode.isEndLevel && down_page->btr_sibling) {
@ -1712,7 +1712,7 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
if (pointer != endPointer || page->btr_length > dbb->dbb_page_size)
{
corrupt(tdbb, control, VAL_INDEX_PAGE_CORRUPT, relation, id + 1,
next, page->btr_level, __FILE__, __LINE__);
next, page->btr_level, pointer - (UCHAR*)page, __FILE__, __LINE__);
}
if (next == down)
@ -1751,7 +1751,6 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation,
// have a corrupt index
if (control && (control->vdr_flags & vdr_records))
{
Database::Checkout dcoHolder(dbb);
RecordBitmap::Accessor accessor(control->vdr_rel_records);
if (accessor.getFirst())
do {

View File

@ -1726,7 +1726,6 @@ void VIO_fini(thread_db* tdbb)
dbb->dbb_flags &= ~DBB_garbage_collector;
dbb->dbb_gc_sem.release(); // Wake up running thread
{ // scope
Database::Checkout dcoHolder(dbb);
dbb->dbb_gc_fini.enter();
}
}
@ -1866,7 +1865,7 @@ Record* VIO_gc_record(thread_db* tdbb, jrd_rel* relation)
// Allocate a vector of garbage collect record blocks for relation.
vec<Record*>* vector = relation->rel_gc_rec;
if (!vector) {
vector = relation->rel_gc_rec = vec<Record*>::newVector(*dbb->dbb_permanent, 1);
vector = relation->rel_gc_rec = vec<Record*>::newVector(*relation->rel_pool, 1);
}
// Set the active flag on an inactive garbage collect record block and return it.
@ -2098,7 +2097,6 @@ bool VIO_get_current(thread_db* tdbb,
VIO_backout(tdbb, rpb, transaction);
continue;
case tra_precommitted:
Database::Checkout dcoHolder(dbb);
THREAD_SLEEP(100); // milliseconds
continue;
}
@ -2122,7 +2120,6 @@ bool VIO_get_current(thread_db* tdbb,
state = TRA_wait(tdbb, transaction, rpb->rpb_transaction_nr, jrd_tra::tra_probe);
if (state == tra_active) {
Database::Checkout dcoHolder(dbb);
THREAD_SLEEP(100); // milliseconds
continue;
}
@ -2235,7 +2232,6 @@ void VIO_init(thread_db* tdbb)
}
{ // scope
Database::Checkout dcoHolder(dbb);
dbb->dbb_gc_init.enter();
}
}
@ -2312,7 +2308,7 @@ void VIO_merge_proc_sav_points(thread_db* tdbb, jrd_tra* transaction, Savepoint*
sav_point_list = &sav_point->sav_next;
}
fb_assert(org_save_point == transaction->tra_save_point);
fb_assert(org_save_point == transaction->tra_save_point || !transaction->tra_save_point);
}
@ -3177,6 +3173,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction)
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
#ifdef VIO_DEBUG
if (debug_flag > DEBUG_TRACE) {
@ -3203,7 +3200,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction)
try {
for (size_t i = 1; (vector = dbb->dbb_relations) && i < vector->count(); i++)
for (size_t i = 1; (vector = attachment->att_relations) && i < vector->count(); i++)
{
if ((relation = (*vector)[i]) && !(relation->rel_flags & (REL_deleted | REL_deleting)) &&
relation->getPages(tdbb)->rel_pages)
@ -4208,7 +4205,6 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
**************************************/
Database* dbb = (Database*)arg;
CHECK_DBB(dbb);
Database::SyncGuard dsGuard(dbb);
ISC_STATUS_ARRAY status_vector;
MOVE_CLEAR(status_vector, sizeof(status_vector));
@ -4233,7 +4229,7 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
try {
// Pseudo attachment needed for lock owner identification.
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb, 0);
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb);
tdbb->setAttachment(attachment);
attachment->att_filename = dbb->dbb_filename;
attachment->att_flags = ATT_garbage_collector;
@ -4288,7 +4284,6 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
while (dbb->dbb_flags & DBB_suspend_bgio)
{
{ // scope
Database::Checkout dcoHolder(dbb);
dbb->dbb_gc_sem.tryEnter(10);
}
if (!(dbb->dbb_flags & DBB_garbage_collector)) {
@ -4309,7 +4304,7 @@ static THREAD_ENTRY_DECLARE garbage_collector(THREAD_ENTRY_PARAM arg)
// Express interest in the relation to prevent it from being deleted
// out from under us while garbage collection is in-progress.
vec<jrd_rel*>* vector = dbb->dbb_relations;
vec<jrd_rel*>* vector = tdbb->getAttachment()->att_relations;
for (ULONG id = 0; vector && id < vector->count(); ++id)
{
relation = (*vector)[id];
@ -4457,7 +4452,6 @@ rel_exit:
}
dbb->dbb_flags &= ~DBB_gc_active;
{ // scope
Database::Checkout dcoHolder(dbb);
dbb->dbb_gc_sem.tryEnter(10);
}
dbb->dbb_flags |= DBB_gc_active;
@ -4760,7 +4754,7 @@ static void notify_garbage_collector(thread_db* tdbb, record_param* rpb, SLONG t
// A relation's garbage collect bitmap is allocated
// from the database permanent pool.
Jrd::ContextPoolHolder context(tdbb, dbb->dbb_permanent);
Jrd::ContextPoolHolder context(tdbb, relation->rel_pool);
const SLONG dp_sequence = rpb->rpb_number.getValue() / dbb->dbb_max_records;
if (!relation->rel_garbage)
@ -5124,7 +5118,6 @@ static int prepare_update( thread_db* tdbb,
if (state == tra_active)
{
Database::Checkout dcoHolder(dbb);
THREAD_SLEEP(100); // milliseconds
continue;
}
@ -5184,7 +5177,6 @@ static int prepare_update( thread_db* tdbb,
if (state == tra_precommitted)
{
Database::Checkout dcoHolder(dbb);
THREAD_SLEEP(100); // milliseconds
}
else {

View File

@ -43,6 +43,7 @@
#include "../lock/lock_proto.h"
#include "../common/ThreadStart.h"
#include "../jrd/jrd.h"
#include "../jrd/Attachment.h"
#include "gen/iberror.h"
#include "../yvalve/gds_proto.h"
#include "../common/gdsassert.h"
@ -98,7 +99,7 @@
#endif
#ifdef DEV_BUILD
#define VALIDATE_LOCK_TABLE
//#define VALIDATE_LOCK_TABLE
#endif
#ifdef DEV_BUILD
@ -406,7 +407,7 @@ bool LockManager::initializeOwner(Arg::StatusVector& statusVector,
}
void LockManager::shutdownOwner(Database* database, SRQ_PTR* owner_offset)
void LockManager::shutdownOwner(Attachment* attachment, SRQ_PTR* owner_offset)
{
/**************************************
*
@ -438,7 +439,7 @@ void LockManager::shutdownOwner(Database* database, SRQ_PTR* owner_offset)
{
m_localMutex.leave();
{ // scope
Database::Checkout dco(database);
Jrd::Attachment::Checkout cout(attachment);
THREAD_SLEEP(10);
}
m_localMutex.enter();
@ -456,7 +457,7 @@ void LockManager::shutdownOwner(Database* database, SRQ_PTR* owner_offset)
}
SRQ_PTR LockManager::enqueue(Database* database,
SRQ_PTR LockManager::enqueue(Attachment* attachment,
Arg::StatusVector& statusVector,
SRQ_PTR prior_request,
SRQ_PTR parent_request,
@ -559,7 +560,7 @@ SRQ_PTR LockManager::enqueue(Database* database,
insert_tail(&lock->lbl_requests, &request->lrq_lbl_requests);
request->lrq_data = data;
const SRQ_PTR lock_id = grant_or_que(database, request, lock, lck_wait);
const SRQ_PTR lock_id = grant_or_que(attachment, request, lock, lck_wait);
if (!lock_id)
{
statusVector << Arg::Gds(lck_wait > 0 ? isc_deadlock :
@ -621,7 +622,7 @@ SRQ_PTR LockManager::enqueue(Database* database,
}
bool LockManager::convert(Database* database,
bool LockManager::convert(Attachment* attachment,
Arg::StatusVector& statusVector,
SRQ_PTR request_offset,
UCHAR type,
@ -657,12 +658,12 @@ bool LockManager::convert(Database* database,
else
++sh_mem_header->lhb_operations[0];
return internal_convert(database, statusVector, request_offset, type, lck_wait, ast_routine,
return internal_convert(attachment, statusVector, request_offset, type, lck_wait, ast_routine,
ast_argument);
}
UCHAR LockManager::downgrade(Database* database, Arg::StatusVector& statusVector,
UCHAR LockManager::downgrade(Attachment* attachment, Arg::StatusVector& statusVector,
const SRQ_PTR request_offset)
{
/**************************************
@ -720,7 +721,7 @@ UCHAR LockManager::downgrade(Database* database, Arg::StatusVector& statusVector
}
else
{
internal_convert(database, statusVector, request_offset, state, LCK_NO_WAIT,
internal_convert(attachment, statusVector, request_offset, state, LCK_NO_WAIT,
request->lrq_ast_routine, request->lrq_ast_argument);
}
@ -765,7 +766,7 @@ bool LockManager::dequeue(const SRQ_PTR request_offset)
}
void LockManager::repost(Database* database, lock_ast_t ast, void* arg, SRQ_PTR owner_offset)
void LockManager::repost(Attachment* attachment, lock_ast_t ast, void* arg, SRQ_PTR owner_offset)
{
/**************************************
*
@ -819,7 +820,7 @@ void LockManager::repost(Database* database, lock_ast_t ast, void* arg, SRQ_PTR
DEBUG_DELAY;
signal_owner(database, (own*) SRQ_ABS_PTR(owner_offset), (SRQ_PTR) NULL);
signal_owner(attachment, (own*) SRQ_ABS_PTR(owner_offset), (SRQ_PTR) NULL);
release_shmem(owner_offset);
}
@ -1392,7 +1393,7 @@ lbl* LockManager::alloc_lock(USHORT length, Arg::StatusVector& statusVector)
}
void LockManager::blocking_action(Database* database,
void LockManager::blocking_action(Attachment* attachment,
SRQ_PTR blocking_owner_offset,
SRQ_PTR blocked_owner_offset)
{
@ -1459,13 +1460,8 @@ void LockManager::blocking_action(Database* database,
owner->own_ast_count++;
release_shmem(blocked_owner_offset);
m_localMutex.leave();
if (database)
{
Database::Checkout dcoHolder(database);
(*routine)(arg);
}
else
{
Jrd::Attachment::Checkout cout(attachment, true);
(*routine)(arg);
}
m_localMutex.enter();
@ -1492,7 +1488,7 @@ void LockManager::blocking_action_thread()
/*
* Main thread may be gone releasing our LockManager instance
* when AST can't lock appropriate database mutex and therefore does not return.
* when AST can't lock appropriate attachment mutex and therefore does not return.
*
* This causes multiple errors when entering/releasing mutexes/semaphores.
* Catch this errors and log them.
@ -2235,7 +2231,7 @@ void LockManager::grant(lrq* request, lbl* lock)
}
SRQ_PTR LockManager::grant_or_que(Database* database, lrq* request, lbl* lock, SSHORT lck_wait)
SRQ_PTR LockManager::grant_or_que(Attachment* attachment, lrq* request, lbl* lock, SSHORT lck_wait)
{
/**************************************
*
@ -2272,7 +2268,7 @@ SRQ_PTR LockManager::grant_or_que(Database* database, lrq* request, lbl* lock, S
if (lck_wait)
{
wait_for_request(database, request, lck_wait);
wait_for_request(attachment, request, lck_wait);
// For performance reasons, we're going to look at the
// request's status without re-acquiring the lock table.
@ -2539,7 +2535,7 @@ void LockManager::insert_tail(SRQ lock_srq, SRQ node)
}
bool LockManager::internal_convert(Database* database,
bool LockManager::internal_convert(Attachment* attachment,
Arg::StatusVector& statusVector,
SRQ_PTR request_offset,
UCHAR type,
@ -2602,7 +2598,7 @@ bool LockManager::internal_convert(Database* database,
else
new_ast = false;
if (wait_for_request(database, request, lck_wait))
if (wait_for_request(attachment, request, lck_wait))
return false;
request = (lrq*) SRQ_ABS_PTR(request_offset);
@ -2693,7 +2689,7 @@ USHORT LockManager::lock_state(const lbl* lock)
}
void LockManager::post_blockage(Database* database, lrq* request, lbl* lock)
void LockManager::post_blockage(Attachment* attachment, lrq* request, lbl* lock)
{
/**************************************
*
@ -2760,7 +2756,7 @@ void LockManager::post_blockage(Database* database, lrq* request, lbl* lock)
while (blocking_owners.getCount())
{
own* const blocking_owner = (own*) SRQ_ABS_PTR(blocking_owners.pop());
if (blocking_owner->own_count && !signal_owner(database, blocking_owner, owner_offset))
if (blocking_owner->own_count && !signal_owner(attachment, blocking_owner, owner_offset))
{
dead_processes.add(blocking_owner->own_process);
}
@ -3281,7 +3277,7 @@ void LockManager::release_request(lrq* request)
}
bool LockManager::signal_owner(Database* database, own* blocking_owner, SRQ_PTR blocked_owner_offset)
bool LockManager::signal_owner(Attachment* attachment, own* blocking_owner, SRQ_PTR blocked_owner_offset)
{
/**************************************
*
@ -3323,7 +3319,7 @@ bool LockManager::signal_owner(Database* database, own* blocking_owner, SRQ_PTR
if (process->prc_process_id == PID)
{
DEBUG_DELAY;
blocking_action(database, SRQ_REL_PTR(blocking_owner), blocked_owner_offset);
blocking_action(attachment, SRQ_REL_PTR(blocking_owner), blocked_owner_offset);
DEBUG_DELAY;
return true;
}
@ -3848,7 +3844,7 @@ void LockManager::validate_shb(const SRQ_PTR shb_ptr)
}
USHORT LockManager::wait_for_request(Database* database, lrq* request, SSHORT lck_wait)
USHORT LockManager::wait_for_request(Attachment* attachment, lrq* request, SSHORT lck_wait)
{
/**************************************
*
@ -3908,7 +3904,7 @@ USHORT LockManager::wait_for_request(Database* database, lrq* request, SSHORT lc
// Post blockage. If the blocking owner has disappeared, the blockage
// may clear spontaneously.
post_blockage(database, request, lock);
post_blockage(attachment, request, lock);
post_history(his_wait, owner_offset, lock_offset, SRQ_REL_PTR(request), true);
release_shmem(owner_offset);
@ -3960,7 +3956,7 @@ USHORT LockManager::wait_for_request(Database* database, lrq* request, SSHORT lc
++m_waitingOwners;
}
{ // scope
Database::Checkout dcoHolder(database);
Jrd::Attachment::Checkout cout(attachment);
ret = ISC_event_wait(&owner->own_wakeup, value, (timeout - current_time) * 1000000);
--m_waitingOwners;
}
@ -4064,7 +4060,7 @@ USHORT LockManager::wait_for_request(Database* database, lrq* request, SSHORT lc
// This could happen if the lock was granted to a different request,
// we have to tell the new owner of the lock that they are blocking us.
post_blockage(database, request, lock);
post_blockage(attachment, request, lock);
release_shmem(owner_offset);
continue;
}
@ -4122,7 +4118,7 @@ USHORT LockManager::wait_for_request(Database* database, lrq* request, SSHORT lc
// We need to inform the new owner.
DEBUG_MSG(0, ("wait_for_request: forcing a resignal of blockers\n"));
post_blockage(database, request, lock);
post_blockage(attachment, request, lock);
#ifdef DEV_BUILD
repost_counter++;
if (repost_counter % 50 == 0)

View File

@ -305,7 +305,7 @@ class Config;
namespace Jrd {
class Database;
class Attachment;
class LockManager : private Firebird::RefCounted,
public Firebird::GlobalStorage,
@ -323,15 +323,15 @@ public:
static void destroy(LockManager*);
bool initializeOwner(Firebird::Arg::StatusVector&, LOCK_OWNER_T, UCHAR, SRQ_PTR*);
void shutdownOwner(Database*, SRQ_PTR*);
void shutdownOwner(Attachment*, SRQ_PTR*);
SLONG enqueue(Database*, Firebird::Arg::StatusVector&, SRQ_PTR, SRQ_PTR, const USHORT,
SLONG enqueue(Attachment*, Firebird::Arg::StatusVector&, SRQ_PTR, SRQ_PTR, const USHORT,
const UCHAR*, const USHORT, UCHAR, lock_ast_t, void*, SLONG, SSHORT, SRQ_PTR);
bool convert(Database*, Firebird::Arg::StatusVector&, SRQ_PTR, UCHAR, SSHORT, lock_ast_t, void*);
UCHAR downgrade(Database*, Firebird::Arg::StatusVector&, const SRQ_PTR);
bool convert(Attachment*, Firebird::Arg::StatusVector&, SRQ_PTR, UCHAR, SSHORT, lock_ast_t, void*);
UCHAR downgrade(Attachment*, Firebird::Arg::StatusVector&, const SRQ_PTR);
bool dequeue(const SRQ_PTR);
void repost(Database*, lock_ast_t, void*, SRQ_PTR);
void repost(Attachment*, lock_ast_t, void*, SRQ_PTR);
bool cancelWait(SRQ_PTR);
SLONG queryData(SRQ_PTR, const USHORT, const USHORT);
@ -351,7 +351,7 @@ private:
void acquire_shmem(SRQ_PTR);
UCHAR* alloc(USHORT, Firebird::Arg::StatusVector*);
lbl* alloc_lock(USHORT, Firebird::Arg::StatusVector&);
void blocking_action(Database*, SRQ_PTR, SRQ_PTR);
void blocking_action(Attachment*, SRQ_PTR, SRQ_PTR);
void blocking_action_thread();
void bug(Firebird::Arg::StatusVector*, const TEXT*);
void bug_assert(const TEXT*, ULONG);
@ -364,15 +364,15 @@ private:
lbl* find_lock(SRQ_PTR, USHORT, const UCHAR*, USHORT, USHORT*);
lrq* get_request(SRQ_PTR);
void grant(lrq*, lbl*);
SRQ_PTR grant_or_que(Database*, lrq*, lbl*, SSHORT);
SRQ_PTR grant_or_que(Attachment*, lrq*, lbl*, SSHORT);
void init_owner_block(own*, UCHAR, LOCK_OWNER_T);
void insert_data_que(lbl*);
void insert_tail(SRQ, SRQ);
bool internal_convert(Database* database, Firebird::Arg::StatusVector&, SRQ_PTR, UCHAR, SSHORT,
bool internal_convert(Attachment* database, Firebird::Arg::StatusVector&, SRQ_PTR, UCHAR, SSHORT,
lock_ast_t, void*);
void internal_dequeue(SRQ_PTR);
static USHORT lock_state(const lbl*);
void post_blockage(Database*, lrq*, lbl*);
void post_blockage(Attachment*, lrq*, lbl*);
void post_history(USHORT, SRQ_PTR, SRQ_PTR, SRQ_PTR, bool);
void post_pending(lbl*);
void post_wakeup(own*);
@ -384,7 +384,7 @@ private:
void release_shmem(SRQ_PTR);
void release_mutex();
void release_request(lrq*);
bool signal_owner(Database*, own*, SRQ_PTR);
bool signal_owner(Attachment*, own*, SRQ_PTR);
void validate_history(const SRQ_PTR history_header);
void validate_parent(const lhb*, const SRQ_PTR);
@ -394,7 +394,7 @@ private:
void validate_request(const SRQ_PTR, USHORT, USHORT);
void validate_shb(const SRQ_PTR);
USHORT wait_for_request(Database*, lrq*, SSHORT);
USHORT wait_for_request(Attachment*, lrq*, SSHORT);
bool attach_shared_file(Firebird::Arg::StatusVector&);
void detach_shared_file(Firebird::Arg::StatusVector&);
void get_shared_file_name(Firebird::PathName&, ULONG extend = 0) const;

View File

@ -84,31 +84,28 @@
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "fb_exception.h"
#include "../remote/remote.h"
#include "gen/iberror.h"
#include "../jrd/license.h"
#include "../common/ThreadStart.h"
#include "../utilities/install/install_nt.h"
#include "../../remote/server/os/win32/cntl_proto.h"
#include "../remote/inet_proto.h"
#include "../remote/server/serve_proto.h"
#include "../../remote/server/os/win32/window_proto.h"
#include "../../remote/os/win32/wnet_proto.h"
#include "../../remote/server/os/win32/window.rh"
#include "../../remote/os/win32/xnet_proto.h"
#include "../yvalve/gds_proto.h"
#include "../common/os/fbsyslog.h"
#include "../common/isc_proto.h"
#include "../jrd/jrd_proto.h"
#include "../common/os/isc_i_proto.h"
#include "../common/isc_s_proto.h"
#include "../common/file_params.h"
#include "../jrd/thread_proto.h"
#include "../common/config/config.h"
#include "../common/utils_proto.h"
#include "../../../../common/classes/semaphore.h"
#include "../../../../common/classes/FpeControl.h"
#include "../jrd/ibase.h"
#include "../common/classes/semaphore.h"
#include "../common/classes/FpeControl.h"
#include "../jrd/license.h"
#include "../utilities/install/install_nt.h"
#include "../remote/remote.h"
#include "../remote/server/os/win32/cntl_proto.h"
#include "../remote/inet_proto.h"
#include "../remote/server/serve_proto.h"
#include "../remote/server/os/win32/window_proto.h"
#include "../remote/os/win32/wnet_proto.h"
#include "../remote/server/os/win32/window.rh"
#include "../remote/os/win32/xnet_proto.h"
#include "../yvalve/gds_proto.h"
#include "FirebirdPluginApi.h"
#include "../common/classes/ImplementHelper.h"
@ -133,6 +130,8 @@ static TEXT instance[MAXPATHLEN];
static USHORT server_flag;
static bool server_shutdown = false;
using namespace Firebird;
class ThreadCounter
{
public:
@ -159,12 +158,12 @@ public:
}
private:
static Firebird::AtomicCounter m_count;
static Firebird::Semaphore m_semaphore;
static AtomicCounter m_count;
static Semaphore m_semaphore;
};
Firebird::AtomicCounter ThreadCounter::m_count;
Firebird::Semaphore ThreadCounter::m_semaphore;
AtomicCounter ThreadCounter::m_count;
Semaphore ThreadCounter::m_semaphore;
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs, int nWndMode)
@ -188,13 +187,13 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
if (!Config::getBugcheckAbort())
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
}
catch (Firebird::fatal_exception& e)
catch (fatal_exception& e)
{
MessageBox(NULL, e.what(), "Firebird server failure",
MB_OK | MB_ICONHAND | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);
return STARTUP_ERROR; // see /common/common.h
}
catch (Firebird::status_exception& e)
catch (status_exception& e)
{
TEXT buffer[BUFFER_LARGE];
const ISC_STATUS* vector = e.value();
@ -208,9 +207,22 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
return STARTUP_ERROR; // see /common/common.h
}
server_flag = Config::getMultiClientServer() ? SRVR_multi_client : 0;
// Check for errors/missing firebird.conf
const char* anyError = Config::getMessage();
if (anyError)
{
Syslog::Record(Syslog::Error, anyError);
MessageBox(NULL, anyError, "Firebird server failure",
MB_OK | MB_ICONHAND | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);
return STARTUP_ERROR;
}
SetProcessAffinityMask(GetCurrentProcess(), static_cast<DWORD>(Config::getCpuAffinityMask()));
server_flag = 0;
const DWORD affinity = static_cast<DWORD>(Config::getCpuAffinityMask());
if (affinity) {
SetProcessAffinityMask(GetCurrentProcess(), affinity);
}
protocol_inet[0] = 0;
protocol_wnet[0] = 0;
@ -243,14 +255,14 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
// Initialize the service
ISC_signal_init();
Firebird::FpeControl::maskAll();
FpeControl::maskAll();
int nReturnValue = 0;
ISC_STATUS_ARRAY status_vector;
fb_utils::init_status(status_vector);
{ // scope for interface ptr
Firebird::PluginManagerInterfacePtr pi;
PluginManagerInterfacePtr pi;
Auth::registerLegacyServer(pi);
#ifdef TRUSTED_AUTH
Auth::registerTrustedServer(pi);
@ -283,7 +295,7 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
if (port)
service_connection(port);
}
catch (const Firebird::Exception& ex)
catch (const Exception& ex)
{
iscLogException("Server error", ex);
}
@ -292,7 +304,7 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
}
else if (!(server_flag & SRVR_non_service))
{
Firebird::string service_name;
string service_name;
service_name.printf(REMOTE_SERVICE, instance);
CNTL_init(start_connections_thread, instance);
@ -329,7 +341,7 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
// due to remote access
//gds_alloc_report(0, __FILE__, __LINE__);
Firebird::PathName name = fb_utils::getPrefix(fb_utils::FB_DIR_LOG, "memdebug.log");
PathName name = fb_utils::getPrefix(fb_utils::FB_DIR_LOG, "memdebug.log");
FILE* file = fopen(name.c_str(), "w+t");
if (file)
{
@ -381,7 +393,7 @@ static THREAD_ENTRY_DECLARE inet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
port = INET_connect(protocol_inet, NULL, server_flag, 0);
}
catch (const Firebird::Exception& ex)
catch (const Exception& ex)
{
iscLogException("INET_connect", ex);
}
@ -399,7 +411,7 @@ static THREAD_ENTRY_DECLARE inet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
Thread::start(process_connection_thread, port, THREAD_medium);
}
catch (const Firebird::Exception& )
catch (const Exception& )
{
gds__log("INET: can't start worker thread, connection terminated");
port->disconnect(NULL, NULL);
@ -431,7 +443,7 @@ static THREAD_ENTRY_DECLARE wnet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
port = WNET_connect(protocol_wnet, NULL, server_flag);
}
catch (const Firebird::Exception& ex)
catch (const Exception& ex)
{
ISC_STATUS_ARRAY status_vector;
ex.stuff_exception(status_vector);
@ -448,7 +460,7 @@ static THREAD_ENTRY_DECLARE wnet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
Thread::start(process_connection_thread, port, THREAD_medium);
}
catch (const Firebird::Exception&)
catch (const Exception&)
{
gds__log("WNET: can't start worker thread, connection terminated");
port->disconnect(NULL, NULL);
@ -482,7 +494,7 @@ static THREAD_ENTRY_DECLARE xnet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
port = XNET_connect(NULL, server_flag);
}
catch (const Firebird::Exception& ex)
catch (const Exception& ex)
{
ISC_STATUS_ARRAY status_vector;
@ -500,7 +512,7 @@ static THREAD_ENTRY_DECLARE xnet_connect_wait_thread(THREAD_ENTRY_PARAM)
{
Thread::start(process_connection_thread, port, THREAD_medium);
}
catch (const Firebird::Exception&)
catch (const Exception&)
{
gds__log("XNET: can't start worker thread, connection terminated");
port->disconnect(NULL, NULL);
@ -545,7 +557,7 @@ static THREAD_ENTRY_DECLARE start_connections_thread(THREAD_ENTRY_PARAM)
try {
Thread::start(inet_connect_wait_thread, 0, THREAD_medium);
}
catch (const Firebird::Exception& ex) {
catch (const Exception& ex) {
iscLogException("INET: can't start listener thread", ex);
}
}
@ -554,7 +566,7 @@ static THREAD_ENTRY_DECLARE start_connections_thread(THREAD_ENTRY_PARAM)
try {
Thread::start(wnet_connect_wait_thread, 0, THREAD_medium);
}
catch (const Firebird::Exception& ex) {
catch (const Exception& ex) {
iscLogException("WNET: can't start listener thread", ex);
}
}
@ -563,7 +575,7 @@ static THREAD_ENTRY_DECLARE start_connections_thread(THREAD_ENTRY_PARAM)
try {
Thread::start(xnet_connect_wait_thread, 0, THREAD_medium);
}
catch (const Firebird::Exception& ex) {
catch (const Exception& ex) {
iscLogException("XNET: can't start listener thread", ex);
}
}

View File

@ -37,7 +37,6 @@
#include "../remote/remote.h"
#include "../common/ThreadStart.h"
#include "../jrd/license.h"
#include "../common/file_params.h"
#include "../common/classes/timestamp.h"
#include "../remote/merge_proto.h"
#include "../remote/parse_proto.h"
@ -51,9 +50,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "../yvalve/gds_proto.h"
#include "../common/isc_proto.h"
#include "../common/isc_s_proto.h"
#include "../jrd/thread_proto.h"
#include "../yvalve/why_proto.h"
#include "../jrd/constants.h"
@ -70,7 +67,6 @@
#include "../common/classes/DbImplementation.h"
#include "../common/Auth.h"
#include "../common/classes/GetPlugins.h"
#include "../common/os/fbsyslog.h"
#include "../common/db_alias.h"
using namespace Firebird;
@ -866,14 +862,6 @@ void SRVR_multi_thread( rem_port* main_port, USHORT flags)
* Multi-threaded flavor of server.
*
**************************************/
// Check for errors/missing firebird.conf
const char* anyError = Config::getMessage();
if (anyError)
{
Syslog::Record(Syslog::Error, anyError);
return;
}
server_req_t* request = NULL;
RemPortPtr port; // Was volatile PORT port = NULL;