mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 17:23:03 +01:00
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.
This commit is contained in:
parent
554f01ab4f
commit
00c63c1f8d
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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++
|
||||
|
||||
|
@ -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
|
||||
|
@ -43,6 +43,9 @@
|
||||
#include "../common/classes/init.h"
|
||||
#include "../jrd/constants.h"
|
||||
|
||||
#ifdef WIN_NT
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#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
|
||||
|
@ -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
|
||||
|
@ -25,10 +25,7 @@
|
||||
|
||||
#include "../jrd/common.h"
|
||||
#include "../dsql/dsql.h"
|
||||
|
||||
namespace Dsql {
|
||||
enum nod_t;
|
||||
}
|
||||
#include "../dsql/node.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
|
@ -301,8 +301,8 @@ public:
|
||||
SSHORT udf_character_set_id;
|
||||
USHORT udf_character_length;
|
||||
USHORT udf_flags;
|
||||
Firebird::Array<dsc> udf_arguments;
|
||||
Firebird::MetaName udf_name;
|
||||
Firebird::Array<dsc> 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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
/**************************************
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 <sys/types.h>
|
||||
#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 <sys/param.h>
|
||||
@ -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 += '/';
|
||||
}
|
||||
|
||||
|
181
src/jrd/jrd.cpp
181
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,
|
||||
|
@ -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 <direct.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#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 */
|
||||
|
||||
|
@ -88,7 +88,7 @@ public:
|
||||
private:
|
||||
static const UCHAR PWD_REQUEST[256];
|
||||
static const UCHAR TPB[4];
|
||||
|
||||
|
||||
Firebird::Mutex mutex;
|
||||
|
||||
ISC_STATUS_ARRAY status;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <windows.h>
|
||||
#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;
|
||||
|
||||
|
@ -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<FailedLogin,
|
||||
|
@ -440,8 +440,8 @@ RELATION(nam_mon_rec_stats, rel_mon_rec_stats, ODS_11_1, rel_virtual)
|
||||
FIELD(f_mon_rec_expunges, nam_mon_rec_expunges, fld_counter, 0, 0, 0, 0)
|
||||
END_RELATION
|
||||
RELATION(nam_mon_ctx_vars, rel_mon_ctx_vars, ODS_11_2, rel_virtual)
|
||||
FIELD(f_mon_ctx_vars_att_id, nam_mon_att_id, fld_att_id, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_vars_tra_id, nam_mon_tra_id, fld_trans_id, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_vars_name, nam_mon_var_name, fld_ctx_var_name, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_vars_value, nam_mon_var_value, fld_ctx_var_value, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_var_att_id, nam_mon_att_id, fld_att_id, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_var_tra_id, nam_mon_tra_id, fld_trans_id, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_var_name, nam_mon_var_name, fld_ctx_var_name, 0, 0, 0, 0)
|
||||
FIELD(f_mon_ctx_var_value, nam_mon_var_value, fld_ctx_var_value, 0, 0, 0, 0)
|
||||
END_RELATION
|
||||
|
@ -100,8 +100,8 @@ public:
|
||||
tra_blobs(p),
|
||||
tra_resources(*p),
|
||||
tra_context_vars(*p),
|
||||
tra_open_cursors(*p),
|
||||
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT)
|
||||
tra_lock_timeout(DEFAULT_LOCK_TIMEOUT),
|
||||
tra_open_cursors(*p)
|
||||
{}
|
||||
|
||||
~jrd_tra()
|
||||
|
551
src/jrd/why.cpp
551
src/jrd/why.cpp
@ -88,20 +88,14 @@
|
||||
#include "../common/classes/rwlock.h"
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/classes/init.h"
|
||||
#include "../common/classes/semaphore.h"
|
||||
#include "../jrd/constants.h"
|
||||
#include "../jrd/thread_proto.h"
|
||||
#include "../jrd/ThreadStart.h"
|
||||
#ifdef SCROLLABLE_CURSORS
|
||||
#include "../jrd/blr.h"
|
||||
#endif
|
||||
|
||||
#if !defined(SUPERCLIENT)
|
||||
#define CANCEL_disable 1
|
||||
#define CANCEL_enable 2
|
||||
#define CANCEL_raise 3
|
||||
//extern "C" ISC_STATUS jrd8_cancel_operation(ISC_STATUS *, Jrd::Attachment**, USHORT);
|
||||
void JRD_shutdown_all(bool);
|
||||
void JRD_shutdown_attachment(Jrd::Attachment**, Jrd::Attachment**);
|
||||
#endif
|
||||
|
||||
using namespace YValve;
|
||||
|
||||
// In 2.0 it's hard to include ibase.h in why.cpp due to API declaration conflicts.
|
||||
@ -166,7 +160,7 @@ inline void nullCheck(const FB_API_HANDLE* ptr, ISC_STATUS code)
|
||||
{
|
||||
// this function is called for incoming API handlers,
|
||||
// proposed to be created by the call
|
||||
if (*ptr)
|
||||
if ((!ptr) || (*ptr))
|
||||
{
|
||||
bad_handle(code);
|
||||
}
|
||||
@ -207,7 +201,56 @@ namespace
|
||||
Firebird::GlobalPtr<Firebird::RWLock> handleMappingLock;
|
||||
|
||||
Firebird::InitInstance<Firebird::SortedArray<Attachment*> > attachments;
|
||||
Firebird::GlobalPtr<Firebird::Mutex> attachmentsMutex;
|
||||
Firebird::GlobalPtr<Firebird::Mutex> 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 <typename Array>
|
||||
void markHandlesShutdown(Array handles)
|
||||
Firebird::GlobalPtr<Firebird::SignalSafeSemaphore> 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> 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<Jrd::Attachment*, 2> 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<Attachment>(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; n<SUBSYSTEMS; ++n)
|
||||
{
|
||||
PTR entry = get_entrypoint(PROC_SHUTDOWN, n);
|
||||
if (entry != no_entrypoint)
|
||||
{
|
||||
if (entry(status) != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown clients after providers
|
||||
if (ShutChain::run(FB_SHUT_POSTPROVIDERS) == 0)
|
||||
{
|
||||
// All clients are ready to exit
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Firebird::Exception& e)
|
||||
{
|
||||
e.stuff_exception(status);
|
||||
}
|
||||
|
||||
return status[1];
|
||||
}
|
||||
|
||||
|
||||
ISC_STATUS API_ROUTINE fb__shutdown_callback(ISC_STATUS * user_status, FPTR_INT callBack, const int mask)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* f b _ s h u t d o w n _ c a l l b a c k
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Register client callback to be called when FB is going down.
|
||||
*
|
||||
**************************************/
|
||||
YEntry status(user_status);
|
||||
try
|
||||
{
|
||||
ShutChain::add(callBack, mask);
|
||||
}
|
||||
catch (const Firebird::Exception& e)
|
||||
{
|
||||
e.stuff_exception(status);
|
||||
}
|
||||
|
||||
return status[1];
|
||||
}
|
||||
|
@ -255,6 +255,11 @@ SLONG API_ROUTINE isc_reset_fpe(USHORT);
|
||||
#define CANCEL_enable 2
|
||||
#define CANCEL_raise 3
|
||||
ISC_STATUS API_ROUTINE gds__cancel_operation(ISC_STATUS*, FB_API_HANDLE*, USHORT);
|
||||
ISC_STATUS API_ROUTINE gds__handle_cleanup(ISC_STATUS*, FB_API_HANDLE*);
|
||||
ISC_STATUS API_ROUTINE fb__shutdown(ISC_STATUS* user_status);
|
||||
const int FB_SHUT_PREPROVIDERS = 1;
|
||||
const int FB_SHUT_POSTPROVIDERS = 2;
|
||||
ISC_STATUS API_ROUTINE fb__shutdown_callback(ISC_STATUS* user_status, FPTR_INT callBack, const int mask);
|
||||
|
||||
typedef void AttachmentCleanupRoutine(FB_API_HANDLE*, void*);
|
||||
typedef void TransactionCleanupRoutine(FB_API_HANDLE, void*);
|
||||
@ -264,8 +269,6 @@ ISC_STATUS API_ROUTINE isc_database_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
||||
int API_ROUTINE gds__disable_subsystem(TEXT*);
|
||||
int API_ROUTINE gds__enable_subsystem(TEXT*);
|
||||
|
||||
ISC_STATUS gds__handle_cleanup(ISC_STATUS*, FB_API_HANDLE*);
|
||||
|
||||
#define INTL_FUNCTION_CHAR_LENGTH 1
|
||||
#define INTL_FUNCTION_CONV_TO_METADATA 2
|
||||
ISC_STATUS API_ROUTINE gds__intl_function(ISC_STATUS*, FB_API_HANDLE*, USHORT, UCHAR, USHORT, const UCHAR*, void*);
|
||||
|
@ -130,11 +130,11 @@ namespace YValve
|
||||
public:
|
||||
static BaseHandle* translate(FB_API_HANDLE);
|
||||
Jrd::Attachment* getAttachmentHandle();
|
||||
void cancel();
|
||||
~BaseHandle();
|
||||
|
||||
// required to put pointers to it into the tree
|
||||
static const FB_API_HANDLE& generate(const void* sender, BaseHandle* value) {
|
||||
static const FB_API_HANDLE& generate(const void* sender, BaseHandle* value)
|
||||
{
|
||||
return value->public_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<AttachmentCleanupRoutine, FB_API_HANDLE*> cleanup;
|
||||
StoredAtt* handle;
|
||||
Firebird::PathName db_path;
|
||||
@ -211,7 +214,6 @@ namespace YValve
|
||||
|
||||
public:
|
||||
Attachment(StoredAtt*, FB_API_HANDLE*, USHORT);
|
||||
void cancel2();
|
||||
~Attachment();
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
#include <setjmp.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 <sys/param.h>
|
||||
//#include "../jrd/os/isc_i_proto.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
@ -69,15 +71,12 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUPERSERVER
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include "../jrd/ibase.h"
|
||||
#include "../jrd/jrd_pwd.h"
|
||||
#endif
|
||||
|
||||
#include "../remote/remote.h"
|
||||
#include "../jrd/license.h"
|
||||
@ -103,11 +102,7 @@
|
||||
#include <sys/resource.h>
|
||||
#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<Firebird::SignalSafeSemaphore> shutSem;
|
||||
static Firebird::GlobalPtr<Firebird::Semaphore> 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
|
||||
|
@ -86,9 +86,6 @@
|
||||
|
||||
#ifdef WIN_NT
|
||||
#define sleep(seconds) Sleep ((seconds) * 1000)
|
||||
|
||||
#include <direct.h> // 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<const UCHAR*>(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<const UCHAR*>(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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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*);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user