mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge sinisa@bk-internal.mysql.com:/home/bk/mysql-4.0
into sinisa.nasamreza.org:/mnt/work/mysql-4.0
This commit is contained in:
@@ -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
|
||||
|
@@ -33,6 +33,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
|
||||
|
5707
Docs/internals.texi
5707
Docs/internals.texi
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@
|
||||
#include <signal.h>
|
||||
#include <violite.h>
|
||||
|
||||
const char *VER= "12.20";
|
||||
const char *VER= "12.21";
|
||||
|
||||
/* Don't try to make a nice table if the data is too big */
|
||||
#define MAX_COLUMN_LENGTH 1024
|
||||
@@ -2615,14 +2615,18 @@ static const char* construct_prompt()
|
||||
add_int_to_prompt(++prompt_counter);
|
||||
break;
|
||||
case 'v':
|
||||
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
|
||||
@@ -2633,8 +2637,13 @@ static const char* construct_prompt()
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") ||
|
||||
! mysql.unix_socket)
|
||||
if (!connected)
|
||||
{
|
||||
processed_prompt.append("not_connected");
|
||||
break;
|
||||
}
|
||||
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || !
|
||||
mysql.unix_socket)
|
||||
add_int_to_prompt(mysql.port);
|
||||
else
|
||||
{
|
||||
|
@@ -515,8 +515,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);
|
||||
|
||||
|
10
configure.in
10
configure.in
@@ -361,7 +361,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
|
||||
@@ -1025,8 +1025,16 @@ case $SYSTEM_TYPE in
|
||||
;;
|
||||
*freebsd*)
|
||||
echo "Adding fix for interrupted reads"
|
||||
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"
|
||||
|
@@ -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
|
||||
@@ -246,7 +246,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>
|
||||
@@ -636,7 +636,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. */
|
||||
|
@@ -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);
|
||||
|
@@ -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. */
|
||||
|
||||
|
@@ -10,15 +10,29 @@ 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_native_event_t;
|
||||
|
||||
typedef struct os_event_struct os_event_struct_t;
|
||||
typedef os_event_struct_t* os_event_t;
|
||||
|
||||
struct os_event_struct {
|
||||
os_native_event_t handle;
|
||||
/* Windows event */
|
||||
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
|
||||
/* list of all created events */
|
||||
};
|
||||
#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 +40,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,10 +52,32 @@ typedef os_mutex_str_t* os_mutex_t;
|
||||
|
||||
#define OS_SYNC_TIME_EXCEEDED 1
|
||||
|
||||
/* Mutex protecting counts and the 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;
|
||||
|
||||
extern ulint os_event_count;
|
||||
extern ulint os_mutex_count;
|
||||
extern ulint os_fast_mutex_count;
|
||||
|
||||
/*************************************************************
|
||||
Creates an event semaphore, i.e., a semaphore which may
|
||||
just have two states: signaled and nonsignaled.
|
||||
The created event is manual reset: it must be reset
|
||||
Initializes global event and OS 'slow' mutex lists. */
|
||||
|
||||
void
|
||||
os_sync_init(void);
|
||||
/*==============*/
|
||||
/*************************************************************
|
||||
Frees created events 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. The created event is manual reset: it must be reset
|
||||
explicitly by calling sync_os_reset_event. */
|
||||
|
||||
os_event_t
|
||||
@@ -50,10 +86,10 @@ os_event_create(
|
||||
/* out: the event handle */
|
||||
char* name); /* in: the name of the event, if NULL
|
||||
the event is created without a name */
|
||||
#ifdef __WIN__
|
||||
/*************************************************************
|
||||
Creates an auto-reset event semaphore, i.e., an event
|
||||
which is automatically reset when a single thread is
|
||||
released. */
|
||||
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
||||
reset when a single thread is released. Works only in Windows. */
|
||||
|
||||
os_event_t
|
||||
os_event_create_auto(
|
||||
@@ -61,6 +97,7 @@ os_event_create_auto(
|
||||
/* out: the event handle */
|
||||
char* name); /* in: the name of the event, if NULL
|
||||
the event is created without a name */
|
||||
#endif
|
||||
/**************************************************************
|
||||
Sets an event semaphore to the signaled state: lets waiting threads
|
||||
proceed. */
|
||||
@@ -85,7 +122,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(
|
||||
@@ -93,7 +133,7 @@ os_event_wait(
|
||||
os_event_t event); /* in: event to wait */
|
||||
/**************************************************************
|
||||
Waits for an event object until it is in the signaled state or
|
||||
a timeout is exceeded. */
|
||||
a timeout is exceeded. In Unix the timeout is always infinite. */
|
||||
|
||||
ulint
|
||||
os_event_wait_time(
|
||||
@@ -104,8 +144,9 @@ os_event_wait_time(
|
||||
os_event_t event, /* in: event to wait */
|
||||
ulint time); /* in: timeout in microseconds, or
|
||||
OS_SYNC_INFINITE_TIME */
|
||||
#ifdef __WIN__
|
||||
/**************************************************************
|
||||
Waits for any event in an event array. Returns if even a single
|
||||
Waits for any event in an OS native event array. Returns if even a single
|
||||
one is signaled or becomes signaled. */
|
||||
|
||||
ulint
|
||||
@@ -115,12 +156,13 @@ os_event_wait_multiple(
|
||||
which was signaled */
|
||||
ulint n, /* in: number of events in the
|
||||
array */
|
||||
os_event_t* event_array); /* in: pointer to an array of event
|
||||
os_native_event_t* native_event_array);
|
||||
/* in: pointer to an array of event
|
||||
handles */
|
||||
#endif
|
||||
/*************************************************************
|
||||
Creates an operating system mutex semaphore.
|
||||
Because these are slow, the mutex semaphore of the database
|
||||
itself (sync_mutex_t) should be used where possible. */
|
||||
Creates an operating system mutex semaphore. Because these are slow, the
|
||||
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
||||
|
||||
os_mutex_t
|
||||
os_mutex_create(
|
||||
|
@@ -44,4 +44,3 @@ os_fast_mutex_trylock(
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -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*);
|
||||
|
||||
@@ -66,7 +65,9 @@ os_thread_pf(
|
||||
/********************************************************************
|
||||
Creates a new thread of execution. The execution starts from
|
||||
the function given. The start function takes a void* parameter
|
||||
and returns a ulint. */
|
||||
and returns a ulint.
|
||||
NOTE: We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
os_thread_t
|
||||
os_thread_create(
|
||||
@@ -83,12 +84,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 +146,6 @@ ulint
|
||||
os_thread_get_last_error(void);
|
||||
/*==========================*/
|
||||
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "os0thread.ic"
|
||||
#endif
|
||||
|
@@ -209,6 +209,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. */
|
||||
|
||||
|
@@ -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_EXIT_THREADS 3
|
||||
|
||||
#endif
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
@@ -999,6 +999,8 @@ log_group_file_header_flush(
|
||||
byte* buf;
|
||||
ulint dest_offset;
|
||||
|
||||
UT_NOT_USED(type);
|
||||
|
||||
ut_ad(mutex_own(&(log_sys->mutex)));
|
||||
|
||||
ut_a(nth_file < group->n_files);
|
||||
@@ -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,8 +2903,7 @@ logs_empty_and_mark_files_at_shutdown(void)
|
||||
dulint lsn;
|
||||
ulint arch_log_no;
|
||||
|
||||
if (srv_print_verbose_log)
|
||||
{
|
||||
if (srv_print_verbose_log) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Starting shutdown...\n");
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@@ -80,6 +80,8 @@ struct os_aio_slot_struct{
|
||||
which pending aio operation was
|
||||
completed */
|
||||
#ifdef WIN_ASYNC_IO
|
||||
os_event_t event; /* event object we need in the
|
||||
OVERLAPPED struct */
|
||||
OVERLAPPED control; /* Windows control block for the
|
||||
aio request */
|
||||
#elif defined(POSIX_ASYNC_IO)
|
||||
@@ -107,11 +109,14 @@ struct os_aio_array_struct{
|
||||
ulint n_reserved;/* Number of reserved slots in the
|
||||
aio array outside the ibuf segment */
|
||||
os_aio_slot_t* slots; /* Pointer to the slots in the array */
|
||||
os_event_t* events; /* Pointer to an array of event handles
|
||||
where we copied the handles from slots,
|
||||
in the same order. This can be used in
|
||||
WaitForMultipleObjects; used only in
|
||||
#ifdef __WIN__
|
||||
os_native_event_t* native_events;
|
||||
/* Pointer to an array of OS native event
|
||||
handles where we copied the handles from
|
||||
slots, in the same order. This can be used
|
||||
in WaitForMultipleObjects; used only in
|
||||
Windows */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Array of events used in simulated aio */
|
||||
@@ -295,7 +300,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: operation */
|
||||
{
|
||||
ulint err;
|
||||
|
||||
@@ -338,6 +344,7 @@ os_file_handle_error(
|
||||
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,8 +426,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,8 +468,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;
|
||||
}
|
||||
@@ -568,8 +577,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,8 +625,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));
|
||||
|
||||
@@ -1309,19 +1319,22 @@ os_aio_array_create(
|
||||
array->n_segments = n_segments;
|
||||
array->n_reserved = 0;
|
||||
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
|
||||
array->events = ut_malloc(n * sizeof(os_event_t));
|
||||
|
||||
#ifdef __WIN__
|
||||
array->native_events = ut_malloc(n * sizeof(os_native_event_t));
|
||||
#endif
|
||||
for (i = 0; i < n; i++) {
|
||||
slot = os_aio_array_get_nth_slot(array, i);
|
||||
|
||||
slot->pos = i;
|
||||
slot->reserved = FALSE;
|
||||
#ifdef WIN_ASYNC_IO
|
||||
slot->event = os_event_create(NULL);
|
||||
|
||||
over = &(slot->control);
|
||||
|
||||
over->hEvent = os_event_create(NULL);
|
||||
over->hEvent = slot->event->handle;
|
||||
|
||||
*((array->events) + i) = over->hEvent;
|
||||
*((array->native_events) + i) = over->hEvent;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1405,6 +1418,50 @@ os_aio_init(
|
||||
#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->slots + i)->event);
|
||||
}
|
||||
}
|
||||
#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
|
||||
be other, synchronous, pending writes. */
|
||||
@@ -1635,7 +1692,7 @@ loop:
|
||||
control = &(slot->control);
|
||||
control->Offset = (DWORD)offset;
|
||||
control->OffsetHigh = (DWORD)offset_high;
|
||||
os_event_reset(control->hEvent);
|
||||
os_event_reset(slot->event);
|
||||
|
||||
#elif defined(POSIX_ASYNC_IO)
|
||||
|
||||
@@ -1693,7 +1750,7 @@ os_aio_array_free_slot(
|
||||
}
|
||||
|
||||
#ifdef WIN_ASYNC_IO
|
||||
os_event_reset(slot->control.hEvent);
|
||||
os_event_reset(slot->event);
|
||||
#endif
|
||||
os_mutex_exit(array->mutex);
|
||||
}
|
||||
@@ -1862,7 +1919,8 @@ os_aio(
|
||||
wait in the Windows case. */
|
||||
|
||||
if (type == OS_FILE_READ) {
|
||||
return(os_file_read(file, buf, offset, offset_high, n));
|
||||
return(os_file_read(file, buf, offset,
|
||||
offset_high, n));
|
||||
}
|
||||
|
||||
ut_a(type == OS_FILE_WRITE);
|
||||
@@ -1941,7 +1999,6 @@ try_again:
|
||||
if (os_aio_use_native_aio) {
|
||||
if ((ret && len == n)
|
||||
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|
||||
|
||||
/* aio was queued successfully! */
|
||||
|
||||
if (mode == OS_AIO_SYNC) {
|
||||
@@ -1971,8 +2028,8 @@ try_again:
|
||||
|
||||
os_aio_array_free_slot(array, slot);
|
||||
|
||||
retry = os_file_handle_error(file, name);
|
||||
|
||||
retry = os_file_handle_error(file, name,
|
||||
type == OS_FILE_READ ? "aio read" : "aio write");
|
||||
if (retry) {
|
||||
|
||||
goto try_again;
|
||||
@@ -2037,15 +2094,15 @@ os_aio_windows_handle(
|
||||
n = array->n_slots / array->n_segments;
|
||||
|
||||
if (array == os_aio_sync_array) {
|
||||
srv_io_thread_op_info[orig_seg] = "wait Windows aio for 1 page";
|
||||
|
||||
ut_ad(pos < array->n_slots);
|
||||
os_event_wait(array->events[pos]);
|
||||
srv_io_thread_op_info[orig_seg] =
|
||||
"wait Windows aio for 1 page";
|
||||
os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
|
||||
i = pos;
|
||||
} else {
|
||||
srv_io_thread_op_info[orig_seg] =
|
||||
"wait Windows aio";
|
||||
i = os_event_wait_multiple(n, (array->events) + segment * n);
|
||||
i = os_event_wait_multiple(n,
|
||||
(array->native_events) + segment * n);
|
||||
}
|
||||
|
||||
os_mutex_enter(array->mutex);
|
||||
@@ -2070,7 +2127,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, "Windows aio");
|
||||
|
||||
ret_val = FALSE;
|
||||
}
|
||||
|
@@ -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{
|
||||
@@ -27,13 +28,77 @@ struct os_mutex_struct{
|
||||
do not assume that the OS mutex
|
||||
supports recursive locking, though
|
||||
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 counts 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 */
|
||||
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;
|
||||
|
||||
ulint os_event_count = 0;
|
||||
ulint os_mutex_count = 0;
|
||||
ulint os_fast_mutex_count = 0;
|
||||
|
||||
|
||||
/*************************************************************
|
||||
Creates an event semaphore, i.e., a semaphore which may
|
||||
just have two states: signaled and nonsignaled.
|
||||
The created event is manual reset: it must be reset
|
||||
explicitly by calling sync_os_reset_event. */
|
||||
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 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. The created event is manual reset: it
|
||||
must be reset explicitly by calling sync_os_reset_event. */
|
||||
|
||||
os_event_t
|
||||
os_event_create(
|
||||
@@ -43,22 +108,20 @@ os_event_create(
|
||||
the event is created without a name */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
HANDLE event;
|
||||
os_event_t event;
|
||||
|
||||
event = CreateEvent(NULL, /* No security attributes */
|
||||
event = ut_malloc(sizeof(struct os_event_struct));
|
||||
|
||||
event->handle = CreateEvent(NULL,/* No security attributes */
|
||||
TRUE, /* Manual reset */
|
||||
FALSE, /* Initial state nonsignaled */
|
||||
name);
|
||||
if (!event) {
|
||||
if (!event->handle) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
|
||||
(ulint)GetLastError());
|
||||
}
|
||||
|
||||
ut_a(event);
|
||||
|
||||
return(event);
|
||||
#else
|
||||
#else /* Unix */
|
||||
os_event_t event;
|
||||
|
||||
UT_NOT_USED(name);
|
||||
@@ -74,15 +137,24 @@ os_event_create(
|
||||
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
|
||||
#endif
|
||||
event->is_set = FALSE;
|
||||
#endif /* __WIN__ */
|
||||
|
||||
/* Put to the list of events */
|
||||
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
|
||||
}
|
||||
|
||||
#ifdef __WIN__
|
||||
/*************************************************************
|
||||
Creates an auto-reset event semaphore, i.e., an event
|
||||
which is automatically reset when a single thread is
|
||||
released. */
|
||||
Creates an auto-reset event semaphore, i.e., an event which is automatically
|
||||
reset when a single thread is released. Works only in Windows. */
|
||||
|
||||
os_event_t
|
||||
os_event_create_auto(
|
||||
@@ -91,24 +163,33 @@ os_event_create_auto(
|
||||
char* name) /* in: the name of the event, if NULL
|
||||
the event is created without a name */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
HANDLE event;
|
||||
os_event_t event;
|
||||
|
||||
event = CreateEvent(NULL, /* No security attributes */
|
||||
event = ut_malloc(sizeof(struct os_event_struct));
|
||||
|
||||
event->handle = CreateEvent(NULL,/* No security attributes */
|
||||
FALSE, /* Auto-reset */
|
||||
FALSE, /* Initial state nonsignaled */
|
||||
name);
|
||||
ut_a(event);
|
||||
|
||||
if (!event->handle) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n",
|
||||
(ulint)GetLastError());
|
||||
}
|
||||
|
||||
/* Put to the list of events */
|
||||
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);
|
||||
#else
|
||||
/* Does nothing in Posix because we do not need this with MySQL */
|
||||
|
||||
UT_NOT_USED(name);
|
||||
|
||||
return(NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************************************
|
||||
Sets an event semaphore to the signaled state: lets waiting threads
|
||||
@@ -121,7 +202,7 @@ os_event_set(
|
||||
{
|
||||
#ifdef __WIN__
|
||||
ut_a(event);
|
||||
ut_a(SetEvent(event));
|
||||
ut_a(SetEvent(event->handle));
|
||||
#else
|
||||
ut_a(event);
|
||||
|
||||
@@ -150,7 +231,7 @@ os_event_reset(
|
||||
#ifdef __WIN__
|
||||
ut_a(event);
|
||||
|
||||
ut_a(ResetEvent(event));
|
||||
ut_a(ResetEvent(event->handle));
|
||||
#else
|
||||
ut_a(event);
|
||||
|
||||
@@ -178,19 +259,31 @@ os_event_free(
|
||||
#ifdef __WIN__
|
||||
ut_a(event);
|
||||
|
||||
ut_a(CloseHandle(event));
|
||||
ut_a(CloseHandle(event->handle));
|
||||
#else
|
||||
ut_a(event);
|
||||
|
||||
os_fast_mutex_free(&(event->os_mutex));
|
||||
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
|
||||
#endif
|
||||
/* Remove from the list of events */
|
||||
|
||||
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(
|
||||
@@ -203,15 +296,23 @@ os_event_wait(
|
||||
ut_a(event);
|
||||
|
||||
/* Specify an infinite time limit for waiting */
|
||||
err = WaitForSingleObject(event, INFINITE);
|
||||
err = WaitForSingleObject(event->handle, 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;
|
||||
@@ -228,7 +329,7 @@ loop:
|
||||
|
||||
/**************************************************************
|
||||
Waits for an event object until it is in the signaled state or
|
||||
a timeout is exceeded. */
|
||||
a timeout is exceeded. In Unix the timeout is always infinite. */
|
||||
|
||||
ulint
|
||||
os_event_wait_time(
|
||||
@@ -245,9 +346,9 @@ os_event_wait_time(
|
||||
ut_a(event);
|
||||
|
||||
if (time != OS_SYNC_INFINITE_TIME) {
|
||||
err = WaitForSingleObject(event, time / 1000);
|
||||
err = WaitForSingleObject(event->handle, time / 1000);
|
||||
} else {
|
||||
err = WaitForSingleObject(event, INFINITE);
|
||||
err = WaitForSingleObject(event->handle, INFINITE);
|
||||
}
|
||||
|
||||
if (err == WAIT_OBJECT_0) {
|
||||
@@ -271,8 +372,9 @@ os_event_wait_time(
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __WIN__
|
||||
/**************************************************************
|
||||
Waits for any event in an event array. Returns if even a single
|
||||
Waits for any event in an OS native event array. Returns if even a single
|
||||
one is signaled or becomes signaled. */
|
||||
|
||||
ulint
|
||||
@@ -282,39 +384,33 @@ os_event_wait_multiple(
|
||||
which was signaled */
|
||||
ulint n, /* in: number of events in the
|
||||
array */
|
||||
os_event_t* event_array) /* in: pointer to an array of event
|
||||
os_native_event_t* native_event_array)
|
||||
/* in: pointer to an array of event
|
||||
handles */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
DWORD index;
|
||||
|
||||
ut_a(event_array);
|
||||
ut_a(native_event_array);
|
||||
ut_a(n > 0);
|
||||
|
||||
index = WaitForMultipleObjects(n,
|
||||
event_array,
|
||||
index = WaitForMultipleObjects(n, native_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);
|
||||
|
||||
return(index - WAIT_OBJECT_0);
|
||||
#else
|
||||
ut_a(n == 0);
|
||||
|
||||
/* In Posix we can only wait for a single event */
|
||||
|
||||
os_event_wait(*event_array);
|
||||
|
||||
return(0);
|
||||
#endif
|
||||
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
|
||||
os_thread_exit(NULL);
|
||||
}
|
||||
|
||||
return(index - WAIT_OBJECT_0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
Creates an operating system mutex semaphore.
|
||||
Because these are slow, the mutex semaphore of the database
|
||||
itself (sync_mutex_t) should be used where possible. */
|
||||
Creates an operating system mutex semaphore. Because these are slow, the
|
||||
mutex semaphore of InnoDB itself (mutex_t) should be used where possible. */
|
||||
|
||||
os_mutex_t
|
||||
os_mutex_create(
|
||||
@@ -331,30 +427,35 @@ os_mutex_create(
|
||||
FALSE, /* Initial state: no owner */
|
||||
name);
|
||||
ut_a(mutex);
|
||||
#else
|
||||
os_fast_mutex_t* mutex;
|
||||
os_mutex_t mutex_str;
|
||||
|
||||
UT_NOT_USED(name);
|
||||
|
||||
mutex = ut_malloc(sizeof(os_fast_mutex_t));
|
||||
|
||||
os_fast_mutex_init(mutex);
|
||||
#endif
|
||||
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
||||
|
||||
mutex_str->handle = mutex;
|
||||
mutex_str->count = 0;
|
||||
|
||||
return(mutex_str);
|
||||
#else
|
||||
os_fast_mutex_t* os_mutex;
|
||||
os_mutex_t mutex_str;
|
||||
if (os_sync_mutex_inited) {
|
||||
/* When creating os_sync_mutex itself we cannot reserve it */
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
}
|
||||
|
||||
UT_NOT_USED(name);
|
||||
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
|
||||
|
||||
os_mutex = ut_malloc(sizeof(os_fast_mutex_t));
|
||||
os_mutex_count++;
|
||||
|
||||
os_fast_mutex_init(os_mutex);
|
||||
|
||||
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
|
||||
|
||||
mutex_str->handle = os_mutex;
|
||||
mutex_str->count = 0;
|
||||
if (os_sync_mutex_inited) {
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
}
|
||||
|
||||
return(mutex_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
@@ -394,21 +495,14 @@ os_mutex_exit(
|
||||
/*==========*/
|
||||
os_mutex_t mutex) /* in: mutex to release */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
ut_a(mutex);
|
||||
|
||||
ut_a(mutex->count == 1);
|
||||
|
||||
(mutex->count)--;
|
||||
|
||||
#ifdef __WIN__
|
||||
ut_a(ReleaseMutex(mutex->handle));
|
||||
#else
|
||||
ut_a(mutex);
|
||||
|
||||
ut_a(mutex->count == 1);
|
||||
|
||||
(mutex->count)--;
|
||||
|
||||
os_fast_mutex_unlock(mutex->handle);
|
||||
#endif
|
||||
}
|
||||
@@ -421,10 +515,19 @@ os_mutex_free(
|
||||
/*==========*/
|
||||
os_mutex_t mutex) /* in: mutex to free */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
ut_a(mutex);
|
||||
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
|
||||
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
|
||||
|
||||
os_mutex_count--;
|
||||
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
|
||||
#ifdef __WIN__
|
||||
ut_a(CloseHandle(mutex->handle));
|
||||
|
||||
ut_free(mutex);
|
||||
#else
|
||||
os_fast_mutex_free(mutex->handle);
|
||||
@@ -452,6 +555,18 @@ os_fast_mutex_init(
|
||||
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
|
||||
#endif
|
||||
#endif
|
||||
if (os_sync_mutex_inited) {
|
||||
/* When creating os_sync_mutex itself (in Unix) we cannot
|
||||
reserve it */
|
||||
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
}
|
||||
|
||||
os_fast_mutex_count++;
|
||||
|
||||
if (os_sync_mutex_inited) {
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
@@ -499,4 +614,9 @@ os_fast_mutex_free(
|
||||
#else
|
||||
ut_a(0 == pthread_mutex_destroy(fast_mutex));
|
||||
#endif
|
||||
os_mutex_enter(os_sync_mutex);
|
||||
|
||||
os_fast_mutex_count--;
|
||||
|
||||
os_mutex_exit(os_sync_mutex);
|
||||
}
|
||||
|
@@ -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);
|
||||
@@ -170,6 +177,30 @@ os_thread_create(
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Exits the current thread. */
|
||||
|
||||
void
|
||||
os_thread_exit(
|
||||
/*===========*/
|
||||
void* exit_value) /* in: exit value; in Windows this void*
|
||||
is cast as a DWORD */
|
||||
{
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("A thread exits.\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
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. */
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@@ -856,6 +856,7 @@ srv_release_max_if_no_queries(void)
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/***********************************************************************
|
||||
Releases one utility thread if no queries are active and
|
||||
the high-water mark 2 for the utility is exceeded. */
|
||||
@@ -890,7 +891,6 @@ srv_release_one_if_no_queries(void)
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/***********************************************************************
|
||||
Decrements the utility meter by the value given and suspends the calling
|
||||
thread, which must be an utility thread of the type given, if necessary. */
|
||||
@@ -1001,6 +1001,8 @@ srv_communication_init(
|
||||
ut_a(ret == 0);
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
|
||||
/*************************************************************************
|
||||
Implements the recovery utility. */
|
||||
static
|
||||
@@ -1060,6 +1062,7 @@ srv_purge_thread(
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif /* notdefined */
|
||||
|
||||
/*************************************************************************
|
||||
Creates the utility threads. */
|
||||
@@ -1090,6 +1093,7 @@ srv_create_utility_threads(void)
|
||||
ut_a(thread); */
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/*************************************************************************
|
||||
Implements the communication threads. */
|
||||
static
|
||||
@@ -1139,6 +1143,7 @@ srv_com_thread(
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
Creates the communication threads. */
|
||||
@@ -1159,6 +1164,7 @@ srv_create_com_threads(void)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef notdefined
|
||||
/*************************************************************************
|
||||
Implements the worker threads. */
|
||||
static
|
||||
@@ -1203,6 +1209,7 @@ srv_worker_thread(
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
Creates the worker threads. */
|
||||
@@ -1694,6 +1701,16 @@ srv_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Frees the OS fast mutex created in srv_init(). */
|
||||
|
||||
void
|
||||
srv_free(void)
|
||||
/*==========*/
|
||||
{
|
||||
os_fast_mutex_free(&srv_conc_mutex);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Initializes the synchronization primitives, memory system, and the thread
|
||||
local storage. */
|
||||
@@ -1702,67 +1719,14 @@ void
|
||||
srv_general_init(void)
|
||||
/*==================*/
|
||||
{
|
||||
os_sync_init();
|
||||
sync_init();
|
||||
mem_init(srv_mem_pool_size);
|
||||
thr_local_init();
|
||||
}
|
||||
|
||||
|
||||
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
|
||||
/* NetWare requires some cleanup of mutexes */
|
||||
|
||||
/*************************************************************************
|
||||
Deinitializes the synchronization primitives, memory system, and the thread
|
||||
local storage. */
|
||||
|
||||
void
|
||||
srv_general_free(void)
|
||||
/*==================*/
|
||||
{
|
||||
sync_close();
|
||||
}
|
||||
#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
|
||||
@@ -2499,6 +2463,10 @@ srv_lock_timeout_and_monitor_thread(
|
||||
char* buf;
|
||||
ulint i;
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Lock timeout thread starts\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
UT_NOT_USED(arg);
|
||||
srv_last_monitor_time = time(NULL);
|
||||
last_table_monitor_time = time(NULL);
|
||||
@@ -2639,6 +2607,10 @@ loop:
|
||||
exit_func:
|
||||
srv_lock_timeout_and_monitor_active = FALSE;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
@@ -2664,6 +2636,10 @@ srv_error_monitor_thread(
|
||||
ulint cnt = 0;
|
||||
|
||||
UT_NOT_USED(arg);
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Error monitor thread starts\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
loop:
|
||||
srv_error_monitor_active = TRUE;
|
||||
|
||||
@@ -2700,6 +2676,11 @@ loop:
|
||||
|
||||
srv_error_monitor_active = FALSE;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit. */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
@@ -2778,6 +2759,10 @@ srv_master_thread(
|
||||
|
||||
UT_NOT_USED(arg);
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Master thread starts\n");
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
srv_main_thread_process_no = os_proc_get_number();
|
||||
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
|
||||
|
||||
@@ -3013,6 +2998,15 @@ background_loop:
|
||||
|
||||
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
|
||||
|
||||
if (n_tables_to_drop > 0) {
|
||||
/* Do not monopolize the CPU even if there are tables waiting
|
||||
in the background drop queue. (It is essentially a bug if
|
||||
MySQL tries to drop a table while there are still open handles
|
||||
to it and we had to put it to the background drop queue.) */
|
||||
|
||||
os_thread_sleep(100000);
|
||||
}
|
||||
|
||||
srv_main_thread_op_info = (char*)"purging";
|
||||
|
||||
if (srv_fast_shutdown && srv_shutdown_state > 0) {
|
||||
@@ -3139,11 +3133,25 @@ 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: */
|
||||
|
||||
goto loop;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit.
|
||||
The thread actually never comes here because it is exited in an
|
||||
os_event_wait(). */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
|
@@ -414,8 +414,10 @@ io_handler_thread(
|
||||
|
||||
segment = *((ulint*)arg);
|
||||
|
||||
/* printf("Io handler thread %lu starts\n", segment); */
|
||||
|
||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||
printf("Io handler thread %lu starts\n", segment);
|
||||
printf("Thread id %lu\n", os_thread_pf(os_thread_get_curr_id()));
|
||||
#endif
|
||||
for (i = 0;; i++) {
|
||||
fil_aio_wait(segment);
|
||||
|
||||
@@ -424,6 +426,13 @@ io_handler_thread(
|
||||
mutex_exit(&ios_mutex);
|
||||
}
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit.
|
||||
The thread actually never comes here because it is exited in an
|
||||
os_event_wait(). */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
#ifndef __WIN__
|
||||
return(NULL);
|
||||
#else
|
||||
@@ -1442,9 +1451,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);
|
||||
@@ -1470,6 +1477,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);
|
||||
@@ -1482,7 +1491,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();
|
||||
@@ -1494,30 +1503,88 @@ 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 and the os_fast_mutexes inside
|
||||
them */
|
||||
|
||||
sync_close();
|
||||
|
||||
/* 4. Free the os_conc_mutex and all os_events and os_mutexes */
|
||||
|
||||
/* 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 (os_thread_count != 0
|
||||
|| os_event_count != 0
|
||||
|| os_mutex_count != 0
|
||||
|| os_fast_mutex_count != 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: some resources were not cleaned up in shutdown:\n"
|
||||
"InnoDB: threads %lu, events %lu, os_mutexes %lu, os_fast_mutexes %lu\n",
|
||||
os_thread_count, os_event_count, os_mutex_count,
|
||||
os_fast_mutex_count);
|
||||
}
|
||||
|
||||
if (srv_print_verbose_log) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Shutdown completed\n");
|
||||
}
|
||||
|
||||
return((int) DB_SUCCESS);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
|
||||
|
||||
mutex_enter(&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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@@ -190,6 +190,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);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@@ -436,7 +436,6 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
||||
(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_rpl_status, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
||||
@@ -1159,9 +1162,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
|
||||
|
@@ -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;
|
||||
|
2
mysql-test/r/have_mest_timezone.require
Normal file
2
mysql-test/r/have_mest_timezone.require
Normal file
@@ -0,0 +1,2 @@
|
||||
Variable_name Value
|
||||
timezone MEST
|
@@ -66,3 +66,17 @@ INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
|
||||
SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2
|
||||
WHERE numeropost=9 ORDER BY numreponse ASC;
|
||||
DROP TABLE IF EXISTS crash1,crash2;
|
||||
drop table if exists t1;
|
||||
drop table if exists 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;
|
||||
|
@@ -8,4 +8,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;
|
||||
|
@@ -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;
|
||||
|
@@ -501,22 +501,62 @@ drop table t1;
|
||||
show status like "Qcache_queries_in_cache";
|
||||
Variable_name Value
|
||||
Qcache_queries_in_cache 0
|
||||
create table t1 (a int);
|
||||
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 1024
|
||||
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 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);
|
||||
|
@@ -23,10 +23,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
|
||||
@@ -39,3 +41,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;
|
||||
|
@@ -36,6 +36,8 @@ show binlog events from 79 limit 2,1;
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
|
||||
flush logs;
|
||||
create table t5 (a int);
|
||||
drop table t5;
|
||||
slave start;
|
||||
flush logs;
|
||||
slave stop;
|
||||
@@ -56,9 +58,11 @@ master-bin.001 1079 Query 1 1079 use test; drop table t1
|
||||
master-bin.001 1127 Rotate 1 1127 master-bin.002;pos=4
|
||||
show binlog events in 'master-bin.002';
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
master-bin.002 4 Query 1 4 use test; create table t1 (n int)
|
||||
master-bin.002 62 Query 1 62 use test; insert into t1 values (1)
|
||||
master-bin.002 122 Query 1 122 use test; drop table t1
|
||||
master-bin.002 4 Query 1 4 use test; create table t5 (a int)
|
||||
master-bin.002 62 Query 1 62 use test; drop table t5
|
||||
master-bin.002 110 Query 1 110 use test; create table t1 (n int)
|
||||
master-bin.002 168 Query 1 168 use test; insert into t1 values (1)
|
||||
master-bin.002 228 Query 1 228 use test; drop table t1
|
||||
show master logs;
|
||||
Log_name
|
||||
master-bin.001
|
||||
@@ -79,14 +83,16 @@ slave-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
|
||||
slave-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581
|
||||
slave-bin.001 1065 Exec_load 1 1056 ;file_id=1
|
||||
slave-bin.001 1088 Query 1 1079 use test; drop table t1
|
||||
slave-bin.001 1136 Rotate 2 1136 slave-bin.002;pos=4
|
||||
slave-bin.001 1136 Query 1 4 use test; create table t5 (a int)
|
||||
slave-bin.001 1194 Query 1 62 use test; drop table t5
|
||||
slave-bin.001 1242 Rotate 2 1242 slave-bin.002;pos=4
|
||||
show binlog events in 'slave-bin.002' from 4;
|
||||
Log_name Pos Event_type Server_id Orig_log_pos Info
|
||||
slave-bin.002 4 Query 1 4 use test; create table t1 (n int)
|
||||
slave-bin.002 62 Query 1 62 use test; insert into t1 values (1)
|
||||
slave-bin.002 122 Query 1 122 use test; drop table t1
|
||||
slave-bin.002 4 Query 1 110 use test; create table t1 (n int)
|
||||
slave-bin.002 62 Query 1 168 use test; insert into t1 values (1)
|
||||
slave-bin.002 122 Query 1 228 use test; drop table t1
|
||||
show slave status;
|
||||
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.002 170 slave-relay-bin.002 1457 master-bin.002 Yes Yes 0 0 170 1461
|
||||
127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1522 master-bin.002 Yes Yes 0 0 276 1526
|
||||
show binlog events in 'slave-bin.005' from 4;
|
||||
Error when executing command SHOW BINLOG EVENTS: Could not find target log
|
||||
|
25
mysql-test/r/timezone.result
Normal file
25
mysql-test/r/timezone.result
Normal file
@@ -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;
|
@@ -133,3 +133,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;
|
||||
|
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# Test some error conditions
|
||||
#
|
||||
|
||||
drop table if exists t1;
|
||||
!$1146 insert into t1 values(1);
|
||||
!$1146 delete from t1;
|
||||
!$1146 update t1 set a=1;
|
||||
create table t1 (a int);
|
||||
!$1054 select count(test.t1.b) from t1;
|
||||
!$1109 select count(not_existing_database.t1) from t1;
|
||||
!$1109 select count(not_existing_database.t1.a) from t1;
|
||||
--error 1044,1146
|
||||
select count(not_existing_database.t1.a) from not_existing_database.t1;
|
||||
!$1054 select 1 from t1 order by 2;
|
||||
!$1054 select 1 from t1 group by 2;
|
||||
!$1054 select 1 from t1 order by t1.b;
|
||||
!$1054 select count(*),b from t1;
|
||||
drop table t1;
|
32
mysql-test/t/errors.test
Normal file
32
mysql-test/t/errors.test
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# Test some error conditions
|
||||
#
|
||||
|
||||
drop table if exists t1;
|
||||
--error 1146
|
||||
insert into t1 values(1);
|
||||
--error 1146
|
||||
delete from t1;
|
||||
--error 1146
|
||||
update t1 set a=1;
|
||||
|
||||
#
|
||||
|
||||
create table t1 (a int);
|
||||
--error 1054
|
||||
select count(test.t1.b) from t1;
|
||||
--error 1109
|
||||
select count(not_existing_database.t1) from t1;
|
||||
--error 1109
|
||||
select count(not_existing_database.t1.a) from t1;
|
||||
--error 1044,1146
|
||||
select count(not_existing_database.t1.a) from not_existing_database.t1;
|
||||
--error 1054
|
||||
select 1 from t1 order by 2;
|
||||
--error 1054
|
||||
select 1 from t1 group by 2;
|
||||
--error 1054
|
||||
select 1 from t1 order by t1.b;
|
||||
--error 1054
|
||||
select count(*),b from t1;
|
||||
drop table t1;
|
@@ -68,3 +68,22 @@ WHERE numeropost=9 ORDER BY numreponse ASC;
|
||||
|
||||
DROP TABLE IF EXISTS crash1,crash2;
|
||||
|
||||
|
||||
# Addendum by Guilhem:
|
||||
# Check if a partly-completed INSERT SELECT in a MyISAM table goes
|
||||
# into the binlog
|
||||
drop table if exists t1;
|
||||
drop table if exists 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;
|
||||
--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;
|
||||
|
@@ -8,4 +8,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;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -12,3 +12,14 @@ 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;
|
||||
|
@@ -343,18 +343,35 @@ show status like "Qcache_queries_in_cache";
|
||||
#
|
||||
# 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
|
||||
|
@@ -1,5 +1,7 @@
|
||||
-- require r/have_raid.require
|
||||
disable_query_log;
|
||||
show variables like "have_raid";
|
||||
enable_query_log;
|
||||
|
||||
#
|
||||
# Test of raided tables
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#see if queries that use both
|
||||
#auto_increment and LAST_INSERT_ID()
|
||||
# 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;
|
||||
drop table if exists t1;
|
||||
@@ -22,10 +24,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;
|
||||
|
@@ -22,10 +22,32 @@ 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;
|
||||
# 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;
|
||||
|
1
mysql-test/t/timezone-master.opt
Normal file
1
mysql-test/t/timezone-master.opt
Normal file
@@ -0,0 +1 @@
|
||||
--timezone=MET
|
28
mysql-test/t/timezone.test
Normal file
28
mysql-test/t/timezone.test
Normal file
@@ -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;
|
@@ -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)
|
||||
@@ -297,9 +298,11 @@ 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 ( ; isspace(end[-1]) ; end--) ;
|
||||
|
||||
if (!value)
|
||||
{
|
||||
if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
|
||||
@@ -368,6 +371,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__
|
||||
|
@@ -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;
|
||||
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,13 +237,6 @@ 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_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 (deleted)
|
||||
if (!alarm_thread_running) /* Safety */
|
||||
{
|
||||
pthread_mutex_destroy(&LOCK_alarm);
|
||||
pthread_cond_destroy(&COND_alarm);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
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,
|
||||
|
@@ -2552,6 +2552,7 @@ void 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;
|
||||
@@ -2560,7 +2561,7 @@ void 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, ¬_used);
|
||||
}
|
||||
else
|
||||
timestamp=0;
|
||||
|
@@ -1454,7 +1454,11 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
{
|
||||
const char* tmp = first + 1;
|
||||
for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
|
||||
#ifdef USE_MB
|
||||
canDoTurboBM = (tmp == last) && !use_mb(default_charset_info);
|
||||
#else
|
||||
canDoTurboBM = tmp == last;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (canDoTurboBM)
|
||||
|
60
sql/log.cc
60
sql/log.cc
@@ -1071,6 +1071,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)
|
||||
@@ -1109,12 +1115,39 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
event_info->set_log_pos(this);
|
||||
if (event_info->write(file) ||
|
||||
file == &log_file && flush_io_cache(file))
|
||||
|
||||
/*
|
||||
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;
|
||||
error=0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the SQL command */
|
||||
|
||||
event_info->set_log_pos(this);
|
||||
if (event_info->write(file))
|
||||
goto err;
|
||||
|
||||
/* 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
|
||||
@@ -1135,6 +1168,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))
|
||||
{
|
||||
/*
|
||||
@@ -1144,8 +1180,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);
|
||||
@@ -1155,6 +1191,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)
|
||||
@@ -1177,13 +1214,14 @@ err:
|
||||
|
||||
pthread_mutex_unlock(&LOCK_log);
|
||||
|
||||
/* Flush the transactional handler log file now that we have released
|
||||
/*
|
||||
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 */
|
||||
group commit
|
||||
*/
|
||||
|
||||
if (called_handler_commit) {
|
||||
if (called_handler_commit)
|
||||
ha_commit_complete(thd);
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
@@ -1954,8 +1954,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
||||
sql_error= ER_UNKNOWN_ERROR;
|
||||
slave_print_error(rli,sql_error,
|
||||
"Error '%s' running load data infile",
|
||||
sql_error ? thd->net.last_error :
|
||||
ER_SAFE(ER_UNKNOWN_ERROR));
|
||||
ER_SAFE(sql_error));
|
||||
free_root(&thd->mem_root,0);
|
||||
return 1;
|
||||
}
|
||||
|
@@ -422,7 +422,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);
|
||||
@@ -458,6 +457,7 @@ Field *find_field_in_tables(THD *thd,Item_field *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;
|
||||
@@ -755,7 +755,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);
|
||||
|
@@ -596,7 +596,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 */
|
||||
@@ -905,6 +905,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
|
||||
@@ -967,7 +968,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);
|
||||
(void) pthread_mutex_destroy(&LOCK_rpl_status);
|
||||
(void) pthread_mutex_destroy(&LOCK_active_mi);
|
||||
@@ -1520,7 +1520,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);
|
||||
@@ -1528,7 +1527,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");
|
||||
|
||||
@@ -1557,14 +1556,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 */
|
||||
@@ -1588,6 +1582,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);
|
||||
@@ -1595,7 +1590,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);
|
||||
@@ -1637,15 +1631,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;
|
||||
}
|
||||
|
||||
@@ -1990,19 +1992,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#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)
|
||||
@@ -2059,7 +2053,6 @@ int main(int argc, char **argv)
|
||||
(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_rpl_status, MY_MUTEX_INIT_FAST);
|
||||
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
|
||||
@@ -2309,18 +2302,17 @@ The server will not act as a slave.");
|
||||
using_update_log=1;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -2558,9 +2550,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);
|
||||
|
@@ -185,6 +185,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);
|
||||
sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank",
|
||||
@@ -204,8 +205,6 @@ sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
|
||||
&opt_slave_compressed_protocol);
|
||||
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
|
||||
&slave_net_timeout);
|
||||
sys_var_bool_ptr sys_readonly("read_only",
|
||||
&opt_readonly);
|
||||
sys_var_long_ptr sys_slow_launch_time("slow_launch_time",
|
||||
&slow_launch_time);
|
||||
sys_var_thd_ulong sys_sort_buffer("sort_buffer_size",
|
||||
@@ -516,6 +515,7 @@ struct show_var_st init_vars[]= {
|
||||
{"port", (char*) &mysql_port, SHOW_INT},
|
||||
{"protocol_version", (char*) &protocol_version, SHOW_INT},
|
||||
{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},
|
||||
{sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
@@ -525,7 +525,6 @@ struct show_var_st init_vars[]= {
|
||||
#endif /* HAVE_QUERY_CACHE */
|
||||
{sys_server_id.name, (char*) &sys_server_id, SHOW_SYS},
|
||||
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
|
||||
{sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
|
||||
{"skip_external_locking", (char*) &my_disable_locking, SHOW_MY_BOOL},
|
||||
{"skip_networking", (char*) &opt_disable_networking, SHOW_BOOL},
|
||||
{"skip_show_database", (char*) &opt_skip_show_db, SHOW_BOOL},
|
||||
|
29
sql/slave.cc
29
sql/slave.cc
@@ -1320,9 +1320,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);
|
||||
@@ -2028,7 +2026,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();
|
||||
@@ -2302,6 +2304,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)
|
||||
@@ -2416,7 +2430,9 @@ slave_begin:
|
||||
rli->pending = 0;
|
||||
|
||||
//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->relay_log_name,
|
||||
@@ -3122,9 +3138,14 @@ 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
|
||||
pthread_cond_broadcast(&rli->log_space_cond);
|
||||
/*
|
||||
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 !
|
||||
rli->relay_log.wait_for_update(rli->sql_thd);
|
||||
// re-acquire data lock since we released it earlier
|
||||
|
@@ -731,7 +731,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());
|
||||
}
|
||||
|
||||
|
||||
@@ -1282,6 +1282,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;
|
||||
@@ -1308,14 +1314,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))))
|
||||
|
@@ -1350,6 +1350,24 @@ void select_insert::send_error(uint errcode,const char *err)
|
||||
::send_error(&thd->net,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);
|
||||
}
|
||||
}
|
||||
ha_rollback_stmt(thd);
|
||||
if (info.copied || info.deleted)
|
||||
{
|
||||
@@ -1365,7 +1383,10 @@ bool select_insert::send_eof()
|
||||
error=table->file->activate_all_index(thd);
|
||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
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,
|
||||
@@ -1393,10 +1414,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->net,info.copied+info.deleted,last_insert_id,buff);
|
||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -912,22 +912,32 @@ 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
|
||||
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)
|
||||
{
|
||||
DBUG_ENTER("safe_remove_from_cache");
|
||||
if (table)
|
||||
static void wait_while_table_is_used(THD *thd,TABLE *table)
|
||||
{
|
||||
DBUG_PRINT("enter",("table: %s", table->real_name));
|
||||
DBUG_ENTER("wait_while_table_is_used");
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
|
||||
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
|
||||
|
||||
#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))
|
||||
@@ -936,25 +946,31 @@ static void safe_remove_from_cache(THD *thd,TABLE *table)
|
||||
(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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
safe_remove_from_cache(thd,table);
|
||||
wait_while_table_is_used(thd,table);
|
||||
/* Close lock if this is not got with LOCK TABLES */
|
||||
if (thd->lock)
|
||||
{
|
||||
@@ -963,7 +979,9 @@ bool close_cached_table(THD *thd,TABLE *table)
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -1094,10 +1112,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
|
||||
|
||||
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
|
||||
|
||||
/* If we could open the table, close it */
|
||||
if (table_list->table)
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
close_cached_table(thd,table_list->table);
|
||||
close_cached_table(thd, table);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
|
||||
}
|
||||
if (lock_and_wait_for_table_name(thd,table_list))
|
||||
{
|
||||
error= -1;
|
||||
@@ -1498,7 +1519,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
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)
|
||||
@@ -1507,12 +1527,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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1970,6 +1996,7 @@ 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.
|
||||
*/
|
||||
if (table)
|
||||
close_cached_table(thd,table);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
goto err;
|
||||
@@ -1980,6 +2007,7 @@ 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
|
||||
*/
|
||||
if (table)
|
||||
close_cached_table(thd,table);
|
||||
VOID(quick_rm_table(old_db_type,db,old_name));
|
||||
}
|
||||
@@ -2000,6 +2028,7 @@ 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
|
||||
if (table)
|
||||
close_cached_table(thd,table); // Remove lock for table
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
goto err;
|
||||
|
@@ -182,7 +182,6 @@ int mysql_update(THD *thd,
|
||||
*/
|
||||
uint length;
|
||||
SORT_FIELD *sortorder;
|
||||
List<Item> fields;
|
||||
ha_rows examined_rows;
|
||||
|
||||
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
|
||||
|
@@ -3397,6 +3397,7 @@ keyword:
|
||||
| USE_FRM {}
|
||||
| VARIABLES {}
|
||||
| WORK_SYM {}
|
||||
| X509_SYM {}
|
||||
| YEAR_SYM {};
|
||||
|
||||
/* Option functions */
|
||||
|
50
sql/time.cc
50
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_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) -
|
||||
|
||||
/*
|
||||
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;
|
||||
(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;
|
||||
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 */
|
||||
|
||||
@@ -399,6 +411,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)
|
||||
@@ -406,7 +420,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, ¬_used));
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user