diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 04c8bcf5a5..366d69c56e 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -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(); diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index 552dd96140..e022ac67f7 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -527,8 +527,6 @@ private: public: Firebird::SortedArray att_statements; // Statements belonging to attachment Firebird::SortedArray att_requests; // Requests belonging to attachment - Firebird::Array att_internal; // internal statements - Firebird::Array 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); diff --git a/src/jrd/Database.cpp b/src/jrd/Database.cpp index 5680952c20..f803868ce9 100644 --- a/src/jrd/Database.cpp +++ b/src/jrd/Database.cpp @@ -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); } diff --git a/src/jrd/Database.h b/src/jrd/Database.h index cd87391f0b..bd4254d04f 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -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> dbb_internal; // internal statements + Firebird::Array> dbb_dyn_req; // internal dyn statements + Firebird::AutoPtr 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); diff --git a/src/jrd/Relation.cpp b/src/jrd/Relation.cpp index 0452d3609e..973ba060dd 100644 --- a/src/jrd/Relation.cpp +++ b/src/jrd/Relation.cpp @@ -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() diff --git a/src/jrd/Relation.h b/src/jrd/Relation.h index 0b87e9f178..7485f445f4 100644 --- a/src/jrd/Relation.h +++ b/src/jrd/Relation.h @@ -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* rel_formats; // Known record formats IndexLocks rel_index_locks; // index existence locks diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index 354243a2e6..2a802ee5c5 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -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() diff --git a/src/jrd/exe_proto.h b/src/jrd/exe_proto.h index ed74adf93e..259c0ecb60 100644 --- a/src/jrd/exe_proto.h +++ b/src/jrd/exe_proto.h @@ -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) diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 5bcdeb5c92..2a7028c0fe 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -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))) &&