diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults index b39d8e8ea7..5f19819914 100755 --- a/builds/posix/make.defaults +++ b/builds/posix/make.defaults @@ -292,7 +292,7 @@ FB_DAEMON = $(BIN)/firebird$(EXEC_EXT) # Per-library link rules LINK_UDF = $(LIB_LINK) $(LIB_LINK_OPTIONS) $(call LIB_LINK_SONAME,$(1).$(SHRLIB_EXT)) $(UNDEF_FLAGS)\ - $(call LIB_LINK_RPATH,lib) -lm + $(call LIB_LINK_RPATH,lib) $(SO_LINK_LIBS) LINK_UDF_LIBS = $(THR_LIBS) -L$(LIB) -lib_util LINK_IB_UTIL = $(LIB_LINK) $(LINK_IBUTIL_SYMBOLS) $(LIB_LINK_OPTIONS) $(UNDEF_FLAGS)\ diff --git a/configure.in b/configure.in index cefa1f55db..03f74ba98e 100644 --- a/configure.in +++ b/configure.in @@ -793,6 +793,8 @@ dnl AC_CHECK_FUNCS(AO_compare_and_swap_full) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[AO_T x; AO_compare_and_swap_full(&x, 0, 0); return 0;]])], AC_DEFINE(HAVE_AO_COMPARE_AND_SWAP_FULL, 1, [Define this if AO_compare_and_swap_full() is defined in atomic_ops.h])) +AC_SEARCH_LIBS(clock_gettime, rt) +AC_CHECK_FUNCS(clock_gettime) dnl Checks for pthread functions AC_CHECK_FUNCS(pthread_mutexattr_setprotocol) diff --git a/lang_helpers/gds_codes.ftn b/lang_helpers/gds_codes.ftn index 11597b5c7d..38e7fbcb4b 100644 --- a/lang_helpers/gds_codes.ftn +++ b/lang_helpers/gds_codes.ftn @@ -1460,6 +1460,8 @@ C -- PARAMETER (GDS__invalid_boolean_usage = 335545023) INTEGER*4 GDS__sysf_argscant_both_be_zero PARAMETER (GDS__sysf_argscant_both_be_zero = 335545024) + INTEGER*4 GDS__spb_no_id + PARAMETER (GDS__spb_no_id = 335545025) INTEGER*4 GDS__gfix_db_name PARAMETER (GDS__gfix_db_name = 335740929) INTEGER*4 GDS__gfix_invalid_sw diff --git a/lang_helpers/gds_codes.pas b/lang_helpers/gds_codes.pas index f9e2c66746..a38ba00093 100644 --- a/lang_helpers/gds_codes.pas +++ b/lang_helpers/gds_codes.pas @@ -737,6 +737,7 @@ const gds_cannot_copy_stmt = 335545022; gds_invalid_boolean_usage = 335545023; gds_sysf_argscant_both_be_zero = 335545024; + gds_spb_no_id = 335545025; gds_gfix_db_name = 335740929; gds_gfix_invalid_sw = 335740930; gds_gfix_incmp_sw = 335740932; diff --git a/src/auth/AuthDbg.cpp b/src/auth/AuthDbg.cpp index b2d7dd75be..814d3b7afc 100644 --- a/src/auth/AuthDbg.cpp +++ b/src/auth/AuthDbg.cpp @@ -33,6 +33,8 @@ //#define AUTH_VERBOSE +static Firebird::MakeUpgradeInfo<> upInfo; + // register plugin static Firebird::SimpleFactory clientFactory; static Firebird::SimpleFactory serverFactory; @@ -60,6 +62,7 @@ Result FB_CARG DebugServer::startAuthentication(Firebird::IStatus* status, bool { try { + Firebird::MasterInterfacePtr()->upgradeInterface(writerInterface, FB_AUTH_WRITER_VERSION, upInfo); str.erase(); Firebird::ClumpletReader rdr(isService ? Firebird::ClumpletReader::spbList : @@ -88,6 +91,7 @@ Result FB_CARG DebugServer::contAuthentication(Firebird::IStatus* status, IWrite #ifdef AUTH_VERBOSE fprintf(stderr, "DebugServerInstance::contAuthentication: %.*s\n", size, data); #endif + Firebird::MasterInterfacePtr()->upgradeInterface(writerInterface, FB_AUTH_WRITER_VERSION, upInfo); writerInterface->add(Firebird::string((const char*) data, size).c_str(), "DEBUG", ""); return AUTH_SUCCESS; } @@ -126,6 +130,7 @@ Result FB_CARG DebugClient::startAuthentication(Firebird::IStatus* status, bool { try { + Firebird::MasterInterfacePtr()->upgradeInterface(dpb, FB_AUTH_DPB_READER_VERSION, upInfo); str = "HAND"; if (dpb) { diff --git a/src/auth/SecurityDatabase/LegacyManagement.epp b/src/auth/SecurityDatabase/LegacyManagement.epp index d8370a6306..c42f09c6bd 100644 --- a/src/auth/SecurityDatabase/LegacyManagement.epp +++ b/src/auth/SecurityDatabase/LegacyManagement.epp @@ -42,6 +42,8 @@ #include "../common/classes/ClumpletWriter.h" #include "firebird/Plugin.h" +static Firebird::MakeUpgradeInfo<> upInfo; + // Here we use version-independent symbolic link (or copy) of actual database DATABASE database = STATIC FILENAME "security.fdb"; @@ -124,6 +126,8 @@ void FB_CARG SecurityDatabaseManagement::start(Firebird::IStatus* st, ILogonInfo { try { + Firebird::MasterInterfacePtr()->upgradeInterface(logonInfo, FB_AUTH_LOGON_INFO_VERSION, upInfo); + st->init(); if (secDbKey == INIT_KEY) @@ -310,6 +314,8 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us try { + Firebird::MasterInterfacePtr()->upgradeInterface(user, FB_AUTH_USER_VERSION, upInfo); + ISC_STATUS_ARRAY isc_status; fb_utils::init_status(isc_status); st->init(); @@ -668,12 +674,11 @@ int FB_CARG SecurityDatabaseManagement::execute(Firebird::IStatus* st, IUser* us // register plugin static Firebird::SimpleFactory factory; -static Firebird::UnloadDetector unloadDetector; extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master) { Firebird::PluginManagerInterfacePtr pi(master); pi->registerPluginFactory(Firebird::PluginType::AuthUserManagement, "Legacy_Auth", &factory); - pi->registerModule(&unloadDetector); + pi->registerModule(&Firebird::myModule); } diff --git a/src/auth/SecurityDatabase/LegacyServer.cpp b/src/auth/SecurityDatabase/LegacyServer.cpp index c60b8d4a0d..6be2f214c5 100644 --- a/src/auth/SecurityDatabase/LegacyServer.cpp +++ b/src/auth/SecurityDatabase/LegacyServer.cpp @@ -49,6 +49,8 @@ using namespace Firebird; namespace { +MakeUpgradeInfo<> upInfo; + // BLR to search database for user name record const UCHAR PWD_REQUEST[] = @@ -367,6 +369,7 @@ Result SecurityDatabase::verify(IWriter* authBlock, ClumpletReader& originalDpb) } } + MasterInterfacePtr()->upgradeInterface(authBlock, FB_AUTH_WRITER_VERSION, upInfo); authBlock->add(login.c_str(), "SecDB", secureDbName); return AUTH_SUCCESS; } @@ -517,7 +520,7 @@ Result SecurityDatabaseServer::startAuthentication(Firebird::IStatus* status, ClumpletReader rdr(isService ? ClumpletReader::spbList : ClumpletReader::dpbList, dpb, dpbSize); Result rc = instance->verify(writerInterface, rdr); - Firebird::TimerInterfacePtr()->start(instance, 10 * 1000 * 1000); + TimerInterfacePtr()->start(instance, 10 * 1000 * 1000); return rc; } catch (const Firebird::Exception& ex) diff --git a/src/auth/trusted/AuthSspi.cpp b/src/auth/trusted/AuthSspi.cpp index a76a746d25..77a83f0285 100644 --- a/src/auth/trusted/AuthSspi.cpp +++ b/src/auth/trusted/AuthSspi.cpp @@ -69,6 +69,8 @@ namespace *data = name; *dataSize = strlen(name); } + + MakeUpgradeInfo<> upInfo; } namespace Auth { @@ -380,6 +382,7 @@ Result WinSspiServer::contAuthentication(Firebird::IStatus* status, bool wheel = false; string login; sspi.getLogin(login, wheel); + MasterInterfacePtr()->upgradeInterface(writerInterface, FB_AUTH_WRITER_VERSION, upInfo); writerInterface->add(login.c_str(), "WIN_SSPI", ""); if (wheel) { @@ -417,6 +420,8 @@ Result WinSspiClient::startAuthentication(Firebird::IStatus* status, if (dpb) { + MasterInterfacePtr()->upgradeInterface(dpb, FB_AUTH_DPB_READER_VERSION, upInfo); + UCHAR tag = isService ? isc_spb_trusted_role : isc_dpb_trusted_role; while (dpb->find(tag)) { diff --git a/src/common/classes/GetPlugins.h b/src/common/classes/GetPlugins.h index 32d79359f3..54bc6ceb19 100644 --- a/src/common/classes/GetPlugins.h +++ b/src/common/classes/GetPlugins.h @@ -34,36 +34,27 @@ namespace Firebird { -// Default replacement for missing virtual functions -class DefaultMissingEntrypoint -{ -public: - virtual void FB_CARG noEntrypoint() - { - Arg::Gds(isc_wish_list).raise(); - } -}; - // Template to help with loop in the set of plugins -template +template class GetPlugins { public: - GetPlugins(unsigned int interfaceType, unsigned int desiredVersion, const char* namesList = NULL) - : masterInterface(), pluginInterface(masterInterface), missing(), + GetPlugins(unsigned int interfaceType, unsigned int desiredVersion, + UpgradeInfo* ui, const char* namesList = NULL) + : masterInterface(), pluginInterface(masterInterface), pluginSet(pluginInterface->getPlugins(interfaceType, namesList ? namesList : Config::getPlugins(interfaceType), - desiredVersion, &missing, NULL)), + desiredVersion, ui, NULL)), currentPlugin(NULL) { pluginSet->release(); getPlugin(); } - GetPlugins(unsigned int interfaceType, unsigned int desiredVersion, + GetPlugins(unsigned int interfaceType, unsigned int desiredVersion, UpgradeInfo* ui, Config* knownConfig, const char* namesList = NULL) - : masterInterface(), pluginInterface(masterInterface), missing(), + : masterInterface(), pluginInterface(masterInterface), pluginSet(pluginInterface->getPlugins(interfaceType, namesList ? namesList : Config::getPlugins(interfaceType), - desiredVersion, &missing, new FirebirdConf(knownConfig))), + desiredVersion, ui, new FirebirdConf(knownConfig))), currentPlugin(NULL) { pluginSet->release(); @@ -124,7 +115,6 @@ public: private: MasterInterfacePtr masterInterface; PluginManagerInterfacePtr pluginInterface; - M missing; RefPtr pluginSet; P* currentPlugin; diff --git a/src/common/classes/ImplementHelper.cpp b/src/common/classes/ImplementHelper.cpp new file mode 100644 index 0000000000..694c5e98a7 --- /dev/null +++ b/src/common/classes/ImplementHelper.cpp @@ -0,0 +1,34 @@ +/* + * PROGRAM: Firebird interface. + * MODULE: ImplementHelper.cpp + * DESCRIPTION: Tools to help create interfaces. + * + * 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 Alex Peshkov + * for the Firebird Open Source RDBMS project. + * + * Copyright (c) 2010 Alex Peshkov + * and all contributors signed below. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * + * + */ + +#include "../common/classes/ImplementHelper.h" + +namespace Firebird +{ + UnloadDetector myModule; +} diff --git a/src/common/classes/ImplementHelper.h b/src/common/classes/ImplementHelper.h index 21486b7a83..6c90f93b2a 100644 --- a/src/common/classes/ImplementHelper.h +++ b/src/common/classes/ImplementHelper.h @@ -71,6 +71,8 @@ public: return V; } + IPluginModule* getModule(); + private: VersionedIface(const VersionedIface&); VersionedIface& operator=(const VersionedIface&); @@ -249,7 +251,10 @@ public: if (flagOsUnload) { PluginManagerInterfacePtr pi; - pi->unregisterModule(this); + if (pi) + { + pi->unregisterModule(this); + } doClean(); } @@ -282,6 +287,44 @@ private: }; typedef GlobalPtr UnloadDetector; +extern UnloadDetector myModule; + +template IPluginModule* VersionedIface::getModule() +{ + return &myModule; +} + + +// Default replacement for missing virtual functions +class DefaultMissingEntrypoint +{ +public: + virtual void FB_CARG noEntrypoint() + { + Arg::Gds(isc_wish_list).raise(); + } +}; + +// Helps to create update information +template +class MakeUpgradeInfo +{ +public: + MakeUpgradeInfo() + { + ui.missingFunctionClass = &missing; + ui.clientModule = &myModule; + } + + operator UpgradeInfo*() + { + return &ui; + } + +private: + M missing; + struct UpgradeInfo ui; +}; class InternalMessageBuffer : public FbMessage diff --git a/src/common/security.cpp b/src/common/security.cpp index 481b9988f5..daaa6bd702 100644 --- a/src/common/security.cpp +++ b/src/common/security.cpp @@ -36,12 +36,14 @@ void raise() (Arg::Gds(isc_random) << "Missing user management plugin").raise(); } +MakeUpgradeInfo<> ui; + } // anonymous namespace namespace Auth { Get::Get(Config* firebirdConf) - : GetPlugins(PluginType::AuthUserManagement, FB_AUTH_MANAGE_VERSION, firebirdConf) + : GetPlugins(PluginType::AuthUserManagement, FB_AUTH_MANAGE_VERSION, ui, firebirdConf) { if (!hasData()) { diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 6eebdd330e..49db3d61e1 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -807,7 +807,7 @@ SINT64 query_performance_counter() return counter.QuadPart; #elif defined(HAVE_CLOCK_GETTIME) - // Use high-resultion clock + // Use high-resolution clock struct timespec tp; if (clock_gettime(CLOCK_REALTIME, &tp) != 0) return 0; diff --git a/src/gpre/boot/gpre_meta_boot.cpp b/src/gpre/boot/gpre_meta_boot.cpp index ef80e642a6..beedc77f4f 100644 --- a/src/gpre/boot/gpre_meta_boot.cpp +++ b/src/gpre/boot/gpre_meta_boot.cpp @@ -683,6 +683,11 @@ public: return FB_MASTER_VERSION; } + virtual IPluginModule* FB_CARG getModule() + { + return NULL; + } + virtual IStatus* FB_CARG getStatus() { fb_assert(false); @@ -697,12 +702,12 @@ public: virtual IPluginManager* FB_CARG getPluginManager() { - fb_assert(false); + //fb_assert(false); return NULL; } virtual int FB_CARG upgradeInterface(IVersioned* /*toUpgrade*/, int /*desiredVersion*/, - void* /*missingFunctionClass*/) + struct UpgradeInfo* /*upInfo*/) { fb_assert(false); return 0; diff --git a/src/include/firebird/ExternalEngine.h b/src/include/firebird/ExternalEngine.h index a6f5098480..b043d545e7 100644 --- a/src/include/firebird/ExternalEngine.h +++ b/src/include/firebird/ExternalEngine.h @@ -33,6 +33,7 @@ #include "./Plugin.h" #include "./Provider.h" +#include "firebird.h" //// FIXME: namespace Firebird { diff --git a/src/include/firebird/Interface.h b/src/include/firebird/Interface.h index 43330a7e85..f2fa9c4ede 100644 --- a/src/include/firebird/Interface.h +++ b/src/include/firebird/Interface.h @@ -39,14 +39,18 @@ namespace Firebird { +// Forward declaration - used to identify client and provider of upgraded interface +class IPluginModule; + // Versioned interface - base for all FB interfaces class IVersioned { public: virtual int FB_CARG getVersion() = 0; + virtual IPluginModule* getModule() = 0; }; // If this is changed, types of all interfaces must be changed -#define FB_VERSIONED_VERSION 1 +#define FB_VERSIONED_VERSION 2 // Reference counted interface - base for refCounted FB interfaces class IRefCounted : public IVersioned @@ -89,6 +93,12 @@ class IAttachment; class ITransaction; class IDtc; +struct UpgradeInfo +{ + void* missingFunctionClass; + IPluginModule* clientModule; +}; + // Master interface is used to access almost all other interfaces. class IMaster : public IVersioned { @@ -96,7 +106,8 @@ public: virtual IStatus* FB_CARG getStatus() = 0; virtual IProvider* FB_CARG getDispatcher() = 0; virtual IPluginManager* FB_CARG getPluginManager() = 0; - virtual int FB_CARG upgradeInterface(IVersioned* toUpgrade, int desiredVersion, void* missingFunctionClass) = 0; + virtual int FB_CARG upgradeInterface(IVersioned* toUpgrade, int desiredVersion, + struct UpgradeInfo* upgradeInfo) = 0; virtual const char* FB_CARG circularAlloc(const char* s, size_t len, intptr_t thr) = 0; virtual ITimerControl* FB_CARG getTimerControl() = 0; virtual IDtc* FB_CARG getDtc() = 0; diff --git a/src/include/firebird/Plugin.h b/src/include/firebird/Plugin.h index 2d5f8e28e6..e542a23a19 100644 --- a/src/include/firebird/Plugin.h +++ b/src/include/firebird/Plugin.h @@ -187,7 +187,7 @@ public: // If caller already has an interface for firebird.conf, it may be passed here // If parameter is missing, plugins will get access to default (non database specific) config virtual IPluginSet* FB_CARG getPlugins(unsigned int interfaceType, const char* namesList, - int desiredVersion, void* missingFunctionClass, + int desiredVersion, UpgradeInfo* ui, IFirebirdConf* firebirdConf) = 0; // Get generic config interface for given file virtual IConfig* FB_CARG getConfig(const char* filename) = 0; diff --git a/src/include/firebird/Provider.h b/src/include/firebird/Provider.h index 08b2d55e13..ce987a102c 100644 --- a/src/include/firebird/Provider.h +++ b/src/include/firebird/Provider.h @@ -29,7 +29,6 @@ #ifndef FB_PROVIDER_INTERFACE #define FB_PROVIDER_INTERFACE -#include "firebird.h" //// FIXME: #include "./Plugin.h" namespace Firebird { diff --git a/src/include/gen/codetext.h b/src/include/gen/codetext.h index 9e3991bc51..e63e6f6666 100644 --- a/src/include/gen/codetext.h +++ b/src/include/gen/codetext.h @@ -726,6 +726,7 @@ static const struct { {"cannot_copy_stmt", 335545022}, {"invalid_boolean_usage", 335545023}, {"sysf_argscant_both_be_zero", 335545024}, + {"spb_no_id", 335545025}, {"gfix_db_name", 335740929}, {"gfix_invalid_sw", 335740930}, {"gfix_incmp_sw", 335740932}, diff --git a/src/include/gen/iberror.h b/src/include/gen/iberror.h index cfa7952836..901b109d2b 100644 --- a/src/include/gen/iberror.h +++ b/src/include/gen/iberror.h @@ -760,6 +760,7 @@ const ISC_STATUS isc_bad_events_handle = 335545021L; const ISC_STATUS isc_cannot_copy_stmt = 335545022L; const ISC_STATUS isc_invalid_boolean_usage = 335545023L; const ISC_STATUS isc_sysf_argscant_both_be_zero = 335545024L; +const ISC_STATUS isc_spb_no_id = 335545025L; const ISC_STATUS isc_gfix_db_name = 335740929L; const ISC_STATUS isc_gfix_invalid_sw = 335740930L; const ISC_STATUS isc_gfix_incmp_sw = 335740932L; @@ -1179,7 +1180,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L; const ISC_STATUS isc_trace_switch_param_miss = 337182758L; const ISC_STATUS isc_trace_param_act_notcompat = 337182759L; const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L; -const ISC_STATUS isc_err_max = 1123; +const ISC_STATUS isc_err_max = 1124; #else /* c definitions */ @@ -1909,6 +1910,7 @@ const ISC_STATUS isc_err_max = 1123; #define isc_cannot_copy_stmt 335545022L #define isc_invalid_boolean_usage 335545023L #define isc_sysf_argscant_both_be_zero 335545024L +#define isc_spb_no_id 335545025L #define isc_gfix_db_name 335740929L #define isc_gfix_invalid_sw 335740930L #define isc_gfix_incmp_sw 335740932L @@ -2328,7 +2330,7 @@ const ISC_STATUS isc_err_max = 1123; #define isc_trace_switch_param_miss 337182758L #define isc_trace_param_act_notcompat 337182759L #define isc_trace_mandatory_switch_miss 337182760L -#define isc_err_max 1123 +#define isc_err_max 1124 #endif diff --git a/src/include/gen/msgs.h b/src/include/gen/msgs.h index 764e42f67d..be65bc1ce3 100644 --- a/src/include/gen/msgs.h +++ b/src/include/gen/msgs.h @@ -729,6 +729,7 @@ Data source : @4"}, /* eds_statement */ {335545022, "Cannot copy statement @1"}, /* cannot_copy_stmt */ {335545023, "Invalid usage of boolean expression"}, /* invalid_boolean_usage */ {335545024, "Arguments for @1 cannot both be zero"}, /* sysf_argscant_both_be_zero */ + {335545025, "missing service ID in spb"}, /* spb_no_id */ {335740929, "data base file name (@1) already given"}, /* gfix_db_name */ {335740930, "invalid switch @1"}, /* gfix_invalid_sw */ {335740932, "incompatible switch combination"}, /* gfix_incmp_sw */ diff --git a/src/include/gen/sql_code.h b/src/include/gen/sql_code.h index 546fce8fda..afc0b8ebef 100644 --- a/src/include/gen/sql_code.h +++ b/src/include/gen/sql_code.h @@ -725,6 +725,7 @@ static const struct { {335545022, -104}, /* 702 cannot_copy_stmt */ {335545023, -104}, /* 703 invalid_boolean_usage */ {335545024, -833}, /* 704 sysf_argscant_both_be_zero */ + {335545025, -901}, /* 705 spb_no_id */ {335740929, -901}, /* 1 gfix_db_name */ {335740930, -901}, /* 2 gfix_invalid_sw */ {335740932, -901}, /* 4 gfix_incmp_sw */ diff --git a/src/include/gen/sql_state.h b/src/include/gen/sql_state.h index dbaabbeb17..ebb3f10126 100644 --- a/src/include/gen/sql_state.h +++ b/src/include/gen/sql_state.h @@ -725,6 +725,7 @@ static const struct { {335545022, "XX000"}, // 702 cannot_copy_stmt {335545023, "22000"}, // 703 invalid_boolean_usage {335545024, "42000"}, // 704 sysf_argscant_both_be_zero + {335545025, "HY000"}, // 705 spb_no_id {335740929, "00000"}, // 1 gfix_db_name {335740930, "00000"}, // 2 gfix_invalid_sw {335740932, "00000"}, // 4 gfix_incmp_sw diff --git a/src/jrd/ExtEngineManager.cpp b/src/jrd/ExtEngineManager.cpp index 6bc984fe9e..d72bc6f1e4 100644 --- a/src/jrd/ExtEngineManager.cpp +++ b/src/jrd/ExtEngineManager.cpp @@ -58,6 +58,7 @@ using namespace Firebird; namespace Jrd { +MakeUpgradeInfo<> upInfo; template class ExtEngineManager::ContextManager { @@ -826,7 +827,7 @@ ExternalEngine* ExtEngineManager::getEngine(thread_db* tdbb, const MetaName& nam if (!engines.get(name, engine)) { GetPlugins engineControl(PluginType::ExternalEngine, - FB_EXTERNAL_ENGINE_VERSION, name.c_str()); + FB_EXTERNAL_ENGINE_VERSION, upInfo, name.c_str()); if (engineControl.hasData()) { diff --git a/src/jrd/UserManagement.cpp b/src/jrd/UserManagement.cpp index 805092278f..ce149c191e 100644 --- a/src/jrd/UserManagement.cpp +++ b/src/jrd/UserManagement.cpp @@ -36,6 +36,7 @@ using namespace Jrd; using namespace Firebird; +static MakeUpgradeInfo<> upInfo; const Format* UsersTableScan::getFormat(thread_db* tdbb, jrd_rel* relation) const { @@ -212,6 +213,7 @@ void UserManagement::execute(USHORT id) void UserManagement::Display::list(Auth::IUser* u) { + MasterInterfacePtr()->upgradeInterface(u, FB_AUTH_USER_VERSION, upInfo); userManagement->list(u); } diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 14c7f1605f..58558bc100 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -296,8 +296,6 @@ int JProvider::release() } -static UnloadDetector unloadDetector; - static void shutdownBeforeUnload() { LocalStatus status; @@ -310,7 +308,7 @@ public: // IPluginFactory implementation IPluginBase* FB_CARG createPlugin(IPluginConfig* factoryParameter) { - if (unloadDetector->unloadStarted()) + if (myModule->unloadStarted()) { return NULL; } @@ -325,9 +323,9 @@ static Static engineFactory; void registerEngine(IPluginManager* iPlugin) { - unloadDetector->setCleanup(shutdownBeforeUnload); + myModule->setCleanup(shutdownBeforeUnload); iPlugin->registerPluginFactory(PluginType::Provider, "Engine12", &engineFactory); - iPlugin->registerModule(&unloadDetector); + iPlugin->registerModule(&myModule); } } // namespace Jrd diff --git a/src/jrd/svc.cpp b/src/jrd/svc.cpp index 9d092642e7..e5d0ecb23f 100644 --- a/src/jrd/svc.cpp +++ b/src/jrd/svc.cpp @@ -1890,6 +1890,10 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data) ClumpletReader spb(ClumpletReader::SpbStart, spb_data, spb_length); // The name of the service is the first element of the buffer + if (spb.isEof()) + { + status_exception::raise(Arg::Gds(isc_service_att_err) << Arg::Gds(isc_spb_no_id)); + } const UCHAR svc_id = spb.getClumpTag(); const serv_entry* serv; for (serv = services; serv->serv_action; serv++) diff --git a/src/jrd/trace/TraceManager.cpp b/src/jrd/trace/TraceManager.cpp index a68424f0a0..67a3600515 100644 --- a/src/jrd/trace/TraceManager.cpp +++ b/src/jrd/trace/TraceManager.cpp @@ -64,6 +64,9 @@ namespace return 1; } }; + + MakeUpgradeInfo upgradePlugin; + MakeUpgradeInfo<> upgradeFactory; } namespace Jrd { @@ -156,7 +159,7 @@ void TraceManager::load_plugins() init_factories = true; factories = FB_NEW(*getDefaultMemoryPool()) TraceManager::Factories(*getDefaultMemoryPool()); - for (GetPlugins traceItr(PluginType::Trace, FB_TRACE_PLUGIN_VERSION); + for (GetPlugins traceItr(PluginType::Trace, FB_TRACE_FACTORY_VERSION, upgradeFactory); traceItr.hasData(); traceItr.next()) { FactoryInfo info; @@ -259,6 +262,8 @@ void TraceManager::update_session(const TraceSession& session) } } + MasterInterfacePtr master; + for (FactoryInfo* info = factories->begin(); info != factories->end(); ++info) { TraceInitInfoImpl attachInfo(session, attachment, filename); @@ -267,6 +272,8 @@ void TraceManager::update_session(const TraceSession& session) if (plugin) { + master->upgradeInterface(plugin, FB_TRACE_PLUGIN_VERSION, upgradePlugin); + plugin->addRef(); SessionInfo sesInfo; sesInfo.plugin = plugin; diff --git a/src/msgs/facilities2.sql b/src/msgs/facilities2.sql index 0bfee6f594..f18227b5ad 100644 --- a/src/msgs/facilities2.sql +++ b/src/msgs/facilities2.sql @@ -1,7 +1,7 @@ /* MAX_NUMBER is the next number to be used, always one more than the highest message number. */ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?); -- -('2011-02-02 12:45:00', 'JRD', 0, 705) +('2011-06-10 16:23:31', 'JRD', 0, 706) ('2010-03-15 06:59:09', 'QLI', 1, 531) -- --('2008-11-28 20:27:04', 'GDEF', 2, 346) diff --git a/src/msgs/messages2.sql b/src/msgs/messages2.sql index 340e1e76d9..25743531bb 100644 --- a/src/msgs/messages2.sql +++ b/src/msgs/messages2.sql @@ -812,6 +812,7 @@ Data source : @4', NULL, NULL) ('cannot_copy_stmt', NULL, NULL, NULL, 0, 702, NULL, 'Cannot copy statement @1', NULL, NULL); ('invalid_boolean_usage', NULL, NULL, NULL, 0, 703, NULL, 'Invalid usage of boolean expression', NULL, NULL); ('sysf_argscant_both_be_zero', 'evlAtan2', 'SysFunction.cpp', NULL, 0, 704, NULL, 'Arguments for @1 cannot both be zero', NULL, NULL) +('spb_no_id', 'Service::start', 'svc.c', NULL, 0, 705, NULL, 'missing service ID in spb', NULL, NULL); -- QLI (NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL); diff --git a/src/msgs/system_errors2.sql b/src/msgs/system_errors2.sql index c08712807e..dcdac7887f 100644 --- a/src/msgs/system_errors2.sql +++ b/src/msgs/system_errors2.sql @@ -710,6 +710,7 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA (-104, 'XX', '000', 0, 702, 'cannot_copy_stmt', NULL, NULL) (-104, '22', '000', 0, 703, 'invalid_boolean_usage', NULL, NULL) (-833, '42', '000', 0, 704, 'sysf_argscant_both_be_zero', NULL, NULL) +(-901, 'HY', '000', 0, 705, 'spb_no_id', NULL, NULL) -- GFIX (-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL) (-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL) diff --git a/src/plugins/udr_engine/UdrEngine.cpp b/src/plugins/udr_engine/UdrEngine.cpp index 66cd22ab2a..6d73361b3e 100644 --- a/src/plugins/udr_engine/UdrEngine.cpp +++ b/src/plugins/udr_engine/UdrEngine.cpp @@ -754,13 +754,12 @@ public: class ExternalEngineFactoryImpl : public SimpleFactory { } factory; -static Firebird::UnloadDetector unloadDetector; extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master) { PluginManagerInterfacePtr pi; pi->registerPluginFactory(PluginType::ExternalEngine, "UDR", &factory); - pi->registerModule(&unloadDetector); + pi->registerModule(&myModule); libraryName->assign("fbclient"); ModuleLoader::doctorModuleExtension(libraryName); diff --git a/src/remote/client/interface.cpp b/src/remote/client/interface.cpp index 52cc3fa90e..814ae25998 100644 --- a/src/remote/client/interface.cpp +++ b/src/remote/client/interface.cpp @@ -5779,6 +5779,7 @@ static void info(IStatus* status, response->p_resp_data = temp; } +static MakeUpgradeInfo<> upInfo; static void init(IStatus* status, rem_port* port, @@ -5808,7 +5809,7 @@ static void init(IStatus* status, // Let plugins try to add data to DPB in order to avoid extra network roundtrip Auth::DpbImplementation di(dpb); LocalStatus s; - GetPlugins authItr(PluginType::AuthClient, FB_AUTH_CLIENT_VERSION); + GetPlugins authItr(PluginType::AuthClient, FB_AUTH_CLIENT_VERSION, upInfo); bool working = true; diff --git a/src/remote/server/server.cpp b/src/remote/server/server.cpp index dfeef56428..5c871360f4 100644 --- a/src/remote/server/server.cpp +++ b/src/remote/server/server.cpp @@ -217,6 +217,8 @@ public: GlobalPtr usernameFailedLogins; GlobalPtr remoteFailedLogins; +MakeUpgradeInfo<> upInfo; + // delayed authentication block for auth callback class ServerAuth : public GlobalStorage, public ServerAuthBase { @@ -231,7 +233,7 @@ public: wrt(getPool(), op == op_service_attach ? ClumpletReader::spbList : ClumpletReader::dpbList, MAX_DPB_SIZE, pb, pbLen), authBlockInterface(op == op_service_attach), - authItr(PluginType::AuthServer, FB_AUTH_SERVER_VERSION, config), + authItr(PluginType::AuthServer, FB_AUTH_SERVER_VERSION, upInfo, config), remoteId(getPool()), userName(getPool()), authServer(NULL), part2(p2), operation(op) { diff --git a/src/utilities/ntrace/TracePluginImpl.cpp b/src/utilities/ntrace/TracePluginImpl.cpp index 43c03000b5..b1fca4ed41 100644 --- a/src/utilities/ntrace/TracePluginImpl.cpp +++ b/src/utilities/ntrace/TracePluginImpl.cpp @@ -38,12 +38,14 @@ #include "../../common/os/path_utils.h" #include "../../jrd/inf_pub.h" #include "../../dsql/sqlda_pub.h" +#include "../common/classes/ImplementHelper.h" using namespace Firebird; using namespace Jrd; static const char* const DEFAULT_LOG_NAME = "default_trace.log"; +static MakeUpgradeInfo<> upInfo; #ifdef WIN_NT #define NEWLINE "\r\n" @@ -89,6 +91,7 @@ TracePluginImpl::TracePluginImpl(const TracePluginConfig &configuration, TraceIn services(getDefaultMemoryPool()), unicodeCollation(*getDefaultMemoryPool()) { + MasterInterfacePtr()->upgradeInterface(logWriter, FB_TRACE_LOG_WRITER_VERSION, upInfo); const char* ses_name = initInfo->getTraceSessionName(); session_name = ses_name && *ses_name ? ses_name : " "; @@ -1937,6 +1940,8 @@ ntrace_boolean_t TracePluginImpl::trace_attach(TraceConnection* connection, { try { + MasterInterfacePtr()->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + log_event_attach(connection, create_db, att_result); return true; } @@ -1951,6 +1956,8 @@ ntrace_boolean_t TracePluginImpl::trace_detach(TraceConnection* connection, ntra { try { + MasterInterfacePtr()->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + log_event_detach(connection, drop_db); return true; } @@ -1967,6 +1974,10 @@ ntrace_boolean_t TracePluginImpl::trace_transaction_start(TraceConnection* conne { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + log_event_transaction_start(connection, transaction, tpb_length, tpb, tra_result); return true; } @@ -1982,6 +1993,10 @@ ntrace_boolean_t TracePluginImpl::trace_transaction_end(TraceConnection* connect { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + log_event_transaction_end(connection, transaction, commit, retain_context, tra_result); return true; } @@ -1998,6 +2013,11 @@ ntrace_boolean_t TracePluginImpl::trace_set_context(TraceConnection* connection, { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(variable, FB_TRACE_CONTEXT_VARIABLE_VERSION, upInfo); + log_event_set_context(connection, transaction, variable); return true; } @@ -2015,6 +2035,11 @@ ntrace_boolean_t TracePluginImpl::trace_proc_execute(TraceConnection* connection { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(procedure, FB_TRACE_PROCEDURE_VERSION, upInfo); + log_event_proc_execute(connection, transaction, procedure, started, proc_result); return true; } @@ -2031,6 +2056,11 @@ ntrace_boolean_t TracePluginImpl::trace_trigger_execute(TraceConnection* connect { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(trigger, FB_TRACE_TRIGGER_VERSION, upInfo); + log_event_trigger_execute(connection, transaction, trigger, started, trig_result); return true; } @@ -2048,6 +2078,11 @@ ntrace_boolean_t TracePluginImpl::trace_dsql_prepare(TraceConnection* connection { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(statement, FB_TRACE_SQL_STATEMENT_VERSION, upInfo); + log_event_dsql_prepare(connection, transaction, statement, time_millis, req_result); return true; } @@ -2063,6 +2098,10 @@ ntrace_boolean_t TracePluginImpl::trace_dsql_free(TraceConnection* connection, { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(statement, FB_TRACE_SQL_STATEMENT_VERSION, upInfo); + log_event_dsql_free(connection, statement, option); return true; } @@ -2079,6 +2118,11 @@ ntrace_boolean_t TracePluginImpl::trace_dsql_execute(TraceConnection* connection { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(statement, FB_TRACE_SQL_STATEMENT_VERSION, upInfo); + log_event_dsql_execute(connection, transaction, statement, started, req_result); return true; } @@ -2096,6 +2140,11 @@ ntrace_boolean_t TracePluginImpl::trace_blr_compile(TraceConnection* connection, { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(statement, FB_TRACE_BLR_STATEMENT_VERSION, upInfo); + log_event_blr_compile(connection, transaction, statement, time_millis, req_result); return true; } @@ -2111,6 +2160,11 @@ ntrace_boolean_t TracePluginImpl::trace_blr_execute(TraceConnection* connection, { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(statement, FB_TRACE_BLR_STATEMENT_VERSION, upInfo); + log_event_blr_execute(connection, transaction, statement, req_result); return true; } @@ -2127,6 +2181,11 @@ ntrace_boolean_t TracePluginImpl::trace_dyn_execute(TraceConnection* connection, { try { + MasterInterfacePtr master; + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + master->upgradeInterface(transaction, FB_TRACE_TRANSACTION_VERSION, upInfo); + master->upgradeInterface(request, FB_TRACE_DYN_REQUEST_VERSION, upInfo); + log_event_dyn_execute(connection, transaction, request, time_millis, req_result); return true; } @@ -2142,6 +2201,7 @@ ntrace_boolean_t TracePluginImpl::trace_service_attach(TraceService* service, nt { try { + MasterInterfacePtr()->upgradeInterface(service, FB_TRACE_SERVICE_VERSION, upInfo); log_event_service_attach(service, att_result); return true; } @@ -2157,6 +2217,7 @@ ntrace_boolean_t TracePluginImpl::trace_service_start(TraceService* service, siz { try { + MasterInterfacePtr()->upgradeInterface(service, FB_TRACE_SERVICE_VERSION, upInfo); log_event_service_start(service, switches_length, switches, start_result); return true; } @@ -2173,6 +2234,7 @@ ntrace_boolean_t TracePluginImpl::trace_service_query(TraceService* service, siz { try { + MasterInterfacePtr()->upgradeInterface(service, FB_TRACE_SERVICE_VERSION, upInfo); log_event_service_query(service, send_item_length, send_items, recv_item_length, recv_items, query_result); return true; @@ -2189,6 +2251,7 @@ ntrace_boolean_t TracePluginImpl::trace_service_detach(TraceService* service, nt { try { + MasterInterfacePtr()->upgradeInterface(service, FB_TRACE_SERVICE_VERSION, upInfo); log_event_service_detach(service, detach_result); return true; } diff --git a/src/utilities/ntrace/traceplugin.cpp b/src/utilities/ntrace/traceplugin.cpp index 86245a96f4..7fb6de51c3 100644 --- a/src/utilities/ntrace/traceplugin.cpp +++ b/src/utilities/ntrace/traceplugin.cpp @@ -26,6 +26,8 @@ * 2008 Khorsun Vladyslav */ +#include "../common/classes/ImplementHelper.h" + #include "TraceConfiguration.h" #include "TracePluginImpl.h" @@ -51,6 +53,8 @@ int FB_CARG TraceFactoryImpl::release() return 1; } +static Firebird::MakeUpgradeInfo<> upInfo; + ntrace_mask_t FB_CARG TraceFactoryImpl::trace_needs() { return (1 << TRACE_EVENT_MAX) - 1; @@ -58,9 +62,12 @@ ntrace_mask_t FB_CARG TraceFactoryImpl::trace_needs() TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, TraceInitInfo* initInfo) { + Firebird::MasterInterfacePtr master; const char* dbname = NULL; try { + master->upgradeInterface(initInfo, FB_TRACE_INIT_INFO_VERSION, upInfo); + dbname = initInfo->getDatabaseName(); if (!dbname) dbname = ""; @@ -69,6 +76,11 @@ TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, T TraceCfgReader::readTraceConfiguration(initInfo->getConfigText(), dbname, config); TraceConnection* connection = initInfo->getConnection(); + if (connection) + { + master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); + } + if (!config.enabled || (config.connection_id && connection && (connection->getConnectionID() != SLONG(config.connection_id)))) @@ -90,6 +102,7 @@ TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, T TraceLogWriter* logWriter = initInfo->getLogWriter(); if (logWriter) { + master->upgradeInterface(logWriter, FB_TRACE_LOG_WRITER_VERSION, upInfo); const char* strEx = TracePluginImpl::marshal_exception(ex); Firebird::string err; if (dbname) @@ -111,12 +124,11 @@ TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, T static Firebird::SimpleFactory traceFactory; -static Firebird::UnloadDetector unloadDetector; void registerTrace(Firebird::IPluginManager* iPlugin) { iPlugin->registerPluginFactory(Firebird::PluginType::Trace, "fbtrace", &traceFactory); - iPlugin->registerModule(&unloadDetector); + iPlugin->registerModule(&Firebird::myModule); } diff --git a/src/yvalve/MasterImplementation.cpp b/src/yvalve/MasterImplementation.cpp index 65687132f9..76e1abce86 100644 --- a/src/yvalve/MasterImplementation.cpp +++ b/src/yvalve/MasterImplementation.cpp @@ -30,6 +30,8 @@ #include "firebird/Interface.h" #include "firebird/Timer.h" +#include + #include "../yvalve/MasterImplementation.h" #include "../common/classes/init.h" #include "../common/StatusHolder.h" @@ -113,14 +115,50 @@ namespace FunctionPtr* vTab; }; - typedef Firebird::Pair > FunctionPair; + class UpgradeKey + { + public: + UpgradeKey(FunctionPtr* aFunc, IPluginModule* aModuleA, IPluginModule* aModuleB) + : func(aFunc), moduleA(aModuleA), moduleB(aModuleB) + { } + + UpgradeKey(const UpgradeKey& el) + : func(el.func), moduleA(el.moduleA), moduleB(el.moduleB) + { } + + UpgradeKey() + : func(NULL), moduleA(NULL), moduleB(NULL) + { } + + bool operator<(const UpgradeKey& el) const + { + return memcmp(this, &el, sizeof(UpgradeKey)) < 0; + } + + bool operator>(const UpgradeKey& el) const + { + return memcmp(this, &el, sizeof(UpgradeKey)) > 0; + } + + bool contains(IPluginModule* module) + { + return moduleA == module || moduleB == module; + } + + private: + FunctionPtr* func; + IPluginModule* moduleA; + IPluginModule* moduleB; + }; + + typedef Firebird::Pair > FunctionPair; GlobalPtr > functionMap; GlobalPtr mapLock; } int FB_CARG MasterImplementation::upgradeInterface(IVersioned* toUpgrade, int desiredVersion, - void* missingFunctionClass) + struct UpgradeInfo* upgradeInfo) { int existingVersion = toUpgrade->getVersion(); @@ -132,9 +170,11 @@ int FB_CARG MasterImplementation::upgradeInterface(IVersioned* toUpgrade, { CVirtualClass* target = (CVirtualClass*) toUpgrade; + UpgradeKey key(target->vTab, toUpgrade->getModule(), upgradeInfo->clientModule); + { // sync scope ReadLockGuard sync(mapLock); - if (functionMap->get((U_IPTR) target->vTab, newTab)) + if (functionMap->get(key, newTab)) { target->vTab = newTab; return 0; @@ -143,9 +183,9 @@ int FB_CARG MasterImplementation::upgradeInterface(IVersioned* toUpgrade, WriteLockGuard sync(mapLock); - if (!functionMap->get((U_IPTR) target->vTab, newTab)) + if (!functionMap->get(key, newTab)) { - CVirtualClass* miss = (CVirtualClass*) missingFunctionClass; + CVirtualClass* miss = (CVirtualClass*) (upgradeInfo->missingFunctionClass); newTab = FB_NEW(*getDefaultMemoryPool()) FunctionPtr[desiredVersion]; for (int i = 0; i < desiredVersion; ++i) @@ -153,7 +193,7 @@ int FB_CARG MasterImplementation::upgradeInterface(IVersioned* toUpgrade, newTab[i] = i < existingVersion ? target->vTab[i] : miss->vTab[0]; } - functionMap->put((U_IPTR) target->vTab, newTab); + functionMap->put(key, newTab); } target->vTab = newTab; @@ -173,6 +213,29 @@ int FB_CARG MasterImplementation::upgradeInterface(IVersioned* toUpgrade, return 0; } +void releaseUpgradeTabs(IPluginModule* module) +{ + HalfStaticArray removeList; + + WriteLockGuard sync(mapLock); + + GenericMap::Accessor scan(&functionMap); + if (scan.getFirst()) do + { + UpgradeKey& cur(scan.current()->first); + if (cur.contains(module)) + { + removeList.add(cur); + } + } + while (scan.getNext()); + + for(unsigned int i = 0; i < removeList.getCount(); ++i) + { + functionMap->remove(removeList[i]); + } +} + } // namespace Why // @@ -415,7 +478,7 @@ void TimerEntry::cleanup() TimerDelay curTime() { - return fb_utils::query_performance_counter() / fb_utils::query_performance_frequency(); + return fb_utils::query_performance_counter() / (fb_utils::query_performance_frequency() / 1000000); } TimerEntry* getTimer(ITimer* timer) diff --git a/src/yvalve/MasterImplementation.h b/src/yvalve/MasterImplementation.h index c544ec7202..732c602bfe 100644 --- a/src/yvalve/MasterImplementation.h +++ b/src/yvalve/MasterImplementation.h @@ -57,7 +57,8 @@ namespace Why Firebird::IStatus* FB_CARG getStatus(); Firebird::IProvider* FB_CARG getDispatcher(); Firebird::IPluginManager* FB_CARG getPluginManager(); - int FB_CARG upgradeInterface(Firebird::IVersioned* toUpgrade, int desiredVersion, void* missingFunctionClass); + int FB_CARG upgradeInterface(Firebird::IVersioned* toUpgrade, int desiredVersion, + Firebird::UpgradeInfo* upgradeInfo); const char* FB_CARG circularAlloc(const char* s, size_t len, intptr_t thr); Firebird::ITimerControl* FB_CARG getTimerControl(); Firebird::IAttachment* registerAttachment(Firebird::IProvider* provider, @@ -68,6 +69,7 @@ namespace Why }; void shutdownTimers(); + void releaseUpgradeTabs(Firebird::IPluginModule* module); } // namespace Why #endif // YVALVE_MASTER_IMPLEMENTATION_H diff --git a/src/yvalve/PluginManager.cpp b/src/yvalve/PluginManager.cpp index 7d3d762784..a810cd2be4 100644 --- a/src/yvalve/PluginManager.cpp +++ b/src/yvalve/PluginManager.cpp @@ -24,6 +24,7 @@ #include "consts_pub.h" #include "iberror.h" #include "../yvalve/PluginManager.h" +#include "../yvalve/MasterImplementation.h" #include "../dsql/sqlda_pub.h" #include "../yvalve/why_proto.h" @@ -344,6 +345,7 @@ namespace if (cleanup) { cleanup->doClean(); + Why::releaseUpgradeTabs(cleanup); } } @@ -442,6 +444,11 @@ namespace ~ConfiguredPlugin(); + const char* getPlugName() + { + return plugName.c_str(); + } + // ITimer implementation void FB_CARG handler() { } @@ -501,6 +508,9 @@ namespace private: ~FactoryParameter() { +#ifdef DEBUG_PLUGINS + fprintf(stderr, "~FactoryParameter places configuredPlugin %s in unload query\n", configuredPlugin->getPlugName()); +#endif TimerInterfacePtr()->start(configuredPlugin, 1000000); // 1 sec } @@ -645,10 +655,10 @@ namespace void FB_CARG next(); PluginSet(unsigned int pinterfaceType, const char* pnamesList, - int pdesiredVersion, void* pmissingFunctionClass, + int pdesiredVersion, UpgradeInfo* pui, IFirebirdConf* fbConf) : interfaceType(pinterfaceType), namesList(getPool()), - desiredVersion(pdesiredVersion), missingFunctionClass(pmissingFunctionClass), + desiredVersion(pdesiredVersion), ui(pui), currentName(getPool()), currentPlugin(NULL), firebirdConf(fbConf) { @@ -672,7 +682,7 @@ namespace unsigned int interfaceType; PathName namesList; int desiredVersion; - void* missingFunctionClass; + UpgradeInfo* ui; PathName currentName; RefPtr currentPlugin; // Missing data in this field indicates EOF @@ -807,7 +817,7 @@ namespace IPluginBase* p = currentPlugin->factory(firebirdConf); if (p) { - if (masterInterface->upgradeInterface(p, desiredVersion, missingFunctionClass) >= 0) + if (masterInterface->upgradeInterface(p, desiredVersion, ui) >= 0) { return p; } @@ -895,13 +905,13 @@ void FB_CARG PluginManager::unregisterModule(IPluginModule* cleanup) } IPluginSet* FB_CARG PluginManager::getPlugins(unsigned int interfaceType, const char* namesList, - int desiredVersion, void* missingFunctionClass, + int desiredVersion, UpgradeInfo* ui, IFirebirdConf* firebirdConf) { MutexLockGuard g(plugins->mutex); IPluginSet* rc = new PluginSet(interfaceType, namesList, desiredVersion, - missingFunctionClass, firebirdConf); + ui, firebirdConf); rc->addRef(); return rc; } diff --git a/src/yvalve/PluginManager.h b/src/yvalve/PluginManager.h index dc47a3640b..b17362301f 100644 --- a/src/yvalve/PluginManager.h +++ b/src/yvalve/PluginManager.h @@ -43,14 +43,14 @@ class PluginManager : public AutoIface class YHelper : public Firebird::StdPlugin, public YObject { public: - YHelper(Intf* aNext) : next(aNext) - { - this->addRef(); - } + YHelper(Intf* aNext); int FB_CARG release() { @@ -426,7 +423,7 @@ public: { if (--refCounter == 0) { - delete this; + //delete this; return 0; } diff --git a/src/yvalve/why.cpp b/src/yvalve/why.cpp index c170d4431e..28f3dd687b 100644 --- a/src/yvalve/why.cpp +++ b/src/yvalve/why.cpp @@ -557,10 +557,12 @@ namespace Why public: virtual void FB_CARG noEntrypoint(IStatus* s) { - s->set(Arg::Gds(isc_unavailable).value()); + s->set(Arg::Gds(isc_wish_list).value()); } }; + MakeUpgradeInfo upInfo; + template // T = YAttachment or YTransaction class CleanupCallbackImpl : public CleanupCallback { @@ -3269,6 +3271,13 @@ ITransaction* MasterImplementation::registerTransaction(IAttachment* attachment, return new YTransaction(static_cast(attachment), transaction); } +template +YHelper::YHelper(Intf* aNext) +{ + MasterInterfacePtr()->upgradeInterface(aNext, Vers, upInfo); + next = aNext; + this->addRef(); +} //------------------------------------- @@ -4640,8 +4649,8 @@ YAttachment* Dispatcher::attachDatabase(IStatus* status, const char* filename, RefPtr config; ResolveDatabaseAlias(expandedFilename, dummy, &config); - for (GetPlugins providerIterator(PluginType::Provider, - FB_PROVIDER_VERSION, config); + for (GetPlugins providerIterator(PluginType::Provider, + FB_PROVIDER_VERSION, upInfo, config); providerIterator.hasData(); providerIterator.next()) { @@ -4763,8 +4772,8 @@ YAttachment* Dispatcher::createDatabase(IStatus* status, const char* filename, ResolveDatabaseAlias(expandedFilename, dummy, &config); ***/ - for (GetPlugins providerIterator(PluginType::Provider, - FB_PROVIDER_VERSION/***, config***/); + for (GetPlugins providerIterator(PluginType::Provider, + FB_PROVIDER_VERSION, upInfo/***, config***/); providerIterator.hasData(); providerIterator.next()) { @@ -4827,8 +4836,8 @@ YService* Dispatcher::attachServiceManager(IStatus* status, const char* serviceN try { - for (GetPlugins providerIterator(PluginType::Provider, - FB_PROVIDER_VERSION); + for (GetPlugins providerIterator(PluginType::Provider, + FB_PROVIDER_VERSION, upInfo); providerIterator.hasData(); providerIterator.next()) { @@ -4916,8 +4925,8 @@ void Dispatcher::shutdown(IStatus* userStatus, unsigned int timeout, const int r shutdownStarted = true; // Shutdown providers (if any present). - for (GetPlugins providerIterator( - PluginType::Provider, FB_PROVIDER_VERSION); + for (GetPlugins providerIterator(PluginType::Provider, + FB_PROVIDER_VERSION, upInfo); providerIterator.hasData(); providerIterator.next()) {