From: <asf...@us...> - 2015-01-25 20:27:56
|
Revision: 60551 http://sourceforge.net/p/firebird/code/60551 Author: asfernandes Date: 2015-01-25 20:27:46 +0000 (Sun, 25 Jan 2015) Log Message: ----------- Improvements to the UDR plugin. Modified Paths: -------------- firebird/trunk/builds/posix/Makefile.in.plugins_examples firebird/trunk/builds/win32/msvc10/udrcpp_example.vcxproj firebird/trunk/builds/win32/msvc12/udrcpp_example.vcxproj firebird/trunk/builds/win32/msvc9/Firebird3_Examples.sln firebird/trunk/examples/udr/UdrCppExample.cpp firebird/trunk/src/include/firebird/FirebirdInterface.idl firebird/trunk/src/include/firebird/IdlFbInterfaces.h firebird/trunk/src/include/firebird/Interface.h firebird/trunk/src/include/firebird/UdrCppEngine.h firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp Removed Paths: ------------- firebird/trunk/src/include/firebird/UdrEngine.h Modified: firebird/trunk/builds/posix/Makefile.in.plugins_examples =================================================================== --- firebird/trunk/builds/posix/Makefile.in.plugins_examples 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/builds/posix/Makefile.in.plugins_examples 2015-01-25 20:27:46 UTC (rev 60551) @@ -67,7 +67,7 @@ $(FIREBIRD_LIBRARY_LINK) else $(LIB_LINK) $(LIB_LINK_OPTIONS) $(LIB_LINK_SONAME)udrcpp_example.$(SHRLIB_EXT) \ - $(LIB_PATH_OPTS) -o $@ $^ $(THR_LIBS) $(PLUGINS)/$(LIB_PREFIX)udr_engine.$(SHRLIB_EXT) \ + $(LIB_PATH_OPTS) -o $@ $^ $(THR_LIBS) \ $(FIREBIRD_LIBRARY_LINK) endif Modified: firebird/trunk/builds/win32/msvc10/udrcpp_example.vcxproj =================================================================== --- firebird/trunk/builds/win32/msvc10/udrcpp_example.vcxproj 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/builds/win32/msvc10/udrcpp_example.vcxproj 2015-01-25 20:27:46 UTC (rev 60551) @@ -207,13 +207,7 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\..\src\jrd</AdditionalIncludeDirectories> </ResourceCompile> </ItemGroup> - <ItemGroup> - <ProjectReference Include="udr_engine.vcxproj"> - <Project>{20debf08-ef0a-4c94-adeb-fe9bba14588b}</Project> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> - </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> Modified: firebird/trunk/builds/win32/msvc12/udrcpp_example.vcxproj =================================================================== --- firebird/trunk/builds/win32/msvc12/udrcpp_example.vcxproj 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/builds/win32/msvc12/udrcpp_example.vcxproj 2015-01-25 20:27:46 UTC (rev 60551) @@ -211,13 +211,7 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\..\src\jrd</AdditionalIncludeDirectories> </ResourceCompile> </ItemGroup> - <ItemGroup> - <ProjectReference Include="udr_engine.vcxproj"> - <Project>{20debf08-ef0a-4c94-adeb-fe9bba14588b}</Project> - <ReferenceOutputAssembly>false</ReferenceOutputAssembly> - </ProjectReference> - </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> -</Project> \ No newline at end of file +</Project> Modified: firebird/trunk/builds/win32/msvc9/Firebird3_Examples.sln =================================================================== --- firebird/trunk/builds/win32/msvc9/Firebird3_Examples.sln 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/builds/win32/msvc9/Firebird3_Examples.sln 2015-01-25 20:27:46 UTC (rev 60551) @@ -12,7 +12,6 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udrcpp_example", "udrcpp_example.vcproj", "{FF0FD8DF-1E5C-486E-B395-A620376A4633}" ProjectSection(ProjectDependencies) = postProject - {20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B} = {20DEBF08-EF0A-4C94-ADEB-FE9BBA14588B} {4FE03933-98CD-4879-A135-FD9430087A6B} = {4FE03933-98CD-4879-A135-FD9430087A6B} EndProjectSection EndProject Modified: firebird/trunk/examples/udr/UdrCppExample.cpp =================================================================== --- firebird/trunk/examples/udr/UdrCppExample.cpp 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/examples/udr/UdrCppExample.cpp 2015-01-25 20:27:46 UTC (rev 60551) @@ -783,3 +783,6 @@ AutoRelease<IMessageMetadata> triggerMetadata; AutoRelease<IStatement> stmt; FB_UDR_END_TRIGGER + + +FB_UDR_IMPLEMENT_ENTRY_POINT Modified: firebird/trunk/src/include/firebird/FirebirdInterface.idl =================================================================== --- firebird/trunk/src/include/firebird/FirebirdInterface.idl 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/src/include/firebird/FirebirdInterface.idl 2015-01-25 20:27:46 UTC (rev 60551) @@ -1216,23 +1216,32 @@ // UDR Factory interfaces. They should be singletons instances created by user's modules and // registered. When UDR engine is going to load a routine, it calls newItem. -interface UdrFunctionFactory : Versioned +interface UdrFunctionFactory : Disposable { void setup(Status status, ExternalContext context, RoutineMetadata metadata, MetadataBuilder inBuilder, MetadataBuilder outBuilder); ExternalFunction newItem(Status status, ExternalContext context, RoutineMetadata metadata); } -interface UdrProcedureFactory : Versioned +interface UdrProcedureFactory : Disposable { void setup(Status status, ExternalContext context, RoutineMetadata metadata, MetadataBuilder inBuilder, MetadataBuilder outBuilder); ExternalProcedure newItem(Status status, ExternalContext context, RoutineMetadata metadata); } -interface UdrTriggerFactory : Versioned +interface UdrTriggerFactory : Disposable { void setup(Status status, ExternalContext context, RoutineMetadata metadata, MetadataBuilder fieldsBuilder); ExternalTrigger newItem(Status status, ExternalContext context, RoutineMetadata metadata); } + +interface UdrPlugin : Versioned +{ + Master getMaster(); + + void registerFunction(Status status, const string name, UdrFunctionFactory factory); + void registerProcedure(Status status, const string name, UdrProcedureFactory factory); + void registerTrigger(Status status, const string name, UdrTriggerFactory factory); +} Modified: firebird/trunk/src/include/firebird/IdlFbInterfaces.h =================================================================== --- firebird/trunk/src/include/firebird/IdlFbInterfaces.h 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/src/include/firebird/IdlFbInterfaces.h 2015-01-25 20:27:46 UTC (rev 60551) @@ -3,6 +3,8 @@ #ifndef IDL_FB_INTERFACES_H #define IDL_FB_INTERFACES_H +#include <stdint.h> + #ifndef CLOOP_CARG #define CLOOP_CARG #endif @@ -106,6 +108,7 @@ class IUdrFunctionFactory; class IUdrProcedureFactory; class IUdrTriggerFactory; + class IUdrPlugin; // Interfaces declarations @@ -4401,10 +4404,10 @@ } }; - class IUdrFunctionFactory : public IVersioned + class IUdrFunctionFactory : public IDisposable { public: - struct VTable : public IVersioned::VTable + struct VTable : public IDisposable::VTable { void (CLOOP_CARG *setup)(IUdrFunctionFactory* self, IStatus* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) throw(); IExternalFunction* (CLOOP_CARG *newItem)(IUdrFunctionFactory* self, IStatus* status, IExternalContext* context, IRoutineMetadata* metadata) throw(); @@ -4412,7 +4415,7 @@ protected: IUdrFunctionFactory(DoNotInherit) - : IVersioned(DoNotInherit()) + : IDisposable(DoNotInherit()) { } @@ -4421,7 +4424,7 @@ } public: - static const unsigned VERSION = 2; + static const unsigned VERSION = 3; template <typename StatusType> void setup(StatusType* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) { @@ -4437,10 +4440,10 @@ } }; - class IUdrProcedureFactory : public IVersioned + class IUdrProcedureFactory : public IDisposable { public: - struct VTable : public IVersioned::VTable + struct VTable : public IDisposable::VTable { void (CLOOP_CARG *setup)(IUdrProcedureFactory* self, IStatus* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) throw(); IExternalProcedure* (CLOOP_CARG *newItem)(IUdrProcedureFactory* self, IStatus* status, IExternalContext* context, IRoutineMetadata* metadata) throw(); @@ -4448,7 +4451,7 @@ protected: IUdrProcedureFactory(DoNotInherit) - : IVersioned(DoNotInherit()) + : IDisposable(DoNotInherit()) { } @@ -4457,7 +4460,7 @@ } public: - static const unsigned VERSION = 2; + static const unsigned VERSION = 3; template <typename StatusType> void setup(StatusType* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder) { @@ -4473,10 +4476,10 @@ } }; - class IUdrTriggerFactory : public IVersioned + class IUdrTriggerFactory : public IDisposable { public: - struct VTable : public IVersioned::VTable + struct VTable : public IDisposable::VTable { void (CLOOP_CARG *setup)(IUdrTriggerFactory* self, IStatus* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* fieldsBuilder) throw(); IExternalTrigger* (CLOOP_CARG *newItem)(IUdrTriggerFactory* self, IStatus* status, IExternalContext* context, IRoutineMetadata* metadata) throw(); @@ -4484,7 +4487,7 @@ protected: IUdrTriggerFactory(DoNotInherit) - : IVersioned(DoNotInherit()) + : IDisposable(DoNotInherit()) { } @@ -4493,7 +4496,7 @@ } public: - static const unsigned VERSION = 2; + static const unsigned VERSION = 3; template <typename StatusType> void setup(StatusType* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* fieldsBuilder) { @@ -4509,6 +4512,55 @@ } }; + class IUdrPlugin : public IVersioned + { + public: + struct VTable : public IVersioned::VTable + { + IMaster* (CLOOP_CARG *getMaster)(IUdrPlugin* self) throw(); + void (CLOOP_CARG *registerFunction)(IUdrPlugin* self, IStatus* status, const char* name, IUdrFunctionFactory* factory) throw(); + void (CLOOP_CARG *registerProcedure)(IUdrPlugin* self, IStatus* status, const char* name, IUdrProcedureFactory* factory) throw(); + void (CLOOP_CARG *registerTrigger)(IUdrPlugin* self, IStatus* status, const char* name, IUdrTriggerFactory* factory) throw(); + }; + + protected: + IUdrPlugin(DoNotInherit) + : IVersioned(DoNotInherit()) + { + } + + ~IUdrPlugin() + { + } + + public: + static const unsigned VERSION = 2; + + IMaster* getMaster() + { + IMaster* ret = static_cast<VTable*>(this->cloopVTable)->getMaster(this); + return ret; + } + + template <typename StatusType> void registerFunction(StatusType* status, const char* name, IUdrFunctionFactory* factory) + { + static_cast<VTable*>(this->cloopVTable)->registerFunction(this, status, name, factory); + StatusType::checkException(status); + } + + template <typename StatusType> void registerProcedure(StatusType* status, const char* name, IUdrProcedureFactory* factory) + { + static_cast<VTable*>(this->cloopVTable)->registerProcedure(this, status, name, factory); + StatusType::checkException(status); + } + + template <typename StatusType> void registerTrigger(StatusType* status, const char* name, IUdrTriggerFactory* factory) + { + static_cast<VTable*>(this->cloopVTable)->registerTrigger(this, status, name, factory); + StatusType::checkException(status); + } + }; + // Interfaces implementations template <typename Name, typename StatusType, typename Base> @@ -14377,6 +14429,7 @@ VTableImpl() { this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; this->setup = &Name::cloopsetupDispatcher; this->newItem = &Name::cloopnewItemDispatcher; } @@ -14413,9 +14466,21 @@ return static_cast<IExternalFunction*>(0); } } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast<Name*>(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } }; - template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUdrFunctionFactory> > > + template <typename Name, typename StatusType, typename Base = IDisposableImpl<Name, StatusType, Inherit<IVersionedImpl<Name, StatusType, Inherit<IUdrFunctionFactory> > > > > class IUdrFunctionFactoryImpl : public IUdrFunctionFactoryBaseImpl<Name, StatusType, Base> { protected: @@ -14445,6 +14510,7 @@ VTableImpl() { this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; this->setup = &Name::cloopsetupDispatcher; this->newItem = &Name::cloopnewItemDispatcher; } @@ -14481,9 +14547,21 @@ return static_cast<IExternalProcedure*>(0); } } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast<Name*>(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } }; - template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUdrProcedureFactory> > > + template <typename Name, typename StatusType, typename Base = IDisposableImpl<Name, StatusType, Inherit<IVersionedImpl<Name, StatusType, Inherit<IUdrProcedureFactory> > > > > class IUdrProcedureFactoryImpl : public IUdrProcedureFactoryBaseImpl<Name, StatusType, Base> { protected: @@ -14513,6 +14591,7 @@ VTableImpl() { this->version = Base::VERSION; + this->dispose = &Name::cloopdisposeDispatcher; this->setup = &Name::cloopsetupDispatcher; this->newItem = &Name::cloopnewItemDispatcher; } @@ -14549,9 +14628,21 @@ return static_cast<IExternalTrigger*>(0); } } + + static void CLOOP_CARG cloopdisposeDispatcher(IDisposable* self) throw() + { + try + { + static_cast<Name*>(self)->Name::dispose(); + } + catch (...) + { + StatusType::catchException(0); + } + } }; - template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUdrTriggerFactory> > > + template <typename Name, typename StatusType, typename Base = IDisposableImpl<Name, StatusType, Inherit<IVersionedImpl<Name, StatusType, Inherit<IUdrTriggerFactory> > > > > class IUdrTriggerFactoryImpl : public IUdrTriggerFactoryBaseImpl<Name, StatusType, Base> { protected: @@ -14567,6 +14658,104 @@ virtual void setup(StatusType* status, IExternalContext* context, IRoutineMetadata* metadata, IMetadataBuilder* fieldsBuilder) = 0; virtual IExternalTrigger* newItem(StatusType* status, IExternalContext* context, IRoutineMetadata* metadata) = 0; }; + + template <typename Name, typename StatusType, typename Base> + class IUdrPluginBaseImpl : public Base + { + public: + typedef IUdrPlugin Declaration; + + IUdrPluginBaseImpl(DoNotInherit = DoNotInherit()) + { + static struct VTableImpl : Base::VTable + { + VTableImpl() + { + this->version = Base::VERSION; + this->getMaster = &Name::cloopgetMasterDispatcher; + this->registerFunction = &Name::cloopregisterFunctionDispatcher; + this->registerProcedure = &Name::cloopregisterProcedureDispatcher; + this->registerTrigger = &Name::cloopregisterTriggerDispatcher; + } + } vTable; + + this->cloopVTable = &vTable; + } + + static IMaster* CLOOP_CARG cloopgetMasterDispatcher(IUdrPlugin* self) throw() + { + try + { + return static_cast<Name*>(self)->Name::getMaster(); + } + catch (...) + { + StatusType::catchException(0); + return static_cast<IMaster*>(0); + } + } + + static void CLOOP_CARG cloopregisterFunctionDispatcher(IUdrPlugin* self, IStatus* status, const char* name, IUdrFunctionFactory* factory) throw() + { + StatusType status2(status); + + try + { + static_cast<Name*>(self)->Name::registerFunction(&status2, name, factory); + } + catch (...) + { + StatusType::catchException(&status2); + } + } + + static void CLOOP_CARG cloopregisterProcedureDispatcher(IUdrPlugin* self, IStatus* status, const char* name, IUdrProcedureFactory* factory) throw() + { + StatusType status2(status); + + try + { + static_cast<Name*>(self)->Name::registerProcedure(&status2, name, factory); + } + catch (...) + { + StatusType::catchException(&status2); + } + } + + static void CLOOP_CARG cloopregisterTriggerDispatcher(IUdrPlugin* self, IStatus* status, const char* name, IUdrTriggerFactory* factory) throw() + { + StatusType status2(status); + + try + { + static_cast<Name*>(self)->Name::registerTrigger(&status2, name, factory); + } + catch (...) + { + StatusType::catchException(&status2); + } + } + }; + + template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUdrPlugin> > > + class IUdrPluginImpl : public IUdrPluginBaseImpl<Name, StatusType, Base> + { + protected: + IUdrPluginImpl(DoNotInherit = DoNotInherit()) + { + } + + public: + virtual ~IUdrPluginImpl() + { + } + + virtual IMaster* getMaster() = 0; + virtual void registerFunction(StatusType* status, const char* name, IUdrFunctionFactory* factory) = 0; + virtual void registerProcedure(StatusType* status, const char* name, IUdrProcedureFactory* factory) = 0; + virtual void registerTrigger(StatusType* status, const char* name, IUdrTriggerFactory* factory) = 0; + }; }; Modified: firebird/trunk/src/include/firebird/Interface.h =================================================================== --- firebird/trunk/src/include/firebird/Interface.h 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/src/include/firebird/Interface.h 2015-01-25 20:27:46 UTC (rev 60551) @@ -239,5 +239,6 @@ } // namespace Firebird #define FB_PLUGIN_ENTRY_POINT firebird_plugin +#define FB_UDR_PLUGIN_ENTRY_POINT firebird_udr_plugin #endif // FB_INTERFACE_H Modified: firebird/trunk/src/include/firebird/UdrCppEngine.h =================================================================== --- firebird/trunk/src/include/firebird/UdrCppEngine.h 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/src/include/firebird/UdrCppEngine.h 2015-01-25 20:27:46 UTC (rev 60551) @@ -27,20 +27,51 @@ #error FB_UDR_STATUS_TYPE must be defined with the Status class before UdrCppEngine.h inclusion. #endif -#include "./UdrEngine.h" #include "./Message.h" -#ifndef JRD_IBASE_H -#include "ibase.h" -#include "iberror.h" -#endif #include <string.h> -namespace Firebird -{ - namespace Udr - { -//------------------------------------------------------------------------------ +#define FB_UDR_IMPLEMENT_ENTRY_POINT \ + namespace Firebird \ + { \ + namespace Udr \ + { \ + RegistrationNode<IUdrFunctionFactory>* regFunctions = NULL; \ + RegistrationNode<IUdrProcedureFactory>* regProcedures = NULL; \ + RegistrationNode<IUdrTriggerFactory>* regTriggers = NULL; \ + } \ + } \ + \ + extern "C" FB_BOOLEAN* FB_UDR_PLUGIN_ENTRY_POINT(IStatus* status, FB_BOOLEAN* theirUnloadFlag, \ + IUdrPlugin* udrPlugin) \ + { \ + ::Firebird::Udr::FactoryRegistration::finish(status, udrPlugin); \ + \ + class UnloadDetector \ + { \ + public: \ + UnloadDetector(FB_BOOLEAN* aTheirUnloadFlag, IUdrPlugin* aUdrPlugin) \ + : myUnloadFlag(FB_FALSE), \ + theirUnloadFlag(aTheirUnloadFlag), \ + udrPlugin(aUdrPlugin) \ + { \ + } \ + \ + ~UnloadDetector() \ + { \ + if (!myUnloadFlag) \ + *theirUnloadFlag = FB_TRUE; \ + } \ + \ + FB_BOOLEAN myUnloadFlag; \ + FB_BOOLEAN* theirUnloadFlag; \ + IUdrPlugin* udrPlugin; \ + }; \ + \ + static UnloadDetector unloadDetector(theirUnloadFlag, udrPlugin); \ + \ + return &unloadDetector.myUnloadFlag; \ + } #define FB_UDR_BEGIN_FUNCTION(name) \ @@ -176,6 +207,13 @@ } +namespace Firebird +{ + namespace Udr + { +//------------------------------------------------------------------------------ + + template <typename T, typename StatusType> class Procedure; @@ -311,15 +349,78 @@ }; +template <typename T> struct RegistrationNode +{ + const char* name; + T* factory; + RegistrationNode<T>* next; +}; + +extern RegistrationNode<IUdrFunctionFactory>* regFunctions; +extern RegistrationNode<IUdrProcedureFactory>* regProcedures; +extern RegistrationNode<IUdrTriggerFactory>* regTriggers; + +class FactoryRegistration +{ +public: + template <typename T> static void schedule(const char* name, T* factory, + RegistrationNode<T>** list) + { + RegistrationNode<T>* node = new RegistrationNode<T>(); + node->name = name; + node->factory = factory; + node->next = *list; + + *list = node; + } + + static void finish(IStatus* status, IUdrPlugin* plugin) + { + CheckStatusWrapper statusWrapper(status); + + if (!run(&statusWrapper, plugin, &IUdrPlugin::registerFunction, regFunctions)) + return; + + if (!run(&statusWrapper, plugin, &IUdrPlugin::registerProcedure, regProcedures)) + return; + + if (!run(&statusWrapper, plugin, &IUdrPlugin::registerTrigger, regTriggers)) + return; + } + +private: + template <typename T> + static bool run(CheckStatusWrapper* statusWrapper, IUdrPlugin* plugin, + void (IUdrPlugin::*routine)(CheckStatusWrapper* status, const char* name, T* factory), + RegistrationNode<T>* list) + { + for (RegistrationNode<T>* node = list; node; node = node->next) + { + (plugin->*routine)(statusWrapper, node->name, node->factory); + + if (statusWrapper->getStatus() & IStatus::FB_HAS_ERRORS) + return false; + } + + return true; + } +}; + + template <typename T, typename StatusType> class FunctionFactoryImpl : public IUdrFunctionFactoryImpl<FunctionFactoryImpl<T, StatusType>, StatusType> { public: explicit FunctionFactoryImpl(const char* name) { - fbUdrRegFunction(name, this); + FactoryRegistration::schedule<IUdrFunctionFactory>(name, this, ®Functions); } + void dispose() + { + // Do not delete this. The instances are statically allocated. + } + void setup(StatusType* status, IExternalContext* /*context*/, IRoutineMetadata* /*metadata*/, IMetadataBuilder* in, IMetadataBuilder* out) { @@ -341,9 +442,14 @@ public: explicit ProcedureFactoryImpl(const char* name) { - fbUdrRegProcedure(name, this); + FactoryRegistration::schedule<IUdrProcedureFactory>(name, this, ®Procedures); } + void dispose() + { + // Do not delete this. The instances are statically allocated. + } + void setup(StatusType* status, IExternalContext* /*context*/, IRoutineMetadata* /*metadata*/, IMetadataBuilder* in, IMetadataBuilder* out) { @@ -365,9 +471,14 @@ public: explicit TriggerFactoryImpl(const char* name) { - fbUdrRegTrigger(name, this); + FactoryRegistration::schedule<IUdrTriggerFactory>(name, this, ®Triggers); } + void dispose() + { + // Do not delete this. The instances are statically allocated. + } + void setup(StatusType* status, IExternalContext* /*context*/, IRoutineMetadata* /*metadata*/, IMetadataBuilder* fields) { Deleted: firebird/trunk/src/include/firebird/UdrEngine.h =================================================================== --- firebird/trunk/src/include/firebird/UdrEngine.h 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/src/include/firebird/UdrEngine.h 2015-01-25 20:27:46 UTC (rev 60551) @@ -1,52 +0,0 @@ -/* - * The contents of this file are subject to the Initial - * Developer's Public License Version 1.0 (the "License"); - * you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. - * - * Software distributed under the License is distributed AS IS, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. - * See the License for the specific language governing rights - * and limitations under the License. - * - * The Original Code was created by Adriano dos Santos Fernandes - * for the Firebird Open Source RDBMS project. - * - * Copyright (c) 2008 Adriano dos Santos Fernandes <adr...@uo...> - * and all contributors signed below. - * - * All Rights Reserved. - * Contributor(s): ______________________________________. - */ - -#ifndef FIREBIRD_UDR_H -#define FIREBIRD_UDR_H - -#include "./Interface.h" - -#ifndef FB_EXPORTED -#if defined(DARWIN) -#define FB_EXPORTED __attribute__((visibility("default"))) -#else -#define FB_EXPORTED -#endif // OS choice (DARWIN) -#endif // FB_EXPORTED - - -namespace Firebird -{ -//------------------------------------------------------------------------------ - - -//// TODO: review -// Routine registration functions. -extern "C" void FB_EXPORTED fbUdrRegFunction(const char* name, IUdrFunctionFactory* factory); -extern "C" void FB_EXPORTED fbUdrRegProcedure(const char* name, IUdrProcedureFactory* factory); -extern "C" void FB_EXPORTED fbUdrRegTrigger(const char* name, IUdrTriggerFactory* factory); - - -//------------------------------------------------------------------------------ -} // namespace Firebird - -#endif // FIREBIRD_UDR_H Modified: firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp =================================================================== --- firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp 2015-01-25 20:27:18 UTC (rev 60550) +++ firebird/trunk/src/plugins/udr_engine/UdrEngine.cpp 2015-01-25 20:27:46 UTC (rev 60551) @@ -22,7 +22,6 @@ #include "firebird.h" #include "../jrd/ibase.h" -#include "firebird/UdrEngine.h" #include "firebird/Interface.h" #include "../common/classes/alloc.h" #include "../common/classes/array.h" @@ -43,37 +42,9 @@ //------------------------------------------------------------------------------ -struct Node -{ - Node() - : name(*getDefaultMemoryPool()), - module(*getDefaultMemoryPool()) - { - } +class UdrPluginImpl; - string name; - PathName module; -}; -struct FunctionNode : public Node -{ - IUdrFunctionFactory* factory; - FunctionNode* next; -}; - -struct ProcedureNode : public Node -{ - IUdrProcedureFactory* factory; - ProcedureNode* next; -}; - -struct TriggerNode : public Node -{ - IUdrTriggerFactory* factory; - TriggerNode* next; -}; - - static GlobalPtr<ObjectsArray<PathName> > paths; class Engine : public StdPlugin<IExternalEngineImpl<Engine, ThrowStatusWrapper> > @@ -129,25 +100,21 @@ } public: - void loadModule(ThrowStatusWrapper* status, IRoutineMetadata* metadata, + UdrPluginImpl* loadModule(ThrowStatusWrapper* status, IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint); template <typename NodeType, typename ObjType, typename SharedObjType> ObjType* getChild( - ThrowStatusWrapper* status, GenericMap<Pair<NonPooled<IExternalContext*, ObjType*> > >& children, - SharedObjType* sharedObj, IExternalContext* context, NodeType* nodes, + ThrowStatusWrapper* status, + GenericMap<Pair<NonPooled<IExternalContext*, ObjType*> > >& children, + SharedObjType* sharedObj, IExternalContext* context, SortedArray<SharedObjType*>& sharedObjs, const PathName& moduleName); template <typename ObjType> void deleteChildren( GenericMap<Pair<NonPooled<IExternalContext*, ObjType*> > >& children); - template <typename T> T* findNode(ThrowStatusWrapper* status, T* nodes, - const PathName& moduleName, const string& entryPoint); + template <typename T> T* findNode(ThrowStatusWrapper* status, + const GenericMap<Pair<Left<string, T*> > >& nodes, const string& entryPoint); -private: - template <typename T, typename T2> T2* getNode(ThrowStatusWrapper* status, T* nodes, - const PathName& moduleName, IExternalContext* context, IRoutineMetadata* metadata, - const string& entryPoint); - public: void open(ThrowStatusWrapper* status, IExternalContext* context, char* name, unsigned nameSize); void openAttachment(ThrowStatusWrapper* status, IExternalContext* context); @@ -172,11 +139,11 @@ }; -class ModulesMap : public GenericMap<Pair<Left<PathName, ModuleLoader::Module*> > > +class ModulesMap : public GenericMap<Pair<Left<PathName, UdrPluginImpl*> > > { public: explicit ModulesMap(MemoryPool& p) - : GenericMap<Pair<Left<PathName, ModuleLoader::Module*> > >(p) + : GenericMap<Pair<Left<PathName, UdrPluginImpl*> > >(p) { } @@ -190,15 +157,125 @@ static GlobalPtr<Mutex> modulesMutex; static GlobalPtr<ModulesMap> modules; -static InitInstance<PathName> loadingModule; -static FunctionNode* registeredFunctions = NULL; -static ProcedureNode* registeredProcedures = NULL; -static TriggerNode* registeredTriggers = NULL; - //-------------------------------------- +class UdrPluginImpl : public VersionedIface<IUdrPluginImpl<UdrPluginImpl, ThrowStatusWrapper> > +{ +public: + UdrPluginImpl(const PathName& aModuleName, ModuleLoader::Module* aModule) + : moduleName(*getDefaultMemoryPool(), aModuleName), + module(aModule), + myUnloadFlag(FB_FALSE), + theirUnloadFlag(NULL), + functionsMap(*getDefaultMemoryPool()), + proceduresMap(*getDefaultMemoryPool()), + triggersMap(*getDefaultMemoryPool()) + { + } + + ~UdrPluginImpl() + { + if (myUnloadFlag) + return; + + *theirUnloadFlag = FB_TRUE; + + { + GenericMap<Pair<Left<string, IUdrFunctionFactory*> > >::Accessor accessor(&functionsMap); + for (bool cont = accessor.getFirst(); cont; cont = accessor.getNext()) + accessor.current()->second->dispose(); + } + + { + GenericMap<Pair<Left<string, IUdrProcedureFactory*> > >::Accessor accessor(&proceduresMap); + for (bool cont = accessor.getFirst(); cont; cont = accessor.getNext()) + accessor.current()->second->dispose(); + } + + { + GenericMap<Pair<Left<string, IUdrTriggerFactory*> > >::Accessor accessor(&triggersMap); + for (bool cont = accessor.getFirst(); cont; cont = accessor.getNext()) + accessor.current()->second->dispose(); + } + + delete module; + } + +public: + IMaster* getMaster() + { + return MasterInterfacePtr(); + } + + void registerFunction(ThrowStatusWrapper* status, const char* name, + IUdrFunctionFactory* factory) + { + if (functionsMap.exist(name)) + { + static const ISC_STATUS statusVector[] = { + isc_arg_gds, isc_random, + isc_arg_string, (ISC_STATUS) "Duplicate UDR function", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) name, + isc_arg_end + }; + + throw FbException(status, statusVector); + } + + functionsMap.put(name, factory); + } + + void registerProcedure(ThrowStatusWrapper* status, const char* name, + IUdrProcedureFactory* factory) + { + if (proceduresMap.exist(name)) + { + static const ISC_STATUS statusVector[] = { + isc_arg_gds, isc_random, + isc_arg_string, (ISC_STATUS) "Duplicate UDR procedure", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) name, + isc_arg_end + }; + + throw FbException(status, statusVector); + } + + proceduresMap.put(name, factory); + } + + void registerTrigger(ThrowStatusWrapper* status, const char* name, + IUdrTriggerFactory* factory) + { + if (triggersMap.exist(name)) + { + static const ISC_STATUS statusVector[] = { + isc_arg_gds, isc_random, + isc_arg_string, (ISC_STATUS) "Duplicate UDR trigger", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) name, + isc_arg_end + }; + + throw FbException(status, statusVector); + } + + triggersMap.put(name, factory); + } + +private: + PathName moduleName; + ModuleLoader::Module* module; + +public: + FB_BOOLEAN myUnloadFlag; + FB_BOOLEAN* theirUnloadFlag; + GenericMap<Pair<Left<string, IUdrFunctionFactory*> > > functionsMap; + GenericMap<Pair<Left<string, IUdrProcedureFactory*> > > proceduresMap; + GenericMap<Pair<Left<string, IUdrTriggerFactory*> > > triggersMap; +}; + + class SharedFunction : public DisposeIface<IExternalFunctionImpl<SharedFunction, ThrowStatusWrapper> > { public: @@ -212,10 +289,12 @@ info(*getDefaultMemoryPool()), children(*getDefaultMemoryPool()) { - engine->loadModule(status, metadata, &moduleName, &entryPoint); - FunctionNode* node = engine->findNode<FunctionNode>( - status, registeredFunctions, moduleName, entryPoint); - node->factory->setup(status, context, metadata, inBuilder, outBuilder); + module = engine->loadModule(status, metadata, &moduleName, &entryPoint); + + IUdrFunctionFactory* factory = engine->findNode<IUdrFunctionFactory>( + status, module->functionsMap, entryPoint); + + factory->setup(status, context, metadata, inBuilder, outBuilder); } ~SharedFunction() @@ -235,8 +314,8 @@ { strncpy(name, context->getClientCharSet(), nameSize); - IExternalFunction* function = engine->getChild<FunctionNode, IExternalFunction>(status, - children, this, context, registeredFunctions, engine->functions, moduleName); + IExternalFunction* function = engine->getChild<IUdrFunctionFactory, IExternalFunction>( + status, children, this, context, engine->functions, moduleName); if (function) function->getCharSet(status, context, name, nameSize); @@ -244,8 +323,9 @@ void execute(ThrowStatusWrapper* status, IExternalContext* context, void* inMsg, void* outMsg) { - IExternalFunction* function = engine->getChild<FunctionNode, IExternalFunction>(status, - children, this, context, registeredFunctions, engine->functions, moduleName); + IExternalFunction* function = engine->getChild<IUdrFunctionFactory, IExternalFunction>( + status, children, this, context, engine->functions, moduleName); + if (function) function->execute(status, context, inMsg, outMsg); } @@ -257,6 +337,7 @@ string entryPoint; string info; GenericMap<Pair<NonPooled<IExternalContext*, IExternalFunction*> > > children; + UdrPluginImpl* module; }; @@ -276,10 +357,12 @@ info(*getDefaultMemoryPool()), children(*getDefaultMemoryPool()) { - engine->loadModule(status, metadata, &moduleName, &entryPoint); - ProcedureNode* node = engine->findNode<ProcedureNode>( - status, registeredProcedures, moduleName, entryPoint); - node->factory->setup(status, context, metadata, inBuilder, outBuilder); + module = engine->loadModule(status, metadata, &moduleName, &entryPoint); + + IUdrProcedureFactory* factory = engine->findNode<IUdrProcedureFactory>( + status, module->proceduresMap, entryPoint); + + factory->setup(status, context, metadata, inBuilder, outBuilder); } ~SharedProcedure() @@ -299,8 +382,8 @@ { strncpy(name, context->getClientCharSet(), nameSize); - IExternalProcedure* procedure = engine->getChild<ProcedureNode, IExternalProcedure>(status, - children, this, context, registeredProcedures, engine->procedures, moduleName); + IExternalProcedure* procedure = engine->getChild<IUdrProcedureFactory, IExternalProcedure>( + status, children, this, context, engine->procedures, moduleName); if (procedure) procedure->getCharSet(status, context, name, nameSize); @@ -309,8 +392,8 @@ IExternalResultSet* open(ThrowStatusWrapper* status, IExternalContext* context, void* inMsg, void* outMsg) { - IExternalProcedure* procedure = engine->getChild<ProcedureNode, IExternalProcedure>(status, - children, this, context, registeredProcedures, engine->procedures, moduleName); + IExternalProcedure* procedure = engine->getChild<IUdrProcedureFactory, IExternalProcedure>( + status, children, this, context, engine->procedures, moduleName); return procedure ? procedure->open(status, context, inMsg, outMsg) : NULL; } @@ -322,6 +405,7 @@ string entryPoint; string info; GenericMap<Pair<NonPooled<IExternalContext*, IExternalProcedure*> > > children; + UdrPluginImpl* module; }; @@ -340,12 +424,12 @@ info(*getDefaultMemoryPool()), children(*getDefaultMemoryPool()) { - engine->loadModule(status, metadata, &moduleName, &entryPoint); + module = engine->loadModule(status, metadata, &moduleName, &entryPoint); - TriggerNode* node = engine->findNode<TriggerNode>(status, - registeredTriggers, moduleName, entryPoint); + IUdrTriggerFactory* factory = engine->findNode<IUdrTriggerFactory>( + status, module->triggersMap, entryPoint); - node->factory->setup(status, context, metadata, fieldsBuilder); + factory->setup(status, context, metadata, fieldsBuilder); } ~SharedTrigger() @@ -365,8 +449,8 @@ { strncpy(name, context->getClientCharSet(), nameSize); - IExternalTrigger* trigger = engine->getChild<TriggerNode, IExternalTrigger>(status, - children, this, context, registeredTriggers, engine->triggers, moduleName); + IExternalTrigger* trigger = engine->getChild<IUdrTriggerFactory, IExternalTrigger>( + status, children, this, context, engine->triggers, moduleName); if (trigger) trigger->getCharSet(status, context, name, nameSize); @@ -375,8 +459,9 @@ void execute(ThrowStatusWrapper* status, IExternalContext* context, unsigned action, void* oldMsg, void* newMsg) { - IExternalTrigger* trigger = engine->getChild<TriggerNode, IExternalTrigger>(status, - children, this, context, registeredTriggers, engine->triggers, moduleName); + IExternalTrigger* trigger = engine->getChild<IUdrTriggerFactory, IExternalTrigger>( + status, children, this, context, engine->triggers, moduleName); + if (trigger) trigger->execute(status, context, action, oldMsg, newMsg); } @@ -388,68 +473,43 @@ string entryPoint; string info; GenericMap<Pair<NonPooled<IExternalContext*, IExternalTrigger*> > > children; + UdrPluginImpl* module; }; //-------------------------------------- -extern "C" void FB_EXPORTED fbUdrRegFunction(const char* name, IUdrFunctionFactory* factory) +template <typename FactoryType> GenericMap<Pair<Left<string, FactoryType*> > >& getFactoryMap( + UdrPluginImpl* udrPlugin) { - FunctionNode* node = new FunctionNode(); - node->name = name; - node->module = loadingModule(); - node->factory = factory; - node->next = registeredFunctions; - registeredFunctions = node; + fb_assert(false); } +template <> GenericMap<Pair<Left<string, IUdrFunctionFactory*> > >& getFactoryMap( + UdrPluginImpl* udrPlugin) +{ + return udrPlugin->functionsMap; +} -extern "C" void FB_EXPORTED fbUdrRegProcedure(const char* name, IUdrProcedureFactory* factory) +template <> GenericMap<Pair<Left<string, IUdrProcedureFactory*> > >& getFactoryMap( + UdrPluginImpl* udrPlugin) { - ProcedureNode* node = new ProcedureNode(); - node->name = name; - node->module = loadingModule(); - node->factory = factory; - node->next = registeredProcedures; - registeredProcedures = node; + return udrPlugin->proceduresMap; } - -extern "C" void FB_EXPORTED fbUdrRegTrigger(const char* name, IUdrTriggerFactory* factory) +template <> GenericMap<Pair<Left<string, IUdrTriggerFactory*> > >& getFactoryMap( + UdrPluginImpl* udrPlugin) { - TriggerNode* node = new TriggerNode(); - node->name = name; - node->module = loadingModule(); - node->factory = factory; - node->next = registeredTriggers; - registeredTriggers = node; + return udrPlugin->triggersMap; } +//-------------------------------------- + + ModulesMap::~ModulesMap() { - while (registeredFunctions) - { - FunctionNode* del = registeredFunctions; - registeredFunctions = registeredFunctions->next; - delete del; - } - - while (registeredProcedures) - { - ProcedureNode* del = registeredProcedures; - registeredProcedures = registeredProcedures->next; - delete del; - } - - while (registeredTriggers) - { - TriggerNode* del = registeredTriggers; - registeredTriggers = registeredTriggers->next; - delete del; - } - Accessor accessor(this); for (bool cont = accessor.getFirst(); cont; cont = accessor.getNext()) delete accessor.current()->second; @@ -459,7 +519,7 @@ //-------------------------------------- -void Engine::loadModule(ThrowStatusWrapper* status, IRoutineMetadata* metadata, +UdrPluginImpl* Engine::loadModule(ThrowStatusWrapper* status, IRoutineMetadata* metadata, PathName* moduleName, string* entryPoint) { const string str(metadata->getEntryPoint(status)); @@ -468,9 +528,9 @@ if (pos == string::npos) { static const ISC_STATUS statusVector[] = { - isc_arg_gds, - isc_random, + isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) "Invalid entry point", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) entryPoint.c_str(), isc_arg_end }; @@ -482,9 +542,9 @@ if (moduleName->find_first_of("/\\") != string::npos) { static const ISC_STATUS statusVector[] = { - isc_arg_gds, - isc_random, + isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) "Invalid module name", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) moduleName->c_str(), isc_arg_end }; @@ -498,10 +558,10 @@ MutexLockGuard guard(modulesMutex, FB_FUNCTION); - if (modules->exist(*moduleName)) - return; + UdrPluginImpl* ret; - loadingModule() = *moduleName; + if (modules->get(*moduleName, ret)) + return ret; for (ObjectsArray<PathName>::iterator i = paths->begin(); i != paths->end(); ++i) { @@ -512,27 +572,59 @@ if (module) { - modules->put(*moduleName, module); - break; + FB_BOOLEAN* (*entryPoint)(IStatus*, FB_BOOLEAN*, IUdrPlugin*); + + if (!module->findSymbol(STRINGIZE(FB_UDR_PLUGIN_ENTRY_POINT), entryPoint)) + { + static const ISC_STATUS statusVector[] = { + isc_arg_gds, isc_random, + isc_arg_string, (ISC_STATUS) "UDR plugin entry point not found", + isc_arg_end + }; + + throw FbException(status, statusVector); + } + + UdrPluginImpl* udrPlugin = new UdrPluginImpl(*moduleName, module); + udrPlugin->theirUnloadFlag = entryPoint(status, &udrPlugin->myUnloadFlag, udrPlugin); + + if (status->getStatus() & IStatus::FB_HAS_ERRORS) + { + delete udrPlugin; + ThrowStatusWrapper::checkException(status); + } + + modules->put(*moduleName, udrPlugin); + + return udrPlugin; } else { static const ISC_STATUS statusVector[] = { - isc_arg_gds, - isc_random, + isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) "Module not found", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) moduleName->c_str(), isc_arg_end }; throw FbException(status, statusVector); } } + + static const ISC_STATUS statusVector[] = { + isc_arg_gds, isc_random, + isc_arg_string, (ISC_STATUS) "No UDR module path was configured", + isc_arg_end + }; + + throw FbException(status, statusVector); } template <typename NodeType, typename ObjType, typename SharedObjType> ObjType* Engine::getChild( - ThrowStatusWrapper* status, GenericMap<Pair<NonPooled<IExternalContext*, ObjType*> > >& children, - SharedObjType* sharedObj, IExternalContext* context, NodeType* nodes, + ThrowStatusWrapper* status, + GenericMap<Pair<NonPooled<IExternalContext*, ObjType*> > >& children, SharedObjType* sharedObj, + IExternalContext* context, SortedArray<SharedObjType*>& sharedObjs, const PathName& moduleName) { MutexLockGuard guard(childrenMutex, FB_FUNCTION); @@ -543,9 +635,12 @@ ObjType* obj; if (!children.get(context, obj)) { - obj = getNode<NodeType, ObjType>(status, nodes, moduleName, context, sharedObj->metadata, - sharedObj->entryPoint); + GenericMap<Pair<Left<string, NodeType*> > >& nodes = getFactoryMap<NodeType>( + sharedObj->module); + NodeType* factory = findNode<NodeType>(status, nodes, sharedObj->entryPoint); + obj = factory->newItem(status, context, sharedObj->metadata); + if (obj) children.put(context, obj); } @@ -567,19 +662,18 @@ } -template <typename T> T* Engine::findNode(ThrowStatusWrapper* status, T* nodes, - const PathName& moduleName, const string& entryPoint) +template <typename T> T* Engine::findNode(ThrowStatusWrapper* status, + const GenericMap<Pair<Left<string, T*> > >& nodes, const string& entryPoint) { - for (T* node = nodes; node; node = node->next) - { - if (node->module == moduleName && entryPoint == node->name) - return node; - } + T* factory; + if (nodes.get(entryPoint, factory)) + return factory; + static const ISC_STATUS statusVector[] = { - isc_arg_gds, - isc_random, + isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) "Entry point not found", + //// TODO: isc_arg_gds, isc_random, isc_arg_string, (ISC_STATUS) entryPoint.c_str(), isc_arg_end }; @@ -589,15 +683,6 @@ } -template <typename T, typename T2> T2* Engine::getNode(ThrowStatusWrapper* status, T* nodes, - const PathName& moduleName, IExternalContext* context, IRoutineMetadata* metadata, - const string& entryPoint) -{ - T* node = findNode<T>(status, nodes, moduleName, entryPoint); - return node->factory->newItem(status, context, metadata); -} - - void Engine::open(ThrowStatusWrapper* /*status*/, IExternalContext* /*context*/, char* name, unsigned nameSize) { strncpy(name, "UTF-8", nameSize); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |