mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:03:02 +01:00
WIP - shared system requests cache
This commit is contained in:
parent
abc7273eb6
commit
07ac45ee66
@ -200,8 +200,6 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, JProvider* provider
|
||||
att_active_snapshots(*pool),
|
||||
att_statements(*pool),
|
||||
att_requests(*pool),
|
||||
att_internal(*pool),
|
||||
att_dyn_req(*pool),
|
||||
att_lock_owner_id(Database::getLockOwnerId()),
|
||||
att_backup_state_counter(0),
|
||||
att_stats(*pool),
|
||||
@ -238,10 +236,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, JProvider* provider
|
||||
att_batches(*pool),
|
||||
att_initial_options(*pool),
|
||||
att_provider(provider)
|
||||
{
|
||||
att_internal.grow(irq_MAX);
|
||||
att_dyn_req.grow(drq_MAX);
|
||||
}
|
||||
{ }
|
||||
|
||||
|
||||
Jrd::Attachment::~Attachment()
|
||||
@ -896,43 +891,6 @@ int Attachment::blockingAstReplSet(void* ast_object)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Find an inactive incarnation of a system request. If necessary, clone it.
|
||||
Jrd::Request* Attachment::findSystemRequest(thread_db* tdbb, USHORT id, InternalRequest 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);
|
||||
|
||||
Statement* 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?)"
|
||||
}
|
||||
|
||||
Request* clone = statement->getRequest(tdbb, n);
|
||||
|
||||
if (!(clone->req_flags & (req_active | req_reserved)))
|
||||
{
|
||||
clone->req_flags |= req_reserved;
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProfilerManager* Attachment::getProfilerManager(thread_db* tdbb)
|
||||
{
|
||||
auto profilerManager = att_profiler_manager.get();
|
||||
|
@ -527,8 +527,6 @@ private:
|
||||
public:
|
||||
Firebird::SortedArray<Statement*> att_statements; // Statements belonging to attachment
|
||||
Firebird::SortedArray<Request*> att_requests; // Requests belonging to attachment
|
||||
Firebird::Array<Statement*> att_internal; // internal statements
|
||||
Firebird::Array<Statement*> att_dyn_req; // internal dyn statements
|
||||
|
||||
Lock* att_id_lock; // Attachment lock (if any)
|
||||
AttNumber att_attachment_id; // Attachment ID
|
||||
@ -614,9 +612,6 @@ public:
|
||||
jrd_tra* getSysTransaction();
|
||||
void setSysTransaction(jrd_tra* trans); // used only by TRA_init
|
||||
|
||||
void cacheRequest(InternalRequest which, USHORT id, Statement* stmt);
|
||||
Request* findSystemRequest(thread_db* tdbb, USHORT id, InternalRequest which);
|
||||
|
||||
bool isSystem() const
|
||||
{
|
||||
return (att_flags & ATT_system);
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "../jrd/os/pio_proto.h"
|
||||
#include "../common/os/os_utils.h"
|
||||
#include "../jrd/met.h"
|
||||
#include "../jrd/Statement.h"
|
||||
|
||||
// Thread data block
|
||||
#include "../common/ThreadData.h"
|
||||
@ -469,6 +470,49 @@ namespace Jrd
|
||||
dbb_filename, dbb_config));
|
||||
}
|
||||
|
||||
// Find an inactive incarnation of a system request.
|
||||
Request* Database::findSystemRequest(thread_db* tdbb, USHORT id, InternalRequest which)
|
||||
{
|
||||
fb_assert(which == IRQ_REQUESTS || which == DYN_REQUESTS);
|
||||
|
||||
//Database::CheckoutLockGuard guard(this, dbb_cmp_clone_mutex);
|
||||
|
||||
// If the request hasn't been compiled or isn't active, there're nothing to do.
|
||||
auto* stPtr = &(which == IRQ_REQUESTS ? dbb_internal : dbb_dyn_req)[id];
|
||||
Statement* statement = stPtr->load(std::memory_order_relaxed);
|
||||
if (!statement)
|
||||
return NULL;
|
||||
|
||||
return statement->findRequest(tdbb);
|
||||
}
|
||||
|
||||
// Store newly compiled request in the cache
|
||||
Request* Database::cacheRequest(InternalRequest which, USHORT id, Request* req)
|
||||
{
|
||||
auto* const stPtr = &(which == IRQ_REQUESTS ? dbb_internal : dbb_dyn_req)[id];
|
||||
|
||||
Statement* existingStmt = stPtr->load(std::memory_order_acquire);
|
||||
Statement* const compiledStmt = req->getStatement();
|
||||
|
||||
if (!existingStmt)
|
||||
{
|
||||
if (stPtr->compare_exchange_strong(existingStmt, compiledStmt,
|
||||
std::memory_order_release, std::memory_order_acquire))
|
||||
{
|
||||
return req;
|
||||
}
|
||||
}
|
||||
|
||||
// Someone else already stored system request in the cache
|
||||
// Let's use it
|
||||
fb_assert(existingStmt);
|
||||
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
compiledStmt->release(tdbb);
|
||||
|
||||
return existingStmt->findRequest(tdbb);
|
||||
}
|
||||
|
||||
// Database::Linger class implementation
|
||||
|
||||
void Database::Linger::handler()
|
||||
@ -598,6 +642,8 @@ namespace Jrd
|
||||
dbb_page_manager(this, *p),
|
||||
dbb_file_id(*p),
|
||||
dbb_modules(*p),
|
||||
dbb_internal(*p),
|
||||
dbb_dyn_req(*p),
|
||||
dbb_extManager(nullptr),
|
||||
dbb_flags(shared ? DBB_shared : 0),
|
||||
dbb_filename(*p),
|
||||
@ -625,6 +671,9 @@ namespace Jrd
|
||||
dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p))
|
||||
{
|
||||
dbb_pools.add(p);
|
||||
|
||||
dbb_internal.grow(irq_MAX);
|
||||
dbb_dyn_req.grow(drq_MAX);
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,6 +103,10 @@ public:
|
||||
static void destroy(KeywordsMap* inst);
|
||||
};
|
||||
|
||||
// Flags to indicate normal internal requests vs. dyn internal requests
|
||||
enum InternalRequest : USHORT {
|
||||
NOT_REQUEST, IRQ_REQUESTS, DYN_REQUESTS
|
||||
};
|
||||
|
||||
//
|
||||
// bit values for dbb_flags
|
||||
@ -357,6 +361,9 @@ private:
|
||||
DatabaseModules dbb_modules; // external function/filter modules
|
||||
|
||||
public:
|
||||
Firebird::Array<std::atomic<Statement*>> dbb_internal; // internal statements
|
||||
Firebird::Array<std::atomic<Statement*>> dbb_dyn_req; // internal dyn statements
|
||||
|
||||
Firebird::AutoPtr<ExtEngineManager> dbb_extManager; // external engine manager
|
||||
|
||||
Firebird::SyncObject dbb_flush_count_mutex;
|
||||
@ -554,6 +561,9 @@ public:
|
||||
return dbb_gblobj_holder->getReplConfig();
|
||||
}
|
||||
|
||||
Request* findSystemRequest(thread_db* tdbb, USHORT id, InternalRequest which);
|
||||
Request* cacheRequest(InternalRequest which, USHORT id, Request* req);
|
||||
|
||||
private:
|
||||
//static int blockingAstSharedCounter(void*);
|
||||
static int blocking_ast_sweep(void* ast_object);
|
||||
|
@ -165,13 +165,13 @@ RelationPermanent::RelationPermanent(thread_db* tdbb, MemoryPool& p, MetaId id,
|
||||
rel_rescan_lock = FB_NEW_RPT(getPool(), 0)
|
||||
Lock(tdbb, sizeof(SLONG), LCK_rel_rescan, this, rescan_ast_relation);
|
||||
rel_rescan_lock->setKey(rel_id);
|
||||
|
||||
/*
|
||||
if (rel_id >= rel_MAX)
|
||||
{
|
||||
rel_existence_lock = FB_NEW_RPT(getPool(), 0)
|
||||
Lock(tdbb, sizeof(SLONG), LCK_rel_exist, this, blocking_ast_relation);
|
||||
rel_existence_lock->setKey(rel_id);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
RelationPermanent::~RelationPermanent()
|
||||
|
@ -740,7 +740,7 @@ public:
|
||||
|
||||
static int partners_ast_relation(void* ast_object);
|
||||
static int rescan_ast_relation(void* ast_object);
|
||||
static int blocking_ast_relation(void* ast_object);
|
||||
// static int blocking_ast_relation(void* ast_object);
|
||||
|
||||
vec<Format*>* rel_formats; // Known record formats
|
||||
IndexLocks rel_index_locks; // index existence locks
|
||||
|
@ -1684,8 +1684,8 @@ static void trigger_failure(thread_db* tdbb, Request* trigger)
|
||||
|
||||
void AutoCacheRequest::cacheRequest()
|
||||
{
|
||||
Jrd::Attachment* att = JRD_get_thread_data()->getAttachment();
|
||||
att->cacheRequest(which, id, request->getStatement());
|
||||
Jrd::Database* dbb = JRD_get_thread_data()->getDatabase();
|
||||
request = dbb->cacheRequest(which, id, request);
|
||||
}
|
||||
|
||||
void AutoCacheRequest::release()
|
||||
|
@ -31,12 +31,7 @@ namespace Jrd {
|
||||
class jrd_tra;
|
||||
class AssignmentNode;
|
||||
|
||||
//
|
||||
// Flags to indicate normal internal requests vs. dyn internal requests
|
||||
//
|
||||
enum InternalRequest : USHORT {
|
||||
NOT_REQUEST, IRQ_REQUESTS, DYN_REQUESTS
|
||||
};
|
||||
enum InternalRequest : USHORT;
|
||||
}
|
||||
|
||||
void EXE_assignment(Jrd::thread_db*, const Jrd::AssignmentNode*);
|
||||
@ -71,7 +66,7 @@ namespace Jrd
|
||||
AutoCacheRequest(thread_db* tdbb, USHORT aId, InternalRequest aWhich)
|
||||
: id(aId),
|
||||
which(aWhich),
|
||||
request(tdbb->getAttachment()->findSystemRequest(tdbb, id, which))
|
||||
request(tdbb->getDatabase()->findSystemRequest(tdbb, id, which))
|
||||
{
|
||||
}
|
||||
|
||||
@ -94,7 +89,7 @@ namespace Jrd
|
||||
|
||||
id = aId;
|
||||
which = aWhich;
|
||||
request = tdbb->getAttachment()->findSystemRequest(tdbb, id, which);
|
||||
request = tdbb->getDatabase()->findSystemRequest(tdbb, id, which);
|
||||
}
|
||||
|
||||
void compile(thread_db* tdbb, const UCHAR* blr, ULONG blrLength)
|
||||
|
@ -7564,20 +7564,6 @@ void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment, XThreadEns
|
||||
|
||||
Monitoring::cleanupAttachment(tdbb);
|
||||
|
||||
// release the system requests
|
||||
|
||||
for (auto* itr : attachment->att_internal)
|
||||
{
|
||||
if (itr)
|
||||
itr->release(tdbb);
|
||||
}
|
||||
|
||||
for (auto* itr : attachment->att_dyn_req)
|
||||
{
|
||||
if (itr)
|
||||
itr->release(tdbb);
|
||||
}
|
||||
|
||||
dbb->dbb_extManager->closeAttachment(tdbb, attachment);
|
||||
|
||||
if (dbb->dbb_config->getServerMode() == MODE_SUPER)
|
||||
@ -7821,6 +7807,21 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Release the system requests
|
||||
for (auto& itr : dbb->dbb_internal)
|
||||
{
|
||||
auto* stmt = itr.load(std::memory_order_relaxed);
|
||||
if (stmt)
|
||||
stmt->release(tdbb);
|
||||
}
|
||||
|
||||
for (auto& itr : dbb->dbb_dyn_req)
|
||||
{
|
||||
auto* stmt = itr.load(std::memory_order_relaxed);
|
||||
if (stmt)
|
||||
stmt->release(tdbb);
|
||||
}
|
||||
|
||||
// Database linger
|
||||
if ((flags & SHUT_DBB_LINGER) &&
|
||||
(!(engineShutdown || (dbb->dbb_ast_flags & DBB_shutdown))) &&
|
||||
|
Loading…
Reference in New Issue
Block a user