8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 19:23:02 +01:00
This commit is contained in:
AlexPeshkoff 2023-07-14 19:20:56 +03:00
parent dae83f6815
commit 4215b9d220
60 changed files with 1518 additions and 1800 deletions

View File

@ -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 PLATFORM_PLUSPLUS_FLAGS=-Wno-invalid-offsetof -Wno-class-memaccess
PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS) PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS)
#DEV_FLAGS=-DUSE_VALGRIND $(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=8 DEV_FLAGS=$(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=2
# This file must be compiled with SSE4.2 support # This file must be compiled with SSE4.2 support
%/CRC32C.o: COMMON_FLAGS += -msse4 %/CRC32C.o: COMMON_FLAGS += -msse4

View File

@ -7,6 +7,23 @@
#define CLOOP_CARG #define CLOOP_CARG
#endif #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 namespace calc
{ {
@ -34,6 +51,8 @@ namespace calc
// Interfaces declarations // Interfaces declarations
#define CALC_IDISPOSABLE_VERSION 1u
class IDisposable class IDisposable
{ {
public: public:
@ -41,7 +60,7 @@ namespace calc
{ {
void* cloopDummy[1]; void* cloopDummy[1];
uintptr_t version; uintptr_t version;
void (CLOOP_CARG *dispose)(IDisposable* self) throw(); void (CLOOP_CARG *dispose)(IDisposable* self) CLOOP_NOEXCEPT;
}; };
void* cloopDummy[1]; void* cloopDummy[1];
@ -57,7 +76,7 @@ namespace calc
} }
public: public:
static const unsigned VERSION = 1; static CLOOP_CONSTEXPR unsigned VERSION = CALC_IDISPOSABLE_VERSION;
void dispose() void dispose()
{ {
@ -65,13 +84,15 @@ namespace calc
} }
}; };
#define CALC_ISTATUS_VERSION 2u
class IStatus : public IDisposable class IStatus : public IDisposable
{ {
public: public:
struct VTable : public IDisposable::VTable struct VTable : public IDisposable::VTable
{ {
int (CLOOP_CARG *getCode)(const IStatus* self) throw(); int (CLOOP_CARG *getCode)(const IStatus* self) CLOOP_NOEXCEPT;
void (CLOOP_CARG *setCode)(IStatus* self, int code) throw(); void (CLOOP_CARG *setCode)(IStatus* self, int code) CLOOP_NOEXCEPT;
}; };
protected: protected:
@ -85,11 +106,11 @@ namespace calc
} }
public: public:
static const unsigned VERSION = 2; static CLOOP_CONSTEXPR unsigned VERSION = CALC_ISTATUS_VERSION;
static const int ERROR_1 = 1; static CLOOP_CONSTEXPR int ERROR_1 = 1;
static const int ERROR_2 = 0x2; static CLOOP_CONSTEXPR int ERROR_2 = 0x2;
static const int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2; static CLOOP_CONSTEXPR int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2;
int getCode() const int getCode() const
{ {
@ -103,15 +124,17 @@ namespace calc
} }
}; };
#define CALC_IFACTORY_VERSION 2u
class IFactory : public IDisposable class IFactory : public IDisposable
{ {
public: public:
struct VTable : public IDisposable::VTable struct VTable : public IDisposable::VTable
{ {
IStatus* (CLOOP_CARG *createStatus)(IFactory* self) throw(); IStatus* (CLOOP_CARG *createStatus)(IFactory* self) CLOOP_NOEXCEPT;
ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) throw(); ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT;
ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) throw(); ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT;
ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) throw(); ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT;
}; };
protected: protected:
@ -125,7 +148,7 @@ namespace calc
} }
public: public:
static const unsigned VERSION = 2; static CLOOP_CONSTEXPR unsigned VERSION = CALC_IFACTORY_VERSION;
IStatus* createStatus() IStatus* createStatus()
{ {
@ -158,15 +181,17 @@ namespace calc
} }
}; };
#define CALC_ICALCULATOR_VERSION 4u
class ICalculator : public IDisposable class ICalculator : public IDisposable
{ {
public: public:
struct VTable : public IDisposable::VTable struct VTable : public IDisposable::VTable
{ {
int (CLOOP_CARG *sum)(const 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) throw(); int (CLOOP_CARG *getMemory)(const ICalculator* self) CLOOP_NOEXCEPT;
void (CLOOP_CARG *setMemory)(ICalculator* self, int n) throw(); void (CLOOP_CARG *setMemory)(ICalculator* self, int n) CLOOP_NOEXCEPT;
void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) throw(); void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT;
}; };
protected: protected:
@ -180,7 +205,7 @@ namespace calc
} }
public: public:
static const unsigned VERSION = 4; static CLOOP_CONSTEXPR unsigned VERSION = CALC_ICALCULATOR_VERSION;
template <typename StatusType> int sum(StatusType* status, int n1, int n2) const template <typename StatusType> int sum(StatusType* status, int n1, int n2) const
{ {
@ -223,14 +248,16 @@ namespace calc
} }
}; };
#define CALC_ICALCULATOR2_VERSION 6u
class ICalculator2 : public ICalculator class ICalculator2 : public ICalculator
{ {
public: public:
struct VTable : public ICalculator::VTable struct VTable : public ICalculator::VTable
{ {
int (CLOOP_CARG *multiply)(const ICalculator2* self, IStatus* status, int n1, int n2) 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) throw(); void (CLOOP_CARG *copyMemory)(ICalculator2* self, const ICalculator* calculator) CLOOP_NOEXCEPT;
void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) throw(); void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) CLOOP_NOEXCEPT;
}; };
protected: protected:
@ -244,7 +271,7 @@ namespace calc
} }
public: public:
static const unsigned VERSION = 6; static CLOOP_CONSTEXPR unsigned VERSION = CALC_ICALCULATOR2_VERSION;
template <typename StatusType> int multiply(StatusType* status, int n1, int n2) const template <typename StatusType> int multiply(StatusType* status, int n1, int n2) const
{ {
@ -291,7 +318,7 @@ namespace calc
this->cloopVTable = &vTable; this->cloopVTable = &vTable;
} }
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT
{ {
try try
{ {
@ -342,7 +369,7 @@ namespace calc
this->cloopVTable = &vTable; this->cloopVTable = &vTable;
} }
static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) throw() static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) CLOOP_NOEXCEPT
{ {
try 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 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 try
{ {
@ -421,7 +448,7 @@ namespace calc
this->cloopVTable = &vTable; this->cloopVTable = &vTable;
} }
static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) throw() static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) CLOOP_NOEXCEPT
{ {
try 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); 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); 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); 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 try
{ {
@ -535,7 +562,7 @@ namespace calc
this->cloopVTable = &vTable; 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); 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 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 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); 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 try
{ {
@ -648,7 +675,7 @@ namespace calc
this->cloopVTable = &vTable; 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); 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 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 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); 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 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 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); 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 try
{ {

View File

@ -12787,7 +12787,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
} }
} }
HazardPtr<Function> func(FB_FUNCTION); Function* func = nullptr;
if (!node->function) if (!node->function)
{ {
func = Function::lookup(tdbb, name, false); func = Function::lookup(tdbb, name, false);
@ -12917,7 +12917,7 @@ ValueExprNode* UdfCallNode::copy(thread_db* tdbb, NodeCopier& copier) const
node->function = function; node->function = function;
else else
{ {
HazardPtr<Function> 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()); node->function = copier.csb->csb_resources.registerResource(tdbb, Resource::rsc_function, func, func->getId());
} }
return node; return node;

View File

@ -30,12 +30,13 @@
namespace Jrd { namespace Jrd {
class Resources;
class NodePrinter class NodePrinter
{ {
public: public:
explicit NodePrinter(unsigned aIndent = 0) NodePrinter(const Resources* aResources, unsigned aIndent = 0)
: indent(aIndent) : indent(aIndent), resources(aResources)
{ {
} }
@ -337,6 +338,11 @@ private:
private: private:
unsigned indent; unsigned indent;
public:
const Resources* resources;
private:
Firebird::ObjectsArray<Firebird::string> stack; Firebird::ObjectsArray<Firebird::string> stack;
Firebird::string text; Firebird::string text;
}; };

View File

@ -2932,7 +2932,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
const auto blrStartPos = csb->csb_blr_reader.getPos(); const auto blrStartPos = csb->csb_blr_reader.getPos();
jrd_prc* procedure = NULL; jrd_prc* procedure = NULL;
HazardPtr<jrd_prc> proc(FB_FUNCTION); HazardPtr<jrd_prc> proc;
QualifiedName name; QualifiedName name;
if (blrOp == blr_exec_pid) 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++) for (FB_SIZE_T i = 0; i < trigger->getCount(tdbb); i++)
{ {
HazardPtr<Trigger> tr(FB_FUNCTION); HazardPtr<Trigger> tr;
if (!trigger->load(tdbb, i, tr)) if (!trigger->load(tdbb, i, tr))
continue; continue;
if (!tr->sysTrigger) if (!tr->sysTrigger)

View File

@ -150,13 +150,15 @@ inline T FB_ALIGN(T n, uintptr_t b)
return (T) ((((uintptr_t) n) + b - 1) & ~(b - 1)); 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 AttNumber;
typedef FB_UINT64 TraNumber; typedef FB_UINT64 TraNumber;
typedef FB_UINT64 StmtNumber; typedef FB_UINT64 StmtNumber;
typedef FB_UINT64 CommitNumber; typedef FB_UINT64 CommitNumber;
typedef ULONG SnapshotHandle; typedef ULONG SnapshotHandle;
typedef ULONG MdcVersion;
typedef USHORT MetaId;
typedef SINT64 SavNumber; typedef SINT64 SavNumber;
#endif /* INCLUDE_FB_TYPES_H */ #endif /* INCLUDE_FB_TYPES_H */

View File

@ -5312,6 +5312,7 @@ const
isc_invalid_blob_util_handle = 335545283; isc_invalid_blob_util_handle = 335545283;
isc_bad_temp_blob_id = 335545284; isc_bad_temp_blob_id = 335545284;
isc_ods_upgrade_err = 335545285; isc_ods_upgrade_err = 335545285;
isc_bad_par_workers = 335545286;
isc_gfix_db_name = 335740929; isc_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930; isc_gfix_invalid_sw = 335740930;
isc_gfix_incmp_sw = 335740932; isc_gfix_incmp_sw = 335740932;

View File

@ -138,10 +138,6 @@ void Jrd::Attachment::destroy(Attachment* const attachment)
jrd_tra::destroy(NULL, sysTransaction); 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; MemoryPool* const pool = attachment->att_pool;
@ -241,8 +237,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, JProvider* provider
att_stmt_timeout(0), att_stmt_timeout(0),
att_batches(*pool), att_batches(*pool),
att_initial_options(*pool), att_initial_options(*pool),
att_provider(provider), att_provider(provider)
att_delayed_delete(*dbb->dbb_permanent, *pool)
{ {
att_internal.grow(irq_MAX); att_internal.grow(irq_MAX);
att_dyn_req.grow(drq_MAX); att_dyn_req.grow(drq_MAX);

View File

@ -784,9 +784,6 @@ private:
Lock* att_repl_lock; // Replication set lock Lock* att_repl_lock; // Replication set lock
JProvider* att_provider; // Provider which created this attachment JProvider* att_provider; // Provider which created this attachment
public:
HazardDelayedDelete att_delayed_delete;
}; };

View File

@ -1130,12 +1130,16 @@ void Collation::release(thread_db* tdbb)
fb_assert(useCount >= 0); fb_assert(useCount >= 0);
if (existenceLock) if (existenceLock)
{
if (!tdbb)
tdbb = JRD_get_thread_data();
LCK_release(tdbb, existenceLock); LCK_release(tdbb, existenceLock);
}
useCount = 0; 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); fprintf(stderr, "Collation::destroy(%p) tt=%p\n", this, tt);
fb_assert(useCount == 0); fb_assert(useCount == 0);
@ -1150,8 +1154,8 @@ void Collation::destroy(thread_db* tdbb)
delete existenceLock; delete existenceLock;
existenceLock = NULL; existenceLock = NULL;
fprintf(stderr, "delayedDelete collation %p\n", this); fprintf(stderr, "retire collation %p\n", this);
this->delayedDelete(tdbb); //this->retire();
} }
void Collation::incUseCount(thread_db* /*tdbb*/) void Collation::incUseCount(thread_db* /*tdbb*/)

View File

@ -80,7 +80,7 @@ public:
virtual PatternMatcher* createContainsMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl) = 0; virtual PatternMatcher* createContainsMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl) = 0;
void release(thread_db* tdbb); void release(thread_db* tdbb);
void destroy(thread_db* tdbb); void destroy(thread_db* tdbb, int);
void incUseCount(thread_db* tdbb); void incUseCount(thread_db* tdbb);
void decUseCount(thread_db* tdbb); void decUseCount(thread_db* tdbb);
@ -89,11 +89,6 @@ public:
return true; return true;
} }
void removeFromCache(thread_db* tdbb) override
{
delayedDelete(tdbb);
}
const char* c_name() const override const char* c_name() const override
{ {
return name.c_str(); return name.c_str();

View File

@ -622,8 +622,7 @@ namespace Jrd
dbb_replica_mode(REPLICA_NONE), dbb_replica_mode(REPLICA_NONE),
dbb_compatibility_index(~0U), dbb_compatibility_index(~0U),
dbb_dic(*p), dbb_dic(*p),
dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p)), dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p))
dbb_delayed_delete(*p, *p)
{ {
dbb_pools.add(p); dbb_pools.add(p);
} }

View File

@ -440,8 +440,6 @@ public:
Firebird::InitInstance<KeywordsMap, KeywordsMapAllocator, Firebird::TraditionalDelete> dbb_keywords_map; Firebird::InitInstance<KeywordsMap, KeywordsMapAllocator, Firebird::TraditionalDelete> dbb_keywords_map;
MetadataCache* dbb_mdc; MetadataCache* dbb_mdc;
HazardDelayedDelete dbb_delayed_delete;
Firebird::Mutex dbb_dd_mutex;
// returns true if primary file is located on raw device // returns true if primary file is located on raw device
bool onRawDevice() const; bool onRawDevice() const;

View File

@ -1419,7 +1419,7 @@ void ExtEngineManager::makeFunction(thread_db* tdbb, CompilerScratch* csb, Jrd::
csbPool, extOutMessageNode, intOutMessageNode); csbPool, extOutMessageNode, intOutMessageNode);
Statement* statement = udf->getStatement(); 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); udf->setStatement(statement);
} }
catch (...) catch (...)
@ -1562,7 +1562,7 @@ void ExtEngineManager::makeProcedure(thread_db* tdbb, CompilerScratch* csb, jrd_
mainNode->statements.add(extProcedureNode); mainNode->statements.add(extProcedureNode);
Statement* statement = prc->getStatement(); 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); prc->setStatement(statement);
} }
catch (...) catch (...)
@ -1662,9 +1662,7 @@ void ExtEngineManager::makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::T
trg->extTrigger); trg->extTrigger);
mainNode->statements.add(extTriggerNode); mainNode->statements.add(extTriggerNode);
HazardPtr<jrd_rel> rel(FB_FUNCTION); PAR_preparsed_node(tdbb, trg->relation, mainNode, NULL, &csb, &trg->statement, true, 0);
rel.safePointer(trg->relation);
PAR_preparsed_node(tdbb, rel, mainNode, NULL, &csb, &trg->statement, true, 0);
} }
catch (...) catch (...)
{ {

View File

@ -59,13 +59,13 @@ DATABASE DB = FILENAME "ODS.RDB";
const char* const Function::EXCEPTION_MESSAGE = "The user defined function: \t%s\n\t referencing" 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:"; " entrypoint: \t%s\n\t in module: \t%s\n\tcaused the fatal exception:";
HazardPtr<Function> 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(); Attachment* const attachment = tdbb->getAttachment();
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
HazardPtr<Function> check_function(tdbb, FB_FUNCTION); Function* check_function = nullptr;
HazardPtr<Function> function = dbb->dbb_mdc->getFunction(tdbb, id); Function* function = dbb->dbb_mdc->getFunction(tdbb, id, noscan);
if (function && function->getId() == id && if (function && function->getId() == id &&
!(function->flags & Routine::FLAG_CLEARED) && !(function->flags & Routine::FLAG_CLEARED) &&
@ -85,7 +85,7 @@ HazardPtr<Function> Function::lookup(thread_db* tdbb, USHORT id, bool return_del
// We need to look up the function in RDB$FUNCTIONS // We need to look up the function in RDB$FUNCTIONS
function.clear(); function = nullptr;
AutoCacheRequest request(tdbb, irq_l_fun_id, IRQ_REQUESTS); AutoCacheRequest request(tdbb, irq_l_fun_id, IRQ_REQUESTS);
@ -109,14 +109,14 @@ HazardPtr<Function> Function::lookup(thread_db* tdbb, USHORT id, bool return_del
return function; return function;
} }
HazardPtr<Function> 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(); Attachment* const attachment = tdbb->getAttachment();
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
// See if we already know the function by name // See if we already know the function by name
HazardPtr<Function> 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); Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED | Routine::FLAG_BEING_SCANNED | Routine::FLAG_BEING_ALTERED);
if (function) if (function)
@ -127,7 +127,7 @@ HazardPtr<Function> Function::lookup(thread_db* tdbb, const QualifiedName& name,
// We need to look up the function in RDB$FUNCTIONS // We need to look up the function in RDB$FUNCTIONS
function.clear(); function = nullptr;
AutoCacheRequest request(tdbb, irq_l_fun_name, IRQ_REQUESTS); AutoCacheRequest request(tdbb, irq_l_fun_name, IRQ_REQUESTS);
@ -143,12 +143,12 @@ HazardPtr<Function> Function::lookup(thread_db* tdbb, const QualifiedName& name,
return function; return function;
} }
HazardPtr<Function> 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::Attachment* attachment = tdbb->getAttachment();
jrd_tra* sysTransaction = attachment->getSysTransaction(); jrd_tra* sysTransaction = attachment->getSysTransaction();
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
HazardPtr<Function> function = dbb->dbb_mdc->getFunction(tdbb, id, true); Function* function = dbb->dbb_mdc->getFunction(tdbb, id, noscan);
if (function && !(function->flags & Routine::FLAG_OBSOLETE)) if (function && !(function->flags & Routine::FLAG_OBSOLETE))
{ {
@ -163,29 +163,28 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
} }
} }
Function* newFun = function.getPointer(); return nullptr;
function.clear(); }
MemoryPool& pool = dbb->dbb_mdc->getPool();
if (!newFun)
newFun = FB_NEW_POOL(*dbb->dbb_permanent) Function(pool);
try Function* Function::create(thread_db* tdbb, MetaId id, CacheObject::Flag flags)
{ {
newFun->flags |= (Routine::FLAG_BEING_SCANNED | flags); Jrd::Attachment* attachment = tdbb->getAttachment();
newFun->flags &= ~(Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED); jrd_tra* sysTransaction = attachment->getSysTransaction();
Database* const dbb = tdbb->getDatabase();
newFun->setId(id);
function = dbb->dbb_mdc->setFunction(tdbb, id, newFun);
newFun = nullptr;
Function* function = FB_NEW_POOL(*dbb->dbb_permanent) Function(*dbb->dbb_permanent, id);
/*
if (!function->existenceLock) if (!function->existenceLock)
{ {
function->existenceLock = FB_NEW_POOL(pool) function->existenceLock = FB_NEW_POOL(pool)
ExistenceLock(pool, tdbb, LCK_fun_exist, function->getId(), function.getPointer()); 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); AutoCacheRequest request_fun(tdbb, irq_l_functions, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request_fun) FOR(REQUEST_HANDLE request_fun)
@ -336,7 +335,7 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
try try
{ {
parameter->prm_default_value = static_cast<ValueExprNode*>(MET_parse_blob( parameter->prm_default_value = static_cast<ValueExprNode*>(MET_parse_blob(
tdbb, nullRel, &default_value, nullptr, nullptr, false, false)); tdbb, nullptr, &default_value, nullptr, nullptr, false, false));
} }
catch (const Exception&) catch (const Exception&)
{ {
@ -419,7 +418,7 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
else else
body.getBuffer(1)[0] = 0; 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()); (X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin());
if (!function->fun_external) if (!function->fun_external)
@ -477,20 +476,12 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
} }
} }
END_FOR END_FOR
} } // if noscan
// Make sure that it is really being scanned
fb_assert(function->flags & Routine::FLAG_BEING_SCANNED);
function->flags &= ~Routine::FLAG_BEING_SCANNED;
} // try } // try
catch (const Exception&) catch (const Exception&)
{ {
if (newFun)
newFun->delayedDelete(tdbb);
if (function) if (function)
function->flags &= ~(Routine::FLAG_BEING_SCANNED | Routine::FLAG_SCANNED); Function::destroy(function);
throw; throw;
} }
@ -500,12 +491,7 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
bool Function::checkCache(thread_db* tdbb) const bool Function::checkCache(thread_db* tdbb) const
{ {
return tdbb->getDatabase()->dbb_mdc->getFunction(tdbb, getId()) == this; return tdbb->getDatabase()->dbb_mdc->getFunction(tdbb, getId(), true) == this;
}
void Function::clearCache(thread_db* tdbb)
{
tdbb->getDatabase()->dbb_mdc->setFunction(tdbb, getId(), nullptr);
} }
bool Function::reload(thread_db* tdbb) bool Function::reload(thread_db* tdbb)

View File

@ -38,8 +38,8 @@ namespace Jrd
static const char* const EXCEPTION_MESSAGE; static const char* const EXCEPTION_MESSAGE;
public: public:
static HazardPtr<Function> lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags); static Function* lookup(thread_db* tdbb, MetaId id, bool return_deleted, bool noscan, USHORT flags);
static HazardPtr<Function> lookup(thread_db* tdbb, const QualifiedName& name, bool noscan); static Function* lookup(thread_db* tdbb, const QualifiedName& name, bool noscan);
explicit Function(MemoryPool& p) explicit Function(MemoryPool& p)
: Routine(p), : Routine(p),
@ -53,7 +53,22 @@ namespace Jrd
{ {
} }
static HazardPtr<Function> 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: public:
virtual int getObjectType() const virtual int getObjectType() const
@ -67,18 +82,20 @@ namespace Jrd
} }
virtual bool checkCache(thread_db* tdbb) const; virtual bool checkCache(thread_db* tdbb) const;
virtual void clearCache(thread_db* tdbb);
private:
virtual ~Function() virtual ~Function()
{ {
delete fun_external; delete fun_external;
} }
public:
virtual void releaseExternal() virtual void releaseExternal()
{ {
delete fun_external; delete fun_external;
fun_external = NULL; fun_external = NULL;
} }
public: public:
int (*fun_entrypoint)(); // function entrypoint int (*fun_entrypoint)(); // function entrypoint
USHORT fun_inputs; // input arguments USHORT fun_inputs; // input arguments

View File

@ -39,171 +39,6 @@ HazardObject::~HazardObject()
CacheObject* TRAP = nullptr; 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<HazardPointers>& 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<HazardPointers> 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<HazardPointers> 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&) bool CacheObject::checkObject(thread_db*, Arg::StatusVector&)
{ {

View File

@ -36,169 +36,126 @@
#include "../common/gdsassert.h" #include "../common/gdsassert.h"
#include "fb_blk.h" #include "fb_blk.h"
#include <atomic> #include <cds/gc/dhp.h>
#include <cds/algo/atomic.h>
#include <type_traits>
namespace Jrd { namespace Jrd {
class thread_db;
class Attachment;
class HazardDelayedDelete;
class HazardObject class HazardObject
{ {
friend HazardDelayedDelete;
protected: protected:
void retire()
{
fb_assert(this);
struct Disposer
{
void operator()(HazardObject* ho)
{
fb_assert(ho);
delete ho;
}
};
cds::gc::DHP::retire<Disposer>(this);
}
virtual ~HazardObject(); 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 <typename T> template <typename T>
class HazardPtr : public HazardBase class HazardPtr : private cds::gc::DHP::Guard
{ {
typedef cds::gc::DHP::Guard inherited;
static_assert(std::is_base_of<HazardObject, T>::value, "class derived from HazardObject should be used");
public: public:
HazardPtr(const char* F) HazardPtr() = default;
: hazardPointer(nullptr),
frm(F)
{ }
template <class DDS> HazardPtr(const atomics::atomic<T*>& from)
explicit HazardPtr(DDS* par, const char* F)
: HazardBase(par),
hazardPointer(nullptr),
frm(F)
{ }
template <class DDS>
HazardPtr(DDS* par, const std::atomic<T*>& from, const char* F)
: HazardBase(par),
hazardPointer(nullptr),
frm(F)
{ {
set(from); protect(from);
} }
HazardPtr(const HazardPtr& copy) HazardPtr(const HazardPtr& copyFrom)
: HazardBase(copy),
hazardPointer(nullptr),
frm(copy.frm)
{ {
reset(copy.hazardPointer); copy(copyFrom);
frm = copy.frm;
} }
HazardPtr(HazardPtr&& move) HazardPtr(HazardPtr&& moveFrom) = default;
: HazardBase(move),
hazardPointer(nullptr), template <class T2>
frm(move.frm) HazardPtr(const HazardPtr<T2>& copyFrom)
{ {
hazardPointer = move.releasePointer(); checkAssign<T2>();
copy(copyFrom);
} }
template <class T2> template <class T2>
HazardPtr(const HazardPtr<T2>& copy) HazardPtr(HazardPtr<T2>&& moveFrom)
: HazardBase(copy), : inherited(std::move(moveFrom))
hazardPointer(nullptr),
frm(copy.frm)
{ {
reset(copy.getPointer()); checkAssign<T2>();
}
template <class T2>
HazardPtr(HazardPtr<T2>&& move)
: HazardBase(move),
hazardPointer(nullptr),
frm(move.frm)
{
hazardPointer = move.releasePointer();
} }
~HazardPtr() ~HazardPtr()
{ { }
reset(nullptr);
}
/*
T* unsafePointer() const // to be removed
{
return getPointer();
}
*/
T* getPointer() const T* getPointer() const
{ {
return hazardPointer; return get<T>();
} }
T* releasePointer() T* releasePointer()
{ {
T* rc = hazardPointer; T* rc = get<T>();
hazardPointer = nullptr; clear();
return rc; return rc;
} }
void set(const std::atomic<T*>& from) void set(const atomics::atomic<T*>& from)
{ {
T* v = from.load(std::memory_order_relaxed); protect(from);
do
{
reset(v);
v = from.load(std::memory_order_acquire);
} while (hazardPointer != v);
} }
// 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' // always sets *this to actual data from 'where'
bool replace(std::atomic<T*>* where, T* newVal) bool replace(atomics::atomic<T*>& where, T* newVal)
{ {
T* val = hazardPointer; T* val = get<T>();
bool rc = where->compare_exchange_strong(val, newVal, bool rc = where.compare_exchange_strong(val, newVal,
std::memory_order_release, std::memory_order_acquire); 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<T*>& where, T* newVal)
{
T* val = get<T>();
bool rc = where.compare_exchange_strong(val, newVal,
std::memory_order_release, std::memory_order_acquire);
if(rc)
assign(newVal);
return rc; return rc;
} }
void clear() void clear()
{ {
reset(nullptr); inherited::clear();
} }
T* operator->() T* operator->()
{ {
return hazardPointer; return get<T>();
} }
const T* operator->() const const T* operator->() const
{ {
return hazardPointer; return get<T>();
} }
/* /*
template <typename R> template <typename R>
@ -209,85 +166,68 @@ namespace Jrd {
*/ */
bool operator!() const bool operator!() const
{ {
return hazardPointer == nullptr; return !hasData();
} }
bool hasData() const bool hasData() const
{ {
return hazardPointer != nullptr; return get_native() != nullptr;
} }
bool operator==(const T* v) const bool operator==(const T* v) const
{ {
return hazardPointer == v; return get<T>() == v;
} }
bool operator!=(const T* v) const bool operator!=(const T* v) const
{ {
return hazardPointer != v; return get<T>() != v;
} }
operator bool() const operator bool() const
{ {
return hazardPointer != nullptr; return hasData();
} }
HazardPtr& operator=(const HazardPtr& copyAssign) HazardPtr& operator=(const HazardPtr& copyAssign)
{ {
reset(copyAssign.hazardPointer, &copyAssign); copy(copyAssign);
return *this; return *this;
} }
HazardPtr& operator=(HazardPtr&& moveAssign) HazardPtr& operator=(HazardPtr&& moveAssign)
{ {
if (hazardPointer) inherited::operator=(std::move(moveAssign));
remove(hazardPointer, frm);
HazardBase::operator=(moveAssign);
hazardPointer = moveAssign.releasePointer();
return *this; return *this;
} }
template <class T2> template <class T2>
HazardPtr& operator=(const HazardPtr<T2>& copyAssign) HazardPtr& operator=(const HazardPtr<T2>& copyAssign)
{ {
reset(copyAssign.getPointer(), &copyAssign); checkAssign<T2>();
copy(copyAssign);
return *this; return *this;
} }
template <class T2> template <class T2>
HazardPtr& operator=(HazardPtr<T2>&& moveAssign) HazardPtr& operator=(HazardPtr<T2>&& moveAssign)
{ {
if (hazardPointer) checkAssign<T2>();
remove(hazardPointer, FB_FUNCTION); inherited::operator=(std::move(moveAssign));
HazardBase::operator=(moveAssign);
hazardPointer = moveAssign.releasePointer();
return *this; return *this;
} }
void safePointer(T* ptr) void safePointer(T* ptr)
{ {
reset(ptr); assign(ptr);
} }
private: private:
void reset(T* newPtr, const HazardBase* newBase = nullptr) template <class T2>
struct checkAssign
{ {
if (newPtr != hazardPointer) static_assert(std::is_trivially_assignable<T*&, T2*>::value, "Invalid type of pointer assigned");
{ };
if (hazardPointer)
remove(hazardPointer, frm);
if (newBase)
HazardBase::operator=(*newBase);
if (newPtr)
add(newPtr, frm);
hazardPointer = newPtr;
}
}
T* hazardPointer;
public:
const char* frm;
}; };
template <typename T> template <typename T>
@ -310,11 +250,10 @@ namespace Jrd {
// Shared read here means that any thread can read from vector using HP. // 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 can be modified only in single thread, and it's caller's responsibility
// It's also callers responsibility to destroy Generation when deleting SharedReadVector: // that modifying thread is single.
// in dtor we do not have enough information to do it correctly, default delayedDelete() may be already wrong.
template <typename T, FB_SIZE_T CAP, bool GC_ENABLED = true> template <typename T, FB_SIZE_T CAP>
class SharedReadVector : public Firebird::PermanentStorage class SharedReadVector : public Firebird::PermanentStorage
{ {
public: public:
@ -382,409 +321,75 @@ namespace Jrd {
while (count && data[count - 1] == notValue) while (count && data[count - 1] == notValue)
count--; count--;
} }
static void destroy(Generation* gen)
{
// delay delete - someone else may access it
gen->retire();
}
}; };
SharedReadVector(MemoryPool& p) SharedReadVector(MemoryPool& p)
: Firebird::PermanentStorage(p), : Firebird::PermanentStorage(p),
v(Generation::create(getPool(), CAP)) currentData(Generation::create(getPool(), CAP))
{ } { }
Generation* writeAccessor() Generation* writeAccessor()
{ {
return v.load(std::memory_order_acquire); return currentData.load(std::memory_order_acquire);
} }
template <class DDS> HazardPtr<Generation> readAccessor() const
HazardPtr<Generation> readAccessor(DDS* par) const
{ {
return HazardPtr<Generation>(par, v, FB_FUNCTION); return HazardPtr<Generation>(currentData);
} }
inline void grow(HazardDelayedDelete* dd, FB_SIZE_T newSize = 0); void grow(FB_SIZE_T newSize = 0)
{
for(;;)
{
HazardPtr<Generation> 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: private:
std::atomic<Generation*> v; atomics::atomic<Generation*> currentData;
}; };
class thread_db;
class HazardDelayedDelete : public Firebird::PermanentStorage class CacheObject
{
private:
static const unsigned int INITIAL_SIZE = 4;
static const unsigned int DELETED_LIST_SIZE = 32;
typedef Firebird::SortedArray<const void*, Firebird::InlineStorage<const void*, 128>> LocalHP;
public:
enum class GarbageCollectMethod {GC_NORMAL, GC_ALL, GC_FORCE};
// In this and only this case disable GC in delayedDelete()
typedef SharedReadVector<const void*, INITIAL_SIZE, false> 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<HazardPointers>& from);
static void copyHazardPointers(thread_db* tdbb, LocalHP& local, Attachment* from);
Firebird::HalfStaticArray<HazardObject*, DELETED_LIST_SIZE> 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 <typename T, FB_SIZE_T CAP, bool GC_ENABLED>
inline void SharedReadVector<T, CAP, GC_ENABLED>::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
{ {
public: public:
typedef unsigned Flag;
virtual bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) /*const*/; virtual bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) /*const*/;
virtual void afterUnlock(thread_db* tdbb, unsigned flags); virtual void afterUnlock(thread_db* tdbb, unsigned flags);
virtual void lockedExcl [[noreturn]] (thread_db* tdbb) /*const*/; virtual void lockedExcl [[noreturn]] (thread_db* tdbb) /*const*/;
virtual const char* c_name() const = 0; virtual const char* c_name() const = 0;
virtual void removeFromCache(thread_db* tdbb) = 0;
};
template <class Object, unsigned SUBARRAY_SHIFT = 8>
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<Object*> SubArrayElement;
typedef std::atomic<SubArrayElement*> ArrayElement;
typedef SharedReadVector<ArrayElement, 4> Storage;
explicit HazardArray(MemoryPool& pool)
: Firebird::PermanentStorage(pool),
m_objects(getPool())
{}
SLONG lookup(thread_db* tdbb, const typename Object::Key& key, HazardPtr<Object>* 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<Object> 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 <class DDS>
FB_SIZE_T getCount(DDS* par) const
{
return m_objects.readAccessor(par)->getCount() << SUBARRAY_SHIFT;
}
static FB_SIZE_T getCount(const HazardPtr<typename Storage::Generation>& 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<Object> 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<Object>(tdbb, *sub, FB_FUNCTION);
}
*/
bool replace(thread_db* tdbb, FB_SIZE_T id, HazardPtr<Object>& 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<Object>& val)
{
store(tdbb, id, val.getPointer());
}
*/
template <class DDS>
bool load(DDS* par, FB_SIZE_T id, HazardPtr<Object>& 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 <class DDS>
HazardPtr<Object> load(DDS* par, FB_SIZE_T id) const
{
HazardPtr<Object> val(FB_FUNCTION);
if (!load(par, id, val))
val.clear();
return val;
}
template <class DDS>
HazardPtr<typename Storage::Generation> readAccessor(DDS* par) const
{
return m_objects.readAccessor(par);
}
class Snapshot;
class Iterator
{
public:
HazardPtr<Object> operator*()
{
return get();
}
HazardPtr<Object> 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<Object>::getHazardDelayed()),
index(loc == Location::Begin ? snap->locateData(0) :
snap->data->getCount() << SUBARRAY_SHIFT)
{ }
HazardPtr<Object> get()
{
HazardPtr<Object> 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<Object>::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<Object>& 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<typename Storage::Generation> data;
};
Snapshot snapshot() const
{
return Snapshot(this);
}
private:
SharedReadVector<ArrayElement, 4> m_objects;
Firebird::Mutex objectsGrowMutex;
}; };
} // namespace Jrd } // namespace Jrd

View File

@ -648,12 +648,12 @@ RecordBuffer* SnapshotData::getData(int id) const
RecordBuffer* SnapshotData::allocBuffer(thread_db* tdbb, MemoryPool& pool, int rel_id) RecordBuffer* SnapshotData::allocBuffer(thread_db* tdbb, MemoryPool& pool, int rel_id)
{ {
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false);
fb_assert(relation); fb_assert(relation);
MET_scan_relation(tdbb, relation); MET_scan_relation(tdbb, relation);
fb_assert(relation->isVirtual()); fb_assert(relation->isVirtual());
const Format* const format = MET_current(tdbb, relation.getPointer()); const Format* const format = MET_current(tdbb, relation);
fb_assert(format); fb_assert(format);
RecordBuffer* const buffer = FB_NEW_POOL(pool) RecordBuffer(pool, 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; SLONG rel_id;
memcpy(&rel_id, field.data, field.length); memcpy(&rel_id, field.data, field.length);
HazardPtr<jrd_rel> 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()) if (!relation || relation->rel_name.isEmpty())
return; return;

View File

@ -28,10 +28,11 @@
#include "../jrd/ids.h" #include "../jrd/ids.h"
#include "../jrd/recsrc/Cursor.h" #include "../jrd/recsrc/Cursor.h"
#include "../jrd/dpm_proto.h" #include "../jrd/dpm_proto.h"
#include "../jrd/lck_proto.h" #include "../jrd/lck.h"
#include "../jrd/met_proto.h" #include "../jrd/met_proto.h"
#include "../jrd/pag_proto.h" #include "../jrd/pag_proto.h"
#include "../jrd/tra_proto.h" #include "../jrd/tra_proto.h"
#include "../jrd/Statement.h"
using namespace Jrd; using namespace Jrd;
using namespace Firebird; using namespace Firebird;

View File

@ -528,7 +528,7 @@ LocalTableSourceNode* LocalTableSourceNode::copy(thread_db* tdbb, NodeCopier& co
void LocalTableSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/, void LocalTableSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/,
BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack) 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. 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 // Find relation either by id or by name
AutoPtr<string> aliasString; AutoPtr<string> aliasString;
MetaName name; MetaName name;
HazardPtr<jrd_rel> rel(FB_FUNCTION); CacheElement<jrd_rel>* rel = nullptr;
switch (blrOp) switch (blrOp)
{ {
@ -587,7 +587,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
csb->csb_blr_reader.getString(*aliasString); csb->csb_blr_reader.getString(*aliasString);
} }
rel = MetadataCache::lookup_relation_id(tdbb, id, false); rel = MetadataCache::lookupRelation(tdbb, id);
if (!rel) if (!rel)
name.printf("id %d", id); name.printf("id %d", id);
break; break;
@ -604,7 +604,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
csb->csb_blr_reader.getString(*aliasString); csb->csb_blr_reader.getString(*aliasString);
} }
rel = MetadataCache::lookup_relation(tdbb, name); rel = MetadataCache::lookupRelation(tdbb, name);
break; break;
} }
@ -617,7 +617,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
// Store relation in CSB resources and after it - in the node // 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 // 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 // Scan the relation if it hasn't already been scanned for meta data
if ((!(node->relation->rel_flags & REL_scanned) || jrd_rel* latestVersion = rel->getObject(tdbb);
(node->relation->rel_flags & REL_being_scanned)) && if (!(csb->csb_g_flags & csb_internal))
!(csb->csb_g_flags & csb_internal)) latestVersion->scan(tdbb);
{ if (latestVersion->rel_flags & REL_sys_triggers)
MET_scan_relation(tdbb, rel); MET_parse_sys_trigger(tdbb, latestVersion);
}
else if (node->relation->rel_flags & REL_sys_triggers)
MET_parse_sys_trigger(tdbb, rel);
// generate a stream for the relation reference, assuming it is a real reference // 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, dsqlName);
NODE_PRINT(printer, alias); NODE_PRINT(printer, alias);
NODE_PRINT(printer, context); NODE_PRINT(printer, context);
if (relation) if (relation.isSet())
printer.print("rel_name", relation->rel_name); printer.print("rel_name", relation.get(JRD_get_thread_data(), printer.resources)->rel_name);
return "RelationSourceNode"; return "RelationSourceNode";
} }
@ -734,12 +731,16 @@ RecordSourceNode* RelationSourceNode::pass1(thread_db* tdbb, CompilerScratch* cs
const auto tail = &csb->csb_rpt[stream]; const auto tail = &csb->csb_rpt[stream];
const auto relation = tail->csb_relation; 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 : const SLONG ssRelationId = tail->csb_view.isSet() ?
view ? view->rel_id : csb->csb_view ? csb->csb_view->rel_id : 0; tail->csb_view.get(tdbb, csb->csb_resources)->rel_id : view.isSet() ?
CMP_post_access(tdbb, csb, relation->rel_security_name, ssRelationId, view.get(tdbb, csb->csb_resources)->rel_id : csb->csb_view.isSet() ?
SCL_select, obj_relations, relation->rel_name); 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; 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 // prepare to check protection of relation when a field in the stream of the
// relation is accessed. // relation is accessed.
jrd_rel* const parentView = csb->csb_view; CachedResource<jrd_rel> const parentView = csb->csb_view;
const StreamType viewStream = csb->csb_view_stream; const StreamType viewStream = csb->csb_view_stream;
jrd_rel* relationView = relation; CachedResource<jrd_rel> relationView = relation;
csb->csb_resources.postResource(tdbb, Resource::rsc_relation, relationView, relationView->rel_id); //csb->csb_resources.postResource(tdbb, Resource::rsc_relation, relationView, relationView->rel_id);
view = parentView; view = parentView;
CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream); 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 // 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; const USHORT key = context;
FB_SIZE_T pos; 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 // 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) if (!viewRse)
return; return;
@ -795,7 +796,7 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN
AutoSetRestore<USHORT> autoRemapVariable(&csb->csb_remap_variable, AutoSetRestore<USHORT> autoRemapVariable(&csb->csb_remap_variable,
(csb->csb_variables ? csb->csb_variables->count() : 0) + 1); (csb->csb_variables ? csb->csb_variables->count() : 0) + 1);
AutoSetRestore<jrd_rel*> autoView(&csb->csb_view, relationView); AutoSetRestore<CachedResource<jrd_rel>> autoView(&csb->csb_view, relationView);
AutoSetRestore<StreamType> autoViewStream(&csb->csb_view_stream, stream); AutoSetRestore<StreamType> autoViewStream(&csb->csb_view_stream, stream);
// We don't expand the view in two cases: // We don't expand the view in two cases:
@ -908,7 +909,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
jrd_prc* procedure = nullptr; jrd_prc* procedure = nullptr;
AutoPtr<string> aliasString; AutoPtr<string> aliasString;
QualifiedName name; QualifiedName name;
HazardPtr<jrd_prc> proc(FB_FUNCTION); CacheElement<jrd_prc>* proc = nullptr;
switch (blrOp) switch (blrOp)
{ {
@ -923,11 +924,8 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
csb->csb_blr_reader.getString(*aliasString); csb->csb_blr_reader.getString(*aliasString);
} }
proc = MetadataCache::lookup_procedure_id(tdbb, pid, false, false, 0); proc = MetadataCache::lookupProcedure(tdbb, pid);
if (proc) if (!proc)
procedure = csb->csb_resources.registerResource(tdbb, Resource::rsc_procedure, proc, proc->getId());
if (!procedure)
name.identifier.printf("id %d", pid); name.identifier.printf("id %d", pid);
break; break;
} }
@ -1008,7 +1006,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
ProcedureSourceNode* node = FB_NEW_POOL(*tdbb->getDefaultPool()) ProcedureSourceNode( ProcedureSourceNode* node = FB_NEW_POOL(*tdbb->getDefaultPool()) ProcedureSourceNode(
*tdbb->getDefaultPool()); *tdbb->getDefaultPool());
node->procedure = procedure; node->procedure = csb->csb_resources.procedures->registerResource(tdbb, proc);
node->isSubRoutine = procedure->isSubRoutine(); node->isSubRoutine = procedure->isSubRoutine();
node->procedureId = node->isSubRoutine ? 0 : procedure->getId(); node->procedureId = node->isSubRoutine ? 0 : procedure->getId();

View File

@ -358,8 +358,6 @@ public:
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RELATION>(pool), : TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RELATION>(pool),
dsqlName(pool, aDsqlName), dsqlName(pool, aDsqlName),
alias(pool), alias(pool),
//relation(NULL),
view(NULL),
context(0) context(0)
{ {
} }
@ -418,10 +416,10 @@ public:
public: public:
MetaName dsqlName; MetaName dsqlName;
Firebird::string alias; // SQL alias for the relation Firebird::string alias; // SQL alias for the relation
jrd_rel* relation; CachedResource<jrd_rel> relation;
private: private:
jrd_rel* view; // parent view for posting access CachedResource<jrd_rel> view; // parent view for posting access
public: public:
SSHORT context; // user-specified context number for the relation reference SSHORT context; // user-specified context number for the relation reference

View File

@ -43,8 +43,8 @@ using namespace Firebird;
/// jrd_rel /// jrd_rel
jrd_rel::jrd_rel(MemoryPool& p) jrd_rel::jrd_rel(MemoryPool& p, MetaId id)
: rel_pool(&p), rel_id(0), rel_current_fmt(0), : rel_pool(&p), rel_id(id), rel_current_fmt(0),
rel_flags(REL_gc_lockneed), rel_current_format(nullptr), rel_flags(REL_gc_lockneed), rel_current_format(nullptr),
rel_name(p), rel_owner_name(p), rel_security_name(p), rel_name(p), rel_owner_name(p), rel_security_name(p),
rel_formats(nullptr), rel_fields(nullptr), rel_formats(nullptr), rel_fields(nullptr),
@ -667,7 +667,7 @@ HazardPtr<IndexLock> jrd_rel::getIndexLock(thread_db* tdbb, USHORT id)
SET_TDBB(tdbb); SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase(); Database* dbb = tdbb->getDatabase();
HazardPtr<IndexLock> indexLock(FB_FUNCTION); HazardPtr<IndexLock> indexLock;
if (rel_id < (USHORT) rel_MAX) if (rel_id < (USHORT) rel_MAX)
return indexLock; return indexLock;
@ -692,5 +692,37 @@ const char* IndexLock::c_name() const
return "* unk *"; return "* unk *";
} }
//extern static void jrd_rel::destroy(jrd_rel* rel)
HazardPtr<jrd_rel> Jrd::nullRel(FB_FUNCTION); {
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;
}

View File

@ -46,11 +46,9 @@ class IndexBlock;
// Relation trigger definition // Relation trigger definition
class Trigger : public CacheObject class Trigger : public CacheObject
/*
{ {
/*
public: public:
typedef MetaName Key;
Firebird::HalfStaticArray<UCHAR, 128> blr; // BLR code Firebird::HalfStaticArray<UCHAR, 128> blr; // BLR code
Firebird::HalfStaticArray<UCHAR, 128> debugInfo; // Debug info Firebird::HalfStaticArray<UCHAR, 128> debugInfo; // Debug info
Statement* statement; // Compiled statement Statement* statement; // Compiled statement
@ -154,84 +152,15 @@ public:
}; };
// Array of triggers (suppose separate arrays for triggers of different types) // Array of triggers (suppose separate arrays for triggers of different types)
class TrigVector : public HazardArray<Trigger> class TrigVector
{ {
/*
public: public:
explicit TrigVector(Firebird::MemoryPool& pool)
: HazardArray<Trigger>(pool),
useCount(0), addCount(0)
{ }
TrigVector()
: HazardArray<Trigger>(Firebird::AutoStorage::getAutoMemoryPool()),
useCount(0), addCount(0)
{ }
HazardPtr<Trigger> 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; bool hasActive() const;
void decompile(thread_db* tdbb); void decompile(thread_db* tdbb);
void release(); virtual ~TrigVector() { }
void release(thread_db* tdbb);
~TrigVector() virtual void addTrigger(thread_db* tdbb, Trigger* trigger) = 0;
{
fb_assert(useCount.load() == 0);
}
private:
std::atomic<int> useCount;
std::atomic<FB_SIZE_T> addCount;
*/
public:
explicit TrigVector(Firebird::MemoryPool& pool)
: Firebird::ObjectsArray<Trigger>(pool),
useCount(0)
{ }
TrigVector()
: Firebird::ObjectsArray<Trigger>(),
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;
}; };
typedef std::atomic<TrigVector*> TrigVectorPtr; typedef std::atomic<TrigVector*> TrigVectorPtr;
@ -445,11 +374,6 @@ public:
bool hasData() { return true; } bool hasData() { return true; }
const char* c_name() const override; 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 // in the database, though it is not really filled out until
// the relation is scanned // the relation is scanned
class jrd_rel : public CacheObject class jrd_rel final : public CacheObject
{ {
typedef Firebird::HalfStaticArray<Record*, 4> GCRecordList; typedef Firebird::HalfStaticArray<Record*, 4> GCRecordList;
typedef HazardArray<IndexLock, 2> IndexLockList; typedef Firebird::ObjectsArray<IndexLock> IndexLocks;
public: public:
typedef MetaName Key;
MemoryPool* rel_pool; MemoryPool* rel_pool;
USHORT rel_id; USHORT rel_id;
USHORT rel_current_fmt; // Current format number USHORT rel_current_fmt; // Current format number
@ -492,7 +414,7 @@ public:
Lock* rel_partners_lock; // partners lock Lock* rel_partners_lock; // partners lock
Lock* rel_rescan_lock; // lock forcing relation to be scanned Lock* rel_rescan_lock; // lock forcing relation to be scanned
Lock* rel_gc_lock; // garbage collection lock 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 //Firebird::Mutex rel_mtx_il; // controls addition & removal of elements
IndexBlock* rel_index_blocks; // index blocks for caching index info IndexBlock* rel_index_blocks; // index blocks for caching index info
TrigVectorPtr rel_pre_erase; // Pre-operation erase trigger TrigVectorPtr rel_pre_erase; // Pre-operation erase trigger
@ -538,6 +460,16 @@ public:
return rel_id; 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); bool delPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, RelationPages* aPages = NULL);
void retainPages(thread_db* tdbb, TraNumber oldNumber, TraNumber newNumber); void retainPages(thread_db* tdbb, TraNumber oldNumber, TraNumber newNumber);
@ -572,13 +504,8 @@ public:
bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) override; bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) override;
void afterUnlock(thread_db* tdbb, unsigned flags) override; void afterUnlock(thread_db* tdbb, unsigned flags) override;
void removeFromCache(thread_db* tdbb) override static void destroy(jrd_rel *rel);
{ static jrd_rel* create(thread_db* tdbb, MetaId id, CacheObject::Flag flags);
if (rel_existence_lock)
rel_existence_lock->removeFromCache(tdbb);
else
delayedDelete(tdbb);
}
private: private:
typedef Firebird::SortedArray< typedef Firebird::SortedArray<
@ -595,7 +522,7 @@ private:
RelationPages* getPagesInternal(thread_db* tdbb, TraNumber tran, bool allocPages); RelationPages* getPagesInternal(thread_db* tdbb, TraNumber tran, bool allocPages);
public: public:
explicit jrd_rel(MemoryPool& p); jrd_rel(MemoryPool& p, MetaId id);
// bool hasTriggers() const; unused ??????????????????? // bool hasTriggers() const; unused ???????????????????
void releaseTriggers(thread_db* tdbb, bool destroy); void releaseTriggers(thread_db* tdbb, bool destroy);
@ -646,8 +573,6 @@ public:
}; };
}; };
extern HazardPtr<jrd_rel> nullRel;
// rel_flags // rel_flags
const ULONG REL_scanned = 0x0001; // Field expressions scanned (or being scanned) const ULONG REL_scanned = 0x0001; // Field expressions scanned (or being scanned)

View File

@ -175,7 +175,7 @@ void Routine::parseBlr(thread_db* tdbb, CompilerScratch* csb, bid* blob_id, bid*
flags &= ~Routine::FLAG_RELOAD; flags &= ~Routine::FLAG_RELOAD;
Statement* statement = getStatement(); 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); setStatement(statement);
if (csb->csb_g_flags & csb_reload) 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 int Routine::getUseCount() const
{ {
return existenceLock.hasData() ? existenceLock->getUseCount() : 1; 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; 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) void Routine::releaseLocks(thread_db* tdbb)
{ {
if (existenceLock) if (existenceLock)

View File

@ -96,7 +96,29 @@ namespace Jrd
protected: protected:
explicit Routine(MemoryPool& p) explicit Routine(MemoryPool& p)
: PermanentStorage(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), name(p),
securityName(p), securityName(p),
statement(NULL), statement(NULL),
@ -141,6 +163,11 @@ namespace Jrd
static Format* createFormat(MemoryPool& pool, Firebird::IMessageMetadata* params, bool addEof); static Format* createFormat(MemoryPool& pool, Firebird::IMessageMetadata* params, bool addEof);
public: public:
static void destroy(Routine* routine)
{
delete routine;
}
USHORT getId() const USHORT getId() const
{ {
fb_assert(!subRoutine); fb_assert(!subRoutine);
@ -156,8 +183,6 @@ namespace Jrd
const MetaName& getSecurityName() const { return securityName; } const MetaName& getSecurityName() const { return securityName; }
void setSecurityName(const MetaName& value) { securityName = value; } void setSecurityName(const MetaName& value) { securityName = value; }
void removeFromCache(thread_db* tdbb) override;
/*const*/ Statement* getStatement() const { return statement; } /*const*/ Statement* getStatement() const { return statement; }
void setStatement(Statement* value); void setStatement(Statement* value);
@ -204,7 +229,7 @@ namespace Jrd
} }
void afterDecrement(Jrd::thread_db*); 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 releaseStatement(thread_db* tdbb);
//void remove(thread_db* tdbb); //void remove(thread_db* tdbb);
virtual void releaseExternal() virtual void releaseExternal()
@ -221,7 +246,6 @@ namespace Jrd
virtual int getObjectType() const = 0; virtual int getObjectType() const = 0;
virtual SLONG getSclType() const = 0; virtual SLONG getSclType() const = 0;
virtual bool checkCache(thread_db* tdbb) const = 0; virtual bool checkCache(thread_db* tdbb) const = 0;
virtual void clearCache(thread_db* tdbb) = 0;
private: private:
USHORT id; // routine ID USHORT id; // routine ID
@ -256,8 +280,6 @@ namespace Jrd
MetaName owner; MetaName owner;
Jrd::UserId* invoker; // Invoker ID Jrd::UserId* invoker; // Invoker ID
typedef QualifiedName Key;
}; };
} }

View File

@ -113,7 +113,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
TraceCounts traceCounts; TraceCounts traceCounts;
traceCounts.trc_relation_id = rel_id; traceCounts.trc_relation_id = rel_id;
traceCounts.trc_counters = base_cnts->getCounterVector(); traceCounts.trc_counters = base_cnts->getCounterVector();
HazardPtr<jrd_rel> 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; traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
temp.add(traceCounts); temp.add(traceCounts);
} }
@ -127,7 +127,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
TraceCounts traceCounts; TraceCounts traceCounts;
traceCounts.trc_relation_id = rel_id; traceCounts.trc_relation_id = rel_id;
traceCounts.trc_counters = new_cnts->getCounterVector(); traceCounts.trc_counters = new_cnts->getCounterVector();
HazardPtr<jrd_rel> 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; traceCounts.trc_relation_name = relation ? relation->rel_name.c_str() : NULL;
temp.add(traceCounts); temp.add(traceCounts);
} }

View File

@ -340,9 +340,9 @@ const Routine* Statement::getRoutine() const
// Determine if any request of this statement are active. // Determine if any request of this statement are active.
bool Statement::isActive() const 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; return true;
} }
@ -372,7 +372,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique)
if (next->req_attachment == attachment) if (next->req_attachment == attachment)
{ {
if (!(next->req_flags & req_in_use)) if (!next->isUsed())
{ {
clone = next; clone = next;
break; break;
@ -383,7 +383,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique)
++count; ++count;
} }
else if (!(next->req_flags & req_in_use) && !clone) else if (!(next->isUsed()) && !clone)
clone = next; clone = next;
} }
@ -396,7 +396,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique)
clone->setAttachment(attachment); clone->setAttachment(attachment);
clone->req_stats.reset(); clone->req_stats.reset();
clone->req_base_stats.reset(); clone->req_base_stats.reset();
clone->req_flags |= req_in_use; clone->setUsed(true);
return clone; return clone;
} }
@ -442,7 +442,7 @@ void Statement::verifyAccess(thread_db* tdbb)
for (ExternalAccess* item = external.begin(); item != external.end(); ++item) for (ExternalAccess* item = external.begin(); item != external.end(); ++item)
{ {
HazardPtr<Routine> routine(tdbb, FB_FUNCTION); HazardPtr<Routine> routine(tdbb);
int aclType; int aclType;
if (item->exa_action == ExternalAccess::exa_procedure) if (item->exa_action == ExternalAccess::exa_procedure)
@ -471,7 +471,7 @@ void Statement::verifyAccess(thread_db* tdbb)
} }
else else
{ {
HazardPtr<jrd_rel> 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) if (!relation)
continue; continue;
@ -479,7 +479,7 @@ void Statement::verifyAccess(thread_db* tdbb)
MetaName userName = item->user; MetaName userName = item->user;
if (item->exa_view_id) if (item->exa_view_id)
{ {
HazardPtr<jrd_rel> 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)) if (view && (view->rel_flags & REL_sql_relation))
userName = view->rel_owner_name; userName = view->rel_owner_name;
} }
@ -515,7 +515,7 @@ void Statement::verifyAccess(thread_db* tdbb)
if (access.acc_ss_rel_id) if (access.acc_ss_rel_id)
{ {
HazardPtr<jrd_rel> 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)) if (view && (view->rel_flags & REL_sql_relation))
userName = view->rel_owner_name; userName = view->rel_owner_name;
} }
@ -583,7 +583,7 @@ void Statement::verifyAccess(thread_db* tdbb)
if (access->acc_ss_rel_id) if (access->acc_ss_rel_id)
{ {
HazardPtr<jrd_rel> 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)) if (view && (view->rel_flags & REL_sql_relation))
userName = view->rel_owner_name; 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. // Check that we have enough rights to access all resources this list of triggers touches.
void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr<jrd_rel>& ownerRelation, void Statement::verifyTriggerAccess(thread_db* tdbb, const jrd_rel* ownerRelation,
TrigVector* triggers, MetaName userName) TrigVector* triggers, MetaName userName)
{ {
if (!triggers) if (!triggers)
@ -668,7 +668,7 @@ void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr<jrd_rel>& o
for (FB_SIZE_T i = 0; i < triggers->getCount(tdbb); i++) for (FB_SIZE_T i = 0; i < triggers->getCount(tdbb); i++)
{ {
HazardPtr<Trigger> t(tdbb, FB_FUNCTION); HazardPtr<Trigger> t(tdbb);
if (!triggers->load(tdbb, i, t)) if (!triggers->load(tdbb, i, t))
continue; continue;
@ -705,7 +705,7 @@ void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr<jrd_rel>& o
// a direct access to an object from this trigger // a direct access to an object from this trigger
if (access->acc_ss_rel_id) if (access->acc_ss_rel_id)
{ {
HazardPtr<jrd_rel> 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)) if (view && (view->rel_flags & REL_sql_relation))
userName = view->rel_owner_name; 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++) for (FB_SIZE_T i = 0; i < tvec->getCount(tdbb); i++)
{ {
HazardPtr<Trigger> t(tdbb, FB_FUNCTION); HazardPtr<Trigger> t(tdbb);
if (!tvec->load(tdbb, i, t)) if (!tvec->load(tdbb, i, t))
continue; continue;
@ -769,7 +769,7 @@ void Statement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list, c
} }
else if (item->exa_action == ExternalAccess::exa_function) else if (item->exa_action == ExternalAccess::exa_function)
{ {
HazardPtr<Function> 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()) if (function && function->getStatement())
{ {
item->user = function->invoker ? MetaName(function->invoker->getUserName()) : user; item->user = function->invoker ? MetaName(function->invoker->getUserName()) : user;
@ -781,7 +781,7 @@ void Statement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list, c
} }
else else
{ {
HazardPtr<jrd_rel> 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) if (!relation)
continue; continue;
@ -912,6 +912,32 @@ StmtNumber Request::getRequestId() const
return req_id; 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 #ifdef DEV_BUILD

View File

@ -81,7 +81,7 @@ public:
Firebird::string getPlan(thread_db* tdbb, bool detailed) const; Firebird::string getPlan(thread_db* tdbb, bool detailed) const;
private: private:
static void verifyTriggerAccess(thread_db* tdbb, const HazardPtr<jrd_rel>& ownerRelation, TrigVector* triggers, static void verifyTriggerAccess(thread_db* tdbb, const jrd_rel* ownerRelation, TrigVector* triggers,
MetaName userName); MetaName userName);
static void triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list, TrigVector* tvec, const MetaName &user); static void triggersExternalAccess(thread_db* tdbb, ExternalAccessList& list, TrigVector* tvec, const MetaName &user);
@ -98,7 +98,7 @@ public:
Firebird::Array<Request*> requests; // vector of requests Firebird::Array<Request*> requests; // vector of requests
ExternalAccessList externalList; // Access to procedures/triggers to be checked ExternalAccessList externalList; // Access to procedures/triggers to be checked
AccessItemList accessList; // Access items 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 jrd_prc* procedure; // procedure, if any
const Function* function; // function, if any const Function* function; // function, if any
MetaName triggerName; // name of request (trigger), 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::RefStrPtr sqlText; // SQL text (encoded in the metadata charset)
Firebird::Array<UCHAR> blr; // BLR for non-SQL query Firebird::Array<UCHAR> blr; // BLR for non-SQL query
MapFieldInfo mapFieldInfo; // Map field name to field info MapFieldInfo mapFieldInfo; // Map field name to field info
private:
Resources resources;
Firebird::RefPtr<VersionedObjects> latestVersion;
}; };

View File

@ -5311,7 +5311,7 @@ dsc* evlMakeDbkey(Jrd::thread_db* tdbb, const SysFunction* function, const NestV
MetaName relName; MetaName relName;
MOV_get_metaname(tdbb, argDsc, relName); MOV_get_metaname(tdbb, argDsc, relName);
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation(tdbb, relName); jrd_rel* relation = MetadataCache::lookup_relation(tdbb, relName);
if (!relation) if (!relation)
(Arg::Gds(isc_relnotdef) << Arg::Str(relName)).raise(); (Arg::Gds(isc_relnotdef) << Arg::Str(relName)).raise();

View File

@ -34,7 +34,7 @@
#include "../common/classes/ClumpletWriter.h" #include "../common/classes/ClumpletWriter.h"
#include "../jrd/jrd.h" #include "../jrd/jrd.h"
#include "../jrd/ini_proto.h" #include "../jrd/ini_proto.h"
#include "../jrd/lck_proto.h" #include "../jrd/lck.h"
#include "../jrd/pag_proto.h" #include "../jrd/pag_proto.h"
#include "../jrd/tra_proto.h" #include "../jrd/tra_proto.h"
#include "../jrd/status.h" #include "../jrd/status.h"

View File

@ -1445,7 +1445,7 @@ blb* blb::open2(thread_db* tdbb,
// know about the relation, the blob id has got to be invalid // know about the relation, the blob id has got to be invalid
// anyway. // anyway.
HazardPtr<jrd_rel> 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) if (!relation)
ERR_post(Arg::Gds(isc_bad_segstr_id)); 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)) if (SDL_info(tdbb->tdbb_status_vector, sdl, &info, 0))
ERR_punt(); ERR_punt();
HazardPtr<jrd_rel> relation = info.sdl_info_relation.length() ? jrd_rel* relation = info.sdl_info_relation.length() ?
MetadataCache::lookup_relation(tdbb, info.sdl_info_relation) : MetadataCache::lookup_relation(tdbb, info.sdl_info_relation) :
MetadataCache::findRelation(tdbb, info.sdl_info_rid); MetadataCache::findRelation(tdbb, info.sdl_info_rid);

View File

@ -566,8 +566,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record
fb_assert(!conditionRequest->req_caller); fb_assert(!conditionRequest->req_caller);
conditionRequest->req_caller = orgRequest; 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); TRA_attach_request(tdbb->getTransaction(), conditionRequest);
tdbb->setRequest(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); EXE_unwind(tdbb, conditionRequest);
conditionRequest->req_flags &= ~req_in_use; conditionRequest->setUsed(false);
conditionRequest->req_attachment = nullptr; conditionRequest->req_attachment = nullptr;
tdbb->setRequest(orgRequest); 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); fb_assert(!expr_request->req_caller);
expr_request->req_caller = org_request; 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_attach_request(tdbb->getTransaction(), expr_request);
TRA_setup_request_snapshot(tdbb, expr_request); TRA_setup_request_snapshot(tdbb, expr_request);
tdbb->setRequest(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); tdbb->setRequest(org_request);
expr_request->req_caller = NULL; expr_request->req_caller = NULL;
expr_request->req_flags &= ~req_in_use; expr_request->setUsed(false);
expr_request->req_attachment = NULL; expr_request->req_attachment = NULL;
expr_request->invalidateTimeStamp(); expr_request->invalidateTimeStamp();
@ -672,7 +670,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool&
tdbb->setRequest(org_request); tdbb->setRequest(org_request);
expr_request->req_caller = NULL; expr_request->req_caller = NULL;
expr_request->req_flags &= ~req_in_use; expr_request->setUsed(false);
expr_request->req_attachment = NULL; expr_request->req_attachment = NULL;
expr_request->invalidateTimeStamp(); expr_request->invalidateTimeStamp();
@ -6203,13 +6201,13 @@ string print_key(thread_db* tdbb, jrd_rel* relation, index_desc* idx, Record* re
string key; string key;
fb_assert(relation && idx && record); fb_assert(relation && idx && record);
HazardPtr<jrd_rel> wrk = MET_scan_relation(tdbb, relation->rel_id); jrd_rel* wrk = MET_scan_relation(tdbb, relation->rel_id);
if (!wrk) if (!wrk)
{ {
key.printf("(target relation %s deleted)", relation->c_name()); key.printf("(target relation %s deleted)", relation->c_name());
return key; return key;
} }
relation = wrk.getPointer(); relation = wrk;
const FB_SIZE_T MAX_KEY_STRING_LEN = 250; const FB_SIZE_T MAX_KEY_STRING_LEN = 250;
string value; string value;

View File

@ -368,7 +368,7 @@ public:
{ {
} }
ProtectRelations(thread_db* tdbb, jrd_tra* transaction, HazardPtr<jrd_rel>& relation) : ProtectRelations(thread_db* tdbb, jrd_tra* transaction, jrd_rel* relation) :
m_tdbb(tdbb), m_tdbb(tdbb),
m_transaction(transaction), m_transaction(transaction),
m_locks() m_locks()
@ -382,7 +382,7 @@ public:
unlock(); unlock();
} }
void addRelation(HazardPtr<jrd_rel>& relation) void addRelation(jrd_rel* relation)
{ {
FB_SIZE_T pos; FB_SIZE_T pos;
if (!m_locks.find(relation->rel_id, pos)) if (!m_locks.find(relation->rel_id, pos))
@ -410,7 +410,7 @@ public:
private: private:
struct relLock struct relLock
{ {
relLock(HazardPtr<jrd_rel> relation = HazardPtr<jrd_rel>(FB_FUNCTION)) : relLock(jrd_rel* relation = nullptr) :
m_relation(relation), m_relation(relation),
m_lock(NULL), m_lock(NULL),
m_release(false) m_release(false)
@ -433,7 +433,7 @@ private:
return &item->m_relation->rel_id; return &item->m_relation->rel_id;
} }
HazardPtr<jrd_rel> m_relation; jrd_rel* m_relation;
Lock* m_lock; Lock* m_lock;
bool m_release; 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 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_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*);
static void get_trigger_dependencies(DeferredWork*, bool, jrd_tra*); static void get_trigger_dependencies(DeferredWork*, bool, jrd_tra*);
static Format* make_format(thread_db*, HazardPtr<jrd_rel>, 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_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 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 void setup_array(thread_db*, blb*, const TEXT*, USHORT, TemporaryField*);
static blb* setup_triggers(thread_db*, HazardPtr<jrd_rel>&, bool, TrigVectorPtr*, blb*); static blb* setup_triggers(thread_db*, jrd_rel*, bool, TrigVectorPtr*, blb*);
static void setup_trigger_details(thread_db*, HazardPtr<jrd_rel>&, blb*, TrigVectorPtr*, const TEXT*, bool); static void setup_trigger_details(thread_db*, jrd_rel*, blb*, TrigVectorPtr*, const TEXT*, bool);
static bool validate_text_type (thread_db*, const TemporaryField*); static bool validate_text_type (thread_db*, const TemporaryField*);
static void check_partners(thread_db*, const USHORT); 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)); Arg::Gds(isc_obj_in_use) << Arg::Str(name));
} }
static void raiseRelationInUseError(const HazardPtr<jrd_rel>& relation) static void raiseRelationInUseError(const jrd_rel* relation)
{ {
const string obj_type = const string obj_type =
relation->isView() ? "VIEW" : "TABLE"; relation->isView() ? "VIEW" : "TABLE";
@ -724,7 +724,7 @@ namespace
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);
const QualifiedName name(work->dfw_name, work->dfw_package); const QualifiedName name(work->dfw_name, work->dfw_package);
HazardPtr<Routine> routine(FB_FUNCTION); HazardPtr<Routine> routine;
fprintf(stderr, "routine %d %s ph %d\n", work->dfw_id, name.c_str(), phase); fprintf(stderr, "routine %d %s ph %d\n", work->dfw_id, name.c_str(), phase);
@ -869,7 +869,7 @@ namespace
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);
const QualifiedName name(work->dfw_name, work->dfw_package); const QualifiedName name(work->dfw_name, work->dfw_package);
HazardPtr<T> routine(FB_FUNCTION); HazardPtr<T> routine;
switch (phase) switch (phase)
{ {
@ -996,7 +996,7 @@ namespace
// works in not deleted context // works in not deleted context
{ {
Jrd::ContextPoolHolder context(tdbb, new_pool); 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), (compile ? &statement : NULL),
NULL, depName, NULL, depName,
(work->dfw_package.isEmpty() ? objType : obj_package_body), (work->dfw_package.isEmpty() ? objType : obj_package_body),
@ -1097,7 +1097,7 @@ namespace
{ {
Jrd::Attachment* attachment = tdbb->getAttachment(); Jrd::Attachment* attachment = tdbb->getAttachment();
AutoCacheRequest handle(tdbb, irq_c_fun_dpd, IRQ_REQUESTS); AutoCacheRequest handle(tdbb, irq_c_fun_dpd, IRQ_REQUESTS);
HazardPtr<Routine> routine(tdbb, FB_FUNCTION); HazardPtr<Routine> routine(tdbb);
FOR(REQUEST_HANDLE handle) FOR(REQUEST_HANDLE handle)
X IN RDB$FUNCTIONS WITH X IN RDB$FUNCTIONS WITH
@ -1142,7 +1142,7 @@ namespace
{ {
Attachment* attachment = tdbb->getAttachment(); Attachment* attachment = tdbb->getAttachment();
AutoCacheRequest handle(tdbb, irq_c_prc_dpd, IRQ_REQUESTS); AutoCacheRequest handle(tdbb, irq_c_prc_dpd, IRQ_REQUESTS);
HazardPtr<Routine> routine(tdbb, FB_FUNCTION); HazardPtr<Routine> routine(tdbb);
FOR(REQUEST_HANDLE handle) FOR(REQUEST_HANDLE handle)
X IN RDB$PROCEDURES WITH X IN RDB$PROCEDURES WITH
@ -2365,7 +2365,7 @@ static bool check_not_null(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
case 3: case 3:
{ {
HazardPtr<jrd_rel> 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()) if (!relation || relation->rel_view_rse || work->dfw_ids.isEmpty())
break; break;
@ -2706,7 +2706,7 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
case 3: case 3:
{ {
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation;
CompilerScratch* csb = nullptr; CompilerScratch* csb = nullptr;
const auto dbb = tdbb->getDatabase(); 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 // dimitr: I have no idea why the condition below is required here
AND IREL.RDB$VIEW_BLR MISSING // views do not have indices AND IREL.RDB$VIEW_BLR MISSING // views do not have indices
{ {
HazardPtr<jrd_rel> 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); RelationPages* const relPages = relation->getPages(tdbb, MAX_TRA_NUMBER, false);
if (relPages && relPages->rel_index_root) 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_id = idx_invalid;
idx.idx_flags = idx_foreign; idx.idx_flags = idx_foreign;
HazardPtr<jrd_rel> partner_relation(FB_FUNCTION); jrd_rel* partner_relation = nullptr;
if (MET_lookup_partner(tdbb, relation.unsafePointer(), &idx, work->dfw_name.c_str())) 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); 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; bool gtt_preserve = false;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
if (is_create) if (is_create)
{ {
@ -3353,8 +3353,8 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
* *
**************************************/ **************************************/
AutoCacheRequest request; AutoCacheRequest request;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
HazardPtr<jrd_rel> partner_relation(FB_FUNCTION); jrd_rel* partner_relation = nullptr;
index_desc idx; index_desc idx;
int key_count; int key_count;
@ -3711,7 +3711,7 @@ static bool create_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
* *
**************************************/ **************************************/
AutoCacheRequest request; AutoCacheRequest request;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
USHORT rel_id, external_flag; USHORT rel_id, external_flag;
bid blob_id; bid blob_id;
AutoRequest handle; AutoRequest handle;
@ -4206,7 +4206,7 @@ void DFW_reset_icu(thread_db* tdbb)
USHORT rel_id = rs->getInt(tdbb, 2); USHORT rel_id = rs->getInt(tdbb, 2);
if (!tables.exists(rel_id)) if (!tables.exists(rel_id))
{ {
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false); jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false);
if (relation) if (relation)
tables.addRelation(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(); MemoryPool* new_pool = dbb->createPool();
Jrd::ContextPoolHolder context(tdbb, new_pool); 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); NULL, NULL, depName, obj_validation, 0, transaction, depName);
dbb->deletePool(new_pool); 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(); MemoryPool* new_pool = dbb->createPool();
Jrd::ContextPoolHolder context(tdbb, new_pool); 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); NULL, NULL, depName, obj_validation, 0, transaction, depName);
dbb->deletePool(new_pool); dbb->deletePool(new_pool);
@ -4695,7 +4695,7 @@ static void check_partners(thread_db* tdbb, const USHORT rel_id)
* *
**************************************/ **************************************/
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
HazardPtr<jrd_rel> relation = dbb->dbb_mdc->getRelation(tdbb, rel_id); jrd_rel* relation = dbb->dbb_mdc->getRelation(tdbb, rel_id);
fb_assert(relation); fb_assert(relation);
relation->rel_flags |= REL_check_partners; relation->rel_flags |= REL_check_partners;
@ -4715,7 +4715,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
* Functional description * Functional description
* *
**************************************/ **************************************/
HazardPtr<IndexLock> index(FB_FUNCTION); HazardPtr<IndexLock> index;
SET_TDBB(tdbb); 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, // Look up the relation. If we can't find the relation,
// don't worry about the index. // don't worry about the index.
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation_id(tdbb, work->dfw_id, false); jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, work->dfw_id, false);
if (!relation) { if (!relation) {
return false; 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"); ERR_post(Arg::Gds(isc_random) << "Index block gone unexpestedly");
fb_assert(!arrVal); fb_assert(!arrVal);
index->idl_lock.releaseLock(tdbb, ExistenceLock::ReleaseMethod::DropObject); index->idl_lock.releaseLock(tdbb, ExistenceLock::ReleaseMethod::DropObject);
// fprintf(stderr, "delayedDelete index, replace NULL, to be reviewed\n"); index->retire();
// --- index->delayedDelete(tdbb);
// Release index refresh lock and memory. // Release index refresh lock and memory.
for (IndexBlock** iptr = &relation->rel_index_blocks; *iptr; iptr = &(*iptr)->idb_next) 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; AutoRequest request;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
Resource* rsc; Resource* rsc;
USHORT view_count; USHORT view_count;
bool adjusted; 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); // ?????????? MutexLockGuard g(dbb->dbb_mdc->mdc_use_mutex, FB_FUNCTION);
adjusted = false; 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)) if (!relation->rel_existence_lock->exclLock(tdbb))
/////// ??????? !LCK_convert(tdbb, relation->rel_existence_lock, LCK_EX, transaction->getLockWait()))) /////// ??????? !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; relation->rel_flags |= REL_deleting;
{ // scope { // scope
EngineCheckout cout(tdbb, FB_FUNCTION); EngineCheckout cout(tdbb, FB_FUNCTION);
relation->rel_drop_mutex.enter(FB_FUNCTION); relation->rel_drop_mutex.enter;
} }
return true; return true;
@ -5165,7 +5148,7 @@ static bool delete_rfr(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tr
int rel_exists, field_count; int rel_exists, field_count;
AutoRequest handle; AutoRequest handle;
MetaName f; MetaName f;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
SET_TDBB(tdbb); SET_TDBB(tdbb);
Jrd::Attachment* attachment = tdbb->getAttachment(); Jrd::Attachment* attachment = tdbb->getAttachment();
@ -5565,7 +5548,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra*
if (compile) if (compile)
compile = !tdbb->getAttachment()->isGbak(); compile = !tdbb->getAttachment()->isGbak();
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
bid blob_id; bid blob_id;
blob_id.clear(); 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<jrd_rel> 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* stack;
TemporaryField* external; TemporaryField* external;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
//bid blob_id; //bid blob_id;
//blob_id.clear(); //blob_id.clear();
@ -6351,7 +6334,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
try try
{ {
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation(tdbb, relation_name); jrd_rel* relation = MetadataCache::lookup_relation(tdbb, relation_name);
if (relation) if (relation)
{ {
@ -6375,7 +6358,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
{ {
if (triggers[i]) if (triggers[i])
{ {
HazardPtr<Trigger> trig(tdbb, FB_FUNCTION); HazardPtr<Trigger> trig(tdbb);
for (FB_SIZE_T j = 0; j < triggers[i].load()->getCount(tdbb); ++j) for (FB_SIZE_T j = 0; j < triggers[i].load()->getCount(tdbb); ++j)
{ {
if (triggers[i].load()->load(tdbb, j, trig)) 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); SET_TDBB(tdbb);
HazardPtr<jrd_rel> rel(FB_FUNCTION); jrd_rel* rel = nullptr;
switch (phase) 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<jrd_rel>& relation, bool null_view, static blb* setup_triggers(thread_db* tdbb, jrd_rel* relation, bool null_view,
TrigVectorPtr* triggers, blb* blob) TrigVectorPtr* triggers, blb* blob)
{ {
/************************************** /**************************************
@ -6729,7 +6712,7 @@ static blb* setup_triggers(thread_db* tdbb, HazardPtr<jrd_rel>& relation, bool n
static void setup_trigger_details(thread_db* tdbb, static void setup_trigger_details(thread_db* tdbb,
HazardPtr<jrd_rel>& relation, jrd_rel* relation,
blb* blob, blb* blob,
TrigVectorPtr* triggers, TrigVectorPtr* triggers,
const TEXT* trigger_name, const TEXT* trigger_name,

View File

@ -2019,7 +2019,7 @@ void DPM_scan_pages( thread_db* tdbb)
// infinite recursion from this internal request when RDB$PAGES // infinite recursion from this internal request when RDB$PAGES
// has been extended with another pointer page. // has been extended with another pointer page.
HazardPtr<jrd_rel> relation = MetadataCache::findRelation(tdbb, 0); jrd_rel* relation = MetadataCache::findRelation(tdbb, 0);
RelationPages* relPages = relation->getBasePages(); RelationPages* relPages = relation->getBasePages();
vcl** address = &relPages->rel_pages; vcl** address = &relPages->rel_pages;

View File

@ -778,7 +778,7 @@ void EXE_release(thread_db* tdbb, Request* request)
request->req_attachment = NULL; 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_post_resources(tdbb, transaction, statement->resources);
TRA_attach_request(transaction, request); 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_active;
request->req_flags &= ~req_reserved; // ????????? request->req_flags &= ~req_reserved;
// set up to count records affected by request // set up to count records affected by request
@ -1245,7 +1245,7 @@ void EXE_execute_triggers(thread_db* tdbb,
EXE_unwind(tdbb, trigger); EXE_unwind(tdbb, trigger);
trigger->req_attachment = NULL; trigger->req_attachment = NULL;
trigger->req_flags &= ~req_in_use; trigger->setUsed(false);
if (!ok) if (!ok)
trigger_failure(tdbb, trigger); trigger_failure(tdbb, trigger);
@ -1265,7 +1265,7 @@ void EXE_execute_triggers(thread_db* tdbb,
{ {
EXE_unwind(tdbb, trigger); EXE_unwind(tdbb, trigger);
trigger->req_attachment = NULL; trigger->req_attachment = NULL;
trigger->req_flags &= ~req_in_use; trigger->setUsed(false);
ex.stuffException(tdbb->tdbb_status_vector); ex.stuffException(tdbb->tdbb_status_vector);
@ -1717,10 +1717,6 @@ void ResourceList::setResetPointersHazard(thread_db* tdbb, bool set)
if (hazardFlag != set) if (hazardFlag != set)
{ {
// (un-)register hazard pointers // (un-)register hazard pointers
HazardDelayedDelete* hazardDelayed = nullptr;
if (list.hasData())
hazardDelayed = HazardBase::getHazardDelayed(tdbb);
for (auto r : list) for (auto r : list)
{ {
void* hazardPointer = nullptr; void* hazardPointer = nullptr;

View File

@ -34,6 +34,7 @@
#include "../jrd/blb.h" #include "../jrd/blb.h"
#include "../jrd/Relation.h" #include "../jrd/Relation.h"
#include "../jrd/CharSetContainer.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../jrd/MetaName.h" #include "../jrd/MetaName.h"
#include "../common/classes/fb_pair.h" #include "../common/classes/fb_pair.h"
@ -167,214 +168,96 @@ struct impure_agg_sort
}; };
// Resources list template <class OBJ> class CacheElement;
class ResourceList class Resources
{ {
typedef Firebird::SortedArray<Resource, Firebird::EmptyStorage<Resource>, public:
Resource, Firebird::DefaultKeyValue<Resource>, Resource> InternalResourceList; template <class OBJ>
class VersionedPtr
{
public:
CacheElement<OBJ>* ptr;
FB_SIZE_T versionedObject;
};
template <class OBJ>
class RscArray : public Firebird::Array<VersionedPtr<OBJ>>
{
public:
RscArray(MemoryPool& p)
: Firebird::Array<VersionedPtr<OBJ>>(p)
{ }
FB_SIZE_T registerResource(CacheElement<OBJ>* res)
{
FB_SIZE_T pos;
if (this->find([res](const VersionedPtr<OBJ>& elem) {
const void* p1 = elem.ptr;
const void* p2 = res;
return p1 < p2 ? -1 : p1 == p2 ? 0 : 1;
}, pos))
{
return pos;
}
VersionedPtr<OBJ> newPtr(res);
return this->append(newPtr);
}
};
public: public:
ResourceList(MemoryPool& p, bool hazard) template <class OBJ> const RscArray<OBJ>& objects() const;
: list(p), hazardFlag(hazard)
Resources(MemoryPool& p)
: charSets(p), relations(p), procedures(p), functions(p), triggers(p)
{ } { }
typedef Firebird::Bits<Resource::rsc_MAX> ResourceTypes; RscArray<CharSetContainer> charSets;
typedef Firebird::HalfStaticArray<FB_SIZE_T, 128> NewResources; RscArray<jrd_rel> relations;
RscArray<jrd_prc> procedures;
RscArray<Function> functions;
RscArray<Trigger> triggers;
};
~ResourceList() // specialization
template <> const Resources::RscArray<jrd_rel>& Resources::objects() const { return relations; }
template <class OBJ>
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<OBJ>();
return array[compileOffset]->ptr->getObject(tdbb);
} }
template <typename T> bool isSet() const;
T* registerResource(thread_db* tdbb, Resource::rsc_s type, const HazardPtr<T>& object, USHORT id) /*
operator OBJ*() const
{ {
fb_assert(type != Resource::rsc_index); return getPtr();
T* ptr = object.getPointer();
Resource r(type, id, ptr);
FB_SIZE_T pos;
if (!list.find(r, pos))
{
list.insert(pos, r);
HazardPtr<T>::getHazardDelayed(tdbb)->add(ptr, FB_FUNCTION);
}
return ptr;
} }
template <typename T> OBJ* operator->() const
void postResource(thread_db* tdbb, Resource::rsc_s type, T* ptr, USHORT id)
{ {
fb_assert(hazardFlag); return getPtr();
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 <typename T>
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);
} }
*/
private: private:
InternalResourceList list; FB_SIZE_T compileOffset;
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);
}; };
// Access items // Access items
// In case we start to use MetaName with required pool parameter, // In case we start to use MetaName with required pool parameter,
// access item to be reworked! // access item to be reworked!
@ -641,7 +524,7 @@ public:
mainCsb(aMainCsb), mainCsb(aMainCsb),
csb_external(p), csb_external(p),
csb_access(p), csb_access(p),
csb_resources(p, true), csb_resources(nullptr),
csb_dependencies(p), csb_dependencies(p),
csb_fors(p), csb_fors(p),
csb_localTables(p), csb_localTables(p),
@ -720,7 +603,7 @@ public:
ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked
AccessItemList csb_access; // Access items to be checked AccessItemList csb_access; // Access items to be checked
vec<DeclareVariableNode*>* csb_variables; // Vector of variables, if any vec<DeclareVariableNode*>* csb_variables; // Vector of variables, if any
ResourceList csb_resources; // Resources (relations and indexes) Resources* csb_resources; // Resources (relations, indexes, routines, etc.)
Firebird::Array<Dependency> csb_dependencies; // objects that this statement depends upon /// !!!!!!!!!!!!!!!!! Firebird::Array<Dependency> csb_dependencies; // objects that this statement depends upon /// !!!!!!!!!!!!!!!!!
Firebird::Array<const Select*> csb_fors; // select expressions Firebird::Array<const Select*> csb_fors; // select expressions
Firebird::Array<const DeclareLocalTableNode*> csb_localTables; // local tables Firebird::Array<const DeclareLocalTableNode*> csb_localTables; // local tables
@ -747,9 +630,9 @@ public:
MetaName csb_domain_validation; // Parsing domain constraint in PSQL MetaName csb_domain_validation; // Parsing domain constraint in PSQL
// used in cmp.cpp/pass1 // used in cmp.cpp/pass1
jrd_rel* csb_view; CachedResource<jrd_rel> csb_view;
StreamType csb_view_stream; StreamType csb_view_stream;
jrd_rel* csb_parent_relation; CachedResource<jrd_rel> csb_parent_relation;
unsigned blrVersion; unsigned blrVersion;
USHORT csb_remap_variable; USHORT csb_remap_variable;
bool csb_validate_expr; bool csb_validate_expr;
@ -783,10 +666,10 @@ public:
StreamType csb_view_stream; // stream number for view relation, below StreamType csb_view_stream; // stream number for view relation, below
USHORT csb_flags; USHORT csb_flags;
jrd_rel* csb_relation; CachedResource<jrd_rel> csb_relation;
Firebird::string* csb_alias; // SQL alias name for this instance of relation Firebird::string* csb_alias; // SQL alias name for this instance of relation
jrd_prc* csb_procedure; CachedResource<jrd_prc> csb_procedure;
jrd_rel* csb_view; // parent view CachedResource<jrd_rel> csb_view; // parent view
IndexDescList* csb_idx; // Packed description of indices IndexDescList* csb_idx; // Packed description of indices
MessageNode* csb_message; // Msg for send/receive MessageNode* csb_message; // Msg for send/receive

View File

@ -235,7 +235,7 @@ void EXT_erase(record_param*, jrd_tra*)
// Third param is unused. // Third param is unused.
ExternalFile* EXT_file(HazardPtr<jrd_rel>& relation, const TEXT* file_name) //, bid* description) ExternalFile* EXT_file(jrd_rel* relation, const TEXT* file_name) //, bid* description)
{ {
/************************************** /**************************************
* *

View File

@ -35,7 +35,7 @@ namespace Jrd {
double EXT_cardinality(Jrd::thread_db*, Jrd::jrd_rel*); double EXT_cardinality(Jrd::thread_db*, Jrd::jrd_rel*);
void EXT_erase(Jrd::record_param*, Jrd::jrd_tra*); void EXT_erase(Jrd::record_param*, Jrd::jrd_tra*);
Jrd::ExternalFile* EXT_file(Jrd::HazardPtr<Jrd::jrd_rel>&, const TEXT*); //, Jrd::bid*); Jrd::ExternalFile* EXT_file(Jrd::jrd_rel*, const TEXT*); //, Jrd::bid*);
void EXT_fini(Jrd::jrd_rel*, bool); void EXT_fini(Jrd::jrd_rel*, bool);
bool EXT_get(Jrd::thread_db*, Jrd::record_param*, FB_UINT64&); bool EXT_get(Jrd::thread_db*, Jrd::record_param*, FB_UINT64&);
void EXT_modify(Jrd::record_param*, Jrd::record_param*, Jrd::jrd_tra*); void EXT_modify(Jrd::record_param*, Jrd::record_param*, Jrd::jrd_tra*);

View File

@ -1738,7 +1738,7 @@ static idx_e check_foreign_key(thread_db* tdbb,
if (!MET_lookup_partner(tdbb, relation, idx, 0)) if (!MET_lookup_partner(tdbb, relation, idx, 0))
return result; return result;
HazardPtr<jrd_rel> partner_relation(tdbb, FB_FUNCTION); jrd_rel* partner_relation(tdbb);
USHORT index_id = 0; USHORT index_id = 0;
if (idx->idx_flags & idx_foreign) if (idx->idx_flags & idx_foreign)

View File

@ -973,7 +973,7 @@ void INI_init(thread_db* tdbb)
const auto id = relfld[RFLD_R_ID]; const auto id = relfld[RFLD_R_ID];
//fprintf(stderr, "INI_init %d %s\n", id, names[relfld[RFLD_R_NAME]]); //fprintf(stderr, "INI_init %d %s\n", id, names[relfld[RFLD_R_NAME]]);
HazardPtr<jrd_rel> relation = MetadataCache::findRelation(tdbb, id); jrd_rel* relation = MetadataCache::findRelation(tdbb, id);
if (id == 7) TRAP = relation.getPointer(); if (id == 7) TRAP = relation.getPointer();

View File

@ -169,24 +169,22 @@ HazardPtr<CharSetContainer> CharSetContainer::lookupCharset(thread_db* tdbb, USH
if (id == CS_dynamic) if (id == CS_dynamic)
id = tdbb->getCharSet(); id = tdbb->getCharSet();
HazardPtr<CharSetContainer> 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; CharSetContainer* csc = FB_NEW_POOL(*dbb->dbb_permanent) CharSetContainer(*dbb->dbb_permanent, id, &info);
dbb->dbb_mdc->setCharSet(tdbb, id, csc);
if (lookupInternalCharSet(id, &info) || MET_get_char_coll_subtype_info(tdbb, id, &info)) cs = dbb->dbb_mdc->getCharSet(tdbb, id);
{
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));
} }
else
return cs; 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()); return CsConvert(cs->getStruct(), toCs->getStruct());
} }
HazardPtr<Collation> 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); const USHORT id = TTYPE_TO_COLLATION(tt_id);
HazardPtr<Collation> coll(FB_FUNCTION); Collation* coll(FB_FUNCTION);
if (charset_collations.load(tdbb, id, coll)) if (charset_collations.load(tdbb, id, coll))
{ {
if (!coll->obsolete) if (!coll->obsolete)
@ -301,7 +299,7 @@ HazardPtr<Collation> CharSetContainer::lookupCollation(thread_db* tdbb, USHORT t
CheckoutLockGuard guard(tdbb, createCollationMtx, FB_FUNCTION); // do we need it ? CheckoutLockGuard guard(tdbb, createCollationMtx, FB_FUNCTION); // do we need it ?
HazardPtr<Collation> to_delete(FB_FUNCTION); Collation* to_delete(FB_FUNCTION);
if (charset_collations.load(tdbb, id, coll)) if (charset_collations.load(tdbb, id, coll))
{ {
if (!coll->obsolete) if (!coll->obsolete)
@ -404,7 +402,7 @@ void CharSetContainer::unloadCollation(thread_db* tdbb, USHORT tt_id)
const USHORT id = TTYPE_TO_COLLATION(tt_id); const USHORT id = TTYPE_TO_COLLATION(tt_id);
fb_assert(id != 0); fb_assert(id != 0);
HazardPtr<Collation> coll(FB_FUNCTION); Collation* coll(FB_FUNCTION);
if (charset_collations.load(tdbb, id, coll)) if (charset_collations.load(tdbb, id, coll))
{ {
MutexLockGuard g(tdbb->getDatabase()->dbb_mdc->mdc_use_mutex, FB_FUNCTION); 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++) for (FB_SIZE_T i = 0; i < mdc_charsets.getCount(tdbb); i++)
{ {
HazardPtr<CharSetContainer> cs(FB_FUNCTION); HazardPtr<CharSetContainer> cs;
if (mdc_charsets.load(tdbb, i, cs)) if (mdc_charsets.load(tdbb, i, cs))
{ {
cs->destroy(tdbb); cs->destroy(tdbb);
@ -996,7 +994,7 @@ CharSet* INTL_charset_lookup(thread_db* tdbb, USHORT parm1)
} }
HazardPtr<Collation> 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); outlen = (dest - pByte->dsc_address);
break; break;
default: default:
HazardPtr<Collation> 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)); 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); outlen = obj->string_to_key(len, src, pByte->dsc_length, dest, key_type);
break; break;

View File

@ -49,7 +49,7 @@ bool INTL_data_or_binary(const dsc*);
bool INTL_defined_type(Jrd::thread_db*, USHORT); bool INTL_defined_type(Jrd::thread_db*, USHORT);
USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT); USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT);
Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1); Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1);
Jrd::HazardPtr<Jrd::Collation> 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); void INTL_texttype_unload(Jrd::thread_db*, USHORT);
bool INTL_texttype_validate(Jrd::thread_db*, const SubtypeInfo*); bool INTL_texttype_validate(Jrd::thread_db*, const SubtypeInfo*);
void INTL_pad_spaces(Jrd::thread_db*, dsc*, UCHAR*, ULONG); void INTL_pad_spaces(Jrd::thread_db*, dsc*, UCHAR*, ULONG);

View File

@ -1732,7 +1732,7 @@ void ExistenceLock::internalObjectDelete(thread_db* tdbb, unsigned fl)
object->afterUnlock(tdbb, fl); object->afterUnlock(tdbb, fl);
if (!(fl & inCache)) 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);
}

View File

@ -256,7 +256,6 @@ public:
#endif #endif
void unlock(thread_db* tdbb); // Release exclusive lock void unlock(thread_db* tdbb); // Release exclusive lock
void releaseLock(thread_db* tdbb, ReleaseMethod rm); // Release any lock void releaseLock(thread_db* tdbb, ReleaseMethod rm); // Release any lock
void removeFromCache(thread_db* tdbb); // Invoked when object is removed from MDC
private: private:
static int ast(void* self) static int ast(void* self)

View File

@ -113,18 +113,18 @@ static int blocking_ast_dsql_cache(void* ast_object);
static int partners_ast_relation(void*); static int partners_ast_relation(void*);
static int rescan_ast_relation(void*); static int rescan_ast_relation(void*);
static ULONG get_rel_flags_from_FLAGS(USHORT); static ULONG get_rel_flags_from_FLAGS(USHORT);
static void get_trigger(thread_db*, HazardPtr<jrd_rel>&, 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<bool> ssDefiner); USHORT, const MetaName&, const string&, const bid*, Nullable<bool> ssDefiner);
static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*); static bool get_type(thread_db*, USHORT*, const UCHAR*, const TEXT*);
static void lookup_view_contexts(thread_db*, HazardPtr<jrd_rel>&); static void lookup_view_contexts(thread_db*, jrd_rel*);
static void make_relation_scope_name(const TEXT*, const USHORT, string& str); 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 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 BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, const MetaName name);
static void save_trigger_data(thread_db*, TrigVectorPtr*, HazardPtr<jrd_rel>&, 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 TEXT*, FB_UINT64, bool, USHORT, const MetaName&, const string&,
const bid*, Nullable<bool> ssDefiner); const bid*, Nullable<bool> ssDefiner);
static void scan_partners(thread_db*, jrd_rel*); static void scan_partners(thread_db*, jrd_rel*);
static void store_dependencies(thread_db*, Array<CompilerScratch::Dependency>&, HazardPtr<jrd_rel>&, static void store_dependencies(thread_db*, Array<CompilerScratch::Dependency>&, jrd_rel*,
const MetaName&, int, jrd_tra*); const MetaName&, int, jrd_tra*);
static bool verify_TRG_ignore_perm(thread_db*, const MetaName&); 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, DmlNode* MET_get_dependencies(thread_db* tdbb,
Jrd::HazardPtr<Jrd::jrd_rel>& relation, Jrd::jrd_rel* relation,
const UCHAR* blob, const UCHAR* blob,
const ULONG blob_length, const ULONG blob_length,
CompilerScratch* view_csb, CompilerScratch* view_csb,
@ -1583,12 +1583,6 @@ DmlNode* MET_get_dependencies(thread_db* tdbb,
} }
jrd_fld* MET_get_field(const Jrd::HazardPtr<Jrd::jrd_rel>& relation, USHORT id)
{
return MET_get_field(relation.getPointer(), id);
}
jrd_fld* MET_get_field(const jrd_rel* relation, USHORT 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 TRG.RDB$TRIGGER_INACTIVE EQ 0
SORTED BY TRG.RDB$TRIGGER_SEQUENCE 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 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) 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 END_FOR
@ -1803,7 +1797,7 @@ void MetadataCache::load_ddl_triggers(thread_db* tdbb)
void MET_load_trigger(thread_db* tdbb, void MET_load_trigger(thread_db* tdbb,
HazardPtr<jrd_rel>& relation, jrd_rel* relation,
const MetaName& trigger_name, const MetaName& trigger_name,
TrigVectorPtr* triggers) TrigVectorPtr* triggers)
{ {
@ -2409,7 +2403,7 @@ SLONG MetadataCache::lookup_index_name(thread_db* tdbb, const MetaName& index_na
*status = MET_object_inactive; *status = MET_object_inactive;
id = X.RDB$INDEX_ID - 1; id = X.RDB$INDEX_ID - 1;
HazardPtr<jrd_rel> relation = lookup_relation(tdbb, X.RDB$RELATION_NAME); jrd_rel* relation = lookup_relation(tdbb, X.RDB$RELATION_NAME);
*relation_id = relation->rel_id; *relation_id = relation->rel_id;
} }
END_FOR END_FOR
@ -2543,7 +2537,7 @@ void MET_lookup_index_expression(thread_db* tdbb, jrd_rel* relation, index_desc*
return; return;
} }
HazardPtr<jrd_rel> wrk = MET_scan_relation(tdbb, relation->rel_id); jrd_rel* wrk = MET_scan_relation(tdbb, relation->rel_id);
if (!wrk) if (!wrk)
{ {
(Arg::Gds(isc_random) << "Relation was deleted").raise(); (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 IND.RDB$UNIQUE_FLAG = 1
{ {
//// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved. //// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved.
HazardPtr<jrd_rel> foundRel(FB_FUNCTION); jrd_rel* foundRel = nullptr;
const jrd_rel* partner_relation = relation; const jrd_rel* partner_relation = relation;
if (relation->rel_name != IND.RDB$RELATION_NAME) if (relation->rel_name != IND.RDB$RELATION_NAME)
{ {
@ -2745,7 +2739,7 @@ HazardPtr<jrd_prc> MetadataCache::lookup_procedure(thread_db* tdbb, const Qualif
SET_TDBB(tdbb); SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment(); Attachment* attachment = tdbb->getAttachment();
MetadataCache* mdc = attachment->att_database->dbb_mdc; MetadataCache* mdc = attachment->att_database->dbb_mdc;
HazardPtr<jrd_prc> check_procedure(FB_FUNCTION); HazardPtr<jrd_prc> check_procedure;
// See if we already know the procedure by name // See if we already know the procedure by name
for (auto procedure : mdc->mdc_procedures.snapshot()) for (auto procedure : mdc->mdc_procedures.snapshot())
@ -2772,7 +2766,7 @@ HazardPtr<jrd_prc> MetadataCache::lookup_procedure(thread_db* tdbb, const Qualif
// We need to look up the procedure name in RDB$PROCEDURES // We need to look up the procedure name in RDB$PROCEDURES
HazardPtr<jrd_prc> procedure(FB_FUNCTION); HazardPtr<jrd_prc> procedure;
AutoCacheRequest request(tdbb, irq_l_procedure, IRQ_REQUESTS); AutoCacheRequest request(tdbb, irq_l_procedure, IRQ_REQUESTS);
@ -2815,7 +2809,7 @@ HazardPtr<jrd_prc> MetadataCache::lookup_procedure_id(thread_db* tdbb, USHORT id
SET_TDBB(tdbb); SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment(); Attachment* attachment = tdbb->getAttachment();
MetadataCache* mdc = attachment->att_database->dbb_mdc; MetadataCache* mdc = attachment->att_database->dbb_mdc;
HazardPtr<jrd_prc> check_procedure(FB_FUNCTION), procedure(FB_FUNCTION); HazardPtr<jrd_prc> check_procedure, procedure;
if (mdc->mdc_procedures.load(tdbb, id, procedure) && if (mdc->mdc_procedures.load(tdbb, id, procedure) &&
procedure->getId() == id && procedure->getId() == id &&
@ -2864,7 +2858,7 @@ HazardPtr<jrd_prc> MetadataCache::lookup_procedure_id(thread_db* tdbb, USHORT id
} }
HazardPtr<jrd_rel> 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<jrd_rel> MetadataCache::lookup_relation(thread_db* tdbb, const MetaNam
SET_TDBB(tdbb); SET_TDBB(tdbb);
Attachment* attachment = tdbb->getAttachment(); Attachment* attachment = tdbb->getAttachment();
MetadataCache* mdc = attachment->att_database->dbb_mdc; MetadataCache* mdc = attachment->att_database->dbb_mdc;
HazardPtr<jrd_rel> check_relation(FB_FUNCTION); jrd_rel* check_relation = nullptr;
// See if we already know the relation by name // See if we already know the relation by name
@ -2919,7 +2913,7 @@ HazardPtr<jrd_rel> MetadataCache::lookup_relation(thread_db* tdbb, const MetaNam
// We need to look up the relation name in RDB$RELATIONS // We need to look up the relation name in RDB$RELATIONS
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
AutoCacheRequest request(tdbb, irq_l_relation, IRQ_REQUESTS); AutoCacheRequest request(tdbb, irq_l_relation, IRQ_REQUESTS);
@ -2963,7 +2957,7 @@ HazardPtr<jrd_rel> MetadataCache::lookup_relation(thread_db* tdbb, const MetaNam
} }
HazardPtr<jrd_rel> 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<jrd_rel> MetadataCache::lookup_relation_id(thread_db* tdbb, SLONG id,
return findRelation(tdbb, (USHORT) id); return findRelation(tdbb, (USHORT) id);
} }
HazardPtr<jrd_rel> relation(FB_FUNCTION), check_relation(FB_FUNCTION); jrd_rel* relation = nullptr, check_relation = nullptr;
if (mdc->mdc_relations.load(tdbb, id, relation)) if (mdc->mdc_relations.load(tdbb, id, relation))
{ {
if (relation->rel_flags & REL_deleting) if (relation->rel_flags & REL_deleting)
@ -3076,7 +3070,7 @@ bool MetadataCache::checkRelation(thread_db* tdbb, jrd_rel* relation)
Attachment* const attachment = tdbb->getAttachment(); Attachment* const attachment = tdbb->getAttachment();
MetadataCache* mdc = attachment->att_database->dbb_mdc; MetadataCache* mdc = attachment->att_database->dbb_mdc;
HazardPtr<jrd_rel> check_relation(FB_FUNCTION); jrd_rel* check_relation = nullptr;
if ((!mdc->mdc_relations.load(tdbb, relation->rel_id, check_relation)) || if ((!mdc->mdc_relations.load(tdbb, relation->rel_id, check_relation)) ||
(relation != 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, DmlNode* MET_parse_blob(thread_db* tdbb,
Jrd::HazardPtr<Jrd::jrd_rel>& relation, Jrd::jrd_rel* relation,
bid* blob_id, bid* blob_id,
CompilerScratch** csb_ptr, CompilerScratch** csb_ptr,
Statement** statementPtr, Statement** statementPtr,
@ -3153,7 +3147,7 @@ DmlNode* MET_parse_blob(thread_db* tdbb,
} }
void MET_parse_sys_trigger(thread_db* tdbb, HazardPtr<jrd_rel>& relation) void MET_parse_sys_trigger(thread_db* tdbb, jrd_rel* relation)
{ {
/************************************** /**************************************
* *
@ -3313,7 +3307,7 @@ HazardPtr<jrd_prc> MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool
if (id >= mdc->mdc_procedures.getCount(tdbb)) if (id >= mdc->mdc_procedures.getCount(tdbb))
mdc->mdc_procedures.grow(tdbb, id + 10); mdc->mdc_procedures.grow(tdbb, id + 10);
HazardPtr<jrd_prc> procedure(FB_FUNCTION); HazardPtr<jrd_prc> procedure;
if (mdc->mdc_procedures.load(tdbb, id, procedure) && !(procedure->flags & Routine::FLAG_OBSOLETE)) if (mdc->mdc_procedures.load(tdbb, id, procedure) && !(procedure->flags & Routine::FLAG_OBSOLETE))
{ {
@ -3356,42 +3350,18 @@ HazardPtr<jrd_prc> 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 { 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); AutoCacheRequest request(tdbb, irq_r_procedure, IRQ_REQUESTS);
FOR(REQUEST_HANDLE request) FOR(REQUEST_HANDLE request)
@ -3503,7 +3473,7 @@ HazardPtr<jrd_prc> MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool
try try
{ {
parameter->prm_default_value = static_cast<ValueExprNode*>( parameter->prm_default_value = static_cast<ValueExprNode*>(
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&) catch (const Exception&)
{ {
@ -3639,29 +3609,16 @@ HazardPtr<jrd_prc> MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool
} }
} }
END_FOR 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 } // try
catch (const Exception&) catch (const Exception&)
{ {
if (newProcedure->getExternal()) jrd_prc::destroy(newProcedure);
{
delete newProcedure->getExternal();
newProcedure->setExternal(NULL);
}
newProcedure->flags &= ~Routine::FLAG_BEING_SCANNED;
newProcedure->startup.open();
throw; throw;
} }
return procedure; return newProcedure;
} }
bool jrd_prc::reload(thread_db* tdbb) bool jrd_prc::reload(thread_db* tdbb)
@ -3710,7 +3667,7 @@ bool jrd_prc::reload(thread_db* tdbb)
return false; return false;
} }
HazardPtr<jrd_rel> MetadataCache::findRelation(thread_db* tdbb, USHORT id) jrd_rel* MetadataCache::findRelation(thread_db* tdbb, USHORT id)
{ {
/************************************** /**************************************
* *
@ -3730,7 +3687,7 @@ HazardPtr<jrd_rel> MetadataCache::findRelation(thread_db* tdbb, USHORT id)
MetadataCache* mdc = dbb->dbb_mdc; MetadataCache* mdc = dbb->dbb_mdc;
MemoryPool& pool = mdc->getPool(); MemoryPool& pool = mdc->getPool();
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
if (mdc->mdc_relations.load(tdbb, id, relation)) if (mdc->mdc_relations.load(tdbb, id, relation))
return relation; return relation;
@ -3838,9 +3795,9 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation)
} }
HazardPtr<jrd_rel> MET_scan_relation(thread_db* tdbb, USHORT id) jrd_rel* MET_scan_relation(thread_db* tdbb, USHORT id)
{ {
HazardPtr<jrd_rel> 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) || if (relation && (!(relation->rel_flags & REL_scanned) ||
(relation->rel_flags & REL_being_scanned))) (relation->rel_flags & REL_being_scanned)))
@ -3851,7 +3808,7 @@ HazardPtr<jrd_rel> MET_scan_relation(thread_db* tdbb, USHORT id)
return relation; return relation;
} }
void MET_scan_relation(thread_db* tdbb, HazardPtr<Jrd::jrd_rel>& relation) void jrd_rel::scan(thread_db* tdbb)
{ {
/************************************** /**************************************
* *
@ -4070,7 +4027,7 @@ void MET_scan_relation(thread_db* tdbb, HazardPtr<Jrd::jrd_rel>& relation)
csb->csb_g_flags |= csb_get_dependencies; csb->csb_g_flags |= csb_get_dependencies;
field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p); field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p);
const MetaName depName(REL.RDB$RELATION_NAME); 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 else
field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p); 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<jrd_rel>& relation, static void get_trigger(thread_db* tdbb, jrd_rel* relation,
bid* blob_id, bid* debug_blob_id, TrigVectorPtr* ptr, bid* blob_id, bid* debug_blob_id, TrigVectorPtr* ptr,
const TEXT* name, FB_UINT64 type, const TEXT* name, FB_UINT64 type,
bool sys_trigger, USHORT flags, 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<jrd_rel>& 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); 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<ValueExprNode*>(node); return static_cast<ValueExprNode*>(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); 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; return;
SET_TDBB(tdbb); SET_TDBB(tdbb);
HazardPtr<Trigger> trigger(FB_FUNCTION); HazardPtr<Trigger> trigger;
SLONG n = vector->load()->lookup(tdbb, name, &trigger); SLONG n = vector->load()->lookup(tdbb, name, &trigger);
if (n < 0) if (n < 0)
return; 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<jrd_rel>& relation, static void save_trigger_data(thread_db* tdbb, TrigVectorPtr* ptr, jrd_rel* relation,
Statement* statement, blb* blrBlob, blb* debugInfoBlob, Statement* statement, blb* blrBlob, blb* debugInfoBlob,
const TEXT* name, FB_UINT64 type, const TEXT* name, FB_UINT64 type,
bool sys_trigger, USHORT flags, bool sys_trigger, USHORT flags,
@ -4960,7 +4917,7 @@ HazardPtr<const Trigger> findTrigger(TrigVector* triggers, const MetaName& trig_
} }
} }
return HazardPtr<const Trigger>(FB_FUNCTION); return HazardPtr<const Trigger>;
} }
@ -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. //// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved.
const jrd_rel* partner_relation = relation; const jrd_rel* partner_relation = relation;
HazardPtr<jrd_rel> rel(FB_FUNCTION); jrd_rel* rel = nullptr;
if (relation->rel_name != IND.RDB$RELATION_NAME) if (relation->rel_name != IND.RDB$RELATION_NAME)
{ {
rel = MetadataCache::lookup_relation(tdbb, 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. //// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved.
const jrd_rel* partner_relation = relation; const jrd_rel* partner_relation = relation;
HazardPtr<jrd_rel> rel(FB_FUNCTION); jrd_rel* rel = nullptr;
if (relation->rel_name != IND.RDB$RELATION_NAME) if (relation->rel_name != IND.RDB$RELATION_NAME)
{ {
rel = MetadataCache::lookup_relation(tdbb, 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, static void store_dependencies(thread_db* tdbb,
Array<CompilerScratch::Dependency>& dependencies, Array<CompilerScratch::Dependency>& dependencies,
HazardPtr<jrd_rel>& dep_rel, jrd_rel* dep_rel,
const MetaName& object_name, const MetaName& object_name,
int dependency_type, int dependency_type,
jrd_tra* transaction) jrd_tra* transaction)
@ -5145,7 +5102,7 @@ static void store_dependencies(thread_db* tdbb,
SET_TDBB(tdbb); SET_TDBB(tdbb);
HazardPtr<const Trigger> t(FB_FUNCTION); HazardPtr<const Trigger> t;
const bool checkTableScope = const bool checkTableScope =
(dependency_type == obj_computed) || (dependency_type == obj_computed) ||
(dependency_type == obj_trigger) && dep_rel && (dependency_type == obj_trigger) && dep_rel &&
@ -5169,7 +5126,7 @@ static void store_dependencies(thread_db* tdbb,
} }
int dpdo_type = dependency.objType; int dpdo_type = dependency.objType;
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation = nullptr;
const jrd_prc* procedure = NULL; const jrd_prc* procedure = NULL;
const MetaName* dpdo_name = NULL; const MetaName* dpdo_name = NULL;
MetaName packageName; MetaName packageName;
@ -5534,13 +5491,13 @@ void MetadataCache::releaseRelations(thread_db* tdbb)
{ {
for (FB_SIZE_T n = 0; n < mdc_relations.getCount(tdbb); ++n) for (FB_SIZE_T n = 0; n < mdc_relations.getCount(tdbb); ++n)
{ {
HazardPtr<jrd_rel> relation(tdbb, FB_FUNCTION); jrd_rel* relation = nullptr;
if (mdc_relations.load(tdbb, n, relation)) if (mdc_relations.load(tdbb, n, relation))
{ {
if (relation->rel_file) if (relation->rel_file)
EXT_fini(relation.getPointer(), false); EXT_fini(relation.getPointer(), false);
relation->delayedDelete(tdbb); delete relation;
} }
} }
// ??????? mdc_relations.clear(); // ??????? mdc_relations.clear();
@ -5620,7 +5577,7 @@ void MetadataCache::invalidateReplSet(thread_db* tdbb)
} }
} }
HazardPtr<Function> 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()) for (auto function : mdc_functions.snapshot())
{ {
@ -5631,19 +5588,19 @@ HazardPtr<Function> MetadataCache::lookupFunction(thread_db* tdbb, const Qualifi
} }
} }
return HazardPtr<Function>(FB_FUNCTION); return nullptr;
} }
HazardPtr<jrd_rel> MetadataCache::getRelation(thread_db* tdbb, ULONG rel_id) jrd_rel* MetadataCache::getRelation(thread_db* tdbb, ULONG rel_id)
{ {
HazardPtr<jrd_rel> rc(tdbb, FB_FUNCTION); jrd_rel* rc(tdbb);
mdc_relations.load(tdbb, rel_id, rc); mdc_relations.load(tdbb, rel_id, rc);
return rc; return rc;
} }
HazardPtr<jrd_rel> MetadataCache::getRelation(Attachment* att, ULONG rel_id) jrd_rel* MetadataCache::getRelation(Attachment* att, ULONG rel_id)
{ {
HazardPtr<jrd_rel> rc(att, FB_FUNCTION); HazardPtr<jrd_rel> rc(att);
mdc_relations.load(att, rel_id, rc); mdc_relations.load(att, rel_id, rc);
return rc; return rc;
} }
@ -5713,7 +5670,7 @@ void Trigger::compile(thread_db* tdbb)
*csb->csb_dbg_info); *csb->csb_dbg_info);
} }
HazardPtr<jrd_rel> rel = MetadataCache::findRelation(tdbb, relation->rel_id); jrd_rel* rel = MetadataCache::findRelation(tdbb, relation->rel_id);
if (!rel) if (!rel)
fatal_exception::raiseFmt("Relation %s unexpectedly lost", relation->rel_name); fatal_exception::raiseFmt("Relation %s unexpectedly lost", relation->rel_name);
@ -5777,7 +5734,7 @@ int Trigger::release(thread_db* tdbb)
statement->release(tdbb); statement->release(tdbb);
statement = NULL; statement = NULL;
delayedDelete(tdbb); retire();
return 0; return 0;
} }
*/ */
@ -5887,3 +5844,47 @@ void Trigger::release(thread_db* tdbb)
statement = NULL; statement = NULL;
} }
CacheElement<jrd_rel>* 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<jrd_rel>* 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<jrd_prc>* 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<jrd_prc>* 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;
}

File diff suppressed because it is too large Load Diff

View File

@ -74,17 +74,16 @@ void MET_delete_shadow(Jrd::thread_db*, USHORT);
void MET_error(const TEXT*, ...); void MET_error(const TEXT*, ...);
Jrd::Format* MET_format(Jrd::thread_db*, Jrd::jrd_rel*, USHORT); Jrd::Format* MET_format(Jrd::thread_db*, Jrd::jrd_rel*, USHORT);
bool MET_get_char_coll_subtype_info(Jrd::thread_db*, USHORT, SubtypeInfo* info); bool MET_get_char_coll_subtype_info(Jrd::thread_db*, USHORT, SubtypeInfo* info);
Jrd::DmlNode* MET_get_dependencies(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&, 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*, Jrd::bid*, Jrd::Statement**,
Jrd::CompilerScratch**, const Jrd::MetaName&, int, USHORT, Jrd::CompilerScratch**, const Jrd::MetaName&, int, USHORT,
Jrd::jrd_tra*, const Jrd::MetaName& = Jrd::MetaName()); Jrd::jrd_tra*, const Jrd::MetaName& = Jrd::MetaName());
Jrd::jrd_fld* MET_get_field(const Jrd::HazardPtr<Jrd::jrd_rel>&, USHORT);
Jrd::jrd_fld* MET_get_field(const Jrd::jrd_rel*, USHORT); Jrd::jrd_fld* MET_get_field(const Jrd::jrd_rel*, USHORT);
ULONG MET_get_rel_flags_from_TYPE(USHORT); ULONG MET_get_rel_flags_from_TYPE(USHORT);
bool MET_get_repl_state(Jrd::thread_db*, const Jrd::MetaName&); bool MET_get_repl_state(Jrd::thread_db*, const Jrd::MetaName&);
void MET_get_shadow_files(Jrd::thread_db*, bool); void MET_get_shadow_files(Jrd::thread_db*, bool);
bool MET_load_exception(Jrd::thread_db*, Jrd::ExceptionItem&); bool MET_load_exception(Jrd::thread_db*, Jrd::ExceptionItem&);
void MET_load_trigger(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&, 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_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_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*); 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_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*); 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); 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::jrd_rel>&, Jrd::bid*, Jrd::CompilerScratch**, Jrd::DmlNode* MET_parse_blob(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::bid*, Jrd::CompilerScratch**,
Jrd::Statement**, bool, bool); Jrd::Statement**, bool, bool);
void MET_parse_sys_trigger(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&); 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_prepare(Jrd::thread_db*, Jrd::jrd_tra*, USHORT, const UCHAR*);
void MET_release_existence(Jrd::thread_db*, Jrd::jrd_rel*); void MET_release_existence(Jrd::thread_db*, Jrd::jrd_rel*);
void MET_release_trigger(Jrd::thread_db*, Jrd::TrigVectorPtr*, const Jrd::MetaName&); 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&, void MET_revoke(Jrd::thread_db*, Jrd::jrd_tra*, const Jrd::MetaName&,
const Jrd::MetaName&, const Firebird::string&); const Jrd::MetaName&, const Firebird::string&);
void MET_scan_partners(Jrd::thread_db*, Jrd::jrd_rel*); void MET_scan_partners(Jrd::thread_db*, Jrd::jrd_rel*);
Jrd::HazardPtr<Jrd::jrd_rel> MET_scan_relation(Jrd::thread_db*, USHORT); void MET_scan_relation(Jrd::thread_db*, Jrd::jrd_rel*&);
void MET_scan_relation(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&);
void MET_trigger_msg(Jrd::thread_db*, Firebird::string&, const Jrd::MetaName&, USHORT); 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_shadow(Jrd::thread_db*, Jrd::Shadow*, USHORT);
void MET_update_transaction(Jrd::thread_db*, Jrd::jrd_tra*, const bool); void MET_update_transaction(Jrd::thread_db*, Jrd::jrd_tra*, const bool);

View File

@ -1122,7 +1122,7 @@ void PAG_header(thread_db* tdbb, bool info)
if (header->hdr_flags & hdr_SQL_dialect_3) if (header->hdr_flags & hdr_SQL_dialect_3)
dbb->dbb_flags |= DBB_DB_SQL_dialect_3; dbb->dbb_flags |= DBB_DB_SQL_dialect_3;
HazardPtr<jrd_rel> relation = MetadataCache::findRelation(tdbb, 0); jrd_rel* relation = MetadataCache::findRelation(tdbb, 0);
RelationPages* relPages = relation->getBasePages(); RelationPages* relPages = relation->getBasePages();
if (!relPages->rel_pages) if (!relPages->rel_pages)
{ {

View File

@ -89,7 +89,7 @@ namespace
class BlrParseWrapper class BlrParseWrapper
{ {
public: public:
BlrParseWrapper(thread_db* tdbb, MemoryPool& pool, HazardPtr<jrd_rel>& relation, CompilerScratch* view_csb, BlrParseWrapper(thread_db* tdbb, MemoryPool& pool, jrd_rel* relation, CompilerScratch* view_csb,
CompilerScratch** csb_ptr, const bool trigger, USHORT flags) CompilerScratch** csb_ptr, const bool trigger, USHORT flags)
: m_csbPtr(csb_ptr) : m_csbPtr(csb_ptr)
{ {
@ -171,7 +171,7 @@ namespace
// Parse blr, returning a compiler scratch block with the results. // Parse blr, returning a compiler scratch block with the results.
// Caller must do pool handling. // Caller must do pool handling.
DmlNode* PAR_blr(thread_db* tdbb, HazardPtr<jrd_rel>& 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, CompilerScratch* view_csb, CompilerScratch** csb_ptr, Statement** statementPtr,
const bool trigger, USHORT flags) const bool trigger, USHORT flags)
{ {
@ -204,7 +204,7 @@ DmlNode* PAR_blr(thread_db* tdbb, HazardPtr<jrd_rel>& relation, const UCHAR* blr
// Finish parse of memory nodes, returning a compiler scratch block with the results. // Finish parse of memory nodes, returning a compiler scratch block with the results.
// Caller must do pool handling. // Caller must do pool handling.
// !!!!!!!!!!!!!!! FixMe - pool handling in ExtEngineManager.cpp // !!!!!!!!!!!!!!! FixMe - pool handling in ExtEngineManager.cpp
void PAR_preparsed_node(thread_db* tdbb, HazardPtr<jrd_rel>& relation, DmlNode* node, void PAR_preparsed_node(thread_db* tdbb, jrd_rel* relation, DmlNode* node,
CompilerScratch* view_csb, CompilerScratch** csb_ptr, Statement** statementPtr, CompilerScratch* view_csb, CompilerScratch** csb_ptr, Statement** statementPtr,
const bool trigger, USHORT flags) const bool trigger, USHORT flags)
{ {
@ -220,7 +220,7 @@ void PAR_preparsed_node(thread_db* tdbb, HazardPtr<jrd_rel>& relation, DmlNode*
// PAR_blr equivalent for validation expressions. // PAR_blr equivalent for validation expressions.
// Validation expressions are boolean expressions, but may be prefixed with a blr_stmt_expr. // Validation expressions are boolean expressions, but may be prefixed with a blr_stmt_expr.
BoolExprNode* PAR_validation_blr(thread_db* tdbb, HazardPtr<jrd_rel>& 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) CompilerScratch* view_csb, CompilerScratch** csb_ptr, USHORT flags)
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);
@ -545,7 +545,7 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
if (csb->collectingDependencies()) if (csb->collectingDependencies())
{ {
CompilerScratch::Dependency dependency(obj_relation); CompilerScratch::Dependency dependency(obj_relation);
HazardPtr<jrd_rel> 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.relation = csb->csb_resources.registerResource(tdbb, Resource::rsc_relation, rel, rel->rel_id);
dependency.subName = fieldName; dependency.subName = fieldName;
csb->addDependency(dependency); csb->addDependency(dependency);

View File

@ -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*, USHORT, USHORT);
Jrd::ValueListNode* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*); Jrd::ValueListNode* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*);
Jrd::DmlNode* PAR_blr(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&, 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); Jrd::CompilerScratch*, Jrd::CompilerScratch**, Jrd::Statement**, const bool, USHORT);
void PAR_preparsed_node(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&, Jrd::DmlNode*, void PAR_preparsed_node(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::DmlNode*,
Jrd::CompilerScratch*, Jrd::CompilerScratch**, Jrd::Statement**, const bool, USHORT); Jrd::CompilerScratch*, Jrd::CompilerScratch**, Jrd::Statement**, const bool, USHORT);
Jrd::BoolExprNode* PAR_validation_blr(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&, 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); ULONG blr_length, Jrd::CompilerScratch*, Jrd::CompilerScratch**, USHORT);
StreamType PAR_context(Jrd::CompilerScratch*, SSHORT*); StreamType PAR_context(Jrd::CompilerScratch*, SSHORT*);
void PAR_dependency(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, StreamType stream, void PAR_dependency(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, StreamType stream,

View File

@ -161,6 +161,39 @@ private:
int modifiedRows; int modifiedRows;
}; };
// Set of objects cached per particular MDC version
class CacheObject;
class VersionedObjects : public pool_alloc_rpt<CacheObject*>,
public Firebird::RefCounted
{
public:
VersionedObjects(FB_SIZE_T cnt, MdcVersion ver);
FB_SIZE_T push(CacheObject* obj);
template <class OBJ>
OBJ* get(FB_SIZE_T n)
{
fb_assert(count == capacity);
fb_assert(n < count);
// ????? fb_assert(dynamic_cast<OBJ*>(data[n]));
return reinterpret_cast<OBJ*>(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 // request block
class Request : public pool_alloc<type_req> class Request : public pool_alloc<type_req>
@ -302,31 +335,7 @@ private:
}; };
public: public:
Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement) 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();
}
Statement* getStatement() Statement* getStatement()
{ {
@ -345,7 +354,6 @@ public:
void setAttachment(Attachment* newAttachment) void setAttachment(Attachment* newAttachment)
{ {
req_attachment = newAttachment; req_attachment = newAttachment;
charSetId = hasInternalStatement() ? CS_METADATA : req_attachment->att_charset;
} }
bool isRoot() const; bool isRoot() const;
@ -362,6 +370,9 @@ public:
req_id = id; req_id = id;
} }
void setUsed(bool inUse);
bool isUsed();
private: private:
Statement* const statement; Statement* const statement;
mutable StmtNumber req_id; // request identifier mutable StmtNumber req_id; // request identifier
@ -505,6 +516,9 @@ public:
{ {
req_timeStampCache.validate(req_attachment->att_current_timezone); req_timeStampCache.validate(req_attachment->att_current_timezone);
} }
private:
Firebird::RefPtr<VersionedObjects> currentVersion;
}; };
// Flags for req_flags // Flags for req_flags
@ -515,7 +529,7 @@ const ULONG req_null = 0x8L;
const ULONG req_abort = 0x10L; const ULONG req_abort = 0x10L;
const ULONG req_error_handler = 0x20L; // looper is called to handle error const ULONG req_error_handler = 0x20L; // looper is called to handle error
const ULONG req_warning = 0x40L; 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_continue_loop = 0x100L; // PSQL continue statement
const ULONG req_proc_fetch = 0x200L; // Fetch from procedure in progress const ULONG req_proc_fetch = 0x200L; // Fetch from procedure in progress
const ULONG req_same_tx_upd = 0x400L; // record was updated by same transaction const ULONG req_same_tx_upd = 0x400L; // record was updated by same transaction

View File

@ -907,7 +907,7 @@ SecurityClass::flags_t SCL_get_mask(thread_db* tdbb, const TEXT* relation_name,
SecurityClass::flags_t access = ~0; SecurityClass::flags_t access = ~0;
// If there's a relation, track it down // If there's a relation, track it down
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation;
if (relation_name && (relation = MetadataCache::lookup_relation(tdbb, relation_name))) if (relation_name && (relation = MetadataCache::lookup_relation(tdbb, relation_name)))
{ {
MET_scan_relation(tdbb, relation); MET_scan_relation(tdbb, relation);

View File

@ -94,7 +94,7 @@ static TraNumber bump_transaction_id(thread_db*, WIN*);
static header_page* bump_transaction_id(thread_db*, WIN*, bool); static header_page* bump_transaction_id(thread_db*, WIN*, bool);
#endif #endif
static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, int state); 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<jrd_rel>&, 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); 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 tx_inv_page* fetch_inventory_page(thread_db*, WIN* window, ULONG sequence, USHORT lock_level);
static const char* get_lockname_v3(const UCHAR lock); 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 * This guarantees that the relation/procedure/collation won't be dropped
* out from under the transaction. * out from under the transaction.
* *
**************************************/ **************************************
SET_TDBB(tdbb); SET_TDBB(tdbb); !!!!!!!!!!!!!!!!!!!!!
Jrd::ContextPoolHolder context(tdbb, transaction->tra_pool); 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()) if (!newRsc.hasData())
return; return;
*/
// !!!!!!!!!!!!! solve EXT_tra_attach problem - where to place references
MutexLockGuard g(tdbb->getDatabase()->dbb_mdc->mdc_use_mutex, FB_FUNCTION); 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 // Care about used external files
// !!!!!!!!!!!!! solve EXT_tra_attach problem - where to place references
/*
for (auto rsc : transaction->tra_resources.getObjects(Resource::rsc_relation)) for (auto rsc : transaction->tra_resources.getObjects(Resource::rsc_relation))
{ {
if (rsc->rsc_state == Resource::State::Extra) 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; rsc->rsc_state = Resource::State::Locked;
} }
} }
*/
// Release interest in relation/procedure existence for transaction // Release interest in relation/procedure existence for transaction
transaction->tra_resources.releaseResources(tdbb, 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 #endif
static void expand_view_lock(thread_db* tdbb, jrd_tra* transaction, HazardPtr<jrd_rel>& 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) 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, HazardPtr<jr
if (ctx[i]->vcx_type == VCT_PROCEDURE) if (ctx[i]->vcx_type == VCT_PROCEDURE)
continue; continue;
HazardPtr<jrd_rel> 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) if (!base_rel)
{ {
// should be a BUGCHECK // 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++) for (FB_SIZE_T i = 0; i < mdc->relCount(tdbb); i++)
{ {
HazardPtr<jrd_rel> relation = mdc->getRelation(tdbb, i); jrd_rel* relation = mdc->getRelation(tdbb, i);
if (relation && (relation->rel_flags & REL_temp_tran)) if (relation && (relation->rel_flags & REL_temp_tran))
relation->delPages(tdbb, transaction->tra_number); 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++) for (FB_SIZE_T i = 0; i < mdc->relCount(tdbb); i++)
{ {
HazardPtr<jrd_rel> relation = mdc->getRelation(tdbb, i); jrd_rel* relation = mdc->getRelation(tdbb, i);
if (relation && (relation->rel_flags & REL_temp_tran)) if (relation && (relation->rel_flags & REL_temp_tran))
relation->retainPages(tdbb, transaction->tra_number, new_number); 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); const MetaName metaName = attachment->nameToMetaCharSet(tdbb, orgName);
tpb += len; tpb += len;
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation(tdbb, metaName); jrd_rel* relation = MetadataCache::lookup_relation(tdbb, metaName);
if (!relation) if (!relation)
{ {
ERR_post(Arg::Gds(isc_bad_tpb_content) << ERR_post(Arg::Gds(isc_bad_tpb_content) <<
@ -3781,7 +3787,7 @@ jrd_tra::~jrd_tra()
delete tra_sec_db_context; 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)) !tra_fetched_blobs.locate(*blob_id))
{ {
MetadataCache* mdc = tra_attachment->att_database->dbb_mdc; MetadataCache* mdc = tra_attachment->att_database->dbb_mdc;
HazardPtr<jrd_rel> blobRelation = mdc->getRelation(tdbb, rel_id); jrd_rel* blobRelation = mdc->getRelation(tdbb, rel_id);
if (blobRelation) if (blobRelation)
{ {
@ -4176,7 +4182,7 @@ TraceSweepEvent::~TraceSweepEvent()
} }
void TraceSweepEvent::beginSweepRelation(const HazardPtr<jrd_rel>& relation) void TraceSweepEvent::beginSweepRelation(const jrd_rel* relation)
{ {
if (!m_need_trace) if (!m_need_trace)
return; return;

View File

@ -178,7 +178,7 @@ public:
tra_blob_util_map(*p), tra_blob_util_map(*p),
tra_arrays(NULL), tra_arrays(NULL),
tra_deferred_job(NULL), tra_deferred_job(NULL),
tra_resources(*p, false), // tra_resources(*p, false),
tra_context_vars(*p), tra_context_vars(*p),
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT), tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
tra_timestamp(Firebird::TimeZoneUtil::getCurrentSystemTimeStamp()), tra_timestamp(Firebird::TimeZoneUtil::getCurrentSystemTimeStamp()),
@ -282,7 +282,7 @@ public:
SavNumber tra_save_point_number; // next save point number to use SavNumber tra_save_point_number; // next save point number to use
ULONG tra_flags; ULONG tra_flags;
DeferredJob* tra_deferred_job; // work deferred to commit time 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 Firebird::StringMap tra_context_vars; // Context variables for the transaction
traRpbList* tra_rpblist; // active record_param's of given transaction traRpbList* tra_rpblist; // active record_param's of given transaction
UCHAR tra_use_count; // use count for safe AST delivery UCHAR tra_use_count; // use count for safe AST delivery

View File

@ -30,6 +30,8 @@ namespace Jrd {
class Attachment; class Attachment;
class Database; class Database;
class TraceTransactionEnd; class TraceTransactionEnd;
class ResourceList;
} }
bool TRA_active_transactions(Jrd::thread_db* tdbb, Jrd::Database*); 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_invalidate(Jrd::thread_db* tdbb, ULONG);
void TRA_link_cursor(Jrd::jrd_tra*, Jrd::DsqlCursor*); void TRA_link_cursor(Jrd::jrd_tra*, Jrd::DsqlCursor*);
void TRA_unlink_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&); void TRA_post_resources(Jrd::thread_db* tdbb, Jrd::jrd_tra*, Jrd::ResourceList&);
bool TRA_is_active(Jrd::thread_db*, TraNumber); bool TRA_is_active(Jrd::thread_db*, TraNumber);
void TRA_prepare(Jrd::thread_db* tdbb, Jrd::jrd_tra*, USHORT, const UCHAR*); 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); Jrd::jrd_tra* TRA_reconnect(Jrd::thread_db* tdbb, const UCHAR*, USHORT);

View File

@ -507,7 +507,7 @@ public:
m_sweep_info.update(header); m_sweep_info.update(header);
} }
void beginSweepRelation(const HazardPtr<jrd_rel>& relation); void beginSweepRelation(const jrd_rel* relation);
void endSweepRelation(); void endSweepRelation();
void finish() void finish()

View File

@ -1629,13 +1629,13 @@ void Validation::walk_database()
} }
MetadataCache* mdc = dbb->dbb_mdc; 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 #ifdef DEBUG_VAL_VERBOSE
if (i > dbb->dbb_max_sys_rel) // Why not system flag instead? if (i > dbb->dbb_max_sys_rel) // Why not system flag instead?
VAL_debug_level = 2; VAL_debug_level = 2;
#endif #endif
HazardPtr<jrd_rel> relation = mdc->getRelation(vdr_tdbb, i); jrd_rel* relation = mdc->getRelation(vdr_tdbb, i);
ExistenceGuard g(vdr_tdbb, relation->rel_existence_lock); ExistenceGuard g(vdr_tdbb, relation->rel_existence_lock);
if (MetadataCache::checkRelation(vdr_tdbb, relation.getPointer())) if (MetadataCache::checkRelation(vdr_tdbb, relation.getPointer()))
@ -3005,7 +3005,7 @@ void Validation::checkDPinPIP(jrd_rel* relation, ULONG page_number)
release_page(&pip_window); release_page(&pip_window);
} }
Validation::RTN Validation::walk_relation(HazardPtr<jrd_rel>& rel) Validation::RTN Validation::walk_relation(jrd_rel* rel)
{ {
/************************************** /**************************************
* *

View File

@ -218,7 +218,7 @@ private:
void walk_pip(); void walk_pip();
RTN walk_pointer_page(jrd_rel*, ULONG); RTN walk_pointer_page(jrd_rel*, ULONG);
RTN walk_record(jrd_rel*, const Ods::rhd*, USHORT, RecordNumber, bool); RTN walk_record(jrd_rel*, const Ods::rhd*, USHORT, RecordNumber, bool);
RTN walk_relation(HazardPtr<jrd_rel>&); RTN walk_relation(jrd_rel*);
RTN walk_root(jrd_rel*, bool); RTN walk_root(jrd_rel*, bool);
RTN walk_scns(); RTN walk_scns();
RTN walk_tip(TraNumber); RTN walk_tip(TraNumber);

View File

@ -2002,8 +2002,8 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
if (needDfw(tdbb, transaction)) if (needDfw(tdbb, transaction))
{ {
HazardPtr<jrd_rel> r2(FB_FUNCTION); jrd_rel* r2;
HazardPtr<jrd_prc> procedure(FB_FUNCTION); HazardPtr<jrd_prc> procedure;
USHORT id; USHORT id;
DeferredWork* work; 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); EVL_field(0, rpb->rpb_record, f_rel_name, &desc);
DFW_post_work(transaction, dfw_delete_relation, &desc, id); DFW_post_work(transaction, dfw_delete_relation, &desc, id);
HazardPtr<jrd_rel> rel_drop = MetadataCache::lookup_relation_id(tdbb, id, false); jrd_rel* rel_drop = MetadataCache::lookup_relation_id(tdbb, id, false);
if (rel_drop) if (rel_drop)
MET_scan_relation(tdbb, 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; MetaName index_name;
MOV_get_metaname(tdbb, &desc3, index_name); MOV_get_metaname(tdbb, &desc3, index_name);
HazardPtr<jrd_rel> partner(FB_FUNCTION); jrd_rel* partner;
index_desc idx; index_desc idx;
if ((BTR_lookup(tdbb, r2.getPointer(), id - 1, &idx, r2->getBasePages())) && 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 // hvlad: restore tdbb->transaction since it can be used later
tdbb->setTransaction(transaction); tdbb->setTransaction(transaction);
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation;
record_param rpb; record_param rpb;
rpb.rpb_record = NULL; rpb.rpb_record = NULL;
@ -5251,7 +5251,7 @@ void Database::garbage_collector(Database* dbb)
Jrd::Attachment::UseCountHolder use(attachment); Jrd::Attachment::UseCountHolder use(attachment);
tdbb->markAsSweeper(); tdbb->markAsSweeper();
HazardPtr<jrd_rel> relation(FB_FUNCTION); jrd_rel* relation;
record_param rpb; record_param rpb;
rpb.getWindow(tdbb).win_flags = WIN_garbage_collector; rpb.getWindow(tdbb).win_flags = WIN_garbage_collector;
rpb.rpb_stream_flags = RPB_s_no_data | RPB_s_sweeper; rpb.rpb_stream_flags = RPB_s_no_data | RPB_s_sweeper;