From 4215b9d2207c19c77501a24b32991b8059768396 Mon Sep 17 00:00:00 2001 From: AlexPeshkoff Date: Fri, 14 Jul 2023 19:20:56 +0300 Subject: [PATCH] WIP --- builds/posix/prefix.linux_amd64 | 4 +- extern/cloop/src/tests/test1/CalcCppApi.h | 115 ++- src/dsql/ExprNodes.cpp | 4 +- src/dsql/NodePrinter.h | 10 +- src/dsql/StmtNodes.cpp | 4 +- src/include/fb_types.h | 4 +- src/include/gen/Firebird.pas | 1 + src/jrd/Attachment.cpp | 7 +- src/jrd/Attachment.h | 3 - src/jrd/Collation.cpp | 10 +- src/jrd/Collation.h | 7 +- src/jrd/Database.cpp | 3 +- src/jrd/Database.h | 2 - src/jrd/ExtEngineManager.cpp | 8 +- src/jrd/Function.epp | 68 +- src/jrd/Function.h | 25 +- src/jrd/HazardPtr.cpp | 165 ---- src/jrd/HazardPtr.h | 655 +++---------- src/jrd/Monitoring.cpp | 6 +- src/jrd/ProfilerManager.cpp | 3 +- src/jrd/RecordSourceNodes.cpp | 66 +- src/jrd/RecordSourceNodes.h | 6 +- src/jrd/Relation.cpp | 42 +- src/jrd/Relation.h | 115 +-- src/jrd/Routine.cpp | 15 +- src/jrd/Routine.h | 36 +- src/jrd/RuntimeStatistics.cpp | 4 +- src/jrd/Statement.cpp | 58 +- src/jrd/Statement.h | 8 +- src/jrd/SysFunction.cpp | 2 +- src/jrd/WorkerAttachment.cpp | 2 +- src/jrd/blb.cpp | 4 +- src/jrd/btr.cpp | 16 +- src/jrd/dfw.epp | 95 +- src/jrd/dpm.epp | 2 +- src/jrd/exe.cpp | 14 +- src/jrd/exe.h | 275 ++---- src/jrd/ext.cpp | 2 +- src/jrd/ext_proto.h | 2 +- src/jrd/idx.cpp | 2 +- src/jrd/ini.epp | 2 +- src/jrd/intl.cpp | 42 +- src/jrd/intl_proto.h | 2 +- src/jrd/lck.cpp | 9 +- src/jrd/lck.h | 1 - src/jrd/met.epp | 217 ++--- src/jrd/met.h | 1015 ++++++++++++++------- src/jrd/met_proto.h | 12 +- src/jrd/pag.cpp | 2 +- src/jrd/par.cpp | 10 +- src/jrd/par_proto.h | 6 +- src/jrd/req.h | 68 +- src/jrd/scl.epp | 2 +- src/jrd/tra.cpp | 30 +- src/jrd/tra.h | 4 +- src/jrd/tra_proto.h | 4 + src/jrd/trace/TraceJrdHelpers.h | 2 +- src/jrd/validation.cpp | 6 +- src/jrd/validation.h | 2 +- src/jrd/vio.cpp | 12 +- 60 files changed, 1518 insertions(+), 1800 deletions(-) diff --git a/builds/posix/prefix.linux_amd64 b/builds/posix/prefix.linux_amd64 index 969f64caf8..861f7f66a6 100644 --- a/builds/posix/prefix.linux_amd64 +++ b/builds/posix/prefix.linux_amd64 @@ -24,8 +24,8 @@ WARN_FLAGS=-Werror=delete-incomplete -Wall -Wno-switch -Wno-parentheses -Wno-unk PLATFORM_PLUSPLUS_FLAGS=-Wno-invalid-offsetof -Wno-class-memaccess PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS) -#DEV_FLAGS=-DUSE_VALGRIND $(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=8 -DEV_FLAGS=$(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=8 +#DEV_FLAGS=-DUSE_VALGRIND $(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=2 +DEV_FLAGS=$(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=2 # This file must be compiled with SSE4.2 support %/CRC32C.o: COMMON_FLAGS += -msse4 diff --git a/extern/cloop/src/tests/test1/CalcCppApi.h b/extern/cloop/src/tests/test1/CalcCppApi.h index bf2d7311e0..3ea664c617 100644 --- a/extern/cloop/src/tests/test1/CalcCppApi.h +++ b/extern/cloop/src/tests/test1/CalcCppApi.h @@ -7,6 +7,23 @@ #define CLOOP_CARG #endif +#ifndef CLOOP_NOEXCEPT +#if __cplusplus >= 201103L +#define CLOOP_NOEXCEPT noexcept +#else +#define CLOOP_NOEXCEPT throw() +#endif +#endif + + +#ifndef CLOOP_CONSTEXPR +#if __cplusplus >= 201103L +#define CLOOP_CONSTEXPR constexpr +#else +#define CLOOP_CONSTEXPR const +#endif +#endif + namespace calc { @@ -34,6 +51,8 @@ namespace calc // Interfaces declarations +#define CALC_IDISPOSABLE_VERSION 1u + class IDisposable { public: @@ -41,7 +60,7 @@ namespace calc { void* cloopDummy[1]; uintptr_t version; - void (CLOOP_CARG *dispose)(IDisposable* self) throw(); + void (CLOOP_CARG *dispose)(IDisposable* self) CLOOP_NOEXCEPT; }; void* cloopDummy[1]; @@ -57,7 +76,7 @@ namespace calc } public: - static const unsigned VERSION = 1; + static CLOOP_CONSTEXPR unsigned VERSION = CALC_IDISPOSABLE_VERSION; void dispose() { @@ -65,13 +84,15 @@ namespace calc } }; +#define CALC_ISTATUS_VERSION 2u + class IStatus : public IDisposable { public: struct VTable : public IDisposable::VTable { - int (CLOOP_CARG *getCode)(const IStatus* self) throw(); - void (CLOOP_CARG *setCode)(IStatus* self, int code) throw(); + int (CLOOP_CARG *getCode)(const IStatus* self) CLOOP_NOEXCEPT; + void (CLOOP_CARG *setCode)(IStatus* self, int code) CLOOP_NOEXCEPT; }; protected: @@ -85,11 +106,11 @@ namespace calc } public: - static const unsigned VERSION = 2; + static CLOOP_CONSTEXPR unsigned VERSION = CALC_ISTATUS_VERSION; - static const int ERROR_1 = 1; - static const int ERROR_2 = 0x2; - static const int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2; + static CLOOP_CONSTEXPR int ERROR_1 = 1; + static CLOOP_CONSTEXPR int ERROR_2 = 0x2; + static CLOOP_CONSTEXPR int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2; int getCode() const { @@ -103,15 +124,17 @@ namespace calc } }; +#define CALC_IFACTORY_VERSION 2u + class IFactory : public IDisposable { public: struct VTable : public IDisposable::VTable { - IStatus* (CLOOP_CARG *createStatus)(IFactory* self) throw(); - ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) throw(); - ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) throw(); - ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) throw(); + IStatus* (CLOOP_CARG *createStatus)(IFactory* self) CLOOP_NOEXCEPT; + ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT; + ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT; + ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT; }; protected: @@ -125,7 +148,7 @@ namespace calc } public: - static const unsigned VERSION = 2; + static CLOOP_CONSTEXPR unsigned VERSION = CALC_IFACTORY_VERSION; IStatus* createStatus() { @@ -158,15 +181,17 @@ namespace calc } }; +#define CALC_ICALCULATOR_VERSION 4u + class ICalculator : public IDisposable { public: struct VTable : public IDisposable::VTable { - int (CLOOP_CARG *sum)(const ICalculator* self, IStatus* status, int n1, int n2) throw(); - int (CLOOP_CARG *getMemory)(const ICalculator* self) throw(); - void (CLOOP_CARG *setMemory)(ICalculator* self, int n) throw(); - void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) throw(); + int (CLOOP_CARG *sum)(const ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT; + int (CLOOP_CARG *getMemory)(const ICalculator* self) CLOOP_NOEXCEPT; + void (CLOOP_CARG *setMemory)(ICalculator* self, int n) CLOOP_NOEXCEPT; + void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT; }; protected: @@ -180,7 +205,7 @@ namespace calc } public: - static const unsigned VERSION = 4; + static CLOOP_CONSTEXPR unsigned VERSION = CALC_ICALCULATOR_VERSION; template int sum(StatusType* status, int n1, int n2) const { @@ -223,14 +248,16 @@ namespace calc } }; +#define CALC_ICALCULATOR2_VERSION 6u + class ICalculator2 : public ICalculator { public: struct VTable : public ICalculator::VTable { - int (CLOOP_CARG *multiply)(const ICalculator2* self, IStatus* status, int n1, int n2) throw(); - void (CLOOP_CARG *copyMemory)(ICalculator2* self, const ICalculator* calculator) throw(); - void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) throw(); + int (CLOOP_CARG *multiply)(const ICalculator2* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT; + void (CLOOP_CARG *copyMemory)(ICalculator2* self, const ICalculator* calculator) CLOOP_NOEXCEPT; + void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) CLOOP_NOEXCEPT; }; protected: @@ -244,7 +271,7 @@ namespace calc } public: - static const unsigned VERSION = 6; + static CLOOP_CONSTEXPR unsigned VERSION = CALC_ICALCULATOR2_VERSION; template int multiply(StatusType* status, int n1, int n2) const { @@ -291,7 +318,7 @@ namespace calc this->cloopVTable = &vTable; } - static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT { try { @@ -342,7 +369,7 @@ namespace calc this->cloopVTable = &vTable; } - static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) throw() + static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) CLOOP_NOEXCEPT { try { @@ -355,7 +382,7 @@ namespace calc } } - static void CLOOP_CARG cloopsetCodeDispatcher(IStatus* self, int code) throw() + static void CLOOP_CARG cloopsetCodeDispatcher(IStatus* self, int code) CLOOP_NOEXCEPT { try { @@ -367,7 +394,7 @@ namespace calc } } - static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT { try { @@ -421,7 +448,7 @@ namespace calc this->cloopVTable = &vTable; } - static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) throw() + static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) CLOOP_NOEXCEPT { try { @@ -434,7 +461,7 @@ namespace calc } } - static ICalculator* CLOOP_CARG cloopcreateCalculatorDispatcher(IFactory* self, IStatus* status) throw() + static ICalculator* CLOOP_CARG cloopcreateCalculatorDispatcher(IFactory* self, IStatus* status) CLOOP_NOEXCEPT { StatusType status2(status); @@ -449,7 +476,7 @@ namespace calc } } - static ICalculator2* CLOOP_CARG cloopcreateCalculator2Dispatcher(IFactory* self, IStatus* status) throw() + static ICalculator2* CLOOP_CARG cloopcreateCalculator2Dispatcher(IFactory* self, IStatus* status) CLOOP_NOEXCEPT { StatusType status2(status); @@ -464,7 +491,7 @@ namespace calc } } - static ICalculator* CLOOP_CARG cloopcreateBrokenCalculatorDispatcher(IFactory* self, IStatus* status) throw() + static ICalculator* CLOOP_CARG cloopcreateBrokenCalculatorDispatcher(IFactory* self, IStatus* status) CLOOP_NOEXCEPT { StatusType status2(status); @@ -479,7 +506,7 @@ namespace calc } } - static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT { try { @@ -535,7 +562,7 @@ namespace calc this->cloopVTable = &vTable; } - static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) throw() + static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT { StatusType status2(status); @@ -550,7 +577,7 @@ namespace calc } } - static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) throw() + static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) CLOOP_NOEXCEPT { try { @@ -563,7 +590,7 @@ namespace calc } } - static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) throw() + static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) CLOOP_NOEXCEPT { try { @@ -575,7 +602,7 @@ namespace calc } } - static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) throw() + static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT { StatusType status2(status); @@ -589,7 +616,7 @@ namespace calc } } - static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT { try { @@ -648,7 +675,7 @@ namespace calc this->cloopVTable = &vTable; } - static int CLOOP_CARG cloopmultiplyDispatcher(const ICalculator2* self, IStatus* status, int n1, int n2) throw() + static int CLOOP_CARG cloopmultiplyDispatcher(const ICalculator2* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT { StatusType status2(status); @@ -663,7 +690,7 @@ namespace calc } } - static void CLOOP_CARG cloopcopyMemoryDispatcher(ICalculator2* self, const ICalculator* calculator) throw() + static void CLOOP_CARG cloopcopyMemoryDispatcher(ICalculator2* self, const ICalculator* calculator) CLOOP_NOEXCEPT { try { @@ -675,7 +702,7 @@ namespace calc } } - static void CLOOP_CARG cloopcopyMemory2Dispatcher(ICalculator2* self, const int* address) throw() + static void CLOOP_CARG cloopcopyMemory2Dispatcher(ICalculator2* self, const int* address) CLOOP_NOEXCEPT { try { @@ -687,7 +714,7 @@ namespace calc } } - static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) throw() + static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT { StatusType status2(status); @@ -702,7 +729,7 @@ namespace calc } } - static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) throw() + static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) CLOOP_NOEXCEPT { try { @@ -715,7 +742,7 @@ namespace calc } } - static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) throw() + static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) CLOOP_NOEXCEPT { try { @@ -727,7 +754,7 @@ namespace calc } } - static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) throw() + static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT { StatusType status2(status); @@ -741,7 +768,7 @@ namespace calc } } - static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT { try { diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 32d004e8a7..9a59d45a71 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -12787,7 +12787,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* } } - HazardPtr func(FB_FUNCTION); + Function* func = nullptr; if (!node->function) { func = Function::lookup(tdbb, name, false); @@ -12917,7 +12917,7 @@ ValueExprNode* UdfCallNode::copy(thread_db* tdbb, NodeCopier& copier) const node->function = function; else { - HazardPtr func = Function::lookup(tdbb, name, false); + Function* func = Function::lookup(tdbb, name, false); node->function = copier.csb->csb_resources.registerResource(tdbb, Resource::rsc_function, func, func->getId()); } return node; diff --git a/src/dsql/NodePrinter.h b/src/dsql/NodePrinter.h index 80703764c2..39bdcb11f6 100644 --- a/src/dsql/NodePrinter.h +++ b/src/dsql/NodePrinter.h @@ -30,12 +30,13 @@ namespace Jrd { +class Resources; class NodePrinter { public: - explicit NodePrinter(unsigned aIndent = 0) - : indent(aIndent) + NodePrinter(const Resources* aResources, unsigned aIndent = 0) + : indent(aIndent), resources(aResources) { } @@ -337,6 +338,11 @@ private: private: unsigned indent; + +public: + const Resources* resources; + +private: Firebird::ObjectsArray stack; Firebird::string text; }; diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index c846c15b23..75e75dc8e3 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -2932,7 +2932,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr const auto blrStartPos = csb->csb_blr_reader.getPos(); jrd_prc* procedure = NULL; - HazardPtr proc(FB_FUNCTION); + HazardPtr proc; QualifiedName name; if (blrOp == blr_exec_pid) @@ -10741,7 +10741,7 @@ static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jr for (FB_SIZE_T i = 0; i < trigger->getCount(tdbb); i++) { - HazardPtr tr(FB_FUNCTION); + HazardPtr tr; if (!trigger->load(tdbb, i, tr)) continue; if (!tr->sysTrigger) diff --git a/src/include/fb_types.h b/src/include/fb_types.h index 24ecf03d56..8fbfc053a3 100644 --- a/src/include/fb_types.h +++ b/src/include/fb_types.h @@ -150,13 +150,15 @@ inline T FB_ALIGN(T n, uintptr_t b) return (T) ((((uintptr_t) n) + b - 1) & ~(b - 1)); } -// Various object IDs (longer-than-32-bit) +// Various object IDs typedef FB_UINT64 AttNumber; typedef FB_UINT64 TraNumber; typedef FB_UINT64 StmtNumber; typedef FB_UINT64 CommitNumber; typedef ULONG SnapshotHandle; +typedef ULONG MdcVersion; +typedef USHORT MetaId; typedef SINT64 SavNumber; #endif /* INCLUDE_FB_TYPES_H */ diff --git a/src/include/gen/Firebird.pas b/src/include/gen/Firebird.pas index 2b85a1feb0..b9faf524b0 100644 --- a/src/include/gen/Firebird.pas +++ b/src/include/gen/Firebird.pas @@ -5312,6 +5312,7 @@ const isc_invalid_blob_util_handle = 335545283; isc_bad_temp_blob_id = 335545284; isc_ods_upgrade_err = 335545285; + isc_bad_par_workers = 335545286; isc_gfix_db_name = 335740929; isc_gfix_invalid_sw = 335740930; isc_gfix_incmp_sw = 335740932; diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 85a675ff69..679ebbcdca 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -138,10 +138,6 @@ void Jrd::Attachment::destroy(Attachment* const attachment) jrd_tra::destroy(NULL, sysTransaction); } - - attachment->att_delayed_delete.garbageCollect(HazardDelayedDelete::GarbageCollectMethod::GC_FORCE); - HZ_DEB(fprintf(stderr, "Attachment::destroy=>delayedDelete to DBB\n")); - dbb->dbb_delayed_delete.delayedDelete(attachment->att_delayed_delete.getHazardPointers()); } MemoryPool* const pool = attachment->att_pool; @@ -241,8 +237,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, JProvider* provider att_stmt_timeout(0), att_batches(*pool), att_initial_options(*pool), - att_provider(provider), - att_delayed_delete(*dbb->dbb_permanent, *pool) + att_provider(provider) { att_internal.grow(irq_MAX); att_dyn_req.grow(drq_MAX); diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index a6ce886bb5..18391f721c 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -784,9 +784,6 @@ private: Lock* att_repl_lock; // Replication set lock JProvider* att_provider; // Provider which created this attachment - -public: - HazardDelayedDelete att_delayed_delete; }; diff --git a/src/jrd/Collation.cpp b/src/jrd/Collation.cpp index 6e7bcc4d1e..6550669f32 100644 --- a/src/jrd/Collation.cpp +++ b/src/jrd/Collation.cpp @@ -1130,12 +1130,16 @@ void Collation::release(thread_db* tdbb) fb_assert(useCount >= 0); if (existenceLock) + { + if (!tdbb) + tdbb = JRD_get_thread_data(); LCK_release(tdbb, existenceLock); + } useCount = 0; } -void Collation::destroy(thread_db* tdbb) +void Collation::destroy(thread_db* tdbb, int xxx) { fprintf(stderr, "Collation::destroy(%p) tt=%p\n", this, tt); fb_assert(useCount == 0); @@ -1150,8 +1154,8 @@ void Collation::destroy(thread_db* tdbb) delete existenceLock; existenceLock = NULL; - fprintf(stderr, "delayedDelete collation %p\n", this); - this->delayedDelete(tdbb); + fprintf(stderr, "retire collation %p\n", this); + //this->retire(); } void Collation::incUseCount(thread_db* /*tdbb*/) diff --git a/src/jrd/Collation.h b/src/jrd/Collation.h index ebec18d7f1..1492789651 100644 --- a/src/jrd/Collation.h +++ b/src/jrd/Collation.h @@ -80,7 +80,7 @@ public: virtual PatternMatcher* createContainsMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl) = 0; void release(thread_db* tdbb); - void destroy(thread_db* tdbb); + void destroy(thread_db* tdbb, int); void incUseCount(thread_db* tdbb); void decUseCount(thread_db* tdbb); @@ -89,11 +89,6 @@ public: return true; } - void removeFromCache(thread_db* tdbb) override - { - delayedDelete(tdbb); - } - const char* c_name() const override { return name.c_str(); diff --git a/src/jrd/Database.cpp b/src/jrd/Database.cpp index 412aa8d312..5680952c20 100644 --- a/src/jrd/Database.cpp +++ b/src/jrd/Database.cpp @@ -622,8 +622,7 @@ namespace Jrd dbb_replica_mode(REPLICA_NONE), dbb_compatibility_index(~0U), dbb_dic(*p), - dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p)), - dbb_delayed_delete(*p, *p) + dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p)) { dbb_pools.add(p); } diff --git a/src/jrd/Database.h b/src/jrd/Database.h index 78d59b12e8..9d52a840e4 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -440,8 +440,6 @@ public: Firebird::InitInstance dbb_keywords_map; MetadataCache* dbb_mdc; - HazardDelayedDelete dbb_delayed_delete; - Firebird::Mutex dbb_dd_mutex; // returns true if primary file is located on raw device bool onRawDevice() const; diff --git a/src/jrd/ExtEngineManager.cpp b/src/jrd/ExtEngineManager.cpp index 5e6ed67ecf..61c6b6e40b 100644 --- a/src/jrd/ExtEngineManager.cpp +++ b/src/jrd/ExtEngineManager.cpp @@ -1419,7 +1419,7 @@ void ExtEngineManager::makeFunction(thread_db* tdbb, CompilerScratch* csb, Jrd:: csbPool, extOutMessageNode, intOutMessageNode); Statement* statement = udf->getStatement(); - PAR_preparsed_node(tdbb, nullRel, mainNode, NULL, &csb, &statement, false, 0); + PAR_preparsed_node(tdbb, nullptr, mainNode, NULL, &csb, &statement, false, 0); udf->setStatement(statement); } catch (...) @@ -1562,7 +1562,7 @@ void ExtEngineManager::makeProcedure(thread_db* tdbb, CompilerScratch* csb, jrd_ mainNode->statements.add(extProcedureNode); Statement* statement = prc->getStatement(); - PAR_preparsed_node(tdbb, nullRel, mainNode, NULL, &csb, &statement, false, 0); + PAR_preparsed_node(tdbb, nullptr, mainNode, NULL, &csb, &statement, false, 0); prc->setStatement(statement); } catch (...) @@ -1662,9 +1662,7 @@ void ExtEngineManager::makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::T trg->extTrigger); mainNode->statements.add(extTriggerNode); - HazardPtr rel(FB_FUNCTION); - rel.safePointer(trg->relation); - PAR_preparsed_node(tdbb, rel, mainNode, NULL, &csb, &trg->statement, true, 0); + PAR_preparsed_node(tdbb, trg->relation, mainNode, NULL, &csb, &trg->statement, true, 0); } catch (...) { diff --git a/src/jrd/Function.epp b/src/jrd/Function.epp index 622bfdedfb..c3a410f9e3 100644 --- a/src/jrd/Function.epp +++ b/src/jrd/Function.epp @@ -59,13 +59,13 @@ DATABASE DB = FILENAME "ODS.RDB"; const char* const Function::EXCEPTION_MESSAGE = "The user defined function: \t%s\n\t referencing" " entrypoint: \t%s\n\t in module: \t%s\n\tcaused the fatal exception:"; -HazardPtr Function::lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags) +Function* Function::lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags) { Attachment* const attachment = tdbb->getAttachment(); Database* const dbb = tdbb->getDatabase(); - HazardPtr check_function(tdbb, FB_FUNCTION); + Function* check_function = nullptr; - HazardPtr function = dbb->dbb_mdc->getFunction(tdbb, id); + Function* function = dbb->dbb_mdc->getFunction(tdbb, id, noscan); if (function && function->getId() == id && !(function->flags & Routine::FLAG_CLEARED) && @@ -85,7 +85,7 @@ HazardPtr Function::lookup(thread_db* tdbb, USHORT id, bool return_del // We need to look up the function in RDB$FUNCTIONS - function.clear(); + function = nullptr; AutoCacheRequest request(tdbb, irq_l_fun_id, IRQ_REQUESTS); @@ -109,14 +109,14 @@ HazardPtr Function::lookup(thread_db* tdbb, USHORT id, bool return_del return function; } -HazardPtr Function::lookup(thread_db* tdbb, const QualifiedName& name, bool noscan) +Function* Function::lookup(thread_db* tdbb, const QualifiedName& name, bool noscan) { Attachment* const attachment = tdbb->getAttachment(); Database* const dbb = tdbb->getDatabase(); // See if we already know the function by name - HazardPtr function = dbb->dbb_mdc->lookupFunction(tdbb, name, noscan ? 0 : Routine::FLAG_SCANNED, + Function* function = dbb->dbb_mdc->lookupFunction(tdbb, name, noscan ? 0 : Routine::FLAG_SCANNED, Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED | Routine::FLAG_BEING_SCANNED | Routine::FLAG_BEING_ALTERED); if (function) @@ -127,7 +127,7 @@ HazardPtr Function::lookup(thread_db* tdbb, const QualifiedName& name, // We need to look up the function in RDB$FUNCTIONS - function.clear(); + function = nullptr; AutoCacheRequest request(tdbb, irq_l_fun_name, IRQ_REQUESTS); @@ -143,12 +143,12 @@ HazardPtr Function::lookup(thread_db* tdbb, const QualifiedName& name, return function; } -HazardPtr Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT flags) +Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT flags) { Jrd::Attachment* attachment = tdbb->getAttachment(); jrd_tra* sysTransaction = attachment->getSysTransaction(); Database* const dbb = tdbb->getDatabase(); - HazardPtr function = dbb->dbb_mdc->getFunction(tdbb, id, true); + Function* function = dbb->dbb_mdc->getFunction(tdbb, id, noscan); if (function && !(function->flags & Routine::FLAG_OBSOLETE)) { @@ -163,29 +163,28 @@ HazardPtr Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc } } - Function* newFun = function.getPointer(); - function.clear(); - MemoryPool& pool = dbb->dbb_mdc->getPool(); - if (!newFun) - newFun = FB_NEW_POOL(*dbb->dbb_permanent) Function(pool); + return nullptr; +} - try - { - newFun->flags |= (Routine::FLAG_BEING_SCANNED | flags); - newFun->flags &= ~(Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED); - - newFun->setId(id); - function = dbb->dbb_mdc->setFunction(tdbb, id, newFun); - newFun = nullptr; +Function* Function::create(thread_db* tdbb, MetaId id, CacheObject::Flag flags) +{ + Jrd::Attachment* attachment = tdbb->getAttachment(); + jrd_tra* sysTransaction = attachment->getSysTransaction(); + Database* const dbb = tdbb->getDatabase(); + Function* function = FB_NEW_POOL(*dbb->dbb_permanent) Function(*dbb->dbb_permanent, id); +/* if (!function->existenceLock) { function->existenceLock = FB_NEW_POOL(pool) ExistenceLock(pool, tdbb, LCK_fun_exist, function->getId(), function.getPointer()); } +*/ - if (!noscan) + try { + if (!(flags & CacheFlag::NOSCAN)) + { AutoCacheRequest request_fun(tdbb, irq_l_functions, IRQ_REQUESTS); FOR(REQUEST_HANDLE request_fun) @@ -336,7 +335,7 @@ HazardPtr Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc try { parameter->prm_default_value = static_cast(MET_parse_blob( - tdbb, nullRel, &default_value, nullptr, nullptr, false, false)); + tdbb, nullptr, &default_value, nullptr, nullptr, false, false)); } catch (const Exception&) { @@ -419,7 +418,7 @@ HazardPtr Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc else body.getBuffer(1)[0] = 0; - dbb->dbb_extManager->makeFunction(tdbb, csb, function.getPointer(), X.RDB$ENGINE_NAME, + dbb->dbb_extManager->makeFunction(tdbb, csb, function, X.RDB$ENGINE_NAME, (X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin()); if (!function->fun_external) @@ -477,20 +476,12 @@ HazardPtr Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc } } END_FOR - } - - // Make sure that it is really being scanned - fb_assert(function->flags & Routine::FLAG_BEING_SCANNED); - - function->flags &= ~Routine::FLAG_BEING_SCANNED; - + } // if noscan } // try catch (const Exception&) { - if (newFun) - newFun->delayedDelete(tdbb); if (function) - function->flags &= ~(Routine::FLAG_BEING_SCANNED | Routine::FLAG_SCANNED); + Function::destroy(function); throw; } @@ -500,12 +491,7 @@ HazardPtr Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc bool Function::checkCache(thread_db* tdbb) const { - return tdbb->getDatabase()->dbb_mdc->getFunction(tdbb, getId()) == this; -} - -void Function::clearCache(thread_db* tdbb) -{ - tdbb->getDatabase()->dbb_mdc->setFunction(tdbb, getId(), nullptr); + return tdbb->getDatabase()->dbb_mdc->getFunction(tdbb, getId(), true) == this; } bool Function::reload(thread_db* tdbb) diff --git a/src/jrd/Function.h b/src/jrd/Function.h index ccb69bc352..4a497d38c0 100644 --- a/src/jrd/Function.h +++ b/src/jrd/Function.h @@ -38,8 +38,8 @@ namespace Jrd static const char* const EXCEPTION_MESSAGE; public: - static HazardPtr lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags); - static HazardPtr lookup(thread_db* tdbb, const QualifiedName& name, bool noscan); + static Function* lookup(thread_db* tdbb, MetaId id, bool return_deleted, bool noscan, USHORT flags); + static Function* lookup(thread_db* tdbb, const QualifiedName& name, bool noscan); explicit Function(MemoryPool& p) : Routine(p), @@ -53,7 +53,22 @@ namespace Jrd { } - static HazardPtr loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT flags); +private: + Function(MemoryPool& p, MetaId id) + : Routine(p, id), + fun_entrypoint(NULL), + fun_inputs(0), + fun_return_arg(0), + fun_temp_length(0), + fun_exception_message(p), + fun_deterministic(false), + fun_external(NULL) + { + } + +public: + static Function* loadMetadata(thread_db* tdbb, MetaId id, bool noscan, USHORT flags); + static Function* create(thread_db* tdbb, MetaId id, CacheObject::Flag flags); public: virtual int getObjectType() const @@ -67,18 +82,20 @@ namespace Jrd } virtual bool checkCache(thread_db* tdbb) const; - virtual void clearCache(thread_db* tdbb); + private: virtual ~Function() { delete fun_external; } + public: virtual void releaseExternal() { delete fun_external; fun_external = NULL; } + public: int (*fun_entrypoint)(); // function entrypoint USHORT fun_inputs; // input arguments diff --git a/src/jrd/HazardPtr.cpp b/src/jrd/HazardPtr.cpp index 257ba056db..b49698709e 100644 --- a/src/jrd/HazardPtr.cpp +++ b/src/jrd/HazardPtr.cpp @@ -39,171 +39,6 @@ HazardObject::~HazardObject() CacheObject* TRAP = nullptr; -int HazardObject::delayedDelete(thread_db* tdbb) -{ - HazardDelayedDelete* dd = HazardBase::getHazardDelayed(tdbb); -// if (this == TRAP) -// abort(); - dd->delayedDelete(this); - return 0; -} - -HazardDelayedDelete* HazardBase::getHazardDelayed(thread_db* tdbb) -{ - if (!tdbb) - tdbb = JRD_get_thread_data(); - fb_assert(tdbb); - - Attachment* att = tdbb->getAttachment(); - if (att) - return &att->att_delayed_delete; - - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // what about locking object in database? (dbb_delayed_delete) - Database* dbb = tdbb->getDatabase(); - fb_assert(dbb); - return &dbb->dbb_delayed_delete; -} - -HazardDelayedDelete* HazardBase::getHazardDelayed(Attachment* att) -{ - return &att->att_delayed_delete; -} - -void HazardDelayedDelete::add(const void* ptr, const char* from) -{ - HZ_DEB(fprintf(stderr, "HazardDelayedDelete::add %s %p\n", from, ptr)); - // as long as we access our own hazard pointers use of write accessor is always OK - auto hp = hazardPointers.writeAccessor(); - - // 1. Search for holes - for (unsigned n = 0; n < hp->getCount(); ++n) - { - if (hp->value(n) == nullptr) - { - // store - hp->value(n) = ptr; - return; - } - } - - // 2. Grow if needed - if (!hp->hasSpace()) - hazardPointers.grow(this); - - // 3. Append - hp = hazardPointers.writeAccessor(); - *(hp->add()) = ptr; -} - -void HazardDelayedDelete::remove(const void* ptr, const char* from) -{ - HZ_DEB(fprintf(stderr, "HazardDelayedDelete::remove %s %p\n", from, ptr)); - // as long as we access our own hazard pointers use of write accessor is always OK - auto hp = hazardPointers.writeAccessor(); - - for (unsigned n = 0; n < hp->getCount(); ++n) - { - if (hp->value(n) == ptr) - { - hp->value(n) = nullptr; - hp->truncate(nullptr); - return; - } - } - - fb_assert(!"Required ptr not found in HazardDelayedDelete::remove"); -} - -void HazardDelayedDelete::delayedDelete(HazardObject* mem, bool gc) -{ - HZ_DEB(fprintf(stderr, "HazardDelayedDelete::delayedDelete %p\n", mem)); - - if (mem) - toDelete.push(mem); - - if (gc) - garbageCollect(GarbageCollectMethod::GC_NORMAL); -} - -void HazardDelayedDelete::copyHazardPointers(LocalHP& local, HazardPtr& from) -{ - for (unsigned n = 0; n < from->getCount(); ++n) - { - const void* ptr = from->value(n); - if (ptr) - local.push(ptr); - } -} - -void HazardDelayedDelete::copyHazardPointers(thread_db* tdbb, LocalHP& local, Attachment* from) -{ - for (Attachment* attachment = from; attachment; attachment = attachment->att_next) - { - HazardPtr hp = attachment->att_delayed_delete.hazardPointers.readAccessor(tdbb); - copyHazardPointers(local, hp); - } -} - - -void HazardDelayedDelete::garbageCollect(GarbageCollectMethod gcMethod) -{ - if (gcMethod == GarbageCollectMethod::GC_NORMAL && toDelete.getCount() < DELETED_LIST_SIZE) - return; - - thread_db* tdbb = JRD_get_thread_data(); - Database* database = tdbb->getDatabase(); - - // collect hazard pointers from all atachments - LocalHP localCopy; - localCopy.setSortMode(FB_ARRAY_SORT_MANUAL); - { - Sync dbbSync(&database->dbb_sync, FB_FUNCTION); - if (!database->dbb_sync.ourExclusiveLock()) - dbbSync.lock(SYNC_SHARED); - - copyHazardPointers(tdbb, localCopy, database->dbb_attachments); - copyHazardPointers(tdbb, localCopy, database->dbb_sys_attachments); - - HazardPtr hp = database->dbb_delayed_delete.hazardPointers.readAccessor(tdbb); - copyHazardPointers(localCopy, hp); - } - localCopy.sort(); - - // delete what can be deleted - unsigned keep = 0; - for (unsigned i = 0; i < toDelete.getCount(); ++i) - { - if (localCopy.exist(toDelete[i])) - toDelete[keep++] = toDelete[i]; - else - delete toDelete[i]; - - if (i + 1 > keep) - toDelete[i] = nullptr; - } - toDelete.shrink(keep); - - if (gcMethod != GarbageCollectMethod::GC_FORCE || keep == 0) - return; - - // Pass remaining to Database - MutexLockGuard g(database->dbb_dd_mutex, FB_FUNCTION); - - database->dbb_delayed_delete.garbageCollect(GarbageCollectMethod::GC_NORMAL); - for (unsigned i = 0; i < toDelete.getCount(); ++i) - { - database->dbb_delayed_delete.add(toDelete[i], FB_FUNCTION); - toDelete[i] = nullptr; - } - toDelete.shrink(0); -} - -HazardDelayedDelete::HazardPointers* HazardDelayedDelete::getHazardPointers() -{ - // as long as we access our own hazard pointers single relaxed load is OK - return hazardPointers.writeAccessor(); -} bool CacheObject::checkObject(thread_db*, Arg::StatusVector&) { diff --git a/src/jrd/HazardPtr.h b/src/jrd/HazardPtr.h index 71f3ae27be..d2e3b79115 100644 --- a/src/jrd/HazardPtr.h +++ b/src/jrd/HazardPtr.h @@ -36,169 +36,126 @@ #include "../common/gdsassert.h" #include "fb_blk.h" -#include +#include +#include + +#include namespace Jrd { - class thread_db; - class Attachment; - class HazardDelayedDelete; - class HazardObject { - friend HazardDelayedDelete; protected: + void retire() + { + fb_assert(this); + + struct Disposer + { + void operator()(HazardObject* ho) + { + fb_assert(ho); + delete ho; + } + }; + + cds::gc::DHP::retire(this); + } + virtual ~HazardObject(); - public: - int delayedDelete(thread_db* tdbb); - }; - - class HazardBase - { - protected: - explicit HazardBase(thread_db* tdbb) - : hazardDelayed(getHazardDelayed(tdbb)) - { } - - explicit HazardBase(Attachment* att) - : hazardDelayed(getHazardDelayed(att)) - { } - - explicit HazardBase(HazardDelayedDelete* hd) - : hazardDelayed(hd) - { } - - HazardBase() - : hazardDelayed(nullptr) - { } - - inline void add(const void* hazardPointer, const char* from); - inline void remove(const void* hazardPointer, const char* from); - - private: - HazardDelayedDelete* hazardDelayed; - - public: - static HazardDelayedDelete* getHazardDelayed(thread_db* tdbb = nullptr); - static HazardDelayedDelete* getHazardDelayed(Attachment* att); }; template - class HazardPtr : public HazardBase + class HazardPtr : private cds::gc::DHP::Guard { + typedef cds::gc::DHP::Guard inherited; + static_assert(std::is_base_of::value, "class derived from HazardObject should be used"); + public: - HazardPtr(const char* F) - : hazardPointer(nullptr), - frm(F) - { } + HazardPtr() = default; - template - explicit HazardPtr(DDS* par, const char* F) - : HazardBase(par), - hazardPointer(nullptr), - frm(F) - { } - - template - HazardPtr(DDS* par, const std::atomic& from, const char* F) - : HazardBase(par), - hazardPointer(nullptr), - frm(F) + HazardPtr(const atomics::atomic& from) { - set(from); + protect(from); } - HazardPtr(const HazardPtr& copy) - : HazardBase(copy), - hazardPointer(nullptr), - frm(copy.frm) + HazardPtr(const HazardPtr& copyFrom) { - reset(copy.hazardPointer); - frm = copy.frm; + copy(copyFrom); } - HazardPtr(HazardPtr&& move) - : HazardBase(move), - hazardPointer(nullptr), - frm(move.frm) + HazardPtr(HazardPtr&& moveFrom) = default; + + template + HazardPtr(const HazardPtr& copyFrom) { - hazardPointer = move.releasePointer(); + checkAssign(); + copy(copyFrom); } template - HazardPtr(const HazardPtr& copy) - : HazardBase(copy), - hazardPointer(nullptr), - frm(copy.frm) + HazardPtr(HazardPtr&& moveFrom) + : inherited(std::move(moveFrom)) { - reset(copy.getPointer()); - } - - template - HazardPtr(HazardPtr&& move) - : HazardBase(move), - hazardPointer(nullptr), - frm(move.frm) - { - hazardPointer = move.releasePointer(); + checkAssign(); } ~HazardPtr() - { - reset(nullptr); - } -/* - T* unsafePointer() const // to be removed - { - return getPointer(); - } - */ + { } + T* getPointer() const { - return hazardPointer; + return get(); } T* releasePointer() { - T* rc = hazardPointer; - hazardPointer = nullptr; + T* rc = get(); + clear(); return rc; } - void set(const std::atomic& from) + void set(const atomics::atomic& from) { - T* v = from.load(std::memory_order_relaxed); - do - { - reset(v); - v = from.load(std::memory_order_acquire); - } while (hazardPointer != v); + protect(from); } - // atomically replaces 'where' with 'newVal', using *this as old value for comparison + /*/ atomically replaces 'where' with 'newVal', using *this as old value for comparison // always sets *this to actual data from 'where' - bool replace(std::atomic* where, T* newVal) + bool replace(atomics::atomic& where, T* newVal) { - T* val = hazardPointer; - bool rc = where->compare_exchange_strong(val, newVal, + T* val = get(); + bool rc = where.compare_exchange_strong(val, newVal, std::memory_order_release, std::memory_order_acquire); - reset(rc ? newVal : val); + assign(rc ? newVal : val); + return rc; + } +*/ + // atomically replaces 'where' with 'newVal', using *this as old value for comparison + // sets *this to actual data from 'where' if replace failed + bool replace2(atomics::atomic& where, T* newVal) + { + T* val = get(); + bool rc = where.compare_exchange_strong(val, newVal, + std::memory_order_release, std::memory_order_acquire); + if(rc) + assign(newVal); return rc; } void clear() { - reset(nullptr); + inherited::clear(); } T* operator->() { - return hazardPointer; + return get(); } const T* operator->() const { - return hazardPointer; + return get(); } /* template @@ -209,85 +166,68 @@ namespace Jrd { */ bool operator!() const { - return hazardPointer == nullptr; + return !hasData(); } bool hasData() const { - return hazardPointer != nullptr; + return get_native() != nullptr; } bool operator==(const T* v) const { - return hazardPointer == v; + return get() == v; } bool operator!=(const T* v) const { - return hazardPointer != v; + return get() != v; } operator bool() const { - return hazardPointer != nullptr; + return hasData(); } HazardPtr& operator=(const HazardPtr& copyAssign) { - reset(copyAssign.hazardPointer, ©Assign); + copy(copyAssign); return *this; } HazardPtr& operator=(HazardPtr&& moveAssign) { - if (hazardPointer) - remove(hazardPointer, frm); - HazardBase::operator=(moveAssign); - hazardPointer = moveAssign.releasePointer(); + inherited::operator=(std::move(moveAssign)); return *this; } template HazardPtr& operator=(const HazardPtr& copyAssign) { - reset(copyAssign.getPointer(), ©Assign); + checkAssign(); + copy(copyAssign); return *this; } template HazardPtr& operator=(HazardPtr&& moveAssign) { - if (hazardPointer) - remove(hazardPointer, FB_FUNCTION); - HazardBase::operator=(moveAssign); - hazardPointer = moveAssign.releasePointer(); + checkAssign(); + inherited::operator=(std::move(moveAssign)); return *this; } void safePointer(T* ptr) { - reset(ptr); + assign(ptr); } private: - void reset(T* newPtr, const HazardBase* newBase = nullptr) + template + struct checkAssign { - if (newPtr != hazardPointer) - { - if (hazardPointer) - remove(hazardPointer, frm); - if (newBase) - HazardBase::operator=(*newBase); - if (newPtr) - add(newPtr, frm); - hazardPointer = newPtr; - } - } - - T* hazardPointer; - - public: - const char* frm; + static_assert(std::is_trivially_assignable::value, "Invalid type of pointer assigned"); + }; }; template @@ -310,11 +250,10 @@ namespace Jrd { // Shared read here means that any thread can read from vector using HP. - // It can be modified only in single thread, and it's caller's responsibility that modifying thread is single. - // It's also callers responsibility to destroy Generation when deleting SharedReadVector: - // in dtor we do not have enough information to do it correctly, default delayedDelete() may be already wrong. + // It can be modified only in single thread, and it's caller's responsibility + // that modifying thread is single. - template + template class SharedReadVector : public Firebird::PermanentStorage { public: @@ -382,409 +321,75 @@ namespace Jrd { while (count && data[count - 1] == notValue) count--; } + + static void destroy(Generation* gen) + { + // delay delete - someone else may access it + gen->retire(); + } }; SharedReadVector(MemoryPool& p) : Firebird::PermanentStorage(p), - v(Generation::create(getPool(), CAP)) + currentData(Generation::create(getPool(), CAP)) { } Generation* writeAccessor() { - return v.load(std::memory_order_acquire); + return currentData.load(std::memory_order_acquire); } - template - HazardPtr readAccessor(DDS* par) const + HazardPtr readAccessor() const { - return HazardPtr(par, v, FB_FUNCTION); + return HazardPtr(currentData); } - inline void grow(HazardDelayedDelete* dd, FB_SIZE_T newSize = 0); + void grow(FB_SIZE_T newSize = 0) + { + for(;;) + { + HazardPtr current(currentData); + if (newSize && (current->getCapacity() >= newSize)) + return; + + FB_SIZE_T doubleSize = current->getCapacity() * 2; + if (newSize > doubleSize) + doubleSize = newSize; + + Generation* newGeneration = Generation::create(getPool(), doubleSize); + Generation* oldGeneration = current.getPointer(); + newGeneration->add(oldGeneration); + if (current.replace2(currentData, newGeneration)) + { + Generation::destroy(oldGeneration); + break; + } + else + { + // Use plain delete - this instance is not known to anybody else + delete newGeneration; + } + } + } + + ~SharedReadVector() + { + Generation::destroy(currentData.load(std::memory_order_acquire)); + } private: - std::atomic v; + atomics::atomic currentData; }; - - class HazardDelayedDelete : public Firebird::PermanentStorage - { - private: - static const unsigned int INITIAL_SIZE = 4; - static const unsigned int DELETED_LIST_SIZE = 32; - - typedef Firebird::SortedArray> LocalHP; - - public: - enum class GarbageCollectMethod {GC_NORMAL, GC_ALL, GC_FORCE}; - // In this and only this case disable GC in delayedDelete() - typedef SharedReadVector HazardPointersStorage; - typedef HazardPointersStorage::Generation HazardPointers; - - HazardDelayedDelete(MemoryPool& dbbPool, MemoryPool& attPool) - : Firebird::PermanentStorage(dbbPool), - toDelete(attPool), - hazardPointers(getPool()) - { } - - void add(const void* ptr, const char* from); - void remove(const void* ptr, const char* from); - - void delayedDelete(HazardObject* mem, bool gc = true); - void garbageCollect(GarbageCollectMethod gcMethod); - - // required in order to correctly pass that memory to DBB when destroying attachment - HazardPointers* getHazardPointers(); - - private: - static void copyHazardPointers(LocalHP& local, HazardPtr& from); - static void copyHazardPointers(thread_db* tdbb, LocalHP& local, Attachment* from); - - Firebird::HalfStaticArray toDelete; - HazardPointersStorage hazardPointers; - }; - - - inline void HazardBase::add(const void* hazardPointer, const char* from) - { - if (!hazardDelayed) - hazardDelayed = getHazardDelayed(); - hazardDelayed->add(hazardPointer, from); - } - - inline void HazardBase::remove(const void* hazardPointer, const char* from) - { - if (!hazardDelayed) - hazardDelayed = getHazardDelayed(); - hazardDelayed->remove(hazardPointer, from); - } - - template - inline void SharedReadVector::grow(HazardDelayedDelete* dd, FB_SIZE_T newSize) - { - Generation* oldGeneration = writeAccessor(); - if (newSize && (oldGeneration->getCapacity() >= newSize)) - return; - - FB_SIZE_T doubleSize = oldGeneration->getCapacity() * 2; - if (newSize < doubleSize) - newSize = doubleSize; - - Generation* newGeneration = Generation::create(getPool(), newSize); - newGeneration->add(oldGeneration); - v.store(newGeneration, std::memory_order_release); - - // delay delete - someone else may access it - dd->delayedDelete(oldGeneration, GC_ENABLED); - } - - - class CacheObject : public HazardObject + class thread_db; + class CacheObject { public: + typedef unsigned Flag; virtual bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) /*const*/; virtual void afterUnlock(thread_db* tdbb, unsigned flags); virtual void lockedExcl [[noreturn]] (thread_db* tdbb) /*const*/; virtual const char* c_name() const = 0; - virtual void removeFromCache(thread_db* tdbb) = 0; - }; - - template - class HazardArray : public Firebird::PermanentStorage - { - public: - static const unsigned SUBARRAY_SIZE = 1 << SUBARRAY_SHIFT; - static const unsigned SUBARRAY_MASK = SUBARRAY_SIZE - 1; - - typedef std::atomic SubArrayElement; - typedef std::atomic ArrayElement; - typedef SharedReadVector Storage; - - explicit HazardArray(MemoryPool& pool) - : Firebird::PermanentStorage(pool), - m_objects(getPool()) - {} - - SLONG lookup(thread_db* tdbb, const typename Object::Key& key, HazardPtr* object = nullptr) const - { - auto a = m_objects.readAccessor(tdbb); - for (FB_SIZE_T i = 0; i < a->getCount(); ++i) - { - SubArrayElement* const sub = a->value(i).load(std::memory_order_relaxed); - if (!sub) - continue; - - for (SubArrayElement* end = &sub[SUBARRAY_SIZE]; sub < end--;) - { - HazardPtr val(tdbb, *end, FB_FUNCTION); - if (val.hasData() && val->getKey() == key) - { - if (object) - *object = val; - return (SLONG)((i << SUBARRAY_SHIFT) + (end - sub)); - } - } - } - - return -1; - } - - ~HazardArray() - { - auto a = m_objects.writeAccessor(); - for (FB_SIZE_T i = 0; i < a->getCount(); ++i) - { - SubArrayElement* const sub = a->value(i).load(std::memory_order_relaxed); - if (!sub) - continue; - - for (SubArrayElement* end = &sub[SUBARRAY_SIZE]; sub < end--;) - delete *end; // no need using release here in HazardArray's dtor - - delete[] sub; - } - - // directly delete Generation - no need using delayedDelete() here, at least for MetadataCache - delete a; - } - - template - FB_SIZE_T getCount(DDS* par) const - { - return m_objects.readAccessor(par)->getCount() << SUBARRAY_SHIFT; - } - - static FB_SIZE_T getCount(const HazardPtr& v) - { - return v->getCount() << SUBARRAY_SHIFT; - } - - void grow(thread_db* tdbb, FB_SIZE_T reqSize) - { - fb_assert(reqSize > 0); - reqSize = ((reqSize - 1) >> SUBARRAY_SHIFT) + 1; - - Firebird::MutexLockGuard g(objectsGrowMutex, FB_FUNCTION); - - m_objects.grow(HazardBase::getHazardDelayed(tdbb), reqSize); - auto a = m_objects.writeAccessor(); - fb_assert(a->getCapacity() >= reqSize); - while (a->getCount() < reqSize) - { - SubArrayElement* sub = FB_NEW_POOL(getPool()) SubArrayElement[SUBARRAY_SIZE]; - memset(sub, 0, sizeof(SubArrayElement) * SUBARRAY_SIZE); - a->add()->store(sub, std::memory_order_release); - } - } -/* - HazardPtr store(thread_db* tdbb, FB_SIZE_T id, Object* const val) - { - if (id >= getCount(tdbb)) - grow(tdbb, id + 1); - - auto a = m_objects.readAccessor(tdbb); - SubArrayElement* sub = a->value(id >> SUBARRAY_SHIFT).load(std::memory_order_relaxed); - fb_assert(sub); - sub = &sub[id & SUBARRAY_MASK]; - - Object* oldVal = sub->load(std::memory_order_acquire); - while (!sub->compare_exchange_weak(oldVal, val, - std::memory_order_release, std::memory_order_acquire)); // empty body - if (oldVal) - { - HZ_DEB(fprintf(stderr, "store=>delayedDelete %p\n", oldVal)); - oldVal->removeFromCache(tdbb); - } - - return HazardPtr(tdbb, *sub, FB_FUNCTION); - } - */ - bool replace(thread_db* tdbb, FB_SIZE_T id, HazardPtr& oldVal, Object* const newVal) - { - if (id >= getCount(tdbb)) - grow(tdbb, id + 1); - - auto a = m_objects.readAccessor(tdbb); - SubArrayElement* sub = a->value(id >> SUBARRAY_SHIFT).load(std::memory_order_acquire); - fb_assert(sub); - sub = &sub[id & SUBARRAY_MASK]; - Object* was = oldVal.getPointer(); - - if (oldVal.replace(sub, newVal)) - { - if (was) - was->removeFromCache(tdbb); - return true; - } - return false; - } -/* - void store(thread_db* tdbb, FB_SIZE_T id, const HazardPtr& val) - { - store(tdbb, id, val.getPointer()); - } - */ - template - bool load(DDS* par, FB_SIZE_T id, HazardPtr& val) const - { - auto a = m_objects.readAccessor(par); - if (id < getCount(a)) - { - SubArrayElement* sub = a->value(id >> SUBARRAY_SHIFT).load(std::memory_order_acquire); - if (sub) - { - val.set(sub[id & SUBARRAY_MASK]); - if (val && val->hasData()) - return true; - } - } - - return false; - } - - template - HazardPtr load(DDS* par, FB_SIZE_T id) const - { - HazardPtr val(FB_FUNCTION); - if (!load(par, id, val)) - val.clear(); - return val; - } - - template - HazardPtr readAccessor(DDS* par) const - { - return m_objects.readAccessor(par); - } - - class Snapshot; - - class Iterator - { - public: - HazardPtr operator*() - { - return get(); - } - - HazardPtr operator->() - { - return get(); - } - - Iterator& operator++() - { - index = snap->locateData(index + 1); - return *this; - } - - bool operator==(const Iterator& itr) const - { - fb_assert(snap == itr.snap); - return index == itr.index; - } - - bool operator!=(const Iterator& itr) const - { - fb_assert(snap == itr.snap); - return index != itr.index; - } - - private: - void* operator new(size_t); - void* operator new[](size_t); - - public: - enum class Location {Begin, End}; - Iterator(const Snapshot* s, Location loc) - : snap(s), - hd(HazardPtr::getHazardDelayed()), - index(loc == Location::Begin ? snap->locateData(0) : - snap->data->getCount() << SUBARRAY_SHIFT) - { } - - HazardPtr get() - { - HazardPtr rc(hd, FB_FUNCTION); - if (!snap->load(index, rc)) - rc.clear(); - return rc; - } - - private: - const Snapshot* snap; - HazardDelayedDelete* hd; - FB_SIZE_T index; - }; - - class Snapshot - { - private: - void* operator new(size_t); - void* operator new[](size_t); - - public: - Snapshot(const HazardArray* array) - : hd(HazardPtr::getHazardDelayed()), - data(array->readAccessor(hd)) - { } - - Iterator begin() const - { - return Iterator(this, Iterator::Location::Begin); - } - - Iterator end() const - { - return Iterator(this, Iterator::Location::End); - } - - FB_SIZE_T locateData(FB_SIZE_T index) const - { - for (FB_SIZE_T i = index >> SUBARRAY_SHIFT; i < data->getCount(); ++i, index = 0) - { - SubArrayElement* const sub = data->value(i).load(std::memory_order_acquire); - if (!sub) - continue; - - for (FB_SIZE_T j = index & SUBARRAY_MASK; j < SUBARRAY_SIZE; ++j) - { - auto p = sub[j].load(std::memory_order_acquire); - if (p && p->hasData()) - return (i << SUBARRAY_SHIFT) + j; - } - } - return data->getCount() << SUBARRAY_SHIFT; - } - - bool load(FB_SIZE_T id, HazardPtr& val) const - { - if (id < (data->getCount() << SUBARRAY_SHIFT)) - { - SubArrayElement* sub = data->value(id >> SUBARRAY_SHIFT).load(std::memory_order_acquire); - if (sub) - { - val.set(sub[id & SUBARRAY_MASK]); - if (val && val->hasData()) - return true; - } - } - - return false; - } - - HazardDelayedDelete* hd; - HazardPtr data; - }; - - Snapshot snapshot() const - { - return Snapshot(this); - } - - private: - SharedReadVector m_objects; - Firebird::Mutex objectsGrowMutex; }; } // namespace Jrd diff --git a/src/jrd/Monitoring.cpp b/src/jrd/Monitoring.cpp index d1a4843198..ea9f5e70c7 100644 --- a/src/jrd/Monitoring.cpp +++ b/src/jrd/Monitoring.cpp @@ -648,12 +648,12 @@ RecordBuffer* SnapshotData::getData(int id) const RecordBuffer* SnapshotData::allocBuffer(thread_db* tdbb, MemoryPool& pool, int rel_id) { - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); fb_assert(relation); MET_scan_relation(tdbb, relation); fb_assert(relation->isVirtual()); - const Format* const format = MET_current(tdbb, relation.getPointer()); + const Format* const format = MET_current(tdbb, relation); fb_assert(format); RecordBuffer* const buffer = FB_NEW_POOL(pool) RecordBuffer(pool, format); @@ -708,7 +708,7 @@ void SnapshotData::putField(thread_db* tdbb, Record* record, const DumpField& fi SLONG rel_id; memcpy(&rel_id, field.data, field.length); - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); if (!relation || relation->rel_name.isEmpty()) return; diff --git a/src/jrd/ProfilerManager.cpp b/src/jrd/ProfilerManager.cpp index f100e96e3b..ca823df273 100644 --- a/src/jrd/ProfilerManager.cpp +++ b/src/jrd/ProfilerManager.cpp @@ -28,10 +28,11 @@ #include "../jrd/ids.h" #include "../jrd/recsrc/Cursor.h" #include "../jrd/dpm_proto.h" -#include "../jrd/lck_proto.h" +#include "../jrd/lck.h" #include "../jrd/met_proto.h" #include "../jrd/pag_proto.h" #include "../jrd/tra_proto.h" +#include "../jrd/Statement.h" using namespace Jrd; using namespace Firebird; diff --git a/src/jrd/RecordSourceNodes.cpp b/src/jrd/RecordSourceNodes.cpp index 8cb27731c3..5fed18b00c 100644 --- a/src/jrd/RecordSourceNodes.cpp +++ b/src/jrd/RecordSourceNodes.cpp @@ -528,7 +528,7 @@ LocalTableSourceNode* LocalTableSourceNode::copy(thread_db* tdbb, NodeCopier& co void LocalTableSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/, BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack) { - fb_assert(!csb->csb_view); // local tables cannot be inside a view + fb_assert(!csb->csb_view.isSet()); // local tables cannot be inside a view stack.push(this); // Assume that the source will be used. Push it on the final stream stack. @@ -572,7 +572,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* // Find relation either by id or by name AutoPtr aliasString; MetaName name; - HazardPtr rel(FB_FUNCTION); + CacheElement* rel = nullptr; switch (blrOp) { @@ -587,7 +587,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* csb->csb_blr_reader.getString(*aliasString); } - rel = MetadataCache::lookup_relation_id(tdbb, id, false); + rel = MetadataCache::lookupRelation(tdbb, id); if (!rel) name.printf("id %d", id); break; @@ -604,7 +604,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* csb->csb_blr_reader.getString(*aliasString); } - rel = MetadataCache::lookup_relation(tdbb, name); + rel = MetadataCache::lookupRelation(tdbb, name); break; } @@ -617,7 +617,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* // Store relation in CSB resources and after it - in the node - node->relation = csb->csb_resources.registerResource(tdbb, Resource::rsc_relation, rel, rel->rel_id); + node->relation = csb->csb_resources->relations.registerResource(rel); // if an alias was passed, store with the relation @@ -626,14 +626,11 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch* // Scan the relation if it hasn't already been scanned for meta data - if ((!(node->relation->rel_flags & REL_scanned) || - (node->relation->rel_flags & REL_being_scanned)) && - !(csb->csb_g_flags & csb_internal)) - { - MET_scan_relation(tdbb, rel); - } - else if (node->relation->rel_flags & REL_sys_triggers) - MET_parse_sys_trigger(tdbb, rel); + jrd_rel* latestVersion = rel->getObject(tdbb); + if (!(csb->csb_g_flags & csb_internal)) + latestVersion->scan(tdbb); + if (latestVersion->rel_flags & REL_sys_triggers) + MET_parse_sys_trigger(tdbb, latestVersion); // generate a stream for the relation reference, assuming it is a real reference @@ -658,8 +655,8 @@ string RelationSourceNode::internalPrint(NodePrinter& printer) const NODE_PRINT(printer, dsqlName); NODE_PRINT(printer, alias); NODE_PRINT(printer, context); - if (relation) - printer.print("rel_name", relation->rel_name); + if (relation.isSet()) + printer.print("rel_name", relation.get(JRD_get_thread_data(), printer.resources)->rel_name); return "RelationSourceNode"; } @@ -734,12 +731,16 @@ RecordSourceNode* RelationSourceNode::pass1(thread_db* tdbb, CompilerScratch* cs const auto tail = &csb->csb_rpt[stream]; const auto relation = tail->csb_relation; - if (relation && !csb->csb_implicit_cursor) + if (relation.isSet() && !csb->csb_implicit_cursor) { - const SLONG ssRelationId = tail->csb_view ? tail->csb_view->rel_id : - view ? view->rel_id : csb->csb_view ? csb->csb_view->rel_id : 0; - CMP_post_access(tdbb, csb, relation->rel_security_name, ssRelationId, - SCL_select, obj_relations, relation->rel_name); + const SLONG ssRelationId = tail->csb_view.isSet() ? + tail->csb_view.get(tdbb, csb->csb_resources)->rel_id : view.isSet() ? + view.get(tdbb, csb->csb_resources)->rel_id : csb->csb_view.isSet() ? + csb->csb_view.get(tdbb, csb->csb_resources)->rel_id : 0; + + const jrd_rel* r = relation.get(tdbb, csb->csb_resources); + CMP_post_access(tdbb, csb, r->rel_security_name, ssRelationId, + SCL_select, obj_relations, r->rel_name); } return this; @@ -756,11 +757,11 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN // prepare to check protection of relation when a field in the stream of the // relation is accessed. - jrd_rel* const parentView = csb->csb_view; + CachedResource const parentView = csb->csb_view; const StreamType viewStream = csb->csb_view_stream; - jrd_rel* relationView = relation; - csb->csb_resources.postResource(tdbb, Resource::rsc_relation, relationView, relationView->rel_id); + CachedResource relationView = relation; + //csb->csb_resources.postResource(tdbb, Resource::rsc_relation, relationView, relationView->rel_id); view = parentView; CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream); @@ -769,9 +770,9 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN // in the case where there is a parent view, find the context name - if (parentView) + if (parentView.isSet()) { - const ViewContexts& ctx = parentView->rel_view_contexts; + const ViewContexts& ctx = parentView.get(tdbb, csb->csb_resources)->rel_view_contexts; const USHORT key = context; FB_SIZE_T pos; @@ -784,7 +785,7 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN // check for a view - if not, nothing more to do - RseNode* viewRse = relationView->rel_view_rse; + RseNode* viewRse = relationView.get(tdbb, csb->csb_resources)->rel_view_rse; if (!viewRse) return; @@ -795,7 +796,7 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN AutoSetRestore autoRemapVariable(&csb->csb_remap_variable, (csb->csb_variables ? csb->csb_variables->count() : 0) + 1); - AutoSetRestore autoView(&csb->csb_view, relationView); + AutoSetRestore> autoView(&csb->csb_view, relationView); AutoSetRestore autoViewStream(&csb->csb_view_stream, stream); // We don't expand the view in two cases: @@ -908,7 +909,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch jrd_prc* procedure = nullptr; AutoPtr aliasString; QualifiedName name; - HazardPtr proc(FB_FUNCTION); + CacheElement* proc = nullptr; switch (blrOp) { @@ -923,11 +924,8 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch csb->csb_blr_reader.getString(*aliasString); } - proc = MetadataCache::lookup_procedure_id(tdbb, pid, false, false, 0); - if (proc) - procedure = csb->csb_resources.registerResource(tdbb, Resource::rsc_procedure, proc, proc->getId()); - - if (!procedure) + proc = MetadataCache::lookupProcedure(tdbb, pid); + if (!proc) name.identifier.printf("id %d", pid); break; } @@ -1008,7 +1006,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch ProcedureSourceNode* node = FB_NEW_POOL(*tdbb->getDefaultPool()) ProcedureSourceNode( *tdbb->getDefaultPool()); - node->procedure = procedure; + node->procedure = csb->csb_resources.procedures->registerResource(tdbb, proc); node->isSubRoutine = procedure->isSubRoutine(); node->procedureId = node->isSubRoutine ? 0 : procedure->getId(); diff --git a/src/jrd/RecordSourceNodes.h b/src/jrd/RecordSourceNodes.h index 99ce7b3078..c587d4b10d 100644 --- a/src/jrd/RecordSourceNodes.h +++ b/src/jrd/RecordSourceNodes.h @@ -358,8 +358,6 @@ public: : TypedNode(pool), dsqlName(pool, aDsqlName), alias(pool), - //relation(NULL), - view(NULL), context(0) { } @@ -418,10 +416,10 @@ public: public: MetaName dsqlName; Firebird::string alias; // SQL alias for the relation - jrd_rel* relation; + CachedResource relation; private: - jrd_rel* view; // parent view for posting access + CachedResource view; // parent view for posting access public: SSHORT context; // user-specified context number for the relation reference diff --git a/src/jrd/Relation.cpp b/src/jrd/Relation.cpp index c6dbec6e12..9460c8f7e6 100644 --- a/src/jrd/Relation.cpp +++ b/src/jrd/Relation.cpp @@ -43,8 +43,8 @@ using namespace Firebird; /// jrd_rel -jrd_rel::jrd_rel(MemoryPool& p) - : rel_pool(&p), rel_id(0), rel_current_fmt(0), +jrd_rel::jrd_rel(MemoryPool& p, MetaId id) + : rel_pool(&p), rel_id(id), rel_current_fmt(0), rel_flags(REL_gc_lockneed), rel_current_format(nullptr), rel_name(p), rel_owner_name(p), rel_security_name(p), rel_formats(nullptr), rel_fields(nullptr), @@ -667,7 +667,7 @@ HazardPtr jrd_rel::getIndexLock(thread_db* tdbb, USHORT id) SET_TDBB(tdbb); Database* dbb = tdbb->getDatabase(); - HazardPtr indexLock(FB_FUNCTION); + HazardPtr indexLock; if (rel_id < (USHORT) rel_MAX) return indexLock; @@ -692,5 +692,37 @@ const char* IndexLock::c_name() const return "* unk *"; } -//extern -HazardPtr Jrd::nullRel(FB_FUNCTION); +static void jrd_rel::destroy(jrd_rel* rel) +{ + rel->rel_flags |= REL_deleted; +/* + thread_db* tdbb = JRD_get_thread_data(); + + LCK_release(tdbb, rel->rel_existence_lock); + if (rel->rel_partners_lock) + { + rel->rel_flags |= REL_check_partners; + LCK_release(tdbb, rel->rel_partners_lock); + rel->rel_flags &= ~REL_check_partners; + } + LCK_release(tdbb, rel->rel_rescan_lock); + */ + // A lot more things to do !!!!!!!!!!!!!!!! + + delete rel; +} + +static jrd_rel* jrd_rel::create(thread_db* tdbb, MetaId id) +{ + SET_TDBB(tdbb); + Database* dbb = tdbb->getDatabase(); + CHECK_DBB(dbb); + + MetadataCache* mdc = dbb->dbb_mdc; + MemoryPool& pool = mdc->getPool(); + + jrd_rel* relation = FB_NEW_POOL(pool) jrd_rel(pool, id); + relation->scan(tdbb, mdc); + + return relation; +} diff --git a/src/jrd/Relation.h b/src/jrd/Relation.h index 2c9cd778a9..42284939dd 100644 --- a/src/jrd/Relation.h +++ b/src/jrd/Relation.h @@ -46,11 +46,9 @@ class IndexBlock; // Relation trigger definition class Trigger : public CacheObject -/* { +/* public: - typedef MetaName Key; - Firebird::HalfStaticArray blr; // BLR code Firebird::HalfStaticArray debugInfo; // Debug info Statement* statement; // Compiled statement @@ -154,84 +152,15 @@ public: }; // Array of triggers (suppose separate arrays for triggers of different types) -class TrigVector : public HazardArray +class TrigVector { -/* public: - explicit TrigVector(Firebird::MemoryPool& pool) - : HazardArray(pool), - useCount(0), addCount(0) - { } - - TrigVector() - : HazardArray(Firebird::AutoStorage::getAutoMemoryPool()), - useCount(0), addCount(0) - { } - - HazardPtr add(thread_db* tdbb, Trigger*); - - void addRef() - { - ++useCount; - } - - bool hasData(thread_db* tdbb) const - { - return getCount(tdbb) > 0; - } - - bool isEmpty(thread_db* tdbb) const - { - return getCount(tdbb) == 0; - } - bool hasActive() const; - void decompile(thread_db* tdbb); - void release(); - void release(thread_db* tdbb); + virtual ~TrigVector() { } - ~TrigVector() - { - fb_assert(useCount.load() == 0); - } - -private: - std::atomic useCount; - std::atomic addCount; -*/ - -public: - explicit TrigVector(Firebird::MemoryPool& pool) - : Firebird::ObjectsArray(pool), - useCount(0) - { } - - TrigVector() - : Firebird::ObjectsArray(), - useCount(0) - { } - - void addRef() - { - ++useCount; - } - - bool hasActive() const; - - void decompile(thread_db* tdbb); - - void release(); - void release(thread_db* tdbb); - - ~TrigVector() - { - fb_assert(useCount.value() == 0); - } - -private: - Firebird::AtomicCounter useCount; + virtual void addTrigger(thread_db* tdbb, Trigger* trigger) = 0; }; typedef std::atomic TrigVectorPtr; @@ -445,11 +374,6 @@ public: bool hasData() { return true; } const char* c_name() const override; - - void removeFromCache(thread_db* tdbb) override - { - idl_lock.removeFromCache(tdbb); - } }; @@ -457,14 +381,12 @@ public: // in the database, though it is not really filled out until // the relation is scanned -class jrd_rel : public CacheObject +class jrd_rel final : public CacheObject { typedef Firebird::HalfStaticArray GCRecordList; - typedef HazardArray IndexLockList; + typedef Firebird::ObjectsArray IndexLocks; public: - typedef MetaName Key; - MemoryPool* rel_pool; USHORT rel_id; USHORT rel_current_fmt; // Current format number @@ -492,7 +414,7 @@ public: Lock* rel_partners_lock; // partners lock Lock* rel_rescan_lock; // lock forcing relation to be scanned Lock* rel_gc_lock; // garbage collection lock - IndexLockList rel_index_locks; // index existence locks + IndexLocks rel_index_locks; // index existence locks //Firebird::Mutex rel_mtx_il; // controls addition & removal of elements IndexBlock* rel_index_blocks; // index blocks for caching index info TrigVectorPtr rel_pre_erase; // Pre-operation erase trigger @@ -538,6 +460,16 @@ public: return rel_id; } + void scan(thread_db* tdbb); +/* + // Scan the relation if it hasn't already been scanned for meta data + +- if (!(node->relation->rel_flags & REL_scanned) || +- (node->relation->rel_flags & REL_being_scanned)) +- { +- MET_scan_relation(tdbb, this); +- } + */ bool delPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, RelationPages* aPages = NULL); void retainPages(thread_db* tdbb, TraNumber oldNumber, TraNumber newNumber); @@ -572,13 +504,8 @@ public: bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) override; void afterUnlock(thread_db* tdbb, unsigned flags) override; - void removeFromCache(thread_db* tdbb) override - { - if (rel_existence_lock) - rel_existence_lock->removeFromCache(tdbb); - else - delayedDelete(tdbb); - } + static void destroy(jrd_rel *rel); + static jrd_rel* create(thread_db* tdbb, MetaId id, CacheObject::Flag flags); private: typedef Firebird::SortedArray< @@ -595,7 +522,7 @@ private: RelationPages* getPagesInternal(thread_db* tdbb, TraNumber tran, bool allocPages); public: - explicit jrd_rel(MemoryPool& p); + jrd_rel(MemoryPool& p, MetaId id); // bool hasTriggers() const; unused ??????????????????? void releaseTriggers(thread_db* tdbb, bool destroy); @@ -646,8 +573,6 @@ public: }; }; -extern HazardPtr nullRel; - // rel_flags const ULONG REL_scanned = 0x0001; // Field expressions scanned (or being scanned) diff --git a/src/jrd/Routine.cpp b/src/jrd/Routine.cpp index 21255bde05..801a810ab4 100644 --- a/src/jrd/Routine.cpp +++ b/src/jrd/Routine.cpp @@ -175,7 +175,7 @@ void Routine::parseBlr(thread_db* tdbb, CompilerScratch* csb, bid* blob_id, bid* flags &= ~Routine::FLAG_RELOAD; Statement* statement = getStatement(); - PAR_blr(tdbb, nullRel, tmp.begin(), (ULONG) tmp.getCount(), NULL, &csb, &statement, false, 0); + PAR_blr(tdbb, nullptr, tmp.begin(), (ULONG) tmp.getCount(), NULL, &csb, &statement, false, 0); setStatement(statement); if (csb->csb_g_flags & csb_reload) @@ -286,14 +286,6 @@ void Routine::afterUnlock(thread_db* tdbb, unsigned fl) } } -void Routine::removeFromCache(thread_db* tdbb) -{ - if (existenceLock) - existenceLock->removeFromCache(tdbb); - else - delayedDelete(tdbb); -} - int Routine::getUseCount() const { return existenceLock.hasData() ? existenceLock->getUseCount() : 1; @@ -368,11 +360,6 @@ bool jrd_prc::checkCache(thread_db* tdbb) const return tdbb->getDatabase()->dbb_mdc->getProcedure(tdbb, getId()) == this; } -void jrd_prc::clearCache(thread_db* tdbb) -{ - tdbb->getDatabase()->dbb_mdc->setProcedure(tdbb, getId(), nullptr); -} - void Routine::releaseLocks(thread_db* tdbb) { if (existenceLock) diff --git a/src/jrd/Routine.h b/src/jrd/Routine.h index cae582488b..1589aeb849 100644 --- a/src/jrd/Routine.h +++ b/src/jrd/Routine.h @@ -96,7 +96,29 @@ namespace Jrd protected: explicit Routine(MemoryPool& p) : PermanentStorage(p), - id(0), + id(~0), + name(p), + securityName(p), + statement(NULL), + subRoutine(true), + implemented(true), + defined(true), + defaultCount(0), + inputFormat(NULL), + outputFormat(NULL), + inputFields(p), + outputFields(p), + flags(0), + intUseCount(0), + alterCount(0), + existenceLock(NULL), + invoker(NULL) + { + } + + explicit Routine(MemoryPool& p, MetaId metaId) + : PermanentStorage(p), + id(metaId), name(p), securityName(p), statement(NULL), @@ -141,6 +163,11 @@ namespace Jrd static Format* createFormat(MemoryPool& pool, Firebird::IMessageMetadata* params, bool addEof); public: + static void destroy(Routine* routine) + { + delete routine; + } + USHORT getId() const { fb_assert(!subRoutine); @@ -156,8 +183,6 @@ namespace Jrd const MetaName& getSecurityName() const { return securityName; } void setSecurityName(const MetaName& value) { securityName = value; } - void removeFromCache(thread_db* tdbb) override; - /*const*/ Statement* getStatement() const { return statement; } void setStatement(Statement* value); @@ -204,7 +229,7 @@ namespace Jrd } void afterDecrement(Jrd::thread_db*); - void afterUnlock(thread_db* tdbb, unsigned fl); + void afterUnlock(thread_db* tdbb, unsigned fl) override; void releaseStatement(thread_db* tdbb); //void remove(thread_db* tdbb); virtual void releaseExternal() @@ -221,7 +246,6 @@ namespace Jrd virtual int getObjectType() const = 0; virtual SLONG getSclType() const = 0; virtual bool checkCache(thread_db* tdbb) const = 0; - virtual void clearCache(thread_db* tdbb) = 0; private: USHORT id; // routine ID @@ -256,8 +280,6 @@ namespace Jrd MetaName owner; Jrd::UserId* invoker; // Invoker ID - - typedef QualifiedName Key; }; } diff --git a/src/jrd/RuntimeStatistics.cpp b/src/jrd/RuntimeStatistics.cpp index 8b85e9ebc4..ed267b7742 100644 --- a/src/jrd/RuntimeStatistics.cpp +++ b/src/jrd/RuntimeStatistics.cpp @@ -113,7 +113,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, TraceCounts traceCounts; traceCounts.trc_relation_id = rel_id; traceCounts.trc_counters = base_cnts->getCounterVector(); - HazardPtr relation = mdc->getRelation(att, rel_id); + jrd_rel* relation = mdc->getRelation(att, rel_id); traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL; temp.add(traceCounts); } @@ -127,7 +127,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att, TraceCounts traceCounts; traceCounts.trc_relation_id = rel_id; traceCounts.trc_counters = new_cnts->getCounterVector(); - HazardPtr relation = mdc->getRelation(att, rel_id); + jrd_rel* relation = mdc->getRelation(att, rel_id); traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL; temp.add(traceCounts); } diff --git a/src/jrd/Statement.cpp b/src/jrd/Statement.cpp index 8c888af9c8..22ede7a075 100644 --- a/src/jrd/Statement.cpp +++ b/src/jrd/Statement.cpp @@ -340,9 +340,9 @@ const Routine* Statement::getRoutine() const // Determine if any request of this statement are active. bool Statement::isActive() const { - for (const Request* const* request = requests.begin(); request != requests.end(); ++request) + for (auto request : requests) { - if (*request && ((*request)->req_flags & req_in_use)) + if (request && request->isUsed()) return true; } @@ -372,7 +372,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique) if (next->req_attachment == attachment) { - if (!(next->req_flags & req_in_use)) + if (!next->isUsed()) { clone = next; break; @@ -383,7 +383,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique) ++count; } - else if (!(next->req_flags & req_in_use) && !clone) + else if (!(next->isUsed()) && !clone) clone = next; } @@ -396,7 +396,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique) clone->setAttachment(attachment); clone->req_stats.reset(); clone->req_base_stats.reset(); - clone->req_flags |= req_in_use; + clone->setUsed(true); return clone; } @@ -442,7 +442,7 @@ void Statement::verifyAccess(thread_db* tdbb) for (ExternalAccess* item = external.begin(); item != external.end(); ++item) { - HazardPtr routine(tdbb, FB_FUNCTION); + HazardPtr routine(tdbb); int aclType; if (item->exa_action == ExternalAccess::exa_procedure) @@ -471,7 +471,7 @@ void Statement::verifyAccess(thread_db* tdbb) } else { - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, item->exa_rel_id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, item->exa_rel_id, false); if (!relation) continue; @@ -479,7 +479,7 @@ void Statement::verifyAccess(thread_db* tdbb) MetaName userName = item->user; if (item->exa_view_id) { - HazardPtr view = MetadataCache::lookup_relation_id(tdbb, item->exa_view_id, false); + jrd_rel* view = MetadataCache::lookup_relation_id(tdbb, item->exa_view_id, false); if (view && (view->rel_flags & REL_sql_relation)) userName = view->rel_owner_name; } @@ -515,7 +515,7 @@ void Statement::verifyAccess(thread_db* tdbb) if (access.acc_ss_rel_id) { - HazardPtr view = MetadataCache::lookup_relation_id(tdbb, access->acc_ss_rel_id, false); + jrd_rel* view = MetadataCache::lookup_relation_id(tdbb, access->acc_ss_rel_id, false); if (view && (view->rel_flags & REL_sql_relation)) userName = view->rel_owner_name; } @@ -583,7 +583,7 @@ void Statement::verifyAccess(thread_db* tdbb) if (access->acc_ss_rel_id) { - HazardPtr view = MetadataCache::lookup_relation_id(tdbb, access->acc_ss_rel_id, false); + jrd_rel* view = MetadataCache::lookup_relation_id(tdbb, access->acc_ss_rel_id, false); if (view && (view->rel_flags & REL_sql_relation)) userName = view->rel_owner_name; } @@ -658,7 +658,7 @@ string Statement::getPlan(thread_db* tdbb, bool detailed) const } // Check that we have enough rights to access all resources this list of triggers touches. -void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr& ownerRelation, +void Statement::verifyTriggerAccess(thread_db* tdbb, const jrd_rel* ownerRelation, TrigVector* triggers, MetaName userName) { if (!triggers) @@ -668,7 +668,7 @@ void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr& o for (FB_SIZE_T i = 0; i < triggers->getCount(tdbb); i++) { - HazardPtr t(tdbb, FB_FUNCTION); + HazardPtr t(tdbb); if (!triggers->load(tdbb, i, t)) continue; @@ -705,7 +705,7 @@ void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr& o // a direct access to an object from this trigger if (access->acc_ss_rel_id) { - HazardPtr view = MetadataCache::lookup_relation_id(tdbb, access->acc_ss_rel_id, false); + jrd_rel* view = MetadataCache::lookup_relation_id(tdbb, access->acc_ss_rel_id, false); if (view && (view->rel_flags & REL_sql_relation)) userName = view->rel_owner_name; } @@ -733,7 +733,7 @@ inline void Statement::triggersExternalAccess(thread_db* tdbb, ExternalAccessLis for (FB_SIZE_T i = 0; i < tvec->getCount(tdbb); i++) { - HazardPtr t(tdbb, FB_FUNCTION); + HazardPtr t(tdbb); if (!tvec->load(tdbb, i, t)) continue; @@ -769,7 +769,7 @@ void Statement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list, c } else if (item->exa_action == ExternalAccess::exa_function) { - HazardPtr function = Function::lookup(tdbb, item->exa_fun_id, false, false, 0); + Function* function = Function::lookup(tdbb, item->exa_fun_id, false, false, 0); if (function && function->getStatement()) { item->user = function->invoker ? MetaName(function->invoker->getUserName()) : user; @@ -781,7 +781,7 @@ void Statement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list, c } else { - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, item->exa_rel_id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, item->exa_rel_id, false); if (!relation) continue; @@ -912,6 +912,32 @@ StmtNumber Request::getRequestId() const return req_id; } +Request::Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement) + : statement(aStatement), + req_pool(pool), + req_memory_stats(&aStatement->pool->getStatsGroup()), + req_blobs(req_pool), + req_stats(*req_pool), + req_base_stats(*req_pool), + req_ext_stmt(NULL), + req_cursors(*req_pool), + req_ext_resultset(NULL), + req_timeout(0), + req_domain_validation(NULL), + req_auto_trans(*req_pool), + req_sorts(*req_pool), + req_rpb(*req_pool), + impureArea(*req_pool) +{ + fb_assert(statement); + setAttachment(attachment); + req_rpb = statement->rpbsSetup; + impureArea.grow(statement->impureSize); + + pool->setStatsGroup(req_memory_stats); + pool.release(); +} + #ifdef DEV_BUILD diff --git a/src/jrd/Statement.h b/src/jrd/Statement.h index e6aaa0e971..f386dccd39 100644 --- a/src/jrd/Statement.h +++ b/src/jrd/Statement.h @@ -81,7 +81,7 @@ public: Firebird::string getPlan(thread_db* tdbb, bool detailed) const; private: - static void verifyTriggerAccess(thread_db* tdbb, const HazardPtr& ownerRelation, TrigVector* triggers, + static void verifyTriggerAccess(thread_db* tdbb, const jrd_rel* ownerRelation, TrigVector* triggers, MetaName userName); static void triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list, TrigVector* tvec, const MetaName &user); @@ -98,7 +98,7 @@ public: Firebird::Array requests; // vector of requests ExternalAccessList externalList; // Access to procedures/triggers to be checked AccessItemList accessList; // Access items to be checked - ResourceList resources; // Resources (relations and indices) + //ResourceList resources; // Resources (relations and indices) const jrd_prc* procedure; // procedure, if any const Function* function; // function, if any MetaName triggerName; // name of request (trigger), if any @@ -112,6 +112,10 @@ public: Firebird::RefStrPtr sqlText; // SQL text (encoded in the metadata charset) Firebird::Array blr; // BLR for non-SQL query MapFieldInfo mapFieldInfo; // Map field name to field info + +private: + Resources resources; + Firebird::RefPtr latestVersion; }; diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp index 867d1cb92c..dfeb018705 100644 --- a/src/jrd/SysFunction.cpp +++ b/src/jrd/SysFunction.cpp @@ -5311,7 +5311,7 @@ dsc* evlMakeDbkey(Jrd::thread_db* tdbb, const SysFunction* function, const NestV MetaName relName; MOV_get_metaname(tdbb, argDsc, relName); - HazardPtr relation = MetadataCache::lookup_relation(tdbb, relName); + jrd_rel* relation = MetadataCache::lookup_relation(tdbb, relName); if (!relation) (Arg::Gds(isc_relnotdef) << Arg::Str(relName)).raise(); diff --git a/src/jrd/WorkerAttachment.cpp b/src/jrd/WorkerAttachment.cpp index 8c9a4df8a3..82d8e9adf7 100644 --- a/src/jrd/WorkerAttachment.cpp +++ b/src/jrd/WorkerAttachment.cpp @@ -34,7 +34,7 @@ #include "../common/classes/ClumpletWriter.h" #include "../jrd/jrd.h" #include "../jrd/ini_proto.h" -#include "../jrd/lck_proto.h" +#include "../jrd/lck.h" #include "../jrd/pag_proto.h" #include "../jrd/tra_proto.h" #include "../jrd/status.h" diff --git a/src/jrd/blb.cpp b/src/jrd/blb.cpp index a85df336b8..34c09237cd 100644 --- a/src/jrd/blb.cpp +++ b/src/jrd/blb.cpp @@ -1445,7 +1445,7 @@ blb* blb::open2(thread_db* tdbb, // know about the relation, the blob id has got to be invalid // anyway. - HazardPtr relation = dbb->dbb_mdc->getRelation(tdbb, blobId.bid_internal.bid_relation_id); + jrd_rel* relation = dbb->dbb_mdc->getRelation(tdbb, blobId.bid_internal.bid_relation_id); if (!relation) ERR_post(Arg::Gds(isc_bad_segstr_id)); @@ -1743,7 +1743,7 @@ void blb::put_slice(thread_db* tdbb, if (SDL_info(tdbb->tdbb_status_vector, sdl, &info, 0)) ERR_punt(); - HazardPtr relation = info.sdl_info_relation.length() ? + jrd_rel* relation = info.sdl_info_relation.length() ? MetadataCache::lookup_relation(tdbb, info.sdl_info_relation) : MetadataCache::findRelation(tdbb, info.sdl_info_rid); diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index 00b89359f4..f38deb0215 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -566,8 +566,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record fb_assert(!conditionRequest->req_caller); conditionRequest->req_caller = orgRequest; - conditionRequest->req_flags &= req_in_use; - conditionRequest->req_flags |= req_active; + conditionRequest->req_flags = req_active; TRA_attach_request(tdbb->getTransaction(), conditionRequest); tdbb->setRequest(conditionRequest); @@ -598,7 +597,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record } EXE_unwind(tdbb, conditionRequest); - conditionRequest->req_flags &= ~req_in_use; + conditionRequest->setUsed(false); conditionRequest->req_attachment = nullptr; tdbb->setRequest(orgRequest); @@ -626,8 +625,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& fb_assert(!expr_request->req_caller); expr_request->req_caller = org_request; - expr_request->req_flags &= req_in_use; - expr_request->req_flags |= req_active; + expr_request->req_flags = req_active; TRA_attach_request(tdbb->getTransaction(), expr_request); TRA_setup_request_snapshot(tdbb, expr_request); tdbb->setRequest(expr_request); @@ -661,7 +659,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& tdbb->setRequest(org_request); expr_request->req_caller = NULL; - expr_request->req_flags &= ~req_in_use; + expr_request->setUsed(false); expr_request->req_attachment = NULL; expr_request->invalidateTimeStamp(); @@ -672,7 +670,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& tdbb->setRequest(org_request); expr_request->req_caller = NULL; - expr_request->req_flags &= ~req_in_use; + expr_request->setUsed(false); expr_request->req_attachment = NULL; expr_request->invalidateTimeStamp(); @@ -6203,13 +6201,13 @@ string print_key(thread_db* tdbb, jrd_rel* relation, index_desc* idx, Record* re string key; fb_assert(relation && idx && record); - HazardPtr wrk = MET_scan_relation(tdbb, relation->rel_id); + jrd_rel* wrk = MET_scan_relation(tdbb, relation->rel_id); if (!wrk) { key.printf("(target relation %s deleted)", relation->c_name()); return key; } - relation = wrk.getPointer(); + relation = wrk; const FB_SIZE_T MAX_KEY_STRING_LEN = 250; string value; diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index c6dfe8816c..7d9502abfa 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -368,7 +368,7 @@ public: { } - ProtectRelations(thread_db* tdbb, jrd_tra* transaction, HazardPtr& relation) : + ProtectRelations(thread_db* tdbb, jrd_tra* transaction, jrd_rel* relation) : m_tdbb(tdbb), m_transaction(transaction), m_locks() @@ -382,7 +382,7 @@ public: unlock(); } - void addRelation(HazardPtr& relation) + void addRelation(jrd_rel* relation) { FB_SIZE_T pos; if (!m_locks.find(relation->rel_id, pos)) @@ -410,7 +410,7 @@ public: private: struct relLock { - relLock(HazardPtr relation = HazardPtr(FB_FUNCTION)) : + relLock(jrd_rel* relation = nullptr) : m_relation(relation), m_lock(NULL), m_release(false) @@ -433,7 +433,7 @@ private: return &item->m_relation->rel_id; } - HazardPtr m_relation; + jrd_rel* m_relation; Lock* m_lock; bool m_release; }; @@ -509,12 +509,12 @@ static bool formatsAreEqual(const Format*, const Format*); static bool find_depend_in_dfw(thread_db*, TEXT*, USHORT, USHORT, jrd_tra*); static void get_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*); static void get_trigger_dependencies(DeferredWork*, bool, jrd_tra*); -static Format* make_format(thread_db*, HazardPtr, USHORT *, TemporaryField*); +static Format* make_format(thread_db*, jrd_rel*, USHORT *, TemporaryField*); static void put_summary_blob(thread_db* tdbb, blb*, enum rsr_t, bid*, jrd_tra*); static void put_summary_record(thread_db* tdbb, blb*, enum rsr_t, const UCHAR*, ULONG); static void setup_array(thread_db*, blb*, const TEXT*, USHORT, TemporaryField*); -static blb* setup_triggers(thread_db*, HazardPtr&, bool, TrigVectorPtr*, blb*); -static void setup_trigger_details(thread_db*, HazardPtr&, blb*, TrigVectorPtr*, const TEXT*, bool); +static blb* setup_triggers(thread_db*, jrd_rel*, bool, TrigVectorPtr*, blb*); +static void setup_trigger_details(thread_db*, jrd_rel*, blb*, TrigVectorPtr*, const TEXT*, bool); static bool validate_text_type (thread_db*, const TemporaryField*); static void check_partners(thread_db*, const USHORT); @@ -587,7 +587,7 @@ static void raiseObjectInUseError(const string& obj_type, const string& obj_name Arg::Gds(isc_obj_in_use) << Arg::Str(name)); } -static void raiseRelationInUseError(const HazardPtr& relation) +static void raiseRelationInUseError(const jrd_rel* relation) { const string obj_type = relation->isView() ? "VIEW" : "TABLE"; @@ -724,7 +724,7 @@ namespace { SET_TDBB(tdbb); const QualifiedName name(work->dfw_name, work->dfw_package); - HazardPtr routine(FB_FUNCTION); + HazardPtr routine; fprintf(stderr, "routine %d %s ph %d\n", work->dfw_id, name.c_str(), phase); @@ -869,7 +869,7 @@ namespace { SET_TDBB(tdbb); const QualifiedName name(work->dfw_name, work->dfw_package); - HazardPtr routine(FB_FUNCTION); + HazardPtr routine; switch (phase) { @@ -996,7 +996,7 @@ namespace // works in not deleted context { Jrd::ContextPoolHolder context(tdbb, new_pool); - MET_get_dependencies(tdbb, nullRel, NULL, 0, NULL, &blobId, + MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &blobId, (compile ? &statement : NULL), NULL, depName, (work->dfw_package.isEmpty() ? objType : obj_package_body), @@ -1097,7 +1097,7 @@ namespace { Jrd::Attachment* attachment = tdbb->getAttachment(); AutoCacheRequest handle(tdbb, irq_c_fun_dpd, IRQ_REQUESTS); - HazardPtr routine(tdbb, FB_FUNCTION); + HazardPtr routine(tdbb); FOR(REQUEST_HANDLE handle) X IN RDB$FUNCTIONS WITH @@ -1142,7 +1142,7 @@ namespace { Attachment* attachment = tdbb->getAttachment(); AutoCacheRequest handle(tdbb, irq_c_prc_dpd, IRQ_REQUESTS); - HazardPtr routine(tdbb, FB_FUNCTION); + HazardPtr routine(tdbb); FOR(REQUEST_HANDLE handle) X IN RDB$PROCEDURES WITH @@ -2365,7 +2365,7 @@ static bool check_not_null(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr case 3: { - HazardPtr relation = MetadataCache::lookup_relation(tdbb, work->dfw_name); + jrd_rel* relation = MetadataCache::lookup_relation(tdbb, work->dfw_name); if (!relation || relation->rel_view_rse || work->dfw_ids.isEmpty()) break; @@ -2706,7 +2706,7 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork* case 3: { - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation; CompilerScratch* csb = nullptr; const auto dbb = tdbb->getDatabase(); @@ -3087,7 +3087,7 @@ static void cleanup_index_creation(thread_db* tdbb, DeferredWork* work, jrd_tra* // dimitr: I have no idea why the condition below is required here AND IREL.RDB$VIEW_BLR MISSING // views do not have indices { - HazardPtr relation = MetadataCache::lookup_relation(tdbb, IDXN.RDB$RELATION_NAME); + jrd_rel* relation = MetadataCache::lookup_relation(tdbb, IDXN.RDB$RELATION_NAME); RelationPages* const relPages = relation->getPages(tdbb, MAX_TRA_NUMBER, false); if (relPages && relPages->rel_index_root) @@ -3130,7 +3130,7 @@ static void cleanup_index_creation(thread_db* tdbb, DeferredWork* work, jrd_tra* idx.idx_id = idx_invalid; idx.idx_flags = idx_foreign; - HazardPtr partner_relation(FB_FUNCTION); + jrd_rel* partner_relation = nullptr; if (MET_lookup_partner(tdbb, relation.unsafePointer(), &idx, work->dfw_name.c_str())) { partner_relation = MetadataCache::lookup_relation_id(tdbb, idx.idx_primary_relation, true); @@ -3287,7 +3287,7 @@ static bool modify_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ } bool gtt_preserve = false; - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; if (is_create) { @@ -3353,8 +3353,8 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ * **************************************/ AutoCacheRequest request; - HazardPtr relation(FB_FUNCTION); - HazardPtr partner_relation(FB_FUNCTION); + jrd_rel* relation = nullptr; + jrd_rel* partner_relation = nullptr; index_desc idx; int key_count; @@ -3711,7 +3711,7 @@ static bool create_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j * **************************************/ AutoCacheRequest request; - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; USHORT rel_id, external_flag; bid blob_id; AutoRequest handle; @@ -4206,7 +4206,7 @@ void DFW_reset_icu(thread_db* tdbb) USHORT rel_id = rs->getInt(tdbb, 2); if (!tables.exists(rel_id)) { - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); if (relation) tables.addRelation(relation); } @@ -4450,7 +4450,7 @@ static bool create_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ MemoryPool* new_pool = dbb->createPool(); Jrd::ContextPoolHolder context(tdbb, new_pool); - MET_get_dependencies(tdbb, nullRel, NULL, 0, NULL, &validation, + MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &validation, NULL, NULL, depName, obj_validation, 0, transaction, depName); dbb->deletePool(new_pool); @@ -4615,7 +4615,7 @@ static bool modify_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ MemoryPool* new_pool = dbb->createPool(); Jrd::ContextPoolHolder context(tdbb, new_pool); - MET_get_dependencies(tdbb, nullRel, NULL, 0, NULL, &validation, + MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &validation, NULL, NULL, depName, obj_validation, 0, transaction, depName); dbb->deletePool(new_pool); @@ -4695,7 +4695,7 @@ static void check_partners(thread_db* tdbb, const USHORT rel_id) * **************************************/ Database* const dbb = tdbb->getDatabase(); - HazardPtr relation = dbb->dbb_mdc->getRelation(tdbb, rel_id); + jrd_rel* relation = dbb->dbb_mdc->getRelation(tdbb, rel_id); fb_assert(relation); relation->rel_flags |= REL_check_partners; @@ -4715,7 +4715,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ * Functional description * **************************************/ - HazardPtr index(FB_FUNCTION); + HazardPtr index; SET_TDBB(tdbb); @@ -4731,7 +4731,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ // Look up the relation. If we can't find the relation, // don't worry about the index. - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, work->dfw_id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, work->dfw_id, false); if (!relation) { return false; } @@ -4841,8 +4841,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ ERR_post(Arg::Gds(isc_random) << "Index block gone unexpestedly"); fb_assert(!arrVal); index->idl_lock.releaseLock(tdbb, ExistenceLock::ReleaseMethod::DropObject); - // fprintf(stderr, "delayedDelete index, replace NULL, to be reviewed\n"); - // --- index->delayedDelete(tdbb); + index->retire(); // Release index refresh lock and memory. for (IndexBlock** iptr = &relation->rel_index_blocks; *iptr; iptr = &(*iptr)->idb_next) @@ -4922,7 +4921,7 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j * **************************************/ AutoRequest request; - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; Resource* rsc; USHORT view_count; bool adjusted; @@ -5004,22 +5003,6 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j // ?????????? MutexLockGuard g(dbb->dbb_mdc->mdc_use_mutex, FB_FUNCTION); adjusted = false; - if (relation->rel_existence_lock->getUseCount() == 1) - { - for (auto rsc : transaction->tra_resources.getObjects(Resource::rsc_relation)) - { - if (rsc->rsc_rel == relation) - { - relation->rel_existence_lock->dec(tdbb); - adjusted = true; - break; - } - } - } - - if (relation->rel_existence_lock->getUseCount()) - MetadataCache::clear_cache(tdbb); - if (!relation->rel_existence_lock->exclLock(tdbb)) /////// ??????? !LCK_convert(tdbb, relation->rel_existence_lock, LCK_EX, transaction->getLockWait()))) { @@ -5038,7 +5021,7 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j relation->rel_flags |= REL_deleting; { // scope EngineCheckout cout(tdbb, FB_FUNCTION); - relation->rel_drop_mutex.enter(FB_FUNCTION); + relation->rel_drop_mutex.enter; } return true; @@ -5165,7 +5148,7 @@ static bool delete_rfr(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tr int rel_exists, field_count; AutoRequest handle; MetaName f; - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; SET_TDBB(tdbb); Jrd::Attachment* attachment = tdbb->getAttachment(); @@ -5565,7 +5548,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra* if (compile) compile = !tdbb->getAttachment()->isGbak(); - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; bid blob_id; blob_id.clear(); @@ -5611,7 +5594,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra* } -static Format* make_format(thread_db* tdbb, HazardPtr relation, USHORT* version, TemporaryField* stack) +static Format* make_format(thread_db* tdbb, jrd_rel* relation, USHORT* version, TemporaryField* stack) { /************************************** * @@ -5829,7 +5812,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ **************************************/ TemporaryField* stack; TemporaryField* external; - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; //bid blob_id; //blob_id.clear(); @@ -6351,7 +6334,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr try { - HazardPtr relation = MetadataCache::lookup_relation(tdbb, relation_name); + jrd_rel* relation = MetadataCache::lookup_relation(tdbb, relation_name); if (relation) { @@ -6375,7 +6358,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr { if (triggers[i]) { - HazardPtr trig(tdbb, FB_FUNCTION); + HazardPtr trig(tdbb); for (FB_SIZE_T j = 0; j < triggers[i].load()->getCount(tdbb); ++j) { if (triggers[i].load()->load(tdbb, j, trig)) @@ -6502,7 +6485,7 @@ static bool scan_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd **************************************/ SET_TDBB(tdbb); - HazardPtr rel(FB_FUNCTION); + jrd_rel* rel = nullptr; switch (phase) { @@ -6632,7 +6615,7 @@ static void setup_array(thread_db* tdbb, blb* blob, const TEXT* field_name, USHO } -static blb* setup_triggers(thread_db* tdbb, HazardPtr& relation, bool null_view, +static blb* setup_triggers(thread_db* tdbb, jrd_rel* relation, bool null_view, TrigVectorPtr* triggers, blb* blob) { /************************************** @@ -6729,7 +6712,7 @@ static blb* setup_triggers(thread_db* tdbb, HazardPtr& relation, bool n static void setup_trigger_details(thread_db* tdbb, - HazardPtr& relation, + jrd_rel* relation, blb* blob, TrigVectorPtr* triggers, const TEXT* trigger_name, diff --git a/src/jrd/dpm.epp b/src/jrd/dpm.epp index dedcf5df24..7ae0d9c352 100644 --- a/src/jrd/dpm.epp +++ b/src/jrd/dpm.epp @@ -2019,7 +2019,7 @@ void DPM_scan_pages( thread_db* tdbb) // infinite recursion from this internal request when RDB$PAGES // has been extended with another pointer page. - HazardPtr relation = MetadataCache::findRelation(tdbb, 0); + jrd_rel* relation = MetadataCache::findRelation(tdbb, 0); RelationPages* relPages = relation->getBasePages(); vcl** address = &relPages->rel_pages; diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index 66f58058d5..933d4e0738 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -778,7 +778,7 @@ void EXE_release(thread_db* tdbb, Request* request) request->req_attachment = NULL; } - request->req_flags &= ~req_in_use; + request->setUsed(false); } @@ -890,9 +890,9 @@ void EXE_start(thread_db* tdbb, Request* request, jrd_tra* transaction) TRA_post_resources(tdbb, transaction, statement->resources); TRA_attach_request(transaction, request); - request->req_flags &= req_in_use | req_restart_ready; + request->req_flags &= req_restart_ready; request->req_flags |= req_active; - request->req_flags &= ~req_reserved; + // ????????? request->req_flags &= ~req_reserved; // set up to count records affected by request @@ -1245,7 +1245,7 @@ void EXE_execute_triggers(thread_db* tdbb, EXE_unwind(tdbb, trigger); trigger->req_attachment = NULL; - trigger->req_flags &= ~req_in_use; + trigger->setUsed(false); if (!ok) trigger_failure(tdbb, trigger); @@ -1265,7 +1265,7 @@ void EXE_execute_triggers(thread_db* tdbb, { EXE_unwind(tdbb, trigger); trigger->req_attachment = NULL; - trigger->req_flags &= ~req_in_use; + trigger->setUsed(false); ex.stuffException(tdbb->tdbb_status_vector); @@ -1717,10 +1717,6 @@ void ResourceList::setResetPointersHazard(thread_db* tdbb, bool set) if (hazardFlag != set) { // (un-)register hazard pointers - HazardDelayedDelete* hazardDelayed = nullptr; - if (list.hasData()) - hazardDelayed = HazardBase::getHazardDelayed(tdbb); - for (auto r : list) { void* hazardPointer = nullptr; diff --git a/src/jrd/exe.h b/src/jrd/exe.h index 8f78c44b3c..c5984b9d8f 100644 --- a/src/jrd/exe.h +++ b/src/jrd/exe.h @@ -34,6 +34,7 @@ #include "../jrd/blb.h" #include "../jrd/Relation.h" +#include "../jrd/CharSetContainer.h" #include "../common/classes/array.h" #include "../jrd/MetaName.h" #include "../common/classes/fb_pair.h" @@ -167,214 +168,96 @@ struct impure_agg_sort }; -// Resources list +template class CacheElement; -class ResourceList +class Resources { - typedef Firebird::SortedArray, - Resource, Firebird::DefaultKeyValue, Resource> InternalResourceList; +public: + template + class VersionedPtr + { + public: + CacheElement* ptr; + FB_SIZE_T versionedObject; + }; + + template + class RscArray : public Firebird::Array> + { + public: + RscArray(MemoryPool& p) + : Firebird::Array>(p) + { } + + FB_SIZE_T registerResource(CacheElement* res) + { + FB_SIZE_T pos; + if (this->find([res](const VersionedPtr& elem) { + const void* p1 = elem.ptr; + const void* p2 = res; + return p1 < p2 ? -1 : p1 == p2 ? 0 : 1; + }, pos)) + { + return pos; + } + + VersionedPtr newPtr(res); + return this->append(newPtr); + } + }; public: - ResourceList(MemoryPool& p, bool hazard) - : list(p), hazardFlag(hazard) + template const RscArray& objects() const; + + Resources(MemoryPool& p) + : charSets(p), relations(p), procedures(p), functions(p), triggers(p) { } - typedef Firebird::Bits ResourceTypes; - typedef Firebird::HalfStaticArray NewResources; + RscArray charSets; + RscArray relations; + RscArray procedures; + RscArray functions; + RscArray triggers; +}; - ~ResourceList() +// specialization +template <> const Resources::RscArray& Resources::objects() const { return relations; } + + +template +class CachedResource +{ +public: + CachedResource(FB_SIZE_T offset) + : compileOffset(offset) + { } + + CachedResource(); + + OBJ* get(thread_db* tdbb, const Resources* compileTime) const { - releaseResources(nullptr); + auto array = compileTime->objects(); + return array[compileOffset]->ptr->getObject(tdbb); } - template - T* registerResource(thread_db* tdbb, Resource::rsc_s type, const HazardPtr& object, USHORT id) + bool isSet() const; +/* + operator OBJ*() const { - fb_assert(type != Resource::rsc_index); - - T* ptr = object.getPointer(); - Resource r(type, id, ptr); - FB_SIZE_T pos; - if (!list.find(r, pos)) - { - list.insert(pos, r); - HazardPtr::getHazardDelayed(tdbb)->add(ptr, FB_FUNCTION); - } - - return ptr; + return getPtr(); } - template - void postResource(thread_db* tdbb, Resource::rsc_s type, T* ptr, USHORT id) + OBJ* operator->() const { - fb_assert(hazardFlag); - - Resource r(type, id, ptr); - FB_SIZE_T pos; - - if (type == Resource::rsc_index) - { - Resource r1 = r; - r1.rsc_id = r1.rsc_rel->rel_id; - r1.rsc_type = Resource::rsc_relation; - - if (!list.find(r1, pos)) - raiseNotRegistered(r, type, ptr->c_name()); - - if (!list.find(r, pos)) - list.insert(pos, r); - } - - else if (!list.find(r, pos)) - raiseNotRegistered(r, type, ptr->c_name()); - - list[pos].rsc_state = Resource::State::Posted; - } - - template - void checkResource(Jrd::Resource::rsc_s type, T* object, USHORT id = 0) - { - Resource r(type, type == Resource::rsc_index ? id : object->getId(), object); - if (!list.exist(r)) - raiseNotRegistered(r, type, object->c_name()); - } - - void transferResources(thread_db* tdbb, ResourceList& from, ResourceTypes rt, NewResources& nr); - void transferResources(thread_db* tdbb, ResourceList& from); - - void postIndex(thread_db* tdbb, jrd_rel* relation, USHORT idxId); - - void releaseResources(thread_db* tdbb, jrd_tra* transaction = nullptr); - -// void inc_int_use_count(); -// void zero_int_use_count(); -// void markUndeletable(); - - Resource* get(FB_SIZE_T n) - { - return &list[n]; - } - - Resource* getPointer(Resource::rsc_s type) - { - FB_SIZE_T pos; - Resource temp(type); - list.find(temp, pos); - - if (pos == list.getCount()) - return list.end(); - return &list[pos]; - } - - Resource* getPointer(bool last) - { - return last ? list.end() : list.begin(); - } - - class iterator - { - public: - Resource* operator*() - { - return get(); - } - - Resource* operator->() - { - return get(); - } - - iterator& operator++() - { - ++index; - return *this; - } - - iterator& operator--() - { - --index; - return *this; - } - - bool operator==(const iterator& itr) const - { - return index == itr.index; - } - - bool operator!=(const iterator& itr) const - { - return index != itr.index; - } - - private: - void* operator new(size_t); - void* operator new[](size_t); - - public: - iterator(ResourceList* a, Resource::rsc_s type) - : index(a->getPointer(type)) - { } - - iterator(ResourceList* a, bool last) - : index(a->getPointer(last)) - { } - - Resource* get() - { - return index; - } - - private: - Resource* index; - }; - - iterator begin() - { - return iterator(this, false); - } - - iterator end() - { - return iterator(this, true); - } - - class Range - { - public: - Range(Resource::rsc_s r, ResourceList* l) - : list(l), start(r) - { } - - iterator begin() const - { - return iterator(list, start); - } - - iterator end() const - { - return iterator(list, Resource::next(start)); - } - - private: - ResourceList* list; - Resource::rsc_s start; - }; - - Range getObjects(Resource::rsc_s type) - { - return Range(type, this); + return getPtr(); } + */ private: - InternalResourceList list; - bool hazardFlag; - - void setResetPointersHazard(thread_db* tdbb, bool set); - void raiseNotRegistered(const Resource& r, Resource::rsc_s type, const char* name); - void transferList(thread_db* tdbb, const InternalResourceList& from, Resource::State resetState, - ResourceTypes rt, NewResources* nr, ResourceList* hazardList); + FB_SIZE_T compileOffset; }; + // Access items // In case we start to use MetaName with required pool parameter, // access item to be reworked! @@ -641,7 +524,7 @@ public: mainCsb(aMainCsb), csb_external(p), csb_access(p), - csb_resources(p, true), + csb_resources(nullptr), csb_dependencies(p), csb_fors(p), csb_localTables(p), @@ -720,7 +603,7 @@ public: ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked AccessItemList csb_access; // Access items to be checked vec* csb_variables; // Vector of variables, if any - ResourceList csb_resources; // Resources (relations and indexes) + Resources* csb_resources; // Resources (relations, indexes, routines, etc.) Firebird::Array csb_dependencies; // objects that this statement depends upon /// !!!!!!!!!!!!!!!!! Firebird::Array csb_fors; // select expressions Firebird::Array csb_localTables; // local tables @@ -747,9 +630,9 @@ public: MetaName csb_domain_validation; // Parsing domain constraint in PSQL // used in cmp.cpp/pass1 - jrd_rel* csb_view; + CachedResource csb_view; StreamType csb_view_stream; - jrd_rel* csb_parent_relation; + CachedResource csb_parent_relation; unsigned blrVersion; USHORT csb_remap_variable; bool csb_validate_expr; @@ -783,10 +666,10 @@ public: StreamType csb_view_stream; // stream number for view relation, below USHORT csb_flags; - jrd_rel* csb_relation; + CachedResource csb_relation; Firebird::string* csb_alias; // SQL alias name for this instance of relation - jrd_prc* csb_procedure; - jrd_rel* csb_view; // parent view + CachedResource csb_procedure; + CachedResource csb_view; // parent view IndexDescList* csb_idx; // Packed description of indices MessageNode* csb_message; // Msg for send/receive diff --git a/src/jrd/ext.cpp b/src/jrd/ext.cpp index 823c6e6272..8dd294f1df 100644 --- a/src/jrd/ext.cpp +++ b/src/jrd/ext.cpp @@ -235,7 +235,7 @@ void EXT_erase(record_param*, jrd_tra*) // Third param is unused. -ExternalFile* EXT_file(HazardPtr& relation, const TEXT* file_name) //, bid* description) +ExternalFile* EXT_file(jrd_rel* relation, const TEXT* file_name) //, bid* description) { /************************************** * diff --git a/src/jrd/ext_proto.h b/src/jrd/ext_proto.h index 3f4cf7c0bc..3d173a26a7 100644 --- a/src/jrd/ext_proto.h +++ b/src/jrd/ext_proto.h @@ -35,7 +35,7 @@ namespace Jrd { double EXT_cardinality(Jrd::thread_db*, Jrd::jrd_rel*); void EXT_erase(Jrd::record_param*, Jrd::jrd_tra*); -Jrd::ExternalFile* EXT_file(Jrd::HazardPtr&, const TEXT*); //, Jrd::bid*); +Jrd::ExternalFile* EXT_file(Jrd::jrd_rel*, const TEXT*); //, Jrd::bid*); void EXT_fini(Jrd::jrd_rel*, bool); bool EXT_get(Jrd::thread_db*, Jrd::record_param*, FB_UINT64&); void EXT_modify(Jrd::record_param*, Jrd::record_param*, Jrd::jrd_tra*); diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index 5f32cffe8b..a80503121d 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -1738,7 +1738,7 @@ static idx_e check_foreign_key(thread_db* tdbb, if (!MET_lookup_partner(tdbb, relation, idx, 0)) return result; - HazardPtr partner_relation(tdbb, FB_FUNCTION); + jrd_rel* partner_relation(tdbb); USHORT index_id = 0; if (idx->idx_flags & idx_foreign) diff --git a/src/jrd/ini.epp b/src/jrd/ini.epp index 709e5dea1b..382de8955c 100644 --- a/src/jrd/ini.epp +++ b/src/jrd/ini.epp @@ -973,7 +973,7 @@ void INI_init(thread_db* tdbb) const auto id = relfld[RFLD_R_ID]; //fprintf(stderr, "INI_init %d %s\n", id, names[relfld[RFLD_R_NAME]]); - HazardPtr relation = MetadataCache::findRelation(tdbb, id); + jrd_rel* relation = MetadataCache::findRelation(tdbb, id); if (id == 7) TRAP = relation.getPointer(); diff --git a/src/jrd/intl.cpp b/src/jrd/intl.cpp index 15b2928150..399ef122f4 100644 --- a/src/jrd/intl.cpp +++ b/src/jrd/intl.cpp @@ -169,24 +169,22 @@ HazardPtr CharSetContainer::lookupCharset(thread_db* tdbb, USH if (id == CS_dynamic) id = tdbb->getCharSet(); - HazardPtr cs = dbb->dbb_mdc->getCharSet(tdbb, id); + return dbb->dbb_mdc->getCharSet(tdbb, id); +} - // allocate a new character set object if we couldn't find one. - if (!cs) + +CharSetContainer* CharSetContainer::create(thread_db* tdbb, MetaId id) +{ + SubtypeInfo info; + + if (lookupInternalCharSet(id, &info) || MET_get_char_coll_subtype_info(tdbb, id, &info)) { - SubtypeInfo info; - - if (lookupInternalCharSet(id, &info) || MET_get_char_coll_subtype_info(tdbb, id, &info)) - { - CharSetContainer* csc = FB_NEW_POOL(*dbb->dbb_permanent) CharSetContainer(*dbb->dbb_permanent, id, &info); - dbb->dbb_mdc->setCharSet(tdbb, id, csc); - cs = dbb->dbb_mdc->getCharSet(tdbb, id); - } - else - ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(ttype)); + CharSetContainer* csc = FB_NEW_POOL(*dbb->dbb_permanent) CharSetContainer(*dbb->dbb_permanent, id, &info); + dbb->dbb_mdc->setCharSet(tdbb, id, csc); + cs = dbb->dbb_mdc->getCharSet(tdbb, id); } - - return cs; + else + ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(ttype)); } @@ -288,11 +286,11 @@ CsConvert CharSetContainer::lookupConverter(thread_db* tdbb, CHARSET_ID toCsId) return CsConvert(cs->getStruct(), toCs->getStruct()); } -HazardPtr CharSetContainer::lookupCollation(thread_db* tdbb, USHORT tt_id) +Collation* CharSetContainer::lookupCollation(thread_db* tdbb, USHORT tt_id) { const USHORT id = TTYPE_TO_COLLATION(tt_id); - HazardPtr coll(FB_FUNCTION); + Collation* coll(FB_FUNCTION); if (charset_collations.load(tdbb, id, coll)) { if (!coll->obsolete) @@ -301,7 +299,7 @@ HazardPtr CharSetContainer::lookupCollation(thread_db* tdbb, USHORT t CheckoutLockGuard guard(tdbb, createCollationMtx, FB_FUNCTION); // do we need it ? - HazardPtr to_delete(FB_FUNCTION); + Collation* to_delete(FB_FUNCTION); if (charset_collations.load(tdbb, id, coll)) { if (!coll->obsolete) @@ -404,7 +402,7 @@ void CharSetContainer::unloadCollation(thread_db* tdbb, USHORT tt_id) const USHORT id = TTYPE_TO_COLLATION(tt_id); fb_assert(id != 0); - HazardPtr coll(FB_FUNCTION); + Collation* coll(FB_FUNCTION); if (charset_collations.load(tdbb, id, coll)) { MutexLockGuard g(tdbb->getDatabase()->dbb_mdc->mdc_use_mutex, FB_FUNCTION); @@ -457,7 +455,7 @@ void Jrd::MetadataCache::destroyIntlObjects(thread_db* tdbb) { for (FB_SIZE_T i = 0; i < mdc_charsets.getCount(tdbb); i++) { - HazardPtr cs(FB_FUNCTION); + HazardPtr cs; if (mdc_charsets.load(tdbb, i, cs)) { cs->destroy(tdbb); @@ -996,7 +994,7 @@ CharSet* INTL_charset_lookup(thread_db* tdbb, USHORT parm1) } -HazardPtr INTL_texttype_lookup(thread_db* tdbb, USHORT parm1) +Collation* INTL_texttype_lookup(thread_db* tdbb, USHORT parm1) { /************************************** * @@ -1189,7 +1187,7 @@ USHORT INTL_string_to_key(thread_db* tdbb, outlen = (dest - pByte->dsc_address); break; default: - HazardPtr obj = INTL_texttype_lookup(tdbb, ttype); + Collation* obj = INTL_texttype_lookup(tdbb, ttype); fb_assert(key_type != INTL_KEY_MULTI_STARTING || (obj->getFlags() & TEXTTYPE_MULTI_STARTING_KEY)); outlen = obj->string_to_key(len, src, pByte->dsc_length, dest, key_type); break; diff --git a/src/jrd/intl_proto.h b/src/jrd/intl_proto.h index b9b642e949..f83a9a635f 100644 --- a/src/jrd/intl_proto.h +++ b/src/jrd/intl_proto.h @@ -49,7 +49,7 @@ bool INTL_data_or_binary(const dsc*); bool INTL_defined_type(Jrd::thread_db*, USHORT); USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT); Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1); -Jrd::HazardPtr INTL_texttype_lookup(Jrd::thread_db* tdbb, USHORT parm1); +Jrd::Collation* INTL_texttype_lookup(Jrd::thread_db* tdbb, USHORT parm1); void INTL_texttype_unload(Jrd::thread_db*, USHORT); bool INTL_texttype_validate(Jrd::thread_db*, const SubtypeInfo*); void INTL_pad_spaces(Jrd::thread_db*, dsc*, UCHAR*, ULONG); diff --git a/src/jrd/lck.cpp b/src/jrd/lck.cpp index 4f3d03730b..4fa1eac40f 100644 --- a/src/jrd/lck.cpp +++ b/src/jrd/lck.cpp @@ -1732,7 +1732,7 @@ void ExistenceLock::internalObjectDelete(thread_db* tdbb, unsigned fl) object->afterUnlock(tdbb, fl); if (!(fl & inCache)) - object->delayedDelete(tdbb); + object->retire(); } } @@ -1790,10 +1790,3 @@ void ExistenceLock::releaseLock(thread_db* tdbb, ReleaseMethod rm) } } -void ExistenceLock::removeFromCache(thread_db* tdbb) -{ - fb_assert(flags & inCache); - unsigned fl = (flags &= ~inCache); - if (((fl & countMask) == 0) && (fl & locked)) - leave245(tdbb, true); -} diff --git a/src/jrd/lck.h b/src/jrd/lck.h index b70b8e8329..601f13e1fa 100644 --- a/src/jrd/lck.h +++ b/src/jrd/lck.h @@ -256,7 +256,6 @@ public: #endif void unlock(thread_db* tdbb); // Release exclusive lock void releaseLock(thread_db* tdbb, ReleaseMethod rm); // Release any lock - void removeFromCache(thread_db* tdbb); // Invoked when object is removed from MDC private: static int ast(void* self) diff --git a/src/jrd/met.epp b/src/jrd/met.epp index 6c09102f0e..779a09b980 100644 --- a/src/jrd/met.epp +++ b/src/jrd/met.epp @@ -113,18 +113,18 @@ static int blocking_ast_dsql_cache(void* ast_object); static int partners_ast_relation(void*); static int rescan_ast_relation(void*); static ULONG get_rel_flags_from_FLAGS(USHORT); -static void get_trigger(thread_db*, HazardPtr&, bid*, bid*, TrigVectorPtr*, const TEXT*, FB_UINT64, bool, +static void get_trigger(thread_db*, jrd_rel*, bid*, bid*, TrigVectorPtr*, const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&, const bid*, Nullable ssDefiner); static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*); -static void lookup_view_contexts(thread_db*, HazardPtr&); +static void lookup_view_contexts(thread_db*, jrd_rel*); static void make_relation_scope_name(const TEXT*, const USHORT, string& str); static ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id); static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, const MetaName name); -static void save_trigger_data(thread_db*, TrigVectorPtr*, HazardPtr&, Statement*, blb*, blb*, +static void save_trigger_data(thread_db*, TrigVectorPtr*, jrd_rel*, Statement*, blb*, blb*, const TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&, const bid*, Nullable ssDefiner); static void scan_partners(thread_db*, jrd_rel*); -static void store_dependencies(thread_db*, Array&, HazardPtr&, +static void store_dependencies(thread_db*, Array&, jrd_rel*, const MetaName&, int, jrd_tra*); static bool verify_TRG_ignore_perm(thread_db*, const MetaName&); @@ -1497,7 +1497,7 @@ bool MET_get_char_coll_subtype_info(thread_db* tdbb, USHORT id, SubtypeInfo* inf DmlNode* MET_get_dependencies(thread_db* tdbb, - Jrd::HazardPtr& relation, + Jrd::jrd_rel* relation, const UCHAR* blob, const ULONG blob_length, CompilerScratch* view_csb, @@ -1583,12 +1583,6 @@ DmlNode* MET_get_dependencies(thread_db* tdbb, } -jrd_fld* MET_get_field(const Jrd::HazardPtr& relation, USHORT id) -{ - return MET_get_field(relation.getPointer(), id); -} - - jrd_fld* MET_get_field(const jrd_rel* relation, USHORT id) { /************************************** @@ -1761,7 +1755,7 @@ void MetadataCache::load_db_triggers(thread_db* tdbb, int type) TRG.RDB$TRIGGER_INACTIVE EQ 0 SORTED BY TRG.RDB$TRIGGER_SEQUENCE { - MET_load_trigger(tdbb, nullRel, TRG.RDB$TRIGGER_NAME, &mdc_triggers[type]); + MET_load_trigger(tdbb, nullptr, TRG.RDB$TRIGGER_NAME, &mdc_triggers[type]); } END_FOR } @@ -1795,7 +1789,7 @@ void MetadataCache::load_ddl_triggers(thread_db* tdbb) { if ((TRG.RDB$TRIGGER_TYPE & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DDL) { - MET_load_trigger(tdbb, nullRel, TRG.RDB$TRIGGER_NAME, &mdc_ddl_triggers); + MET_load_trigger(tdbb, nullptr, TRG.RDB$TRIGGER_NAME, &mdc_ddl_triggers); } } END_FOR @@ -1803,7 +1797,7 @@ void MetadataCache::load_ddl_triggers(thread_db* tdbb) void MET_load_trigger(thread_db* tdbb, - HazardPtr& relation, + jrd_rel* relation, const MetaName& trigger_name, TrigVectorPtr* triggers) { @@ -2409,7 +2403,7 @@ SLONG MetadataCache::lookup_index_name(thread_db* tdbb, const MetaName& index_na *status = MET_object_inactive; id = X.RDB$INDEX_ID - 1; - HazardPtr relation = lookup_relation(tdbb, X.RDB$RELATION_NAME); + jrd_rel* relation = lookup_relation(tdbb, X.RDB$RELATION_NAME); *relation_id = relation->rel_id; } END_FOR @@ -2543,7 +2537,7 @@ void MET_lookup_index_expression(thread_db* tdbb, jrd_rel* relation, index_desc* return; } - HazardPtr wrk = MET_scan_relation(tdbb, relation->rel_id); + jrd_rel* wrk = MET_scan_relation(tdbb, relation->rel_id); if (!wrk) { (Arg::Gds(isc_random) << "Relation was deleted").raise(); @@ -2666,7 +2660,7 @@ bool MET_lookup_partner(thread_db* tdbb, jrd_rel* relation, index_desc* idx, con IND.RDB$UNIQUE_FLAG = 1 { //// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved. - HazardPtr foundRel(FB_FUNCTION); + jrd_rel* foundRel = nullptr; const jrd_rel* partner_relation = relation; if (relation->rel_name != IND.RDB$RELATION_NAME) { @@ -2745,7 +2739,7 @@ HazardPtr MetadataCache::lookup_procedure(thread_db* tdbb, const Qualif SET_TDBB(tdbb); Attachment* attachment = tdbb->getAttachment(); MetadataCache* mdc = attachment->att_database->dbb_mdc; - HazardPtr check_procedure(FB_FUNCTION); + HazardPtr check_procedure; // See if we already know the procedure by name for (auto procedure : mdc->mdc_procedures.snapshot()) @@ -2772,7 +2766,7 @@ HazardPtr MetadataCache::lookup_procedure(thread_db* tdbb, const Qualif // We need to look up the procedure name in RDB$PROCEDURES - HazardPtr procedure(FB_FUNCTION); + HazardPtr procedure; AutoCacheRequest request(tdbb, irq_l_procedure, IRQ_REQUESTS); @@ -2815,7 +2809,7 @@ HazardPtr MetadataCache::lookup_procedure_id(thread_db* tdbb, USHORT id SET_TDBB(tdbb); Attachment* attachment = tdbb->getAttachment(); MetadataCache* mdc = attachment->att_database->dbb_mdc; - HazardPtr check_procedure(FB_FUNCTION), procedure(FB_FUNCTION); + HazardPtr check_procedure, procedure; if (mdc->mdc_procedures.load(tdbb, id, procedure) && procedure->getId() == id && @@ -2864,7 +2858,7 @@ HazardPtr MetadataCache::lookup_procedure_id(thread_db* tdbb, USHORT id } -HazardPtr MetadataCache::lookup_relation(thread_db* tdbb, const MetaName& name) +jrd_rel* MetadataCache::lookup_relation(thread_db* tdbb, const MetaName& name) { /************************************** * @@ -2880,7 +2874,7 @@ HazardPtr MetadataCache::lookup_relation(thread_db* tdbb, const MetaNam SET_TDBB(tdbb); Attachment* attachment = tdbb->getAttachment(); MetadataCache* mdc = attachment->att_database->dbb_mdc; - HazardPtr check_relation(FB_FUNCTION); + jrd_rel* check_relation = nullptr; // See if we already know the relation by name @@ -2919,7 +2913,7 @@ HazardPtr MetadataCache::lookup_relation(thread_db* tdbb, const MetaNam // We need to look up the relation name in RDB$RELATIONS - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; AutoCacheRequest request(tdbb, irq_l_relation, IRQ_REQUESTS); @@ -2963,7 +2957,7 @@ HazardPtr MetadataCache::lookup_relation(thread_db* tdbb, const MetaNam } -HazardPtr MetadataCache::lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted) +jrd_rel* MetadataCache::lookup_relation_id(thread_db* tdbb, SLONG id, bool return_deleted) { /************************************** * @@ -2987,7 +2981,7 @@ HazardPtr MetadataCache::lookup_relation_id(thread_db* tdbb, SLONG id, return findRelation(tdbb, (USHORT) id); } - HazardPtr relation(FB_FUNCTION), check_relation(FB_FUNCTION); + jrd_rel* relation = nullptr, check_relation = nullptr; if (mdc->mdc_relations.load(tdbb, id, relation)) { if (relation->rel_flags & REL_deleting) @@ -3076,7 +3070,7 @@ bool MetadataCache::checkRelation(thread_db* tdbb, jrd_rel* relation) Attachment* const attachment = tdbb->getAttachment(); MetadataCache* mdc = attachment->att_database->dbb_mdc; - HazardPtr check_relation(FB_FUNCTION); + jrd_rel* check_relation = nullptr; if ((!mdc->mdc_relations.load(tdbb, relation->rel_id, check_relation)) || (relation != check_relation)) { @@ -3107,7 +3101,7 @@ bool MetadataCache::checkRelation(thread_db* tdbb, jrd_rel* relation) DmlNode* MET_parse_blob(thread_db* tdbb, - Jrd::HazardPtr& relation, + Jrd::jrd_rel* relation, bid* blob_id, CompilerScratch** csb_ptr, Statement** statementPtr, @@ -3153,7 +3147,7 @@ DmlNode* MET_parse_blob(thread_db* tdbb, } -void MET_parse_sys_trigger(thread_db* tdbb, HazardPtr& relation) +void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation) { /************************************** * @@ -3313,7 +3307,7 @@ HazardPtr MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool if (id >= mdc->mdc_procedures.getCount(tdbb)) mdc->mdc_procedures.grow(tdbb, id + 10); - HazardPtr procedure(FB_FUNCTION); + HazardPtr procedure; if (mdc->mdc_procedures.load(tdbb, id, procedure) && !(procedure->flags & Routine::FLAG_OBSOLETE)) { @@ -3356,42 +3350,18 @@ HazardPtr MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool } } - jrd_prc* newProcedure = FB_NEW_POOL(mdc->getPool()) jrd_prc(mdc->getPool()); + return NULL; +} + +jrd_prc* jrd_prc::create(thread_db* tdbb, MetaId id) +{ + Attachment* attachment = tdbb->getAttachment(); + Database* dbb = tdbb->getDatabase(); + MetadataCache* mdc = dbb->dbb_mdc; + + jrd_prc* newProcedure = FB_NEW_POOL(mdc->getPool()) jrd_prc(mdc->getPool(), id); try { - - newProcedure->flags |= (Routine::FLAG_BEING_SCANNED | flags); - newProcedure->flags &= ~(Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED); - newProcedure->setId(id); - - if (!newProcedure->existenceLock) - { - newProcedure->existenceLock = FB_NEW_POOL(mdc->getPool()) - ExistenceLock(mdc->getPool(), tdbb, LCK_prc_exist, id, newProcedure); - } - - while (!dbb->dbb_mdc->mdc_procedures.replace(tdbb, id, procedure, newProcedure)) - { - if (procedure) - { - procedure->startup.wait(); - - if (!(procedure->flags & Routine::FLAG_OBSOLETE)) - { - // Someone else created required procedure - - delete newProcedure->getExternal(); - newProcedure->setExternal(NULL); - newProcedure->delayedDelete(tdbb); - - if (procedure->flags & Routine::FLAG_SCANNED) - return procedure; - } - } - } - - if (!noscan) - { AutoCacheRequest request(tdbb, irq_r_procedure, IRQ_REQUESTS); FOR(REQUEST_HANDLE request) @@ -3503,7 +3473,7 @@ HazardPtr MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool try { parameter->prm_default_value = static_cast( - MET_parse_blob(tdbb, nullRel, &pa_default_value, NULL, NULL, false, false)); + MET_parse_blob(tdbb, nullptr, &pa_default_value, NULL, NULL, false, false)); } catch (const Exception&) { @@ -3639,29 +3609,16 @@ HazardPtr MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool } } END_FOR - } // if !noscan - - // Make sure that it is really being scanned - fb_assert(newProcedure->flags & Routine::FLAG_BEING_SCANNED); - - newProcedure->flags &= ~Routine::FLAG_BEING_SCANNED; - newProcedure->startup.open(); + newProcedure->startup.open(); } // try catch (const Exception&) { - if (newProcedure->getExternal()) - { - delete newProcedure->getExternal(); - newProcedure->setExternal(NULL); - } - - newProcedure->flags &= ~Routine::FLAG_BEING_SCANNED; - newProcedure->startup.open(); + jrd_prc::destroy(newProcedure); throw; } - return procedure; + return newProcedure; } bool jrd_prc::reload(thread_db* tdbb) @@ -3710,7 +3667,7 @@ bool jrd_prc::reload(thread_db* tdbb) return false; } -HazardPtr MetadataCache::findRelation(thread_db* tdbb, USHORT id) +jrd_rel* MetadataCache::findRelation(thread_db* tdbb, USHORT id) { /************************************** * @@ -3730,7 +3687,7 @@ HazardPtr MetadataCache::findRelation(thread_db* tdbb, USHORT id) MetadataCache* mdc = dbb->dbb_mdc; MemoryPool& pool = mdc->getPool(); - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; if (mdc->mdc_relations.load(tdbb, id, relation)) return relation; @@ -3838,9 +3795,9 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation) } -HazardPtr MET_scan_relation(thread_db* tdbb, USHORT id) +jrd_rel* MET_scan_relation(thread_db* tdbb, USHORT id) { - HazardPtr relation = MetadataCache::lookup_relation_id(tdbb, id, false); + jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, id, false); if (relation && (!(relation->rel_flags & REL_scanned) || (relation->rel_flags & REL_being_scanned))) @@ -3851,7 +3808,7 @@ HazardPtr MET_scan_relation(thread_db* tdbb, USHORT id) return relation; } -void MET_scan_relation(thread_db* tdbb, HazardPtr& relation) +void jrd_rel::scan(thread_db* tdbb) { /************************************** * @@ -4070,7 +4027,7 @@ void MET_scan_relation(thread_db* tdbb, HazardPtr& relation) csb->csb_g_flags |= csb_get_dependencies; field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p); const MetaName depName(REL.RDB$RELATION_NAME); - store_dependencies(tdbb, csb->csb_dependencies, nullRel, depName, obj_view, depTrans); + store_dependencies(tdbb, csb->csb_dependencies, nullptr, depName, obj_view, depTrans); } else field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p); @@ -4490,7 +4447,7 @@ ULONG MET_get_rel_flags_from_TYPE(USHORT type) } -static void get_trigger(thread_db* tdbb, HazardPtr& relation, +static void get_trigger(thread_db* tdbb, jrd_rel* relation, bid* blob_id, bid* debug_blob_id, TrigVectorPtr* ptr, const TEXT* name, FB_UINT64 type, bool sys_trigger, USHORT flags, @@ -4580,7 +4537,7 @@ static bool get_type(thread_db* tdbb, USHORT* id, const UCHAR* name, const TEXT* } -static void lookup_view_contexts( thread_db* tdbb, HazardPtr& view) +static void lookup_view_contexts( thread_db* tdbb, jrd_rel* view) { /************************************** * @@ -4659,7 +4616,7 @@ static ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id) length = blob->BLB_get_data(tdbb, temp.getBuffer(length), length); - DmlNode* const node = PAR_blr(tdbb, nullRel, temp.begin(), length, NULL, &csb, NULL, false, 0); + DmlNode* const node = PAR_blr(tdbb, nullptr, temp.begin(), length, NULL, &csb, NULL, false, 0); return static_cast(node); } @@ -4682,7 +4639,7 @@ static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, c length = blob->BLB_get_data(tdbb, temp.getBuffer(length), length); - return PAR_validation_blr(tdbb, nullRel, temp.begin(), length, NULL, &csb, 0); + return PAR_validation_blr(tdbb, nullptr, temp.begin(), length, NULL, &csb, 0); } @@ -4705,7 +4662,7 @@ void MetadataCache::releaseTrigger(thread_db* tdbb, USHORT triggerId, const Meta return; SET_TDBB(tdbb); - HazardPtr trigger(FB_FUNCTION); + HazardPtr trigger; SLONG n = vector->load()->lookup(tdbb, name, &trigger); if (n < 0) return; @@ -4868,7 +4825,7 @@ bool MetadataCache::resolve_charset_and_collation(thread_db* tdbb, USHORT* id, } -static void save_trigger_data(thread_db* tdbb, TrigVectorPtr* ptr, HazardPtr& relation, +static void save_trigger_data(thread_db* tdbb, TrigVectorPtr* ptr, jrd_rel* relation, Statement* statement, blb* blrBlob, blb* debugInfoBlob, const TEXT* name, FB_UINT64 type, bool sys_trigger, USHORT flags, @@ -4960,7 +4917,7 @@ HazardPtr findTrigger(TrigVector* triggers, const MetaName& trig_ } } - return HazardPtr(FB_FUNCTION); + return HazardPtr; } @@ -5021,7 +4978,7 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation) { //// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved. const jrd_rel* partner_relation = relation; - HazardPtr rel(FB_FUNCTION); + jrd_rel* rel = nullptr; if (relation->rel_name != IND.RDB$RELATION_NAME) { rel = MetadataCache::lookup_relation(tdbb, IND.RDB$RELATION_NAME); @@ -5087,7 +5044,7 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation) { //// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved. const jrd_rel* partner_relation = relation; - HazardPtr rel(FB_FUNCTION); + jrd_rel* rel = nullptr; if (relation->rel_name != IND.RDB$RELATION_NAME) { rel = MetadataCache::lookup_relation(tdbb, IND.RDB$RELATION_NAME); @@ -5124,7 +5081,7 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation) static void store_dependencies(thread_db* tdbb, Array& dependencies, - HazardPtr& dep_rel, + jrd_rel* dep_rel, const MetaName& object_name, int dependency_type, jrd_tra* transaction) @@ -5145,7 +5102,7 @@ static void store_dependencies(thread_db* tdbb, SET_TDBB(tdbb); - HazardPtr t(FB_FUNCTION); + HazardPtr t; const bool checkTableScope = (dependency_type == obj_computed) || (dependency_type == obj_trigger) && dep_rel && @@ -5169,7 +5126,7 @@ static void store_dependencies(thread_db* tdbb, } int dpdo_type = dependency.objType; - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation = nullptr; const jrd_prc* procedure = NULL; const MetaName* dpdo_name = NULL; MetaName packageName; @@ -5534,13 +5491,13 @@ void MetadataCache::releaseRelations(thread_db* tdbb) { for (FB_SIZE_T n = 0; n < mdc_relations.getCount(tdbb); ++n) { - HazardPtr relation(tdbb, FB_FUNCTION); + jrd_rel* relation = nullptr; if (mdc_relations.load(tdbb, n, relation)) { if (relation->rel_file) EXT_fini(relation.getPointer(), false); - relation->delayedDelete(tdbb); + delete relation; } } // ??????? mdc_relations.clear(); @@ -5620,7 +5577,7 @@ void MetadataCache::invalidateReplSet(thread_db* tdbb) } } -HazardPtr MetadataCache::lookupFunction(thread_db* tdbb, const QualifiedName& name, USHORT setBits, USHORT clearBits) +Function* MetadataCache::lookupFunction(thread_db* tdbb, const QualifiedName& name, USHORT setBits, USHORT clearBits) { for (auto function : mdc_functions.snapshot()) { @@ -5631,19 +5588,19 @@ HazardPtr MetadataCache::lookupFunction(thread_db* tdbb, const Qualifi } } - return HazardPtr(FB_FUNCTION); + return nullptr; } -HazardPtr MetadataCache::getRelation(thread_db* tdbb, ULONG rel_id) +jrd_rel* MetadataCache::getRelation(thread_db* tdbb, ULONG rel_id) { - HazardPtr rc(tdbb, FB_FUNCTION); + jrd_rel* rc(tdbb); mdc_relations.load(tdbb, rel_id, rc); return rc; } -HazardPtr MetadataCache::getRelation(Attachment* att, ULONG rel_id) +jrd_rel* MetadataCache::getRelation(Attachment* att, ULONG rel_id) { - HazardPtr rc(att, FB_FUNCTION); + HazardPtr rc(att); mdc_relations.load(att, rel_id, rc); return rc; } @@ -5713,7 +5670,7 @@ void Trigger::compile(thread_db* tdbb) *csb->csb_dbg_info); } - HazardPtr rel = MetadataCache::findRelation(tdbb, relation->rel_id); + jrd_rel* rel = MetadataCache::findRelation(tdbb, relation->rel_id); if (!rel) fatal_exception::raiseFmt("Relation %s unexpectedly lost", relation->rel_name); @@ -5777,7 +5734,7 @@ int Trigger::release(thread_db* tdbb) statement->release(tdbb); statement = NULL; - delayedDelete(tdbb); + retire(); return 0; } */ @@ -5887,3 +5844,47 @@ void Trigger::release(thread_db* tdbb) statement = NULL; } +CacheElement* MetadataCache::lookupRelation(thread_db* tdbb, const MetaName& name) +{ + SET_TDBB(tdbb); + + MetadataCache* mdc = tdbb->getDatabase()->dbb_mdc; + auto rc = mdc->mdc_relations->lookup(tdbb, [name](jrd_rel* rel) { return rel->rel_name == name; }); + if (!rc) carefully lookup & load relation + + return rc; +} + +CacheElement* MetadataCache::lookupRelation(thread_db* tdbb, MetaId id) +{ + SET_TDBB(tdbb); + + MetadataCache* mdc = tdbb->getDatabase()->dbb_mdc; + auto rc = mdc->mdc_relations->getData(tdbb, id); + if (!rc) carefully lookup & load relation + + return rc; +} + +CacheElement* MetadataCache::lookupProcedure(thread_db* tdbb, const MetaName& name) +{ + SET_TDBB(tdbb); + + MetadataCache* mdc = tdbb->getDatabase()->dbb_mdc; + auto rc = mdc->mdc_procedures->lookup(tdbb, [name](jrd_prc* proc) { return proc->routine_name == name; }); + if (!rc) carefully lookup & load procedure + + return rc; +} + +CacheElement* MetadataCache::lookupProcedure(thread_db* tdbb, MetaId id, bool noscan = false) +{ + SET_TDBB(tdbb); + + MetadataCache* mdc = tdbb->getDatabase()->dbb_mdc; + auto rc = mdc->mdc_procedures->getData(tdbb, id); + if (!rc) carefully lookup & load procedure + + return rc; +} + diff --git a/src/jrd/met.h b/src/jrd/met.h index c79aa20af0..cb19234b99 100644 --- a/src/jrd/met.h +++ b/src/jrd/met.h @@ -25,6 +25,9 @@ #define JRD_MET_H #include "../jrd/HazardPtr.h" +#include + +#include "../common/StatusArg.h" #include "../jrd/Relation.h" #include "../jrd/Function.h" @@ -33,7 +36,7 @@ #include "../jrd/irq.h" #include "../jrd/drq.h" -#include "../jrd/Collation.h" +#include "../jrd/CharSetContainer.h" // Record types for record summary blob records @@ -140,13 +143,8 @@ const int TRIGGER_COMBINED_MAX = 128; #include "../jrd/obj.h" #include "../dsql/sym.h" -struct SubtypeInfo; - namespace Jrd { -class CharSetContainer; - -/* // Procedure block class jrd_prc : public Routine @@ -161,88 +159,14 @@ public: private: const ExtEngineManager::Procedure* prc_external; -public: - explicit jrd_prc(MemoryPool& p) - : Routine(p), + jrd_prc(MemoryPool& p, MetaId id) + : Routine(p, id), prc_record_format(NULL), prc_type(prc_legacy), prc_external(NULL) { } -public: - virtual int getObjectType() const - { - return obj_procedure; - } - - virtual SLONG getSclType() const - { - return obj_procedure; - } - - virtual void releaseFormat() - { - delete prc_record_format; - prc_record_format = NULL; - } - - virtual ~jrd_prc() - { - delete prc_external; - } - - virtual bool checkCache(thread_db* tdbb) const; - virtual void clearCache(thread_db* tdbb); - - virtual void releaseExternal() - { - delete prc_external; - prc_external = NULL; - } - -protected: - virtual bool reload(thread_db* tdbb); // impl is in met.epp -}; - - -// Parameter block - -class Parameter : public pool_alloc -{ -public: - USHORT prm_number; - dsc prm_desc; - NestConst prm_default_value; - bool prm_nullable; - prm_mech_t prm_mechanism; - MetaName prm_name; // asciiz name - MetaName prm_field_source; - FUN_T prm_fun_mechanism; - -public: - explicit Parameter(MemoryPool& p) - : prm_name(p), - prm_field_source(p) - { - } -}; -*/ - -// Procedure block - -class jrd_prc : public Routine -{ -public: - const Format* prc_record_format; - prc_t prc_type; // procedure type - - const ExtEngineManager::Procedure* getExternal() const { return prc_external; } - void setExternal(ExtEngineManager::Procedure* value) { prc_external = value; } - -private: - const ExtEngineManager::Procedure* prc_external; - public: explicit jrd_prc(MemoryPool& p) : Routine(p), @@ -269,13 +193,16 @@ public: prc_record_format = NULL; } - virtual ~jrd_prc() +private: + virtual ~jrd_prc() override { delete prc_external; } +public: + static jrd_prc* create(thread_db* tdbb, MetaId id, CacheObject::Flag flags); + virtual bool checkCache(thread_db* tdbb) const; - virtual void clearCache(thread_db* tdbb); virtual void releaseExternal() { @@ -330,188 +257,679 @@ enum IndexStatus class CharSet; -class Dependency : public CacheObject +class ObjectBase : public HazardObject { public: - virtual void resetDependentObject(thread_db* tdbb); + enum ResetType {Recompile, Mark, Commit, Rollback}; + typedef SLONG ReturnedId; // enable '-1' as not found + +public: + virtual void resetDependentObject(thread_db* tdbb, ResetType rt) = 0; + virtual void eraseObject(thread_db* tdbb) = 0; // erase object + +public: void resetDependentObjects(thread_db* tdbb, TraNumber olderThan); - void addDependentObject(thread_db* tdbb, Dependency* dep); - void removeDependentObject(thread_db* tdbb, Dependency* dep); + void addDependentObject(thread_db* tdbb, ObjectBase* dep); + void removeDependentObject(thread_db* tdbb, ObjectBase* dep); + [[noreturn]] void busyError(thread_db* tdbb, MetaId id, const char* name); }; +namespace CacheFlag +{ + static const CacheObject::Flag COMMITTED = 0x01; + static const CacheObject::Flag ERASED = 0x02; + static const CacheObject::Flag NOSCAN = 0x04; + static const CacheObject::Flag AUTOCREATE = 0x08; -class CharSetContainer : public DependentObject + static const CacheObject::Flag IGNORE_MASK = COMMITTED | ERASED; +} + +template +class CacheList : public HazardObject { public: - typedef const char* Key; + CacheList(OBJ* obj, TraNumber currentTrans, CacheObject::Flag fl = 0) + : object(obj), next(nullptr), traNumber(currentTrans), cacheFlags(fl) + { } - CharSetContainer(MemoryPool& p, USHORT cs_id, const SubtypeInfo* info); - - void release(thread_db* tdbb) + // find appropriate object in cache + OBJ* getObject(TraNumber currentTrans, CacheObject::Flag flags) const { - for (auto coll : charset_collations.snapshot()) + CacheObject::Flag f(cacheFlags.load() & ~(flags & CacheFlag::IGNORE_MASK)); + + // object deleted, good bye + if (f & CacheFlag::ERASED) + return nullptr; + + // committed (i.e. confirmed) objects are freely available + if (f & CacheFlag::COMMITTED) + return object; + + // transaction that created an object can always access it + if ((traNumber == currentTrans) && currentTrans) + return object; + + // try next level + CacheList* n = next.load(atomics::memory_order_acquire); + return n ? n->getObject(currentTrans, flags) : nullptr; + } + + bool isBusy(TraNumber currentTrans) const + { + return traNumber != currentTrans && !(cacheFlags & CacheFlag::COMMITTED); + } + + // add new entry to the list + static bool add(atomics::atomic& list, CacheList* newVal) + { + HazardPtr oldVal(list); + + do { - if (coll) - coll->release(tdbb); + if (oldVal && oldVal->isBusy(newVal->traNumber)) // modified in other transaction + return false; + newVal->next.store(oldVal.getPointer(), atomics::memory_order_relaxed); + } while (! oldVal.replace2(list, newVal)); + + return true; + } + + // remove too old objects - they are anyway can't be in use + static TraNumber cleanup(atomics::atomic& list, const TraNumber oldest) + { + TraNumber rc = 0; + for (HazardPtr entry(list); entry; entry.set(entry->next)) + { + if ((entry->cacheFlags & CacheFlag::COMMITTED) && entry->traNumber < oldest) + { + if (entry->cacheFlags.fetch_or(CacheFlag::ERASED) & CacheFlag::ERASED) + break; // someone else also performs cleanup + + // split remaining list off + if (entry.replace2(list, nullptr)) + { + while (entry && !(entry->cacheFlags.fetch_or(CacheFlag::ERASED) & CacheFlag::ERASED)) + { + entry->retire(); + OBJ::destroy(entry->object); + entry.set(entry->next); + } + } + break; + } + + // store traNumber of last not removed list element + rc = entry->traNumber; + } + + return rc; // 0 is returned in a case when list becomes empty + } + + // created earlier object is OK and should become visible to the world + void commit(TraNumber currentTrans, TraNumber nextTrans) + { + fb_assert(cacheFlags == 0); + fb_assert(traNumber == currentTrans); + traNumber = nextTrans; + cacheFlags |= CacheFlag::COMMITTED; + } + + // created earlier object is bad and should be destroyed + static void rollback(atomics::atomic& list, const TraNumber currentTran) + { + // Take into an account that no other transaction except current (i.e. object creator) + // can access uncommitted objects, only list entries may be accessed as hazard pointers. + // Therefore rollback can retire such entries at once, a kind of pop() from stack. + + HazardPtr entry(list); + while (entry) + { + if (entry->cacheFlags & CacheFlag::COMMITTED) + break; + fb_assert(entry->traNumber == currentTran); + + if (entry.replace2(list, entry->next)) + { + entry->retire(); + OBJ::destroy(entry->object); + entry = list; + } } } - void destroy(thread_db* tdbb) + // mark as erased + void erase() { - cs->destroy(); - release(tdbb); + cacheFlags |= CacheFlag::ERASED; } - CharSet* getCharSet() + void assertCommitted() { - return cs; - } - - HazardPtr lookupCollation(thread_db* tdbb, USHORT tt_id); - void unloadCollation(thread_db* tdbb, USHORT tt_id); - - CsConvert lookupConverter(thread_db* tdbb, CHARSET_ID to_cs); - - static HazardPtr lookupCharset(thread_db* tdbb, USHORT ttype); - static Lock* createCollationLock(thread_db* tdbb, USHORT ttype, void* object = NULL); - - bool hasData() const - { - return cs != nullptr; - } - - void removeFromCache(thread_db* tdbb) override - { - delayedDelete(tdbb); - } - - const char* c_name() const override - { - return cs->getName(); + fb_assert(cacheFlags & CacheFlag::COMMITTED); } private: - static bool lookupInternalCharSet(USHORT id, SubtypeInfo* info); - -private: - HazardArray charset_collations; - CharSet* cs; + OBJ* object; + atomics::atomic next; + TraNumber traNumber; // when COMMITTED not set - stores transaction that created this list element + // when COMMITTED is set - stores transaction after which older elements are not needed + // traNumber to be changed BEFORE setting COMMITTED + MdcVersion version; // version of metadata cache when object was added + atomics::atomic cacheFlags; }; + +class CurrentTransaction +{ +public: + static TraNumber getNumber(thread_db* tdbb); +/* static TraNumber currentTraNumber(thread_db* tdbb) + { + jrd_tra* tra = tdbb->getTransaction(); + return tra ? tra->tra_number : 0; + } */ +}; + + +template +class CacheElement : public ObjectBase +{ + typedef CacheList CachedObj; + +public: + CacheElement(MetaId id) : + list(nullptr), resetAt(0), myId(id) + { } + + ~CacheElement() + { + cleanup(); + } + + OBJ* getObject(thread_db* tdbb, CacheObject::Flag flags = 0) + { + HazardPtr l(list); + if (!l) + return nullptr; + return l->getObject(CurrentTransaction::getNumber(tdbb), flags); + } + + bool storeObject(thread_db* tdbb, OBJ* obj, CacheObject::Flag fl = 0) + { + TraNumber oldest = tdbb->getDatabase()->dbb_oldest_active; + TraNumber oldResetAt = resetAt.load(atomics::memory_order_acquire); + if (oldResetAt && oldResetAt < oldest) + setNewResetAt(oldResetAt, CachedObj::cleanup(list, oldest)); + + TraNumber current = CurrentTransaction::getNumber(tdbb); + CachedObj* value = FB_NEW CachedObj(obj, current, fl & CacheFlag::IGNORE_MASK); + if (!CachedObj::add(list, value)) + { + delete value; + return false; + } + + setNewResetAt(oldResetAt, current); + return true; + } + + void commit(thread_db* tdbb) + { + HazardPtr current(list); + if (current) + current->commit(CurrentTransaction::getNumber(tdbb), tdbb->getDatabase()->dbb_next_transaction); + } + + void rollback(thread_db* tdbb) + { + CacheList::rollback(list, CurrentTransaction::getNumber(tdbb)); + } + + void cleanup() + { + list.load()->assertCommitted(); + CacheList::cleanup(list, MAX_TRA_NUMBER); + } + + void resetDependentObject(thread_db* tdbb, ResetType rt) override + { + switch (rt) + { + case ObjectBase::ResetType::Recompile: + { + OBJ* newObj = OBJ::create(tdbb, myId, 0); + if (!storeObject(tdbb, newObj)) + { + OBJ::destroy(newObj); + OBJ* oldObj = getObject(tdbb); + busyError(tdbb, myId, oldObj ? oldObj->c_name() : nullptr); + } + } + break; + + case ObjectBase::ResetType::Mark: + // used in AST, therefore ignore error when saving empty object + if (storeObject(tdbb, nullptr)) + commit(tdbb); + break; + + case ObjectBase::ResetType::Commit: + commit(tdbb); + break; + + case ObjectBase::ResetType::Rollback: + rollback(tdbb); + break; + } + } + + void eraseObject(thread_db* tdbb) override + { + HazardPtr l(list); + fb_assert(l); + if (!l) + return; + + if (!storeObject(tdbb, nullptr, CacheFlag::ERASED)) + { + OBJ* oldObj = getObject(tdbb); + busyError(tdbb, myId, oldObj ? oldObj->c_name() : nullptr); + } + } + +private: + void setNewResetAt(TraNumber oldVal, TraNumber newVal) + { + resetAt.compare_exchange_strong(oldVal, newVal, + atomics::memory_order_release, atomics::memory_order_relaxed); + } + + atomics::atomic list; + atomics::atomic resetAt; + MetaId myId; +}; + + +template +class CacheVector : public Firebird::PermanentStorage +{ +public: + static const unsigned SUBARRAY_SIZE = 1 << SUBARRAY_SHIFT; + static const unsigned SUBARRAY_MASK = SUBARRAY_SIZE - 1; + + typedef CacheElement StoredObject; + typedef atomics::atomic SubArrayData; + typedef atomics::atomic ArrayData; + typedef SharedReadVector Storage; + + explicit CacheVector(MemoryPool& pool) + : Firebird::PermanentStorage(pool), + m_objects(getPool()) + {} + +private: + static FB_SIZE_T getCount(const HazardPtr& v) + { + return v->getCount() << SUBARRAY_SHIFT; + } + + SubArrayData* getDataPointer(MetaId id) const + { + auto up = m_objects.readAccessor(); + if (id >= getCount(up)) + return nullptr; + + auto sub = up->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire); + fb_assert(sub); + return &sub[id & SUBARRAY_MASK]; + } + + void grow(FB_SIZE_T reqSize) + { + fb_assert(reqSize > 0); + reqSize = ((reqSize - 1) >> SUBARRAY_SHIFT) + 1; + + Firebird::MutexLockGuard g(objectsGrowMutex, FB_FUNCTION); + + m_objects.grow(reqSize); + auto wa = m_objects.writeAccessor(); + fb_assert(wa->getCapacity() >= reqSize); + while (wa->getCount() < reqSize) + { + SubArrayData* sub = FB_NEW_POOL(getPool()) SubArrayData[SUBARRAY_SIZE]; + memset(sub, 0, sizeof(SubArrayData) * SUBARRAY_SIZE); + wa->add()->store(sub, atomics::memory_order_release); + } + } + +public: + StoredObject* getData(thread_db*, MetaId id) + { + auto ptr = getDataPointer(id); + return ptr ? *ptr : nullptr; + } + + E* getObject(thread_db* tdbb, MetaId id, CacheObject::Flag flags) + { +// In theory that should be endless cycle - object may arrive/disappear again and again. +// But in order to faster find devel problems we run it very limited number of times. +#ifdef DEV_BUILD + for (int i = 0; i < 2; ++i) +#else + for (;;) +#endif + { + auto ptr = getDataPointer(id); + if (ptr) + { + HazardPtr data(*ptr); + if (data) + { + auto rc = data->getObject(tdbb, flags); + if (rc) + return rc; + } + } + + if (!(flags & CacheFlag::AUTOCREATE)) + return nullptr; + + auto val = E::create(tdbb, id, flags); + if (!val) + (Firebird::Arg::Gds(isc_random) << "Object create failed").raise(); + + if (storeObject(tdbb, id, val)) + return val; + + E::destroy(val); + } +#ifdef DEV_BUILD + (Firebird::Arg::Gds(isc_random) << "Object suddenly disappeared").raise(); +#endif + } + + StoredObject* storeObject(thread_db* tdbb, MetaId id, E* const val) + { + if (id >= getCount()) + grow(id + 1); + + auto ptr = getDataPointer(id); + fb_assert(ptr); + + HazardPtr data(*ptr); + if (!data) + { + MemoryPool* pool = tdbb->getDatabase()->dbb_permanent; + fb_assert(pool); + StoredObject* newData = FB_NEW_POOL(*pool) StoredObject(id); + if (!data.replace2(*ptr, newData)) + delete newData; + else + data.set(*ptr); + } + + if (!data->storeObject(tdbb, val)) + data.clear(); + return data.getPointer(); + } + + StoredObject* lookup(thread_db* tdbb, std::function cmp, MetaId* foundId = nullptr) const + { + auto a = m_objects.readAccessor(); + for (FB_SIZE_T i = 0; i < a->getCount(); ++i) + { + SubArrayData* const sub = a->value(i).load(atomics::memory_order_relaxed); + if (!sub) + continue; + + for (SubArrayData* end = &sub[SUBARRAY_SIZE]; sub < end--;) + { + StoredObject* ptr = end->load(atomics::memory_order_relaxed); + if (!ptr) + continue; + + E* val = ptr->getObject(tdbb); + if (val && cmp(val)) + { + if (foundId) + *foundId = (i << SUBARRAY_SHIFT) + (end - sub); + return ptr; + } + } + } + + return nullptr; + } + + ~CacheVector() + { + auto a = m_objects.writeAccessor(); + for (FB_SIZE_T i = 0; i < a->getCount(); ++i) + { + SubArrayData* const sub = a->value(i).load(atomics::memory_order_relaxed); + if (!sub) + continue; + + for (SubArrayData* end = &sub[SUBARRAY_SIZE]; sub < end--;) + delete *end; // no need using release here in CacheVector's dtor + + delete[] sub; + } + + delete a; + } + + FB_SIZE_T getCount() const + { + return m_objects.readAccessor()->getCount() << SUBARRAY_SHIFT; + } + + bool replace2(MetaId id, HazardPtr& oldVal, E* const newVal) + { + if (id >= getCount()) + grow(id + 1); + + auto a = m_objects.readAccessor(); + SubArrayData* sub = a->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire); + fb_assert(sub); + sub = &sub[id & SUBARRAY_MASK]; + + return oldVal.replace2(sub, newVal); + } + + bool clear(MetaId id) + { + if (id >= getCount()) + return false; + + auto a = m_objects.readAccessor(); + SubArrayData* sub = a->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire); + fb_assert(sub); + sub = &sub[id & SUBARRAY_MASK]; + + sub->store(nullptr, atomics::memory_order_release); + return true; + } + + bool load(MetaId id, HazardPtr& val) const + { + auto a = m_objects.readAccessor(); + if (id < getCount(a)) + { + SubArrayData* sub = a->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire); + if (sub) + { + val.set(sub[id & SUBARRAY_MASK]); + if (val && val->hasData()) + return true; + } + } + + return false; + } + + HazardPtr load(MetaId id) const + { + HazardPtr val; + if (!load(id, val)) + val.clear(); + return val; + } + + HazardPtr readAccessor() const + { + return m_objects.readAccessor(); + } + + class Snapshot; + + class Iterator + { + public: + HazardPtr operator*() + { + return get(); + } + + HazardPtr operator->() + { + return get(); + } + + Iterator& operator++() + { + index = snap->locateData(index + 1); + return *this; + } + + bool operator==(const Iterator& itr) const + { + fb_assert(snap == itr.snap); + return index == itr.index; + } + + bool operator!=(const Iterator& itr) const + { + fb_assert(snap == itr.snap); + return index != itr.index; + } + + private: + void* operator new(size_t); + void* operator new[](size_t); + + public: + enum class Location {Begin, End}; + Iterator(const Snapshot* s, Location loc) + : snap(s), + index(loc == Location::Begin ? snap->locateData(0) : + snap->data->getCount() << SUBARRAY_SHIFT) + { } + + HazardPtr get() + { + HazardPtr rc; + if (!snap->load(index, rc)) + rc.clear(); + return rc; + } + + private: + const Snapshot* snap; + FB_SIZE_T index; + }; + + class Snapshot + { + private: + void* operator new(size_t); + void* operator new[](size_t); + + public: + Snapshot(const CacheVector* array) + : data(array->readAccessor()) + { } + + Iterator begin() const + { + return Iterator(this, Iterator::Location::Begin); + } + + Iterator end() const + { + return Iterator(this, Iterator::Location::End); + } + + FB_SIZE_T locateData(FB_SIZE_T index) const + { + for (FB_SIZE_T i = index >> SUBARRAY_SHIFT; i < data->getCount(); ++i, index = 0) + { + SubArrayData* const sub = data->value(i).load(atomics::memory_order_acquire); + if (!sub) + continue; + + for (FB_SIZE_T j = index & SUBARRAY_MASK; j < SUBARRAY_SIZE; ++j) + { + auto p = sub[j].load(atomics::memory_order_acquire); + if (p && p->hasData()) + return (i << SUBARRAY_SHIFT) + j; + } + } + return data->getCount() << SUBARRAY_SHIFT; + } + + bool load(MetaId id, HazardPtr& val) const + { + if (id < (data->getCount() << SUBARRAY_SHIFT)) + { + SubArrayData* sub = data->value(id >> SUBARRAY_SHIFT).load(atomics::memory_order_acquire); + if (sub) + { + val.set(sub[id & SUBARRAY_MASK]); + if (val && val->hasData()) + return true; + } + } + + return false; + } + + HazardPtr data; + }; + + Snapshot snapshot() const + { + return Snapshot(this); + } + +private: + Storage m_objects; + Firebird::Mutex objectsGrowMutex; +}; + + class MetadataCache : public Firebird::PermanentStorage { friend class CharSetContainer; - - // to be reworked to linked list of appr.library - template - class CacheList : public OBJ +/* + class ListNodeAllocator { public: - template - CacheList(Args ... args) : - OBJ(args), next(nullptr), lastPossible(0), flags(FL_UNCOMMITTED) - { } + typedef int value_type; - template - bool link(DDS* dds, std::atomic* to) - { - if (*to->load(std::memory_order_acquire)->flags & FL_UNCOMMITTED) - return false; - - do - { - HazardPtr current(dds, *to, FB_FUNCTION); - next = current; - } while (!current.replace(to, this)); - - return true; - } - - void commit(TraNumber cur) - { - fb_assert(flags & FL_UNCOMMITTED); - createdBy = cur; - flags &= ~FL_UNCOMMITTED; - } - - template - void rollback(DDS* dds, std::atomic* to) - { - fb_assert(flags & FL_UNCOMMITTED); - do - { - HazardPtr current(dds, *to, FB_FUNCTION); - } while (!current.replace(to, next)); - } - - static template - void clear(DDS* dds, std::atomic* headPtr, TraNumber oldestInteresting) - { - while (*headPtr) - { - if (*headPtr->createdBy < oldestInteresting) - { - CacheList* toDel = nullptr; - do - { - HazardPtr toDrop(dds, *headPtr, FB_FUNCTION); - toDel = toDrop.getPointer(); - } while (!toDrop.replace(*headPtr, nullptr)); - - delete toDel; - break; - } - - headPtr = &(headPtr->load()->next); - } - } - - private: - std::atomic next; - TraNumber createdBy; - unsigned flags; - - static unsigned FL_UNCOMMITTED = 0x01; - static unsigned FL_ERASED = 0x02; + T* allocate(std::size_t n); + void deallocate(T* p, std::size_t n); }; - class Generator : public CacheObject + struct MetaTraits : public cds::container::michael_list::traits { - public: - typedef MetaName Key; - - Generator(MetaName name) - : value(name) - { } - - Generator() - { } - - bool hasData() const - { - return value.hasData(); - } - - MetaName getKey() const - { - return value; - } - - void removeFromCache(thread_db* tdbb) override - { - delayedDelete(tdbb); - } - - const char* c_name() const override - { - return value.c_str(); - } - - public: - MetaName value; + typedef ListNodeAllocator allocator; }; + template + using MetaList = cds::container::MichaelList; +*/ public: MetadataCache(MemoryPool& pool) @@ -519,7 +937,6 @@ public: mdc_relations(getPool()), mdc_procedures(getPool()), mdc_functions(getPool()), - mdc_generators(getPool()), mdc_charsets(getPool()), mdc_charset_ids(getPool()) { @@ -529,6 +946,17 @@ public: ~MetadataCache(); +/* + // Objects are placed to this list after DROP OBJECT + // and wait for current OAT >= NEXT when DDL committed + atomics::atomic*> dropList; + { +public: + void drop( +}; ????????????????????? +*/ + + void releaseIntlObjects(thread_db* tdbb); // defined in intl.cpp void destroyIntlObjects(thread_db* tdbb); // defined in intl.cpp @@ -537,94 +965,54 @@ public: void releaseGTTs(thread_db* tdbb); void runDBTriggers(thread_db* tdbb, TriggerAction action); void invalidateReplSet(thread_db* tdbb); - HazardPtr lookupFunction(thread_db* tdbb, const QualifiedName& name, USHORT setBits, USHORT clearBits); - HazardPtr getRelation(thread_db* tdbb, ULONG rel_id); - HazardPtr getRelation(Attachment* att, ULONG rel_id); + Function* lookupFunction(thread_db* tdbb, const QualifiedName& name, USHORT setBits, USHORT clearBits); + jrd_rel* getRelation(thread_db* tdbb, ULONG rel_id); void setRelation(thread_db* tdbb, ULONG rel_id, jrd_rel* rel); void releaseTrigger(thread_db* tdbb, USHORT triggerId, const MetaName& name); TrigVectorPtr* getTriggers(USHORT triggerId); - template - USHORT relCount(DDS* par) + MetaId relCount() { - return mdc_relations.getCount(par); + return mdc_relations.getCount(); } - HazardPtr getFunction(thread_db* tdbb, USHORT id, bool grow = false) + Function* getFunction(thread_db* tdbb, MetaId id, bool noscan) { - HazardPtr rc(tdbb, FB_FUNCTION); + if (id >= mdc_functions.getCount()) + return nullptr; - if (id >= mdc_functions.getCount(tdbb)) - { - if (grow) - mdc_functions.grow(tdbb, id + 1); - } - else - mdc_functions.load(tdbb, id, rc); - - return rc; + return mdc_functions.getObject(tdbb, id, CacheFlag::AUTOCREATE | (noscan ? CacheFlag::NOSCAN : 0)); } - HazardPtr setFunction(thread_db* tdbb, USHORT id, Function* f) + bool makeFunction(thread_db* tdbb, MetaId id, Function* f) { - return mdc_functions.store(tdbb, id, f); + return mdc_functions.storeObject(tdbb, id, f); } - HazardPtr getProcedure(thread_db* tdbb, USHORT id, bool grow = false) + jrd_prc* getProcedure(thread_db* tdbb, MetaId id, bool grow = false) { - HazardPtr rc(tdbb, FB_FUNCTION); + if (id >= mdc_procedures.getCount() && !grow) + return nullptr; - if (id >= mdc_procedures.getCount(tdbb)) - { - if (grow) - mdc_procedures.grow(tdbb, id + 1); - } - else - mdc_procedures.load(tdbb, id, rc); - - return rc; + return mdc_procedures.getObject(tdbb, id, CacheFlag::AUTOCREATE); } - void setProcedure(thread_db* tdbb, USHORT id, jrd_prc* p) + bool makeProcedure(thread_db* tdbb, MetaId id, jrd_prc* p) { - mdc_procedures.store(tdbb, id, p); + return mdc_procedures.storeObject(tdbb, id, p); } - SLONG lookupSequence(thread_db* tdbb, const MetaName& name) + CharSetContainer* getCharSet(thread_db* tdbb, MetaId id) { - return mdc_generators.lookup(tdbb, name); + if (id >= mdc_charsets.getCount()) + return nullptr; + + return mdc_charsets.getObject(tdbb, id, 0); } - bool getSequence(thread_db* tdbb, SLONG id, MetaName& name) + bool makeCharSet(thread_db* tdbb, MetaId id, CharSetContainer* cs) { - HazardPtr hp(tdbb, FB_FUNCTION); - - if (!mdc_generators.load(tdbb, id, hp)) - return false; - - name = hp->value; - return true; - } - - void setSequence(thread_db* tdbb, SLONG id, MetaName name) - { - Generator* genObj = FB_NEW_POOL(getPool()) Generator(name); - mdc_generators.store(tdbb, id, genObj); - } - - HazardPtr getCharSet(thread_db* tdbb, USHORT id) - { - HazardPtr rc(FB_FUNCTION); - mdc_charsets.load(tdbb, id, rc); - return rc; - } - - void setCharSet(thread_db* tdbb, USHORT id, CharSetContainer* cs) - { - if (id >= mdc_charsets.getCount(tdbb)) - mdc_charsets.grow(tdbb, id + 10); - - mdc_charsets.store(tdbb, id, cs); + return mdc_charsets.storeObject(tdbb, id, cs); } // former met_proto.h @@ -638,18 +1026,22 @@ public: static bool routine_in_use(thread_db* tdbb, HazardPtr routine); void load_db_triggers(thread_db* tdbb, int type); void load_ddl_triggers(thread_db* tdbb); - static HazardPtr lookup_procedure(thread_db* tdbb, const QualifiedName& name, bool noscan); - static HazardPtr lookup_procedure_id(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags); - static HazardPtr lookup_relation(thread_db*, const MetaName&); - static HazardPtr lookup_relation_id(thread_db*, SLONG, bool); + static jrd_prc* lookup_procedure(thread_db* tdbb, const QualifiedName& name, bool noscan); + static jrd_prc* lookup_procedure_id(thread_db* tdbb, MetaId id, bool return_deleted, bool noscan, USHORT flags); + static CacheElement* lookupProcedure(thread_db* tdbb, const MetaName& name); + static CacheElement* lookupProcedure(thread_db* tdbb, MetaId id, bool noscan = false); + static jrd_rel* lookup_relation(thread_db*, const MetaName&); + static jrd_rel* lookup_relation_id(thread_db*, MetaId, bool); + static CacheElement* lookupRelation(thread_db* tdbb, const MetaName& name); + static CacheElement* lookupRelation(thread_db* tdbb, MetaId id, bool noscan = false); static void lookup_index(thread_db* tdbb, MetaName& index_name, const MetaName& relation_name, USHORT number); - static SLONG lookup_index_name(thread_db* tdbb, const MetaName& index_name, - SLONG* relation_id, IndexStatus* status); + static ObjectBase::ReturnedId lookup_index_name(thread_db* tdbb, const MetaName& index_name, + MetaId* relation_id, IndexStatus* status); static void post_existence(thread_db* tdbb, jrd_rel* relation); - static HazardPtr findProcedure(thread_db* tdbb, USHORT id, bool noscan, USHORT flags); - static HazardPtr findRelation(thread_db* tdbb, USHORT id); - static bool get_char_coll_subtype(thread_db* tdbb, USHORT* id, const UCHAR* name, USHORT length); - bool resolve_charset_and_collation(thread_db* tdbb, USHORT* id, + static HazardPtr findProcedure(thread_db* tdbb, MetaId id, bool noscan, USHORT flags); + static jrd_rel* findRelation(thread_db* tdbb, MetaId id); + static bool get_char_coll_subtype(thread_db* tdbb, MetaId* id, const UCHAR* name, USHORT length); + bool resolve_charset_and_collation(thread_db* tdbb, MetaId* id, const UCHAR* charset, const UCHAR* collation); static DSqlCacheItem* get_dsql_cache_item(thread_db* tdbb, sym_type type, const QualifiedName& name); static void dsql_cache_release(thread_db* tdbb, sym_type type, const MetaName& name, const MetaName& package = ""); @@ -658,22 +1050,17 @@ public: static bool checkRelation(thread_db* tdbb, jrd_rel* relation); private: -// static void inc_int_use_count(Statement* statement); -// static void inc_int_use_count(TrigVector* vector); - - HazardArray mdc_relations; - HazardArray mdc_procedures; + CacheVector mdc_relations; + CacheVector mdc_procedures; TrigVectorPtr mdc_triggers[DB_TRIGGER_MAX]; TrigVectorPtr mdc_ddl_triggers; - HazardArray mdc_functions; // User defined functions - HazardArray mdc_generators; - HazardArray mdc_charsets; // intl character set descriptions + CacheVector mdc_functions; // User defined functions + CacheVector mdc_charsets; // intl character set descriptions Firebird::GenericMap > > mdc_charset_ids; // Character set ids public: Firebird::Mutex mdc_db_triggers_mutex, // Also used for load DDL triggers - mdc_use_mutex, // Everything related with use counters mdc_charset_mutex; // Protects mdc_charset_ids }; diff --git a/src/jrd/met_proto.h b/src/jrd/met_proto.h index 86cd23191a..d923e515c7 100644 --- a/src/jrd/met_proto.h +++ b/src/jrd/met_proto.h @@ -74,17 +74,16 @@ void MET_delete_shadow(Jrd::thread_db*, USHORT); void MET_error(const TEXT*, ...); Jrd::Format* MET_format(Jrd::thread_db*, Jrd::jrd_rel*, USHORT); bool MET_get_char_coll_subtype_info(Jrd::thread_db*, USHORT, SubtypeInfo* info); -Jrd::DmlNode* MET_get_dependencies(Jrd::thread_db*, Jrd::HazardPtr&, const UCHAR*, const ULONG, +Jrd::DmlNode* MET_get_dependencies(Jrd::thread_db*, Jrd::jrd_rel*, const UCHAR*, const ULONG, Jrd::CompilerScratch*, Jrd::bid*, Jrd::Statement**, Jrd::CompilerScratch**, const Jrd::MetaName&, int, USHORT, Jrd::jrd_tra*, const Jrd::MetaName& = Jrd::MetaName()); -Jrd::jrd_fld* MET_get_field(const Jrd::HazardPtr&, USHORT); Jrd::jrd_fld* MET_get_field(const Jrd::jrd_rel*, USHORT); ULONG MET_get_rel_flags_from_TYPE(USHORT); bool MET_get_repl_state(Jrd::thread_db*, const Jrd::MetaName&); void MET_get_shadow_files(Jrd::thread_db*, bool); bool MET_load_exception(Jrd::thread_db*, Jrd::ExceptionItem&); -void MET_load_trigger(Jrd::thread_db*, Jrd::HazardPtr&, const Jrd::MetaName&, Jrd::TrigVectorPtr*); +void MET_load_trigger(Jrd::thread_db*, Jrd::jrd_rel*, const Jrd::MetaName&, Jrd::TrigVectorPtr*); void MET_lookup_cnstrt_for_index(Jrd::thread_db*, Jrd::MetaName& constraint, const Jrd::MetaName& index_name); void MET_lookup_cnstrt_for_trigger(Jrd::thread_db*, Jrd::MetaName&, Jrd::MetaName&, const Jrd::MetaName&); void MET_lookup_exception(Jrd::thread_db*, SLONG, /* OUT */ Jrd::MetaName&, /* OUT */ Firebird::string*); @@ -96,9 +95,9 @@ bool MET_lookup_generator_id(Jrd::thread_db*, SLONG, Jrd::MetaName&, bool* sysG void MET_update_generator_increment(Jrd::thread_db* tdbb, SLONG gen_id, SLONG step); void MET_lookup_index_expression(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*); bool MET_lookup_partner(Jrd::thread_db* tdbb, Jrd::jrd_rel* relation, Jrd::index_desc* idx, const TEXT* index_name); -Jrd::DmlNode* MET_parse_blob(Jrd::thread_db*, Jrd::HazardPtr&, Jrd::bid*, Jrd::CompilerScratch**, +Jrd::DmlNode* MET_parse_blob(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::bid*, Jrd::CompilerScratch**, Jrd::Statement**, bool, bool); -void MET_parse_sys_trigger(Jrd::thread_db*, Jrd::HazardPtr&); +void MET_parse_sys_trigger(Jrd::thread_db*, Jrd::jrd_rel*); void MET_prepare(Jrd::thread_db*, Jrd::jrd_tra*, USHORT, const UCHAR*); void MET_release_existence(Jrd::thread_db*, Jrd::jrd_rel*); void MET_release_trigger(Jrd::thread_db*, Jrd::TrigVectorPtr*, const Jrd::MetaName&); @@ -106,8 +105,7 @@ void MET_release_triggers(Jrd::thread_db*, Jrd::TrigVectorPtr*, bool); void MET_revoke(Jrd::thread_db*, Jrd::jrd_tra*, const Jrd::MetaName&, const Jrd::MetaName&, const Firebird::string&); void MET_scan_partners(Jrd::thread_db*, Jrd::jrd_rel*); -Jrd::HazardPtr MET_scan_relation(Jrd::thread_db*, USHORT); -void MET_scan_relation(Jrd::thread_db*, Jrd::HazardPtr&); +void MET_scan_relation(Jrd::thread_db*, Jrd::jrd_rel*&); void MET_trigger_msg(Jrd::thread_db*, Firebird::string&, const Jrd::MetaName&, USHORT); void MET_update_shadow(Jrd::thread_db*, Jrd::Shadow*, USHORT); void MET_update_transaction(Jrd::thread_db*, Jrd::jrd_tra*, const bool); diff --git a/src/jrd/pag.cpp b/src/jrd/pag.cpp index da7bdaf5fa..4cd74e4d0f 100644 --- a/src/jrd/pag.cpp +++ b/src/jrd/pag.cpp @@ -1122,7 +1122,7 @@ void PAG_header(thread_db* tdbb, bool info) if (header->hdr_flags & hdr_SQL_dialect_3) dbb->dbb_flags |= DBB_DB_SQL_dialect_3; - HazardPtr relation = MetadataCache::findRelation(tdbb, 0); + jrd_rel* relation = MetadataCache::findRelation(tdbb, 0); RelationPages* relPages = relation->getBasePages(); if (!relPages->rel_pages) { diff --git a/src/jrd/par.cpp b/src/jrd/par.cpp index 861a1012d3..96b6061591 100644 --- a/src/jrd/par.cpp +++ b/src/jrd/par.cpp @@ -89,7 +89,7 @@ namespace class BlrParseWrapper { public: - BlrParseWrapper(thread_db* tdbb, MemoryPool& pool, HazardPtr& relation, CompilerScratch* view_csb, + BlrParseWrapper(thread_db* tdbb, MemoryPool& pool, jrd_rel* relation, CompilerScratch* view_csb, CompilerScratch** csb_ptr, const bool trigger, USHORT flags) : m_csbPtr(csb_ptr) { @@ -171,7 +171,7 @@ namespace // Parse blr, returning a compiler scratch block with the results. // Caller must do pool handling. -DmlNode* PAR_blr(thread_db* tdbb, HazardPtr& relation, const UCHAR* blr, ULONG blr_length, +DmlNode* PAR_blr(thread_db* tdbb, jrd_rel* relation, const UCHAR* blr, ULONG blr_length, CompilerScratch* view_csb, CompilerScratch** csb_ptr, Statement** statementPtr, const bool trigger, USHORT flags) { @@ -204,7 +204,7 @@ DmlNode* PAR_blr(thread_db* tdbb, HazardPtr& relation, const UCHAR* blr // Finish parse of memory nodes, returning a compiler scratch block with the results. // Caller must do pool handling. // !!!!!!!!!!!!!!! FixMe - pool handling in ExtEngineManager.cpp -void PAR_preparsed_node(thread_db* tdbb, HazardPtr& relation, DmlNode* node, +void PAR_preparsed_node(thread_db* tdbb, jrd_rel* relation, DmlNode* node, CompilerScratch* view_csb, CompilerScratch** csb_ptr, Statement** statementPtr, const bool trigger, USHORT flags) { @@ -220,7 +220,7 @@ void PAR_preparsed_node(thread_db* tdbb, HazardPtr& relation, DmlNode* // PAR_blr equivalent for validation expressions. // Validation expressions are boolean expressions, but may be prefixed with a blr_stmt_expr. -BoolExprNode* PAR_validation_blr(thread_db* tdbb, HazardPtr& relation, const UCHAR* blr, ULONG blr_length, +BoolExprNode* PAR_validation_blr(thread_db* tdbb, jrd_rel* relation, const UCHAR* blr, ULONG blr_length, CompilerScratch* view_csb, CompilerScratch** csb_ptr, USHORT flags) { SET_TDBB(tdbb); @@ -545,7 +545,7 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item if (csb->collectingDependencies()) { CompilerScratch::Dependency dependency(obj_relation); - HazardPtr rel = MetadataCache::lookup_relation(tdbb, *relationName); + jrd_rel* rel = MetadataCache::lookup_relation(tdbb, *relationName); dependency.relation = csb->csb_resources.registerResource(tdbb, Resource::rsc_relation, rel, rel->rel_id); dependency.subName = fieldName; csb->addDependency(dependency); diff --git a/src/jrd/par_proto.h b/src/jrd/par_proto.h index 8e83bdbe9d..77ea5dd2a0 100644 --- a/src/jrd/par_proto.h +++ b/src/jrd/par_proto.h @@ -45,11 +45,11 @@ struct dsc; Jrd::ValueListNode* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT, USHORT); Jrd::ValueListNode* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*); -Jrd::DmlNode* PAR_blr(Jrd::thread_db*, Jrd::HazardPtr&, const UCHAR*, ULONG blr_length, +Jrd::DmlNode* PAR_blr(Jrd::thread_db*, Jrd::jrd_rel*, const UCHAR*, ULONG blr_length, Jrd::CompilerScratch*, Jrd::CompilerScratch**, Jrd::Statement**, const bool, USHORT); -void PAR_preparsed_node(Jrd::thread_db*, Jrd::HazardPtr&, Jrd::DmlNode*, +void PAR_preparsed_node(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::DmlNode*, Jrd::CompilerScratch*, Jrd::CompilerScratch**, Jrd::Statement**, const bool, USHORT); -Jrd::BoolExprNode* PAR_validation_blr(Jrd::thread_db*, Jrd::HazardPtr&, const UCHAR* blr, +Jrd::BoolExprNode* PAR_validation_blr(Jrd::thread_db*, Jrd::jrd_rel*, const UCHAR* blr, ULONG blr_length, Jrd::CompilerScratch*, Jrd::CompilerScratch**, USHORT); StreamType PAR_context(Jrd::CompilerScratch*, SSHORT*); void PAR_dependency(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, StreamType stream, diff --git a/src/jrd/req.h b/src/jrd/req.h index 35d03b1314..07d742c718 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -161,6 +161,39 @@ private: int modifiedRows; }; + +// Set of objects cached per particular MDC version + +class CacheObject; + +class VersionedObjects : public pool_alloc_rpt, + public Firebird::RefCounted +{ +public: + VersionedObjects(FB_SIZE_T cnt, MdcVersion ver); + + FB_SIZE_T push(CacheObject* obj); + + template + OBJ* get(FB_SIZE_T n) + { + fb_assert(count == capacity); + fb_assert(n < count); +// ????? fb_assert(dynamic_cast(data[n])); + return reinterpret_cast(data[n]); + } + + MdcVersion version; // version when created + +private: + FB_SIZE_T count; +#ifdef DEV_BUILD + FB_SIZE_T capacity; +#endif + CacheObject* data[1]; +}; + + // request block class Request : public pool_alloc @@ -302,31 +335,7 @@ private: }; public: - Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement) - : statement(aStatement), - req_pool(pool), - req_memory_stats(&aStatement->pool->getStatsGroup()), - req_blobs(req_pool), - req_stats(*req_pool), - req_base_stats(*req_pool), - req_ext_stmt(NULL), - req_cursors(*req_pool), - req_ext_resultset(NULL), - req_timeout(0), - req_domain_validation(NULL), - req_auto_trans(*req_pool), - req_sorts(*req_pool), - req_rpb(*req_pool), - impureArea(*req_pool) - { - fb_assert(statement); - setAttachment(attachment); - req_rpb = statement->rpbsSetup; - impureArea.grow(statement->impureSize); - - pool->setStatsGroup(req_memory_stats); - pool.release(); - } + Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement); Statement* getStatement() { @@ -345,7 +354,6 @@ public: void setAttachment(Attachment* newAttachment) { req_attachment = newAttachment; - charSetId = hasInternalStatement() ? CS_METADATA : req_attachment->att_charset; } bool isRoot() const; @@ -362,6 +370,9 @@ public: req_id = id; } + void setUsed(bool inUse); + bool isUsed(); + private: Statement* const statement; mutable StmtNumber req_id; // request identifier @@ -505,6 +516,9 @@ public: { req_timeStampCache.validate(req_attachment->att_current_timezone); } + +private: + Firebird::RefPtr currentVersion; }; // Flags for req_flags @@ -515,7 +529,7 @@ const ULONG req_null = 0x8L; const ULONG req_abort = 0x10L; const ULONG req_error_handler = 0x20L; // looper is called to handle error const ULONG req_warning = 0x40L; -const ULONG req_in_use = 0x80L; +//const ULONG req_in_use = 0x80L; const ULONG req_continue_loop = 0x100L; // PSQL continue statement const ULONG req_proc_fetch = 0x200L; // Fetch from procedure in progress const ULONG req_same_tx_upd = 0x400L; // record was updated by same transaction diff --git a/src/jrd/scl.epp b/src/jrd/scl.epp index 05c795eb76..91eade2c54 100644 --- a/src/jrd/scl.epp +++ b/src/jrd/scl.epp @@ -907,7 +907,7 @@ SecurityClass::flags_t SCL_get_mask(thread_db* tdbb, const TEXT* relation_name, SecurityClass::flags_t access = ~0; // If there's a relation, track it down - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation; if (relation_name && (relation = MetadataCache::lookup_relation(tdbb, relation_name))) { MET_scan_relation(tdbb, relation); diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index e677122b9c..eb636595fe 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -94,7 +94,7 @@ static TraNumber bump_transaction_id(thread_db*, WIN*); static header_page* bump_transaction_id(thread_db*, WIN*, bool); #endif static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, int state); -static void expand_view_lock(thread_db* tdbb, jrd_tra*, HazardPtr&, UCHAR lock_type, +static void expand_view_lock(thread_db* tdbb, jrd_tra*, jrd_rel*, UCHAR lock_type, const char* option_name, RelationLockTypeMap& lockmap, const int level); static tx_inv_page* fetch_inventory_page(thread_db*, WIN* window, ULONG sequence, USHORT lock_level); static const char* get_lockname_v3(const UCHAR lock); @@ -963,8 +963,8 @@ void TRA_post_resources(thread_db* tdbb, jrd_tra* transaction, ResourceList& res * This guarantees that the relation/procedure/collation won't be dropped * out from under the transaction. * - **************************************/ - SET_TDBB(tdbb); + ************************************** + SET_TDBB(tdbb); !!!!!!!!!!!!!!!!!!!!! Jrd::ContextPoolHolder context(tdbb, transaction->tra_pool); @@ -978,6 +978,9 @@ void TRA_post_resources(thread_db* tdbb, jrd_tra* transaction, ResourceList& res if (!newRsc.hasData()) return; + */ + + // !!!!!!!!!!!!! solve EXT_tra_attach problem - where to place references MutexLockGuard g(tdbb->getDatabase()->dbb_mdc->mdc_use_mutex, FB_FUNCTION); @@ -1253,6 +1256,9 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr } // Care about used external files + + // !!!!!!!!!!!!! solve EXT_tra_attach problem - where to place references +/* for (auto rsc : transaction->tra_resources.getObjects(Resource::rsc_relation)) { if (rsc->rsc_state == Resource::State::Extra) @@ -1262,7 +1268,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr rsc->rsc_state = Resource::State::Locked; } } - + */ // Release interest in relation/procedure existence for transaction transaction->tra_resources.releaseResources(tdbb, transaction); @@ -2150,7 +2156,7 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window, bool dontW #endif -static void expand_view_lock(thread_db* tdbb, jrd_tra* transaction, HazardPtr& relation, +static void expand_view_lock(thread_db* tdbb, jrd_tra* transaction, jrd_rel* relation, UCHAR lock_type, const char* option_name, RelationLockTypeMap& lockmap, const int level) { /************************************** @@ -2261,7 +2267,7 @@ static void expand_view_lock(thread_db* tdbb, jrd_tra* transaction, HazardPtrvcx_type == VCT_PROCEDURE) continue; - HazardPtr base_rel = MetadataCache::lookup_relation(tdbb, ctx[i]->vcx_relation_name); + jrd_rel* base_rel = MetadataCache::lookup_relation(tdbb, ctx[i]->vcx_relation_name); if (!base_rel) { // should be a BUGCHECK @@ -2484,7 +2490,7 @@ static void release_temp_tables(thread_db* tdbb, jrd_tra* transaction) for (FB_SIZE_T i = 0; i < mdc->relCount(tdbb); i++) { - HazardPtr relation = mdc->getRelation(tdbb, i); + jrd_rel* relation = mdc->getRelation(tdbb, i); if (relation && (relation->rel_flags & REL_temp_tran)) relation->delPages(tdbb, transaction->tra_number); @@ -2509,7 +2515,7 @@ static void retain_temp_tables(thread_db* tdbb, jrd_tra* transaction, TraNumber for (FB_SIZE_T i = 0; i < mdc->relCount(tdbb); i++) { - HazardPtr relation = mdc->getRelation(tdbb, i); + jrd_rel* relation = mdc->getRelation(tdbb, i); if (relation && (relation->rel_flags & REL_temp_tran)) relation->retainPages(tdbb, transaction->tra_number, new_number); @@ -3188,7 +3194,7 @@ static void transaction_options(thread_db* tdbb, const MetaName metaName = attachment->nameToMetaCharSet(tdbb, orgName); tpb += len; - HazardPtr relation = MetadataCache::lookup_relation(tdbb, metaName); + jrd_rel* relation = MetadataCache::lookup_relation(tdbb, metaName); if (!relation) { ERR_post(Arg::Gds(isc_bad_tpb_content) << @@ -3781,7 +3787,7 @@ jrd_tra::~jrd_tra() delete tra_sec_db_context; - tra_resources.releaseResources(nullptr, this); +// !!!!!!!!!!!!!!!!!!!! tra_resources.releaseResources(nullptr, this); } @@ -4053,7 +4059,7 @@ void jrd_tra::checkBlob(thread_db* tdbb, const bid* blob_id, jrd_fld* fld, bool !tra_fetched_blobs.locate(*blob_id)) { MetadataCache* mdc = tra_attachment->att_database->dbb_mdc; - HazardPtr blobRelation = mdc->getRelation(tdbb, rel_id); + jrd_rel* blobRelation = mdc->getRelation(tdbb, rel_id); if (blobRelation) { @@ -4176,7 +4182,7 @@ TraceSweepEvent::~TraceSweepEvent() } -void TraceSweepEvent::beginSweepRelation(const HazardPtr& relation) +void TraceSweepEvent::beginSweepRelation(const jrd_rel* relation) { if (!m_need_trace) return; diff --git a/src/jrd/tra.h b/src/jrd/tra.h index fd250ada13..44733dc57c 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -178,7 +178,7 @@ public: tra_blob_util_map(*p), tra_arrays(NULL), tra_deferred_job(NULL), - tra_resources(*p, false), +// tra_resources(*p, false), tra_context_vars(*p), tra_lock_timeout(DEFAULT_LOCK_TIMEOUT), tra_timestamp(Firebird::TimeZoneUtil::getCurrentSystemTimeStamp()), @@ -282,7 +282,7 @@ public: SavNumber tra_save_point_number; // next save point number to use ULONG tra_flags; DeferredJob* tra_deferred_job; // work deferred to commit time - ResourceList tra_resources; // resource existence list +// ResourceList tra_resources; // resource existence list Firebird::StringMap tra_context_vars; // Context variables for the transaction traRpbList* tra_rpblist; // active record_param's of given transaction UCHAR tra_use_count; // use count for safe AST delivery diff --git a/src/jrd/tra_proto.h b/src/jrd/tra_proto.h index 3c2d4b0ebb..f5f13fcbb2 100644 --- a/src/jrd/tra_proto.h +++ b/src/jrd/tra_proto.h @@ -30,6 +30,8 @@ namespace Jrd { class Attachment; class Database; class TraceTransactionEnd; + + class ResourceList; } bool TRA_active_transactions(Jrd::thread_db* tdbb, Jrd::Database*); @@ -47,7 +49,9 @@ void TRA_init(Jrd::Attachment*); void TRA_invalidate(Jrd::thread_db* tdbb, ULONG); void TRA_link_cursor(Jrd::jrd_tra*, Jrd::DsqlCursor*); void TRA_unlink_cursor(Jrd::jrd_tra*, Jrd::DsqlCursor*); + void TRA_post_resources(Jrd::thread_db* tdbb, Jrd::jrd_tra*, Jrd::ResourceList&); + bool TRA_is_active(Jrd::thread_db*, TraNumber); void TRA_prepare(Jrd::thread_db* tdbb, Jrd::jrd_tra*, USHORT, const UCHAR*); Jrd::jrd_tra* TRA_reconnect(Jrd::thread_db* tdbb, const UCHAR*, USHORT); diff --git a/src/jrd/trace/TraceJrdHelpers.h b/src/jrd/trace/TraceJrdHelpers.h index df9d351daf..a29c63f9f4 100644 --- a/src/jrd/trace/TraceJrdHelpers.h +++ b/src/jrd/trace/TraceJrdHelpers.h @@ -507,7 +507,7 @@ public: m_sweep_info.update(header); } - void beginSweepRelation(const HazardPtr& relation); + void beginSweepRelation(const jrd_rel* relation); void endSweepRelation(); void finish() diff --git a/src/jrd/validation.cpp b/src/jrd/validation.cpp index 6fa35524ec..de81e3da90 100644 --- a/src/jrd/validation.cpp +++ b/src/jrd/validation.cpp @@ -1629,13 +1629,13 @@ void Validation::walk_database() } MetadataCache* mdc = dbb->dbb_mdc; - for (USHORT i = 0; i < mdc->relCount(&dbb->dbb_delayed_delete); i++) + for (USHORT i = 0; i < mdc->relCount(); i++) { #ifdef DEBUG_VAL_VERBOSE if (i > dbb->dbb_max_sys_rel) // Why not system flag instead? VAL_debug_level = 2; #endif - HazardPtr relation = mdc->getRelation(vdr_tdbb, i); + jrd_rel* relation = mdc->getRelation(vdr_tdbb, i); ExistenceGuard g(vdr_tdbb, relation->rel_existence_lock); if (MetadataCache::checkRelation(vdr_tdbb, relation.getPointer())) @@ -3005,7 +3005,7 @@ void Validation::checkDPinPIP(jrd_rel* relation, ULONG page_number) release_page(&pip_window); } -Validation::RTN Validation::walk_relation(HazardPtr& rel) +Validation::RTN Validation::walk_relation(jrd_rel* rel) { /************************************** * diff --git a/src/jrd/validation.h b/src/jrd/validation.h index 6c9c3f077e..19ab8e4c53 100644 --- a/src/jrd/validation.h +++ b/src/jrd/validation.h @@ -218,7 +218,7 @@ private: void walk_pip(); RTN walk_pointer_page(jrd_rel*, ULONG); RTN walk_record(jrd_rel*, const Ods::rhd*, USHORT, RecordNumber, bool); - RTN walk_relation(HazardPtr&); + RTN walk_relation(jrd_rel*); RTN walk_root(jrd_rel*, bool); RTN walk_scns(); RTN walk_tip(TraNumber); diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 45ef553405..636b0a76c8 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -2002,8 +2002,8 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) if (needDfw(tdbb, transaction)) { - HazardPtr r2(FB_FUNCTION); - HazardPtr procedure(FB_FUNCTION); + jrd_rel* r2; + HazardPtr procedure; USHORT id; DeferredWork* work; @@ -2060,7 +2060,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) } EVL_field(0, rpb->rpb_record, f_rel_name, &desc); DFW_post_work(transaction, dfw_delete_relation, &desc, id); - HazardPtr rel_drop = MetadataCache::lookup_relation_id(tdbb, id, false); + jrd_rel* rel_drop = MetadataCache::lookup_relation_id(tdbb, id, false); if (rel_drop) MET_scan_relation(tdbb, rel_drop); } @@ -2149,7 +2149,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction) MetaName index_name; MOV_get_metaname(tdbb, &desc3, index_name); - HazardPtr partner(FB_FUNCTION); + jrd_rel* partner; index_desc idx; if ((BTR_lookup(tdbb, r2.getPointer(), id - 1, &idx, r2->getBasePages())) && @@ -4367,7 +4367,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee // hvlad: restore tdbb->transaction since it can be used later tdbb->setTransaction(transaction); - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation; record_param rpb; rpb.rpb_record = NULL; @@ -5251,7 +5251,7 @@ void Database::garbage_collector(Database* dbb) Jrd::Attachment::UseCountHolder use(attachment); tdbb->markAsSweeper(); - HazardPtr relation(FB_FUNCTION); + jrd_rel* relation; record_param rpb; rpb.getWindow(tdbb).win_flags = WIN_garbage_collector; rpb.rpb_stream_flags = RPB_s_no_data | RPB_s_sweeper;