Commit 9bd57aa4 authored by Sinisa@sinisa.nasamreza.org's avatar Sinisa@sinisa.nasamreza.org

Merge sinisa@bk-internal.mysql.com:/home/bk/mysql-4.0

into sinisa.nasamreza.org:/mnt/work/mysql-4.0
parents ec4a0ee4 eebdcd0c
......@@ -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
......
This diff is collapsed.
......@@ -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':
processed_prompt.append(mysql_get_server_info(&mysql));
if (connected)
processed_prompt.append(mysql_get_server_info(&mysql));
else
processed_prompt.append("not_connected");
break;
case 'd':
processed_prompt.append(current_db ? current_db : "(none)");
break;
case 'h':
{
const char *prompt=mysql_get_host_info(&mysql);
const char *prompt;
prompt= connected ? mysql_get_host_info(&mysql) : "not_connected";
if (strstr(prompt, "Localhost"))
processed_prompt.append("localhost");
else
......@@ -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);
......
......@@ -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"
CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
if test "$OSVERSION" -gt "480100" && \
test "$OSVERSION" -lt "500000" || \
test "$OSVERSION" -gt "500109"
then
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
else
CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
fi
;;
*netbsd*)
echo "Adding flag -Dunix"
......
/* 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;
#else
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;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(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
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
......@@ -113,14 +154,15 @@ os_event_wait_multiple(
/*===================*/
/* out: index of the event
which was signaled */
ulint n, /* in: number of events in the
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_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);
}
......@@ -998,6 +998,8 @@ log_group_file_header_flush(
{
byte* buf;
ulint dest_offset;
UT_NOT_USED(type);
ut_ad(mutex_own(&(log_sys->mutex)));
......@@ -1068,8 +1070,8 @@ log_group_write_buf(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
if (new_data_offset == 0) {
write_header = TRUE;
......@@ -2901,10 +2903,9 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn;
ulint arch_log_no;
if (srv_print_verbose_log)
{
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Starting shutdown...\n");
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Starting shutdown...\n");
}
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
......@@ -3006,15 +3007,17 @@ loop:
goto loop;
}
/* Make some checks that the server really is quiet */
ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
fil_flush_file_spaces(FIL_TABLESPACE);
if (srv_print_verbose_log)
{
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n");
}
/* Make some checks that the server really is quiet */
ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
/**********************************************************
......
......@@ -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
}
......@@ -1404,6 +1417,50 @@ os_aio_init(
pthread_sigmask(SIG_BLOCK, &sigset, NULL); */
#endif
}
#ifdef WIN_ASYNC_IO
/****************************************************************************
Wakes up all async i/o threads in the array in Windows async i/o at
shutdown. */
static
void
os_aio_array_wake_win_aio_at_shutdown(
/*==================================*/
os_aio_array_t* array) /* in: aio array */
{
ulint i;
for (i = 0; i < array->n_slots; i++) {
os_event_set((array->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
......@@ -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);
}
......@@ -1818,7 +1875,7 @@ os_aio(
offset where to read or write */
ulint offset_high, /* in: most significant 32 bits of
offset */
ulint n, /* in: number of bytes to read or write */
ulint n, /* in: number of bytes to read or write */
void* message1,/* in: messages for the aio handler (these
can be used to identify a completed aio
operation); if mode is OS_AIO_SYNC, these
......@@ -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);
......@@ -1940,8 +1998,7 @@ try_again:
#ifdef WIN_ASYNC_IO
if (os_aio_use_native_aio) {
if ((ret && len == n)
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|| (!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;
}
......
This diff is collapsed.
/******************************************************
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. */
......@@ -1000,6 +1000,8 @@ srv_communication_init(
ut_a(ret == 0);
}
#ifdef notdefined
/*************************************************************************
Implements the recovery utility. */
......@@ -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. */
......@@ -1693,76 +1700,33 @@ srv_init(void)
ut_a(conc_slot->event);
}
}
/*************************************************************************
Initializes the synchronization primitives, memory system, and the thread
local storage. */
Frees the OS fast mutex created in srv_init(). */
void
srv_general_init(void)
/*==================*/
srv_free(void)
/*==========*/
{
sync_init();
mem_init(srv_mem_pool_size);
thr_local_init();
os_fast_mutex_free(&srv_conc_mutex);
}
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/*************************************************************************
Deinitializes the synchronization primitives, memory system, and the thread
Initializes the synchronization primitives, memory system, and the thread
local storage. */
void
srv_general_free(void)
srv_general_init(void)
/*==================*/
{
sync_close();
os_sync_init();
sync_init();
mem_init(srv_mem_pool_size);
thr_local_init();
}
#endif /* __NETWARE__ */
/*======================= InnoDB Server FIFO queue =======================*/
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/*************************************************************************
Deinitializes the server. */
void
srv_free(void)
/*==========*/
{
srv_conc_slot_t* conc_slot;
srv_slot_t* slot;
ulint i;
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
slot = srv_table_get_nth_slot(i);
os_event_free(slot->event);
}
/* TODO: free(srv_sys->threads); */
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
slot = srv_mysql_table + i;
os_event_free(slot->event);
}
/* TODO: free(srv_mysql_table); */
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
conc_slot = srv_conc_slots + i;
os_event_free(conc_slot->event);
}
}
#endif /* __NETWARE__ */
/*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads
......@@ -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);
mutex_enter(&mutex_list_mutex);
if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
UT_LIST_REMOVE(list, mutex_list, mutex);
mutex_enter(&mutex_list_mutex);
mutex_exit(&mutex_list_mutex);
UT_LIST_REMOVE(list, mutex_list, mutex);
mutex_exit(&mutex_list_mutex);
}
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
......@@ -1230,13 +1232,26 @@ sync_init(void)
}
/**********************************************************************
Frees the resources in synchronization data structures. */
Frees the resources in InnoDB's own synchronization data structures. Use
os_sync_free() after calling this. */
void
sync_close(void)
/*===========*/
{
mutex_t* mutex;
sync_array_free(sync_primary_wait_array);
mutex = UT_LIST_GET_FIRST(mutex_list);
while (mutex) {
mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(mutex_list);
}
mutex_free(&mutex_list_mutex);
mutex_free(&sync_thread_mutex);
}
/***********************************************************************
......
......@@ -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;
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 0
select * from t1;
a
set GLOBAL query_cache_size=10240;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=20480;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=40960;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=51200;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 51200
select * from t1;
a
set GLOBAL query_cache_size=61440;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 1024
query_cache_size 61440
select * from t1;
a
set GLOBAL query_cache_size=81920;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 81920
select * from t1;
a
set GLOBAL query_cache_size=102400;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 102400
select * from t1;
a
drop table t1;
set GLOBAL query_cache_size=1048576;
create table t1 (i int not null);
create table t2 (i int not null);
......
......@@ -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
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;
#
# 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;
#
# 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
......
-- require r/have_raid.require
disable_query_log;
show variables like "have_raid";
enable_query_log;
#
# Test of raided tables
......
#see if queries that use both
#auto_increment and LAST_INSERT_ID()
#are replicated well
# 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;
......
--timezone=MET
#
# 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;
my_bool thr_alarm_inited=0;
static int alarm_aborted=1; /* No alarm thread */
my_bool thr_alarm_inited= 0;
volatile my_bool alarm_thread_running= 0;
static sig_handler process_alarm_part2(int sig);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm;
static pthread_cond_t COND_alarm;
static sigset_t full_signal_set;
static QUEUE alarm_queue;
static uint max_used_alarms=0;
pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD
static pthread_cond_t COND_alarm;
static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm)
#else
......@@ -77,6 +79,7 @@ void init_thr_alarm(uint max_alarms)
compare_ulong,NullS);
sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread)
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */
......@@ -96,7 +99,6 @@ void init_thr_alarm(uint max_alarms)
{
pthread_attr_t thr_attr;
pthread_attr_init(&thr_attr);
pthread_cond_init(&COND_alarm,NULL);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thr_attr,8196);
......@@ -136,19 +138,24 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
now=(ulong) time((time_t*) 0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
if (alarm_aborted)
if (alarm_aborted > 0)
{ /* No signal thread */
DBUG_PRINT("info", ("alarm aborted"));
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
}
if (alarm_aborted < 0)
sec= 1; /* Abort mode */
if (alarm_queue.elements >= max_used_alarms)
{
if (alarm_queue.elements == alarm_queue.max_elements)
{
DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n");
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
......@@ -163,6 +170,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
{
DBUG_PRINT("info", ("failed my_malloc()"));
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
......@@ -219,6 +227,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
break;
}
}
DBUG_ASSERT(!*alarmed || found);
if (!found)
{
#ifdef MAIN
......@@ -228,14 +237,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
(long) *alarmed));
}
if (alarm_aborted && !alarm_queue.elements)
{
delete_queue(&alarm_queue);
pthread_mutex_unlock(&LOCK_alarm);
pthread_mutex_destroy(&LOCK_alarm);
}
else
pthread_mutex_unlock(&LOCK_alarm);
pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_VOID_RETURN;
}
......@@ -365,31 +367,66 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
/*
Shedule all alarms now.
When all alarms are given, Free alarm memory and don't allow more alarms.
Schedule all alarms now and optionally free all structures
SYNPOSIS
end_thr_alarm()
free_structures Set to 1 if we should free memory used for
the alarm queue.
When we call this we should KNOW that there
is no active alarms
IMPLEMENTATION
Set alarm_abort to -1 which will change the behavior of alarms as follows:
- All old alarms will be rescheduled at once
- All new alarms will be rescheduled to one second
*/
void end_thr_alarm(void)
void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
if (!alarm_aborted)
if (alarm_aborted != 1) /* If memory not freed */
{
my_bool deleted=0;
pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
alarm_aborted=1; /* mark aborted */
if (!alarm_queue.elements)
alarm_aborted= -1; /* mark aborted */
if (alarm_queue.elements || (alarm_thread_running && free_structures))
{
deleted= 1;
delete_queue(&alarm_queue);
if (pthread_equal(pthread_self(),alarm_thread))
alarm(1); /* Shut down everything soon */
else
reschedule_alarms();
}
if (free_structures)
{
struct timespec abstime;
/*
The following test is just for safety, the caller should not
depend on this
*/
DBUG_ASSERT(!alarm_queue.elements);
/* Wait until alarm thread dies */
set_timespec(abstime, 10); /* Wait up to 10 seconds */
while (alarm_thread_running)
{
int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
if (error == ETIME || error == ETIMEDOUT)
break; /* Don't wait forever */
}
if (!alarm_queue.elements)
{
delete_queue(&alarm_queue);
alarm_aborted= 1;
pthread_mutex_unlock(&LOCK_alarm);
if (!alarm_thread_running) /* Safety */
{
pthread_mutex_destroy(&LOCK_alarm);
pthread_cond_destroy(&COND_alarm);
}
}
}
if (pthread_equal(pthread_self(),alarm_thread))
alarm(1); /* Shut down everything soon */
else
reschedule_alarms();
pthread_mutex_unlock(&LOCK_alarm);
if (deleted)
pthread_mutex_destroy(&LOCK_alarm);
pthread_mutex_unlock(&LOCK_alarm);
}
DBUG_VOID_RETURN;
}
......@@ -471,6 +508,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
puts("Starting alarm thread");
#endif
my_thread_init();
alarm_thread_running= 1;
pthread_mutex_lock(&LOCK_alarm);
for (;;)
{
......@@ -495,7 +533,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
}
}
}
else if (alarm_aborted)
else if (alarm_aborted == -1)
break;
else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm)))
{
......@@ -507,6 +545,8 @@ static void *alarm_handler(void *arg __attribute__((unused)))
process_alarm(0);
}
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
alarm_thread_running= 0;
pthread_cond_signal(&COND_alarm);
pthread_mutex_unlock(&LOCK_alarm);
pthread_exit(0);
return 0; /* Impossible */
......@@ -629,7 +669,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
void end_thr_alarm(void)
void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
......@@ -708,7 +748,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr)
}
}
void end_thr_alarm(void)
void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */
......@@ -907,7 +947,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
case SIGHUP:
#endif
printf("Aborting nicely\n");
end_thr_alarm();
end_thr_alarm(0);
break;
#ifdef SIGTSTP
case SIGTSTP:
......@@ -1004,10 +1044,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
if (thread_count == 1)
{
printf("Calling end_thr_alarm. This should cancel the last thread\n");
end_thr_alarm();
end_thr_alarm(0);
}
}
pthread_mutex_unlock(&LOCK_thread_count);
end_thr_alarm(1);
thr_alarm_info(&alarm_info);
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
alarm_info.active_alarms, alarm_info.max_used_alarms,
......
......@@ -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, &not_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)
......
......@@ -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;
}
/*
If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
command in the binlog inside:
SET FOREIGN_KEY_CHECKS=0;
<command>;
SET FOREIGN_KEY_CHECKS=1;
*/
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
{
Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=0", 24, 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
}
}
/* Write the SQL command */
event_info->set_log_pos(this);
if (event_info->write(file) ||
file == &log_file && flush_io_cache(file))
if (event_info->write(file))
goto err;
error=0;
/* Write log events to reset the 'run environment' of the SQL command */
if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
{
Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
}
/*
Tell for transactional table handlers up to which position in the
......@@ -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
LOCK_log; the flush is placed here to eliminate the bottleneck on the
group commit */
/*
Flush the transactional handler log file now that we have released
LOCK_log; the flush is placed here to eliminate the bottleneck on the
group commit
*/
if (called_handler_commit) {
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);
......@@ -2281,7 +2274,7 @@ int main(int argc, char **argv)
#endif
/* init_slave() must be called after the thread keys are created */
init_slave();
DBUG_ASSERT(current_thd == 0);
if (opt_bin_log && !server_id)
{
......@@ -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},
......
......@@ -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,58 +912,76 @@ mysql_rename_table(enum db_type base,
}
/*
close table in this thread and force close + reopen in other threads
This assumes that the calling thread has lock on LOCK_open
Win32 clients must also have a WRITE LOCK on the table !
Force all other threads to stop using the table
SYNOPSIS
wait_while_table_is_used()
thd Thread handler
table Table to remove from cache
NOTES
When returning, the table will be unusable for other threads until
the table is closed.
PREREQUISITES
Lock on LOCK_open
Win32 clients must also have a WRITE LOCK on the table !
*/
static void safe_remove_from_cache(THD *thd,TABLE *table)
static void wait_while_table_is_used(THD *thd,TABLE *table)
{
DBUG_ENTER("safe_remove_from_cache");
if (table)
{
DBUG_PRINT("enter",("table: %s", table->real_name));
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
/* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd,table); // end threads waiting on lock
DBUG_PRINT("enter",("table: %s", table->real_name));
DBUG_ENTER("wait_while_table_is_used");
safe_mutex_assert_owner(&LOCK_open);
#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
/* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key,
table->real_name))
{
dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--;
}
#else
(void) remove_table_from_cache(thd,table->table_cache_key,
table->real_name);
#endif
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
/* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd, table); // end threads waiting on lock
/* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key,
table->real_name))
{
dropping_tables++;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--;
}
DBUG_VOID_RETURN;
}
/*
Close a cached table
SYNOPSIS
clsoe_cached_table()
thd Thread handler
table Table to remove from cache
bool close_cached_table(THD *thd,TABLE *table)
NOTES
Function ends by signaling threads waiting for the table to try to
reopen the table.
PREREQUISITES
Lock on LOCK_open
Win32 clients must also have a WRITE LOCK on the table !
*/
static bool close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
safe_mutex_assert_owner(&LOCK_open);
if (table)
wait_while_table_is_used(thd,table);
/* Close lock if this is not got with LOCK TABLES */
if (thd->lock)
{
safe_remove_from_cache(thd,table);
/* Close lock if this is not got with LOCK TABLES */
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
thd->lock=0; // Start locked threads
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
mysql_unlock_tables(thd, thd->lock);
thd->lock=0; // Start locked threads
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
DBUG_RETURN(0);
}
......@@ -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);
pthread_mutex_lock(&LOCK_open);
close_cached_table(thd,table_list->table);
pthread_mutex_unlock(&LOCK_open);
/* If we could open the table, close it */
if (table_list->table)
{
pthread_mutex_lock(&LOCK_open);
close_cached_table(thd, table);
pthread_mutex_unlock(&LOCK_open);
}
if (lock_and_wait_for_table_name(thd,table_list))
{
error= -1;
......@@ -1494,11 +1515,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
*fn_ext(new_name)=0;
close_cached_table(thd,table);
close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1;
}
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
......@@ -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);
error= table->file->activate_all_index(thd);
VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table);
VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->activate_all_index(thd);
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
safe_remove_from_cache(thd,table);
VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table);
VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR);
/* COND_refresh will be signaled in close_thread_tables() */
break;
}
}
......@@ -1936,7 +1962,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
if (close_cached_table(thd,table))
if (close_cached_table(thd, table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
......@@ -1970,7 +1996,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
This shouldn't happen. We solve this the safe way by
closing the locked table.
*/
close_cached_table(thd,table);
if (table)
close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
......@@ -1980,7 +2007,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Not table locking or alter table with rename
free locks and remove old table
*/
close_cached_table(thd,table);
if (table)
close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name));
}
else
......@@ -2000,7 +2028,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0))
{ // This shouldn't happen
close_cached_table(thd,table); // Remove lock for table
if (table)
close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
}
......
......@@ -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 */
......
......@@ -28,7 +28,6 @@ uchar *days_in_month= (uchar*) "\037\034\037\036\037\036\037\037\036\037\036\037
/* Currently only my_time_zone is inited */
static long my_time_zone=0;
pthread_mutex_t LOCK_timezone;
void init_time(void)
{
......@@ -39,14 +38,14 @@ void init_time(void)
seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp);
l_time= &tm_tmp;
my_time_zone=0;
my_time_zone= 3600; /* Comp. for -3600 in my_gmt_sec */
my_time.year= (uint) l_time->tm_year+1900;
my_time.month= (uint) l_time->tm_mon+1;
my_time.day= (uint) l_time->tm_mday;
my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min;
my_time.second= (uint) l_time->tm_sec;
VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */
my_time.second= (uint) l_time->tm_sec;
my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
}
/*
......@@ -57,26 +56,39 @@ void init_time(void)
*/
long my_gmt_sec(TIME *t)
long my_gmt_sec(TIME *t, long *my_timezone)
{
uint loop;
time_t tmp;
struct tm *l_time,tm_tmp;
long diff;
long diff, current_timezone;
if (t->hour >= 24)
{ /* Fix for time-loop */
t->day+=t->hour/24;
t->hour%=24;
}
pthread_mutex_lock(&LOCK_timezone);
tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
(long) days_at_timestart)*86400L + (long) t->hour*3600L +
(long) (t->minute*60 + t->second)) + (time_t) my_time_zone;
/*
Calculate the gmt time based on current time and timezone
The -1 on the end is to ensure that if have a date that exists twice
(like 2002-10-27 02:00:0 MET), we will find the initial date.
By doing -3600 we will have to call localtime_r() several times, but
I couldn't come up with a better way to get a repeatable result :(
We can't use mktime() as it's buggy on many platforms and not thread safe.
*/
tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
(long) days_at_timestart)*86400L + (long) t->hour*3600L +
(long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
3600);
current_timezone= my_time_zone;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
for (loop=0;
loop < 3 &&
loop < 2 &&
(t->hour != (uint) l_time->tm_hour ||
t->minute != (uint) l_time->tm_min);
loop++)
......@@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t)
days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
(long) (60*((int) t->minute - (int) l_time->tm_min)));
my_time_zone+=diff;
tmp+=(time_t) diff;
current_timezone+= diff+3600; // Compensate for -3600 above
tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
}
/* Fix that if we are in the not existing daylight saving time hour
we move the start of the next real hour */
if (loop == 3 && t->hour != (uint) l_time->tm_hour)
/*
Fix that if we are in the not existing daylight saving time hour
we move the start of the next real hour
*/
if (loop == 2 && t->hour != (uint) l_time->tm_hour)
{
int days= t->day - l_time->tm_mday;
if (days < -1)
......@@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t)
if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600)
tmp-=t->minute*60 + t->second; // Move to next hour
tmp-=t->minute*60 + t->second; // Move to previous hour
}
if ((my_time_zone >=0 ? my_time_zone: -my_time_zone) > 3600L*12)
my_time_zone=0; /* Wrong date */
pthread_mutex_unlock(&LOCK_timezone);
*my_timezone= current_timezone;
return (long) tmp;
} /* my_gmt_sec */
......@@ -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, &not_used));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment