8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 18:43:02 +01:00

Added IRoutineMetadata to external engines.

Not well tested:
1) EE is broken after shared page cache.
2) Semantics of addRef/release still keeps changing in developers minds.
This commit is contained in:
asfernandes 2011-05-15 15:37:11 +00:00
parent 9083c98e8b
commit 983686d71c
7 changed files with 281 additions and 149 deletions

View File

@ -30,6 +30,8 @@ using namespace Firebird;
using namespace Firebird::Udr;
typedef IMaster* (ISC_EXPORT *FuncGetMasterInterface)();
typedef ISC_LONG (ISC_EXPORT_VARARG *FuncEventBlock)(ISC_UCHAR**, ISC_UCHAR**, ISC_USHORT, ...);
typedef ISC_STATUS (ISC_EXPORT *FuncWaitForEvent)(ISC_STATUS*, isc_db_handle*,
short, const ISC_UCHAR*, ISC_UCHAR*);
@ -50,6 +52,87 @@ typedef ISC_STATUS (ISC_EXPORT *FuncDsqlPrepare)(ISC_STATUS*, isc_tr_handle*, is
unsigned short, const ISC_SCHAR*, unsigned short, XSQLDA*);
namespace
{
template <typename T>
class AutoDispose
{
public:
AutoDispose<T>(T* aPtr = NULL)
: ptr(aPtr)
{
}
~AutoDispose()
{
clear();
}
AutoDispose<T>& operator =(T* aPtr)
{
clear();
ptr = aPtr;
return *this;
}
operator T*()
{
return ptr;
}
operator const T*() const
{
return ptr;
}
bool operator !() const
{
return !ptr;
}
bool hasData() const
{
return ptr != NULL;
}
T* operator ->()
{
return ptr;
}
T* release()
{
T* tmp = ptr;
ptr = NULL;
return tmp;
}
void reset(T* aPtr = NULL)
{
if (aPtr != ptr)
{
clear();
ptr = aPtr;
}
}
private:
void clear()
{
if (ptr)
ptr->dispose();
}
// not implemented
AutoDispose<T>(AutoDispose<T>&);
void operator =(AutoDispose<T>&);
private:
T* ptr;
};
}
/***
create function wait_event (
event_name varchar(31) character set ascii
@ -135,6 +218,7 @@ private:
isc_stmt_handle stmtHandle;
// ISC entry points
FuncGetMasterInterface funcGetMasterInterface;
FuncDsqlAllocateStatement funcDsqlAllocateStatement;
FuncDsqlDescribe funcDsqlDescribe;
FuncDsqlDescribeBind funcDsqlDescribeBind;
@ -246,6 +330,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
return;
// ISC entry points
funcGetMasterInterface = (FuncGetMasterInterface) getEntryPoint(context, "fb_get_master_interface");
funcDsqlAllocateStatement = (FuncDsqlAllocateStatement)
getEntryPoint(context, "isc_dsql_allocate_statement");
funcDsqlDescribe = (FuncDsqlDescribe) getEntryPoint(context, "isc_dsql_describe");
@ -265,14 +350,33 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
"select data_source from replicate_config where name = ?",
SQL_DIALECT_CURRENT, NULL), statusVector);
AutoDispose<IMaster> master(funcGetMasterInterface());
AutoDispose<IStatus> status(master->getStatus());
const char* table = metadata->getTriggerTable(status);
ThrowError::check(status->get());
// Skip the first exclamation point, separing the module name and entry point.
const char* info = strchr(metadata->getEntryPoint(status), '!');
ThrowError::check(status->get());
// Skip the second exclamation point, separing the entry point and the misc info (config).
if (info)
info = strchr(info + 1, '!');
if (info)
++info;
else
info = "";
inSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
inSqlDa->version = SQLDA_VERSION1;
inSqlDa->sqln = 1;
ThrowError::check(funcDsqlDescribeBind(statusVector, &stmtHandle, SQL_DIALECT_CURRENT, inSqlDa),
statusVector);
inSqlDa->sqlvar[0].sqldata = new char[sizeof(short) + inSqlDa->sqlvar[0].sqllen];
strncpy(inSqlDa->sqlvar[0].sqldata + sizeof(short), metaInfo->info, inSqlDa->sqlvar[0].sqllen);
*reinterpret_cast<short*>(inSqlDa->sqlvar[0].sqldata) = strlen(metaInfo->info);
strncpy(inSqlDa->sqlvar[0].sqldata + sizeof(short), info, inSqlDa->sqlvar[0].sqllen);
*reinterpret_cast<short*>(inSqlDa->sqlvar[0].sqldata) = strlen(info);
XSQLDA* outSqlDa = reinterpret_cast<XSQLDA*>(new char[(XSQLDA_LENGTH(1))]);
outSqlDa->version = SQLDA_VERSION1;
@ -304,7 +408,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
const char* name = val->getName(ThrowError());
strcat(buffer, " p");
sprintf(buffer + strlen(buffer), "%d type of column \"%s\".\"%s\" = ?", i, metaInfo->table, name);
sprintf(buffer + strlen(buffer), "%d type of column \"%s\".\"%s\" = ?", i, table, name);
}
strcat(buffer,
@ -313,7 +417,7 @@ void FB_UDR_TRIGGER(replicate)::initialize(ExternalContext* context, Values* val
"begin\n"
" execute statement ('insert into \"");
strcat(buffer, metaInfo->table);
strcat(buffer, table);
strcat(buffer, "\" (");
for (int i = 1; i <= count; ++i)
@ -449,7 +553,7 @@ FB_UDR_BEGIN_TRIGGER(replicate)
{
case SQL_VARYING:
{
uint len;
unsigned len;
const char* s = val->getString(ThrowError(), &len);
*reinterpret_cast<unsigned short*>(var->sqldata) = len;
memcpy(var->sqldata + sizeof(unsigned short), s, len);

View File

@ -152,6 +152,19 @@ public:
};
class IRoutineMetadata // : public IVersioned
{
public:
virtual const char* FB_CARG getPackage(IStatus* status) const = 0;
virtual const char* FB_CARG getName(IStatus* status) const = 0;
virtual const char* FB_CARG getEntryPoint(IStatus* status) const = 0;
virtual const char* FB_CARG getBody(IStatus* status) const = 0;
virtual const char* FB_CARG getTriggerTable(IStatus* status) const = 0;
virtual ExternalTrigger::Type FB_CARG getTriggerType(IStatus* status) const = 0;
};
// #define FB_I_ROUTINE_METADATA_VERSION (FB_VERSIONED_VERSION + 6)
// In SuperServer, shared by all attachments to one database and disposed when last (non-external)
// user attachment to the database is closed.
class ExternalEngine : public IPluginBase
@ -175,12 +188,11 @@ public:
// Called when engine wants to load object in the cache. Objects are disposed when
// going out of the cache.
virtual ExternalFunction* FB_CALL makeFunction(Error* error, ExternalContext* context,
const char* package, const char* name, const char* entryPoint, const char* body) = 0;
const IRoutineMetadata* metadata) = 0;
virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context,
const char* package, const char* name, const char* entryPoint, const char* body) = 0;
const IRoutineMetadata* metadata) = 0;
virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context,
const char* name, const char* entryPoint, const char* body,
const char* table, ExternalTrigger::Type type) = 0;
const IRoutineMetadata* metadata) = 0;
};
#define FB_EXTERNAL_ENGINE_VERSION (FB_PLUGIN_VERSION + 7)

View File

@ -34,24 +34,6 @@ namespace Firebird
//------------------------------------------------------------------------------
// Metadata information passed from the UDR engine to user's routines factories when asking to
// create routines instances.
struct MetaInfo
{
const char* package; // package name - NULL from triggers
const char* name; // metadata object name
const char* entryPoint; // external routine's name
const char* info; // misc. info encoded on the external name
const char* body; // body text
};
struct TriggerMetaInfo : public MetaInfo
{
ExternalTrigger::Type type; // trigger type
const char* table; // table name
};
// Factory classes. They should be singletons instances created by user's modules and
// registered. When UDR engine is going to load a routine, it calls newItem.
@ -59,21 +41,21 @@ class FunctionFactory
{
public:
virtual const char* FB_CALL getName() = 0;
virtual ExternalFunction* FB_CALL newItem(MetaInfo* metaInfo) = 0;
virtual ExternalFunction* FB_CALL newItem(const IRoutineMetadata* metadata) = 0;
};
class ProcedureFactory
{
public:
virtual const char* FB_CALL getName() = 0;
virtual ExternalProcedure* FB_CALL newItem(MetaInfo* metaInfo) = 0;
virtual ExternalProcedure* FB_CALL newItem(const IRoutineMetadata* metadata) = 0;
};
class TriggerFactory
{
public:
virtual const char* FB_CALL getName() = 0;
virtual ExternalTrigger* FB_CALL newItem(TriggerMetaInfo* metaInfo) = 0;
virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata) = 0;
};

View File

@ -503,7 +503,7 @@ public:
}
public:
MetaInfo* metaInfo;
const IRoutineMetadata* metadata;
};
@ -525,7 +525,7 @@ public:
}
public:
MetaInfo* metaInfo;
const IRoutineMetadata* metadata;
};
@ -547,7 +547,7 @@ public:
}
public:
TriggerMetaInfo* metaInfo;
const IRoutineMetadata* metadata;
};
@ -566,10 +566,10 @@ public:
return name;
}
virtual ExternalFunction* FB_CALL newItem(MetaInfo* metaInfo)
virtual ExternalFunction* FB_CALL newItem(const IRoutineMetadata* metadata)
{
Function* function = new T();
function->metaInfo = metaInfo;
function->metadata = metadata;
return function;
}
@ -593,10 +593,10 @@ public:
return name;
}
virtual ExternalProcedure* FB_CALL newItem(MetaInfo* metaInfo)
virtual ExternalProcedure* FB_CALL newItem(const IRoutineMetadata* metadata)
{
Procedure* procedure = new T();
procedure->metaInfo = metaInfo;
procedure->metadata = metadata;
return procedure;
}
@ -620,10 +620,10 @@ public:
return name;
}
virtual ExternalTrigger* FB_CALL newItem(TriggerMetaInfo* metaInfo)
virtual ExternalTrigger* FB_CALL newItem(const IRoutineMetadata* metadata)
{
Trigger* trigger = new T();
trigger->metaInfo = metaInfo;
trigger->metadata = metadata;
return trigger;
}

View File

@ -286,10 +286,11 @@ void* FB_CALL ExtEngineManager::ExternalContextImpl::setInfo(int code, void* val
ExtEngineManager::Function::Function(thread_db* tdbb, ExtEngineManager* aExtManager,
ExternalEngine* aEngine, ExternalFunction* aFunction,
ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalFunction* aFunction,
const Jrd::Function* aUdf)
: extManager(aExtManager),
engine(aEngine),
metadata(aMetadata),
function(aFunction),
udf(aUdf),
database(tdbb->getDatabase())
@ -384,10 +385,11 @@ void ExtEngineManager::Function::execute(thread_db* tdbb, const NestValueArray&
ExtEngineManager::Procedure::Procedure(thread_db* tdbb, ExtEngineManager* aExtManager,
ExternalEngine* aEngine, ExternalProcedure* aProcedure,
ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalProcedure* aProcedure,
const jrd_prc* aPrc)
: extManager(aExtManager),
engine(aEngine),
metadata(aMetadata),
procedure(aProcedure),
prc(aPrc),
database(tdbb->getDatabase())
@ -467,10 +469,11 @@ bool ExtEngineManager::ResultSet::fetch(thread_db* tdbb)
ExtEngineManager::Trigger::Trigger(thread_db* tdbb, ExtEngineManager* aExtManager,
ExternalEngine* aEngine, ExternalTrigger* aTrigger,
ExternalEngine* aEngine, RoutineMetadata* aMetadata, ExternalTrigger* aTrigger,
const Jrd::Trigger* aTrg)
: extManager(aExtManager),
engine(aEngine),
metadata(aMetadata),
trigger(aTrigger),
trg(aTrg),
database(tdbb->getDatabase())
@ -651,14 +654,19 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons
CallerName(obj_udf, udf->getName().identifier) :
CallerName(obj_package_header, udf->getName().package)));
MemoryPool& pool = *tdbb->getDefaultPool();
AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
metadata->package = udf->getName().package;
metadata->name = udf->getName().identifier;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
ExternalFunction* externalFunction;
{ // scope
Attachment::Checkout attCout(tdbb->getAttachment());
externalFunction = attInfo->engine->makeFunction(RaiseError(),
attInfo->context, udf->getName().package.nullStr(), udf->getName().identifier.c_str(),
entryPointTrimmed.nullStr(), body.nullStr());
externalFunction = attInfo->engine->makeFunction(RaiseError(), attInfo->context, metadata);
if (!externalFunction)
{
@ -670,7 +678,8 @@ ExtEngineManager::Function* ExtEngineManager::makeFunction(thread_db* tdbb, cons
try
{
return FB_NEW(getPool()) Function(tdbb, this, attInfo->engine, externalFunction, udf);
return FB_NEW(getPool()) Function(tdbb, this, attInfo->engine, metadata.release(),
externalFunction, udf);
}
catch (...)
{
@ -693,14 +702,19 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co
CallerName(obj_procedure, prc->getName().identifier) :
CallerName(obj_package_header, prc->getName().package)));
MemoryPool& pool = *tdbb->getDefaultPool();
AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
metadata->package = prc->getName().package;
metadata->name = prc->getName().identifier;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
ExternalProcedure* externalProcedure;
{ // scope
Attachment::Checkout attCout(tdbb->getAttachment());
externalProcedure = attInfo->engine->makeProcedure(RaiseError(),
attInfo->context, prc->getName().package.nullStr(), prc->getName().identifier.c_str(),
entryPointTrimmed.nullStr(), body.nullStr());
externalProcedure = attInfo->engine->makeProcedure(RaiseError(), attInfo->context, metadata);
if (!externalProcedure)
{
@ -712,7 +726,8 @@ ExtEngineManager::Procedure* ExtEngineManager::makeProcedure(thread_db* tdbb, co
try
{
return FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine, externalProcedure, prc);
return FB_NEW(getPool()) Procedure(tdbb, this, attInfo->engine, metadata.release(),
externalProcedure, prc);
}
catch (...)
{
@ -729,22 +744,25 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
string entryPointTrimmed = entryPoint;
entryPointTrimmed.trim();
MetaName relationNameTrimmed;
if (trg->relation)
relationNameTrimmed = trg->relation->rel_name;
EngineAttachmentInfo* attInfo = getEngineAttachment(tdbb, engine);
ContextManager<ExternalTrigger> ctxManager(tdbb, attInfo, attInfo->adminCharSet,
CallerName(obj_trigger, trg->name));
MemoryPool& pool = *tdbb->getDefaultPool();
AutoPtr<RoutineMetadata> metadata(FB_NEW(pool) RoutineMetadata(pool));
metadata->name = trg->name;
metadata->entryPoint = entryPointTrimmed;
metadata->body = body;
metadata->triggerType = type;
if (trg->relation)
metadata->triggerTable = trg->relation->rel_name;
ExternalTrigger* externalTrigger;
{ // scope
Attachment::Checkout attCout(tdbb->getAttachment());
externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context,
trg->name.c_str(), entryPointTrimmed.nullStr(), body.nullStr(),
relationNameTrimmed.c_str(), type);
externalTrigger = attInfo->engine->makeTrigger(RaiseError(), attInfo->context, metadata);
if (!externalTrigger)
{
@ -755,7 +773,8 @@ ExtEngineManager::Trigger* ExtEngineManager::makeTrigger(thread_db* tdbb, const
try
{
return FB_NEW(getPool()) Trigger(tdbb, this, attInfo->engine, externalTrigger, trg);
return FB_NEW(getPool()) Trigger(tdbb, this, attInfo->engine, metadata.release(),
externalTrigger, trg);
}
catch (...)
{

View File

@ -61,6 +61,59 @@ private:
template <typename T> class ContextManager;
class TransactionImpl;
class RoutineMetadata : public Firebird::IRoutineMetadata, public Firebird::PermanentStorage
{
public:
RoutineMetadata(MemoryPool& pool)
: PermanentStorage(pool),
package(pool),
name(pool),
entryPoint(pool),
body(pool),
triggerTable(pool),
triggerType(Firebird::ExternalTrigger::Type(0))
{
}
virtual const char* FB_CARG getPackage(Firebird::IStatus* /*status*/) const
{
return package.nullStr();
}
virtual const char* FB_CARG getName(Firebird::IStatus* /*status*/) const
{
return name.c_str();
}
virtual const char* FB_CARG getEntryPoint(Firebird::IStatus* /*status*/) const
{
return entryPoint.c_str();
}
virtual const char* FB_CARG getBody(Firebird::IStatus* /*status*/) const
{
return body.c_str();
}
virtual const char* FB_CARG getTriggerTable(Firebird::IStatus* /*status*/) const
{
return triggerTable.c_str();
}
virtual Firebird::ExternalTrigger::Type FB_CARG getTriggerType(Firebird::IStatus* /*status*/) const
{
return triggerType;
}
public:
Firebird::MetaName package;
Firebird::MetaName name;
Firebird::string entryPoint;
Firebird::string body;
Firebird::MetaName triggerTable;
Firebird::ExternalTrigger::Type triggerType;
};
class ExternalContextImpl : public Firebird::ExternalContext
{
friend class AttachmentImpl;
@ -130,6 +183,7 @@ public:
public:
Function(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::ExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::ExternalFunction* aFunction,
const Jrd::Function* aUdf);
~Function();
@ -140,6 +194,7 @@ public:
private:
ExtEngineManager* extManager;
Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Firebird::ExternalFunction* function;
const Jrd::Function* udf;
Database* database;
@ -152,6 +207,7 @@ public:
public:
Procedure(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::ExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::ExternalProcedure* aProcedure,
const jrd_prc* aPrc);
~Procedure();
@ -161,6 +217,7 @@ public:
private:
ExtEngineManager* extManager;
Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Firebird::ExternalProcedure* procedure;
const jrd_prc* prc;
Database* database;
@ -191,6 +248,7 @@ public:
public:
Trigger(thread_db* tdbb, ExtEngineManager* aExtManager,
Firebird::ExternalEngine* aEngine,
RoutineMetadata* aMetadata,
Firebird::ExternalTrigger* aTrigger,
const Jrd::Trigger* aTrg);
~Trigger();
@ -205,6 +263,7 @@ public:
ExtEngineManager* extManager;
Firebird::ExternalEngine* engine;
Firebird::AutoPtr<RoutineMetadata> metadata;
Firebird::ExternalTrigger* trigger;
const Jrd::Trigger* trg;
Database* database;

View File

@ -36,6 +36,7 @@
#include "../common/os/mod_loader.h"
#include "../common/os/path_utils.h"
#include "../common/classes/ImplementHelper.h"
#include "../common/StatusHolder.h"
namespace Firebird
@ -130,7 +131,7 @@ public:
}
public:
void loadModule(const string& str, PathName* moduleName, string* entryPoint, string* info);
void loadModule(const IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint);
template <typename NodeType, typename ObjType, typename SharedObjType> ObjType* getChild(
GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children, SharedObjType* sharedObj,
ExternalContext* context, NodeType* nodes, SortedArray<SharedObjType*>& sharedObjs,
@ -138,12 +139,12 @@ public:
template <typename ObjType> void deleteChildren(
GenericMap<Pair<NonPooled<ExternalContext*, ObjType*> > >& children);
template <typename T, typename T2> T* findNode(T* nodes, const PathName& moduleName,
T2* metaInfo);
template <typename T> T* findNode(T* nodes, const PathName& moduleName,
const string& entryPoint);
private:
template <typename T, typename T2, typename T3> T2* getNode(T* nodes, const PathName& moduleName,
T3* metaInfo);
template <typename T, typename T2> T2* getNode(T* nodes, const PathName& moduleName,
const IRoutineMetadata* metadata, const string& entryPoint);
public:
virtual int FB_CALL getVersion(Error* error);
@ -151,12 +152,11 @@ public:
virtual void FB_CALL openAttachment(Error* error, ExternalContext* context);
virtual void FB_CALL closeAttachment(Error* error, ExternalContext* context);
virtual ExternalFunction* FB_CALL makeFunction(Error* error, ExternalContext* context,
const char* package, const char* name, const char* entryPoint, const char* body);
const IRoutineMetadata* metadata);
virtual ExternalProcedure* FB_CALL makeProcedure(Error* error, ExternalContext* context,
const char* package, const char* name, const char* entryPoint, const char* body);
const IRoutineMetadata* metadata);
virtual ExternalTrigger* FB_CALL makeTrigger(Error* error, ExternalContext* context,
const char* name, const char* entryPoint, const char* body, const char* table,
ExternalTrigger::Type type);
const IRoutineMetadata* metadata);
public:
virtual void FB_CALL dispose(Error* error);
@ -205,25 +205,16 @@ static TriggerNode* registeredTriggers = NULL;
class SharedFunction : public ExternalFunction
{
public:
SharedFunction(Engine* aEngine, const string& aPackage, const string& aName,
const string& aEntryPoint, const string& aBody)
SharedFunction(Engine* aEngine, const IRoutineMetadata* aMetadata)
: engine(aEngine),
package(*getDefaultMemoryPool(), aPackage),
name(*getDefaultMemoryPool(), aName),
entryPoint(*getDefaultMemoryPool()),
body(*getDefaultMemoryPool(), aBody),
metadata(aMetadata),
moduleName(*getDefaultMemoryPool()),
entryPoint(*getDefaultMemoryPool()),
info(*getDefaultMemoryPool()),
children(*getDefaultMemoryPool())
{
engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info);
metaInfo.package = package.nullStr();
metaInfo.name = name.c_str();
metaInfo.entryPoint = entryPoint.c_str();
metaInfo.body = body.c_str();
metaInfo.info = info.c_str();
engine->findNode<FunctionNode, MetaInfo>(registeredFunctions, moduleName, &metaInfo);
engine->loadModule(metadata, &moduleName, &entryPoint);
engine->findNode<FunctionNode>(registeredFunctions, moduleName, entryPoint);
}
virtual ~SharedFunction()
@ -266,13 +257,10 @@ public:
}
public:
MetaInfo metaInfo;
Engine* engine;
string package;
string name;
string entryPoint;
string body;
const IRoutineMetadata* metadata;
PathName moduleName;
string entryPoint;
string info;
GenericMap<Pair<NonPooled<ExternalContext*, ExternalFunction*> > > children;
};
@ -284,25 +272,15 @@ public:
class SharedProcedure : public ExternalProcedure
{
public:
SharedProcedure(Engine* aEngine, const string& aPackage, const string& aName,
const string& aEntryPoint, const string& aBody)
SharedProcedure(Engine* aEngine, const IRoutineMetadata* aMetadata)
: engine(aEngine),
package(*getDefaultMemoryPool(), aPackage),
name(*getDefaultMemoryPool(), aName),
entryPoint(*getDefaultMemoryPool(), aEntryPoint),
body(*getDefaultMemoryPool(), aBody),
moduleName(*getDefaultMemoryPool()),
entryPoint(*getDefaultMemoryPool()),
info(*getDefaultMemoryPool()),
children(*getDefaultMemoryPool())
{
engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info);
metaInfo.package = package.nullStr();
metaInfo.name = name.c_str();
metaInfo.entryPoint = entryPoint.c_str();
metaInfo.body = body.c_str();
metaInfo.info = info.c_str();
engine->findNode<ProcedureNode, MetaInfo>(registeredProcedures, moduleName, &metaInfo);
engine->loadModule(metadata, &moduleName, &entryPoint);
engine->findNode<ProcedureNode>(registeredProcedures, moduleName, entryPoint);
}
virtual ~SharedProcedure()
@ -352,13 +330,10 @@ public:
}
public:
MetaInfo metaInfo;
Engine* engine;
string package;
string name;
string entryPoint;
string body;
const IRoutineMetadata* metadata;
PathName moduleName;
string entryPoint;
string info;
GenericMap<Pair<NonPooled<ExternalContext*, ExternalProcedure*> > > children;
};
@ -370,28 +345,16 @@ public:
class SharedTrigger : public ExternalTrigger
{
public:
SharedTrigger(Engine* aEngine, const string& aName, const string& aEntryPoint,
const string& aBody, const string& aTable, ExternalTrigger::Type aType)
SharedTrigger(Engine* aEngine, const IRoutineMetadata* aMetadata)
: engine(aEngine),
name(*getDefaultMemoryPool(), aName),
entryPoint(*getDefaultMemoryPool(), aEntryPoint),
body(*getDefaultMemoryPool(), aBody),
metadata(aMetadata),
moduleName(*getDefaultMemoryPool()),
entryPoint(*getDefaultMemoryPool()),
info(*getDefaultMemoryPool()),
table(*getDefaultMemoryPool(), aTable),
type(aType),
children(*getDefaultMemoryPool())
{
engine->loadModule(aEntryPoint, &moduleName, &entryPoint, &info);
metaInfo.package = NULL;
metaInfo.name = name.c_str();
metaInfo.entryPoint = entryPoint.c_str();
metaInfo.body = body.c_str();
metaInfo.info = info.c_str();
metaInfo.type = type;
metaInfo.table = table.nullStr();
engine->findNode<TriggerNode, TriggerMetaInfo>(registeredTriggers, moduleName, &metaInfo);
engine->loadModule(metadata, &moduleName, &entryPoint);
engine->findNode<TriggerNode>(registeredTriggers, moduleName, entryPoint);
}
virtual ~SharedTrigger()
@ -434,15 +397,11 @@ public:
}
public:
TriggerMetaInfo metaInfo;
Engine* engine;
string name;
string entryPoint;
string body;
const IRoutineMetadata* metadata;
PathName moduleName;
string entryPoint;
string info;
string table;
ExternalTrigger::Type type;
GenericMap<Pair<NonPooled<ExternalContext*, ExternalTrigger*> > > children;
};
@ -530,8 +489,12 @@ ModulesMap::~ModulesMap()
//--------------------------------------
void Engine::loadModule(const string& str, PathName* moduleName, string* entryPoint, string* info)
void Engine::loadModule(const IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint)
{
LocalStatus status;
const string str(metadata->getEntryPoint(&status));
ThrowError::check(status.get());
const size_t pos = str.find('!');
if (pos == string::npos)
{
@ -562,7 +525,6 @@ void Engine::loadModule(const string& str, PathName* moduleName, string* entryPo
*entryPoint = str.substr(pos + 1);
size_t n = entryPoint->find('!');
*info = (n == string::npos ? "" : entryPoint->substr(n + 1));
*entryPoint = (n == string::npos ? *entryPoint : entryPoint->substr(0, n));
MutexLockGuard guard(modulesMutex);
@ -612,7 +574,7 @@ template <typename NodeType, typename ObjType, typename SharedObjType> ObjType*
ObjType* obj;
if (!children.get(context, obj))
{
obj = getNode<NodeType, ObjType>(nodes, moduleName, &sharedObj->metaInfo);
obj = getNode<NodeType, ObjType>(nodes, moduleName, sharedObj->metadata, sharedObj->entryPoint);
if (obj)
children.put(context, obj);
}
@ -634,11 +596,9 @@ template <typename ObjType> void Engine::deleteChildren(
}
template <typename T, typename T2> T* Engine::findNode(T* nodes,
const PathName& moduleName, T2* params)
template <typename T> T* Engine::findNode(T* nodes, const PathName& moduleName,
const string& entryPoint)
{
const string entryPoint(params->entryPoint);
for (T* node = nodes; node; node = node->next)
{
if (node->module == moduleName && entryPoint == node->factory->getName())
@ -658,11 +618,11 @@ template <typename T, typename T2> T* Engine::findNode(T* nodes,
}
template <typename T, typename T2, typename T3> T2* Engine::getNode(T* nodes,
const PathName& moduleName, T3* params)
template <typename T, typename T2> T2* Engine::getNode(T* nodes, const PathName& moduleName,
const IRoutineMetadata* metadata, const string& entryPoint)
{
T* node = findNode<T, T3>(nodes, moduleName, params);
return node->factory->newItem(params);
T* node = findNode<T>(nodes, moduleName, entryPoint);
return node->factory->newItem(metadata);
}
@ -720,12 +680,11 @@ void FB_CALL Engine::closeAttachment(Error* error, ExternalContext* context)
ExternalFunction* FB_CALL Engine::makeFunction(Error* error, ExternalContext* /*context*/,
const char* package, const char* name, const char* entryPoint, const char* body)
const IRoutineMetadata* metadata)
{
try
{
return new SharedFunction(this, (package ? package : ""), name,
(entryPoint ? entryPoint : ""), (body ? body : ""));
return new SharedFunction(this, metadata);
}
catch (const ThrowError::Exception& e)
{
@ -736,12 +695,11 @@ ExternalFunction* FB_CALL Engine::makeFunction(Error* error, ExternalContext* /*
ExternalProcedure* FB_CALL Engine::makeProcedure(Error* error, ExternalContext* /*context*/,
const char* package, const char* name, const char* entryPoint, const char* body)
const IRoutineMetadata* metadata)
{
try
{
return new SharedProcedure(this, (package ? package : ""), name,
(entryPoint ? entryPoint : ""), (body ? body : ""));
return new SharedProcedure(this, metadata);
}
catch (const ThrowError::Exception& e)
{
@ -752,13 +710,11 @@ ExternalProcedure* FB_CALL Engine::makeProcedure(Error* error, ExternalContext*
ExternalTrigger* FB_CALL Engine::makeTrigger(Error* error, ExternalContext* /*context*/,
const char* name, const char* entryPoint, const char* body, const char* table,
ExternalTrigger::Type type)
const IRoutineMetadata* metadata)
{
try
{
return new SharedTrigger(this, name, (entryPoint ? entryPoint : ""), (body ? body : ""),
table, type);
return new SharedTrigger(this, metadata);
}
catch (const ThrowError::Exception& e)
{