mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
WIP
This commit is contained in:
parent
dae83f6815
commit
4215b9d220
@ -24,8 +24,8 @@ WARN_FLAGS=-Werror=delete-incomplete -Wall -Wno-switch -Wno-parentheses -Wno-unk
|
||||
PLATFORM_PLUSPLUS_FLAGS=-Wno-invalid-offsetof -Wno-class-memaccess
|
||||
|
||||
PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS)
|
||||
#DEV_FLAGS=-DUSE_VALGRIND $(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=8
|
||||
DEV_FLAGS=$(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=8
|
||||
#DEV_FLAGS=-DUSE_VALGRIND $(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=2
|
||||
DEV_FLAGS=$(WARN_FLAGS) $(COMMON_FLAGS) -fmax-errors=2
|
||||
|
||||
# This file must be compiled with SSE4.2 support
|
||||
%/CRC32C.o: COMMON_FLAGS += -msse4
|
||||
|
115
extern/cloop/src/tests/test1/CalcCppApi.h
vendored
115
extern/cloop/src/tests/test1/CalcCppApi.h
vendored
@ -7,6 +7,23 @@
|
||||
#define CLOOP_CARG
|
||||
#endif
|
||||
|
||||
#ifndef CLOOP_NOEXCEPT
|
||||
#if __cplusplus >= 201103L
|
||||
#define CLOOP_NOEXCEPT noexcept
|
||||
#else
|
||||
#define CLOOP_NOEXCEPT throw()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef CLOOP_CONSTEXPR
|
||||
#if __cplusplus >= 201103L
|
||||
#define CLOOP_CONSTEXPR constexpr
|
||||
#else
|
||||
#define CLOOP_CONSTEXPR const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace calc
|
||||
{
|
||||
@ -34,6 +51,8 @@ namespace calc
|
||||
|
||||
// Interfaces declarations
|
||||
|
||||
#define CALC_IDISPOSABLE_VERSION 1u
|
||||
|
||||
class IDisposable
|
||||
{
|
||||
public:
|
||||
@ -41,7 +60,7 @@ namespace calc
|
||||
{
|
||||
void* cloopDummy[1];
|
||||
uintptr_t version;
|
||||
void (CLOOP_CARG *dispose)(IDisposable* self) throw();
|
||||
void (CLOOP_CARG *dispose)(IDisposable* self) CLOOP_NOEXCEPT;
|
||||
};
|
||||
|
||||
void* cloopDummy[1];
|
||||
@ -57,7 +76,7 @@ namespace calc
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 1;
|
||||
static CLOOP_CONSTEXPR unsigned VERSION = CALC_IDISPOSABLE_VERSION;
|
||||
|
||||
void dispose()
|
||||
{
|
||||
@ -65,13 +84,15 @@ namespace calc
|
||||
}
|
||||
};
|
||||
|
||||
#define CALC_ISTATUS_VERSION 2u
|
||||
|
||||
class IStatus : public IDisposable
|
||||
{
|
||||
public:
|
||||
struct VTable : public IDisposable::VTable
|
||||
{
|
||||
int (CLOOP_CARG *getCode)(const IStatus* self) throw();
|
||||
void (CLOOP_CARG *setCode)(IStatus* self, int code) throw();
|
||||
int (CLOOP_CARG *getCode)(const IStatus* self) CLOOP_NOEXCEPT;
|
||||
void (CLOOP_CARG *setCode)(IStatus* self, int code) CLOOP_NOEXCEPT;
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -85,11 +106,11 @@ namespace calc
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 2;
|
||||
static CLOOP_CONSTEXPR unsigned VERSION = CALC_ISTATUS_VERSION;
|
||||
|
||||
static const int ERROR_1 = 1;
|
||||
static const int ERROR_2 = 0x2;
|
||||
static const int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2;
|
||||
static CLOOP_CONSTEXPR int ERROR_1 = 1;
|
||||
static CLOOP_CONSTEXPR int ERROR_2 = 0x2;
|
||||
static CLOOP_CONSTEXPR int ERROR_12 = IStatus::ERROR_1 | IStatus::ERROR_2;
|
||||
|
||||
int getCode() const
|
||||
{
|
||||
@ -103,15 +124,17 @@ namespace calc
|
||||
}
|
||||
};
|
||||
|
||||
#define CALC_IFACTORY_VERSION 2u
|
||||
|
||||
class IFactory : public IDisposable
|
||||
{
|
||||
public:
|
||||
struct VTable : public IDisposable::VTable
|
||||
{
|
||||
IStatus* (CLOOP_CARG *createStatus)(IFactory* self) throw();
|
||||
ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) throw();
|
||||
ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) throw();
|
||||
ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) throw();
|
||||
IStatus* (CLOOP_CARG *createStatus)(IFactory* self) CLOOP_NOEXCEPT;
|
||||
ICalculator* (CLOOP_CARG *createCalculator)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT;
|
||||
ICalculator2* (CLOOP_CARG *createCalculator2)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT;
|
||||
ICalculator* (CLOOP_CARG *createBrokenCalculator)(IFactory* self, IStatus* status) CLOOP_NOEXCEPT;
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -125,7 +148,7 @@ namespace calc
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 2;
|
||||
static CLOOP_CONSTEXPR unsigned VERSION = CALC_IFACTORY_VERSION;
|
||||
|
||||
IStatus* createStatus()
|
||||
{
|
||||
@ -158,15 +181,17 @@ namespace calc
|
||||
}
|
||||
};
|
||||
|
||||
#define CALC_ICALCULATOR_VERSION 4u
|
||||
|
||||
class ICalculator : public IDisposable
|
||||
{
|
||||
public:
|
||||
struct VTable : public IDisposable::VTable
|
||||
{
|
||||
int (CLOOP_CARG *sum)(const ICalculator* self, IStatus* status, int n1, int n2) throw();
|
||||
int (CLOOP_CARG *getMemory)(const ICalculator* self) throw();
|
||||
void (CLOOP_CARG *setMemory)(ICalculator* self, int n) throw();
|
||||
void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) throw();
|
||||
int (CLOOP_CARG *sum)(const ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT;
|
||||
int (CLOOP_CARG *getMemory)(const ICalculator* self) CLOOP_NOEXCEPT;
|
||||
void (CLOOP_CARG *setMemory)(ICalculator* self, int n) CLOOP_NOEXCEPT;
|
||||
void (CLOOP_CARG *sumAndStore)(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT;
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -180,7 +205,7 @@ namespace calc
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 4;
|
||||
static CLOOP_CONSTEXPR unsigned VERSION = CALC_ICALCULATOR_VERSION;
|
||||
|
||||
template <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
|
||||
{
|
||||
public:
|
||||
struct VTable : public ICalculator::VTable
|
||||
{
|
||||
int (CLOOP_CARG *multiply)(const ICalculator2* self, IStatus* status, int n1, int n2) throw();
|
||||
void (CLOOP_CARG *copyMemory)(ICalculator2* self, const ICalculator* calculator) throw();
|
||||
void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) throw();
|
||||
int (CLOOP_CARG *multiply)(const ICalculator2* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT;
|
||||
void (CLOOP_CARG *copyMemory)(ICalculator2* self, const ICalculator* calculator) CLOOP_NOEXCEPT;
|
||||
void (CLOOP_CARG *copyMemory2)(ICalculator2* self, const int* address) CLOOP_NOEXCEPT;
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -244,7 +271,7 @@ namespace calc
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 6;
|
||||
static CLOOP_CONSTEXPR unsigned VERSION = CALC_ICALCULATOR2_VERSION;
|
||||
|
||||
template <typename StatusType> int multiply(StatusType* status, int n1, int n2) const
|
||||
{
|
||||
@ -291,7 +318,7 @@ namespace calc
|
||||
this->cloopVTable = &vTable;
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw()
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -342,7 +369,7 @@ namespace calc
|
||||
this->cloopVTable = &vTable;
|
||||
}
|
||||
|
||||
static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) throw()
|
||||
static int CLOOP_CARG cloopgetCodeDispatcher(const IStatus* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -355,7 +382,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopsetCodeDispatcher(IStatus* self, int code) throw()
|
||||
static void CLOOP_CARG cloopsetCodeDispatcher(IStatus* self, int code) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -367,7 +394,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw()
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -421,7 +448,7 @@ namespace calc
|
||||
this->cloopVTable = &vTable;
|
||||
}
|
||||
|
||||
static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) throw()
|
||||
static IStatus* CLOOP_CARG cloopcreateStatusDispatcher(IFactory* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -434,7 +461,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static ICalculator* CLOOP_CARG cloopcreateCalculatorDispatcher(IFactory* self, IStatus* status) throw()
|
||||
static ICalculator* CLOOP_CARG cloopcreateCalculatorDispatcher(IFactory* self, IStatus* status) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -449,7 +476,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static ICalculator2* CLOOP_CARG cloopcreateCalculator2Dispatcher(IFactory* self, IStatus* status) throw()
|
||||
static ICalculator2* CLOOP_CARG cloopcreateCalculator2Dispatcher(IFactory* self, IStatus* status) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -464,7 +491,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static ICalculator* CLOOP_CARG cloopcreateBrokenCalculatorDispatcher(IFactory* self, IStatus* status) throw()
|
||||
static ICalculator* CLOOP_CARG cloopcreateBrokenCalculatorDispatcher(IFactory* self, IStatus* status) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -479,7 +506,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw()
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -535,7 +562,7 @@ namespace calc
|
||||
this->cloopVTable = &vTable;
|
||||
}
|
||||
|
||||
static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) throw()
|
||||
static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -550,7 +577,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) throw()
|
||||
static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -563,7 +590,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) throw()
|
||||
static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -575,7 +602,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) throw()
|
||||
static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -589,7 +616,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw()
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -648,7 +675,7 @@ namespace calc
|
||||
this->cloopVTable = &vTable;
|
||||
}
|
||||
|
||||
static int CLOOP_CARG cloopmultiplyDispatcher(const ICalculator2* self, IStatus* status, int n1, int n2) throw()
|
||||
static int CLOOP_CARG cloopmultiplyDispatcher(const ICalculator2* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -663,7 +690,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopcopyMemoryDispatcher(ICalculator2* self, const ICalculator* calculator) throw()
|
||||
static void CLOOP_CARG cloopcopyMemoryDispatcher(ICalculator2* self, const ICalculator* calculator) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -675,7 +702,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopcopyMemory2Dispatcher(ICalculator2* self, const int* address) throw()
|
||||
static void CLOOP_CARG cloopcopyMemory2Dispatcher(ICalculator2* self, const int* address) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -687,7 +714,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) throw()
|
||||
static int CLOOP_CARG cloopsumDispatcher(const ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -702,7 +729,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) throw()
|
||||
static int CLOOP_CARG cloopgetMemoryDispatcher(const ICalculator* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -715,7 +742,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) throw()
|
||||
static void CLOOP_CARG cloopsetMemoryDispatcher(ICalculator* self, int n) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -727,7 +754,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) throw()
|
||||
static void CLOOP_CARG cloopsumAndStoreDispatcher(ICalculator* self, IStatus* status, int n1, int n2) CLOOP_NOEXCEPT
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
@ -741,7 +768,7 @@ namespace calc
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw()
|
||||
static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) CLOOP_NOEXCEPT
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -12787,7 +12787,7 @@ DmlNode* UdfCallNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
}
|
||||
}
|
||||
|
||||
HazardPtr<Function> func(FB_FUNCTION);
|
||||
Function* func = nullptr;
|
||||
if (!node->function)
|
||||
{
|
||||
func = Function::lookup(tdbb, name, false);
|
||||
@ -12917,7 +12917,7 @@ ValueExprNode* UdfCallNode::copy(thread_db* tdbb, NodeCopier& copier) const
|
||||
node->function = function;
|
||||
else
|
||||
{
|
||||
HazardPtr<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());
|
||||
}
|
||||
return node;
|
||||
|
@ -30,12 +30,13 @@
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class Resources;
|
||||
|
||||
class NodePrinter
|
||||
{
|
||||
public:
|
||||
explicit NodePrinter(unsigned aIndent = 0)
|
||||
: indent(aIndent)
|
||||
NodePrinter(const Resources* aResources, unsigned aIndent = 0)
|
||||
: indent(aIndent), resources(aResources)
|
||||
{
|
||||
}
|
||||
|
||||
@ -337,6 +338,11 @@ private:
|
||||
|
||||
private:
|
||||
unsigned indent;
|
||||
|
||||
public:
|
||||
const Resources* resources;
|
||||
|
||||
private:
|
||||
Firebird::ObjectsArray<Firebird::string> stack;
|
||||
Firebird::string text;
|
||||
};
|
||||
|
@ -2932,7 +2932,7 @@ DmlNode* ExecProcedureNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScr
|
||||
|
||||
const auto blrStartPos = csb->csb_blr_reader.getPos();
|
||||
jrd_prc* procedure = NULL;
|
||||
HazardPtr<jrd_prc> proc(FB_FUNCTION);
|
||||
HazardPtr<jrd_prc> proc;
|
||||
QualifiedName name;
|
||||
|
||||
if (blrOp == blr_exec_pid)
|
||||
@ -10741,7 +10741,7 @@ static RelationSourceNode* pass1Update(thread_db* tdbb, CompilerScratch* csb, jr
|
||||
|
||||
for (FB_SIZE_T i = 0; i < trigger->getCount(tdbb); i++)
|
||||
{
|
||||
HazardPtr<Trigger> tr(FB_FUNCTION);
|
||||
HazardPtr<Trigger> tr;
|
||||
if (!trigger->load(tdbb, i, tr))
|
||||
continue;
|
||||
if (!tr->sysTrigger)
|
||||
|
@ -150,13 +150,15 @@ inline T FB_ALIGN(T n, uintptr_t b)
|
||||
return (T) ((((uintptr_t) n) + b - 1) & ~(b - 1));
|
||||
}
|
||||
|
||||
// Various object IDs (longer-than-32-bit)
|
||||
// Various object IDs
|
||||
|
||||
typedef FB_UINT64 AttNumber;
|
||||
typedef FB_UINT64 TraNumber;
|
||||
typedef FB_UINT64 StmtNumber;
|
||||
typedef FB_UINT64 CommitNumber;
|
||||
typedef ULONG SnapshotHandle;
|
||||
typedef ULONG MdcVersion;
|
||||
typedef USHORT MetaId;
|
||||
typedef SINT64 SavNumber;
|
||||
|
||||
#endif /* INCLUDE_FB_TYPES_H */
|
||||
|
@ -5312,6 +5312,7 @@ const
|
||||
isc_invalid_blob_util_handle = 335545283;
|
||||
isc_bad_temp_blob_id = 335545284;
|
||||
isc_ods_upgrade_err = 335545285;
|
||||
isc_bad_par_workers = 335545286;
|
||||
isc_gfix_db_name = 335740929;
|
||||
isc_gfix_invalid_sw = 335740930;
|
||||
isc_gfix_incmp_sw = 335740932;
|
||||
|
@ -138,10 +138,6 @@ void Jrd::Attachment::destroy(Attachment* const attachment)
|
||||
|
||||
jrd_tra::destroy(NULL, sysTransaction);
|
||||
}
|
||||
|
||||
attachment->att_delayed_delete.garbageCollect(HazardDelayedDelete::GarbageCollectMethod::GC_FORCE);
|
||||
HZ_DEB(fprintf(stderr, "Attachment::destroy=>delayedDelete to DBB\n"));
|
||||
dbb->dbb_delayed_delete.delayedDelete(attachment->att_delayed_delete.getHazardPointers());
|
||||
}
|
||||
|
||||
MemoryPool* const pool = attachment->att_pool;
|
||||
@ -241,8 +237,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, JProvider* provider
|
||||
att_stmt_timeout(0),
|
||||
att_batches(*pool),
|
||||
att_initial_options(*pool),
|
||||
att_provider(provider),
|
||||
att_delayed_delete(*dbb->dbb_permanent, *pool)
|
||||
att_provider(provider)
|
||||
{
|
||||
att_internal.grow(irq_MAX);
|
||||
att_dyn_req.grow(drq_MAX);
|
||||
|
@ -784,9 +784,6 @@ private:
|
||||
|
||||
Lock* att_repl_lock; // Replication set lock
|
||||
JProvider* att_provider; // Provider which created this attachment
|
||||
|
||||
public:
|
||||
HazardDelayedDelete att_delayed_delete;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1130,12 +1130,16 @@ void Collation::release(thread_db* tdbb)
|
||||
fb_assert(useCount >= 0);
|
||||
|
||||
if (existenceLock)
|
||||
{
|
||||
if (!tdbb)
|
||||
tdbb = JRD_get_thread_data();
|
||||
LCK_release(tdbb, existenceLock);
|
||||
}
|
||||
|
||||
useCount = 0;
|
||||
}
|
||||
|
||||
void Collation::destroy(thread_db* tdbb)
|
||||
void Collation::destroy(thread_db* tdbb, int xxx)
|
||||
{
|
||||
fprintf(stderr, "Collation::destroy(%p) tt=%p\n", this, tt);
|
||||
fb_assert(useCount == 0);
|
||||
@ -1150,8 +1154,8 @@ void Collation::destroy(thread_db* tdbb)
|
||||
delete existenceLock;
|
||||
existenceLock = NULL;
|
||||
|
||||
fprintf(stderr, "delayedDelete collation %p\n", this);
|
||||
this->delayedDelete(tdbb);
|
||||
fprintf(stderr, "retire collation %p\n", this);
|
||||
//this->retire();
|
||||
}
|
||||
|
||||
void Collation::incUseCount(thread_db* /*tdbb*/)
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
virtual PatternMatcher* createContainsMatcher(MemoryPool& pool, const UCHAR* p, SLONG pl) = 0;
|
||||
|
||||
void release(thread_db* tdbb);
|
||||
void destroy(thread_db* tdbb);
|
||||
void destroy(thread_db* tdbb, int);
|
||||
void incUseCount(thread_db* tdbb);
|
||||
void decUseCount(thread_db* tdbb);
|
||||
|
||||
@ -89,11 +89,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeFromCache(thread_db* tdbb) override
|
||||
{
|
||||
delayedDelete(tdbb);
|
||||
}
|
||||
|
||||
const char* c_name() const override
|
||||
{
|
||||
return name.c_str();
|
||||
|
@ -622,8 +622,7 @@ namespace Jrd
|
||||
dbb_replica_mode(REPLICA_NONE),
|
||||
dbb_compatibility_index(~0U),
|
||||
dbb_dic(*p),
|
||||
dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p)),
|
||||
dbb_delayed_delete(*p, *p)
|
||||
dbb_mdc(FB_NEW_POOL(*p) MetadataCache(*p))
|
||||
{
|
||||
dbb_pools.add(p);
|
||||
}
|
||||
|
@ -440,8 +440,6 @@ public:
|
||||
Firebird::InitInstance<KeywordsMap, KeywordsMapAllocator, Firebird::TraditionalDelete> dbb_keywords_map;
|
||||
|
||||
MetadataCache* dbb_mdc;
|
||||
HazardDelayedDelete dbb_delayed_delete;
|
||||
Firebird::Mutex dbb_dd_mutex;
|
||||
|
||||
// returns true if primary file is located on raw device
|
||||
bool onRawDevice() const;
|
||||
|
@ -1419,7 +1419,7 @@ void ExtEngineManager::makeFunction(thread_db* tdbb, CompilerScratch* csb, Jrd::
|
||||
csbPool, extOutMessageNode, intOutMessageNode);
|
||||
|
||||
Statement* statement = udf->getStatement();
|
||||
PAR_preparsed_node(tdbb, nullRel, mainNode, NULL, &csb, &statement, false, 0);
|
||||
PAR_preparsed_node(tdbb, nullptr, mainNode, NULL, &csb, &statement, false, 0);
|
||||
udf->setStatement(statement);
|
||||
}
|
||||
catch (...)
|
||||
@ -1562,7 +1562,7 @@ void ExtEngineManager::makeProcedure(thread_db* tdbb, CompilerScratch* csb, jrd_
|
||||
mainNode->statements.add(extProcedureNode);
|
||||
|
||||
Statement* statement = prc->getStatement();
|
||||
PAR_preparsed_node(tdbb, nullRel, mainNode, NULL, &csb, &statement, false, 0);
|
||||
PAR_preparsed_node(tdbb, nullptr, mainNode, NULL, &csb, &statement, false, 0);
|
||||
prc->setStatement(statement);
|
||||
}
|
||||
catch (...)
|
||||
@ -1662,9 +1662,7 @@ void ExtEngineManager::makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::T
|
||||
trg->extTrigger);
|
||||
mainNode->statements.add(extTriggerNode);
|
||||
|
||||
HazardPtr<jrd_rel> rel(FB_FUNCTION);
|
||||
rel.safePointer(trg->relation);
|
||||
PAR_preparsed_node(tdbb, rel, mainNode, NULL, &csb, &trg->statement, true, 0);
|
||||
PAR_preparsed_node(tdbb, trg->relation, mainNode, NULL, &csb, &trg->statement, true, 0);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -59,13 +59,13 @@ DATABASE DB = FILENAME "ODS.RDB";
|
||||
const char* const Function::EXCEPTION_MESSAGE = "The user defined function: \t%s\n\t referencing"
|
||||
" entrypoint: \t%s\n\t in module: \t%s\n\tcaused the fatal exception:";
|
||||
|
||||
HazardPtr<Function> Function::lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags)
|
||||
Function* Function::lookup(thread_db* tdbb, USHORT id, bool return_deleted, bool noscan, USHORT flags)
|
||||
{
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
HazardPtr<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 &&
|
||||
!(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
|
||||
|
||||
function.clear();
|
||||
function = nullptr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
|
||||
function.clear();
|
||||
function = nullptr;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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_tra* sysTransaction = attachment->getSysTransaction();
|
||||
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))
|
||||
{
|
||||
@ -163,29 +163,28 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
|
||||
}
|
||||
}
|
||||
|
||||
Function* newFun = function.getPointer();
|
||||
function.clear();
|
||||
MemoryPool& pool = dbb->dbb_mdc->getPool();
|
||||
if (!newFun)
|
||||
newFun = FB_NEW_POOL(*dbb->dbb_permanent) Function(pool);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
newFun->flags |= (Routine::FLAG_BEING_SCANNED | flags);
|
||||
newFun->flags &= ~(Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED);
|
||||
|
||||
newFun->setId(id);
|
||||
function = dbb->dbb_mdc->setFunction(tdbb, id, newFun);
|
||||
newFun = nullptr;
|
||||
Function* Function::create(thread_db* tdbb, MetaId id, CacheObject::Flag flags)
|
||||
{
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
jrd_tra* sysTransaction = attachment->getSysTransaction();
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
||||
Function* function = FB_NEW_POOL(*dbb->dbb_permanent) Function(*dbb->dbb_permanent, id);
|
||||
/*
|
||||
if (!function->existenceLock)
|
||||
{
|
||||
function->existenceLock = FB_NEW_POOL(pool)
|
||||
ExistenceLock(pool, tdbb, LCK_fun_exist, function->getId(), function.getPointer());
|
||||
}
|
||||
*/
|
||||
|
||||
if (!noscan)
|
||||
try
|
||||
{
|
||||
if (!(flags & CacheFlag::NOSCAN))
|
||||
{
|
||||
AutoCacheRequest request_fun(tdbb, irq_l_functions, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request_fun)
|
||||
@ -336,7 +335,7 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
|
||||
try
|
||||
{
|
||||
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&)
|
||||
{
|
||||
@ -419,7 +418,7 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
|
||||
else
|
||||
body.getBuffer(1)[0] = 0;
|
||||
|
||||
dbb->dbb_extManager->makeFunction(tdbb, csb, function.getPointer(), X.RDB$ENGINE_NAME,
|
||||
dbb->dbb_extManager->makeFunction(tdbb, csb, function, X.RDB$ENGINE_NAME,
|
||||
(X.RDB$ENTRYPOINT.NULL ? "" : X.RDB$ENTRYPOINT), (char*) body.begin());
|
||||
|
||||
if (!function->fun_external)
|
||||
@ -477,20 +476,12 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
|
||||
// Make sure that it is really being scanned
|
||||
fb_assert(function->flags & Routine::FLAG_BEING_SCANNED);
|
||||
|
||||
function->flags &= ~Routine::FLAG_BEING_SCANNED;
|
||||
|
||||
} // if noscan
|
||||
} // try
|
||||
catch (const Exception&)
|
||||
{
|
||||
if (newFun)
|
||||
newFun->delayedDelete(tdbb);
|
||||
if (function)
|
||||
function->flags &= ~(Routine::FLAG_BEING_SCANNED | Routine::FLAG_SCANNED);
|
||||
Function::destroy(function);
|
||||
|
||||
throw;
|
||||
}
|
||||
@ -500,12 +491,7 @@ HazardPtr<Function> Function::loadMetadata(thread_db* tdbb, USHORT id, bool nosc
|
||||
|
||||
bool Function::checkCache(thread_db* tdbb) const
|
||||
{
|
||||
return tdbb->getDatabase()->dbb_mdc->getFunction(tdbb, getId()) == this;
|
||||
}
|
||||
|
||||
void Function::clearCache(thread_db* tdbb)
|
||||
{
|
||||
tdbb->getDatabase()->dbb_mdc->setFunction(tdbb, getId(), nullptr);
|
||||
return tdbb->getDatabase()->dbb_mdc->getFunction(tdbb, getId(), true) == this;
|
||||
}
|
||||
|
||||
bool Function::reload(thread_db* tdbb)
|
||||
|
@ -38,8 +38,8 @@ namespace Jrd
|
||||
static const char* const EXCEPTION_MESSAGE;
|
||||
|
||||
public:
|
||||
static HazardPtr<Function> lookup(thread_db* tdbb, USHORT 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, MetaId id, bool return_deleted, bool noscan, USHORT flags);
|
||||
static Function* lookup(thread_db* tdbb, const QualifiedName& name, bool noscan);
|
||||
|
||||
explicit Function(MemoryPool& p)
|
||||
: Routine(p),
|
||||
@ -53,7 +53,22 @@ namespace Jrd
|
||||
{
|
||||
}
|
||||
|
||||
static HazardPtr<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:
|
||||
virtual int getObjectType() const
|
||||
@ -67,18 +82,20 @@ namespace Jrd
|
||||
}
|
||||
|
||||
virtual bool checkCache(thread_db* tdbb) const;
|
||||
virtual void clearCache(thread_db* tdbb);
|
||||
|
||||
private:
|
||||
virtual ~Function()
|
||||
{
|
||||
delete fun_external;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void releaseExternal()
|
||||
{
|
||||
delete fun_external;
|
||||
fun_external = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
int (*fun_entrypoint)(); // function entrypoint
|
||||
USHORT fun_inputs; // input arguments
|
||||
|
@ -39,171 +39,6 @@ HazardObject::~HazardObject()
|
||||
|
||||
CacheObject* TRAP = nullptr;
|
||||
|
||||
int HazardObject::delayedDelete(thread_db* tdbb)
|
||||
{
|
||||
HazardDelayedDelete* dd = HazardBase::getHazardDelayed(tdbb);
|
||||
// if (this == TRAP)
|
||||
// abort();
|
||||
dd->delayedDelete(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HazardDelayedDelete* HazardBase::getHazardDelayed(thread_db* tdbb)
|
||||
{
|
||||
if (!tdbb)
|
||||
tdbb = JRD_get_thread_data();
|
||||
fb_assert(tdbb);
|
||||
|
||||
Attachment* att = tdbb->getAttachment();
|
||||
if (att)
|
||||
return &att->att_delayed_delete;
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// what about locking object in database? (dbb_delayed_delete)
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
fb_assert(dbb);
|
||||
return &dbb->dbb_delayed_delete;
|
||||
}
|
||||
|
||||
HazardDelayedDelete* HazardBase::getHazardDelayed(Attachment* att)
|
||||
{
|
||||
return &att->att_delayed_delete;
|
||||
}
|
||||
|
||||
void HazardDelayedDelete::add(const void* ptr, const char* from)
|
||||
{
|
||||
HZ_DEB(fprintf(stderr, "HazardDelayedDelete::add %s %p\n", from, ptr));
|
||||
// as long as we access our own hazard pointers use of write accessor is always OK
|
||||
auto hp = hazardPointers.writeAccessor();
|
||||
|
||||
// 1. Search for holes
|
||||
for (unsigned n = 0; n < hp->getCount(); ++n)
|
||||
{
|
||||
if (hp->value(n) == nullptr)
|
||||
{
|
||||
// store
|
||||
hp->value(n) = ptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Grow if needed
|
||||
if (!hp->hasSpace())
|
||||
hazardPointers.grow(this);
|
||||
|
||||
// 3. Append
|
||||
hp = hazardPointers.writeAccessor();
|
||||
*(hp->add()) = ptr;
|
||||
}
|
||||
|
||||
void HazardDelayedDelete::remove(const void* ptr, const char* from)
|
||||
{
|
||||
HZ_DEB(fprintf(stderr, "HazardDelayedDelete::remove %s %p\n", from, ptr));
|
||||
// as long as we access our own hazard pointers use of write accessor is always OK
|
||||
auto hp = hazardPointers.writeAccessor();
|
||||
|
||||
for (unsigned n = 0; n < hp->getCount(); ++n)
|
||||
{
|
||||
if (hp->value(n) == ptr)
|
||||
{
|
||||
hp->value(n) = nullptr;
|
||||
hp->truncate(nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fb_assert(!"Required ptr not found in HazardDelayedDelete::remove");
|
||||
}
|
||||
|
||||
void HazardDelayedDelete::delayedDelete(HazardObject* mem, bool gc)
|
||||
{
|
||||
HZ_DEB(fprintf(stderr, "HazardDelayedDelete::delayedDelete %p\n", mem));
|
||||
|
||||
if (mem)
|
||||
toDelete.push(mem);
|
||||
|
||||
if (gc)
|
||||
garbageCollect(GarbageCollectMethod::GC_NORMAL);
|
||||
}
|
||||
|
||||
void HazardDelayedDelete::copyHazardPointers(LocalHP& local, HazardPtr<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&)
|
||||
{
|
||||
|
@ -36,169 +36,126 @@
|
||||
#include "../common/gdsassert.h"
|
||||
#include "fb_blk.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cds/gc/dhp.h>
|
||||
#include <cds/algo/atomic.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
class thread_db;
|
||||
class Attachment;
|
||||
class HazardDelayedDelete;
|
||||
|
||||
class HazardObject
|
||||
{
|
||||
friend HazardDelayedDelete;
|
||||
protected:
|
||||
void retire()
|
||||
{
|
||||
fb_assert(this);
|
||||
|
||||
struct Disposer
|
||||
{
|
||||
void operator()(HazardObject* ho)
|
||||
{
|
||||
fb_assert(ho);
|
||||
delete ho;
|
||||
}
|
||||
};
|
||||
|
||||
cds::gc::DHP::retire<Disposer>(this);
|
||||
}
|
||||
|
||||
virtual ~HazardObject();
|
||||
public:
|
||||
int delayedDelete(thread_db* tdbb);
|
||||
};
|
||||
|
||||
class HazardBase
|
||||
{
|
||||
protected:
|
||||
explicit HazardBase(thread_db* tdbb)
|
||||
: hazardDelayed(getHazardDelayed(tdbb))
|
||||
{ }
|
||||
|
||||
explicit HazardBase(Attachment* att)
|
||||
: hazardDelayed(getHazardDelayed(att))
|
||||
{ }
|
||||
|
||||
explicit HazardBase(HazardDelayedDelete* hd)
|
||||
: hazardDelayed(hd)
|
||||
{ }
|
||||
|
||||
HazardBase()
|
||||
: hazardDelayed(nullptr)
|
||||
{ }
|
||||
|
||||
inline void add(const void* hazardPointer, const char* from);
|
||||
inline void remove(const void* hazardPointer, const char* from);
|
||||
|
||||
private:
|
||||
HazardDelayedDelete* hazardDelayed;
|
||||
|
||||
public:
|
||||
static HazardDelayedDelete* getHazardDelayed(thread_db* tdbb = nullptr);
|
||||
static HazardDelayedDelete* getHazardDelayed(Attachment* att);
|
||||
};
|
||||
|
||||
template <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:
|
||||
HazardPtr(const char* F)
|
||||
: hazardPointer(nullptr),
|
||||
frm(F)
|
||||
{ }
|
||||
HazardPtr() = default;
|
||||
|
||||
template <class DDS>
|
||||
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)
|
||||
HazardPtr(const atomics::atomic<T*>& from)
|
||||
{
|
||||
set(from);
|
||||
protect(from);
|
||||
}
|
||||
|
||||
HazardPtr(const HazardPtr& copy)
|
||||
: HazardBase(copy),
|
||||
hazardPointer(nullptr),
|
||||
frm(copy.frm)
|
||||
HazardPtr(const HazardPtr& copyFrom)
|
||||
{
|
||||
reset(copy.hazardPointer);
|
||||
frm = copy.frm;
|
||||
copy(copyFrom);
|
||||
}
|
||||
|
||||
HazardPtr(HazardPtr&& move)
|
||||
: HazardBase(move),
|
||||
hazardPointer(nullptr),
|
||||
frm(move.frm)
|
||||
HazardPtr(HazardPtr&& moveFrom) = default;
|
||||
|
||||
template <class T2>
|
||||
HazardPtr(const HazardPtr<T2>& copyFrom)
|
||||
{
|
||||
hazardPointer = move.releasePointer();
|
||||
checkAssign<T2>();
|
||||
copy(copyFrom);
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
HazardPtr(const HazardPtr<T2>& copy)
|
||||
: HazardBase(copy),
|
||||
hazardPointer(nullptr),
|
||||
frm(copy.frm)
|
||||
HazardPtr(HazardPtr<T2>&& moveFrom)
|
||||
: inherited(std::move(moveFrom))
|
||||
{
|
||||
reset(copy.getPointer());
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
HazardPtr(HazardPtr<T2>&& move)
|
||||
: HazardBase(move),
|
||||
hazardPointer(nullptr),
|
||||
frm(move.frm)
|
||||
{
|
||||
hazardPointer = move.releasePointer();
|
||||
checkAssign<T2>();
|
||||
}
|
||||
|
||||
~HazardPtr()
|
||||
{
|
||||
reset(nullptr);
|
||||
}
|
||||
/*
|
||||
T* unsafePointer() const // to be removed
|
||||
{
|
||||
return getPointer();
|
||||
}
|
||||
*/
|
||||
{ }
|
||||
|
||||
T* getPointer() const
|
||||
{
|
||||
return hazardPointer;
|
||||
return get<T>();
|
||||
}
|
||||
|
||||
T* releasePointer()
|
||||
{
|
||||
T* rc = hazardPointer;
|
||||
hazardPointer = nullptr;
|
||||
T* rc = get<T>();
|
||||
clear();
|
||||
return rc;
|
||||
}
|
||||
|
||||
void set(const std::atomic<T*>& from)
|
||||
void set(const atomics::atomic<T*>& from)
|
||||
{
|
||||
T* v = from.load(std::memory_order_relaxed);
|
||||
do
|
||||
{
|
||||
reset(v);
|
||||
v = from.load(std::memory_order_acquire);
|
||||
} while (hazardPointer != v);
|
||||
protect(from);
|
||||
}
|
||||
|
||||
// atomically replaces 'where' with 'newVal', using *this as old value for comparison
|
||||
/*/ atomically replaces 'where' with 'newVal', using *this as old value for comparison
|
||||
// always sets *this to actual data from 'where'
|
||||
bool replace(std::atomic<T*>* where, T* newVal)
|
||||
bool replace(atomics::atomic<T*>& where, T* newVal)
|
||||
{
|
||||
T* val = hazardPointer;
|
||||
bool rc = where->compare_exchange_strong(val, newVal,
|
||||
T* val = get<T>();
|
||||
bool rc = where.compare_exchange_strong(val, newVal,
|
||||
std::memory_order_release, std::memory_order_acquire);
|
||||
reset(rc ? newVal : val);
|
||||
assign(rc ? newVal : val);
|
||||
return rc;
|
||||
}
|
||||
*/
|
||||
// atomically replaces 'where' with 'newVal', using *this as old value for comparison
|
||||
// sets *this to actual data from 'where' if replace failed
|
||||
bool replace2(atomics::atomic<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;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
reset(nullptr);
|
||||
inherited::clear();
|
||||
}
|
||||
|
||||
T* operator->()
|
||||
{
|
||||
return hazardPointer;
|
||||
return get<T>();
|
||||
}
|
||||
|
||||
const T* operator->() const
|
||||
{
|
||||
return hazardPointer;
|
||||
return get<T>();
|
||||
}
|
||||
/*
|
||||
template <typename R>
|
||||
@ -209,85 +166,68 @@ namespace Jrd {
|
||||
*/
|
||||
bool operator!() const
|
||||
{
|
||||
return hazardPointer == nullptr;
|
||||
return !hasData();
|
||||
}
|
||||
|
||||
bool hasData() const
|
||||
{
|
||||
return hazardPointer != nullptr;
|
||||
return get_native() != nullptr;
|
||||
}
|
||||
|
||||
bool operator==(const T* v) const
|
||||
{
|
||||
return hazardPointer == v;
|
||||
return get<T>() == v;
|
||||
}
|
||||
|
||||
bool operator!=(const T* v) const
|
||||
{
|
||||
return hazardPointer != v;
|
||||
return get<T>() != v;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return hazardPointer != nullptr;
|
||||
return hasData();
|
||||
}
|
||||
|
||||
HazardPtr& operator=(const HazardPtr& copyAssign)
|
||||
{
|
||||
reset(copyAssign.hazardPointer, ©Assign);
|
||||
copy(copyAssign);
|
||||
return *this;
|
||||
}
|
||||
|
||||
HazardPtr& operator=(HazardPtr&& moveAssign)
|
||||
{
|
||||
if (hazardPointer)
|
||||
remove(hazardPointer, frm);
|
||||
HazardBase::operator=(moveAssign);
|
||||
hazardPointer = moveAssign.releasePointer();
|
||||
inherited::operator=(std::move(moveAssign));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
HazardPtr& operator=(const HazardPtr<T2>& copyAssign)
|
||||
{
|
||||
reset(copyAssign.getPointer(), ©Assign);
|
||||
checkAssign<T2>();
|
||||
copy(copyAssign);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
HazardPtr& operator=(HazardPtr<T2>&& moveAssign)
|
||||
{
|
||||
if (hazardPointer)
|
||||
remove(hazardPointer, FB_FUNCTION);
|
||||
HazardBase::operator=(moveAssign);
|
||||
hazardPointer = moveAssign.releasePointer();
|
||||
checkAssign<T2>();
|
||||
inherited::operator=(std::move(moveAssign));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void safePointer(T* ptr)
|
||||
{
|
||||
reset(ptr);
|
||||
assign(ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
void reset(T* newPtr, const HazardBase* newBase = nullptr)
|
||||
template <class T2>
|
||||
struct checkAssign
|
||||
{
|
||||
if (newPtr != hazardPointer)
|
||||
{
|
||||
if (hazardPointer)
|
||||
remove(hazardPointer, frm);
|
||||
if (newBase)
|
||||
HazardBase::operator=(*newBase);
|
||||
if (newPtr)
|
||||
add(newPtr, frm);
|
||||
hazardPointer = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
T* hazardPointer;
|
||||
|
||||
public:
|
||||
const char* frm;
|
||||
static_assert(std::is_trivially_assignable<T*&, T2*>::value, "Invalid type of pointer assigned");
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -310,11 +250,10 @@ namespace Jrd {
|
||||
|
||||
|
||||
// Shared read here means that any thread can read from vector using HP.
|
||||
// It can be modified only in single thread, and it's caller's responsibility that modifying thread is single.
|
||||
// It's also callers responsibility to destroy Generation when deleting SharedReadVector:
|
||||
// in dtor we do not have enough information to do it correctly, default delayedDelete() may be already wrong.
|
||||
// It can be modified only in single thread, and it's caller's responsibility
|
||||
// that modifying thread is single.
|
||||
|
||||
template <typename T, FB_SIZE_T CAP, bool GC_ENABLED = true>
|
||||
template <typename T, FB_SIZE_T CAP>
|
||||
class SharedReadVector : public Firebird::PermanentStorage
|
||||
{
|
||||
public:
|
||||
@ -382,409 +321,75 @@ namespace Jrd {
|
||||
while (count && data[count - 1] == notValue)
|
||||
count--;
|
||||
}
|
||||
|
||||
static void destroy(Generation* gen)
|
||||
{
|
||||
// delay delete - someone else may access it
|
||||
gen->retire();
|
||||
}
|
||||
};
|
||||
|
||||
SharedReadVector(MemoryPool& p)
|
||||
: Firebird::PermanentStorage(p),
|
||||
v(Generation::create(getPool(), CAP))
|
||||
currentData(Generation::create(getPool(), CAP))
|
||||
{ }
|
||||
|
||||
Generation* writeAccessor()
|
||||
{
|
||||
return v.load(std::memory_order_acquire);
|
||||
return currentData.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
template <class DDS>
|
||||
HazardPtr<Generation> readAccessor(DDS* par) const
|
||||
HazardPtr<Generation> readAccessor() 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:
|
||||
std::atomic<Generation*> v;
|
||||
atomics::atomic<Generation*> currentData;
|
||||
};
|
||||
|
||||
|
||||
class HazardDelayedDelete : public Firebird::PermanentStorage
|
||||
{
|
||||
private:
|
||||
static const unsigned int INITIAL_SIZE = 4;
|
||||
static const unsigned int DELETED_LIST_SIZE = 32;
|
||||
|
||||
typedef Firebird::SortedArray<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
|
||||
class thread_db;
|
||||
class CacheObject
|
||||
{
|
||||
public:
|
||||
typedef unsigned Flag;
|
||||
virtual bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) /*const*/;
|
||||
virtual void afterUnlock(thread_db* tdbb, unsigned flags);
|
||||
virtual void lockedExcl [[noreturn]] (thread_db* tdbb) /*const*/;
|
||||
virtual const char* c_name() const = 0;
|
||||
virtual void removeFromCache(thread_db* tdbb) = 0;
|
||||
};
|
||||
|
||||
template <class 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
|
||||
|
@ -648,12 +648,12 @@ RecordBuffer* SnapshotData::getData(int id) const
|
||||
|
||||
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);
|
||||
MET_scan_relation(tdbb, relation);
|
||||
fb_assert(relation->isVirtual());
|
||||
|
||||
const Format* const format = MET_current(tdbb, relation.getPointer());
|
||||
const Format* const format = MET_current(tdbb, relation);
|
||||
fb_assert(format);
|
||||
|
||||
RecordBuffer* const buffer = FB_NEW_POOL(pool) RecordBuffer(pool, format);
|
||||
@ -708,7 +708,7 @@ void SnapshotData::putField(thread_db* tdbb, Record* record, const DumpField& fi
|
||||
SLONG rel_id;
|
||||
memcpy(&rel_id, field.data, field.length);
|
||||
|
||||
HazardPtr<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())
|
||||
return;
|
||||
|
||||
|
@ -28,10 +28,11 @@
|
||||
#include "../jrd/ids.h"
|
||||
#include "../jrd/recsrc/Cursor.h"
|
||||
#include "../jrd/dpm_proto.h"
|
||||
#include "../jrd/lck_proto.h"
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/pag_proto.h"
|
||||
#include "../jrd/tra_proto.h"
|
||||
#include "../jrd/Statement.h"
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
|
@ -528,7 +528,7 @@ LocalTableSourceNode* LocalTableSourceNode::copy(thread_db* tdbb, NodeCopier& co
|
||||
void LocalTableSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseNode* /*rse*/,
|
||||
BoolExprNode** /*boolean*/, RecordSourceNodeStack& stack)
|
||||
{
|
||||
fb_assert(!csb->csb_view); // local tables cannot be inside a view
|
||||
fb_assert(!csb->csb_view.isSet()); // local tables cannot be inside a view
|
||||
|
||||
stack.push(this); // Assume that the source will be used. Push it on the final stream stack.
|
||||
|
||||
@ -572,7 +572,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
|
||||
// Find relation either by id or by name
|
||||
AutoPtr<string> aliasString;
|
||||
MetaName name;
|
||||
HazardPtr<jrd_rel> rel(FB_FUNCTION);
|
||||
CacheElement<jrd_rel>* rel = nullptr;
|
||||
|
||||
switch (blrOp)
|
||||
{
|
||||
@ -587,7 +587,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
|
||||
csb->csb_blr_reader.getString(*aliasString);
|
||||
}
|
||||
|
||||
rel = MetadataCache::lookup_relation_id(tdbb, id, false);
|
||||
rel = MetadataCache::lookupRelation(tdbb, id);
|
||||
if (!rel)
|
||||
name.printf("id %d", id);
|
||||
break;
|
||||
@ -604,7 +604,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
|
||||
csb->csb_blr_reader.getString(*aliasString);
|
||||
}
|
||||
|
||||
rel = MetadataCache::lookup_relation(tdbb, name);
|
||||
rel = MetadataCache::lookupRelation(tdbb, name);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
|
||||
|
||||
// Store relation in CSB resources and after it - in the node
|
||||
|
||||
node->relation = csb->csb_resources.registerResource(tdbb, Resource::rsc_relation, rel, rel->rel_id);
|
||||
node->relation = csb->csb_resources->relations.registerResource(rel);
|
||||
|
||||
// if an alias was passed, store with the relation
|
||||
|
||||
@ -626,14 +626,11 @@ RelationSourceNode* RelationSourceNode::parse(thread_db* tdbb, CompilerScratch*
|
||||
|
||||
// Scan the relation if it hasn't already been scanned for meta data
|
||||
|
||||
if ((!(node->relation->rel_flags & REL_scanned) ||
|
||||
(node->relation->rel_flags & REL_being_scanned)) &&
|
||||
!(csb->csb_g_flags & csb_internal))
|
||||
{
|
||||
MET_scan_relation(tdbb, rel);
|
||||
}
|
||||
else if (node->relation->rel_flags & REL_sys_triggers)
|
||||
MET_parse_sys_trigger(tdbb, rel);
|
||||
jrd_rel* latestVersion = rel->getObject(tdbb);
|
||||
if (!(csb->csb_g_flags & csb_internal))
|
||||
latestVersion->scan(tdbb);
|
||||
if (latestVersion->rel_flags & REL_sys_triggers)
|
||||
MET_parse_sys_trigger(tdbb, latestVersion);
|
||||
|
||||
// generate a stream for the relation reference, assuming it is a real reference
|
||||
|
||||
@ -658,8 +655,8 @@ string RelationSourceNode::internalPrint(NodePrinter& printer) const
|
||||
NODE_PRINT(printer, dsqlName);
|
||||
NODE_PRINT(printer, alias);
|
||||
NODE_PRINT(printer, context);
|
||||
if (relation)
|
||||
printer.print("rel_name", relation->rel_name);
|
||||
if (relation.isSet())
|
||||
printer.print("rel_name", relation.get(JRD_get_thread_data(), printer.resources)->rel_name);
|
||||
|
||||
return "RelationSourceNode";
|
||||
}
|
||||
@ -734,12 +731,16 @@ RecordSourceNode* RelationSourceNode::pass1(thread_db* tdbb, CompilerScratch* cs
|
||||
const auto tail = &csb->csb_rpt[stream];
|
||||
const auto relation = tail->csb_relation;
|
||||
|
||||
if (relation && !csb->csb_implicit_cursor)
|
||||
if (relation.isSet() && !csb->csb_implicit_cursor)
|
||||
{
|
||||
const SLONG ssRelationId = tail->csb_view ? tail->csb_view->rel_id :
|
||||
view ? view->rel_id : csb->csb_view ? csb->csb_view->rel_id : 0;
|
||||
CMP_post_access(tdbb, csb, relation->rel_security_name, ssRelationId,
|
||||
SCL_select, obj_relations, relation->rel_name);
|
||||
const SLONG ssRelationId = tail->csb_view.isSet() ?
|
||||
tail->csb_view.get(tdbb, csb->csb_resources)->rel_id : view.isSet() ?
|
||||
view.get(tdbb, csb->csb_resources)->rel_id : csb->csb_view.isSet() ?
|
||||
csb->csb_view.get(tdbb, csb->csb_resources)->rel_id : 0;
|
||||
|
||||
const jrd_rel* r = relation.get(tdbb, csb->csb_resources);
|
||||
CMP_post_access(tdbb, csb, r->rel_security_name, ssRelationId,
|
||||
SCL_select, obj_relations, r->rel_name);
|
||||
}
|
||||
|
||||
return this;
|
||||
@ -756,11 +757,11 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN
|
||||
// prepare to check protection of relation when a field in the stream of the
|
||||
// relation is accessed.
|
||||
|
||||
jrd_rel* const parentView = csb->csb_view;
|
||||
CachedResource<jrd_rel> const parentView = csb->csb_view;
|
||||
const StreamType viewStream = csb->csb_view_stream;
|
||||
|
||||
jrd_rel* relationView = relation;
|
||||
csb->csb_resources.postResource(tdbb, Resource::rsc_relation, relationView, relationView->rel_id);
|
||||
CachedResource<jrd_rel> relationView = relation;
|
||||
//csb->csb_resources.postResource(tdbb, Resource::rsc_relation, relationView, relationView->rel_id);
|
||||
view = parentView;
|
||||
|
||||
CompilerScratch::csb_repeat* const element = CMP_csb_element(csb, stream);
|
||||
@ -769,9 +770,9 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN
|
||||
|
||||
// in the case where there is a parent view, find the context name
|
||||
|
||||
if (parentView)
|
||||
if (parentView.isSet())
|
||||
{
|
||||
const ViewContexts& ctx = parentView->rel_view_contexts;
|
||||
const ViewContexts& ctx = parentView.get(tdbb, csb->csb_resources)->rel_view_contexts;
|
||||
const USHORT key = context;
|
||||
FB_SIZE_T pos;
|
||||
|
||||
@ -784,7 +785,7 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN
|
||||
|
||||
// check for a view - if not, nothing more to do
|
||||
|
||||
RseNode* viewRse = relationView->rel_view_rse;
|
||||
RseNode* viewRse = relationView.get(tdbb, csb->csb_resources)->rel_view_rse;
|
||||
if (!viewRse)
|
||||
return;
|
||||
|
||||
@ -795,7 +796,7 @@ void RelationSourceNode::pass1Source(thread_db* tdbb, CompilerScratch* csb, RseN
|
||||
|
||||
AutoSetRestore<USHORT> autoRemapVariable(&csb->csb_remap_variable,
|
||||
(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);
|
||||
|
||||
// We don't expand the view in two cases:
|
||||
@ -908,7 +909,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
|
||||
jrd_prc* procedure = nullptr;
|
||||
AutoPtr<string> aliasString;
|
||||
QualifiedName name;
|
||||
HazardPtr<jrd_prc> proc(FB_FUNCTION);
|
||||
CacheElement<jrd_prc>* proc = nullptr;
|
||||
|
||||
switch (blrOp)
|
||||
{
|
||||
@ -923,11 +924,8 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
|
||||
csb->csb_blr_reader.getString(*aliasString);
|
||||
}
|
||||
|
||||
proc = MetadataCache::lookup_procedure_id(tdbb, pid, false, false, 0);
|
||||
if (proc)
|
||||
procedure = csb->csb_resources.registerResource(tdbb, Resource::rsc_procedure, proc, proc->getId());
|
||||
|
||||
if (!procedure)
|
||||
proc = MetadataCache::lookupProcedure(tdbb, pid);
|
||||
if (!proc)
|
||||
name.identifier.printf("id %d", pid);
|
||||
break;
|
||||
}
|
||||
@ -1008,7 +1006,7 @@ ProcedureSourceNode* ProcedureSourceNode::parse(thread_db* tdbb, CompilerScratch
|
||||
ProcedureSourceNode* node = FB_NEW_POOL(*tdbb->getDefaultPool()) ProcedureSourceNode(
|
||||
*tdbb->getDefaultPool());
|
||||
|
||||
node->procedure = procedure;
|
||||
node->procedure = csb->csb_resources.procedures->registerResource(tdbb, proc);
|
||||
node->isSubRoutine = procedure->isSubRoutine();
|
||||
node->procedureId = node->isSubRoutine ? 0 : procedure->getId();
|
||||
|
||||
|
@ -358,8 +358,6 @@ public:
|
||||
: TypedNode<RecordSourceNode, RecordSourceNode::TYPE_RELATION>(pool),
|
||||
dsqlName(pool, aDsqlName),
|
||||
alias(pool),
|
||||
//relation(NULL),
|
||||
view(NULL),
|
||||
context(0)
|
||||
{
|
||||
}
|
||||
@ -418,10 +416,10 @@ public:
|
||||
public:
|
||||
MetaName dsqlName;
|
||||
Firebird::string alias; // SQL alias for the relation
|
||||
jrd_rel* relation;
|
||||
CachedResource<jrd_rel> relation;
|
||||
|
||||
private:
|
||||
jrd_rel* view; // parent view for posting access
|
||||
CachedResource<jrd_rel> view; // parent view for posting access
|
||||
|
||||
public:
|
||||
SSHORT context; // user-specified context number for the relation reference
|
||||
|
@ -43,8 +43,8 @@ using namespace Firebird;
|
||||
|
||||
/// jrd_rel
|
||||
|
||||
jrd_rel::jrd_rel(MemoryPool& p)
|
||||
: rel_pool(&p), rel_id(0), rel_current_fmt(0),
|
||||
jrd_rel::jrd_rel(MemoryPool& p, MetaId id)
|
||||
: rel_pool(&p), rel_id(id), rel_current_fmt(0),
|
||||
rel_flags(REL_gc_lockneed), rel_current_format(nullptr),
|
||||
rel_name(p), rel_owner_name(p), rel_security_name(p),
|
||||
rel_formats(nullptr), rel_fields(nullptr),
|
||||
@ -667,7 +667,7 @@ HazardPtr<IndexLock> jrd_rel::getIndexLock(thread_db* tdbb, USHORT id)
|
||||
SET_TDBB(tdbb);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
|
||||
HazardPtr<IndexLock> indexLock(FB_FUNCTION);
|
||||
HazardPtr<IndexLock> indexLock;
|
||||
if (rel_id < (USHORT) rel_MAX)
|
||||
return indexLock;
|
||||
|
||||
@ -692,5 +692,37 @@ const char* IndexLock::c_name() const
|
||||
return "* unk *";
|
||||
}
|
||||
|
||||
//extern
|
||||
HazardPtr<jrd_rel> Jrd::nullRel(FB_FUNCTION);
|
||||
static void jrd_rel::destroy(jrd_rel* rel)
|
||||
{
|
||||
rel->rel_flags |= REL_deleted;
|
||||
/*
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
LCK_release(tdbb, rel->rel_existence_lock);
|
||||
if (rel->rel_partners_lock)
|
||||
{
|
||||
rel->rel_flags |= REL_check_partners;
|
||||
LCK_release(tdbb, rel->rel_partners_lock);
|
||||
rel->rel_flags &= ~REL_check_partners;
|
||||
}
|
||||
LCK_release(tdbb, rel->rel_rescan_lock);
|
||||
*/
|
||||
// A lot more things to do !!!!!!!!!!!!!!!!
|
||||
|
||||
delete rel;
|
||||
}
|
||||
|
||||
static jrd_rel* jrd_rel::create(thread_db* tdbb, MetaId id)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
MetadataCache* mdc = dbb->dbb_mdc;
|
||||
MemoryPool& pool = mdc->getPool();
|
||||
|
||||
jrd_rel* relation = FB_NEW_POOL(pool) jrd_rel(pool, id);
|
||||
relation->scan(tdbb, mdc);
|
||||
|
||||
return relation;
|
||||
}
|
||||
|
@ -46,11 +46,9 @@ class IndexBlock;
|
||||
// Relation trigger definition
|
||||
|
||||
class Trigger : public CacheObject
|
||||
/*
|
||||
{
|
||||
/*
|
||||
public:
|
||||
typedef MetaName Key;
|
||||
|
||||
Firebird::HalfStaticArray<UCHAR, 128> blr; // BLR code
|
||||
Firebird::HalfStaticArray<UCHAR, 128> debugInfo; // Debug info
|
||||
Statement* statement; // Compiled statement
|
||||
@ -154,84 +152,15 @@ public:
|
||||
};
|
||||
|
||||
// Array of triggers (suppose separate arrays for triggers of different types)
|
||||
class TrigVector : public HazardArray<Trigger>
|
||||
class TrigVector
|
||||
{
|
||||
/*
|
||||
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;
|
||||
|
||||
void decompile(thread_db* tdbb);
|
||||
|
||||
void release();
|
||||
void release(thread_db* tdbb);
|
||||
virtual ~TrigVector() { }
|
||||
|
||||
~TrigVector()
|
||||
{
|
||||
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;
|
||||
virtual void addTrigger(thread_db* tdbb, Trigger* trigger) = 0;
|
||||
};
|
||||
|
||||
typedef std::atomic<TrigVector*> TrigVectorPtr;
|
||||
@ -445,11 +374,6 @@ public:
|
||||
|
||||
bool hasData() { return true; }
|
||||
const char* c_name() const override;
|
||||
|
||||
void removeFromCache(thread_db* tdbb) override
|
||||
{
|
||||
idl_lock.removeFromCache(tdbb);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -457,14 +381,12 @@ public:
|
||||
// in the database, though it is not really filled out until
|
||||
// the relation is scanned
|
||||
|
||||
class jrd_rel : public CacheObject
|
||||
class jrd_rel final : public CacheObject
|
||||
{
|
||||
typedef Firebird::HalfStaticArray<Record*, 4> GCRecordList;
|
||||
typedef HazardArray<IndexLock, 2> IndexLockList;
|
||||
typedef Firebird::ObjectsArray<IndexLock> IndexLocks;
|
||||
|
||||
public:
|
||||
typedef MetaName Key;
|
||||
|
||||
MemoryPool* rel_pool;
|
||||
USHORT rel_id;
|
||||
USHORT rel_current_fmt; // Current format number
|
||||
@ -492,7 +414,7 @@ public:
|
||||
Lock* rel_partners_lock; // partners lock
|
||||
Lock* rel_rescan_lock; // lock forcing relation to be scanned
|
||||
Lock* rel_gc_lock; // garbage collection lock
|
||||
IndexLockList rel_index_locks; // index existence locks
|
||||
IndexLocks rel_index_locks; // index existence locks
|
||||
//Firebird::Mutex rel_mtx_il; // controls addition & removal of elements
|
||||
IndexBlock* rel_index_blocks; // index blocks for caching index info
|
||||
TrigVectorPtr rel_pre_erase; // Pre-operation erase trigger
|
||||
@ -538,6 +460,16 @@ public:
|
||||
return rel_id;
|
||||
}
|
||||
|
||||
void scan(thread_db* tdbb);
|
||||
/*
|
||||
// Scan the relation if it hasn't already been scanned for meta data
|
||||
|
||||
- if (!(node->relation->rel_flags & REL_scanned) ||
|
||||
- (node->relation->rel_flags & REL_being_scanned))
|
||||
- {
|
||||
- MET_scan_relation(tdbb, this);
|
||||
- }
|
||||
*/
|
||||
bool delPages(thread_db* tdbb, TraNumber tran = MAX_TRA_NUMBER, RelationPages* aPages = NULL);
|
||||
void retainPages(thread_db* tdbb, TraNumber oldNumber, TraNumber newNumber);
|
||||
|
||||
@ -572,13 +504,8 @@ public:
|
||||
bool checkObject(thread_db* tdbb, Firebird::Arg::StatusVector&) override;
|
||||
void afterUnlock(thread_db* tdbb, unsigned flags) override;
|
||||
|
||||
void removeFromCache(thread_db* tdbb) override
|
||||
{
|
||||
if (rel_existence_lock)
|
||||
rel_existence_lock->removeFromCache(tdbb);
|
||||
else
|
||||
delayedDelete(tdbb);
|
||||
}
|
||||
static void destroy(jrd_rel *rel);
|
||||
static jrd_rel* create(thread_db* tdbb, MetaId id, CacheObject::Flag flags);
|
||||
|
||||
private:
|
||||
typedef Firebird::SortedArray<
|
||||
@ -595,7 +522,7 @@ private:
|
||||
RelationPages* getPagesInternal(thread_db* tdbb, TraNumber tran, bool allocPages);
|
||||
|
||||
public:
|
||||
explicit jrd_rel(MemoryPool& p);
|
||||
jrd_rel(MemoryPool& p, MetaId id);
|
||||
|
||||
// bool hasTriggers() const; unused ???????????????????
|
||||
void releaseTriggers(thread_db* tdbb, bool destroy);
|
||||
@ -646,8 +573,6 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
extern HazardPtr<jrd_rel> nullRel;
|
||||
|
||||
// rel_flags
|
||||
|
||||
const ULONG REL_scanned = 0x0001; // Field expressions scanned (or being scanned)
|
||||
|
@ -175,7 +175,7 @@ void Routine::parseBlr(thread_db* tdbb, CompilerScratch* csb, bid* blob_id, bid*
|
||||
flags &= ~Routine::FLAG_RELOAD;
|
||||
|
||||
Statement* statement = getStatement();
|
||||
PAR_blr(tdbb, nullRel, tmp.begin(), (ULONG) tmp.getCount(), NULL, &csb, &statement, false, 0);
|
||||
PAR_blr(tdbb, nullptr, tmp.begin(), (ULONG) tmp.getCount(), NULL, &csb, &statement, false, 0);
|
||||
setStatement(statement);
|
||||
|
||||
if (csb->csb_g_flags & csb_reload)
|
||||
@ -286,14 +286,6 @@ void Routine::afterUnlock(thread_db* tdbb, unsigned fl)
|
||||
}
|
||||
}
|
||||
|
||||
void Routine::removeFromCache(thread_db* tdbb)
|
||||
{
|
||||
if (existenceLock)
|
||||
existenceLock->removeFromCache(tdbb);
|
||||
else
|
||||
delayedDelete(tdbb);
|
||||
}
|
||||
|
||||
int Routine::getUseCount() const
|
||||
{
|
||||
return existenceLock.hasData() ? existenceLock->getUseCount() : 1;
|
||||
@ -368,11 +360,6 @@ bool jrd_prc::checkCache(thread_db* tdbb) const
|
||||
return tdbb->getDatabase()->dbb_mdc->getProcedure(tdbb, getId()) == this;
|
||||
}
|
||||
|
||||
void jrd_prc::clearCache(thread_db* tdbb)
|
||||
{
|
||||
tdbb->getDatabase()->dbb_mdc->setProcedure(tdbb, getId(), nullptr);
|
||||
}
|
||||
|
||||
void Routine::releaseLocks(thread_db* tdbb)
|
||||
{
|
||||
if (existenceLock)
|
||||
|
@ -96,7 +96,29 @@ namespace Jrd
|
||||
protected:
|
||||
explicit Routine(MemoryPool& p)
|
||||
: PermanentStorage(p),
|
||||
id(0),
|
||||
id(~0),
|
||||
name(p),
|
||||
securityName(p),
|
||||
statement(NULL),
|
||||
subRoutine(true),
|
||||
implemented(true),
|
||||
defined(true),
|
||||
defaultCount(0),
|
||||
inputFormat(NULL),
|
||||
outputFormat(NULL),
|
||||
inputFields(p),
|
||||
outputFields(p),
|
||||
flags(0),
|
||||
intUseCount(0),
|
||||
alterCount(0),
|
||||
existenceLock(NULL),
|
||||
invoker(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
explicit Routine(MemoryPool& p, MetaId metaId)
|
||||
: PermanentStorage(p),
|
||||
id(metaId),
|
||||
name(p),
|
||||
securityName(p),
|
||||
statement(NULL),
|
||||
@ -141,6 +163,11 @@ namespace Jrd
|
||||
static Format* createFormat(MemoryPool& pool, Firebird::IMessageMetadata* params, bool addEof);
|
||||
|
||||
public:
|
||||
static void destroy(Routine* routine)
|
||||
{
|
||||
delete routine;
|
||||
}
|
||||
|
||||
USHORT getId() const
|
||||
{
|
||||
fb_assert(!subRoutine);
|
||||
@ -156,8 +183,6 @@ namespace Jrd
|
||||
const MetaName& getSecurityName() const { return securityName; }
|
||||
void setSecurityName(const MetaName& value) { securityName = value; }
|
||||
|
||||
void removeFromCache(thread_db* tdbb) override;
|
||||
|
||||
/*const*/ Statement* getStatement() const { return statement; }
|
||||
void setStatement(Statement* value);
|
||||
|
||||
@ -204,7 +229,7 @@ namespace Jrd
|
||||
}
|
||||
|
||||
void afterDecrement(Jrd::thread_db*);
|
||||
void afterUnlock(thread_db* tdbb, unsigned fl);
|
||||
void afterUnlock(thread_db* tdbb, unsigned fl) override;
|
||||
void releaseStatement(thread_db* tdbb);
|
||||
//void remove(thread_db* tdbb);
|
||||
virtual void releaseExternal()
|
||||
@ -221,7 +246,6 @@ namespace Jrd
|
||||
virtual int getObjectType() const = 0;
|
||||
virtual SLONG getSclType() const = 0;
|
||||
virtual bool checkCache(thread_db* tdbb) const = 0;
|
||||
virtual void clearCache(thread_db* tdbb) = 0;
|
||||
|
||||
private:
|
||||
USHORT id; // routine ID
|
||||
@ -256,8 +280,6 @@ namespace Jrd
|
||||
|
||||
MetaName owner;
|
||||
Jrd::UserId* invoker; // Invoker ID
|
||||
|
||||
typedef QualifiedName Key;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
|
||||
TraceCounts traceCounts;
|
||||
traceCounts.trc_relation_id = rel_id;
|
||||
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;
|
||||
temp.add(traceCounts);
|
||||
}
|
||||
@ -127,7 +127,7 @@ PerformanceInfo* RuntimeStatistics::computeDifference(Attachment* att,
|
||||
TraceCounts traceCounts;
|
||||
traceCounts.trc_relation_id = rel_id;
|
||||
traceCounts.trc_counters = new_cnts->getCounterVector();
|
||||
HazardPtr<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;
|
||||
temp.add(traceCounts);
|
||||
}
|
||||
|
@ -340,9 +340,9 @@ const Routine* Statement::getRoutine() const
|
||||
// Determine if any request of this statement are active.
|
||||
bool Statement::isActive() const
|
||||
{
|
||||
for (const Request* const* request = requests.begin(); request != requests.end(); ++request)
|
||||
for (auto request : requests)
|
||||
{
|
||||
if (*request && ((*request)->req_flags & req_in_use))
|
||||
if (request && request->isUsed())
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -372,7 +372,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique)
|
||||
|
||||
if (next->req_attachment == attachment)
|
||||
{
|
||||
if (!(next->req_flags & req_in_use))
|
||||
if (!next->isUsed())
|
||||
{
|
||||
clone = next;
|
||||
break;
|
||||
@ -383,7 +383,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique)
|
||||
|
||||
++count;
|
||||
}
|
||||
else if (!(next->req_flags & req_in_use) && !clone)
|
||||
else if (!(next->isUsed()) && !clone)
|
||||
clone = next;
|
||||
}
|
||||
|
||||
@ -396,7 +396,7 @@ Request* Statement::findRequest(thread_db* tdbb, bool unique)
|
||||
clone->setAttachment(attachment);
|
||||
clone->req_stats.reset();
|
||||
clone->req_base_stats.reset();
|
||||
clone->req_flags |= req_in_use;
|
||||
clone->setUsed(true);
|
||||
|
||||
return clone;
|
||||
}
|
||||
@ -442,7 +442,7 @@ void Statement::verifyAccess(thread_db* tdbb)
|
||||
|
||||
for (ExternalAccess* item = external.begin(); item != external.end(); ++item)
|
||||
{
|
||||
HazardPtr<Routine> routine(tdbb, FB_FUNCTION);
|
||||
HazardPtr<Routine> routine(tdbb);
|
||||
int aclType;
|
||||
|
||||
if (item->exa_action == ExternalAccess::exa_procedure)
|
||||
@ -471,7 +471,7 @@ void Statement::verifyAccess(thread_db* tdbb)
|
||||
}
|
||||
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)
|
||||
continue;
|
||||
@ -479,7 +479,7 @@ void Statement::verifyAccess(thread_db* tdbb)
|
||||
MetaName userName = item->user;
|
||||
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))
|
||||
userName = view->rel_owner_name;
|
||||
}
|
||||
@ -515,7 +515,7 @@ void Statement::verifyAccess(thread_db* tdbb)
|
||||
|
||||
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))
|
||||
userName = view->rel_owner_name;
|
||||
}
|
||||
@ -583,7 +583,7 @@ void Statement::verifyAccess(thread_db* tdbb)
|
||||
|
||||
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))
|
||||
userName = view->rel_owner_name;
|
||||
}
|
||||
@ -658,7 +658,7 @@ string Statement::getPlan(thread_db* tdbb, bool detailed) const
|
||||
}
|
||||
|
||||
// Check that we have enough rights to access all resources this list of triggers touches.
|
||||
void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr<jrd_rel>& ownerRelation,
|
||||
void Statement::verifyTriggerAccess(thread_db* tdbb, const jrd_rel* ownerRelation,
|
||||
TrigVector* triggers, MetaName userName)
|
||||
{
|
||||
if (!triggers)
|
||||
@ -668,7 +668,7 @@ void Statement::verifyTriggerAccess(thread_db* tdbb, const HazardPtr<jrd_rel>& o
|
||||
|
||||
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))
|
||||
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
|
||||
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))
|
||||
userName = view->rel_owner_name;
|
||||
}
|
||||
@ -733,7 +733,7 @@ inline void Statement::triggersExternalAccess(thread_db* tdbb, ExternalAccessLis
|
||||
|
||||
for (FB_SIZE_T i = 0; i < tvec->getCount(tdbb); i++)
|
||||
{
|
||||
HazardPtr<Trigger> t(tdbb, FB_FUNCTION);
|
||||
HazardPtr<Trigger> t(tdbb);
|
||||
if (!tvec->load(tdbb, i, t))
|
||||
continue;
|
||||
|
||||
@ -769,7 +769,7 @@ void Statement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list, c
|
||||
}
|
||||
else if (item->exa_action == ExternalAccess::exa_function)
|
||||
{
|
||||
HazardPtr<Function> function = Function::lookup(tdbb, item->exa_fun_id, false, false, 0);
|
||||
Function* function = Function::lookup(tdbb, item->exa_fun_id, false, false, 0);
|
||||
if (function && function->getStatement())
|
||||
{
|
||||
item->user = function->invoker ? MetaName(function->invoker->getUserName()) : user;
|
||||
@ -781,7 +781,7 @@ void Statement::buildExternalAccess(thread_db* tdbb, ExternalAccessList& list, c
|
||||
}
|
||||
else
|
||||
{
|
||||
HazardPtr<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)
|
||||
continue;
|
||||
@ -912,6 +912,32 @@ StmtNumber Request::getRequestId() const
|
||||
return req_id;
|
||||
}
|
||||
|
||||
Request::Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement)
|
||||
: statement(aStatement),
|
||||
req_pool(pool),
|
||||
req_memory_stats(&aStatement->pool->getStatsGroup()),
|
||||
req_blobs(req_pool),
|
||||
req_stats(*req_pool),
|
||||
req_base_stats(*req_pool),
|
||||
req_ext_stmt(NULL),
|
||||
req_cursors(*req_pool),
|
||||
req_ext_resultset(NULL),
|
||||
req_timeout(0),
|
||||
req_domain_validation(NULL),
|
||||
req_auto_trans(*req_pool),
|
||||
req_sorts(*req_pool),
|
||||
req_rpb(*req_pool),
|
||||
impureArea(*req_pool)
|
||||
{
|
||||
fb_assert(statement);
|
||||
setAttachment(attachment);
|
||||
req_rpb = statement->rpbsSetup;
|
||||
impureArea.grow(statement->impureSize);
|
||||
|
||||
pool->setStatsGroup(req_memory_stats);
|
||||
pool.release();
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEV_BUILD
|
||||
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
Firebird::string getPlan(thread_db* tdbb, bool detailed) const;
|
||||
|
||||
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);
|
||||
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
|
||||
ExternalAccessList externalList; // Access to procedures/triggers to be checked
|
||||
AccessItemList accessList; // Access items to be checked
|
||||
ResourceList resources; // Resources (relations and indices)
|
||||
//ResourceList resources; // Resources (relations and indices)
|
||||
const jrd_prc* procedure; // procedure, if any
|
||||
const Function* function; // function, if any
|
||||
MetaName triggerName; // name of request (trigger), if any
|
||||
@ -112,6 +112,10 @@ public:
|
||||
Firebird::RefStrPtr sqlText; // SQL text (encoded in the metadata charset)
|
||||
Firebird::Array<UCHAR> blr; // BLR for non-SQL query
|
||||
MapFieldInfo mapFieldInfo; // Map field name to field info
|
||||
|
||||
private:
|
||||
Resources resources;
|
||||
Firebird::RefPtr<VersionedObjects> latestVersion;
|
||||
};
|
||||
|
||||
|
||||
|
@ -5311,7 +5311,7 @@ dsc* evlMakeDbkey(Jrd::thread_db* tdbb, const SysFunction* function, const NestV
|
||||
MetaName 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)
|
||||
(Arg::Gds(isc_relnotdef) << Arg::Str(relName)).raise();
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "../common/classes/ClumpletWriter.h"
|
||||
#include "../jrd/jrd.h"
|
||||
#include "../jrd/ini_proto.h"
|
||||
#include "../jrd/lck_proto.h"
|
||||
#include "../jrd/lck.h"
|
||||
#include "../jrd/pag_proto.h"
|
||||
#include "../jrd/tra_proto.h"
|
||||
#include "../jrd/status.h"
|
||||
|
@ -1445,7 +1445,7 @@ blb* blb::open2(thread_db* tdbb,
|
||||
// know about the relation, the blob id has got to be invalid
|
||||
// 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)
|
||||
ERR_post(Arg::Gds(isc_bad_segstr_id));
|
||||
|
||||
@ -1743,7 +1743,7 @@ void blb::put_slice(thread_db* tdbb,
|
||||
if (SDL_info(tdbb->tdbb_status_vector, sdl, &info, 0))
|
||||
ERR_punt();
|
||||
|
||||
HazardPtr<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::findRelation(tdbb, info.sdl_info_rid);
|
||||
|
||||
|
@ -566,8 +566,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record
|
||||
fb_assert(!conditionRequest->req_caller);
|
||||
conditionRequest->req_caller = orgRequest;
|
||||
|
||||
conditionRequest->req_flags &= req_in_use;
|
||||
conditionRequest->req_flags |= req_active;
|
||||
conditionRequest->req_flags = req_active;
|
||||
TRA_attach_request(tdbb->getTransaction(), conditionRequest);
|
||||
tdbb->setRequest(conditionRequest);
|
||||
|
||||
@ -598,7 +597,7 @@ bool BTR_check_condition(Jrd::thread_db* tdbb, Jrd::index_desc* idx, Jrd::Record
|
||||
}
|
||||
|
||||
EXE_unwind(tdbb, conditionRequest);
|
||||
conditionRequest->req_flags &= ~req_in_use;
|
||||
conditionRequest->setUsed(false);
|
||||
conditionRequest->req_attachment = nullptr;
|
||||
|
||||
tdbb->setRequest(orgRequest);
|
||||
@ -626,8 +625,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool&
|
||||
fb_assert(!expr_request->req_caller);
|
||||
expr_request->req_caller = org_request;
|
||||
|
||||
expr_request->req_flags &= req_in_use;
|
||||
expr_request->req_flags |= req_active;
|
||||
expr_request->req_flags = req_active;
|
||||
TRA_attach_request(tdbb->getTransaction(), expr_request);
|
||||
TRA_setup_request_snapshot(tdbb, expr_request);
|
||||
tdbb->setRequest(expr_request);
|
||||
@ -661,7 +659,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool&
|
||||
tdbb->setRequest(org_request);
|
||||
|
||||
expr_request->req_caller = NULL;
|
||||
expr_request->req_flags &= ~req_in_use;
|
||||
expr_request->setUsed(false);
|
||||
expr_request->req_attachment = NULL;
|
||||
expr_request->invalidateTimeStamp();
|
||||
|
||||
@ -672,7 +670,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool&
|
||||
tdbb->setRequest(org_request);
|
||||
|
||||
expr_request->req_caller = NULL;
|
||||
expr_request->req_flags &= ~req_in_use;
|
||||
expr_request->setUsed(false);
|
||||
expr_request->req_attachment = NULL;
|
||||
expr_request->invalidateTimeStamp();
|
||||
|
||||
@ -6203,13 +6201,13 @@ string print_key(thread_db* tdbb, jrd_rel* relation, index_desc* idx, Record* re
|
||||
string key;
|
||||
|
||||
fb_assert(relation && idx && record);
|
||||
HazardPtr<jrd_rel> wrk = MET_scan_relation(tdbb, relation->rel_id);
|
||||
jrd_rel* wrk = MET_scan_relation(tdbb, relation->rel_id);
|
||||
if (!wrk)
|
||||
{
|
||||
key.printf("(target relation %s deleted)", relation->c_name());
|
||||
return key;
|
||||
}
|
||||
relation = wrk.getPointer();
|
||||
relation = wrk;
|
||||
|
||||
const FB_SIZE_T MAX_KEY_STRING_LEN = 250;
|
||||
string value;
|
||||
|
@ -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_transaction(transaction),
|
||||
m_locks()
|
||||
@ -382,7 +382,7 @@ public:
|
||||
unlock();
|
||||
}
|
||||
|
||||
void addRelation(HazardPtr<jrd_rel>& relation)
|
||||
void addRelation(jrd_rel* relation)
|
||||
{
|
||||
FB_SIZE_T pos;
|
||||
if (!m_locks.find(relation->rel_id, pos))
|
||||
@ -410,7 +410,7 @@ public:
|
||||
private:
|
||||
struct relLock
|
||||
{
|
||||
relLock(HazardPtr<jrd_rel> relation = HazardPtr<jrd_rel>(FB_FUNCTION)) :
|
||||
relLock(jrd_rel* relation = nullptr) :
|
||||
m_relation(relation),
|
||||
m_lock(NULL),
|
||||
m_release(false)
|
||||
@ -433,7 +433,7 @@ private:
|
||||
return &item->m_relation->rel_id;
|
||||
}
|
||||
|
||||
HazardPtr<jrd_rel> m_relation;
|
||||
jrd_rel* m_relation;
|
||||
Lock* m_lock;
|
||||
bool m_release;
|
||||
};
|
||||
@ -509,12 +509,12 @@ static bool formatsAreEqual(const Format*, const Format*);
|
||||
static bool find_depend_in_dfw(thread_db*, TEXT*, USHORT, USHORT, jrd_tra*);
|
||||
static void get_array_desc(thread_db*, const TEXT*, Ods::InternalArrayDesc*);
|
||||
static void get_trigger_dependencies(DeferredWork*, bool, jrd_tra*);
|
||||
static Format* make_format(thread_db*, HazardPtr<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_record(thread_db* tdbb, blb*, enum rsr_t, const UCHAR*, ULONG);
|
||||
static void setup_array(thread_db*, blb*, const TEXT*, USHORT, TemporaryField*);
|
||||
static blb* setup_triggers(thread_db*, HazardPtr<jrd_rel>&, bool, TrigVectorPtr*, blb*);
|
||||
static void setup_trigger_details(thread_db*, HazardPtr<jrd_rel>&, blb*, TrigVectorPtr*, const TEXT*, bool);
|
||||
static blb* setup_triggers(thread_db*, jrd_rel*, bool, TrigVectorPtr*, blb*);
|
||||
static void setup_trigger_details(thread_db*, jrd_rel*, blb*, TrigVectorPtr*, const TEXT*, bool);
|
||||
static bool validate_text_type (thread_db*, const TemporaryField*);
|
||||
|
||||
static void check_partners(thread_db*, const USHORT);
|
||||
@ -587,7 +587,7 @@ static void raiseObjectInUseError(const string& obj_type, const string& obj_name
|
||||
Arg::Gds(isc_obj_in_use) << Arg::Str(name));
|
||||
}
|
||||
|
||||
static void raiseRelationInUseError(const HazardPtr<jrd_rel>& relation)
|
||||
static void raiseRelationInUseError(const jrd_rel* relation)
|
||||
{
|
||||
const string obj_type =
|
||||
relation->isView() ? "VIEW" : "TABLE";
|
||||
@ -724,7 +724,7 @@ namespace
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
const QualifiedName name(work->dfw_name, work->dfw_package);
|
||||
HazardPtr<Routine> routine(FB_FUNCTION);
|
||||
HazardPtr<Routine> routine;
|
||||
|
||||
fprintf(stderr, "routine %d %s ph %d\n", work->dfw_id, name.c_str(), phase);
|
||||
|
||||
@ -869,7 +869,7 @@ namespace
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
const QualifiedName name(work->dfw_name, work->dfw_package);
|
||||
HazardPtr<T> routine(FB_FUNCTION);
|
||||
HazardPtr<T> routine;
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
@ -996,7 +996,7 @@ namespace
|
||||
// works in not deleted context
|
||||
{
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
MET_get_dependencies(tdbb, nullRel, NULL, 0, NULL, &blobId,
|
||||
MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &blobId,
|
||||
(compile ? &statement : NULL),
|
||||
NULL, depName,
|
||||
(work->dfw_package.isEmpty() ? objType : obj_package_body),
|
||||
@ -1097,7 +1097,7 @@ namespace
|
||||
{
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest handle(tdbb, irq_c_fun_dpd, IRQ_REQUESTS);
|
||||
HazardPtr<Routine> routine(tdbb, FB_FUNCTION);
|
||||
HazardPtr<Routine> routine(tdbb);
|
||||
|
||||
FOR(REQUEST_HANDLE handle)
|
||||
X IN RDB$FUNCTIONS WITH
|
||||
@ -1142,7 +1142,7 @@ namespace
|
||||
{
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
AutoCacheRequest handle(tdbb, irq_c_prc_dpd, IRQ_REQUESTS);
|
||||
HazardPtr<Routine> routine(tdbb, FB_FUNCTION);
|
||||
HazardPtr<Routine> routine(tdbb);
|
||||
|
||||
FOR(REQUEST_HANDLE handle)
|
||||
X IN RDB$PROCEDURES WITH
|
||||
@ -2365,7 +2365,7 @@ static bool check_not_null(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
|
||||
|
||||
case 3:
|
||||
{
|
||||
HazardPtr<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())
|
||||
break;
|
||||
|
||||
@ -2706,7 +2706,7 @@ static bool create_expression_index(thread_db* tdbb, SSHORT phase, DeferredWork*
|
||||
|
||||
case 3:
|
||||
{
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation;
|
||||
CompilerScratch* csb = nullptr;
|
||||
|
||||
const auto dbb = tdbb->getDatabase();
|
||||
@ -3087,7 +3087,7 @@ static void cleanup_index_creation(thread_db* tdbb, DeferredWork* work, jrd_tra*
|
||||
// dimitr: I have no idea why the condition below is required here
|
||||
AND IREL.RDB$VIEW_BLR MISSING // views do not have indices
|
||||
{
|
||||
HazardPtr<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);
|
||||
|
||||
if (relPages && relPages->rel_index_root)
|
||||
@ -3130,7 +3130,7 @@ static void cleanup_index_creation(thread_db* tdbb, DeferredWork* work, jrd_tra*
|
||||
idx.idx_id = idx_invalid;
|
||||
idx.idx_flags = idx_foreign;
|
||||
|
||||
HazardPtr<jrd_rel> partner_relation(FB_FUNCTION);
|
||||
jrd_rel* partner_relation = nullptr;
|
||||
if (MET_lookup_partner(tdbb, relation.unsafePointer(), &idx, work->dfw_name.c_str()))
|
||||
{
|
||||
partner_relation = MetadataCache::lookup_relation_id(tdbb, idx.idx_primary_relation, true);
|
||||
@ -3287,7 +3287,7 @@ static bool modify_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
}
|
||||
|
||||
bool gtt_preserve = false;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
|
||||
if (is_create)
|
||||
{
|
||||
@ -3353,8 +3353,8 @@ static bool create_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
*
|
||||
**************************************/
|
||||
AutoCacheRequest request;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
HazardPtr<jrd_rel> partner_relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
jrd_rel* partner_relation = nullptr;
|
||||
index_desc idx;
|
||||
int key_count;
|
||||
|
||||
@ -3711,7 +3711,7 @@ static bool create_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
*
|
||||
**************************************/
|
||||
AutoCacheRequest request;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
USHORT rel_id, external_flag;
|
||||
bid blob_id;
|
||||
AutoRequest handle;
|
||||
@ -4206,7 +4206,7 @@ void DFW_reset_icu(thread_db* tdbb)
|
||||
USHORT rel_id = rs->getInt(tdbb, 2);
|
||||
if (!tables.exists(rel_id))
|
||||
{
|
||||
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false);
|
||||
jrd_rel* relation = MetadataCache::lookup_relation_id(tdbb, rel_id, false);
|
||||
if (relation)
|
||||
tables.addRelation(relation);
|
||||
}
|
||||
@ -4450,7 +4450,7 @@ static bool create_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
MemoryPool* new_pool = dbb->createPool();
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
|
||||
MET_get_dependencies(tdbb, nullRel, NULL, 0, NULL, &validation,
|
||||
MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &validation,
|
||||
NULL, NULL, depName, obj_validation, 0, transaction, depName);
|
||||
|
||||
dbb->deletePool(new_pool);
|
||||
@ -4615,7 +4615,7 @@ static bool modify_field(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
MemoryPool* new_pool = dbb->createPool();
|
||||
Jrd::ContextPoolHolder context(tdbb, new_pool);
|
||||
|
||||
MET_get_dependencies(tdbb, nullRel, NULL, 0, NULL, &validation,
|
||||
MET_get_dependencies(tdbb, nullptr, NULL, 0, NULL, &validation,
|
||||
NULL, NULL, depName, obj_validation, 0, transaction, depName);
|
||||
|
||||
dbb->deletePool(new_pool);
|
||||
@ -4695,7 +4695,7 @@ static void check_partners(thread_db* tdbb, const USHORT rel_id)
|
||||
*
|
||||
**************************************/
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
HazardPtr<jrd_rel> relation = dbb->dbb_mdc->getRelation(tdbb, rel_id);
|
||||
jrd_rel* relation = dbb->dbb_mdc->getRelation(tdbb, rel_id);
|
||||
fb_assert(relation);
|
||||
|
||||
relation->rel_flags |= REL_check_partners;
|
||||
@ -4715,7 +4715,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
* Functional description
|
||||
*
|
||||
**************************************/
|
||||
HazardPtr<IndexLock> index(FB_FUNCTION);
|
||||
HazardPtr<IndexLock> index;
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
@ -4731,7 +4731,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
// Look up the relation. If we can't find the relation,
|
||||
// don't worry about the index.
|
||||
|
||||
HazardPtr<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) {
|
||||
return false;
|
||||
}
|
||||
@ -4841,8 +4841,7 @@ static bool delete_index(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_
|
||||
ERR_post(Arg::Gds(isc_random) << "Index block gone unexpestedly");
|
||||
fb_assert(!arrVal);
|
||||
index->idl_lock.releaseLock(tdbb, ExistenceLock::ReleaseMethod::DropObject);
|
||||
// fprintf(stderr, "delayedDelete index, replace NULL, to be reviewed\n");
|
||||
// --- index->delayedDelete(tdbb);
|
||||
index->retire();
|
||||
|
||||
// Release index refresh lock and memory.
|
||||
for (IndexBlock** iptr = &relation->rel_index_blocks; *iptr; iptr = &(*iptr)->idb_next)
|
||||
@ -4922,7 +4921,7 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
*
|
||||
**************************************/
|
||||
AutoRequest request;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
Resource* rsc;
|
||||
USHORT view_count;
|
||||
bool adjusted;
|
||||
@ -5004,22 +5003,6 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
// ?????????? MutexLockGuard g(dbb->dbb_mdc->mdc_use_mutex, FB_FUNCTION);
|
||||
|
||||
adjusted = false;
|
||||
if (relation->rel_existence_lock->getUseCount() == 1)
|
||||
{
|
||||
for (auto rsc : transaction->tra_resources.getObjects(Resource::rsc_relation))
|
||||
{
|
||||
if (rsc->rsc_rel == relation)
|
||||
{
|
||||
relation->rel_existence_lock->dec(tdbb);
|
||||
adjusted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (relation->rel_existence_lock->getUseCount())
|
||||
MetadataCache::clear_cache(tdbb);
|
||||
|
||||
if (!relation->rel_existence_lock->exclLock(tdbb))
|
||||
/////// ??????? !LCK_convert(tdbb, relation->rel_existence_lock, LCK_EX, transaction->getLockWait())))
|
||||
{
|
||||
@ -5038,7 +5021,7 @@ static bool delete_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
relation->rel_flags |= REL_deleting;
|
||||
{ // scope
|
||||
EngineCheckout cout(tdbb, FB_FUNCTION);
|
||||
relation->rel_drop_mutex.enter(FB_FUNCTION);
|
||||
relation->rel_drop_mutex.enter;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -5165,7 +5148,7 @@ static bool delete_rfr(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_tr
|
||||
int rel_exists, field_count;
|
||||
AutoRequest handle;
|
||||
MetaName f;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
@ -5565,7 +5548,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra*
|
||||
if (compile)
|
||||
compile = !tdbb->getAttachment()->isGbak();
|
||||
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
bid blob_id;
|
||||
blob_id.clear();
|
||||
|
||||
@ -5611,7 +5594,7 @@ static void get_trigger_dependencies(DeferredWork* work, bool compile, jrd_tra*
|
||||
}
|
||||
|
||||
|
||||
static Format* make_format(thread_db* tdbb, HazardPtr<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* external;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
//bid blob_id;
|
||||
//blob_id.clear();
|
||||
|
||||
@ -6351,7 +6334,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
|
||||
|
||||
try
|
||||
{
|
||||
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation(tdbb, relation_name);
|
||||
jrd_rel* relation = MetadataCache::lookup_relation(tdbb, relation_name);
|
||||
|
||||
if (relation)
|
||||
{
|
||||
@ -6375,7 +6358,7 @@ static bool modify_trigger(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr
|
||||
{
|
||||
if (triggers[i])
|
||||
{
|
||||
HazardPtr<Trigger> trig(tdbb, FB_FUNCTION);
|
||||
HazardPtr<Trigger> trig(tdbb);
|
||||
for (FB_SIZE_T j = 0; j < triggers[i].load()->getCount(tdbb); ++j)
|
||||
{
|
||||
if (triggers[i].load()->load(tdbb, j, trig))
|
||||
@ -6502,7 +6485,7 @@ static bool scan_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd
|
||||
**************************************/
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
HazardPtr<jrd_rel> rel(FB_FUNCTION);
|
||||
jrd_rel* rel = nullptr;
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
@ -6632,7 +6615,7 @@ static void setup_array(thread_db* tdbb, blb* blob, const TEXT* field_name, USHO
|
||||
}
|
||||
|
||||
|
||||
static blb* setup_triggers(thread_db* tdbb, HazardPtr<jrd_rel>& relation, bool null_view,
|
||||
static blb* setup_triggers(thread_db* tdbb, jrd_rel* relation, bool null_view,
|
||||
TrigVectorPtr* triggers, blb* blob)
|
||||
{
|
||||
/**************************************
|
||||
@ -6729,7 +6712,7 @@ static blb* setup_triggers(thread_db* tdbb, HazardPtr<jrd_rel>& relation, bool n
|
||||
|
||||
|
||||
static void setup_trigger_details(thread_db* tdbb,
|
||||
HazardPtr<jrd_rel>& relation,
|
||||
jrd_rel* relation,
|
||||
blb* blob,
|
||||
TrigVectorPtr* triggers,
|
||||
const TEXT* trigger_name,
|
||||
|
@ -2019,7 +2019,7 @@ void DPM_scan_pages( thread_db* tdbb)
|
||||
// infinite recursion from this internal request when RDB$PAGES
|
||||
// has been extended with another pointer page.
|
||||
|
||||
HazardPtr<jrd_rel> relation = MetadataCache::findRelation(tdbb, 0);
|
||||
jrd_rel* relation = MetadataCache::findRelation(tdbb, 0);
|
||||
RelationPages* relPages = relation->getBasePages();
|
||||
|
||||
vcl** address = &relPages->rel_pages;
|
||||
|
@ -778,7 +778,7 @@ void EXE_release(thread_db* tdbb, Request* request)
|
||||
request->req_attachment = NULL;
|
||||
}
|
||||
|
||||
request->req_flags &= ~req_in_use;
|
||||
request->setUsed(false);
|
||||
}
|
||||
|
||||
|
||||
@ -890,9 +890,9 @@ void EXE_start(thread_db* tdbb, Request* request, jrd_tra* transaction)
|
||||
TRA_post_resources(tdbb, transaction, statement->resources);
|
||||
|
||||
TRA_attach_request(transaction, request);
|
||||
request->req_flags &= req_in_use | req_restart_ready;
|
||||
request->req_flags &= req_restart_ready;
|
||||
request->req_flags |= req_active;
|
||||
request->req_flags &= ~req_reserved;
|
||||
// ????????? request->req_flags &= ~req_reserved;
|
||||
|
||||
// set up to count records affected by request
|
||||
|
||||
@ -1245,7 +1245,7 @@ void EXE_execute_triggers(thread_db* tdbb,
|
||||
|
||||
EXE_unwind(tdbb, trigger);
|
||||
trigger->req_attachment = NULL;
|
||||
trigger->req_flags &= ~req_in_use;
|
||||
trigger->setUsed(false);
|
||||
|
||||
if (!ok)
|
||||
trigger_failure(tdbb, trigger);
|
||||
@ -1265,7 +1265,7 @@ void EXE_execute_triggers(thread_db* tdbb,
|
||||
{
|
||||
EXE_unwind(tdbb, trigger);
|
||||
trigger->req_attachment = NULL;
|
||||
trigger->req_flags &= ~req_in_use;
|
||||
trigger->setUsed(false);
|
||||
|
||||
ex.stuffException(tdbb->tdbb_status_vector);
|
||||
|
||||
@ -1717,10 +1717,6 @@ void ResourceList::setResetPointersHazard(thread_db* tdbb, bool set)
|
||||
if (hazardFlag != set)
|
||||
{
|
||||
// (un-)register hazard pointers
|
||||
HazardDelayedDelete* hazardDelayed = nullptr;
|
||||
if (list.hasData())
|
||||
hazardDelayed = HazardBase::getHazardDelayed(tdbb);
|
||||
|
||||
for (auto r : list)
|
||||
{
|
||||
void* hazardPointer = nullptr;
|
||||
|
275
src/jrd/exe.h
275
src/jrd/exe.h
@ -34,6 +34,7 @@
|
||||
|
||||
#include "../jrd/blb.h"
|
||||
#include "../jrd/Relation.h"
|
||||
#include "../jrd/CharSetContainer.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../jrd/MetaName.h"
|
||||
#include "../common/classes/fb_pair.h"
|
||||
@ -167,214 +168,96 @@ struct impure_agg_sort
|
||||
};
|
||||
|
||||
|
||||
// Resources list
|
||||
template <class OBJ> class CacheElement;
|
||||
|
||||
class ResourceList
|
||||
class Resources
|
||||
{
|
||||
typedef Firebird::SortedArray<Resource, Firebird::EmptyStorage<Resource>,
|
||||
Resource, Firebird::DefaultKeyValue<Resource>, Resource> InternalResourceList;
|
||||
public:
|
||||
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:
|
||||
ResourceList(MemoryPool& p, bool hazard)
|
||||
: list(p), hazardFlag(hazard)
|
||||
template <class OBJ> const RscArray<OBJ>& objects() const;
|
||||
|
||||
Resources(MemoryPool& p)
|
||||
: charSets(p), relations(p), procedures(p), functions(p), triggers(p)
|
||||
{ }
|
||||
|
||||
typedef Firebird::Bits<Resource::rsc_MAX> ResourceTypes;
|
||||
typedef Firebird::HalfStaticArray<FB_SIZE_T, 128> NewResources;
|
||||
RscArray<CharSetContainer> charSets;
|
||||
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>
|
||||
T* registerResource(thread_db* tdbb, Resource::rsc_s type, const HazardPtr<T>& object, USHORT id)
|
||||
bool isSet() const;
|
||||
/*
|
||||
operator OBJ*() const
|
||||
{
|
||||
fb_assert(type != Resource::rsc_index);
|
||||
|
||||
T* ptr = object.getPointer();
|
||||
Resource r(type, id, ptr);
|
||||
FB_SIZE_T pos;
|
||||
if (!list.find(r, pos))
|
||||
{
|
||||
list.insert(pos, r);
|
||||
HazardPtr<T>::getHazardDelayed(tdbb)->add(ptr, FB_FUNCTION);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
return getPtr();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void postResource(thread_db* tdbb, Resource::rsc_s type, T* ptr, USHORT id)
|
||||
OBJ* operator->() const
|
||||
{
|
||||
fb_assert(hazardFlag);
|
||||
|
||||
Resource r(type, id, ptr);
|
||||
FB_SIZE_T pos;
|
||||
|
||||
if (type == Resource::rsc_index)
|
||||
{
|
||||
Resource r1 = r;
|
||||
r1.rsc_id = r1.rsc_rel->rel_id;
|
||||
r1.rsc_type = Resource::rsc_relation;
|
||||
|
||||
if (!list.find(r1, pos))
|
||||
raiseNotRegistered(r, type, ptr->c_name());
|
||||
|
||||
if (!list.find(r, pos))
|
||||
list.insert(pos, r);
|
||||
}
|
||||
|
||||
else if (!list.find(r, pos))
|
||||
raiseNotRegistered(r, type, ptr->c_name());
|
||||
|
||||
list[pos].rsc_state = Resource::State::Posted;
|
||||
}
|
||||
|
||||
template <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);
|
||||
return getPtr();
|
||||
}
|
||||
*/
|
||||
|
||||
private:
|
||||
InternalResourceList list;
|
||||
bool hazardFlag;
|
||||
|
||||
void setResetPointersHazard(thread_db* tdbb, bool set);
|
||||
void raiseNotRegistered(const Resource& r, Resource::rsc_s type, const char* name);
|
||||
void transferList(thread_db* tdbb, const InternalResourceList& from, Resource::State resetState,
|
||||
ResourceTypes rt, NewResources* nr, ResourceList* hazardList);
|
||||
FB_SIZE_T compileOffset;
|
||||
};
|
||||
|
||||
|
||||
// Access items
|
||||
// In case we start to use MetaName with required pool parameter,
|
||||
// access item to be reworked!
|
||||
@ -641,7 +524,7 @@ public:
|
||||
mainCsb(aMainCsb),
|
||||
csb_external(p),
|
||||
csb_access(p),
|
||||
csb_resources(p, true),
|
||||
csb_resources(nullptr),
|
||||
csb_dependencies(p),
|
||||
csb_fors(p),
|
||||
csb_localTables(p),
|
||||
@ -720,7 +603,7 @@ public:
|
||||
ExternalAccessList csb_external; // Access to outside procedures/triggers to be checked
|
||||
AccessItemList csb_access; // Access items to be checked
|
||||
vec<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<const Select*> csb_fors; // select expressions
|
||||
Firebird::Array<const DeclareLocalTableNode*> csb_localTables; // local tables
|
||||
@ -747,9 +630,9 @@ public:
|
||||
MetaName csb_domain_validation; // Parsing domain constraint in PSQL
|
||||
|
||||
// used in cmp.cpp/pass1
|
||||
jrd_rel* csb_view;
|
||||
CachedResource<jrd_rel> csb_view;
|
||||
StreamType csb_view_stream;
|
||||
jrd_rel* csb_parent_relation;
|
||||
CachedResource<jrd_rel> csb_parent_relation;
|
||||
unsigned blrVersion;
|
||||
USHORT csb_remap_variable;
|
||||
bool csb_validate_expr;
|
||||
@ -783,10 +666,10 @@ public:
|
||||
StreamType csb_view_stream; // stream number for view relation, below
|
||||
USHORT csb_flags;
|
||||
|
||||
jrd_rel* csb_relation;
|
||||
CachedResource<jrd_rel> csb_relation;
|
||||
Firebird::string* csb_alias; // SQL alias name for this instance of relation
|
||||
jrd_prc* csb_procedure;
|
||||
jrd_rel* csb_view; // parent view
|
||||
CachedResource<jrd_prc> csb_procedure;
|
||||
CachedResource<jrd_rel> csb_view; // parent view
|
||||
|
||||
IndexDescList* csb_idx; // Packed description of indices
|
||||
MessageNode* csb_message; // Msg for send/receive
|
||||
|
@ -235,7 +235,7 @@ void EXT_erase(record_param*, jrd_tra*)
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
|
@ -35,7 +35,7 @@ namespace Jrd {
|
||||
|
||||
double EXT_cardinality(Jrd::thread_db*, Jrd::jrd_rel*);
|
||||
void EXT_erase(Jrd::record_param*, Jrd::jrd_tra*);
|
||||
Jrd::ExternalFile* EXT_file(Jrd::HazardPtr<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);
|
||||
bool EXT_get(Jrd::thread_db*, Jrd::record_param*, FB_UINT64&);
|
||||
void EXT_modify(Jrd::record_param*, Jrd::record_param*, Jrd::jrd_tra*);
|
||||
|
@ -1738,7 +1738,7 @@ static idx_e check_foreign_key(thread_db* tdbb,
|
||||
if (!MET_lookup_partner(tdbb, relation, idx, 0))
|
||||
return result;
|
||||
|
||||
HazardPtr<jrd_rel> partner_relation(tdbb, FB_FUNCTION);
|
||||
jrd_rel* partner_relation(tdbb);
|
||||
USHORT index_id = 0;
|
||||
|
||||
if (idx->idx_flags & idx_foreign)
|
||||
|
@ -973,7 +973,7 @@ void INI_init(thread_db* tdbb)
|
||||
|
||||
const auto id = relfld[RFLD_R_ID];
|
||||
//fprintf(stderr, "INI_init %d %s\n", id, names[relfld[RFLD_R_NAME]]);
|
||||
HazardPtr<jrd_rel> relation = MetadataCache::findRelation(tdbb, id);
|
||||
jrd_rel* relation = MetadataCache::findRelation(tdbb, id);
|
||||
|
||||
if (id == 7) TRAP = relation.getPointer();
|
||||
|
||||
|
@ -169,24 +169,22 @@ HazardPtr<CharSetContainer> CharSetContainer::lookupCharset(thread_db* tdbb, USH
|
||||
if (id == CS_dynamic)
|
||||
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;
|
||||
|
||||
if (lookupInternalCharSet(id, &info) || MET_get_char_coll_subtype_info(tdbb, id, &info))
|
||||
{
|
||||
CharSetContainer* csc = FB_NEW_POOL(*dbb->dbb_permanent) CharSetContainer(*dbb->dbb_permanent, id, &info);
|
||||
dbb->dbb_mdc->setCharSet(tdbb, id, csc);
|
||||
cs = dbb->dbb_mdc->getCharSet(tdbb, id);
|
||||
}
|
||||
else
|
||||
ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(ttype));
|
||||
CharSetContainer* csc = FB_NEW_POOL(*dbb->dbb_permanent) CharSetContainer(*dbb->dbb_permanent, id, &info);
|
||||
dbb->dbb_mdc->setCharSet(tdbb, id, csc);
|
||||
cs = dbb->dbb_mdc->getCharSet(tdbb, id);
|
||||
}
|
||||
|
||||
return cs;
|
||||
else
|
||||
ERR_post(Arg::Gds(isc_text_subtype) << Arg::Num(ttype));
|
||||
}
|
||||
|
||||
|
||||
@ -288,11 +286,11 @@ CsConvert CharSetContainer::lookupConverter(thread_db* tdbb, CHARSET_ID toCsId)
|
||||
return CsConvert(cs->getStruct(), toCs->getStruct());
|
||||
}
|
||||
|
||||
HazardPtr<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);
|
||||
|
||||
HazardPtr<Collation> coll(FB_FUNCTION);
|
||||
Collation* coll(FB_FUNCTION);
|
||||
if (charset_collations.load(tdbb, id, coll))
|
||||
{
|
||||
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 ?
|
||||
|
||||
HazardPtr<Collation> to_delete(FB_FUNCTION);
|
||||
Collation* to_delete(FB_FUNCTION);
|
||||
if (charset_collations.load(tdbb, id, coll))
|
||||
{
|
||||
if (!coll->obsolete)
|
||||
@ -404,7 +402,7 @@ void CharSetContainer::unloadCollation(thread_db* tdbb, USHORT tt_id)
|
||||
const USHORT id = TTYPE_TO_COLLATION(tt_id);
|
||||
fb_assert(id != 0);
|
||||
|
||||
HazardPtr<Collation> coll(FB_FUNCTION);
|
||||
Collation* coll(FB_FUNCTION);
|
||||
if (charset_collations.load(tdbb, id, coll))
|
||||
{
|
||||
MutexLockGuard g(tdbb->getDatabase()->dbb_mdc->mdc_use_mutex, FB_FUNCTION);
|
||||
@ -457,7 +455,7 @@ void Jrd::MetadataCache::destroyIntlObjects(thread_db* tdbb)
|
||||
{
|
||||
for (FB_SIZE_T i = 0; i < mdc_charsets.getCount(tdbb); i++)
|
||||
{
|
||||
HazardPtr<CharSetContainer> cs(FB_FUNCTION);
|
||||
HazardPtr<CharSetContainer> cs;
|
||||
if (mdc_charsets.load(tdbb, i, cs))
|
||||
{
|
||||
cs->destroy(tdbb);
|
||||
@ -996,7 +994,7 @@ CharSet* INTL_charset_lookup(thread_db* tdbb, USHORT parm1)
|
||||
}
|
||||
|
||||
|
||||
HazardPtr<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);
|
||||
break;
|
||||
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));
|
||||
outlen = obj->string_to_key(len, src, pByte->dsc_length, dest, key_type);
|
||||
break;
|
||||
|
@ -49,7 +49,7 @@ bool INTL_data_or_binary(const dsc*);
|
||||
bool INTL_defined_type(Jrd::thread_db*, USHORT);
|
||||
USHORT INTL_key_length(Jrd::thread_db*, USHORT, USHORT);
|
||||
Jrd::CharSet* INTL_charset_lookup(Jrd::thread_db* tdbb, USHORT parm1);
|
||||
Jrd::HazardPtr<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);
|
||||
bool INTL_texttype_validate(Jrd::thread_db*, const SubtypeInfo*);
|
||||
void INTL_pad_spaces(Jrd::thread_db*, dsc*, UCHAR*, ULONG);
|
||||
|
@ -1732,7 +1732,7 @@ void ExistenceLock::internalObjectDelete(thread_db* tdbb, unsigned fl)
|
||||
object->afterUnlock(tdbb, fl);
|
||||
|
||||
if (!(fl & inCache))
|
||||
object->delayedDelete(tdbb);
|
||||
object->retire();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1790,10 +1790,3 @@ void ExistenceLock::releaseLock(thread_db* tdbb, ReleaseMethod rm)
|
||||
}
|
||||
}
|
||||
|
||||
void ExistenceLock::removeFromCache(thread_db* tdbb)
|
||||
{
|
||||
fb_assert(flags & inCache);
|
||||
unsigned fl = (flags &= ~inCache);
|
||||
if (((fl & countMask) == 0) && (fl & locked))
|
||||
leave245(tdbb, true);
|
||||
}
|
||||
|
@ -256,7 +256,6 @@ public:
|
||||
#endif
|
||||
void unlock(thread_db* tdbb); // Release exclusive lock
|
||||
void releaseLock(thread_db* tdbb, ReleaseMethod rm); // Release any lock
|
||||
void removeFromCache(thread_db* tdbb); // Invoked when object is removed from MDC
|
||||
|
||||
private:
|
||||
static int ast(void* self)
|
||||
|
217
src/jrd/met.epp
217
src/jrd/met.epp
@ -113,18 +113,18 @@ static int blocking_ast_dsql_cache(void* ast_object);
|
||||
static int partners_ast_relation(void*);
|
||||
static int rescan_ast_relation(void*);
|
||||
static ULONG get_rel_flags_from_FLAGS(USHORT);
|
||||
static void get_trigger(thread_db*, HazardPtr<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);
|
||||
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 ValueExprNode* parse_field_default_blr(thread_db* tdbb, bid* blob_id);
|
||||
static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, const MetaName name);
|
||||
static void save_trigger_data(thread_db*, TrigVectorPtr*, HazardPtr<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 bid*, Nullable<bool> ssDefiner);
|
||||
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*);
|
||||
static bool verify_TRG_ignore_perm(thread_db*, const MetaName&);
|
||||
|
||||
@ -1497,7 +1497,7 @@ bool MET_get_char_coll_subtype_info(thread_db* tdbb, USHORT id, SubtypeInfo* inf
|
||||
|
||||
|
||||
DmlNode* MET_get_dependencies(thread_db* tdbb,
|
||||
Jrd::HazardPtr<Jrd::jrd_rel>& relation,
|
||||
Jrd::jrd_rel* relation,
|
||||
const UCHAR* blob,
|
||||
const ULONG blob_length,
|
||||
CompilerScratch* view_csb,
|
||||
@ -1583,12 +1583,6 @@ DmlNode* MET_get_dependencies(thread_db* tdbb,
|
||||
}
|
||||
|
||||
|
||||
jrd_fld* MET_get_field(const Jrd::HazardPtr<Jrd::jrd_rel>& relation, USHORT id)
|
||||
{
|
||||
return MET_get_field(relation.getPointer(), id);
|
||||
}
|
||||
|
||||
|
||||
jrd_fld* MET_get_field(const jrd_rel* relation, USHORT id)
|
||||
{
|
||||
/**************************************
|
||||
@ -1761,7 +1755,7 @@ void MetadataCache::load_db_triggers(thread_db* tdbb, int type)
|
||||
TRG.RDB$TRIGGER_INACTIVE EQ 0
|
||||
SORTED BY TRG.RDB$TRIGGER_SEQUENCE
|
||||
{
|
||||
MET_load_trigger(tdbb, nullRel, TRG.RDB$TRIGGER_NAME, &mdc_triggers[type]);
|
||||
MET_load_trigger(tdbb, nullptr, TRG.RDB$TRIGGER_NAME, &mdc_triggers[type]);
|
||||
}
|
||||
END_FOR
|
||||
}
|
||||
@ -1795,7 +1789,7 @@ void MetadataCache::load_ddl_triggers(thread_db* tdbb)
|
||||
{
|
||||
if ((TRG.RDB$TRIGGER_TYPE & TRIGGER_TYPE_MASK) == TRIGGER_TYPE_DDL)
|
||||
{
|
||||
MET_load_trigger(tdbb, nullRel, TRG.RDB$TRIGGER_NAME, &mdc_ddl_triggers);
|
||||
MET_load_trigger(tdbb, nullptr, TRG.RDB$TRIGGER_NAME, &mdc_ddl_triggers);
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
@ -1803,7 +1797,7 @@ void MetadataCache::load_ddl_triggers(thread_db* tdbb)
|
||||
|
||||
|
||||
void MET_load_trigger(thread_db* tdbb,
|
||||
HazardPtr<jrd_rel>& relation,
|
||||
jrd_rel* relation,
|
||||
const MetaName& trigger_name,
|
||||
TrigVectorPtr* triggers)
|
||||
{
|
||||
@ -2409,7 +2403,7 @@ SLONG MetadataCache::lookup_index_name(thread_db* tdbb, const MetaName& index_na
|
||||
*status = MET_object_inactive;
|
||||
|
||||
id = X.RDB$INDEX_ID - 1;
|
||||
HazardPtr<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;
|
||||
}
|
||||
END_FOR
|
||||
@ -2543,7 +2537,7 @@ void MET_lookup_index_expression(thread_db* tdbb, jrd_rel* relation, index_desc*
|
||||
return;
|
||||
}
|
||||
|
||||
HazardPtr<jrd_rel> wrk = MET_scan_relation(tdbb, relation->rel_id);
|
||||
jrd_rel* wrk = MET_scan_relation(tdbb, relation->rel_id);
|
||||
if (!wrk)
|
||||
{
|
||||
(Arg::Gds(isc_random) << "Relation was deleted").raise();
|
||||
@ -2666,7 +2660,7 @@ bool MET_lookup_partner(thread_db* tdbb, jrd_rel* relation, index_desc* idx, con
|
||||
IND.RDB$UNIQUE_FLAG = 1
|
||||
{
|
||||
//// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved.
|
||||
HazardPtr<jrd_rel> foundRel(FB_FUNCTION);
|
||||
jrd_rel* foundRel = nullptr;
|
||||
const jrd_rel* partner_relation = relation;
|
||||
if (relation->rel_name != IND.RDB$RELATION_NAME)
|
||||
{
|
||||
@ -2745,7 +2739,7 @@ HazardPtr<jrd_prc> MetadataCache::lookup_procedure(thread_db* tdbb, const Qualif
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
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
|
||||
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
|
||||
|
||||
HazardPtr<jrd_prc> procedure(FB_FUNCTION);
|
||||
HazardPtr<jrd_prc> procedure;
|
||||
|
||||
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);
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
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) &&
|
||||
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);
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
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
|
||||
|
||||
@ -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
|
||||
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 (relation->rel_flags & REL_deleting)
|
||||
@ -3076,7 +3070,7 @@ bool MetadataCache::checkRelation(thread_db* tdbb, jrd_rel* relation)
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
MetadataCache* mdc = attachment->att_database->dbb_mdc;
|
||||
|
||||
HazardPtr<jrd_rel> check_relation(FB_FUNCTION);
|
||||
jrd_rel* check_relation = nullptr;
|
||||
if ((!mdc->mdc_relations.load(tdbb, relation->rel_id, check_relation)) ||
|
||||
(relation != check_relation))
|
||||
{
|
||||
@ -3107,7 +3101,7 @@ bool MetadataCache::checkRelation(thread_db* tdbb, jrd_rel* relation)
|
||||
|
||||
|
||||
DmlNode* MET_parse_blob(thread_db* tdbb,
|
||||
Jrd::HazardPtr<Jrd::jrd_rel>& relation,
|
||||
Jrd::jrd_rel* relation,
|
||||
bid* blob_id,
|
||||
CompilerScratch** csb_ptr,
|
||||
Statement** statementPtr,
|
||||
@ -3153,7 +3147,7 @@ DmlNode* MET_parse_blob(thread_db* tdbb,
|
||||
}
|
||||
|
||||
|
||||
void MET_parse_sys_trigger(thread_db* tdbb, HazardPtr<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))
|
||||
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))
|
||||
{
|
||||
@ -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 {
|
||||
|
||||
newProcedure->flags |= (Routine::FLAG_BEING_SCANNED | flags);
|
||||
newProcedure->flags &= ~(Routine::FLAG_OBSOLETE | Routine::FLAG_CLEARED);
|
||||
newProcedure->setId(id);
|
||||
|
||||
if (!newProcedure->existenceLock)
|
||||
{
|
||||
newProcedure->existenceLock = FB_NEW_POOL(mdc->getPool())
|
||||
ExistenceLock(mdc->getPool(), tdbb, LCK_prc_exist, id, newProcedure);
|
||||
}
|
||||
|
||||
while (!dbb->dbb_mdc->mdc_procedures.replace(tdbb, id, procedure, newProcedure))
|
||||
{
|
||||
if (procedure)
|
||||
{
|
||||
procedure->startup.wait();
|
||||
|
||||
if (!(procedure->flags & Routine::FLAG_OBSOLETE))
|
||||
{
|
||||
// Someone else created required procedure
|
||||
|
||||
delete newProcedure->getExternal();
|
||||
newProcedure->setExternal(NULL);
|
||||
newProcedure->delayedDelete(tdbb);
|
||||
|
||||
if (procedure->flags & Routine::FLAG_SCANNED)
|
||||
return procedure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!noscan)
|
||||
{
|
||||
AutoCacheRequest request(tdbb, irq_r_procedure, IRQ_REQUESTS);
|
||||
|
||||
FOR(REQUEST_HANDLE request)
|
||||
@ -3503,7 +3473,7 @@ HazardPtr<jrd_prc> MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool
|
||||
try
|
||||
{
|
||||
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&)
|
||||
{
|
||||
@ -3639,29 +3609,16 @@ HazardPtr<jrd_prc> MetadataCache::findProcedure(thread_db* tdbb, USHORT id, bool
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
} // if !noscan
|
||||
|
||||
// Make sure that it is really being scanned
|
||||
fb_assert(newProcedure->flags & Routine::FLAG_BEING_SCANNED);
|
||||
|
||||
newProcedure->flags &= ~Routine::FLAG_BEING_SCANNED;
|
||||
newProcedure->startup.open();
|
||||
|
||||
newProcedure->startup.open();
|
||||
} // try
|
||||
catch (const Exception&)
|
||||
{
|
||||
if (newProcedure->getExternal())
|
||||
{
|
||||
delete newProcedure->getExternal();
|
||||
newProcedure->setExternal(NULL);
|
||||
}
|
||||
|
||||
newProcedure->flags &= ~Routine::FLAG_BEING_SCANNED;
|
||||
newProcedure->startup.open();
|
||||
jrd_prc::destroy(newProcedure);
|
||||
throw;
|
||||
}
|
||||
|
||||
return procedure;
|
||||
return newProcedure;
|
||||
}
|
||||
|
||||
bool jrd_prc::reload(thread_db* tdbb)
|
||||
@ -3710,7 +3667,7 @@ bool jrd_prc::reload(thread_db* tdbb)
|
||||
return false;
|
||||
}
|
||||
|
||||
HazardPtr<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;
|
||||
MemoryPool& pool = mdc->getPool();
|
||||
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
if (mdc->mdc_relations.load(tdbb, id, relation))
|
||||
return relation;
|
||||
|
||||
@ -3838,9 +3795,9 @@ void MET_scan_partners(thread_db* tdbb, jrd_rel* relation)
|
||||
}
|
||||
|
||||
|
||||
HazardPtr<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) ||
|
||||
(relation->rel_flags & REL_being_scanned)))
|
||||
@ -3851,7 +3808,7 @@ HazardPtr<jrd_rel> MET_scan_relation(thread_db* tdbb, USHORT id)
|
||||
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;
|
||||
field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p);
|
||||
const MetaName depName(REL.RDB$RELATION_NAME);
|
||||
store_dependencies(tdbb, csb->csb_dependencies, nullRel, depName, obj_view, depTrans);
|
||||
store_dependencies(tdbb, csb->csb_dependencies, nullptr, depName, obj_view, depTrans);
|
||||
}
|
||||
else
|
||||
field->fld_source = PAR_make_field(tdbb, csb, view_context, (TEXT*) p);
|
||||
@ -4490,7 +4447,7 @@ ULONG MET_get_rel_flags_from_TYPE(USHORT type)
|
||||
}
|
||||
|
||||
|
||||
static void get_trigger(thread_db* tdbb, HazardPtr<jrd_rel>& relation,
|
||||
static void get_trigger(thread_db* tdbb, jrd_rel* relation,
|
||||
bid* blob_id, bid* debug_blob_id, TrigVectorPtr* ptr,
|
||||
const TEXT* name, FB_UINT64 type,
|
||||
bool sys_trigger, USHORT flags,
|
||||
@ -4580,7 +4537,7 @@ static bool get_type(thread_db* tdbb, USHORT* id, const UCHAR* name, const TEXT*
|
||||
}
|
||||
|
||||
|
||||
static void lookup_view_contexts( thread_db* tdbb, HazardPtr<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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -4682,7 +4639,7 @@ static BoolExprNode* parse_field_validation_blr(thread_db* tdbb, bid* blob_id, c
|
||||
|
||||
length = blob->BLB_get_data(tdbb, temp.getBuffer(length), length);
|
||||
|
||||
return PAR_validation_blr(tdbb, nullRel, temp.begin(), length, NULL, &csb, 0);
|
||||
return PAR_validation_blr(tdbb, nullptr, temp.begin(), length, NULL, &csb, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -4705,7 +4662,7 @@ void MetadataCache::releaseTrigger(thread_db* tdbb, USHORT triggerId, const Meta
|
||||
return;
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
HazardPtr<Trigger> trigger(FB_FUNCTION);
|
||||
HazardPtr<Trigger> trigger;
|
||||
SLONG n = vector->load()->lookup(tdbb, name, &trigger);
|
||||
if (n < 0)
|
||||
return;
|
||||
@ -4868,7 +4825,7 @@ bool MetadataCache::resolve_charset_and_collation(thread_db* tdbb, USHORT* id,
|
||||
}
|
||||
|
||||
|
||||
static void save_trigger_data(thread_db* tdbb, TrigVectorPtr* ptr, HazardPtr<jrd_rel>& relation,
|
||||
static void save_trigger_data(thread_db* tdbb, TrigVectorPtr* ptr, jrd_rel* relation,
|
||||
Statement* statement, blb* blrBlob, blb* debugInfoBlob,
|
||||
const TEXT* name, FB_UINT64 type,
|
||||
bool sys_trigger, USHORT flags,
|
||||
@ -4960,7 +4917,7 @@ HazardPtr<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.
|
||||
const jrd_rel* partner_relation = relation;
|
||||
HazardPtr<jrd_rel> rel(FB_FUNCTION);
|
||||
jrd_rel* rel = nullptr;
|
||||
if (relation->rel_name != IND.RDB$RELATION_NAME)
|
||||
{
|
||||
rel = MetadataCache::lookup_relation(tdbb, IND.RDB$RELATION_NAME);
|
||||
@ -5087,7 +5044,7 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation)
|
||||
{
|
||||
//// ASF: Hack fix for CORE-4304, until nasty interactions between dfw and met are not resolved.
|
||||
const jrd_rel* partner_relation = relation;
|
||||
HazardPtr<jrd_rel> rel(FB_FUNCTION);
|
||||
jrd_rel* rel = nullptr;
|
||||
if (relation->rel_name != IND.RDB$RELATION_NAME)
|
||||
{
|
||||
rel = MetadataCache::lookup_relation(tdbb, IND.RDB$RELATION_NAME);
|
||||
@ -5124,7 +5081,7 @@ void scan_partners(thread_db* tdbb, jrd_rel* relation)
|
||||
|
||||
static void store_dependencies(thread_db* tdbb,
|
||||
Array<CompilerScratch::Dependency>& dependencies,
|
||||
HazardPtr<jrd_rel>& dep_rel,
|
||||
jrd_rel* dep_rel,
|
||||
const MetaName& object_name,
|
||||
int dependency_type,
|
||||
jrd_tra* transaction)
|
||||
@ -5145,7 +5102,7 @@ static void store_dependencies(thread_db* tdbb,
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
HazardPtr<const Trigger> t(FB_FUNCTION);
|
||||
HazardPtr<const Trigger> t;
|
||||
const bool checkTableScope =
|
||||
(dependency_type == obj_computed) ||
|
||||
(dependency_type == obj_trigger) && dep_rel &&
|
||||
@ -5169,7 +5126,7 @@ static void store_dependencies(thread_db* tdbb,
|
||||
}
|
||||
|
||||
int dpdo_type = dependency.objType;
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
const jrd_prc* procedure = NULL;
|
||||
const MetaName* dpdo_name = NULL;
|
||||
MetaName packageName;
|
||||
@ -5534,13 +5491,13 @@ void MetadataCache::releaseRelations(thread_db* tdbb)
|
||||
{
|
||||
for (FB_SIZE_T n = 0; n < mdc_relations.getCount(tdbb); ++n)
|
||||
{
|
||||
HazardPtr<jrd_rel> relation(tdbb, FB_FUNCTION);
|
||||
jrd_rel* relation = nullptr;
|
||||
if (mdc_relations.load(tdbb, n, relation))
|
||||
{
|
||||
if (relation->rel_file)
|
||||
EXT_fini(relation.getPointer(), false);
|
||||
|
||||
relation->delayedDelete(tdbb);
|
||||
delete relation;
|
||||
}
|
||||
}
|
||||
// ??????? mdc_relations.clear();
|
||||
@ -5620,7 +5577,7 @@ void MetadataCache::invalidateReplSet(thread_db* tdbb)
|
||||
}
|
||||
}
|
||||
|
||||
HazardPtr<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())
|
||||
{
|
||||
@ -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);
|
||||
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);
|
||||
return rc;
|
||||
}
|
||||
@ -5713,7 +5670,7 @@ void Trigger::compile(thread_db* tdbb)
|
||||
*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)
|
||||
fatal_exception::raiseFmt("Relation %s unexpectedly lost", relation->rel_name);
|
||||
|
||||
@ -5777,7 +5734,7 @@ int Trigger::release(thread_db* tdbb)
|
||||
statement->release(tdbb);
|
||||
statement = NULL;
|
||||
|
||||
delayedDelete(tdbb);
|
||||
retire();
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
@ -5887,3 +5844,47 @@ void Trigger::release(thread_db* tdbb)
|
||||
statement = NULL;
|
||||
}
|
||||
|
||||
CacheElement<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;
|
||||
}
|
||||
|
||||
|
1015
src/jrd/met.h
1015
src/jrd/met.h
File diff suppressed because it is too large
Load Diff
@ -74,17 +74,16 @@ void MET_delete_shadow(Jrd::thread_db*, USHORT);
|
||||
void MET_error(const TEXT*, ...);
|
||||
Jrd::Format* MET_format(Jrd::thread_db*, Jrd::jrd_rel*, USHORT);
|
||||
bool MET_get_char_coll_subtype_info(Jrd::thread_db*, USHORT, SubtypeInfo* info);
|
||||
Jrd::DmlNode* MET_get_dependencies(Jrd::thread_db*, Jrd::HazardPtr<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**, const Jrd::MetaName&, int, USHORT,
|
||||
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);
|
||||
ULONG MET_get_rel_flags_from_TYPE(USHORT);
|
||||
bool MET_get_repl_state(Jrd::thread_db*, const Jrd::MetaName&);
|
||||
void MET_get_shadow_files(Jrd::thread_db*, bool);
|
||||
bool MET_load_exception(Jrd::thread_db*, Jrd::ExceptionItem&);
|
||||
void MET_load_trigger(Jrd::thread_db*, Jrd::HazardPtr<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_trigger(Jrd::thread_db*, Jrd::MetaName&, Jrd::MetaName&, const Jrd::MetaName&);
|
||||
void MET_lookup_exception(Jrd::thread_db*, SLONG, /* OUT */ Jrd::MetaName&, /* OUT */ Firebird::string*);
|
||||
@ -96,9 +95,9 @@ bool MET_lookup_generator_id(Jrd::thread_db*, SLONG, Jrd::MetaName&, bool* sysG
|
||||
void MET_update_generator_increment(Jrd::thread_db* tdbb, SLONG gen_id, SLONG step);
|
||||
void MET_lookup_index_expression(Jrd::thread_db*, Jrd::jrd_rel*, Jrd::index_desc*);
|
||||
bool MET_lookup_partner(Jrd::thread_db* tdbb, Jrd::jrd_rel* relation, Jrd::index_desc* idx, const TEXT* index_name);
|
||||
Jrd::DmlNode* MET_parse_blob(Jrd::thread_db*, Jrd::HazardPtr<Jrd::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);
|
||||
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_release_existence(Jrd::thread_db*, Jrd::jrd_rel*);
|
||||
void MET_release_trigger(Jrd::thread_db*, Jrd::TrigVectorPtr*, const Jrd::MetaName&);
|
||||
@ -106,8 +105,7 @@ void MET_release_triggers(Jrd::thread_db*, Jrd::TrigVectorPtr*, bool);
|
||||
void MET_revoke(Jrd::thread_db*, Jrd::jrd_tra*, const Jrd::MetaName&,
|
||||
const Jrd::MetaName&, const Firebird::string&);
|
||||
void MET_scan_partners(Jrd::thread_db*, Jrd::jrd_rel*);
|
||||
Jrd::HazardPtr<Jrd::jrd_rel> MET_scan_relation(Jrd::thread_db*, USHORT);
|
||||
void MET_scan_relation(Jrd::thread_db*, Jrd::HazardPtr<Jrd::jrd_rel>&);
|
||||
void MET_scan_relation(Jrd::thread_db*, Jrd::jrd_rel*&);
|
||||
void MET_trigger_msg(Jrd::thread_db*, Firebird::string&, const Jrd::MetaName&, USHORT);
|
||||
void MET_update_shadow(Jrd::thread_db*, Jrd::Shadow*, USHORT);
|
||||
void MET_update_transaction(Jrd::thread_db*, Jrd::jrd_tra*, const bool);
|
||||
|
@ -1122,7 +1122,7 @@ void PAG_header(thread_db* tdbb, bool info)
|
||||
if (header->hdr_flags & hdr_SQL_dialect_3)
|
||||
dbb->dbb_flags |= DBB_DB_SQL_dialect_3;
|
||||
|
||||
HazardPtr<jrd_rel> relation = MetadataCache::findRelation(tdbb, 0);
|
||||
jrd_rel* relation = MetadataCache::findRelation(tdbb, 0);
|
||||
RelationPages* relPages = relation->getBasePages();
|
||||
if (!relPages->rel_pages)
|
||||
{
|
||||
|
@ -89,7 +89,7 @@ namespace
|
||||
class BlrParseWrapper
|
||||
{
|
||||
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)
|
||||
: m_csbPtr(csb_ptr)
|
||||
{
|
||||
@ -171,7 +171,7 @@ namespace
|
||||
|
||||
// Parse blr, returning a compiler scratch block with the results.
|
||||
// Caller must do pool handling.
|
||||
DmlNode* PAR_blr(thread_db* tdbb, HazardPtr<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,
|
||||
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.
|
||||
// Caller must do pool handling.
|
||||
// !!!!!!!!!!!!!!! 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,
|
||||
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.
|
||||
// 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)
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
@ -545,7 +545,7 @@ USHORT PAR_desc(thread_db* tdbb, CompilerScratch* csb, dsc* desc, ItemInfo* item
|
||||
if (csb->collectingDependencies())
|
||||
{
|
||||
CompilerScratch::Dependency dependency(obj_relation);
|
||||
HazardPtr<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.subName = fieldName;
|
||||
csb->addDependency(dependency);
|
||||
|
@ -45,11 +45,11 @@ struct dsc;
|
||||
|
||||
Jrd::ValueListNode* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*, USHORT, USHORT);
|
||||
Jrd::ValueListNode* PAR_args(Jrd::thread_db*, Jrd::CompilerScratch*);
|
||||
Jrd::DmlNode* PAR_blr(Jrd::thread_db*, Jrd::HazardPtr<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);
|
||||
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::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);
|
||||
StreamType PAR_context(Jrd::CompilerScratch*, SSHORT*);
|
||||
void PAR_dependency(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, StreamType stream,
|
||||
|
@ -161,6 +161,39 @@ private:
|
||||
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
|
||||
|
||||
class Request : public pool_alloc<type_req>
|
||||
@ -302,31 +335,7 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement)
|
||||
: statement(aStatement),
|
||||
req_pool(pool),
|
||||
req_memory_stats(&aStatement->pool->getStatsGroup()),
|
||||
req_blobs(req_pool),
|
||||
req_stats(*req_pool),
|
||||
req_base_stats(*req_pool),
|
||||
req_ext_stmt(NULL),
|
||||
req_cursors(*req_pool),
|
||||
req_ext_resultset(NULL),
|
||||
req_timeout(0),
|
||||
req_domain_validation(NULL),
|
||||
req_auto_trans(*req_pool),
|
||||
req_sorts(*req_pool),
|
||||
req_rpb(*req_pool),
|
||||
impureArea(*req_pool)
|
||||
{
|
||||
fb_assert(statement);
|
||||
setAttachment(attachment);
|
||||
req_rpb = statement->rpbsSetup;
|
||||
impureArea.grow(statement->impureSize);
|
||||
|
||||
pool->setStatsGroup(req_memory_stats);
|
||||
pool.release();
|
||||
}
|
||||
Request(Firebird::AutoMemoryPool& pool, Attachment* attachment, /*const*/ Statement* aStatement);
|
||||
|
||||
Statement* getStatement()
|
||||
{
|
||||
@ -345,7 +354,6 @@ public:
|
||||
void setAttachment(Attachment* newAttachment)
|
||||
{
|
||||
req_attachment = newAttachment;
|
||||
charSetId = hasInternalStatement() ? CS_METADATA : req_attachment->att_charset;
|
||||
}
|
||||
|
||||
bool isRoot() const;
|
||||
@ -362,6 +370,9 @@ public:
|
||||
req_id = id;
|
||||
}
|
||||
|
||||
void setUsed(bool inUse);
|
||||
bool isUsed();
|
||||
|
||||
private:
|
||||
Statement* const statement;
|
||||
mutable StmtNumber req_id; // request identifier
|
||||
@ -505,6 +516,9 @@ public:
|
||||
{
|
||||
req_timeStampCache.validate(req_attachment->att_current_timezone);
|
||||
}
|
||||
|
||||
private:
|
||||
Firebird::RefPtr<VersionedObjects> currentVersion;
|
||||
};
|
||||
|
||||
// Flags for req_flags
|
||||
@ -515,7 +529,7 @@ const ULONG req_null = 0x8L;
|
||||
const ULONG req_abort = 0x10L;
|
||||
const ULONG req_error_handler = 0x20L; // looper is called to handle error
|
||||
const ULONG req_warning = 0x40L;
|
||||
const ULONG req_in_use = 0x80L;
|
||||
//const ULONG req_in_use = 0x80L;
|
||||
const ULONG req_continue_loop = 0x100L; // PSQL continue statement
|
||||
const ULONG req_proc_fetch = 0x200L; // Fetch from procedure in progress
|
||||
const ULONG req_same_tx_upd = 0x400L; // record was updated by same transaction
|
||||
|
@ -907,7 +907,7 @@ SecurityClass::flags_t SCL_get_mask(thread_db* tdbb, const TEXT* relation_name,
|
||||
SecurityClass::flags_t access = ~0;
|
||||
|
||||
// If there's a relation, track it down
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation;
|
||||
if (relation_name && (relation = MetadataCache::lookup_relation(tdbb, relation_name)))
|
||||
{
|
||||
MET_scan_relation(tdbb, relation);
|
||||
|
@ -94,7 +94,7 @@ static TraNumber bump_transaction_id(thread_db*, WIN*);
|
||||
static header_page* bump_transaction_id(thread_db*, WIN*, bool);
|
||||
#endif
|
||||
static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, int state);
|
||||
static void expand_view_lock(thread_db* tdbb, jrd_tra*, HazardPtr<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);
|
||||
static tx_inv_page* fetch_inventory_page(thread_db*, WIN* window, ULONG sequence, USHORT lock_level);
|
||||
static const char* get_lockname_v3(const UCHAR lock);
|
||||
@ -963,8 +963,8 @@ void TRA_post_resources(thread_db* tdbb, jrd_tra* transaction, ResourceList& res
|
||||
* This guarantees that the relation/procedure/collation won't be dropped
|
||||
* out from under the transaction.
|
||||
*
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
**************************************
|
||||
SET_TDBB(tdbb); !!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
Jrd::ContextPoolHolder context(tdbb, transaction->tra_pool);
|
||||
|
||||
@ -978,6 +978,9 @@ void TRA_post_resources(thread_db* tdbb, jrd_tra* transaction, ResourceList& res
|
||||
|
||||
if (!newRsc.hasData())
|
||||
return;
|
||||
*/
|
||||
|
||||
// !!!!!!!!!!!!! solve EXT_tra_attach problem - where to place references
|
||||
|
||||
MutexLockGuard g(tdbb->getDatabase()->dbb_mdc->mdc_use_mutex, FB_FUNCTION);
|
||||
|
||||
@ -1253,6 +1256,9 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
|
||||
}
|
||||
|
||||
// Care about used external files
|
||||
|
||||
// !!!!!!!!!!!!! solve EXT_tra_attach problem - where to place references
|
||||
/*
|
||||
for (auto rsc : transaction->tra_resources.getObjects(Resource::rsc_relation))
|
||||
{
|
||||
if (rsc->rsc_state == Resource::State::Extra)
|
||||
@ -1262,7 +1268,7 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
|
||||
rsc->rsc_state = Resource::State::Locked;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// Release interest in relation/procedure existence for transaction
|
||||
transaction->tra_resources.releaseResources(tdbb, transaction);
|
||||
|
||||
@ -2150,7 +2156,7 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window, bool dontW
|
||||
#endif
|
||||
|
||||
|
||||
static void expand_view_lock(thread_db* tdbb, jrd_tra* transaction, HazardPtr<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)
|
||||
{
|
||||
/**************************************
|
||||
@ -2261,7 +2267,7 @@ static void expand_view_lock(thread_db* tdbb, jrd_tra* transaction, HazardPtr<jr
|
||||
if (ctx[i]->vcx_type == VCT_PROCEDURE)
|
||||
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)
|
||||
{
|
||||
// should be a BUGCHECK
|
||||
@ -2484,7 +2490,7 @@ static void release_temp_tables(thread_db* tdbb, jrd_tra* transaction)
|
||||
|
||||
for (FB_SIZE_T i = 0; i < mdc->relCount(tdbb); i++)
|
||||
{
|
||||
HazardPtr<jrd_rel> relation = mdc->getRelation(tdbb, i);
|
||||
jrd_rel* relation = mdc->getRelation(tdbb, i);
|
||||
|
||||
if (relation && (relation->rel_flags & REL_temp_tran))
|
||||
relation->delPages(tdbb, transaction->tra_number);
|
||||
@ -2509,7 +2515,7 @@ static void retain_temp_tables(thread_db* tdbb, jrd_tra* transaction, TraNumber
|
||||
|
||||
for (FB_SIZE_T i = 0; i < mdc->relCount(tdbb); i++)
|
||||
{
|
||||
HazardPtr<jrd_rel> relation = mdc->getRelation(tdbb, i);
|
||||
jrd_rel* relation = mdc->getRelation(tdbb, i);
|
||||
|
||||
if (relation && (relation->rel_flags & REL_temp_tran))
|
||||
relation->retainPages(tdbb, transaction->tra_number, new_number);
|
||||
@ -3188,7 +3194,7 @@ static void transaction_options(thread_db* tdbb,
|
||||
const MetaName metaName = attachment->nameToMetaCharSet(tdbb, orgName);
|
||||
|
||||
tpb += len;
|
||||
HazardPtr<jrd_rel> relation = MetadataCache::lookup_relation(tdbb, metaName);
|
||||
jrd_rel* relation = MetadataCache::lookup_relation(tdbb, metaName);
|
||||
if (!relation)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_bad_tpb_content) <<
|
||||
@ -3781,7 +3787,7 @@ jrd_tra::~jrd_tra()
|
||||
|
||||
delete tra_sec_db_context;
|
||||
|
||||
tra_resources.releaseResources(nullptr, this);
|
||||
// !!!!!!!!!!!!!!!!!!!! tra_resources.releaseResources(nullptr, this);
|
||||
}
|
||||
|
||||
|
||||
@ -4053,7 +4059,7 @@ void jrd_tra::checkBlob(thread_db* tdbb, const bid* blob_id, jrd_fld* fld, bool
|
||||
!tra_fetched_blobs.locate(*blob_id))
|
||||
{
|
||||
MetadataCache* mdc = tra_attachment->att_database->dbb_mdc;
|
||||
HazardPtr<jrd_rel> blobRelation = mdc->getRelation(tdbb, rel_id);
|
||||
jrd_rel* blobRelation = mdc->getRelation(tdbb, rel_id);
|
||||
|
||||
if (blobRelation)
|
||||
{
|
||||
@ -4176,7 +4182,7 @@ TraceSweepEvent::~TraceSweepEvent()
|
||||
}
|
||||
|
||||
|
||||
void TraceSweepEvent::beginSweepRelation(const HazardPtr<jrd_rel>& relation)
|
||||
void TraceSweepEvent::beginSweepRelation(const jrd_rel* relation)
|
||||
{
|
||||
if (!m_need_trace)
|
||||
return;
|
||||
|
@ -178,7 +178,7 @@ public:
|
||||
tra_blob_util_map(*p),
|
||||
tra_arrays(NULL),
|
||||
tra_deferred_job(NULL),
|
||||
tra_resources(*p, false),
|
||||
// tra_resources(*p, false),
|
||||
tra_context_vars(*p),
|
||||
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
|
||||
tra_timestamp(Firebird::TimeZoneUtil::getCurrentSystemTimeStamp()),
|
||||
@ -282,7 +282,7 @@ public:
|
||||
SavNumber tra_save_point_number; // next save point number to use
|
||||
ULONG tra_flags;
|
||||
DeferredJob* tra_deferred_job; // work deferred to commit time
|
||||
ResourceList tra_resources; // resource existence list
|
||||
// ResourceList tra_resources; // resource existence list
|
||||
Firebird::StringMap tra_context_vars; // Context variables for the transaction
|
||||
traRpbList* tra_rpblist; // active record_param's of given transaction
|
||||
UCHAR tra_use_count; // use count for safe AST delivery
|
||||
|
@ -30,6 +30,8 @@ namespace Jrd {
|
||||
class Attachment;
|
||||
class Database;
|
||||
class TraceTransactionEnd;
|
||||
|
||||
class ResourceList;
|
||||
}
|
||||
|
||||
bool TRA_active_transactions(Jrd::thread_db* tdbb, Jrd::Database*);
|
||||
@ -47,7 +49,9 @@ void TRA_init(Jrd::Attachment*);
|
||||
void TRA_invalidate(Jrd::thread_db* tdbb, ULONG);
|
||||
void TRA_link_cursor(Jrd::jrd_tra*, Jrd::DsqlCursor*);
|
||||
void TRA_unlink_cursor(Jrd::jrd_tra*, Jrd::DsqlCursor*);
|
||||
|
||||
void TRA_post_resources(Jrd::thread_db* tdbb, Jrd::jrd_tra*, Jrd::ResourceList&);
|
||||
|
||||
bool TRA_is_active(Jrd::thread_db*, TraNumber);
|
||||
void TRA_prepare(Jrd::thread_db* tdbb, Jrd::jrd_tra*, USHORT, const UCHAR*);
|
||||
Jrd::jrd_tra* TRA_reconnect(Jrd::thread_db* tdbb, const UCHAR*, USHORT);
|
||||
|
@ -507,7 +507,7 @@ public:
|
||||
m_sweep_info.update(header);
|
||||
}
|
||||
|
||||
void beginSweepRelation(const HazardPtr<jrd_rel>& relation);
|
||||
void beginSweepRelation(const jrd_rel* relation);
|
||||
void endSweepRelation();
|
||||
|
||||
void finish()
|
||||
|
@ -1629,13 +1629,13 @@ void Validation::walk_database()
|
||||
}
|
||||
|
||||
MetadataCache* mdc = dbb->dbb_mdc;
|
||||
for (USHORT i = 0; i < mdc->relCount(&dbb->dbb_delayed_delete); i++)
|
||||
for (USHORT i = 0; i < mdc->relCount(); i++)
|
||||
{
|
||||
#ifdef DEBUG_VAL_VERBOSE
|
||||
if (i > dbb->dbb_max_sys_rel) // Why not system flag instead?
|
||||
VAL_debug_level = 2;
|
||||
#endif
|
||||
HazardPtr<jrd_rel> relation = mdc->getRelation(vdr_tdbb, i);
|
||||
jrd_rel* relation = mdc->getRelation(vdr_tdbb, i);
|
||||
ExistenceGuard g(vdr_tdbb, relation->rel_existence_lock);
|
||||
|
||||
if (MetadataCache::checkRelation(vdr_tdbb, relation.getPointer()))
|
||||
@ -3005,7 +3005,7 @@ void Validation::checkDPinPIP(jrd_rel* relation, ULONG page_number)
|
||||
release_page(&pip_window);
|
||||
}
|
||||
|
||||
Validation::RTN Validation::walk_relation(HazardPtr<jrd_rel>& rel)
|
||||
Validation::RTN Validation::walk_relation(jrd_rel* rel)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
|
@ -218,7 +218,7 @@ private:
|
||||
void walk_pip();
|
||||
RTN walk_pointer_page(jrd_rel*, ULONG);
|
||||
RTN walk_record(jrd_rel*, const Ods::rhd*, USHORT, RecordNumber, bool);
|
||||
RTN walk_relation(HazardPtr<jrd_rel>&);
|
||||
RTN walk_relation(jrd_rel*);
|
||||
RTN walk_root(jrd_rel*, bool);
|
||||
RTN walk_scns();
|
||||
RTN walk_tip(TraNumber);
|
||||
|
@ -2002,8 +2002,8 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
|
||||
if (needDfw(tdbb, transaction))
|
||||
{
|
||||
HazardPtr<jrd_rel> r2(FB_FUNCTION);
|
||||
HazardPtr<jrd_prc> procedure(FB_FUNCTION);
|
||||
jrd_rel* r2;
|
||||
HazardPtr<jrd_prc> procedure;
|
||||
USHORT id;
|
||||
DeferredWork* work;
|
||||
|
||||
@ -2060,7 +2060,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
}
|
||||
EVL_field(0, rpb->rpb_record, f_rel_name, &desc);
|
||||
DFW_post_work(transaction, dfw_delete_relation, &desc, id);
|
||||
HazardPtr<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)
|
||||
MET_scan_relation(tdbb, rel_drop);
|
||||
}
|
||||
@ -2149,7 +2149,7 @@ bool VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
MetaName index_name;
|
||||
MOV_get_metaname(tdbb, &desc3, index_name);
|
||||
|
||||
HazardPtr<jrd_rel> partner(FB_FUNCTION);
|
||||
jrd_rel* partner;
|
||||
index_desc idx;
|
||||
|
||||
if ((BTR_lookup(tdbb, r2.getPointer(), id - 1, &idx, r2->getBasePages())) &&
|
||||
@ -4367,7 +4367,7 @@ bool VIO_sweep(thread_db* tdbb, jrd_tra* transaction, TraceSweepEvent* traceSwee
|
||||
// hvlad: restore tdbb->transaction since it can be used later
|
||||
tdbb->setTransaction(transaction);
|
||||
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation;
|
||||
|
||||
record_param rpb;
|
||||
rpb.rpb_record = NULL;
|
||||
@ -5251,7 +5251,7 @@ void Database::garbage_collector(Database* dbb)
|
||||
Jrd::Attachment::UseCountHolder use(attachment);
|
||||
tdbb->markAsSweeper();
|
||||
|
||||
HazardPtr<jrd_rel> relation(FB_FUNCTION);
|
||||
jrd_rel* relation;
|
||||
record_param rpb;
|
||||
rpb.getWindow(tdbb).win_flags = WIN_garbage_collector;
|
||||
rpb.rpb_stream_flags = RPB_s_no_data | RPB_s_sweeper;
|
||||
|
Loading…
Reference in New Issue
Block a user