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