summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD/SETUP.sh18
-rw-r--r--BitKeeper/etc/logging_ok1
-rw-r--r--client/mysql.cc17
-rw-r--r--client/mysqltest.c6
-rw-r--r--configure.in14
-rw-r--r--include/config-win.h8
-rw-r--r--include/my_global.h14
-rw-r--r--include/mysql_version.h.in1
-rw-r--r--include/thr_alarm.h2
-rw-r--r--innobase/include/os0file.h7
-rw-r--r--innobase/include/os0sync.h41
-rw-r--r--innobase/include/os0thread.h7
-rw-r--r--innobase/include/srv0srv.h6
-rw-r--r--innobase/include/srv0start.h7
-rw-r--r--innobase/include/univ.i4
-rw-r--r--innobase/log/log0log.c27
-rw-r--r--innobase/os/os0file.c82
-rw-r--r--innobase/os/os0sync.c148
-rw-r--r--innobase/os/os0thread.c31
-rw-r--r--innobase/row/row0ins.c5
-rw-r--r--innobase/srv/srv0srv.c74
-rw-r--r--innobase/srv/srv0start.c95
-rw-r--r--innobase/sync/sync0sync.c27
-rw-r--r--innobase/ut/ut0mem.c2
-rw-r--r--libmysql/libmysql.c2
-rw-r--r--man/mysql_fix_privilege_tables.17
-rw-r--r--mysql-test/mysql-test-run.sh14
-rw-r--r--mysql-test/r/alter_table.result5
-rw-r--r--mysql-test/r/errors.result (renamed from mysql-test/r/err000001.result)0
-rw-r--r--mysql-test/r/have_mest_timezone.require2
-rw-r--r--mysql-test/r/insert_select.result12
-rw-r--r--mysql-test/r/loaddata.result7
-rw-r--r--mysql-test/r/lowercase_table.result12
-rw-r--r--mysql-test/r/query_cache.result60
-rw-r--r--mysql-test/r/rpl_insert_id.result30
-rw-r--r--mysql-test/r/timezone.result25
-rw-r--r--mysql-test/t/alter_table.test9
-rw-r--r--mysql-test/t/errors.test (renamed from mysql-test/t/err000001.test)0
-rw-r--r--mysql-test/t/insert_select.test17
-rw-r--r--mysql-test/t/loaddata.test8
-rw-r--r--mysql-test/t/lowercase_table.test11
-rw-r--r--mysql-test/t/query_cache.test35
-rw-r--r--mysql-test/t/raid.test2
-rw-r--r--mysql-test/t/rpl_insert_id.test23
-rw-r--r--mysql-test/t/rpl_log.test24
-rw-r--r--mysql-test/t/timezone-master.opt1
-rw-r--r--mysql-test/t/timezone.test28
-rw-r--r--mysys/default.c29
-rw-r--r--mysys/thr_alarm.c107
-rw-r--r--sql/field.cc3
-rw-r--r--sql/log.cc51
-rw-r--r--sql/mysql_priv.h4
-rw-r--r--sql/mysqld.cc52
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/slave.cc27
-rw-r--r--sql/sql_cache.cc16
-rw-r--r--sql/sql_insert.cc24
-rw-r--r--sql/sql_table.cc133
-rw-r--r--sql/sql_update.cc1
-rw-r--r--sql/sql_yacc.yy3
-rw-r--r--sql/time.cc56
61 files changed, 1150 insertions, 336 deletions
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index 4a19c490e5d..4d41f514704 100644
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -71,6 +71,22 @@ else
make=make
fi
-if test -z $CXX ; then
+if test -z "$CXX" ; then
CXX=gcc
fi
+
+# If ccache (a compiler cache which reduces build time)
+# (http://samba.org/ccache) is installed, use it.
+# We use 'grep' and hope 'grep' will work as expected
+# (returns 0 if finds lines)
+if ccache -V > /dev/null 2>&1
+then
+ if ! (echo "$CC" | grep "ccache" > /dev/null)
+ then
+ CC="ccache $CC"
+ fi
+ if ! (echo "$CXX" | grep "ccache" > /dev/null)
+ then
+ CXX="ccache $CXX"
+ fi
+fi
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 065b2aee15b..41337a66cdd 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -39,6 +39,7 @@ jani@hynda.mysql.fi
jani@janikt.pp.saunalahti.fi
jani@rhols221.adsl.netsonic.fi
jani@rhols221.arenanet.fi
+jani@ua126d19.elisa.omakaista.fi
jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@mugatu.spaceapes.com
diff --git a/client/mysql.cc b/client/mysql.cc
index c8fed137344..6090e8aa970 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -44,7 +44,7 @@
#include <locale.h>
#endif
-const char *VER= "14.0";
+const char *VER= "14.1";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -2929,14 +2929,18 @@ static const char* construct_prompt()
add_int_to_prompt(++prompt_counter);
break;
case 'v':
- processed_prompt.append(mysql_get_server_info(&mysql));
+ if (connected)
+ processed_prompt.append(mysql_get_server_info(&mysql));
+ else
+ processed_prompt.append("not_connected");
break;
case 'd':
processed_prompt.append(current_db ? current_db : "(none)");
break;
case 'h':
{
- const char *prompt=mysql_get_host_info(&mysql);
+ const char *prompt;
+ prompt= connected ? mysql_get_host_info(&mysql) : "not_connected";
if (strstr(prompt, "Localhost"))
processed_prompt.append("localhost");
else
@@ -2948,8 +2952,13 @@ static const char* construct_prompt()
}
case 'p':
#ifndef EMBEDDED_LIBRARY
+ if (!connected)
+ {
+ processed_prompt.append("not_connected");
+ break;
+ }
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") ||
- ! mysql.unix_socket)
+ !mysql.unix_socket)
add_int_to_prompt(mysql.port);
else
{
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 84ff41d73a6..517c41c2b18 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -523,8 +523,12 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS);
- if (!eval_result && stat_info.st_size != ds->length)
+ if (!eval_result && (uint) stat_info.st_size != ds->length)
+ {
+ DBUG_PRINT("info",("Size differs: result size: %u file size: %u",
+ ds->length, stat_info.st_size));
DBUG_RETURN(2);
+ }
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS);
diff --git a/configure.in b/configure.in
index 63286db74c5..7ad34b39b6b 100644
--- a/configure.in
+++ b/configure.in
@@ -359,7 +359,7 @@ then
# we will gets some problems when linking static programs.
# The following code is used to fix this problem.
- if test "$CXX" = "gcc"
+ if test "$CXX" = "gcc" -o "$CXX" = "ccache gcc"
then
if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1
then
@@ -1023,8 +1023,16 @@ case $SYSTEM_TYPE in
;;
*freebsd*)
echo "Adding fix for interrupted reads"
- CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
- CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
+ OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
+ if test "$OSVERSION" -gt "480100" && \
+ test "$OSVERSION" -lt "500000" || \
+ test "$OSVERSION" -gt "500109"
+ then
+ CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
+ else
+ CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
+ CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
+ fi
;;
*netbsd*)
echo "Adding flag -Dunix"
diff --git a/include/config-win.h b/include/config-win.h
index b0a30353196..7b7096df66f 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -138,6 +138,11 @@ typedef uint rf_SetTimer;
#define SIZEOF_LONG 4
#define SIZEOF_LONG_LONG 8
#define SIZEOF_OFF_T 8
+#ifdef _WIN64
+#define SIZEOF_CHARP 8
+#else
+#define SIZEOF_CHARP 4
+#endif
#define HAVE_BROKEN_NETINET_INCLUDES
#ifdef __NT__
#define HAVE_NAMED_PIPE /* We can only create pipes on NT */
@@ -203,6 +208,7 @@ inline double ulonglong2double(ulonglong value)
/* Optimized store functions for Intel x86 */
+#ifndef _WIN64
#define sint2korr(A) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
@@ -243,7 +249,7 @@ inline double ulonglong2double(ulonglong value)
#define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
#define float8store(V,M) doublestore((V),(M))
-
+#endif /* _WIN64 */
#define HAVE_PERROR
#define HAVE_VFPRINT
diff --git a/include/my_global.h b/include/my_global.h
index 86fb2a5ee4d..6d6f24c2438 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -266,7 +266,7 @@ C_MODE_END
# endif
#endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_UNISTD_H
-#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT)
+#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
#define crypt unistd_crypt
#endif
#include <unistd.h>
@@ -654,7 +654,15 @@ extern double my_atof(const char*);
Max size that must be added to a so that we know Size to make
adressable obj.
*/
+#if SIZEOF_CHARP == 4
typedef long my_ptrdiff_t;
+#else
+typedef long long my_ptrdiff_t;
+#endif
+
+/* typedef used for length of string; Should be unsigned! */
+typedef ulong size_str;
+
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
/* Size to make adressable obj. */
@@ -869,7 +877,7 @@ typedef char bool; /* Ordinary boolean values 0 1 */
*/
/* Optimized store functions for Intel x86 */
-#ifdef __i386__
+#if defined(__i386__) && !defined(_WIN64)
#define sint2korr(A) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \
diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in
index 793bf36e9fe..da184665f6e 100644
--- a/include/mysql_version.h.in
+++ b/include/mysql_version.h.in
@@ -10,6 +10,7 @@
#else
#define PROTOCOL_VERSION @PROTOCOL_VERSION@
#define MYSQL_SERVER_VERSION "@VERSION@"
+#define MYSQL_BASE_VERSION "mysqld-@MYSQL_BASE_VERSION@"
#ifndef MYSQL_SERVER_SUFFIX
#define MYSQL_SERVER_SUFFIX "@MYSQL_SERVER_SUFFIX@"
#endif
diff --git a/include/thr_alarm.h b/include/thr_alarm.h
index 30825d49158..439f046252f 100644
--- a/include/thr_alarm.h
+++ b/include/thr_alarm.h
@@ -103,7 +103,7 @@ void init_thr_alarm(uint max_alarm);
bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
void thr_alarm_kill(pthread_t thread_id);
void thr_end_alarm(thr_alarm_t *alarmed);
-void end_thr_alarm(void);
+void end_thr_alarm(my_bool free_structures);
sig_handler process_alarm(int);
#ifndef thr_got_alarm
bool thr_got_alarm(thr_alarm_t *alrm);
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index a7624a90d5e..86f27a2d3eb 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -301,6 +301,13 @@ os_aio(
are ignored */
void* message2);
/****************************************************************************
+Wakes up all async i/o threads so that they know to exit themselves in
+shutdown. */
+
+void
+os_aio_wake_all_threads_at_shutdown(void);
+/*=====================================*/
+/****************************************************************************
Waits until there are no pending writes in os_aio_write_array. There can
be other, synchronous, pending writes. */
diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h
index b2d613c4619..bad8e6e120a 100644
--- a/innobase/include/os0sync.h
+++ b/innobase/include/os0sync.h
@@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri
#define os0sync_h
#include "univ.i"
+#include "ut0lst.h"
#ifdef __WIN__
-
#define os_fast_mutex_t CRITICAL_SECTION
-typedef void* os_event_t;
-
+typedef HANDLE os_event_t;
#else
-
typedef pthread_mutex_t os_fast_mutex_t;
+
+typedef struct os_event_struct os_event_struct_t;
+typedef os_event_struct_t* os_event_t;
struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */
@@ -26,9 +27,9 @@ struct os_event_struct {
not reserved */
pthread_cond_t cond_var; /* condition variable is used in
waiting for the event */
+ UT_LIST_NODE_T(os_event_struct_t) os_event_list;
+ /* list of all created events */
};
-typedef struct os_event_struct os_event_struct_t;
-typedef os_event_struct_t* os_event_t;
#endif
typedef struct os_mutex_struct os_mutex_str_t;
@@ -38,6 +39,29 @@ typedef os_mutex_str_t* os_mutex_t;
#define OS_SYNC_TIME_EXCEEDED 1
+/* Mutex protecting the thread count and event and OS 'slow' mutex lists */
+extern os_mutex_t os_sync_mutex;
+
+/* This is incremented by 1 in os_thread_create and decremented by 1 in
+os_thread_exit */
+extern ulint os_thread_count;
+
+/* The following are approximate counters for debugging in Unix */
+extern ulint os_event_count;
+extern ulint os_mutex_count;
+
+/*************************************************************
+Initializes global event and OS 'slow' mutex lists. */
+
+void
+os_sync_init(void);
+/*==============*/
+/*************************************************************
+Frees created events (not in Windows) and OS 'slow' mutexes. */
+
+void
+os_sync_free(void);
+/*==============*/
/*************************************************************
Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled.
@@ -85,7 +109,10 @@ os_event_free(
/*==========*/
os_event_t event); /* in: event to free */
/**************************************************************
-Waits for an event object until it is in the signaled state. */
+Waits for an event object until it is in the signaled state. If
+srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
+waiting thread when the event becomes signaled (or immediately if the
+event is already in the signaled state). */
void
os_event_wait(
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 629cfef23a8..92187f315c2 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -41,7 +41,6 @@ typedef os_thread_t os_thread_id_t; /* In Unix we use the thread
the thread */
#endif
-
/* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*);
@@ -83,12 +82,13 @@ os_thread_create(
os_thread_id_t* thread_id); /* out: id of the created
thread */
/*********************************************************************
-A thread calling this function ends its execution. */
+Exits the current thread. */
void
os_thread_exit(
/*===========*/
- ulint code); /* in: exit code */
+ void* exit_value); /* in: exit value; in Windows this void*
+ is cast as a DWORD */
/*********************************************************************
Returns the thread identifier of current thread. */
@@ -144,7 +144,6 @@ ulint
os_thread_get_last_error(void);
/*==========================*/
-
#ifndef UNIV_NONINL
#include "os0thread.ic"
#endif
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 121e9c44a24..8fd0fc2dd6d 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -212,6 +212,12 @@ void
srv_init(void);
/*==========*/
/*************************************************************************
+Frees the OS fast mutex created in srv_init(). */
+
+void
+srv_free(void);
+/*==========*/
+/*************************************************************************
Initializes the synchronization primitives, memory system, and the thread
local storage. */
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index aec3ebfeea9..8d2c3fa12c5 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down;
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP
-and then to SRV_SHUTDOWN_LAST_PHASE */
+and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
extern ulint srv_shutdown_state;
-#define SRV_SHUTDOWN_CLEANUP 1
-#define SRV_SHUTDOWN_LAST_PHASE 2
+#define SRV_SHUTDOWN_CLEANUP 1
+#define SRV_SHUTDOWN_LAST_PHASE 2
+#define SRV_SHUTDOWN_EXIT_THREADS 3
#endif
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index e29f3ec92e1..4854e5a7b78 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -187,7 +187,11 @@ management to ensure correct alignment for doubles etc. */
/* Another basic type we use is unsigned long integer which is intended to be
equal to the word size of the machine. */
+#ifdef _WIN64
+typedef unsigned __int64 ulint;
+#else
typedef unsigned long int ulint;
+#endif
typedef long int lint;
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index e717d897e41..6892e6fc6c1 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -375,7 +375,7 @@ log_pad_current_log_block(void)
log_close();
log_release();
- ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
+ ut_ad((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
== LOG_BLOCK_HDR_SIZE);
}
@@ -998,6 +998,8 @@ log_group_file_header_flush(
{
byte* buf;
ulint dest_offset;
+
+ UT_NOT_USED(type);
ut_ad(mutex_own(&(log_sys->mutex)));
@@ -1068,8 +1070,8 @@ log_group_write_buf(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
- ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
if (new_data_offset == 0) {
write_header = TRUE;
@@ -2901,10 +2903,9 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn;
ulint arch_log_no;
- if (srv_print_verbose_log)
- {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Starting shutdown...\n");
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Starting shutdown...\n");
}
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
@@ -3006,15 +3007,17 @@ loop:
goto loop;
}
+ /* Make some checks that the server really is quiet */
+ ut_a(buf_all_freed());
+ ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
+
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
fil_flush_file_spaces(FIL_TABLESPACE);
- if (srv_print_verbose_log)
- {
- ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB: Shutdown completed\n");
- }
+ /* Make some checks that the server really is quiet */
+ ut_a(buf_all_freed());
+ ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
/**********************************************************
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 53224eb59c5..9da5c6a47a5 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -295,7 +295,8 @@ os_file_handle_error(
/* out: TRUE if we should retry the
operation */
os_file_t file, /* in: file pointer */
- char* name) /* in: name of a file or NULL */
+ char* name, /* in: name of a file or NULL */
+ const char* operation) /* in: type of operation */
{
ulint err;
@@ -337,7 +338,8 @@ os_file_handle_error(
if (name) {
fprintf(stderr, "InnoDB: File name %s\n", name);
}
-
+ fprintf(stderr, "InnoDB: system call %s\n", operation);
+
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
fflush(stderr);
@@ -419,7 +421,9 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
@@ -460,7 +464,10 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
+
if (retry) {
goto try_again;
@@ -568,7 +575,9 @@ try_again:
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
@@ -615,7 +624,9 @@ try_again:
if (file == -1) {
*success = FALSE;
- retry = os_file_handle_error(file, name);
+ retry = os_file_handle_error(file, name,
+ create_mode == OS_FILE_OPEN ?
+ "open" : "create");
if (retry) {
goto try_again;
@@ -649,7 +660,7 @@ os_file_close(
return(TRUE);
}
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "close");
return(FALSE);
#else
int ret;
@@ -657,7 +668,7 @@ os_file_close(
ret = close(file);
if (ret == -1) {
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "close");
return(FALSE);
}
@@ -825,7 +836,7 @@ os_file_flush(
return(TRUE);
}
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
@@ -858,7 +869,7 @@ os_file_flush(
fprintf(stderr,
" InnoDB: Error: the OS said file flush did not succeed\n");
- os_file_handle_error(file, NULL);
+ os_file_handle_error(file, NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
@@ -1099,7 +1110,7 @@ try_again:
#ifdef __WIN__
error_handling:
#endif
- retry = os_file_handle_error(file, NULL);
+ retry = os_file_handle_error(file, NULL, "read");
if (retry) {
goto try_again;
@@ -1295,7 +1306,6 @@ os_aio_array_create(
#endif
ut_a(n > 0);
ut_a(n_segments > 0);
- ut_a(n % n_segments == 0);
array = ut_malloc(sizeof(os_aio_array_t));
@@ -1404,6 +1414,50 @@ os_aio_init(
pthread_sigmask(SIG_BLOCK, &sigset, NULL); */
#endif
}
+
+#ifdef WIN_ASYNC_IO
+/****************************************************************************
+Wakes up all async i/o threads in the array in Windows async i/o at
+shutdown. */
+static
+void
+os_aio_array_wake_win_aio_at_shutdown(
+/*==================================*/
+ os_aio_array_t* array) /* in: aio array */
+{
+ ulint i;
+
+ for (i = 0; i < array->n_slots; i++) {
+
+ os_event_set(*(array->events + i));
+ }
+}
+#endif
+
+/****************************************************************************
+Wakes up all async i/o threads so that they know to exit themselves in
+shutdown. */
+
+void
+os_aio_wake_all_threads_at_shutdown(void)
+/*=====================================*/
+{
+ ulint i;
+
+#ifdef WIN_ASYNC_IO
+ /* This code wakes up all ai/o threads in Windows native aio */
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
+ os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
+#endif
+ /* This loop wakes up all simulated ai/o threads */
+
+ for (i = 0; i < os_aio_n_segments; i++) {
+
+ os_event_set(os_aio_segment_wait_events[i]);
+ }
+}
/****************************************************************************
Waits until there are no pending writes in os_aio_write_array. There can
@@ -1971,7 +2025,7 @@ try_again:
os_aio_array_free_slot(array, slot);
- retry = os_file_handle_error(file, name);
+ retry = os_file_handle_error(file, name, "aio");
if (retry) {
@@ -2070,7 +2124,7 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file));
}
} else {
- os_file_handle_error(slot->file, slot->name);
+ os_file_handle_error(slot->file, slot->name, "aio");
ret_val = FALSE;
}
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 407b280f805..4f322ee82b2 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -17,6 +17,7 @@ Created 9/6/1995 Heikki Tuuri
#endif
#include "ut0mem.h"
+#include "srv0start.h"
/* Type definition for an operating system mutex struct */
struct os_mutex_struct{
@@ -26,9 +27,75 @@ struct os_mutex_struct{
recursively lock the mutex: we
do not assume that the OS mutex
supports recursive locking, though
- NT seems to do that */
+ NT seems to do that */
+ UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
+ /* list of all 'slow' OS mutexes created */
};
+/* Mutex protecting the thread count and the lists of OS mutexes
+and events */
+os_mutex_t os_sync_mutex;
+ibool os_sync_mutex_inited = FALSE;
+
+/* This is incremented by 1 in os_thread_create and decremented by 1 in
+os_thread_exit */
+ulint os_thread_count = 0;
+
+/* The list of all events created (not in Windows) */
+UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
+
+/* The list of all OS 'slow' mutexes */
+UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
+
+/* The following are approximate counters for debugging in Unix */
+ulint os_event_count = 0;
+ulint os_mutex_count = 0;
+
+
+/*************************************************************
+Initializes global event and OS 'slow' mutex lists. */
+
+void
+os_sync_init(void)
+/*==============*/
+{
+ UT_LIST_INIT(os_event_list);
+ UT_LIST_INIT(os_mutex_list);
+
+ os_sync_mutex = os_mutex_create(NULL);
+
+ os_sync_mutex_inited = TRUE;
+}
+
+/*************************************************************
+Frees created events (not in Windows) and OS 'slow' mutexes. */
+
+void
+os_sync_free(void)
+/*==============*/
+{
+ os_event_t event;
+ os_mutex_t mutex;
+
+ event = UT_LIST_GET_FIRST(os_event_list);
+
+ while (event) {
+
+ os_event_free(event);
+
+ event = UT_LIST_GET_FIRST(os_event_list);
+ }
+
+ mutex = UT_LIST_GET_FIRST(os_mutex_list);
+
+ while (mutex) {
+
+ os_mutex_free(mutex);
+
+ mutex = UT_LIST_GET_FIRST(os_mutex_list);
+ }
+}
+
/*************************************************************
Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled.
@@ -43,8 +110,8 @@ os_event_create(
the event is created without a name */
{
#ifdef __WIN__
- HANDLE event;
-
+ os_event_t event;
+
event = CreateEvent(NULL, /* No security attributes */
TRUE, /* Manual reset */
FALSE, /* Initial state nonsignaled */
@@ -75,6 +142,14 @@ os_event_create(
#endif
event->is_set = FALSE;
+ os_mutex_enter(os_sync_mutex);
+
+ UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
+
+ os_event_count++;
+
+ os_mutex_exit(os_sync_mutex);
+
return(event);
#endif
}
@@ -92,7 +167,7 @@ os_event_create_auto(
the event is created without a name */
{
#ifdef __WIN__
- HANDLE event;
+ os_event_t event;
event = CreateEvent(NULL, /* No security attributes */
FALSE, /* Auto-reset */
@@ -106,6 +181,8 @@ os_event_create_auto(
UT_NOT_USED(name);
+ ut_a(0);
+
return(NULL);
#endif
}
@@ -185,12 +262,23 @@ os_event_free(
os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
+ os_mutex_enter(os_sync_mutex);
+
+ UT_LIST_REMOVE(os_event_list, os_event_list, event);
+
+ os_event_count--;
+
+ os_mutex_exit(os_sync_mutex);
+
ut_free(event);
#endif
}
/**************************************************************
-Waits for an event object until it is in the signaled state. */
+Waits for an event object until it is in the signaled state. If
+srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
+waiting thread when the event becomes signaled (or immediately if the
+event is already in the signaled state). */
void
os_event_wait(
@@ -206,12 +294,20 @@ os_event_wait(
err = WaitForSingleObject(event, INFINITE);
ut_a(err == WAIT_OBJECT_0);
+
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ os_thread_exit(NULL);
+ }
#else
os_fast_mutex_lock(&(event->os_mutex));
loop:
if (event->is_set == TRUE) {
os_fast_mutex_unlock(&(event->os_mutex));
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+
+ os_thread_exit(NULL);
+ }
/* Ok, we may return */
return;
@@ -291,14 +387,17 @@ os_event_wait_multiple(
ut_a(event_array);
ut_a(n > 0);
- index = WaitForMultipleObjects(n,
- event_array,
+ index = WaitForMultipleObjects(n, event_array,
FALSE, /* Wait for any 1 event */
INFINITE); /* Infinite wait time
limit */
ut_a(index >= WAIT_OBJECT_0);
ut_a(index < WAIT_OBJECT_0 + n);
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ os_thread_exit(NULL);
+ }
+
return(index - WAIT_OBJECT_0);
#else
ut_a(n == 0);
@@ -337,6 +436,16 @@ os_mutex_create(
mutex_str->handle = mutex;
mutex_str->count = 0;
+ if (os_sync_mutex_inited) {
+ os_mutex_enter(os_sync_mutex);
+ }
+
+ UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
+
+ if (os_sync_mutex_inited) {
+ os_mutex_exit(os_sync_mutex);
+ }
+
return(mutex_str);
#else
os_fast_mutex_t* os_mutex;
@@ -353,6 +462,16 @@ os_mutex_create(
mutex_str->handle = os_mutex;
mutex_str->count = 0;
+ if (os_sync_mutex_inited) {
+ os_mutex_enter(os_sync_mutex);
+ }
+
+ UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
+
+ if (os_sync_mutex_inited) {
+ os_mutex_exit(os_sync_mutex);
+ }
+
return(mutex_str);
#endif
}
@@ -424,9 +543,22 @@ os_mutex_free(
#ifdef __WIN__
ut_a(mutex);
+ os_mutex_enter(os_sync_mutex);
+
+ UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
+
+ os_mutex_exit(os_sync_mutex);
+
ut_a(CloseHandle(mutex->handle));
+
ut_free(mutex);
#else
+ os_mutex_enter(os_sync_mutex);
+
+ UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
+
+ os_mutex_exit(os_sync_mutex);
+
os_fast_mutex_free(mutex->handle);
ut_free(mutex->handle);
ut_free(mutex);
@@ -451,6 +583,7 @@ os_fast_mutex_init(
#else
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif
+ os_mutex_count++;
#endif
}
@@ -498,5 +631,6 @@ os_fast_mutex_free(
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
ut_a(0 == pthread_mutex_destroy(fast_mutex));
+ os_mutex_count--;
#endif
}
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index b0076921e43..02ea2c227a7 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -1,6 +1,5 @@
/******************************************************
-The interface to the operating system
-process and thread control primitives
+The interface to the operating system thread control primitives
(c) 1995 Innobase Oy
@@ -17,6 +16,7 @@ Created 9/8/1995 Heikki Tuuri
#endif
#include "srv0srv.h"
+#include "os0sync.h"
/*******************************************************************
Compares two thread ids for equality. */
@@ -102,6 +102,10 @@ os_thread_create(
os_thread_t thread;
ulint win_thread_id;
+ os_mutex_enter(os_sync_mutex);
+ os_thread_count++;
+ os_mutex_exit(os_sync_mutex);
+
thread = CreateThread(NULL, /* no security attributes */
0, /* default size stack */
(LPTHREAD_START_ROUTINE)start_f,
@@ -144,6 +148,9 @@ os_thread_create(
exit(1);
}
#endif
+ os_mutex_enter(os_sync_mutex);
+ os_thread_count++;
+ os_mutex_exit(os_sync_mutex);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
@@ -171,6 +178,26 @@ os_thread_create(
}
/*********************************************************************
+Exits the current thread. */
+
+void
+os_thread_exit(
+/*===========*/
+ void* exit_value) /* in: exit value; in Windows this void*
+ is cast as a DWORD */
+{
+ os_mutex_enter(os_sync_mutex);
+ os_thread_count--;
+ os_mutex_exit(os_sync_mutex);
+
+#ifdef __WIN__
+ ExitThread((DWORD)exit_value);
+#else
+ pthread_exit(exit_value);
+#endif
+}
+
+/*********************************************************************
Returns handle to the current thread. */
os_thread_t
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 3af9e1b752b..e96c08a715b 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -1275,6 +1275,10 @@ row_ins_unique_report_err(
dtuple_t* entry, /* in: index entry to insert in the index */
dict_index_t* index) /* in: index */
{
+#ifdef notdefined
+ /* Disable reporting to test if the slowdown of REPLACE in 4.0.13 was
+ caused by this! */
+
char* buf = dict_unique_err_buf;
/* The foreign err mutex protects also dict_unique_err_buf */
@@ -1303,6 +1307,7 @@ row_ins_unique_report_err(
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
+#endif
}
/*******************************************************************
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 7cd831fe239..9353766248d 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -1705,76 +1705,33 @@ srv_init(void)
ut_a(conc_slot->event);
}
}
-
+
/*************************************************************************
-Initializes the synchronization primitives, memory system, and the thread
-local storage. */
+Frees the OS fast mutex created in srv_init(). */
void
-srv_general_init(void)
-/*==================*/
+srv_free(void)
+/*==========*/
{
- sync_init();
- mem_init(srv_mem_pool_size);
- thr_local_init();
+ os_fast_mutex_free(&srv_conc_mutex);
}
-
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
-/* NetWare requires some cleanup of mutexes */
-
/*************************************************************************
-Deinitializes the synchronization primitives, memory system, and the thread
+Initializes the synchronization primitives, memory system, and the thread
local storage. */
void
-srv_general_free(void)
+srv_general_init(void)
/*==================*/
{
- sync_close();
+ os_sync_init();
+ sync_init();
+ mem_init(srv_mem_pool_size);
+ thr_local_init();
}
-#endif /* __NETWARE__ */
-
/*======================= InnoDB Server FIFO queue =======================*/
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
-/* NetWare requires some cleanup of mutexes */
-
-/*************************************************************************
-Deinitializes the server. */
-
-void
-srv_free(void)
-/*==========*/
-{
- srv_conc_slot_t* conc_slot;
- srv_slot_t* slot;
- ulint i;
-
- for (i = 0; i < OS_THREAD_MAX_N; i++)
- {
- slot = srv_table_get_nth_slot(i);
- os_event_free(slot->event);
- }
-
- /* TODO: free(srv_sys->threads); */
-
- for (i = 0; i < OS_THREAD_MAX_N; i++)
- {
- slot = srv_mysql_table + i;
- os_event_free(slot->event);
- }
-
- /* TODO: free(srv_mysql_table); */
-
- for (i = 0; i < OS_THREAD_MAX_N; i++)
- {
- conc_slot = srv_conc_slots + i;
- os_event_free(conc_slot->event);
- }
-}
-#endif /* __NETWARE__ */
/*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads
@@ -2734,6 +2691,8 @@ loop:
srv_error_monitor_active = FALSE;
+ os_thread_exit(NULL);
+
#ifndef __WIN__
return(NULL);
#else
@@ -3173,6 +3132,13 @@ suspend_thread:
os_event_wait(event);
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+ /* This is only extra safety, the thread should exit
+ already when the event wait ends */
+
+ os_thread_exit(NULL);
+ }
+
/* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 536aa5b67e4..9a2bf72130b 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1481,9 +1481,7 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex);
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */
-#endif /* __NETWARE__ */
+ os_fast_mutex_free(&srv_os_test_mutex);
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
@@ -1509,6 +1507,8 @@ innobase_shutdown_for_mysql(void)
/*=============================*/
/* out: DB_SUCCESS or error code */
{
+ ulint i;
+
if (!srv_was_started) {
if (srv_is_being_started) {
ut_print_timestamp(stderr);
@@ -1521,7 +1521,7 @@ innobase_shutdown_for_mysql(void)
return(DB_SUCCESS);
}
- /* Flush buffer pool to disk, write the current lsn to
+ /* 1. Flush buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive */
logs_empty_and_mark_files_at_shutdown();
@@ -1533,30 +1533,77 @@ innobase_shutdown_for_mysql(void)
srv_conc_n_threads);
}
-#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- /*
- TODO: Fix this temporary solution
- We are having a race condition occure with io_handler_thread threads.
- When they yield in os_aio_simulated_handle during shutdown, this
- thread was able to free the memory early.
- */
- os_thread_yield();
+ /* 2. Make all threads created by InnoDB to exit */
+
+ srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
+
+ /* All threads end up waiting for certain events. Put those events
+ to the signaled state. Then the threads will exit themselves in
+ os_thread_event_wait(). */
+
+ for (i = 0; i < 1000; i++) {
+ /* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
+ HERE OR EARLIER */
+
+ /* 1. Let the lock timeout thread exit */
+ os_event_set(srv_lock_timeout_thread_event);
+
+ /* 2. srv error monitor thread exits automatically, no need
+ to do anything here */
+
+ /* 3. We wake the master thread so that it exits */
+ srv_wake_master_thread();
+
+ /* 4. Exit the i/o threads */
+
+ os_aio_wake_all_threads_at_shutdown();
+
+ os_mutex_enter(os_sync_mutex);
+
+ if (os_thread_count == 0) {
+ /* All the threads have exited or are just exiting;
+ NOTE that the threads may not have completed their
+ exit yet. Should we use pthread_join() to make sure
+ they have exited? Now we just sleep 0.1 seconds and
+ hope that is enough! */
+
+ os_mutex_exit(os_sync_mutex);
+
+ os_thread_sleep(100000);
+
+ break;
+ }
+
+ os_mutex_exit(os_sync_mutex);
+
+ os_thread_sleep(100000);
+ }
+
+ if (i == 1000) {
+ fprintf(stderr,
+"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n",
+ os_thread_count);
+ }
+
+ /* 3. Free all InnoDB's own mutexes */
+
+ sync_close();
+
+ /* 4. Free all OS synchronization primitives (in Windows currently
+ events are not freed) */
- /* TODO: Where should this be called? */
srv_free();
+ os_sync_free();
+
+ /* 5. Free all allocated memory (and the os_fast_mutex created in
+ ut0mem.c */
- /* TODO: Where should this be called? */
- srv_general_free();
-#endif
- /*
- TODO: We should exit the i/o-handler and other utility threads
- before freeing all memory. Now this can potentially cause a seg
- fault!
- */
-#if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
- /* NetWare requires this free */
ut_free_all_mem();
-#endif
+
+ if (srv_print_verbose_log) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB: Shutdown completed\n");
+ }
return((int) DB_SUCCESS);
}
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 20d68ba5a9f..32615ce88ac 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -235,8 +235,7 @@ mutex_create_func(
mutex->cline = cline;
/* Check that lock_word is aligned; this is important on Intel */
-
- ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0);
+ ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
/* NOTE! The very first mutexes are not put to the mutex list */
@@ -266,11 +265,14 @@ mutex_free(
ut_a(mutex_get_lock_word(mutex) == 0);
ut_a(mutex_get_waiters(mutex) == 0);
- mutex_enter(&mutex_list_mutex);
+ if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
- UT_LIST_REMOVE(list, mutex_list, mutex);
+ mutex_enter(&mutex_list_mutex);
- mutex_exit(&mutex_list_mutex);
+ UT_LIST_REMOVE(list, mutex_list, mutex);
+
+ mutex_exit(&mutex_list_mutex);
+ }
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
@@ -1230,13 +1232,26 @@ sync_init(void)
}
/**********************************************************************
-Frees the resources in synchronization data structures. */
+Frees the resources in InnoDB's own synchronization data structures. Use
+os_sync_free() after calling this. */
void
sync_close(void)
/*===========*/
{
+ mutex_t* mutex;
+
sync_array_free(sync_primary_wait_array);
+
+ mutex = UT_LIST_GET_FIRST(mutex_list);
+
+ while (mutex) {
+ mutex_free(mutex);
+ mutex = UT_LIST_GET_FIRST(mutex_list);
+ }
+
+ mutex_free(&mutex_list_mutex);
+ mutex_free(&sync_thread_mutex);
}
/***********************************************************************
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index 23deed0fa55..2609b8f5241 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -225,6 +225,8 @@ ut_free_all_mem(void)
os_fast_mutex_unlock(&ut_list_mutex);
ut_a(ut_total_allocated_memory == 0);
+
+ os_fast_mutex_free(&ut_list_mutex);
}
/**************************************************************************
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index c28ee6bbfed..118d8cdfd99 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -2066,7 +2066,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE);
bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
- strmov(UNIXaddr.sun_path, unix_socket);
+ strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
mysql->options.connect_timeout))
{
diff --git a/man/mysql_fix_privilege_tables.1 b/man/mysql_fix_privilege_tables.1
index bf4e0e15dfa..4ed81368098 100644
--- a/man/mysql_fix_privilege_tables.1
+++ b/man/mysql_fix_privilege_tables.1
@@ -2,7 +2,7 @@
.SH NAME
mysql_fix_privilege_tables \- Fixes MySQL privilege tables.
.SH SYNOPSIS
-mysql_fix_privilege_tables [options]
+mysql_fix_privilege_tables [mysql_root_password]
.SH DESCRIPTION
This scripts updates the mysql.user, mysql.db, mysql.host and the
mysql.func tables to MySQL 3.22.14 and above.
@@ -10,10 +10,9 @@ mysql.func tables to MySQL 3.22.14 and above.
This is needed if you want to use the new GRANT functions,
CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23
-If you get 'Access denied' errors, you should run this script again
-and give the MySQL root user password as an argument!
+If you get 'Access denied' errors, run the script again
+and give the MySQL root user password as an argument.
-For more information start the program with '--help'.
.SH "SEE ALSO"
mysql (1), mysqld (1)
.SH AUTHOR
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 81e3f866709..137e99f48b3 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -13,12 +13,15 @@ DB=test
DBPASSWD=
VERBOSE=""
USE_MANAGER=0
-TZ=GMT-3; export TZ # for UNIX_TIMESTAMP tests to work
+MY_TZ=GMT-3
+TZ=$MY_TZ; export TZ # for UNIX_TIMESTAMP tests to work
#++
# Program Definitions
#--
+LC_COLLATE=C
+export LC_COLLATE
PATH=/bin:/usr/bin:/usr/local/bin:/usr/bsd:/usr/X11R6/bin:/usr/openwin/bin:/usr/bin/X11:$PATH
MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master"
@@ -1163,9 +1166,18 @@ run_testcase ()
if [ -f $master_opt_file ] ;
then
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"`
+ case "$EXTRA_MASTER_OPT" in
+ --timezone=*)
+ TZ=`$ECHO "$EXTRA_MASTER_OPT" | $SED -e "s;--timezone=;;"`
+ export TZ
+ # Note that this must be set to space, not "" for test-reset to work
+ EXTRA_MASTER_OPT=" "
+ ;;
+ esac
stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master
+ TZ=$MY_TZ; export TZ
else
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ]
then
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index 7bd836acefd..02c392c964f 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -276,3 +276,8 @@ t1 0 a 1 a A 3 NULL NULL YES BTREE
t1 0 a 2 b A 300 NULL NULL YES BTREE
t1 1 b 1 b A 100 NULL NULL YES BTREE
drop table t1;
+CREATE TABLE t1 (i int(10), index(i) );
+ALTER TABLE t1 DISABLE KEYS;
+INSERT DELAYED INTO t1 VALUES(1),(2),(3);
+ALTER TABLE t1 ENABLE KEYS;
+drop table t1;
diff --git a/mysql-test/r/err000001.result b/mysql-test/r/errors.result
index d0011c8deb6..d0011c8deb6 100644
--- a/mysql-test/r/err000001.result
+++ b/mysql-test/r/errors.result
diff --git a/mysql-test/r/have_mest_timezone.require b/mysql-test/r/have_mest_timezone.require
new file mode 100644
index 00000000000..2a219f39b7e
--- /dev/null
+++ b/mysql-test/r/have_mest_timezone.require
@@ -0,0 +1,2 @@
+Variable_name Value
+timezone MEST
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index 3325995f2bd..4f6349f8f8b 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -65,3 +65,15 @@ INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS t1,t2;
+create table t1(a int, unique(a));
+insert into t1 values(2);
+create table t2(a int);
+insert into t2 values(1),(2);
+reset master;
+insert into t1 select * from t2;
+Duplicate entry '2' for key 1
+show binlog events;
+Log_name Pos Event_type Server_id Orig_log_pos Info
+master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
+master-bin.001 79 Query 1 79 use test; insert into t1 select * from t2
+drop table t1, t2;
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index 7b4802136f3..560c5b2567e 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -15,4 +15,11 @@ a b c d
0000-00-00 0000-00-00 0000-00-00 0000-00-00
2003-03-03 2003-03-03 2003-03-03 NULL
2003-03-03 2003-03-03 2003-03-03 NULL
+truncate table t1;
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+SELECT * from t1;
+a b c d
+NULL NULL 0000-00-00 0000-00-00
+NULL 0000-00-00 0000-00-00 0000-00-00
+NULL 2003-03-03 2003-03-03 NULL
drop table t1;
diff --git a/mysql-test/r/lowercase_table.result b/mysql-test/r/lowercase_table.result
index 1caaf317c96..d32228216b8 100644
--- a/mysql-test/r/lowercase_table.result
+++ b/mysql-test/r/lowercase_table.result
@@ -13,3 +13,15 @@ show tables like 't_';
Tables_in_test (t_)
t3
drop table t3;
+create table t1 (a int);
+select count(*) from T1;
+count(*)
+0
+select count(*) from t1;
+count(*)
+0
+select count(T1.a) from t1;
+Unknown table 'T1' in field list
+select count(bags.a) from t1 as Bags;
+Unknown table 'bags' in field list
+drop table t1;
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 4622bb231a2..9d0c105b6c0 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -502,6 +502,7 @@ drop table t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
+create table t1 (a int);
show global variables like "query_cache_min_res_unit";
Variable_name Value
query_cache_min_res_unit 4096
@@ -565,18 +566,57 @@ set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
-set GLOBAL query_cache_size=1100;
-set GLOBAL query_cache_size=1200;
-set GLOBAL query_cache_size=1300;
-set GLOBAL query_cache_size=1400;
-set GLOBAL query_cache_size=1500;
-set GLOBAL query_cache_size=1600;
-set GLOBAL query_cache_size=1700;
-set GLOBAL query_cache_size=1800;
-set GLOBAL query_cache_size=1900;
+select * from t1;
+a
+set GLOBAL query_cache_size=1024;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=10240;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=20480;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=40960;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 0
+select * from t1;
+a
+set GLOBAL query_cache_size=51200;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 51200
+select * from t1;
+a
+set GLOBAL query_cache_size=61440;
show global variables like "query_cache_size";
Variable_name Value
-query_cache_size 1024
+query_cache_size 61440
+select * from t1;
+a
+set GLOBAL query_cache_size=81920;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 81920
+select * from t1;
+a
+set GLOBAL query_cache_size=102400;
+show global variables like "query_cache_size";
+Variable_name Value
+query_cache_size 102400
+select * from t1;
+a
+drop table t1;
set GLOBAL query_cache_size=1048576;
create table t1 (i int not null);
create table t2 (i int not null);
diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result
index 82015bdf538..3d7a2a0dd75 100644
--- a/mysql-test/r/rpl_insert_id.result
+++ b/mysql-test/r/rpl_insert_id.result
@@ -22,10 +22,12 @@ drop table t1;
drop table t2;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
+SET FOREIGN_KEY_CHECKS=0;
insert into t1 values (10);
insert into t1 values (null),(null),(null);
insert into t2 values (5,0);
insert into t2 values (null,last_insert_id());
+SET FOREIGN_KEY_CHECKS=1;
select * from t1;
a
10
@@ -38,3 +40,31 @@ b c
6 11
drop table t1;
drop table t2;
+create table t1(a int auto_increment, key(a));
+create table t2(b int auto_increment, c int, key(b));
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 (c) select * from t1;
+select * from t2;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+select * from t1;
+a
+10
+11
+12
+13
+select * from t2;
+b c
+5 0
+6 10
+7 11
+8 12
+9 13
+drop table t1;
+drop table t2;
diff --git a/mysql-test/r/timezone.result b/mysql-test/r/timezone.result
new file mode 100644
index 00000000000..b82b39da262
--- /dev/null
+++ b/mysql-test/r/timezone.result
@@ -0,0 +1,25 @@
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (ts int);
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
+SELECT ts,from_unixtime(ts) FROM t1;
+ts from_unixtime(ts)
+1035673200 2002-10-27 01:00:00
+1035680400 2002-10-27 02:00:00
+1035684000 2002-10-27 03:00:00
+1035680400 2002-10-27 02:00:00
+1035673200 2002-10-27 01:00:00
+1035680400 2002-10-27 02:00:00
+1048986000 2003-03-30 03:00:00
+1048986000 2003-03-30 03:00:00
+1048989599 2003-03-30 03:59:59
+1048989601 2003-03-30 04:00:01
+DROP TABLE t1;
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index fc22bc85aee..04229bd1882 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -135,3 +135,12 @@ analyze table t1;
show keys from t1;
drop table t1;
+#
+# Test of ALTER TABLE DELAYED
+#
+
+CREATE TABLE t1 (i int(10), index(i) );
+ALTER TABLE t1 DISABLE KEYS;
+INSERT DELAYED INTO t1 VALUES(1),(2),(3);
+ALTER TABLE t1 ENABLE KEYS;
+drop table t1;
diff --git a/mysql-test/t/err000001.test b/mysql-test/t/errors.test
index b558c90b0c6..b558c90b0c6 100644
--- a/mysql-test/t/err000001.test
+++ b/mysql-test/t/errors.test
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index 8fcb22e4684..5bd7b95f560 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -71,3 +71,20 @@ WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS t1,t2;
+# Addendum by Guilhem:
+# Check if a partly-completed INSERT SELECT in a MyISAM table goes
+# into the binlog
+
+create table t1(a int, unique(a));
+insert into t1 values(2);
+create table t2(a int);
+insert into t2 values(1),(2);
+reset master;
+--error 1062
+insert into t1 select * from t2;
+# The above should produce an error, but still be in the binlog;
+# verify the binlog :
+let $VERSION=`select version()`;
+--replace_result $VERSION VERSION
+show binlog events;
+drop table t1, t2;
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index d7e84590dc0..2f484d30ff7 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -10,4 +10,12 @@ create table t1 (a date, b date, c date not null, d date);
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
SELECT * from t1;
+truncate table t1;
+
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+SELECT * from t1;
drop table t1;
+
+
+
+
diff --git a/mysql-test/t/lowercase_table.test b/mysql-test/t/lowercase_table.test
index 348116b02f2..cb30c14b70c 100644
--- a/mysql-test/t/lowercase_table.test
+++ b/mysql-test/t/lowercase_table.test
@@ -14,3 +14,14 @@ ALTER TABLE T2 ADD new_col int not null;
ALTER TABLE T2 RENAME T3;
show tables like 't_';
drop table t3;
+#
+# Test alias
+#
+create table t1 (a int);
+select count(*) from T1;
+select count(*) from t1;
+--error 1109
+select count(T1.a) from t1;
+--error 1109
+select count(bags.a) from t1 as Bags;
+drop table t1;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 1078d19533c..929146ba97a 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -371,18 +371,35 @@ show global variables like "query_cache_min_res_unit";
#
# Test of query cache resizing
#
+create table t1 (a int);
set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size";
-set GLOBAL query_cache_size=1100;
-set GLOBAL query_cache_size=1200;
-set GLOBAL query_cache_size=1300;
-set GLOBAL query_cache_size=1400;
-set GLOBAL query_cache_size=1500;
-set GLOBAL query_cache_size=1600;
-set GLOBAL query_cache_size=1700;
-set GLOBAL query_cache_size=1800;
-set GLOBAL query_cache_size=1900;
+select * from t1;
+set GLOBAL query_cache_size=1024;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=10240;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=20480;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=40960;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=51200;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=61440;
+show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=81920;
show global variables like "query_cache_size";
+select * from t1;
+set GLOBAL query_cache_size=102400;
+show global variables like "query_cache_size";
+select * from t1;
+drop table t1;
#
# Temporary tables
diff --git a/mysql-test/t/raid.test b/mysql-test/t/raid.test
index 235add63c22..395a04615cb 100644
--- a/mysql-test/t/raid.test
+++ b/mysql-test/t/raid.test
@@ -1,5 +1,7 @@
-- require r/have_raid.require
+disable_query_log;
show variables like "have_raid";
+enable_query_log;
#
# Test of raided tables
diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test
index 93062f39c20..3e84f86c092 100644
--- a/mysql-test/t/rpl_insert_id.test
+++ b/mysql-test/t/rpl_insert_id.test
@@ -1,5 +1,8 @@
# See if queries that use both auto_increment and LAST_INSERT_ID()
# are replicated well
+
+# We also check how the foreign_key_check variable is replicated
+
source include/master-slave.inc;
connection master;
create table t1(a int auto_increment, key(a));
@@ -20,10 +23,30 @@ drop table t1;
drop table t2;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
+SET FOREIGN_KEY_CHECKS=0;
insert into t1 values (10);
insert into t1 values (null),(null),(null);
insert into t2 values (5,0);
insert into t2 values (null,last_insert_id());
+SET FOREIGN_KEY_CHECKS=1;
+save_master_pos;
+connection slave;
+sync_with_master;
+select * from t1;
+select * from t2;
+connection master;
+
+# check if INSERT SELECT in auto_increment is well replicated (bug #490)
+
+drop table t1;
+drop table t2;
+create table t1(a int auto_increment, key(a));
+create table t2(b int auto_increment, c int, key(b));
+insert into t1 values (10);
+insert into t1 values (null),(null),(null);
+insert into t2 values (5,0);
+insert into t2 (c) select * from t1;
+select * from t2;
save_master_pos;
connection slave;
sync_with_master;
diff --git a/mysql-test/t/rpl_log.test b/mysql-test/t/rpl_log.test
index faca1a6c339..369c62848f9 100644
--- a/mysql-test/t/rpl_log.test
+++ b/mysql-test/t/rpl_log.test
@@ -32,11 +32,33 @@ show binlog events from 79 limit 2;
show binlog events from 79 limit 2,1;
flush logs;
+# We need an extra update before doing save_master_pos.
+# Otherwise, an unlikely scenario may occur:
+# * When the master's binlog_dump thread reads the end of master-bin.001,
+# it send the rotate event which is at this end, plus a fake rotate event
+# because it's starting to read a new binlog.
+# save_master_pos will record the position of the first of the two rotate
+# (because the fake one is not in the master's binlog anyway).
+# * Later the slave waits for the position of the first rotate event,
+# and it may quickly stop (in 'slave stop') without having received the fake
+# one.
+# So, depending on a few milliseconds, we end up with 2 rotate events in the
+# relay log or one, which influences the output of SHOW SLAVE STATUS, making
+# it not predictable and causing random test failures.
+# To make it predictable, we do a useless update now, but which has the interest
+# of making the slave catch both rotate events.
+
+create table t5 (a int);
+drop table t5;
+
# Sync slave and force it to start on another binary log
save_master_pos;
connection slave;
-start slave;
+# Note that the above 'slave start' will cause a 3rd rotate event (a fake one)
+# to go into the relay log (the master always sends a fake one when replication
+# starts).
+slave start;
sync_with_master;
flush logs;
stop slave;
diff --git a/mysql-test/t/timezone-master.opt b/mysql-test/t/timezone-master.opt
new file mode 100644
index 00000000000..0477f941e9d
--- /dev/null
+++ b/mysql-test/t/timezone-master.opt
@@ -0,0 +1 @@
+--timezone=MET
diff --git a/mysql-test/t/timezone.test b/mysql-test/t/timezone.test
new file mode 100644
index 00000000000..14facc0374a
--- /dev/null
+++ b/mysql-test/t/timezone.test
@@ -0,0 +1,28 @@
+#
+# Test of timezone handling. This script must be run with TZ=MEST
+
+-- require r/have_mest_timezone.require
+disable_query_log;
+show variables like "timezone";
+enable_query_log;
+
+# Initialization
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+
+CREATE TABLE t1 (ts int);
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
+INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
+
+SELECT ts,from_unixtime(ts) FROM t1;
+DROP TABLE t1;
diff --git a/mysys/default.c b/mysys/default.c
index 17ee1b8c8da..28aa5459c58 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -72,6 +72,7 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
const char *dir, const char *config_file,
const char *ext, TYPELIB *group);
+static char *remove_end_comment(char *ptr);
void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
@@ -299,8 +300,9 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
if (!read_values)
continue;
- if (!(end=value=strchr(ptr,'=')))
- end=strend(ptr); /* Option without argument */
+ end= remove_end_comment(ptr);
+ if ((value= strchr(ptr, '=')))
+ end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
@@ -370,6 +372,29 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
+static char *remove_end_comment(char *ptr)
+{
+ char quote= 0;
+
+ for (; *ptr; ptr++)
+ {
+ if (*ptr == '\'' || *ptr == '\"')
+ {
+ if (!quote)
+ quote= *ptr;
+ else if (quote == *ptr)
+ quote= 0;
+ }
+ if (!quote && *ptr == '#') /* We are not inside a comment */
+ {
+ *ptr= 0;
+ return ptr;
+ }
+ }
+ return ptr;
+}
+
+
void print_defaults(const char *conf_file, const char **groups)
{
#ifdef __WIN__
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index add5335a7af..a2647ec7399 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -27,6 +27,7 @@
#include <m_string.h>
#include <queues.h>
#include "thr_alarm.h"
+#include <assert.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> /* AIX needs this for fd_set */
@@ -36,21 +37,22 @@
#define ETIME ETIMEDOUT
#endif
-static my_bool alarm_aborted=1;
-my_bool thr_alarm_inited=0;
+static int alarm_aborted=1; /* No alarm thread */
+my_bool thr_alarm_inited= 0;
+volatile my_bool alarm_thread_running= 0;
static sig_handler process_alarm_part2(int sig);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm;
+static pthread_cond_t COND_alarm;
static sigset_t full_signal_set;
static QUEUE alarm_queue;
static uint max_used_alarms=0;
pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD
-static pthread_cond_t COND_alarm;
static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm)
#else
@@ -77,6 +79,7 @@ void init_thr_alarm(uint max_alarms)
compare_ulong,NullS);
sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread)
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */
@@ -96,7 +99,6 @@ void init_thr_alarm(uint max_alarms)
{
pthread_attr_t thr_attr;
pthread_attr_init(&thr_attr);
- pthread_cond_init(&COND_alarm,NULL);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thr_attr,8196);
@@ -136,19 +138,24 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
now=(ulong) time((time_t*) 0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
- if (alarm_aborted)
+ if (alarm_aborted > 0)
{ /* No signal thread */
DBUG_PRINT("info", ("alarm aborted"));
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
}
+ if (alarm_aborted < 0)
+ sec= 1; /* Abort mode */
+
if (alarm_queue.elements >= max_used_alarms)
{
if (alarm_queue.elements == alarm_queue.max_elements)
{
DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n");
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
@@ -163,6 +170,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
{
DBUG_PRINT("info", ("failed my_malloc()"));
+ *alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
@@ -219,6 +227,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
break;
}
}
+ DBUG_ASSERT(!*alarmed || found);
if (!found)
{
#ifdef MAIN
@@ -228,14 +237,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
(long) *alarmed));
}
- if (alarm_aborted && !alarm_queue.elements)
- {
- delete_queue(&alarm_queue);
- pthread_mutex_unlock(&LOCK_alarm);
- pthread_mutex_destroy(&LOCK_alarm);
- }
- else
- pthread_mutex_unlock(&LOCK_alarm);
+ pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_VOID_RETURN;
}
@@ -365,31 +367,66 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
/*
- Shedule all alarms now.
- When all alarms are given, Free alarm memory and don't allow more alarms.
+ Schedule all alarms now and optionally free all structures
+
+ SYNPOSIS
+ end_thr_alarm()
+ free_structures Set to 1 if we should free memory used for
+ the alarm queue.
+ When we call this we should KNOW that there
+ is no active alarms
+ IMPLEMENTATION
+ Set alarm_abort to -1 which will change the behavior of alarms as follows:
+ - All old alarms will be rescheduled at once
+ - All new alarms will be rescheduled to one second
*/
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
- if (!alarm_aborted)
+ if (alarm_aborted != 1) /* If memory not freed */
{
- my_bool deleted=0;
pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
- alarm_aborted=1; /* mark aborted */
- if (!alarm_queue.elements)
+ alarm_aborted= -1; /* mark aborted */
+ if (alarm_queue.elements || (alarm_thread_running && free_structures))
{
- deleted= 1;
- delete_queue(&alarm_queue);
+ if (pthread_equal(pthread_self(),alarm_thread))
+ alarm(1); /* Shut down everything soon */
+ else
+ reschedule_alarms();
+ }
+ if (free_structures)
+ {
+ struct timespec abstime;
+ /*
+ The following test is just for safety, the caller should not
+ depend on this
+ */
+ DBUG_ASSERT(!alarm_queue.elements);
+ /* Wait until alarm thread dies */
+
+ set_timespec(abstime, 10); /* Wait up to 10 seconds */
+ while (alarm_thread_running)
+ {
+ int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
+ if (error == ETIME || error == ETIMEDOUT)
+ break; /* Don't wait forever */
+ }
+ if (!alarm_queue.elements)
+ {
+ delete_queue(&alarm_queue);
+ alarm_aborted= 1;
+ pthread_mutex_unlock(&LOCK_alarm);
+ if (!alarm_thread_running) /* Safety */
+ {
+ pthread_mutex_destroy(&LOCK_alarm);
+ pthread_cond_destroy(&COND_alarm);
+ }
+ }
}
- if (pthread_equal(pthread_self(),alarm_thread))
- alarm(1); /* Shut down everything soon */
else
- reschedule_alarms();
- pthread_mutex_unlock(&LOCK_alarm);
- if (deleted)
- pthread_mutex_destroy(&LOCK_alarm);
+ pthread_mutex_unlock(&LOCK_alarm);
}
DBUG_VOID_RETURN;
}
@@ -471,6 +508,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
puts("Starting alarm thread");
#endif
my_thread_init();
+ alarm_thread_running= 1;
pthread_mutex_lock(&LOCK_alarm);
for (;;)
{
@@ -495,7 +533,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
}
}
}
- else if (alarm_aborted)
+ else if (alarm_aborted == -1)
break;
else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm)))
{
@@ -507,6 +545,8 @@ static void *alarm_handler(void *arg __attribute__((unused)))
process_alarm(0);
}
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
+ alarm_thread_running= 0;
+ pthread_cond_signal(&COND_alarm);
pthread_mutex_unlock(&LOCK_alarm);
pthread_exit(0);
return 0; /* Impossible */
@@ -629,7 +669,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
@@ -708,7 +748,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
-void end_thr_alarm(void)
+void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
@@ -907,7 +947,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
case SIGHUP:
#endif
printf("Aborting nicely\n");
- end_thr_alarm();
+ end_thr_alarm(0);
break;
#ifdef SIGTSTP
case SIGTSTP:
@@ -1004,10 +1044,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
if (thread_count == 1)
{
printf("Calling end_thr_alarm. This should cancel the last thread\n");
- end_thr_alarm();
+ end_thr_alarm(0);
}
}
pthread_mutex_unlock(&LOCK_thread_count);
+ end_thr_alarm(1);
thr_alarm_info(&alarm_info);
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
alarm_info.active_alarms, alarm_info.max_used_alarms,
diff --git a/sql/field.cc b/sql/field.cc
index a61654ed8f4..f610f95ae0e 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -2755,6 +2755,7 @@ int Field_timestamp::store(longlong nr)
if ((nr=fix_datetime(nr)))
{
+ long not_used;
part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000));
l_time.year= (int) (part1/10000L); part1%=10000L;
@@ -2763,7 +2764,7 @@ int Field_timestamp::store(longlong nr)
l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100;
- timestamp=my_gmt_sec(&l_time);
+ timestamp=my_gmt_sec(&l_time, &not_used);
}
else
timestamp=0;
diff --git a/sql/log.cc b/sql/log.cc
index c05d52bdc5d..0ccb40c5246 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -1200,6 +1200,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
No check for auto events flag here - this write method should
never be called if auto-events are enabled
*/
+
+ /*
+ 1. Write first log events which describe the 'run environment'
+ of the SQL command
+ */
+
if (thd)
{
if (thd->last_insert_id_used)
@@ -1245,7 +1251,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err;
}
}
-#if 0
+#ifdef TO_BE_REMOVED
if (thd->variables.convert_set)
{
char buf[256], *p;
@@ -1257,12 +1263,39 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err;
}
#endif
+
+ /*
+ If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
+ command in the binlog inside:
+ SET FOREIGN_KEY_CHECKS=0;
+ <command>;
+ SET FOREIGN_KEY_CHECKS=1;
+ */
+
+ if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
+ {
+ Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
}
+
+ /* Write the SQL command */
+
event_info->set_log_pos(this);
- if (event_info->write(file) ||
- file == &log_file && flush_io_cache(file))
+ if (event_info->write(file))
goto err;
- error=0;
+
+ /* Write log events to reset the 'run environment' of the SQL command */
+
+ if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
+ {
+ Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
+ e.set_log_pos(this);
+ if (e.write(file))
+ goto err;
+ }
/*
Tell for transactional table handlers up to which position in the
@@ -1283,6 +1316,9 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file) // we are writing to the real log (disk)
{
+ if (flush_io_cache(file))
+ goto err;
+
if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{
/*
@@ -1292,8 +1328,8 @@ bool MYSQL_LOG::write(Log_event* event_info)
handler if the log event type is appropriate.
*/
- if (event_info->get_type_code() == QUERY_EVENT
- || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ if (event_info->get_type_code() == QUERY_EVENT ||
+ event_info->get_type_code() == EXEC_LOAD_EVENT)
{
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file);
@@ -1303,6 +1339,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* we wrote to the real log, check automatic rotation */
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
+ error=0;
err:
if (error)
@@ -1329,7 +1366,7 @@ err:
Flush the transactional handler log file now that we have released
LOCK_log; the flush is placed here to eliminate the bottleneck on the
group commit
- */
+ */
if (called_handler_commit)
ha_commit_complete(thd);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 97158191111..b7e8c0bd0ab 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -461,7 +461,6 @@ bool mysql_rename_table(enum db_type base,
const char * old_name,
const char *new_db,
const char * new_name);
-bool close_cached_table(THD *thd,TABLE *table);
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
@@ -501,6 +500,7 @@ Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
+#include <openssl/des.h>
struct st_des_keyblock
{
des_cblock key1, key2, key3;
@@ -837,7 +837,7 @@ uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
void init_time(void);
-long my_gmt_sec(TIME *);
+long my_gmt_sec(TIME *, long *current_timezone);
time_t str_to_timestamp(const char *str,uint length);
bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 019a3388341..c6922edb674 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -566,7 +566,7 @@ static void close_connections(void)
unix_sock= INVALID_SOCKET;
}
#endif
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(0); // Abort old alarms.
end_slave();
/* First signal all threads that it's time to die */
@@ -875,6 +875,7 @@ void clean_up(bool print_message)
#endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache();
+ end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
#endif
@@ -940,7 +941,6 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_crypt);
(void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received);
- (void) pthread_mutex_destroy(&LOCK_timezone);
(void) pthread_mutex_destroy(&LOCK_user_conn);
#ifdef HAVE_REPLICATION
(void) pthread_mutex_destroy(&LOCK_rpl_status);
@@ -1501,7 +1501,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size);
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
- fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
@@ -1509,7 +1508,7 @@ and this may fail.\n\n");
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
bytes of memory\n", ((ulong) keybuff_size +
(global_system_variables.read_buff_size +
- thd->variables.sortbuff_size) *
+ global_system_variables.sortbuff_size) *
max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
@@ -1538,14 +1537,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
Some pointers may be invalid and cause the dump to abort...\n");
safe_print_str("thd->query", thd->query, 1024);
fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id);
- fprintf(stderr, "\n\
-Successfully dumped variables, if you ran with --log, take a look at the\n\
-details of what thread %ld did to cause the crash. In some cases of really\n\
-bad corruption, the values shown above may be invalid.\n\n",
- thd->thread_id);
}
fprintf(stderr, "\
-The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\
+The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
information that should help you find out what is causing the crash.\n");
fflush(stderr);
#endif /* HAVE_STACKTRACE */
@@ -1569,6 +1563,7 @@ information that should help you find out what is causing the crash.\n");
static void init_signals(void)
{
sigset_t set;
+ struct sigaction sa;
DBUG_ENTER("init_signals");
sigset(THR_KILL_SIGNAL,end_thread_signal);
@@ -1576,7 +1571,6 @@ static void init_signals(void)
if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
{
- struct sigaction sa;
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
@@ -1618,15 +1612,23 @@ static void init_signals(void)
sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP);
- sigset(SIGTERM, print_signal_warning); // If it's blocked by parent
- sigset(SIGHUP, print_signal_warning); // If it's blocked by parent
+
+ /* Fix signals if blocked by parents (can happen on Mac OS X) */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = print_signal_warning;
+ sigaction(SIGTERM, &sa, (struct sigaction*) 0);
+ sa.sa_flags = 0;
+ sa.sa_handler = print_signal_warning;
+ sigaction(SIGHUP, &sa, (struct sigaction*) 0);
#ifdef SIGTSTP
sigaddset(&set,SIGTSTP);
#endif
sigaddset(&set,THR_SERVER_ALARM);
sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
sigdelset(&set,THR_CLIENT_ALARM); // For alarms
- (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
+ sigprocmask(SIG_SETMASK,&set,NULL);
+ pthread_sigmask(SIG_SETMASK,&set,NULL);
DBUG_VOID_RETURN;
}
@@ -1894,7 +1896,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif
-const char *load_default_groups[]= { "mysqld","server",0 };
+const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 };
bool open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension,
@@ -1951,19 +1953,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
}
#endif
#ifdef HAVE_TZNAME
-#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
{
struct tm tm_tmp;
localtime_r(&start_time,&tm_tmp);
strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
}
-#else
- {
- struct tm *start_tm;
- start_tm=localtime(&start_time);
- strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
- }
-#endif
#endif
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
@@ -2075,7 +2069,6 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
- (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
@@ -2441,14 +2434,14 @@ The server will not act as a slave.");
if (opt_bootstrap)
{
int error=bootstrap(stdin);
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(1); // Don't allow alarms
unireg_abort(error ? 1 : 0);
}
if (opt_init_file)
{
if (read_init_file(opt_init_file))
{
- end_thr_alarm(); // Don't allow alarms
+ end_thr_alarm(1); // Don't allow alarms
unireg_abort(1);
}
}
@@ -2620,9 +2613,12 @@ int main(int argc, char **argv)
return 0;
if (Service.IsService(argv[2]))
{
- /* start an optional service */
+ /*
+ mysqld was started as
+ mysqld --defaults-file=my_path\my.ini service-name
+ */
use_opt_args=1;
- opt_argc=argc;
+ opt_argc= 2; // Skip service-name
opt_argv=argv;
start_mode= 1;
Service.Init(argv[2], mysql_service);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 42ea92825d1..b772f6410f7 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -209,6 +209,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_size);
+sys_var_bool_ptr sys_readonly("read_only", &opt_readonly);
sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size);
#ifdef HAVE_REPLICATION
@@ -596,6 +597,7 @@ struct show_var_st init_vars[]= {
{"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
+ {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
#ifdef HAVE_REPLICATION
{sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS},
diff --git a/sql/slave.cc b/sql/slave.cc
index be95cc16d90..21674d9ece2 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1388,9 +1388,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
while (rli->log_space_limit < rli->log_space_total &&
!(slave_killed=io_slave_killed(thd,mi)) &&
!rli->ignore_log_space_limit)
- {
pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
- }
thd->proc_info = save_proc_info;
pthread_mutex_unlock(&rli->log_space_lock);
DBUG_RETURN(slave_killed);
@@ -2101,7 +2099,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
Log_event * ev = next_event(rli);
DBUG_ASSERT(rli->sql_thd==thd);
if (sql_slave_killed(thd,rli))
+ {
+ /* do not forget to free ev ! */
+ if (ev) delete ev;
return 1;
+ }
if (ev)
{
int type_code = ev->get_type_code();
@@ -2376,6 +2378,18 @@ reconnect done to recover from failed read");
goto err;
}
flush_master_info(mi);
+ /*
+ See if the relay logs take too much space.
+ We don't lock mi->rli.log_space_lock here; this dirty read saves time
+ and does not introduce any problem:
+ - if mi->rli.ignore_log_space_limit is 1 but becomes 0 just after (so
+ the clean value is 0), then we are reading only one more event as we
+ should, and we'll block only at the next event. No big deal.
+ - if mi->rli.ignore_log_space_limit is 0 but becomes 1 just after (so
+ the clean value is 1), then we are going into wait_for_relay_log_space()
+ for no reason, but this function will do a clean read, notice the clean
+ value and exit immediately.
+ */
if (mi->rli.log_space_limit && mi->rli.log_space_limit <
mi->rli.log_space_total &&
!mi->rli.ignore_log_space_limit)
@@ -2489,7 +2503,9 @@ slave_begin:
pthread_cond_broadcast(&rli->start_cond);
//tell the I/O thread to take relay_log_space_limit into account from now on
+ pthread_mutex_lock(&rli->log_space_lock);
rli->ignore_log_space_limit= 0;
+ pthread_mutex_unlock(&rli->log_space_lock);
if (init_relay_log_pos(rli,
rli->group_relay_log_name,
@@ -3221,7 +3237,12 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
pthread_mutex_lock(&rli->log_space_lock);
// prevent the I/O thread from blocking next times
rli->ignore_log_space_limit= 1;
- // If the I/O thread is blocked, unblock it
+ /*
+ If the I/O thread is blocked, unblock it.
+ Ok to broadcast after unlock, because the mutex is only destroyed in
+ ~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be
+ destroyed before we exit the present function.
+ */
pthread_mutex_unlock(&rli->log_space_lock);
pthread_cond_broadcast(&rli->log_space_cond);
// Note that wait_for_update unlocks lock_log !
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 7a154d206ef..ac6471e794c 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -739,7 +739,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
query_cache_size_arg));
free_cache(0);
query_cache_size= query_cache_size_arg;
- DBUG_RETURN(init_cache());
+ DBUG_RETURN(::query_cache_size= init_cache());
}
@@ -1318,6 +1318,12 @@ ulong Query_cache::init_cache()
mem_bin_steps = 1;
mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
prev_size = 0;
+ if (mem_bin_size <= min_allocation_unit)
+ {
+ DBUG_PRINT("qcache", ("too small query cache => query cache disabled"));
+ // TODO here (and above) should be warning in 4.1
+ goto err;
+ }
while (mem_bin_size > min_allocation_unit)
{
mem_bin_num += mem_bin_count;
@@ -1344,14 +1350,6 @@ ulong Query_cache::init_cache()
query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
- if (max_mem_bin_size <= min_allocation_unit)
- {
- DBUG_PRINT("qcache",
- (" max bin size (%lu) <= min_allocation_unit => cache disabled",
- max_mem_bin_size));
- STRUCT_UNLOCK(&structure_guard_mutex);
- goto err;
- }
if (!(cache = (byte *)
my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 1908f898a27..69382b2db95 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1421,6 +1421,24 @@ void select_insert::send_error(uint errcode,const char *err)
::send_error(thd,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd);
+ /*
+ If at least one row has been inserted/modified and will stay in the table
+ (the table doesn't have transactions) (example: we got a duplicate key
+ error while inserting into a MyISAM table) we must write to the binlog (and
+ the error code will make the slave stop).
+ */
+ if ((info.copied || info.deleted) && !table->file->has_transactions())
+ {
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
+ mysql_update_log.write(thd,thd->query,thd->query_length);
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length,
+ table->file->has_transactions());
+ mysql_bin_log.write(&qinfo);
+ }
+ }
if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1);
ha_rollback_stmt(thd);
@@ -1442,7 +1460,10 @@ bool select_insert::send_eof()
if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1);
+ if (last_insert_id)
+ thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */
+ mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
@@ -1467,10 +1488,7 @@ bool select_insert::send_eof()
else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields);
- if (last_insert_id)
- thd->insert_id(last_insert_id); // For update log
::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
- mysql_update_log.write(thd,thd->query,thd->query_length);
return 0;
}
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 7cadf187181..c15c824f843 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1081,58 +1081,76 @@ mysql_rename_table(enum db_type base,
}
/*
- close table in this thread and force close + reopen in other threads
- This assumes that the calling thread has lock on LOCK_open
- Win32 clients must also have a WRITE LOCK on the table !
+ Force all other threads to stop using the table
+
+ SYNOPSIS
+ wait_while_table_is_used()
+ thd Thread handler
+ table Table to remove from cache
+
+ NOTES
+ When returning, the table will be unusable for other threads until
+ the table is closed.
+
+ PREREQUISITES
+ Lock on LOCK_open
+ Win32 clients must also have a WRITE LOCK on the table !
*/
-static void safe_remove_from_cache(THD *thd,TABLE *table)
+static void wait_while_table_is_used(THD *thd,TABLE *table)
{
- DBUG_ENTER("safe_remove_from_cache");
- if (table)
- {
- DBUG_PRINT("enter",("table: %s", table->real_name));
- VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
- /* Mark all tables that are in use as 'old' */
- mysql_lock_abort(thd,table); // end threads waiting on lock
+ DBUG_PRINT("enter",("table: %s", table->real_name));
+ DBUG_ENTER("wait_while_table_is_used");
+ safe_mutex_assert_owner(&LOCK_open);
-#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
- /* Wait until all there are no other threads that has this table open */
- while (remove_table_from_cache(thd,table->table_cache_key,
- table->real_name))
- {
- dropping_tables++;
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- dropping_tables--;
- }
-#else
- (void) remove_table_from_cache(thd,table->table_cache_key,
- table->real_name);
-#endif
- /* When lock on LOCK_open is freed other threads can continue */
- pthread_cond_broadcast(&COND_refresh);
+ VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
+ /* Mark all tables that are in use as 'old' */
+ mysql_lock_abort(thd, table); // end threads waiting on lock
+
+ /* Wait until all there are no other threads that has this table open */
+ while (remove_table_from_cache(thd,table->table_cache_key,
+ table->real_name))
+ {
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
}
DBUG_VOID_RETURN;
}
+/*
+ Close a cached table
-bool close_cached_table(THD *thd,TABLE *table)
+ SYNOPSIS
+ clsoe_cached_table()
+ thd Thread handler
+ table Table to remove from cache
+
+ NOTES
+ Function ends by signaling threads waiting for the table to try to
+ reopen the table.
+
+ PREREQUISITES
+ Lock on LOCK_open
+ Win32 clients must also have a WRITE LOCK on the table !
+*/
+
+static bool close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
- safe_mutex_assert_owner(&LOCK_open);
-
- if (table)
+
+ wait_while_table_is_used(thd,table);
+ /* Close lock if this is not got with LOCK TABLES */
+ if (thd->lock)
{
- safe_remove_from_cache(thd,table);
- /* Close lock if this is not got with LOCK TABLES */
- if (thd->lock)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock=0; // Start locked threads
- }
- /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
- thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0; // Start locked threads
}
+ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
+ thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
+
+ /* When lock on LOCK_open is freed other threads can continue */
+ pthread_cond_broadcast(&COND_refresh);
DBUG_RETURN(0);
}
@@ -1261,10 +1279,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
- pthread_mutex_lock(&LOCK_open);
- close_cached_table(thd,table_list->table);
- pthread_mutex_unlock(&LOCK_open);
-
+ /* If we could open the table, close it */
+ if (table_list->table)
+ {
+ pthread_mutex_lock(&LOCK_open);
+ close_cached_table(thd, table);
+ pthread_mutex_unlock(&LOCK_open);
+ }
if (lock_and_wait_for_table_name(thd,table_list))
{
error= -1;
@@ -1794,11 +1815,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
*fn_ext(new_name)=0;
- close_cached_table(thd,table);
+ close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1;
}
- VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
@@ -1807,12 +1827,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
- safe_remove_from_cache(thd,table);
- error= table->file->activate_all_index(thd);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ error= table->file->activate_all_index(thd);
+ /* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
- safe_remove_from_cache(thd,table);
+ VOID(pthread_mutex_lock(&LOCK_open));
+ wait_while_table_is_used(thd, table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR);
+ /* COND_refresh will be signaled in close_thread_tables() */
break;
}
}
@@ -2247,7 +2273,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
- if (close_cached_table(thd,table))
+ if (close_cached_table(thd, table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
@@ -2281,7 +2307,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
This shouldn't happen. We solve this the safe way by
closing the locked table.
*/
- close_cached_table(thd,table);
+ if (table)
+ close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
@@ -2291,7 +2318,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Not table locking or alter table with rename
free locks and remove old table
*/
- close_cached_table(thd,table);
+ if (table)
+ close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name));
}
else
@@ -2311,7 +2339,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0))
{ // This shouldn't happen
- close_cached_table(thd,table); // Remove lock for table
+ if (table)
+ close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 1f6364ec427..989d17b006b 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -200,7 +200,6 @@ int mysql_update(THD *thd,
*/
uint length;
SORT_FIELD *sortorder;
- List<Item> fields;
ha_rows examined_rows;
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index efb5e42626d..e96c87b3f43 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4324,6 +4324,7 @@ keyword:
| SHARE_SYM {}
| SHUTDOWN {}
| SLAVE {}
+ | SOUNDS_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {}
@@ -4348,8 +4349,8 @@ keyword:
| VARIABLES {}
| VALUE_SYM {}
| WORK_SYM {}
+ | X509_SYM {}
| YEAR_SYM {}
- | SOUNDS_SYM {}
;
/* Option functions */
diff --git a/sql/time.cc b/sql/time.cc
index eba664a690d..b6ca306e523 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Currently only my_time_zone is inited */
static long my_time_zone=0;
-pthread_mutex_t LOCK_timezone;
void init_time(void)
{
@@ -39,14 +38,14 @@ void init_time(void)
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
l_time= &tm_tmp;
- my_time_zone=0;
+ my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */
my_time.year= (uint) l_time->tm_year+1900;
my_time.month= (uint) l_time->tm_mon+1;
my_time.day= (uint) l_time->tm_mday;
my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min;
- my_time.second= (uint) l_time->tm_sec;
- VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */
+ my_time.second= (uint) l_time->tm_sec;
+ my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
}
/*
@@ -57,26 +56,39 @@ void init_time(void)
*/
-long my_gmt_sec(TIME *t)
+long my_gmt_sec(TIME *t, long *my_timezone)
{
uint loop;
time_t tmp;
struct tm *l_time,tm_tmp;
- long diff;
+ long diff, current_timezone;
if (t->hour >= 24)
{ /* Fix for time-loop */
t->day+=t->hour/24;
t->hour%=24;
}
- pthread_mutex_lock(&LOCK_timezone);
- tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
- (long) days_at_timestart)*86400L + (long) t->hour*3600L +
- (long) (t->minute*60 + t->second)) + (time_t) my_time_zone;
+
+ /*
+ Calculate the gmt time based on current time and timezone
+ The -1 on the end is to ensure that if have a date that exists twice
+ (like 2002-10-27 02:00:0 MET), we will find the initial date.
+
+ By doing -3600 we will have to call localtime_r() several times, but
+ I couldn't come up with a better way to get a repeatable result :(
+
+ We can't use mktime() as it's buggy on many platforms and not thread safe.
+ */
+ tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
+ (long) days_at_timestart)*86400L + (long) t->hour*3600L +
+ (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
+ 3600);
+ current_timezone= my_time_zone;
+
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
for (loop=0;
- loop < 3 &&
+ loop < 2 &&
(t->hour != (uint) l_time->tm_hour ||
t->minute != (uint) l_time->tm_min);
loop++)
@@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t)
days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
(long) (60*((int) t->minute - (int) l_time->tm_min)));
- my_time_zone+=diff;
- tmp+=(time_t) diff;
+ current_timezone+= diff+3600; // Compensate for -3600 above
+ tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
}
- /* Fix that if we are in the not existing daylight saving time hour
- we move the start of the next real hour */
- if (loop == 3 && t->hour != (uint) l_time->tm_hour)
+ /*
+ Fix that if we are in the not existing daylight saving time hour
+ we move the start of the next real hour
+ */
+ if (loop == 2 && t->hour != (uint) l_time->tm_hour)
{
int days= t->day - l_time->tm_mday;
if (days < -1)
@@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t)
if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600)
- tmp-=t->minute*60 + t->second; // Move to next hour
+ tmp-=t->minute*60 + t->second; // Move to previous hour
}
- if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12)
- my_time_zone=0; /* Wrong date */
- pthread_mutex_unlock(&LOCK_timezone);
+ *my_timezone= current_timezone;
return (long) tmp;
} /* my_gmt_sec */
@@ -428,6 +440,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
time_t str_to_timestamp(const char *str,uint length)
{
TIME l_time;
+ long not_used;
+
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
@@ -435,7 +449,7 @@ time_t str_to_timestamp(const char *str,uint length)
current_thd->cuted_fields++;
return(0);
}
- return(my_gmt_sec(&l_time));
+ return(my_gmt_sec(&l_time, &not_used));
}