From 00c63c1f8d05a738f8c73f04b710d8bcec77cfd7 Mon Sep 17 00:00:00 2001 From: alexpeshkoff Date: Thu, 28 Feb 2008 18:42:30 +0000 Subject: [PATCH] 1. Make signals handling in yValve MT safe. 2. Introduce new private API calls, fb__shutdown() and fb__shutdown_callback(). 3. Introduce fb_smp_server - binary to run superclassic on posix. 4. Various cleanups. --- .../linux/classic/postinstall.sh.in | 12 +- builds/install/misc/classicLibrary.sh.in | 18 +- builds/install/misc/posixLibrary.sh.in | 3 + builds/posix/Makefile.in.firebird | 7 +- builds/posix/firebird.vers | 5 + builds/posix/make.defaults | 1 + configure.in | 1 + src/common/utils.cpp | 16 + src/common/utils_proto.h | 2 + src/dsql/Parser.h | 5 +- src/dsql/dsql.h | 6 +- src/dsql/make_proto.h | 17 +- src/dsql/node.h | 11 - src/isql/isql.epp | 35 +- src/jrd/ThreadData.cpp | 35 -- src/jrd/ThreadData.h | 3 - src/jrd/entry.h | 12 +- src/jrd/isc_file.cpp | 18 +- src/jrd/jrd.cpp | 181 ++---- src/jrd/jrd_proto.h | 29 +- src/jrd/jrd_pwd.h | 2 +- src/jrd/os/posix/isc_ipc.cpp | 2 +- src/jrd/os/posix/unix.cpp | 22 +- src/jrd/os/win32/ibinitdll.cpp | 4 +- src/jrd/pwd.cpp | 2 +- src/jrd/relations.h | 8 +- src/jrd/tra.h | 4 +- src/jrd/why.cpp | 551 ++++++++---------- src/jrd/why_proto.h | 7 +- src/jrd/y_handle.h | 8 +- src/qli/dtr.cpp | 26 +- src/qli/exe.cpp | 14 +- src/remote/inet.cpp | 25 +- src/remote/inet_proto.h | 9 +- src/remote/inet_server.cpp | 179 ++---- src/remote/interface.cpp | 45 +- src/remote/os/win32/cntl.cpp | 2 +- src/remote/os/win32/srvr_w32.cpp | 2 +- src/remote/remot_proto.h | 6 +- src/remote/remote.cpp | 118 +--- src/remote/server.cpp | 11 +- 41 files changed, 527 insertions(+), 937 deletions(-) diff --git a/builds/install/arch-specific/linux/classic/postinstall.sh.in b/builds/install/arch-specific/linux/classic/postinstall.sh.in index 5bd4633aa0..a2754fd720 100644 --- a/builds/install/arch-specific/linux/classic/postinstall.sh.in +++ b/builds/install/arch-specific/linux/classic/postinstall.sh.in @@ -70,23 +70,19 @@ fi - # Create log - touch firebird.log - - - # Update ownership and SUID bits for programs. - chown -R $RunUser:$RunUser $FBRootDir - + # Update ownership and SUID bits for files. fixFilePermissions + # Create libgds.so links createLinksForBackCompatibility + # Prepare for uninstall buildUninstallFile + # Update the /etc/inetd.conf or xinetd entry updateInetdServiceEntry - # Get inetd to reread new init files. resetInetdServer diff --git a/builds/install/misc/classicLibrary.sh.in b/builds/install/misc/classicLibrary.sh.in index 98484a90e6..7f5b842b66 100644 --- a/builds/install/misc/classicLibrary.sh.in +++ b/builds/install/misc/classicLibrary.sh.in @@ -13,6 +13,7 @@ DefaultLibrary=libfbembed fixFilePermissions() { + cd $FBRootDir chown -R $RunUser:$RunGroup $FBRootDir # Turn other access off. @@ -42,18 +43,6 @@ fixFilePermissions() { chmod a=rx isql chmod a=rx qli - # Root SUID is still needed for group direct access. - # General users cannot run though. - for i in fb_lock_mgr - do - if [ -f $i ] - then - chown root $i - chmod ug=rx,o= $i - chmod ug+s $i - fi - done - # set up libraries cd $FBRootDir cd lib @@ -70,11 +59,14 @@ fixFilePermissions() { do FileName=$i.`hostname` touch $FileName + chown $RunUser:$RunGroup $FileName chmod ug=rw,o= $FileName done + # Create log + touch firebird.log + # Fix the rest - touch firebird.log chmod ug=rw,o= firebird.log chmod a=r aliases.conf chmod a=r firebird.conf diff --git a/builds/install/misc/posixLibrary.sh.in b/builds/install/misc/posixLibrary.sh.in index d913d39cf3..f31d851fa0 100644 --- a/builds/install/misc/posixLibrary.sh.in +++ b/builds/install/misc/posixLibrary.sh.in @@ -404,6 +404,8 @@ buildUninstallFile() { cp -r scripts $FBRootDir/misc/ cp scripts/tarMainUninstall.sh $FBRootDir/bin/uninstall.sh + + cd $FBRootDir } @@ -447,6 +449,7 @@ createLinksForBackCompatibility() { # to ensure it loads the fb equivalent. Eventually these should be # optional and in a seperate rpm install. MOD 7-Nov-2002. + cd $FBRootDir if [ "$1" ] then # Use library name from parameter diff --git a/builds/posix/Makefile.in.firebird b/builds/posix/Makefile.in.firebird index 84092af09f..1ecfe5299f 100644 --- a/builds/posix/Makefile.in.firebird +++ b/builds/posix/Makefile.in.firebird @@ -327,10 +327,10 @@ otherfiles: misc_files #_ Embedded Firebird Targets (Classic)_______________________________________ -.PHONY: libfbembed inet_server embed_gfix embed_gbak embed_isql +.PHONY: libfbembed inet_server fb_smp_server embed_gfix embed_gbak embed_isql .PHONY: embed_gpre embed_util -classic_targets: $(PLAT_CLASSIC_PRE_TARGET) libfbembed inet_server embed_gfix embed_gbak embed_isql \ +classic_targets: $(PLAT_CLASSIC_PRE_TARGET) libfbembed inet_server fb_smp_server embed_gfix embed_gbak embed_isql \ embed_gpre embed_util embed_gdef embed_qli embed_fbudf libfbclient $(PLAT_CLASSIC_POST_TARGET) libfbembed: @@ -339,6 +339,9 @@ libfbembed: inet_server: $(MAKE) -f $(GEN_ROOT)/Makefile.inet_server +fb_smp_server: + $(MAKE) -f $(GEN_ROOT)/Makefile.smp_server + embed_gfix: $(MAKE) -f $(GEN_ROOT)/Makefile.embed.gfix diff --git a/builds/posix/firebird.vers b/builds/posix/firebird.vers index 501466025b..8be1e0a774 100644 --- a/builds/posix/firebird.vers +++ b/builds/posix/firebird.vers @@ -36,6 +36,7 @@ global: gds__blob_size; gds__cancel_blob; gds__cancel_events; + gds__cancel_operation; gds__close; gds__close_blob; gds__commit_retaining; @@ -71,6 +72,7 @@ global: gds__get_prefix; gds__get_segment; gds__get_slice; + gds__handle_cleanup; gds__interprete; gds__log; gds__log_status; @@ -133,6 +135,9 @@ global: gds_alloc_flag_unfreed; gds_alloc_report; + fb__shutdown; + fb__shutdown_callback; + perf_format; perf_get_info; perf_report; diff --git a/builds/posix/make.defaults b/builds/posix/make.defaults index 25a07d4e13..8fa6889cf4 100755 --- a/builds/posix/make.defaults +++ b/builds/posix/make.defaults @@ -273,6 +273,7 @@ FBEMBED_LINK= -L$(LIB) -lfbembed FB_SUPER_SERVER = $(BIN)/fbserver$(EXEC_EXT) FB_CLASSIC_SERVER = $(BIN)/fb_inet_server$(EXEC_EXT) +FB_DAEMON = $(BIN)/fb_smp_server$(EXEC_EXT) STATIC_CXXSUPPORT_LIB = -lsupc++ diff --git a/configure.in b/configure.in index 31a15c0a8c..4fb41934a5 100644 --- a/configure.in +++ b/configure.in @@ -1152,6 +1152,7 @@ gen/Makefile.static.gbak:${MAKE_SRC_DIR}/Makefile.in.static.gbak gen/Makefile.static.isql:${MAKE_SRC_DIR}/Makefile.in.static.isql gen/Makefile.refDatabases:${MAKE_SRC_DIR}/Makefile.in.refDatabases gen/Makefile.fbserver:${MAKE_SRC_DIR}/Makefile.in.fbserver +gen/Makefile.smp_server:${MAKE_SRC_DIR}/Makefile.in.smp_server gen/Makefile.libfbclient:${MAKE_SRC_DIR}/Makefile.in.libfbclient gen/Makefile.client.fbudf:${MAKE_SRC_DIR}/Makefile.in.client.fbudf gen/Makefile.client.gbak:${MAKE_SRC_DIR}/Makefile.in.client.gbak diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 887b1be204..6042f67901 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -43,6 +43,9 @@ #include "../common/classes/init.h" #include "../jrd/constants.h" +#ifdef WIN_NT +#include +#endif #ifdef HAVE_UNISTD_H #include #endif @@ -662,4 +665,17 @@ SLONG genReadOnlyId() return ++cnt; } +void getCwd(Firebird::PathName& pn) +{ + char *buffer = pn.getBuffer(MAXPATHLEN); +#if defined(WIN_NT) + _getcwd(buffer, MAXPATHLEN); +#elif defined(HAVE_GETCWD) + getcwd(buffer, MAXPATHLEN); +#else + getwd(buffer); +#endif + pn.recalculate_length(); +} + } // namespace fb_utils diff --git a/src/common/utils_proto.h b/src/common/utils_proto.h index 1b802fe381..1015dd1949 100644 --- a/src/common/utils_proto.h +++ b/src/common/utils_proto.h @@ -95,6 +95,8 @@ namespace fb_utils Firebird::PathName get_process_name(); SLONG genReadOnlyId(); + + void getCwd(Firebird::PathName& pn); } // namespace fb_utils #endif // INCLUDE_UTILS_PROTO_H diff --git a/src/dsql/Parser.h b/src/dsql/Parser.h index ba8d96d144..8419fcb720 100644 --- a/src/dsql/Parser.h +++ b/src/dsql/Parser.h @@ -25,10 +25,7 @@ #include "../jrd/common.h" #include "../dsql/dsql.h" - -namespace Dsql { - enum nod_t; -} +#include "../dsql/node.h" namespace Jrd { diff --git a/src/dsql/dsql.h b/src/dsql/dsql.h index 7ba2bc226a..d47b23d023 100644 --- a/src/dsql/dsql.h +++ b/src/dsql/dsql.h @@ -301,8 +301,8 @@ public: SSHORT udf_character_set_id; USHORT udf_character_length; USHORT udf_flags; - Firebird::Array udf_arguments; Firebird::MetaName udf_name; + Firebird::Array udf_arguments; }; // udf_flags bits @@ -433,8 +433,8 @@ public: DsqlContextStack req_dt_context; //!< Save contexts for views of derived tables dsql_sym* req_name; //!< Name of request dsql_sym* req_cursor; //!< Cursor symbol, if any - dsql_dbb* req_dbb; //!< DSQL attachment - jrd_tra* req_transaction; //!< JRD transaction + dsql_dbb* req_dbb; //!< DSQL attachment + jrd_tra* req_transaction; //!< JRD transaction dsql_nod* req_ddl_node; //!< Store metadata request dsql_nod* req_blk_node; //!< exec_block node class dsql_blb* req_blob; //!< Blob info for blob requests diff --git a/src/dsql/make_proto.h b/src/dsql/make_proto.h index e92b13d874..80068ac1d9 100644 --- a/src/dsql/make_proto.h +++ b/src/dsql/make_proto.h @@ -27,18 +27,25 @@ #define DSQL_MAKE_PROTO_H #include "../dsql/sym.h" +#include "../dsql/node.h" namespace Jrd { class dsql_nod; class dsql_fld; class dsql_req; - enum dsql_constant_type; - enum sym_type; + +// Parameters to MAKE_constant + enum dsql_constant_type { + CONSTANT_STRING = 0, // stored as a string +// CONSTANT_SLONG = 1, // stored as a SLONG + CONSTANT_DOUBLE = 2, // stored as a string + CONSTANT_DATE = 3, // stored as a SLONG + CONSTANT_TIME = 4, // stored as a ULONG + CONSTANT_TIMESTAMP = 5, // stored as a QUAD + CONSTANT_SINT64 = 6 // stored as a SINT64 + }; }; -namespace Dsql { - enum nod_t; -} Jrd::dsql_nod* MAKE_const_slong(SLONG); Jrd::dsql_nod* MAKE_constant(Jrd::dsql_str*, Jrd::dsql_constant_type); diff --git a/src/dsql/node.h b/src/dsql/node.h index 5b03102083..34214ec982 100644 --- a/src/dsql/node.h +++ b/src/dsql/node.h @@ -1064,17 +1064,6 @@ enum nod_flags_vals { NOD_SPECIAL_SYNTAX = 1 // nod_sys_function }; -// Parameters to MAKE_constant -enum dsql_constant_type { - CONSTANT_STRING = 0, // stored as a string -// CONSTANT_SLONG = 1, // stored as a SLONG - CONSTANT_DOUBLE = 2, // stored as a string - CONSTANT_DATE = 3, // stored as a SLONG - CONSTANT_TIME = 4, // stored as a ULONG - CONSTANT_TIMESTAMP = 5, // stored as a QUAD - CONSTANT_SINT64 = 6 // stored as a SINT64 -}; - }; // namespace #endif // DSQL_NODE_H diff --git a/src/isql/isql.epp b/src/isql/isql.epp index 39a169c12b..6945f4769c 100644 --- a/src/isql/isql.epp +++ b/src/isql/isql.epp @@ -112,6 +112,7 @@ enum literal_string_type #include "../isql/show_proto.h" #include "../jrd/perf_proto.h" #include "../jrd/utl_proto.h" +#include "../jrd/why_proto.h" #include "../jrd/gdsassert.h" #ifdef SCROLLABLE_CURSORS @@ -353,7 +354,7 @@ static int process_statement(const TEXT*, XSQLDA**); #ifdef WIN_NT static BOOL CALLBACK query_abort(DWORD); #else -static void CLIB_ROUTINE query_abort(int); +static int API_ROUTINE query_abort(); #endif static bool stdin_redirected(); static void strip_quotes(const TEXT*, TEXT*); @@ -4037,14 +4038,7 @@ static void do_isql() #ifdef WIN_NT SetConsoleCtrlHandler(query_abort, TRUE); #elif defined(HAVE_SIGACTION) - struct sigaction sig_action; - if (sigaction(SIGINT, NULL, &sig_action) == 0) { - sig_action.sa_handler = query_abort; - sig_action.sa_flags |= SA_RESTART; - sigaction(SIGINT, &sig_action, NULL); - } -#else - signal(SIGINT, query_abort); + fb__shutdown_callback(0, query_abort, FB_SHUT_PREPROVIDERS); #endif // Open database and start tansaction @@ -8545,7 +8539,7 @@ static int process_statement(const TEXT* string, #ifdef WIN_NT static BOOL CALLBACK query_abort(DWORD dwCtrlType) #else -static void CLIB_ROUTINE query_abort(int) +static int API_ROUTINE query_abort() #endif { /************************************** @@ -8559,18 +8553,31 @@ static void CLIB_ROUTINE query_abort(int) * **************************************/ + bool flag = true; + #ifdef WIN_NT if (dwCtrlType != CTRL_C_EVENT) return FALSE; +#else + if (DB) + { + ISC_STATUS_ARRAY status; + flag = (gds__cancel_operation(status, &DB, CANCEL_raise) == FB_SUCCESS); + } #endif - if (Interactive) - Interrupt_flag = true; - else - Abort_flag = true; + if (flag) + { + if (Interactive) + Interrupt_flag = true; + else + Abort_flag = true; + } #ifdef WIN_NT return TRUE; +#else + return 1; // we do not want to proceed with shutdown #endif } diff --git a/src/jrd/ThreadData.cpp b/src/jrd/ThreadData.cpp index a7078afa08..0eaedc391d 100644 --- a/src/jrd/ThreadData.cpp +++ b/src/jrd/ThreadData.cpp @@ -59,7 +59,6 @@ namespace { -TLS_DECLARE (void*, tSpecific); TLS_DECLARE (ThreadData*, tData); } @@ -82,23 +81,6 @@ ThreadData* ThreadData::getSpecific(void) } -void ThreadData::getSpecificData(void **t_data) -{ -/************************************** - * - * T H D _ g e t s p e c i f i c _ d a t a - * - ************************************** - * - * Functional description - * return the previously stored t_data. - * - **************************************/ - - *t_data = TLS_GET(tSpecific); -} - - void ThreadData::putSpecific() { /************************************** @@ -116,23 +98,6 @@ void ThreadData::putSpecific() } -void ThreadData::putSpecificData(void *t_data) -{ -/************************************** - * - * T H D _ p u t s p e c i f i c _ d a t a - * - ************************************** - * - * Functional description - * Store the passed t_data - * - **************************************/ - - TLS_SET(tSpecific, t_data); -} - - void ThreadData::restoreSpecific() { /************************************** diff --git a/src/jrd/ThreadData.h b/src/jrd/ThreadData.h index 8e03b60cd6..d211b9756c 100644 --- a/src/jrd/ThreadData.h +++ b/src/jrd/ThreadData.h @@ -68,9 +68,6 @@ public: static ThreadData* getSpecific(void); void putSpecific(); static void restoreSpecific(void); - - static void getSpecificData(void** t_data); - static void putSpecificData(void* t_data); }; // Thread entry point definitions might much better look in ThreadStart.h, diff --git a/src/jrd/entry.h b/src/jrd/entry.h index 163406f18e..1b657cf15e 100644 --- a/src/jrd/entry.h +++ b/src/jrd/entry.h @@ -23,17 +23,8 @@ /* Order of battle in ENTRY macro: - generic name current local access method entrypoint - prior local access method (bridge) entrypoint remote entrypoint - OS2 remote name - Central server interface - RDB interface entrypoint - Pipe server interface - Bridge pipe server interface - Windows local access method entrypoint - Win95 interprocess interface */ /***************************************************** @@ -226,4 +217,7 @@ ENTRYPOINT( jrd8_dsql_cache, ENTRYPOINT( jrd8_internal_compile_request, /* REM_internal_compile_request */ no_entrypoint) +ENTRYPOINT( jrd8_shutdown_all, + /* REM_shutdown_all */ no_entrypoint) + #undef ENTRYPOINT diff --git a/src/jrd/isc_file.cpp b/src/jrd/isc_file.cpp index 29c71a971a..ae32070352 100644 --- a/src/jrd/isc_file.cpp +++ b/src/jrd/isc_file.cpp @@ -55,6 +55,7 @@ #include "../common/config/config.h" #include "../common/config/dir_list.h" #include "../common/classes/init.h" +#include "../common/utils_proto.h" #include #ifdef HAVE_SYS_IPC_H @@ -75,12 +76,6 @@ const char INET_FLAG = ':'; -#ifdef SUPERSERVER -#define GETWD(buf) JRD_getdir(buf) -#else -#define GETWD(buf) fb_getcwd(buf) -#endif /* SUPERSERVER */ - #ifdef DARWIN #ifdef HAVE_SYS_PARAM_H #include @@ -859,8 +854,9 @@ bool ISC_expand_filename(tstring& file_name, bool expand_mounts) // Expand the file name #ifdef SUPERSERVER - if ((!fully_qualified_path) && JRD_getdir(file_name)) + if (!fully_qualified_path) { + fb_utils::getCwd(file_name); if (device.hasData() && device[0] == file_name[0]) { // case where temp is of the form "c:foo.fdb" and // expanded_name is "c:\x\y". @@ -888,8 +884,7 @@ bool ISC_expand_filename(tstring& file_name, bool expand_mounts) else #endif { - // Here we get "." and ".." translated by the API, but ONLY IF we are using - // local conection, because in that case, JRD_getdir() returns false. + // Here we get "." and ".." translated by the API. if (!get_full_path(temp, file_name)) { file_name = temp; @@ -1100,10 +1095,7 @@ static void expand_filename2(tstring& buff, bool expand_mounts) // If the file is local, expand partial pathnames with default directory if (*from && *from != '/') { - if (! GETWD(buff)) - { - buff = ""; - } + fb_utils::getCwd(buff); buff += '/'; } diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 341323768b..67eae50d0f 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -129,6 +129,7 @@ #include "../jrd/IntlManager.h" #include "../common/classes/fb_tls.h" #include "../common/classes/ClumpletReader.h" +#include "../common/utils_proto.h" #include "../jrd/DebugInterface.h" #include "../dsql/dsql.h" @@ -464,6 +465,7 @@ static void shutdown_database(Database*, const bool); static void strip_quotes(Firebird::string&); static void purge_attachment(thread_db*, ISC_STATUS*, Attachment*, const bool); static void getUserInfo(UserId&, const DatabaseOptions&); +static bool shutdown_all(); //____________________________________________________________ // @@ -542,6 +544,7 @@ const int BUFFER_LENGTH128 = 128; #define GDS_TRANSACT_REQUEST jrd8_transact_request #define GDS_TRANSACTION_INFO jrd8_transaction_info #define GDS_UNWIND jrd8_unwind_request +#define GDS_SHUTDOWN jrd8_shutdown_all #define GDS_DSQL_ALLOCATE jrd8_allocate_statement #define GDS_DSQL_EXECUTE jrd8_execute @@ -3378,6 +3381,35 @@ ISC_STATUS GDS_START(ISC_STATUS * user_status, } +ISC_STATUS GDS_SHUTDOWN(ISC_STATUS * user_status) +{ +/************************************** + * + * G D S _ S H U T D O W N + * + ************************************** + * + * Functional description + * Rollback every transaction, release + * every attachment, and shutdown every + * database. + * + **************************************/ + ISC_STATUS *s = user_status; + *s++ = isc_arg_gds; + *s = isc_arg_end; + + if (!shutdown_all()) + { + *s++ = isc_random; + *s++ = isc_arg_string; + *s++ = (ISC_STATUS)("Forced server shutdown - not all databases closed"); + } + + return user_status[1]; +} + + ISC_STATUS GDS_START_MULTIPLE(ISC_STATUS * user_status, jrd_tra** tra_handle, USHORT count, @@ -3998,82 +4030,6 @@ ISC_STATUS GDS_DSQL_SQL_INFO(ISC_STATUS* user_status, } -#ifdef SUPERSERVER -bool JRD_getdir(Firebird::PathName& buf) -{ -/************************************** - * - * J R D _ g e t d i r - * - ************************************** - * - * Functional description - * Current working directory is cached in the attachment - * block. Get it out. This function could be called before - * an attachment is created. In such a case thread specific - * data (t_data) will hold the user name which will be used - * to get the users home directory. - * - **************************************/ - char* t_data = NULL; - char b[MAXPATHLEN]; - - ThreadData::getSpecificData((void**) &t_data); - - if (t_data) { -#ifdef WIN_NT - GetCurrentDirectory(MAXPATHLEN, b); - buf = b; -#else - const struct passwd* pwd; - strcpy(b, t_data); - pwd = getpwnam(b); - if (pwd) - buf = pwd->pw_dir; - else // No home dir for this users here. Default to server dir - return fb_getcwd(buf); -#endif - } - else - { - thread_db* tdbb = JRD_get_thread_data(); - - /** If the server has not done a JRD_set_thread_data prior to this call - (which will be the case when connecting via IPC), thread_db will - be NULL so do not attempt to get the attachment handle from - thread_db. Just return false as described below. - NOTE: The only time - this code is entered via IPC is if the database name = "". - **/ - - /** In case of backup/restore APIs, JRD_set_thread_data has been done but - the thread's context is a 'gbak' specific, so don't try extract - attachment from there. - **/ - - Attachment* attachment; - if (tdbb && (tdbb->getType() == ThreadData::tddDBB)) - attachment = tdbb->getAttachment(); - else - return false; - - /** - An older version of client will not be sending isc_dpb_working directory - so in all probabilities attachment->att_working_directory will be null. - return false so that ISC_expand_filename will create the file in fbserver's dir - **/ - if (!attachment || attachment->att_working_directory.empty()) - { - return false; - } - buf = attachment->att_working_directory; - } - - return true; -} -#endif // SUPERSERVER - - #ifdef DEBUG_PROCS void JRD_print_procedure_info(thread_db* tdbb, const char* mesg) { @@ -4698,38 +4654,7 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli switch (rdr.getClumpTag()) { case isc_dpb_working_directory: - { - rdr.getPath(dpb_working_directory); - - // CLASSIC have no thread data. Init to zero. - char* t_data = 0; - ThreadData::getSpecificData((void **) &t_data); - - // Null value for working_directory implies remote database. So get - // the users HOME directory -#ifndef WIN_NT - if (dpb_working_directory.isEmpty()) { - struct passwd *passwd = NULL; - - if (t_data) - passwd = getpwnam(t_data); - if (passwd) - { - dpb_working_directory = passwd->pw_dir; - } - else { // No home dir for this users here. Default to server dir - fb_getcwd(dpb_working_directory); - } - } -#endif - if (t_data) - { - free(t_data); - t_data = NULL; - } - // Null out the thread local data so that further references will fail - ThreadData::putSpecificData(0); - } + rdr.getPath(dpb_working_directory); break; case isc_dpb_set_page_buffers: @@ -6006,46 +5931,6 @@ void JRD_shutdown_all(bool asyncMode) } -void JRD_shutdown_attachment(Attachment** handle, Attachment** released) -{ -/************************************** - * - * J R D _ s h u t d o w n _ a t t a c h m e n t - * - ************************************** - * - * Functional description - * Release attachment. - * - **************************************/ - ISC_STATUS_ARRAY temp_status; - ThreadContextHolder tdbb(temp_status); - - try - { - Firebird::MutexLockGuard guard(databases_mutex); - - Attachment* attachment = *handle; - validateHandle(tdbb, attachment); - DatabaseContextHolder dbbHolder(tdbb); - - purge_attachment(tdbb, temp_status, attachment, true); - - if (released) - { - *released++ = attachment; - } - } - catch (const Firebird::Exception&) - {} // no-op - - if (released) - { - *released = NULL; - } -} - - static unsigned int purge_transactions(thread_db* tdbb, Attachment* attachment, const bool force_flag, diff --git a/src/jrd/jrd_proto.h b/src/jrd/jrd_proto.h index d9d401e3dd..d20cebe4c7 100644 --- a/src/jrd/jrd_proto.h +++ b/src/jrd/jrd_proto.h @@ -143,7 +143,7 @@ ISC_STATUS jrd8_transact_request(ISC_STATUS*, Jrd::Attachment**, USHORT, SCHAR*, USHORT, SCHAR*); ISC_STATUS jrd8_unwind_request(ISC_STATUS *, Jrd::jrd_req**, SSHORT); - +ISC_STATUS jrd8_shutdown_all(ISC_STATUS *); ISC_STATUS jrd8_allocate_statement(ISC_STATUS*, Jrd::Attachment**, Jrd::dsql_req**); @@ -209,42 +209,15 @@ enum JRD_info_tag UCHAR* JRD_num_attachments(UCHAR* const, USHORT, JRD_info_tag, ULONG*, ULONG*); void JRD_shutdown_all(bool); -void JRD_shutdown_attachment(Jrd::Attachment**, Jrd::Attachment**); bool JRD_reschedule(Jrd::thread_db*, SLONG, bool); // Call this function from the debugger if desired void JRD_print_pools(const char* filename); -#ifdef SUPERSERVER -bool JRD_getdir(Firebird::PathName&); -#endif - #ifdef DEBUG_PROCS void JRD_print_procedure_info(Jrd::thread_db*, const char*); #endif -#ifdef WIN_NT -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif - -inline bool fb_getcwd(Firebird::PathName& pn) -{ - char buffer[MAXPATHLEN]; -#if defined(WIN_NT) - _getcwd(buffer, MAXPATHLEN); -#elif defined(HAVE_GETCWD) - getcwd(buffer, MAXPATHLEN); -#else - getwd(buffer); -#endif - pn = buffer; - return bool(buffer); -} - - #endif /* JRD_JRD_PROTO_H */ diff --git a/src/jrd/jrd_pwd.h b/src/jrd/jrd_pwd.h index 5b2f131340..015d5db063 100644 --- a/src/jrd/jrd_pwd.h +++ b/src/jrd/jrd_pwd.h @@ -88,7 +88,7 @@ public: private: static const UCHAR PWD_REQUEST[256]; static const UCHAR TPB[4]; - + Firebird::Mutex mutex; ISC_STATUS_ARRAY status; diff --git a/src/jrd/os/posix/isc_ipc.cpp b/src/jrd/os/posix/isc_ipc.cpp index bbe43a9e85..3b91cffc9a 100644 --- a/src/jrd/os/posix/isc_ipc.cpp +++ b/src/jrd/os/posix/isc_ipc.cpp @@ -336,7 +336,7 @@ static bool isc_signal2( /* Que up the new ISC signal handler routine */ - que_signal(signal_number, handler, arg, flags, old_sig_w_siginfo); + que_signal(signal_number, handler, arg, flags, false); return rc; } diff --git a/src/jrd/os/posix/unix.cpp b/src/jrd/os/posix/unix.cpp index 7463b9e288..eea44d6d67 100644 --- a/src/jrd/os/posix/unix.cpp +++ b/src/jrd/os/posix/unix.cpp @@ -599,6 +599,7 @@ jrd_file* PIO_open(Database* dbb, * Open a database file. * **************************************/ + bool readOnly = false; const TEXT* const ptr = (string.hasData() ? string : file_name).c_str(); int desc = openFile(ptr, false, false, false); @@ -613,16 +614,15 @@ jrd_file* PIO_open(Database* dbb, isc_arg_cstring, file_name.length(), ERR_cstring(file_name), isc_arg_gds, isc_io_open_err, isc_arg_unix, errno, 0); } - else { - /* If this is the primary file, set Database flag to indicate that it is - * being opened ReadOnly. This flag will be used later to compare with - * the Header Page flag setting to make sure that the database is set - * ReadOnly. - */ - PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); - if (!pageSpace->file) - dbb->dbb_flags |= DBB_being_opened_read_only; - } + /* If this is the primary file, set Database flag to indicate that it is + * being opened ReadOnly. This flag will be used later to compare with + * the Header Page flag setting to make sure that the database is set + * ReadOnly. + */ + PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE); + if (!pageSpace->file) + dbb->dbb_flags |= DBB_being_opened_read_only; + readOnly = true; } // posix_fadvise(desc, 0, 0, POSIX_FADV_RANDOM); @@ -647,6 +647,8 @@ jrd_file* PIO_open(Database* dbb, jrd_file *file; try { file = setup_file(dbb, string, desc); + if (readOnly) + file->fil_flags |= FIL_readonly; } catch (const Firebird::Exception&) { close(desc); diff --git a/src/jrd/os/win32/ibinitdll.cpp b/src/jrd/os/win32/ibinitdll.cpp index 1d4c1c37c8..edcbaea70d 100644 --- a/src/jrd/os/win32/ibinitdll.cpp +++ b/src/jrd/os/win32/ibinitdll.cpp @@ -25,7 +25,7 @@ #include #include "../jrd/common.h" #include "../../utilities/install/registry.h" -#include "../jrd/jrd_proto.h" +#include "../jrd/why_proto.h" #include "../jrd/thread_proto.h" @@ -35,7 +35,7 @@ BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID reserved) case DLL_PROCESS_DETACH: #ifdef EMBEDDED - JRD_shutdown_all(false); + fb__shutdown(0); #endif break; diff --git a/src/jrd/pwd.cpp b/src/jrd/pwd.cpp index 56666d01ce..22503afc65 100644 --- a/src/jrd/pwd.cpp +++ b/src/jrd/pwd.cpp @@ -136,7 +136,7 @@ namespace { }; const size_t MAX_CONCURRENT_FAILURES = 16; - const int MAX_FAILED_ATTEMPTS = 2; //4; + const int MAX_FAILED_ATTEMPTS = 4; const int FAILURE_DELAY = 8; // seconds class FailedLogins : private Firebird::SortedObjectsArray handleMappingLock; Firebird::InitInstance > attachments; - Firebird::GlobalPtr attachmentsMutex; + Firebird::GlobalPtr attachmentsMutex, shutdownMutex; + + class ShutChain : public Firebird::GlobalStorage + { + private: + ShutChain(ShutChain* link, FPTR_INT cb, const int m) + : next(link), callBack(cb), mask(m) { } + + ~ShutChain() { } + + private: + static ShutChain* list; + ShutChain* next; + FPTR_INT callBack; + int mask; + + public: + static void add(FPTR_INT cb, const int m) + { + Firebird::MutexLockGuard guard(shutdownMutex); + + for (ShutChain* chain = list; chain; chain = chain->next) + { + if (chain->callBack == cb && chain->mask == m) + { + return; + } + } + + list = new ShutChain(list, cb, m); + } + + static int run(const int m) + { + int rc = 0; + Firebird::MutexLockGuard guard(shutdownMutex); + + for (ShutChain* chain = list; chain; chain = chain->next) + { + if (chain->mask & m && chain->callBack()) + { + rc = 1; + } + } + + return rc; + } + }; + + ShutChain* ShutChain::list = 0; }; namespace YValve @@ -220,7 +263,6 @@ namespace YValve { // scope for write lock on handleMappingLock Firebird::WriteLockGuard sync(handleMappingLock); - fb_assert(handleMapping); // Loop until we find an empty handle slot. // This is to care of case when counter rolls over do { @@ -246,7 +288,6 @@ namespace YValve { Firebird::ReadLockGuard sync(handleMappingLock); - fb_assert(handleMapping); HandleMapping::Accessor accessor(&handleMapping); if (accessor.locate(handle)) { @@ -268,15 +309,6 @@ namespace YValve return parent ? parent->handle : 0; } - void BaseHandle::cancel() - { - if (!parent) - { - return; - } - parent->cancel2(); - } - BaseHandle::~BaseHandle() { if (user_handle) @@ -287,7 +319,6 @@ namespace YValve Firebird::WriteLockGuard sync(handleMappingLock); // Silently ignore bad handles for PROD_BUILD - fb_assert(handleMapping); if (handleMapping->locate(public_handle)) { handleMapping->fastRemove(); @@ -411,22 +442,12 @@ const USHORT DESCRIBE_BUFFER_SIZE = 1024; // size of buffer used in isc_dsql_de namespace { -/* - * class YEntry: - * 1. Provides correct status vector for operation and init() it. - * 2. Tracks subsystem_enter/exit() calls. - * For single-threaded systems: - * 3. Knows location of primary handle and detachs database when - * cancel / shutdown takes place. - * In some cases (primarily - attach/create) specific handle may - * be missing. - */ - + // Status: Provides correct status vector for operation and init() it. class Status { public: Status(ISC_STATUS* v) throw() - : local_vector(v ? v : local_status), doExit(true) + : local_vector(v ? v : local_status) { init_status(local_vector); } @@ -436,275 +457,156 @@ namespace return local_vector; } - // don't exit on missing user_status - // That feature is suspicious: on windows after - // printf() and exit() will happen silent exit. AP-2007. - void ok() - { - doExit = false; - } - ~Status() { #ifdef DEV_BUILD check_status_vector(local_vector); #endif - -#ifndef SUPERSERVER - if (local_vector == local_status && - local_vector[0] == isc_arg_gds && - local_vector[1] != FB_SUCCESS && - doExit) - { - // user did not specify status, but error took place: - // should better specify it next time :-( - gds__print_status(local_vector); - exit((int) local_vector[1]); - } -#endif } + private: ISC_STATUS_ARRAY local_status; ISC_STATUS* local_vector; - bool doExit; }; -#ifndef SERVER_SHUTDOWN // appears this macro has now nothing with shutdown +#ifdef UNIX + int killed; + bool procInt, procTerm; - template - void markHandlesShutdown(Array handles) + Firebird::GlobalPtr shutdownSemaphore; + + THREAD_ENTRY_DECLARE shutdownThread(THREAD_ENTRY_PARAM) { - for (size_t n = 0; n < handles.getCount(); ++n) + for(;;) { - handles[n]->flags |= HANDLE_shutdown; - } - } - - void markShutdown(Attachment* attach) - { - Firebird::MutexLockGuard guard(attach->mutex); - attach->flags |= HANDLE_shutdown; - - markHandlesShutdown(attach->transactions); - markHandlesShutdown(attach->statements); - markHandlesShutdown(attach->requests); - markHandlesShutdown(attach->blobs); - } - - // should be called with locked attachmentsMutex - void markShutdown(Jrd::Attachment** list) - { - while (Jrd::Attachment* ja = *list++) - { - for (size_t n = 0; n < attachments().getCount(); ++n) + killed = 0; + try { + shutdownSemaphore->enter(); + } + catch (Firebird::status_exception& e) { - if (attachments()[n]->handle == ja) + TEXT buffer[1024]; + const ISC_STATUS* vector = e.value(); + if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector))) { - markShutdown(attachments()[n]); - break; + strcpy(buffer, "Unknown failure in shutdown thread in shutSem:enter()"); } - } + gds__log(buffer, 0); + exit(0); + } + + if (! killed) + { + break; + } + + // perform shutdown + ISC_STATUS_ARRAY status; + fb__shutdown(status); + + if (status[0] == 1 && status[1] != 0) + { + char buffer[256]; + const ISC_STATUS *vector = status; + if (!fb_interpret(buffer, sizeof(buffer), &vector)) + { + strcpy(buffer, "Unknown failure in shutdown thread in fb__shutdown()"); + } + gds__log(buffer, 0); + } } + + return 0; } + void handler(int sig) + { + if (killed) + { + return; + } + killed = sig; +#if !defined (SUPERCLIENT) + shutdown_flag = true; +#endif + shutdownSemaphore->release(); + } + + void handlerInt(void*) + { + handler(SIGINT); + } + + void handlerTerm(void*) + { + handler(SIGTERM); + } + + class CtrlCHandler + { + public: + CtrlCHandler(Firebird::MemoryPool&) + { + gds__thread_start(shutdownThread, 0, 0, 0, 0); + + procInt = ISC_signal(SIGINT, handlerInt, 0); + procTerm = ISC_signal(SIGTERM, handlerTerm, 0); + } + + ~CtrlCHandler() + { + ISC_signal_cancel(SIGINT, handlerInt, 0); + ISC_signal_cancel(SIGTERM, handlerTerm, 0); + + if (! killed) + { + // must be done to let shutdownThread close + shutdownSemaphore->release(); + THREAD_YIELD(); + } + } + }; +#endif //UNIX + + // YEntry: Tracks subsystem_enter/exit() calls. + // Accounts activity per different attachments. class YEntry : public Status { public: YEntry(ISC_STATUS* v) throw() - : Status(v), recursive(false) + : Status(v), att(0) { subsystem_enter(); - - if (handle || killed) { - recursive = true; - return; - } - - handle = 0; - vector = (ISC_STATUS*)(*this); - inside = true; - if (!init) - { - init = true; - installCtrlCHandler(); - } +#ifdef UNIX + static Firebird::GlobalPtr ctrlCHandler; +#endif //UNIX } - void setPrimaryHandle(BaseHandle* h) + void setPrimaryHandle(BaseHandle* primary) { - handle = h; + if (primary && primary->parent && (!att)) + { + att = primary->parent; + Firebird::MutexLockGuard guard(att->enterMutex); + att->enterCount++; + } } ~YEntry() { + if (att) + { + Firebird::MutexLockGuard guard(att->enterMutex); + att->enterCount--; + } subsystem_exit(); - - if (recursive) - { - return; - } - - if (killed) - { -#if !defined (SUPERCLIENT) - JRD_shutdown_all(false); -#endif - propagateKill(); - } - - if (fatal()) - { - if (handle) - { - Jrd::Attachment* attach = handle->getAttachmentHandle(); - Firebird::HalfStaticArray releasedBuffer; - - Firebird::MutexLockGuard guard(attachmentsMutex); - Jrd::Attachment** released = - releasedBuffer.getBuffer(attachments().getCount() + 1); - *released = 0; -#if !defined (SUPERCLIENT) - JRD_shutdown_attachment(&attach, released); -#endif - markShutdown(released); - } - } - - inside = false; - handle = 0; } + private: YEntry(const YEntry&); // prohibit copy constructor - - bool recursive; // loopback call from ExecState, Udf, etc. - - static bool inside; - static BaseHandle* handle; - static ISC_STATUS* vector; - static bool init; - static int killed; - static bool proc2, proc15; - - static void installCtrlCHandler() throw() - { - try - { - proc2 = ISC_signal(SIGINT, Handler2, 0); - proc15 = ISC_signal(SIGTERM, Handler15, 0); - } - catch (...) - { - gds__log("Failure setting ctrl-C handlers"); - } - } - - static void propagateKill() - { - ISC_signal_cancel(SIGINT, Handler2, 0); - ISC_signal_cancel(SIGTERM, Handler15, 0); - - // if signal is not processed by someone else, exit now - if (!(killed == 2 ? proc2 : proc15)) - { - exit(0); - } - - // Someone else watches signals - let him shutdown gracefully - - // Using recursive mutex in signal handler routine - - // relatively safe cause we need read-only access. - // With correctly implemented insert / remove methods in array - // and memcpy/memmove copying data with at least sizeof(void*) - // portions, this code is really safe. - - Firebird::MutexLockGuard guard(attachmentsMutex); - for (size_t n = 0; n < attachments().getCount(); ++n) - { - markShutdown(attachments()[n]); - } - } - - static void Handler2(void*) - { - if (killed) - { - return; // do nothing - already killed - } - killed = 2; - Handler(); - } - - static void Handler15(void*) - { - if (killed) - { - return; // do nothing - already killed - } - killed = 15; - Handler(); - } - - static void Handler() - { -#if !defined (SUPERCLIENT) - shutdown_flag = true; -#endif - if (inside) - { - if (handle) - { - handle->cancel(); - } - } - else - { - // this function must in theory use only signal-safe code - // but as long as we have not entered engine, - // any call to it should be safe -#if !defined (SUPERCLIENT) - JRD_shutdown_all(false); -#endif - propagateKill(); - } - } - - bool fatal() const - { - return (vector[0] == isc_arg_gds && vector[1] == isc_shutdown); - } + Attachment* att; }; - bool YEntry::init = false; - bool YEntry::inside = false; - BaseHandle* YEntry::handle = 0; - ISC_STATUS* YEntry::vector = 0; - int YEntry::killed = 0; - bool YEntry::proc2 = false; - bool YEntry::proc15 = false; - -#else - - class YEntry : public Status - { - public: - YEntry(ISC_STATUS* v) : Status(v) - { - subsystem_enter(); - } - - void setPrimaryHandle(BaseHandle* h) - { - } - - ~YEntry() - { - subsystem_exit(); - } - private: - YEntry(const YEntry&); //prohibit copy constructor - }; - -#endif } // anonymous namespace @@ -863,7 +765,9 @@ const int PROC_INTL_FUNCTION = 54; // internal call const int PROC_DSQL_CACHE = 55; // internal call const int PROC_INTERNAL_COMPILE = 56; // internal call -const int PROC_count = 57; +const int PROC_SHUTDOWN = 57; + +const int PROC_count = 58; /* Define complicated table for multi-subsystem world */ @@ -988,18 +892,6 @@ static const SCHAR sql_prepare_info2[] = }; -namespace YValve -{ - void Attachment::cancel2() - { -#if !defined (SUPERCLIENT) && !defined(SERVER_SHUTDOWN) - ISC_STATUS_ARRAY local; - jrd8_cancel_operation(local, &handle, CANCEL_raise); -#endif - } -} - - ISC_STATUS API_ROUTINE GDS_ATTACH_DATABASE(ISC_STATUS* user_status, SSHORT file_length, const TEXT* file_name, @@ -1282,10 +1174,18 @@ ISC_STATUS API_ROUTINE GDS_CANCEL_OPERATION(ISC_STATUS * user_status, try { Attachment* attachment = translate(handle); - status.setPrimaryHandle(attachment); - CALL(PROC_CANCEL_OPERATION, attachment->implementation) (status, - &attachment->handle, - option); + // mutex will be locked here for a really long time + Firebird::MutexLockGuard guard(attachment->enterMutex); + if (attachment->enterCount) + { + CALL(PROC_CANCEL_OPERATION, attachment->implementation) (status, + &attachment->handle, + option); + } + else + { + Firebird::status_exception::raise(isc_random, isc_arg_string, "Nothing to cancel", 0); + } } catch (const Firebird::Exception& e) { @@ -2495,7 +2395,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_EXEC_IMMED2(ISC_STATUS* user_status, dasup.dasup_clauses[DASUP_CLAUSE_select].dasup_blr, out_msg_type, out_msg_length, dasup.dasup_clauses[DASUP_CLAUSE_select].dasup_msg); - status.ok(); if (!s) { s = UTLD_parse_sqlda(status, &dasup, NULL, NULL, NULL, dialect, @@ -2803,7 +2702,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH(ISC_STATUS* user_status, dasup.dasup_clauses[DASUP_CLAUSE_select].dasup_msg); if (s && s != 101) { - status.ok(); return s; } @@ -2812,7 +2710,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH(ISC_STATUS* user_status, { return status[1]; } - status.ok(); } catch (const Firebird::Exception& e) { @@ -2870,7 +2767,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH2(ISC_STATUS* user_status, direction, offset); if (s && s != 101) { - status.ok(); return s; } @@ -2879,7 +2775,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH2(ISC_STATUS* user_status, { return status[1]; } - status.ok(); } catch (const Firebird::Exception& e) { @@ -2931,7 +2826,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH_M(ISC_STATUS* user_status, if (s == 100 || s == 101) { - status.ok(); return s; } } @@ -2984,7 +2878,6 @@ ISC_STATUS API_ROUTINE GDS_DSQL_FETCH2_M(ISC_STATUS* user_status, if (s == 100 || s == 101) { - status.ok(); return s; } } @@ -3625,7 +3518,6 @@ ISC_STATUS API_ROUTINE GDS_GET_SEGMENT(ISC_STATUS * user_status, if (code == isc_segstr_eof || code == isc_segment) { - status.ok(); return code; } } @@ -3686,8 +3578,8 @@ ISC_STATUS API_ROUTINE GDS_GET_SLICE(ISC_STATUS* user_status, } -ISC_STATUS gds__handle_cleanup(ISC_STATUS * user_status, - FB_API_HANDLE * user_handle) +ISC_STATUS API_ROUTINE gds__handle_cleanup(ISC_STATUS * user_status, + FB_API_HANDLE * user_handle) { /************************************** * @@ -4810,7 +4702,6 @@ ISC_STATUS API_ROUTINE_VARARG GDS_START_TRANSACTION(ISC_STATUS * user_status, va_end(ptr); GDS_START_MULTIPLE(user_status, tra_handle, count, teb); - status.ok(); } catch (const Firebird::Exception& e) { @@ -5378,7 +5269,6 @@ static ISC_STATUS get_transaction_info(ISC_STATUS* user_status, { TEXT buffer[16]; TEXT* p = *ptr; - status.ok(); if (CALL(PROC_TRANSACTION_INFO, transaction->implementation) (status, &transaction-> @@ -5573,7 +5463,6 @@ static ISC_STATUS prepare(ISC_STATUS* user_status, * **************************************/ Status status(user_status); - status.ok(); Transaction* sub; TEXT tdr_buffer[1024]; @@ -5918,3 +5807,75 @@ bool WHY_get_shutdown() return shutdown_flag; } #endif // !SUPERCLIENT + + +ISC_STATUS API_ROUTINE fb__shutdown(ISC_STATUS * user_status) +{ +/************************************** + * + * f b _ s h u t d o w n + * + ************************************** + * + * Functional description + * Shutdown firebird. + * + **************************************/ + YEntry status(user_status); + try + { + // Shutdown clients before providers + if (ShutChain::run(FB_SHUT_PREPROVIDERS) == 0) + { + // Shutdown providers + for (int n=0; npublic_handle; } }; @@ -193,6 +193,9 @@ namespace YValve // of collision is so slow here, that I prefer to save resources, using single mutex. Firebird::Mutex mutex; + int enterCount; + Firebird::Mutex enterMutex; + Clean cleanup; StoredAtt* handle; Firebird::PathName db_path; @@ -211,7 +214,6 @@ namespace YValve public: Attachment(StoredAtt*, FB_API_HANDLE*, USHORT); - void cancel2(); ~Attachment(); }; diff --git a/src/qli/dtr.cpp b/src/qli/dtr.cpp index 8903469d0e..b4e0f0c7a7 100644 --- a/src/qli/dtr.cpp +++ b/src/qli/dtr.cpp @@ -51,6 +51,7 @@ #include "../qli/meta_proto.h" #include "../qli/parse_proto.h" #include "../jrd/gds_proto.h" +#include "../jrd/why_proto.h" #include "../jrd/perf_proto.h" #include "../include/fb_exception.h" #include "../common/utils_proto.h" @@ -60,18 +61,13 @@ using MsgFormat::SafeArg; const char* STARTUP_FILE = "HOME"; // Assume its Unix -#ifndef SIGQUIT -#define SIGQUIT SIGINT -#define SIGPIPE SIGINT -#endif - extern TEXT *QLI_prompt; static void enable_signals(void); static bool process_statement(bool); static void CLIB_ROUTINE signal_arith_excp(USHORT, USHORT, USHORT); -static void CLIB_ROUTINE signal_quit(int); +static int CLIB_ROUTINE async_quit(); static bool yes_no(USHORT, const TEXT*); struct answer_t { @@ -299,9 +295,13 @@ static void enable_signals(void) **************************************/ typedef void (*new_handler) (int); - signal(SIGQUIT, signal_quit); - signal(SIGINT, signal_quit); - signal(SIGPIPE, signal_quit); +#ifdef SIGQUIT + signal(SIGQUIT, SIG_IGN); +#endif + fb__shutdown_callback(0, async_quit, FB_SHUT_PREPROVIDERS); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif signal(SIGFPE, (new_handler) signal_arith_excp); } @@ -559,7 +559,7 @@ static void CLIB_ROUTINE signal_arith_excp(USHORT sig, USHORT code, USHORT scp) } -static void CLIB_ROUTINE signal_quit(int) +static int CLIB_ROUTINE async_quit() { /************************************** * @@ -571,12 +571,8 @@ static void CLIB_ROUTINE signal_quit(int) * Stop whatever we happened to be doing. * **************************************/ - //void (*prev_handler) (); - - signal(SIGQUIT, SIG_DFL); - signal(SIGINT, SIG_DFL); - EXEC_abort(); + return 1; } diff --git a/src/qli/exe.cpp b/src/qli/exe.cpp index 9897a24123..afbd85e9a3 100644 --- a/src/qli/exe.cpp +++ b/src/qli/exe.cpp @@ -26,6 +26,8 @@ #include #include "../jrd/ibase.h" +#include "../jrd/common.h" +#include "../jrd/why_proto.h" #include "../qli/dtr.h" #include "../qli/exe.h" #include "../qli/all_proto.h" @@ -102,13 +104,17 @@ void EXEC_abort(void) **************************************/ ISC_STATUS_ARRAY status_vector; - for (qli_req* request = QLI_requests; request; request = request->req_next) + for (DBB database = QLI_databases; database; database = database->dbb_next) { - if (request->req_handle) - isc_unwind_request(status_vector, &request->req_handle, 0); + if (database->dbb_handle) + { + if (gds__cancel_operation(status_vector, &database->dbb_handle, CANCEL_raise) == 0) + { + QLI_abort = true; + } + } } - QLI_abort = true; } diff --git a/src/remote/inet.cpp b/src/remote/inet.cpp index 26537254c6..3157f2ff8c 100644 --- a/src/remote/inet.cpp +++ b/src/remote/inet.cpp @@ -301,8 +301,7 @@ static rem_port* inet_try_connect( PACKET*, Firebird::PathName&, const TEXT*, ISC_STATUS*, - const UCHAR*, - USHORT); + Firebird::ClumpletReader &); static bool_t inet_write(XDR *, int); #if !(defined WIN_NT) static int parse_hosts(const TEXT*, const TEXT*, const TEXT*); @@ -406,8 +405,7 @@ rem_port* INET_analyze(Firebird::PathName& file_name, const TEXT* node_name, const TEXT* user_string, bool uv_flag, - const UCHAR* dpb, - USHORT dpb_length) + Firebird::ClumpletReader &dpb) { /************************************** * @@ -489,7 +487,7 @@ rem_port* INET_analyze(Firebird::PathName& file_name, /* Try connection using first set of protocols. punt if error */ rem_port* port = inet_try_connect(packet, rdb, file_name, - node_name, status_vector, dpb, dpb_length); + node_name, status_vector, dpb); if (!port) { return NULL; } @@ -516,7 +514,7 @@ rem_port* INET_analyze(Firebird::PathName& file_name, cnct->p_cnct_count); port = inet_try_connect(packet, rdb, file_name, - node_name, status_vector, dpb, dpb_length); + node_name, status_vector, dpb); if (!port) { return NULL; } @@ -544,7 +542,7 @@ rem_port* INET_analyze(Firebird::PathName& file_name, cnct->p_cnct_count); port = inet_try_connect(packet, rdb, file_name, - node_name, status_vector, dpb, dpb_length); + node_name, status_vector, dpb); if (!port) { return NULL; } @@ -591,7 +589,7 @@ rem_port* INET_analyze(Firebird::PathName& file_name, rem_port* INET_connect(const TEXT* name, PACKET* packet, ISC_STATUS* status_vector, - USHORT flag, const UCHAR* dpb, USHORT dpb_length) + USHORT flag, Firebird::ClumpletReader* dpb) { /************************************** * @@ -622,7 +620,7 @@ rem_port* INET_connect(const TEXT* name, rem_port* port = alloc_port(0); port->port_status_vector = status_vector; - REMOTE_get_timeout_params(port, dpb, dpb_length); + REMOTE_get_timeout_params(port, dpb); status_vector[0] = isc_arg_gds; status_vector[1] = 0; status_vector[2] = isc_arg_end; @@ -1258,7 +1256,7 @@ static rem_port* alloc_port( rem_port* parent) rem_port* port = (rem_port*) ALLR_block(type_port, INET_remote_buffer * 2); port->port_type = port_inet; port->port_state = state_pending; - REMOTE_get_timeout_params(port, 0, 0); + REMOTE_get_timeout_params(port, 0); gethostname(buffer, sizeof(buffer)); port->port_host = REMOTE_make_string(buffer); @@ -3095,8 +3093,7 @@ static rem_port* inet_try_connect( Firebird::PathName& file_name, const TEXT* node_name, ISC_STATUS* status_vector, - const UCHAR* dpb, - USHORT dpb_length) + Firebird::ClumpletReader& dpb) { /************************************** * @@ -3124,9 +3121,7 @@ static rem_port* inet_try_connect( /* If we can't talk to a server, punt. Let somebody else generate an error. status_vector will have the network error info. */ - rem_port* port = - INET_connect(node_name, packet, status_vector, FALSE, dpb, - dpb_length); + rem_port* port = INET_connect(node_name, packet, status_vector, FALSE, &dpb); if (!port) { ALLR_free(rdb); return NULL; diff --git a/src/remote/inet_proto.h b/src/remote/inet_proto.h index a27aa348a3..492d5dcb1a 100644 --- a/src/remote/inet_proto.h +++ b/src/remote/inet_proto.h @@ -26,10 +26,15 @@ #include "../common/classes/fb_string.h" +namespace Firebird +{ + class ClumpletReader; +}; + rem_port* INET_analyze(Firebird::PathName&, ISC_STATUS*, const TEXT*, const TEXT*, - bool, const UCHAR*, USHORT); + bool, Firebird::ClumpletReader&); rem_port* INET_connect(const TEXT*, struct packet*, ISC_STATUS*, USHORT, - const UCHAR*, USHORT); + Firebird::ClumpletReader*); rem_port* INET_reconnect(HANDLE, ISC_STATUS*); rem_port* INET_server(int); void INET_set_clients(int); diff --git a/src/remote/inet_server.cpp b/src/remote/inet_server.cpp index 1684936e14..b5085f5d9c 100644 --- a/src/remote/inet_server.cpp +++ b/src/remote/inet_server.cpp @@ -37,10 +37,12 @@ #include "../jrd/common.h" #include "../jrd/isc_proto.h" #include "../jrd/divorce.h" -#include "../jrd/jrd_proto.h" +#include "../jrd/ibase.h" +#include "../jrd/why_proto.h" #include "../common/classes/init.h" #include "../common/config/config.h" #include +//#include "../jrd/os/isc_i_proto.h" #ifdef HAVE_SYS_TYPES_H #include @@ -69,15 +71,12 @@ #include #endif - -#ifdef SUPERSERVER #ifdef HAVE_UNISTD_H #include #endif #include #include "../jrd/ibase.h" #include "../jrd/jrd_pwd.h" -#endif #include "../remote/remote.h" #include "../jrd/license.h" @@ -103,11 +102,7 @@ #include #endif -#if (defined SUPERSERVER && defined UNIX && defined SERVER_SHUTDOWN) #include "../common/classes/semaphore.h" -#define SHUTDOWN_THREAD -#include "../jrd/ThreadStart.h" -#endif #ifdef UNIX const char* TEMP_DIR = "/tmp"; @@ -124,17 +119,9 @@ const char* FIREBIRD_USER_NAME = "firebird"; static void set_signal(int, void (*)(int)); static void signal_handler(int); -#if (defined SUPERSERVER && defined UNIX ) -//static void signal_sigpipe_handler(int); -#endif - -#ifdef SHUTDOWN_THREAD -static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg); -static void signal_term(int); -static void shutdown_init(); -static void shutdown_fini(); +static int shutdownInetServer(); +static void shutdownInit(); static void tryStopMainThread(); -#endif static TEXT protocol[128]; static int INET_SERVER_start = 0; @@ -272,8 +259,7 @@ int CLIB_ROUTINE server_main( int argc, char** argv) // activate paths set with -e family of switches ISC_set_prefix(0, 0); -#if (defined SUPERSERVER && defined UNIX ) - /* set_signal(SIGPIPE, signal_sigpipe_handler); */ +#ifdef UNIX set_signal(SIGPIPE, signal_handler); set_signal(SIGUSR1, signal_handler); set_signal(SIGUSR2, signal_handler); @@ -314,7 +300,9 @@ int CLIB_ROUTINE server_main( int argc, char** argv) #ifndef SUPERSERVER if (multi_client && !debug) { +#ifdef UNIX set_signal(SIGUSR1, signal_handler); +#endif int child; for (int n = 0; n < 100; n++) { INET_SERVER_start = 0; @@ -327,7 +315,9 @@ int CLIB_ROUTINE server_main( int argc, char** argv) } gds__log("INET_SERVER/main: gds_inet_server restarted"); } +#ifdef UNIX set_signal(SIGUSR1, SIG_DFL); +#endif } #endif @@ -370,8 +360,7 @@ int CLIB_ROUTINE server_main( int argc, char** argv) { // scope block ISC_STATUS_ARRAY status_vector; THREAD_ENTER(); - port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag, - 0, 0); + port = INET_connect(protocol, 0, status_vector, INET_SERVER_flag, 0); THREAD_EXIT(); if (!port) { gds__print_status(status_vector); @@ -390,7 +379,6 @@ int CLIB_ROUTINE server_main( int argc, char** argv) } #ifdef SUPERSERVER - /* before starting the superserver stuff change directory to tmp */ if (CHANGE_DIR(TEMP_DIR)) { /* error on changing the directory */ @@ -424,10 +412,7 @@ int CLIB_ROUTINE server_main( int argc, char** argv) } } -#endif - -#ifdef SHUTDOWN_THREAD - shutdown_init(); + shutdownInit(); #endif if (multi_threaded) @@ -435,10 +420,6 @@ int CLIB_ROUTINE server_main( int argc, char** argv) else SRVR_main(port, INET_SERVER_flag); -#ifdef SHUTDOWN_THREAD - shutdown_fini(); -#endif - #ifdef DEBUG_GDS_ALLOC /* In Debug mode - this will report all server-side memory leaks * due to remote access @@ -472,12 +453,14 @@ static void set_signal( int signal_number, void (*handler) (int)) * Establish signal handler. * **************************************/ +#ifdef UNIX struct sigaction vec, old_vec; vec.sa_handler = handler; sigemptyset(&vec.sa_mask); vec.sa_flags = 0; sigaction(signal_number, &vec, &old_vec); +#endif } @@ -497,38 +480,16 @@ static void signal_handler(int) ++INET_SERVER_start; } -#ifdef NOT_USED_OR_REPLACED -#if (defined SUPERSERVER && defined UNIX ) -static void signal_sigpipe_handler(int) -{ -/**************************************************** - * - * s i g n a l _ s i g p i p e _ h a n d l e r - * - **************************************************** - * - * Functional description - * Dummy signal handler. - * - **************************************/ - ++INET_SERVER_start; - gds__log - ("Super Server/main: Bad client socket, send() resulted in SIGPIPE, caught by server\n client exited improperly or crashed ????"); -} -#endif //SUPERSERVER && UNIX -#endif - -#ifdef SHUTDOWN_THREAD -static Firebird::GlobalPtr shutSem; static Firebird::GlobalPtr mainThreadStopSem; -static bool alreadyClosing = false; +static bool serverClosing = false; -static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg) + +static int shutdownInetServer() { /**************************************************** * - * s h u t d o w n _ t h r e a d + * s h u t d o w n I n e t S e r v e r * **************************************************** * @@ -537,85 +498,38 @@ static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg) * which received SIGTERM, run in separate thread. * **************************************/ - try { - shutSem->enter(); - } - catch (Firebird::status_exception& e) - { - TEXT buffer[1024]; - const ISC_STATUS* vector = e.value(); - if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector))) - { - strcpy(buffer, "Unknown failure in shutdown thread in shutSem:enter()"); - } - gds__log(buffer, 0); - exit(0); - } - if (! alreadyClosing) - { - alreadyClosing = true; - // shutdown databases - JRD_shutdown_all(false); - // shutdown worker threads - SRVR_shutdown(); - // shutdown main thread - send self-signal to close select() - // in main thread and wait for it to get into safe state - kill(getpid(), SIGTERM); - mainThreadStopSem->enter(); - // ready - exit(0); - } - return 0; //make compilers happy + + serverClosing = true; + + // shutdown worker threads + SRVR_shutdown(); + + // shutdown main thread - send self-signal to close select() + // in main thread and wait for it to get into safe state +#ifdef UNIX + kill(getpid(), SIGUSR1); +#else + need a way to interrupt select in main listener thread in windows +#endif + + mainThreadStopSem->enter(); + + // Ready to die + return 0; } -static void signal_term(int) +static void shutdownInit() { -/**************************************************** - * - * s i g n a l _ t e r m - * - **************************************************** - * - * Functional description - * Handle ^C and kill. - * - **************************************/ - if (alreadyClosing) - { - return; - } - try - { - shutSem->release(); - } - catch (Firebird::status_exception& e) - { - TEXT buffer[1024]; - const ISC_STATUS* vector = e.value(); - if (! (vector && fb_interpret(buffer, sizeof(buffer), &vector))) - { - strcpy(buffer, "Unknown failure in semaphore::release()"); - } - gds__log(buffer, 0); - exit(0); - } -} - -static void shutdown_init() -{ - gds__thread_start(shutdown_thread, 0, THREAD_medium, 0, 0); - // process signals 2 & 15 in order to exit gracefully - set_signal(SIGINT, signal_term); - set_signal(SIGTERM, signal_term); setStopMainThread(tryStopMainThread); -} -static void shutdown_fini() -{ - set_signal(SIGINT, SIG_IGN); - set_signal(SIGTERM, SIG_IGN); - alreadyClosing = true; - shutSem->release(); + ISC_STATUS_ARRAY status; + fb__shutdown_callback(status, shutdownInetServer, FB_SHUT_POSTPROVIDERS); + if (status[0] == 1 && status[1] > 0) + { + gds__log_status("shutdownInit", status); + isc_print_status(status); + exit(STARTUP_ERROR); + } } static void tryStopMainThread() @@ -631,7 +545,7 @@ static void tryStopMainThread() * In that case release semaphore and wait indefinitely. * **************************************/ - if (alreadyClosing) + if (serverClosing) { mainThreadStopSem->release(); for (;;) @@ -640,4 +554,3 @@ static void tryStopMainThread() } } } -#endif //SHUTDOWN_THREAD diff --git a/src/remote/interface.cpp b/src/remote/interface.cpp index eeebaba67e..e3eb6d14a5 100644 --- a/src/remote/interface.cpp +++ b/src/remote/interface.cpp @@ -86,9 +86,6 @@ #ifdef WIN_NT #define sleep(seconds) Sleep ((seconds) * 1000) - -#include // getcwd - #endif // WIN_NT const char* ISC_USER = "ISC_USER"; @@ -130,9 +127,9 @@ static RVNT add_event(rem_port*); static void add_other_params(rem_port*, Firebird::ClumpletWriter&, const ParametersSet&); static void add_working_directory(Firebird::ClumpletWriter&, const Firebird::PathName&); static rem_port* analyze(Firebird::PathName&, ISC_STATUS*, const TEXT*, - bool, const UCHAR*, USHORT, Firebird::PathName&); + bool, Firebird::ClumpletReader&, Firebird::PathName&); static rem_port* analyze_service(Firebird::PathName&, ISC_STATUS*, const TEXT*, - bool, const UCHAR*, USHORT); + bool, Firebird::ClumpletReader&); static bool batch_gds_receive(rem_port*, struct rmtque *, ISC_STATUS *, USHORT); static bool batch_dsql_fetch(rem_port*, struct rmtque *, @@ -326,8 +323,7 @@ ISC_STATUS GDS_ATTACH_DATABASE(ISC_STATUS* user_status, Firebird::PathName expanded_name(expanded_filename); Firebird::PathName node_name; rem_port* port = analyze(expanded_name, user_status, us, user_verification, - newDpb.getBuffer(), - newDpb.getBufferLength(), node_name); + newDpb, node_name); if (!port) { return user_status[1]; @@ -852,8 +848,7 @@ ISC_STATUS GDS_CREATE_DATABASE(ISC_STATUS* user_status, Firebird::PathName expanded_name(expanded_filename); Firebird::PathName node_name; const UCHAR* dpb2 = reinterpret_cast(dpb); - rem_port* port = analyze(expanded_name, user_status, us, - user_verification, dpb2, dpb_length, node_name); + rem_port* port = analyze(expanded_name, user_status, us, user_verification, newDpb, node_name); if (!port) { return user_status[1]; } @@ -3835,9 +3830,8 @@ ISC_STATUS GDS_SERVICE_ATTACH(ISC_STATUS* user_status, const bool user_verification = get_new_dpb(newSpb, user_string, spbParam); const TEXT* us = (user_string.hasData()) ? user_string.c_str() : 0; - const UCHAR* spb2 = reinterpret_cast(spb); rem_port* port = analyze_service(expanded_name, user_status, us, - user_verification, spb2, spb_length); + user_verification, newSpb); if (!port) { return user_status[1]; } @@ -4536,7 +4530,7 @@ static void add_working_directory(Firebird::ClumpletWriter& dpb, // for WNet local node_name should be compared with "\\\\." ? if (node_name == "localhost") { - fb_getcwd(cwd); + fb_utils::getCwd(cwd); } dpb.insertPath(isc_dpb_working_directory, cwd); } @@ -4546,8 +4540,7 @@ static rem_port* analyze(Firebird::PathName& file_name, ISC_STATUS* status_vector, const TEXT* user_string, bool uv_flag, - const UCHAR* dpb, - USHORT dpb_length, + Firebird::ClumpletReader& dpb, Firebird::PathName& node_name) { /************************************** @@ -4588,16 +4581,14 @@ static rem_port* analyze(Firebird::PathName& file_name, if (ISC_analyze_tcp(file_name, node_name)) { port = INET_analyze(file_name, status_vector, - node_name.c_str(), user_string, uv_flag, dpb, - dpb_length); + node_name.c_str(), user_string, uv_flag, dpb); if (!port) { /* retry in case multiclient inet server not forked yet */ sleep(2); port = INET_analyze(file_name, status_vector, - node_name.c_str(), user_string, uv_flag, dpb, - dpb_length); + node_name.c_str(), user_string, uv_flag, dpb); } } else @@ -4608,8 +4599,7 @@ static rem_port* analyze(Firebird::PathName& file_name, if (ISC_analyze_nfs(file_name, node_name)) { port = INET_analyze(file_name, status_vector, - node_name.c_str(), user_string, uv_flag, dpb, - dpb_length); + node_name.c_str(), user_string, uv_flag, dpb); if (!port) { /* retry in case multiclient inet server not forked yet */ @@ -4618,8 +4608,7 @@ static rem_port* analyze(Firebird::PathName& file_name, port = INET_analyze(file_name, status_vector, node_name.c_str(), - user_string, uv_flag, dpb, - dpb_length); + user_string, uv_flag, dpb); } } } @@ -4668,8 +4657,7 @@ static rem_port* analyze(Firebird::PathName& file_name, node_name.c_str(), user_string, uv_flag, - dpb, - dpb_length); + dpb); } } @@ -4690,8 +4678,7 @@ static rem_port* analyze_service(Firebird::PathName& service_name, ISC_STATUS* status_vector, const TEXT* user_string, bool uv_flag, - const UCHAR* dpb, - USHORT dpb_length) + Firebird::ClumpletReader& spb) { /************************************** * @@ -4723,8 +4710,7 @@ static rem_port* analyze_service(Firebird::PathName& service_name, if (!port) { if (ISC_analyze_tcp(service_name, node_name)) { port = INET_analyze(service_name, status_vector, - node_name.c_str(), user_string, uv_flag, dpb, - dpb_length); + node_name.c_str(), user_string, uv_flag, spb); } } @@ -4751,8 +4737,7 @@ static rem_port* analyze_service(Firebird::PathName& service_name, node_name.c_str(), user_string, uv_flag, - dpb, - dpb_length); + spb); } } #endif /* UNIX */ diff --git a/src/remote/os/win32/cntl.cpp b/src/remote/os/win32/cntl.cpp index 69aa6a37d6..31e1818d2e 100644 --- a/src/remote/os/win32/cntl.cpp +++ b/src/remote/os/win32/cntl.cpp @@ -337,7 +337,7 @@ static THREAD_ENTRY_DECLARE cleanup_thread(THREAD_ENTRY_PARAM) if (new_ptr != return_buffer) gds__free(new_ptr); - JRD_shutdown_all(false); + fb__shutdown(0); SRVR_shutdown(); return 0; } diff --git a/src/remote/os/win32/srvr_w32.cpp b/src/remote/os/win32/srvr_w32.cpp index fd4892af5a..8f4291f9ff 100644 --- a/src/remote/os/win32/srvr_w32.cpp +++ b/src/remote/os/win32/srvr_w32.cpp @@ -343,7 +343,7 @@ static THREAD_ENTRY_DECLARE inet_connect_wait_thread(THREAD_ENTRY_PARAM) { THREAD_ENTER(); rem_port* port = - INET_connect(protocol_inet, NULL, status_vector, server_flag, 0, 0); + INET_connect(protocol_inet, NULL, status_vector, server_flag, 0); THREAD_EXIT(); if (!port) { gds__log_status(0, status_vector); diff --git a/src/remote/remot_proto.h b/src/remote/remot_proto.h index fc8e01a00e..b78f116f86 100644 --- a/src/remote/remot_proto.h +++ b/src/remote/remot_proto.h @@ -25,10 +25,14 @@ #define REMOTE_REMOT_PROTO_H struct blk; +namespace Firebird +{ + class ClumpletReader; +}; void REMOTE_cleanup_transaction (struct rtr *); ULONG REMOTE_compute_batch_size (rem_port*, USHORT, P_OP, const rem_fmt*); -void REMOTE_get_timeout_params (rem_port*, const UCHAR*, USHORT); +void REMOTE_get_timeout_params(rem_port* port, Firebird::ClumpletReader* pb); struct rrq* REMOTE_find_request (struct rrq *, USHORT); void REMOTE_free_packet (rem_port*, struct packet *, bool = false); struct rem_str* REMOTE_make_string (const SCHAR*); diff --git a/src/remote/remote.cpp b/src/remote/remote.cpp index 7dabd0860c..dd2185b144 100644 --- a/src/remote/remote.cpp +++ b/src/remote/remote.cpp @@ -48,7 +48,6 @@ static TEXT* attach_failures = NULL; static TEXT* attach_failures_ptr; static void cleanup_memory(void*); -static SLONG get_parameter(const UCHAR**); void REMOTE_cleanup_transaction( RTR transaction) @@ -322,9 +321,7 @@ void REMOTE_free_packet( rem_port* port, PACKET * packet, bool partial) } -void REMOTE_get_timeout_params( - rem_port* port, - const UCHAR* dpb, USHORT dpb_length) +void REMOTE_get_timeout_params(rem_port* port, Firebird::ClumpletReader* pb) { /************************************** * @@ -341,99 +338,19 @@ void REMOTE_get_timeout_params( * **************************************/ bool got_dpb_connect_timeout = false; - bool got_dpb_dummy_packet_interval = false; fb_assert(isc_dpb_connect_timeout == isc_spb_connect_timeout); - fb_assert(isc_dpb_dummy_packet_interval == isc_spb_dummy_packet_interval); - port->port_flags &= ~PORT_dummy_pckt_set; - - if (dpb && dpb_length) { - const UCHAR* p = dpb; - const UCHAR* const end = p + dpb_length; - - if (*p++ == isc_dpb_version1) { - while (p < end) - switch (*p++) { - case isc_dpb_connect_timeout: - port->port_connect_timeout = get_parameter(&p); - got_dpb_connect_timeout = true; - break; - -// 22 Aug 2003. Do not receive this parameter from the client as dummy packets -// either kill idle client process or cause unexpected disconnections. -// This applies to all IB/FB versions. -// case isc_dpb_dummy_packet_interval: -// port->port_dummy_packet_interval = get_parameter(&p); -// got_dpb_dummy_packet_interval = true; -// port->port_flags |= PORT_dummy_pckt_set; -// break; - - case isc_dpb_sys_user_name: - /** Store the user name in thread specific storage. - We need this later while expanding filename to - get the users home directory. - Normally the working directory is stored in - the attachment but in this case the attachment is - not yet created. - Also note that the thread performing this task - has already called THREAD_ENTER - **/ - { - char* t_data; - int i = 0; - int l = *(p++); - if (l) { - t_data = (char *) malloc(l + 1); - do { - t_data[i] = *p; - if (t_data[i] == '.') - t_data[i] = 0; - i++; - p++; - } while (--l); - } - else - t_data = (char *) malloc(1); - t_data[i] = 0; - - - ThreadData::putSpecificData((void *) t_data); - - } - break; - - default: - { - // Skip over this parameter - not important to us - const USHORT len = *p++; - p += len; - break; - } - } - } - } - - if (!got_dpb_connect_timeout || !got_dpb_dummy_packet_interval) { - /* Didn't find all parameters in the dpb, fetch configuration - information from the configuration file and set the missing - values */ - - if (!got_dpb_connect_timeout) - port->port_connect_timeout = Config::getConnectionTimeout(); - - if (!got_dpb_dummy_packet_interval) { - port->port_flags |= PORT_dummy_pckt_set; - port->port_dummy_packet_interval = Config::getDummyPacketInterval(); - } - } -/* Insure a meaningful keepalive interval has been set. Otherwise, too - many keepalive packets will drain network performance. */ + port->port_connect_timeout = pb && pb->find(isc_dpb_connect_timeout) ? + pb->getInt() : Config::getConnectionTimeout(); + port->port_flags |= PORT_dummy_pckt_set; + port->port_dummy_packet_interval = Config::getDummyPacketInterval(); if (port->port_dummy_packet_interval < 0) port->port_dummy_packet_interval = DUMMY_INTERVAL; port->port_dummy_timeout = port->port_dummy_packet_interval; + #ifdef DEBUG printf("REMOTE_get_timeout dummy = %lu conn = %lu\n", port->port_dummy_packet_interval, port->port_connect_timeout); @@ -776,29 +693,6 @@ static void cleanup_memory( void *block) } -static SLONG get_parameter(const UCHAR** ptr) -{ -/************************************** - * - * g e t _ p a r a m e t e r - * - ************************************** - * - * Functional description - * Pick up a VAX format parameter from a parameter block, including the - * length byte. - * This is a clone of jrd/jrd.c:get_parameter() - * - **************************************/ - const SSHORT l = *(*ptr)++; - const SLONG parameter = gds__vax_integer(*ptr, l); - *ptr += l; - - return parameter; -} - - - // TMN: Beginning of C++ port - ugly but a start int rem_port::accept(p_cnct* cnct) diff --git a/src/remote/server.cpp b/src/remote/server.cpp index dc4f011c5b..5ac365f2e6 100644 --- a/src/remote/server.cpp +++ b/src/remote/server.cpp @@ -848,7 +848,6 @@ static void addClumplets(Firebird::ClumpletWriter& dpb_buffer, * * Functional description * Insert remote endpoint data into DPB address stack - * If configured, insert remote_attachment into dpb * **************************************/ Firebird::ClumpletWriter address_stack_buffer(Firebird::ClumpletReader::UnTagged, MAX_UCHAR - 2); @@ -1028,12 +1027,12 @@ static void attach_database2(rem_port* port, dpb_buffer.deleteWithTag(isc_dpb_gsec_attach); dpb_buffer.deleteWithTag(isc_dpb_sec_attach); - dpb = dpb_buffer.getBuffer(); - dl = dpb_buffer.getBufferLength(); - /* See if user has specified parameters relevant to the connection, they will be stuffed in the DPB if so. */ - REMOTE_get_timeout_params(port, dpb, dl); + REMOTE_get_timeout_params(port, &dpb_buffer); + + dpb = dpb_buffer.getBuffer(); + dl = dpb_buffer.getBufferLength(); THREAD_EXIT(); if (operation == op_attach) @@ -4948,7 +4947,7 @@ ISC_STATUS rem_port::service_attach(const char* service_name, /* See if user has specified parameters relevent to the connection, they will be stuffed in the SPB if so. */ - REMOTE_get_timeout_params(this, spb.getBuffer(), spb.getBufferLength()); + REMOTE_get_timeout_params(this, &spb); THREAD_EXIT(); ISC_STATUS_ARRAY status_vector;