Merge with 4.0.13

This commit is contained in:
monty@narttu.mysql.fi 2003-06-04 19:21:51 +03:00
commit 40109c574a
61 changed files with 1151 additions and 337 deletions

View File

@ -71,6 +71,22 @@ else
make=make make=make
fi fi
if test -z $CXX ; then if test -z "$CXX" ; then
CXX=gcc CXX=gcc
fi 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

View File

@ -39,6 +39,7 @@ jani@hynda.mysql.fi
jani@janikt.pp.saunalahti.fi jani@janikt.pp.saunalahti.fi
jani@rhols221.adsl.netsonic.fi jani@rhols221.adsl.netsonic.fi
jani@rhols221.arenanet.fi jani@rhols221.arenanet.fi
jani@ua126d19.elisa.omakaista.fi
jcole@abel.spaceapes.com jcole@abel.spaceapes.com
jcole@main.burghcom.com jcole@main.burghcom.com
jcole@mugatu.spaceapes.com jcole@mugatu.spaceapes.com

View File

@ -44,7 +44,7 @@
#include <locale.h> #include <locale.h>
#endif #endif
const char *VER= "14.0"; const char *VER= "14.1";
/* Don't try to make a nice table if the data is too big */ /* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024 #define MAX_COLUMN_LENGTH 1024
@ -2929,14 +2929,18 @@ static const char* construct_prompt()
add_int_to_prompt(++prompt_counter); add_int_to_prompt(++prompt_counter);
break; break;
case 'v': case 'v':
if (connected)
processed_prompt.append(mysql_get_server_info(&mysql)); processed_prompt.append(mysql_get_server_info(&mysql));
else
processed_prompt.append("not_connected");
break; break;
case 'd': case 'd':
processed_prompt.append(current_db ? current_db : "(none)"); processed_prompt.append(current_db ? current_db : "(none)");
break; break;
case 'h': 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")) if (strstr(prompt, "Localhost"))
processed_prompt.append("localhost"); processed_prompt.append("localhost");
else else
@ -2948,8 +2952,13 @@ static const char* construct_prompt()
} }
case 'p': case 'p':
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (!connected)
{
processed_prompt.append("not_connected");
break;
}
if (strstr(mysql_get_host_info(&mysql),"TCP/IP") || if (strstr(mysql_get_host_info(&mysql),"TCP/IP") ||
! mysql.unix_socket) !mysql.unix_socket)
add_int_to_prompt(mysql.port); add_int_to_prompt(mysql.port);
else else
{ {

View File

@ -523,8 +523,12 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
if (!my_stat(eval_file, &stat_info, MYF(MY_WME))) if (!my_stat(eval_file, &stat_info, MYF(MY_WME)))
die(NullS); 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); DBUG_RETURN(2);
}
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME)))) if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS); die(NullS);

View File

@ -359,7 +359,7 @@ then
# we will gets some problems when linking static programs. # we will gets some problems when linking static programs.
# The following code is used to fix this problem. # The following code is used to fix this problem.
if test "$CXX" = "gcc" if test "$CXX" = "gcc" -o "$CXX" = "ccache gcc"
then then
if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1 if $CXX -v 2>&1 | grep 'version 3' > /dev/null 2>&1
then then
@ -1023,8 +1023,16 @@ case $SYSTEM_TYPE in
;; ;;
*freebsd*) *freebsd*)
echo "Adding fix for interrupted reads" echo "Adding fix for interrupted reads"
OSVERSION=`sysctl -a | grep osreldate | awk '{ print $2 }'`
if test "$OSVERSION" -gt "480100" && \
test "$OSVERSION" -lt "500000" || \
test "$OSVERSION" -gt "500109"
then
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000"
else
CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH" CFLAGS="$CFLAGS -DHAVE_BROKEN_REALPATH"
CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH" CXXFLAGS="$CXXFLAGS -DMYSQLD_NET_RETRY_COUNT=1000000 -DHAVE_BROKEN_REALPATH"
fi
;; ;;
*netbsd*) *netbsd*)
echo "Adding flag -Dunix" echo "Adding flag -Dunix"

View File

@ -138,6 +138,11 @@ typedef uint rf_SetTimer;
#define SIZEOF_LONG 4 #define SIZEOF_LONG 4
#define SIZEOF_LONG_LONG 8 #define SIZEOF_LONG_LONG 8
#define SIZEOF_OFF_T 8 #define SIZEOF_OFF_T 8
#ifdef _WIN64
#define SIZEOF_CHARP 8
#else
#define SIZEOF_CHARP 4
#endif
#define HAVE_BROKEN_NETINET_INCLUDES #define HAVE_BROKEN_NETINET_INCLUDES
#ifdef __NT__ #ifdef __NT__
#define HAVE_NAMED_PIPE /* We can only create pipes on NT */ #define HAVE_NAMED_PIPE /* We can only create pipes on NT */
@ -203,6 +208,7 @@ inline double ulonglong2double(ulonglong value)
/* Optimized store functions for Intel x86 */ /* Optimized store functions for Intel x86 */
#ifndef _WIN64
#define sint2korr(A) (*((int16 *) (A))) #define sint2korr(A) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ #define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \ (((uint32) 255L << 24) | \
@ -243,7 +249,7 @@ inline double ulonglong2double(ulonglong value)
#define float8get(V,M) doubleget((V),(M)) #define float8get(V,M) doubleget((V),(M))
#define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float)) #define float4store(V,M) memcpy((byte*) V,(byte*) (&M),sizeof(float))
#define float8store(V,M) doublestore((V),(M)) #define float8store(V,M) doublestore((V),(M))
#endif /* _WIN64 */
#define HAVE_PERROR #define HAVE_PERROR
#define HAVE_VFPRINT #define HAVE_VFPRINT

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2000 MySQL AB /* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -266,7 +266,7 @@ C_MODE_END
# endif # endif
#endif /* TIME_WITH_SYS_TIME */ #endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_UNISTD_H #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 #define crypt unistd_crypt
#endif #endif
#include <unistd.h> #include <unistd.h>
@ -654,7 +654,15 @@ extern double my_atof(const char*);
Max size that must be added to a so that we know Size to make Max size that must be added to a so that we know Size to make
adressable obj. adressable obj.
*/ */
#if SIZEOF_CHARP == 4
typedef long my_ptrdiff_t; 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 MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double)) #define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
/* Size to make adressable obj. */ /* Size to make adressable obj. */
@ -869,7 +877,7 @@ typedef char bool; /* Ordinary boolean values 0 1 */
*/ */
/* Optimized store functions for Intel x86 */ /* Optimized store functions for Intel x86 */
#ifdef __i386__ #if defined(__i386__) && !defined(_WIN64)
#define sint2korr(A) (*((int16 *) (A))) #define sint2korr(A) (*((int16 *) (A)))
#define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \ #define sint3korr(A) ((int32) ((((uchar) (A)[2]) & 128) ? \
(((uint32) 255L << 24) | \ (((uint32) 255L << 24) | \

View File

@ -10,6 +10,7 @@
#else #else
#define PROTOCOL_VERSION @PROTOCOL_VERSION@ #define PROTOCOL_VERSION @PROTOCOL_VERSION@
#define MYSQL_SERVER_VERSION "@VERSION@" #define MYSQL_SERVER_VERSION "@VERSION@"
#define MYSQL_BASE_VERSION "mysqld-@MYSQL_BASE_VERSION@"
#ifndef MYSQL_SERVER_SUFFIX #ifndef MYSQL_SERVER_SUFFIX
#define MYSQL_SERVER_SUFFIX "@MYSQL_SERVER_SUFFIX@" #define MYSQL_SERVER_SUFFIX "@MYSQL_SERVER_SUFFIX@"
#endif #endif

View File

@ -103,7 +103,7 @@ void init_thr_alarm(uint max_alarm);
bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff); bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
void thr_alarm_kill(pthread_t thread_id); void thr_alarm_kill(pthread_t thread_id);
void thr_end_alarm(thr_alarm_t *alarmed); 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); sig_handler process_alarm(int);
#ifndef thr_got_alarm #ifndef thr_got_alarm
bool thr_got_alarm(thr_alarm_t *alrm); bool thr_got_alarm(thr_alarm_t *alrm);

View File

@ -301,6 +301,13 @@ os_aio(
are ignored */ are ignored */
void* message2); 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 Waits until there are no pending writes in os_aio_write_array. There can
be other, synchronous, pending writes. */ be other, synchronous, pending writes. */

View File

@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri
#define os0sync_h #define os0sync_h
#include "univ.i" #include "univ.i"
#include "ut0lst.h"
#ifdef __WIN__ #ifdef __WIN__
#define os_fast_mutex_t CRITICAL_SECTION #define os_fast_mutex_t CRITICAL_SECTION
typedef void* os_event_t; typedef HANDLE os_event_t;
#else #else
typedef pthread_mutex_t os_fast_mutex_t; 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 { struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */ fields */
@ -26,9 +27,9 @@ struct os_event_struct {
not reserved */ not reserved */
pthread_cond_t cond_var; /* condition variable is used in pthread_cond_t cond_var; /* condition variable is used in
waiting for the event */ 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 #endif
typedef struct os_mutex_struct os_mutex_str_t; typedef struct os_mutex_struct os_mutex_str_t;
@ -38,6 +39,29 @@ typedef os_mutex_str_t* os_mutex_t;
#define OS_SYNC_TIME_EXCEEDED 1 #define OS_SYNC_TIME_EXCEEDED 1
/* Mutex protecting the thread count and event and OS 'slow' mutex lists */
extern os_mutex_t os_sync_mutex;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
extern ulint os_thread_count;
/* The following are approximate counters for debugging in Unix */
extern ulint os_event_count;
extern ulint os_mutex_count;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(void);
/*==============*/
/*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. */
void
os_sync_free(void);
/*==============*/
/************************************************************* /*************************************************************
Creates an event semaphore, i.e., a semaphore which may Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled. just have two states: signaled and nonsignaled.
@ -85,7 +109,10 @@ os_event_free(
/*==========*/ /*==========*/
os_event_t event); /* in: event to 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 void
os_event_wait( os_event_wait(

View File

@ -41,7 +41,6 @@ typedef os_thread_t os_thread_id_t; /* In Unix we use the thread
the thread */ the thread */
#endif #endif
/* Define a function pointer type to use in a typecast */ /* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*); typedef void* (*os_posix_f_t) (void*);
@ -83,12 +82,13 @@ os_thread_create(
os_thread_id_t* thread_id); /* out: id of the created os_thread_id_t* thread_id); /* out: id of the created
thread */ thread */
/********************************************************************* /*********************************************************************
A thread calling this function ends its execution. */ Exits the current thread. */
void void
os_thread_exit( 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. */ Returns the thread identifier of current thread. */
@ -144,7 +144,6 @@ ulint
os_thread_get_last_error(void); os_thread_get_last_error(void);
/*==========================*/ /*==========================*/
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
#include "os0thread.ic" #include "os0thread.ic"
#endif #endif

View File

@ -212,6 +212,12 @@ void
srv_init(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 Initializes the synchronization primitives, memory system, and the thread
local storage. */ local storage. */

View File

@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down; extern ibool srv_is_being_shut_down;
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP /* 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; extern ulint srv_shutdown_state;
#define SRV_SHUTDOWN_CLEANUP 1 #define SRV_SHUTDOWN_CLEANUP 1
#define SRV_SHUTDOWN_LAST_PHASE 2 #define SRV_SHUTDOWN_LAST_PHASE 2
#define SRV_SHUTDOWN_EXIT_THREADS 3
#endif #endif

View File

@ -187,7 +187,11 @@ management to ensure correct alignment for doubles etc. */
/* Another basic type we use is unsigned long integer which is intended to be /* Another basic type we use is unsigned long integer which is intended to be
equal to the word size of the machine. */ equal to the word size of the machine. */
#ifdef _WIN64
typedef unsigned __int64 ulint;
#else
typedef unsigned long int ulint; typedef unsigned long int ulint;
#endif
typedef long int lint; typedef long int lint;

View File

@ -375,7 +375,7 @@ log_pad_current_log_block(void)
log_close(); log_close();
log_release(); 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); == LOG_BLOCK_HDR_SIZE);
} }
@ -999,6 +999,8 @@ log_group_file_header_flush(
byte* buf; byte* buf;
ulint dest_offset; ulint dest_offset;
UT_NOT_USED(type);
ut_ad(mutex_own(&(log_sys->mutex))); ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(nth_file < group->n_files); ut_a(nth_file < group->n_files);
@ -1068,8 +1070,8 @@ log_group_write_buf(
ulint i; ulint i;
ut_ad(mutex_own(&(log_sys->mutex))); ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0); ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(ut_dulint_get_low(start_lsn) % 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) { if (new_data_offset == 0) {
write_header = TRUE; write_header = TRUE;
@ -2901,8 +2903,7 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn; dulint lsn;
ulint arch_log_no; ulint arch_log_no;
if (srv_print_verbose_log) if (srv_print_verbose_log) {
{
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Starting shutdown...\n"); fprintf(stderr, " InnoDB: Starting shutdown...\n");
} }
@ -3006,15 +3007,17 @@ loop:
goto 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_write_flushed_lsn_to_data_files(lsn, arch_log_no);
fil_flush_file_spaces(FIL_TABLESPACE); fil_flush_file_spaces(FIL_TABLESPACE);
if (srv_print_verbose_log) /* Make some checks that the server really is quiet */
{ ut_a(buf_all_freed());
ut_print_timestamp(stderr); ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
fprintf(stderr, " InnoDB: Shutdown completed\n");
}
} }
/********************************************************** /**********************************************************

View File

@ -295,7 +295,8 @@ os_file_handle_error(
/* out: TRUE if we should retry the /* out: TRUE if we should retry the
operation */ operation */
os_file_t file, /* in: file pointer */ os_file_t file, /* in: file pointer */
char* name) /* in: name of a file or NULL */ char* name, /* in: name of a file or NULL */
const char* operation) /* in: type of operation */
{ {
ulint err; ulint err;
@ -337,6 +338,7 @@ os_file_handle_error(
if (name) { if (name) {
fprintf(stderr, "InnoDB: File name %s\n", name); fprintf(stderr, "InnoDB: File name %s\n", name);
} }
fprintf(stderr, "InnoDB: system call %s\n", operation);
fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fprintf(stderr, "InnoDB: Cannot continue operation.\n");
@ -419,7 +421,9 @@ try_again:
if (file == INVALID_HANDLE_VALUE) { if (file == INVALID_HANDLE_VALUE) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
@ -460,7 +464,10 @@ try_again:
if (file == -1) { if (file == -1) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
@ -568,7 +575,9 @@ try_again:
if (file == INVALID_HANDLE_VALUE) { if (file == INVALID_HANDLE_VALUE) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
@ -615,7 +624,9 @@ try_again:
if (file == -1) { if (file == -1) {
*success = FALSE; *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) { if (retry) {
goto try_again; goto try_again;
@ -649,7 +660,7 @@ os_file_close(
return(TRUE); return(TRUE);
} }
os_file_handle_error(file, NULL); os_file_handle_error(file, NULL, "close");
return(FALSE); return(FALSE);
#else #else
int ret; int ret;
@ -657,7 +668,7 @@ os_file_close(
ret = close(file); ret = close(file);
if (ret == -1) { if (ret == -1) {
os_file_handle_error(file, NULL); os_file_handle_error(file, NULL, "close");
return(FALSE); return(FALSE);
} }
@ -825,7 +836,7 @@ os_file_flush(
return(TRUE); 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 /* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */ the database can get corrupt on disk */
@ -858,7 +869,7 @@ os_file_flush(
fprintf(stderr, fprintf(stderr,
" InnoDB: Error: the OS said file flush did not succeed\n"); " 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 /* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */ the database can get corrupt on disk */
@ -1099,7 +1110,7 @@ try_again:
#ifdef __WIN__ #ifdef __WIN__
error_handling: error_handling:
#endif #endif
retry = os_file_handle_error(file, NULL); retry = os_file_handle_error(file, NULL, "read");
if (retry) { if (retry) {
goto try_again; goto try_again;
@ -1295,7 +1306,6 @@ os_aio_array_create(
#endif #endif
ut_a(n > 0); ut_a(n > 0);
ut_a(n_segments > 0); ut_a(n_segments > 0);
ut_a(n % n_segments == 0);
array = ut_malloc(sizeof(os_aio_array_t)); array = ut_malloc(sizeof(os_aio_array_t));
@ -1405,6 +1415,50 @@ os_aio_init(
#endif #endif
} }
#ifdef WIN_ASYNC_IO
/****************************************************************************
Wakes up all async i/o threads in the array in Windows async i/o at
shutdown. */
static
void
os_aio_array_wake_win_aio_at_shutdown(
/*==================================*/
os_aio_array_t* array) /* in: aio array */
{
ulint i;
for (i = 0; i < array->n_slots; i++) {
os_event_set(*(array->events + i));
}
}
#endif
/****************************************************************************
Wakes up all async i/o threads so that they know to exit themselves in
shutdown. */
void
os_aio_wake_all_threads_at_shutdown(void)
/*=====================================*/
{
ulint i;
#ifdef WIN_ASYNC_IO
/* This code wakes up all ai/o threads in Windows native aio */
os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
#endif
/* This loop wakes up all simulated ai/o threads */
for (i = 0; i < os_aio_n_segments; i++) {
os_event_set(os_aio_segment_wait_events[i]);
}
}
/**************************************************************************** /****************************************************************************
Waits until there are no pending writes in os_aio_write_array. There can Waits until there are no pending writes in os_aio_write_array. There can
be other, synchronous, pending writes. */ be other, synchronous, pending writes. */
@ -1971,7 +2025,7 @@ try_again:
os_aio_array_free_slot(array, slot); os_aio_array_free_slot(array, slot);
retry = os_file_handle_error(file, name); retry = os_file_handle_error(file, name, "aio");
if (retry) { if (retry) {
@ -2070,7 +2124,7 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file)); ut_a(TRUE == os_file_flush(slot->file));
} }
} else { } else {
os_file_handle_error(slot->file, slot->name); os_file_handle_error(slot->file, slot->name, "aio");
ret_val = FALSE; ret_val = FALSE;
} }

View File

@ -17,6 +17,7 @@ Created 9/6/1995 Heikki Tuuri
#endif #endif
#include "ut0mem.h" #include "ut0mem.h"
#include "srv0start.h"
/* Type definition for an operating system mutex struct */ /* Type definition for an operating system mutex struct */
struct os_mutex_struct{ struct os_mutex_struct{
@ -27,8 +28,74 @@ struct os_mutex_struct{
do not assume that the OS mutex do not assume that the OS mutex
supports recursive locking, though supports recursive locking, though
NT seems to do that */ NT seems to do that */
UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
/* list of all 'slow' OS mutexes created */
}; };
/* Mutex protecting the thread count and the lists of OS mutexes
and events */
os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
ulint os_thread_count = 0;
/* The list of all events created (not in Windows) */
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
/* The list of all OS 'slow' mutexes */
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
/* The following are approximate counters for debugging in Unix */
ulint os_event_count = 0;
ulint os_mutex_count = 0;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(void)
/*==============*/
{
UT_LIST_INIT(os_event_list);
UT_LIST_INIT(os_mutex_list);
os_sync_mutex = os_mutex_create(NULL);
os_sync_mutex_inited = TRUE;
}
/*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. */
void
os_sync_free(void)
/*==============*/
{
os_event_t event;
os_mutex_t mutex;
event = UT_LIST_GET_FIRST(os_event_list);
while (event) {
os_event_free(event);
event = UT_LIST_GET_FIRST(os_event_list);
}
mutex = UT_LIST_GET_FIRST(os_mutex_list);
while (mutex) {
os_mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(os_mutex_list);
}
}
/************************************************************* /*************************************************************
Creates an event semaphore, i.e., a semaphore which may Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled. just have two states: signaled and nonsignaled.
@ -43,7 +110,7 @@ os_event_create(
the event is created without a name */ the event is created without a name */
{ {
#ifdef __WIN__ #ifdef __WIN__
HANDLE event; os_event_t event;
event = CreateEvent(NULL, /* No security attributes */ event = CreateEvent(NULL, /* No security attributes */
TRUE, /* Manual reset */ TRUE, /* Manual reset */
@ -75,6 +142,14 @@ os_event_create(
#endif #endif
event->is_set = FALSE; event->is_set = FALSE;
os_mutex_enter(os_sync_mutex);
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
os_event_count++;
os_mutex_exit(os_sync_mutex);
return(event); return(event);
#endif #endif
} }
@ -92,7 +167,7 @@ os_event_create_auto(
the event is created without a name */ the event is created without a name */
{ {
#ifdef __WIN__ #ifdef __WIN__
HANDLE event; os_event_t event;
event = CreateEvent(NULL, /* No security attributes */ event = CreateEvent(NULL, /* No security attributes */
FALSE, /* Auto-reset */ FALSE, /* Auto-reset */
@ -106,6 +181,8 @@ os_event_create_auto(
UT_NOT_USED(name); UT_NOT_USED(name);
ut_a(0);
return(NULL); return(NULL);
#endif #endif
} }
@ -185,12 +262,23 @@ os_event_free(
os_fast_mutex_free(&(event->os_mutex)); os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var))); ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_event_list, os_event_list, event);
os_event_count--;
os_mutex_exit(os_sync_mutex);
ut_free(event); ut_free(event);
#endif #endif
} }
/************************************************************** /**************************************************************
Waits for an event object until it is in the signaled state. */ Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state). */
void void
os_event_wait( os_event_wait(
@ -206,12 +294,20 @@ os_event_wait(
err = WaitForSingleObject(event, INFINITE); err = WaitForSingleObject(event, INFINITE);
ut_a(err == WAIT_OBJECT_0); ut_a(err == WAIT_OBJECT_0);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
#else #else
os_fast_mutex_lock(&(event->os_mutex)); os_fast_mutex_lock(&(event->os_mutex));
loop: loop:
if (event->is_set == TRUE) { if (event->is_set == TRUE) {
os_fast_mutex_unlock(&(event->os_mutex)); os_fast_mutex_unlock(&(event->os_mutex));
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
/* Ok, we may return */ /* Ok, we may return */
return; return;
@ -291,14 +387,17 @@ os_event_wait_multiple(
ut_a(event_array); ut_a(event_array);
ut_a(n > 0); ut_a(n > 0);
index = WaitForMultipleObjects(n, index = WaitForMultipleObjects(n, event_array,
event_array,
FALSE, /* Wait for any 1 event */ FALSE, /* Wait for any 1 event */
INFINITE); /* Infinite wait time INFINITE); /* Infinite wait time
limit */ limit */
ut_a(index >= WAIT_OBJECT_0); ut_a(index >= WAIT_OBJECT_0);
ut_a(index < WAIT_OBJECT_0 + n); ut_a(index < WAIT_OBJECT_0 + n);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
return(index - WAIT_OBJECT_0); return(index - WAIT_OBJECT_0);
#else #else
ut_a(n == 0); ut_a(n == 0);
@ -337,6 +436,16 @@ os_mutex_create(
mutex_str->handle = mutex; mutex_str->handle = mutex;
mutex_str->count = 0; mutex_str->count = 0;
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
return(mutex_str); return(mutex_str);
#else #else
os_fast_mutex_t* os_mutex; os_fast_mutex_t* os_mutex;
@ -353,6 +462,16 @@ os_mutex_create(
mutex_str->handle = os_mutex; mutex_str->handle = os_mutex;
mutex_str->count = 0; mutex_str->count = 0;
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
return(mutex_str); return(mutex_str);
#endif #endif
} }
@ -424,9 +543,22 @@ os_mutex_free(
#ifdef __WIN__ #ifdef __WIN__
ut_a(mutex); ut_a(mutex);
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_exit(os_sync_mutex);
ut_a(CloseHandle(mutex->handle)); ut_a(CloseHandle(mutex->handle));
ut_free(mutex); ut_free(mutex);
#else #else
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_exit(os_sync_mutex);
os_fast_mutex_free(mutex->handle); os_fast_mutex_free(mutex->handle);
ut_free(mutex->handle); ut_free(mutex->handle);
ut_free(mutex); ut_free(mutex);
@ -451,6 +583,7 @@ os_fast_mutex_init(
#else #else
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif #endif
os_mutex_count++;
#endif #endif
} }
@ -498,5 +631,6 @@ os_fast_mutex_free(
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex); DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else #else
ut_a(0 == pthread_mutex_destroy(fast_mutex)); ut_a(0 == pthread_mutex_destroy(fast_mutex));
os_mutex_count--;
#endif #endif
} }

View File

@ -1,6 +1,5 @@
/****************************************************** /******************************************************
The interface to the operating system The interface to the operating system thread control primitives
process and thread control primitives
(c) 1995 Innobase Oy (c) 1995 Innobase Oy
@ -17,6 +16,7 @@ Created 9/8/1995 Heikki Tuuri
#endif #endif
#include "srv0srv.h" #include "srv0srv.h"
#include "os0sync.h"
/******************************************************************* /*******************************************************************
Compares two thread ids for equality. */ Compares two thread ids for equality. */
@ -102,6 +102,10 @@ os_thread_create(
os_thread_t thread; os_thread_t thread;
ulint win_thread_id; 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 */ thread = CreateThread(NULL, /* no security attributes */
0, /* default size stack */ 0, /* default size stack */
(LPTHREAD_START_ROUTINE)start_f, (LPTHREAD_START_ROUTINE)start_f,
@ -144,6 +148,9 @@ os_thread_create(
exit(1); exit(1);
} }
#endif #endif
os_mutex_enter(os_sync_mutex);
os_thread_count++;
os_mutex_exit(os_sync_mutex);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10) #if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg); ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
@ -170,6 +177,26 @@ os_thread_create(
#endif #endif
} }
/*********************************************************************
Exits the current thread. */
void
os_thread_exit(
/*===========*/
void* exit_value) /* in: exit value; in Windows this void*
is cast as a DWORD */
{
os_mutex_enter(os_sync_mutex);
os_thread_count--;
os_mutex_exit(os_sync_mutex);
#ifdef __WIN__
ExitThread((DWORD)exit_value);
#else
pthread_exit(exit_value);
#endif
}
/********************************************************************* /*********************************************************************
Returns handle to the current thread. */ Returns handle to the current thread. */

View File

@ -1275,6 +1275,10 @@ row_ins_unique_report_err(
dtuple_t* entry, /* in: index entry to insert in the index */ dtuple_t* entry, /* in: index entry to insert in the index */
dict_index_t* index) /* in: 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; char* buf = dict_unique_err_buf;
/* The foreign err mutex protects also 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); ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex); mutex_exit(&dict_foreign_err_mutex);
#endif
} }
/******************************************************************* /*******************************************************************

View File

@ -1706,6 +1706,16 @@ srv_init(void)
} }
} }
/*************************************************************************
Frees the OS fast mutex created in srv_init(). */
void
srv_free(void)
/*==========*/
{
os_fast_mutex_free(&srv_conc_mutex);
}
/************************************************************************* /*************************************************************************
Initializes the synchronization primitives, memory system, and the thread Initializes the synchronization primitives, memory system, and the thread
local storage. */ local storage. */
@ -1714,67 +1724,14 @@ void
srv_general_init(void) srv_general_init(void)
/*==================*/ /*==================*/
{ {
os_sync_init();
sync_init(); sync_init();
mem_init(srv_mem_pool_size); mem_init(srv_mem_pool_size);
thr_local_init(); thr_local_init();
} }
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/*************************************************************************
Deinitializes the synchronization primitives, memory system, and the thread
local storage. */
void
srv_general_free(void)
/*==================*/
{
sync_close();
}
#endif /* __NETWARE__ */
/*======================= InnoDB Server FIFO queue =======================*/ /*======================= 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 Puts an OS thread to wait if there are too many concurrent threads
@ -2734,6 +2691,8 @@ loop:
srv_error_monitor_active = FALSE; srv_error_monitor_active = FALSE;
os_thread_exit(NULL);
#ifndef __WIN__ #ifndef __WIN__
return(NULL); return(NULL);
#else #else
@ -3173,6 +3132,13 @@ suspend_thread:
os_event_wait(event); 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 /* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */ thread goes back to loop: */

View File

@ -1481,9 +1481,7 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex); os_fast_mutex_unlock(&srv_os_test_mutex);
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) os_fast_mutex_free(&srv_os_test_mutex);
os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */
#endif /* __NETWARE__ */
if (srv_print_verbose_log) { if (srv_print_verbose_log) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
@ -1509,6 +1507,8 @@ innobase_shutdown_for_mysql(void)
/*=============================*/ /*=============================*/
/* out: DB_SUCCESS or error code */ /* out: DB_SUCCESS or error code */
{ {
ulint i;
if (!srv_was_started) { if (!srv_was_started) {
if (srv_is_being_started) { if (srv_is_being_started) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
@ -1521,7 +1521,7 @@ innobase_shutdown_for_mysql(void)
return(DB_SUCCESS); 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 */ the tablespace header(s), and copy all log data to archive */
logs_empty_and_mark_files_at_shutdown(); logs_empty_and_mark_files_at_shutdown();
@ -1533,30 +1533,77 @@ innobase_shutdown_for_mysql(void)
srv_conc_n_threads); srv_conc_n_threads);
} }
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY) /* 2. Make all threads created by InnoDB to exit */
/*
TODO: Fix this temporary solution srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
We are having a race condition occure with io_handler_thread threads.
When they yield in os_aio_simulated_handle during shutdown, this /* All threads end up waiting for certain events. Put those events
thread was able to free the memory early. to the signaled state. Then the threads will exit themselves in
*/ os_thread_event_wait(). */
os_thread_yield();
for (i = 0; i < 1000; i++) {
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
HERE OR EARLIER */
/* 1. Let the lock timeout thread exit */
os_event_set(srv_lock_timeout_thread_event);
/* 2. srv error monitor thread exits automatically, no need
to do anything here */
/* 3. We wake the master thread so that it exits */
srv_wake_master_thread();
/* 4. Exit the i/o threads */
os_aio_wake_all_threads_at_shutdown();
os_mutex_enter(os_sync_mutex);
if (os_thread_count == 0) {
/* All the threads have exited or are just exiting;
NOTE that the threads may not have completed their
exit yet. Should we use pthread_join() to make sure
they have exited? Now we just sleep 0.1 seconds and
hope that is enough! */
os_mutex_exit(os_sync_mutex);
os_thread_sleep(100000);
break;
}
os_mutex_exit(os_sync_mutex);
os_thread_sleep(100000);
}
if (i == 1000) {
fprintf(stderr,
"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n",
os_thread_count);
}
/* 3. Free all InnoDB's own mutexes */
sync_close();
/* 4. Free all OS synchronization primitives (in Windows currently
events are not freed) */
/* TODO: Where should this be called? */
srv_free(); 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(); ut_free_all_mem();
#endif
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n");
}
return((int) DB_SUCCESS); return((int) DB_SUCCESS);
} }

View File

@ -235,8 +235,7 @@ mutex_create_func(
mutex->cline = cline; mutex->cline = cline;
/* Check that lock_word is aligned; this is important on Intel */ /* Check that lock_word is aligned; this is important on Intel */
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0);
/* NOTE! The very first mutexes are not put to the mutex list */ /* 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_lock_word(mutex) == 0);
ut_a(mutex_get_waiters(mutex) == 0); ut_a(mutex_get_waiters(mutex) == 0);
if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
mutex_enter(&mutex_list_mutex); mutex_enter(&mutex_list_mutex);
UT_LIST_REMOVE(list, mutex_list, mutex); UT_LIST_REMOVE(list, mutex_list, mutex);
mutex_exit(&mutex_list_mutex); mutex_exit(&mutex_list_mutex);
}
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER) #if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex)); 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 void
sync_close(void) sync_close(void)
/*===========*/ /*===========*/
{ {
mutex_t* mutex;
sync_array_free(sync_primary_wait_array); 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);
} }
/*********************************************************************** /***********************************************************************

View File

@ -225,6 +225,8 @@ ut_free_all_mem(void)
os_fast_mutex_unlock(&ut_list_mutex); os_fast_mutex_unlock(&ut_list_mutex);
ut_a(ut_total_allocated_memory == 0); ut_a(ut_total_allocated_memory == 0);
os_fast_mutex_free(&ut_list_mutex);
} }
/************************************************************************** /**************************************************************************

View File

@ -2066,7 +2066,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE); net->vio = vio_new(sock, VIO_TYPE_SOCKET, TRUE);
bzero((char*) &UNIXaddr,sizeof(UNIXaddr)); bzero((char*) &UNIXaddr,sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX; UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, unix_socket); strmake(UNIXaddr.sun_path, unix_socket, sizeof(UNIXaddr.sun_path)-1);
if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr), if (my_connect(sock,(struct sockaddr *) &UNIXaddr, sizeof(UNIXaddr),
mysql->options.connect_timeout)) mysql->options.connect_timeout))
{ {

View File

@ -2,7 +2,7 @@
.SH NAME .SH NAME
mysql_fix_privilege_tables \- Fixes MySQL privilege tables. mysql_fix_privilege_tables \- Fixes MySQL privilege tables.
.SH SYNOPSIS .SH SYNOPSIS
mysql_fix_privilege_tables [options] mysql_fix_privilege_tables [mysql_root_password]
.SH DESCRIPTION .SH DESCRIPTION
This scripts updates the mysql.user, mysql.db, mysql.host and the This scripts updates the mysql.user, mysql.db, mysql.host and the
mysql.func tables to MySQL 3.22.14 and above. 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, 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 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 If you get 'Access denied' errors, run the script again
and give the MySQL root user password as an argument! and give the MySQL root user password as an argument.
For more information start the program with '--help'.
.SH "SEE ALSO" .SH "SEE ALSO"
mysql (1), mysqld (1) mysql (1), mysqld (1)
.SH AUTHOR .SH AUTHOR

View File

@ -13,12 +13,15 @@ DB=test
DBPASSWD= DBPASSWD=
VERBOSE="" VERBOSE=""
USE_MANAGER=0 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 # 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 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" MASTER_40_ARGS="--rpl-recovery-rank=1 --init-rpl-role=master"
@ -1163,9 +1166,18 @@ run_testcase ()
if [ -f $master_opt_file ] ; if [ -f $master_opt_file ] ;
then then
EXTRA_MASTER_OPT=`$CAT $master_opt_file | $SED -e "s;\\$MYSQL_TEST_DIR;$MYSQL_TEST_DIR;"` 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 stop_master
echo "CURRENT_TEST: $tname" >> $MASTER_MYERR echo "CURRENT_TEST: $tname" >> $MASTER_MYERR
start_master start_master
TZ=$MY_TZ; export TZ
else else
if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ] if [ ! -z "$EXTRA_MASTER_OPT" ] || [ x$MASTER_RUNNING != x1 ] || [ -f $master_init_script ]
then then

View File

@ -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 0 a 2 b A 300 NULL NULL YES BTREE
t1 1 b 1 b A 100 NULL NULL YES BTREE t1 1 b 1 b A 100 NULL NULL YES BTREE
drop table t1; 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;

View File

@ -0,0 +1,2 @@
Variable_name Value
timezone MEST

View File

@ -65,3 +65,15 @@ INSERT INTO t1 (numeropost,icone,contenu,pseudo,date,signature,ip)
SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM t2 SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM t2
WHERE numeropost=9 ORDER BY numreponse ASC; WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS t1,t2; DROP TABLE IF EXISTS t1,t2;
create table t1(a int, unique(a));
insert into t1 values(2);
create table t2(a int);
insert into t2 values(1),(2);
reset master;
insert into t1 select * from t2;
Duplicate entry '2' for key 1
show binlog events;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
master-bin.001 79 Query 1 79 use test; insert into t1 select * from t2
drop table t1, t2;

View File

@ -15,4 +15,11 @@ a b c d
0000-00-00 0000-00-00 0000-00-00 0000-00-00 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
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; drop table t1;

View File

@ -13,3 +13,15 @@ show tables like 't_';
Tables_in_test (t_) Tables_in_test (t_)
t3 t3
drop table 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;

View File

@ -502,6 +502,7 @@ drop table t1;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 0 Qcache_queries_in_cache 0
create table t1 (a int);
show global variables like "query_cache_min_res_unit"; show global variables like "query_cache_min_res_unit";
Variable_name Value Variable_name Value
query_cache_min_res_unit 4096 query_cache_min_res_unit 4096
@ -565,18 +566,57 @@ set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size"; show global variables like "query_cache_size";
Variable_name Value Variable_name Value
query_cache_size 0 query_cache_size 0
set GLOBAL query_cache_size=1100; select * from t1;
set GLOBAL query_cache_size=1200; a
set GLOBAL query_cache_size=1300; set GLOBAL query_cache_size=1024;
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;
show global variables like "query_cache_size"; show global variables like "query_cache_size";
Variable_name Value Variable_name Value
query_cache_size 1024 query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=10240;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=20480;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=40960;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=51200;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 51200
select * from t1;
a
set GLOBAL query_cache_size=61440;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 61440
select * from t1;
a
set GLOBAL query_cache_size=81920;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 81920
select * from t1;
a
set GLOBAL query_cache_size=102400;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 102400
select * from t1;
a
drop table t1;
set GLOBAL query_cache_size=1048576; set GLOBAL query_cache_size=1048576;
create table t1 (i int not null); create table t1 (i int not null);
create table t2 (i int not null); create table t2 (i int not null);

View File

@ -22,10 +22,12 @@ drop table t1;
drop table t2; drop table t2;
create table t1(a int auto_increment, key(a)); create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b)); 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 (10);
insert into t1 values (null),(null),(null); insert into t1 values (null),(null),(null);
insert into t2 values (5,0); insert into t2 values (5,0);
insert into t2 values (null,last_insert_id()); insert into t2 values (null,last_insert_id());
SET FOREIGN_KEY_CHECKS=1;
select * from t1; select * from t1;
a a
10 10
@ -38,3 +40,31 @@ b c
6 11 6 11
drop table t1; drop table t1;
drop table t2; 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;

View File

@ -0,0 +1,25 @@
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (ts int);
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
ts from_unixtime(ts)
1035673200 2002-10-27 01:00:00
1035680400 2002-10-27 02:00:00
1035684000 2002-10-27 03:00:00
1035680400 2002-10-27 02:00:00
1035673200 2002-10-27 01:00:00
1035680400 2002-10-27 02:00:00
1048986000 2003-03-30 03:00:00
1048986000 2003-03-30 03:00:00
1048989599 2003-03-30 03:59:59
1048989601 2003-03-30 04:00:01
DROP TABLE t1;

View File

@ -135,3 +135,12 @@ analyze table t1;
show keys from t1; show keys from t1;
drop table 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;

View File

@ -71,3 +71,20 @@ WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS t1,t2; DROP TABLE IF EXISTS t1,t2;
# Addendum by Guilhem:
# Check if a partly-completed INSERT SELECT in a MyISAM table goes
# into the binlog
create table t1(a int, unique(a));
insert into t1 values(2);
create table t2(a int);
insert into t2 values(1),(2);
reset master;
--error 1062
insert into t1 select * from t2;
# The above should produce an error, but still be in the binlog;
# verify the binlog :
let $VERSION=`select version()`;
--replace_result $VERSION VERSION
show binlog events;
drop table t1, t2;

View File

@ -10,4 +10,12 @@ create table t1 (a date, b date, c date not null, d date);
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ','; load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES; load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
SELECT * from t1; 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; drop table t1;

View File

@ -14,3 +14,14 @@ ALTER TABLE T2 ADD new_col int not null;
ALTER TABLE T2 RENAME T3; ALTER TABLE T2 RENAME T3;
show tables like 't_'; show tables like 't_';
drop table t3; 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;

View File

@ -371,18 +371,35 @@ show global variables like "query_cache_min_res_unit";
# #
# Test of query cache resizing # Test of query cache resizing
# #
create table t1 (a int);
set GLOBAL query_cache_size=1000; set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size"; show global variables like "query_cache_size";
set GLOBAL query_cache_size=1100; select * from t1;
set GLOBAL query_cache_size=1200; set GLOBAL query_cache_size=1024;
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;
show global variables like "query_cache_size"; 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 # Temporary tables

View File

@ -1,5 +1,7 @@
-- require r/have_raid.require -- require r/have_raid.require
disable_query_log;
show variables like "have_raid"; show variables like "have_raid";
enable_query_log;
# #
# Test of raided tables # Test of raided tables

View File

@ -1,5 +1,8 @@
# See if queries that use both auto_increment and LAST_INSERT_ID() # See if queries that use both auto_increment and LAST_INSERT_ID()
# are replicated well # are replicated well
# We also check how the foreign_key_check variable is replicated
source include/master-slave.inc; source include/master-slave.inc;
connection master; connection master;
create table t1(a int auto_increment, key(a)); create table t1(a int auto_increment, key(a));
@ -20,10 +23,30 @@ drop table t1;
drop table t2; drop table t2;
create table t1(a int auto_increment, key(a)); create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b)); 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 (10);
insert into t1 values (null),(null),(null); insert into t1 values (null),(null),(null);
insert into t2 values (5,0); insert into t2 values (5,0);
insert into t2 values (null,last_insert_id()); 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; save_master_pos;
connection slave; connection slave;
sync_with_master; sync_with_master;

View File

@ -32,11 +32,33 @@ show binlog events from 79 limit 2;
show binlog events from 79 limit 2,1; show binlog events from 79 limit 2,1;
flush logs; 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 # Sync slave and force it to start on another binary log
save_master_pos; save_master_pos;
connection slave; connection slave;
start slave; # Note that the above 'slave start' will cause a 3rd rotate event (a fake one)
# to go into the relay log (the master always sends a fake one when replication
# starts).
slave start;
sync_with_master; sync_with_master;
flush logs; flush logs;
stop slave; stop slave;

View File

@ -0,0 +1 @@
--timezone=MET

View File

@ -0,0 +1,28 @@
#
# Test of timezone handling. This script must be run with TZ=MEST
-- require r/have_mest_timezone.require
disable_query_log;
show variables like "timezone";
enable_query_log;
# Initialization
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (ts int);
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 03:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 01:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2002-10-27 02:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 02:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:00:00'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 03:59:59'));
INSERT INTO t1 (ts) VALUES (Unix_timestamp('2003-03-30 04:00:01'));
SELECT ts,from_unixtime(ts) FROM t1;
DROP TABLE t1;

View File

@ -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 *dir, const char *config_file,
const char *ext, TYPELIB *group); const char *ext, TYPELIB *group);
static char *remove_end_comment(char *ptr);
void load_defaults(const char *conf_file, const char **groups, void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv) int *argc, char ***argv)
@ -299,8 +300,9 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
} }
if (!read_values) if (!read_values)
continue; continue;
if (!(end=value=strchr(ptr,'='))) end= remove_end_comment(ptr);
end=strend(ptr); /* Option without argument */ if ((value= strchr(ptr, '=')))
end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value) if (!value)
{ {
@ -370,6 +372,29 @@ static my_bool search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
} }
static char *remove_end_comment(char *ptr)
{
char quote= 0;
for (; *ptr; ptr++)
{
if (*ptr == '\'' || *ptr == '\"')
{
if (!quote)
quote= *ptr;
else if (quote == *ptr)
quote= 0;
}
if (!quote && *ptr == '#') /* We are not inside a comment */
{
*ptr= 0;
return ptr;
}
}
return ptr;
}
void print_defaults(const char *conf_file, const char **groups) void print_defaults(const char *conf_file, const char **groups)
{ {
#ifdef __WIN__ #ifdef __WIN__

View File

@ -27,6 +27,7 @@
#include <m_string.h> #include <m_string.h>
#include <queues.h> #include <queues.h>
#include "thr_alarm.h" #include "thr_alarm.h"
#include <assert.h>
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> /* AIX needs this for fd_set */ #include <sys/select.h> /* AIX needs this for fd_set */
@ -36,21 +37,22 @@
#define ETIME ETIMEDOUT #define ETIME ETIMEDOUT
#endif #endif
static my_bool alarm_aborted=1; static int alarm_aborted=1; /* No alarm thread */
my_bool thr_alarm_inited=0; my_bool thr_alarm_inited= 0;
volatile my_bool alarm_thread_running= 0;
static sig_handler process_alarm_part2(int sig); static sig_handler process_alarm_part2(int sig);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) #if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm; static pthread_mutex_t LOCK_alarm;
static pthread_cond_t COND_alarm;
static sigset_t full_signal_set; static sigset_t full_signal_set;
static QUEUE alarm_queue; static QUEUE alarm_queue;
static uint max_used_alarms=0; static uint max_used_alarms=0;
pthread_t alarm_thread; pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD #ifdef USE_ALARM_THREAD
static pthread_cond_t COND_alarm;
static void *alarm_handler(void *arg); static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm) #define reschedule_alarms() pthread_cond_signal(&COND_alarm)
#else #else
@ -77,6 +79,7 @@ void init_thr_alarm(uint max_alarms)
compare_ulong,NullS); compare_ulong,NullS);
sigfillset(&full_signal_set); /* Neaded to block signals */ sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST); 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 THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread) #if defined(HAVE_mit_thread)
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */ 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_t thr_attr;
pthread_attr_init(&thr_attr); pthread_attr_init(&thr_attr);
pthread_cond_init(&COND_alarm,NULL);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thr_attr,8196); 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); now=(ulong) time((time_t*) 0);
pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */
if (alarm_aborted) if (alarm_aborted > 0)
{ /* No signal thread */ { /* No signal thread */
DBUG_PRINT("info", ("alarm aborted")); DBUG_PRINT("info", ("alarm aborted"));
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL); pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (alarm_aborted < 0)
sec= 1; /* Abort mode */
if (alarm_queue.elements >= max_used_alarms) if (alarm_queue.elements >= max_used_alarms)
{ {
if (alarm_queue.elements == alarm_queue.max_elements) if (alarm_queue.elements == alarm_queue.max_elements)
{ {
DBUG_PRINT("info", ("alarm queue full")); DBUG_PRINT("info", ("alarm queue full"));
fprintf(stderr,"Warning: thr_alarm queue is full\n"); fprintf(stderr,"Warning: thr_alarm queue is full\n");
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL); pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1); 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)))) if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME))))
{ {
DBUG_PRINT("info", ("failed my_malloc()")); DBUG_PRINT("info", ("failed my_malloc()"));
*alrm= 0; /* No alarm */
pthread_mutex_unlock(&LOCK_alarm); pthread_mutex_unlock(&LOCK_alarm);
pthread_sigmask(SIG_SETMASK,&old_mask,NULL); pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1); DBUG_RETURN(1);
@ -219,6 +227,7 @@ void thr_end_alarm(thr_alarm_t *alarmed)
break; break;
} }
} }
DBUG_ASSERT(!*alarmed || found);
if (!found) if (!found)
{ {
#ifdef MAIN #ifdef MAIN
@ -228,13 +237,6 @@ void thr_end_alarm(thr_alarm_t *alarmed)
DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n", DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
(long) *alarmed)); (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); pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
@ -365,31 +367,66 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
/* /*
Shedule all alarms now. Schedule all alarms now and optionally free all structures
When all alarms are given, Free alarm memory and don't allow more alarms.
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"); 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); pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
alarm_aborted=1; /* mark aborted */ alarm_aborted= -1; /* mark aborted */
if (!alarm_queue.elements) if (alarm_queue.elements || (alarm_thread_running && free_structures))
{ {
deleted= 1;
delete_queue(&alarm_queue);
}
if (pthread_equal(pthread_self(),alarm_thread)) if (pthread_equal(pthread_self(),alarm_thread))
alarm(1); /* Shut down everything soon */ alarm(1); /* Shut down everything soon */
else else
reschedule_alarms(); 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); pthread_mutex_unlock(&LOCK_alarm);
if (deleted) if (!alarm_thread_running) /* Safety */
{
pthread_mutex_destroy(&LOCK_alarm); pthread_mutex_destroy(&LOCK_alarm);
pthread_cond_destroy(&COND_alarm);
}
}
}
else
pthread_mutex_unlock(&LOCK_alarm);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -471,6 +508,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
puts("Starting alarm thread"); puts("Starting alarm thread");
#endif #endif
my_thread_init(); my_thread_init();
alarm_thread_running= 1;
pthread_mutex_lock(&LOCK_alarm); pthread_mutex_lock(&LOCK_alarm);
for (;;) for (;;)
{ {
@ -495,7 +533,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
} }
} }
} }
else if (alarm_aborted) else if (alarm_aborted == -1)
break; break;
else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) 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); process_alarm(0);
} }
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ 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_mutex_unlock(&LOCK_alarm);
pthread_exit(0); pthread_exit(0);
return 0; /* Impossible */ 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"); DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */ 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"); DBUG_ENTER("end_thr_alarm");
alarm_aborted=1; /* No more alarms */ alarm_aborted=1; /* No more alarms */
@ -907,7 +947,7 @@ static void *signal_hand(void *arg __attribute__((unused)))
case SIGHUP: case SIGHUP:
#endif #endif
printf("Aborting nicely\n"); printf("Aborting nicely\n");
end_thr_alarm(); end_thr_alarm(0);
break; break;
#ifdef SIGTSTP #ifdef SIGTSTP
case SIGTSTP: case SIGTSTP:
@ -1004,10 +1044,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
if (thread_count == 1) if (thread_count == 1)
{ {
printf("Calling end_thr_alarm. This should cancel the last thread\n"); 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); pthread_mutex_unlock(&LOCK_thread_count);
end_thr_alarm(1);
thr_alarm_info(&alarm_info); thr_alarm_info(&alarm_info);
printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
alarm_info.active_alarms, alarm_info.max_used_alarms, alarm_info.active_alarms, alarm_info.max_used_alarms,

View File

@ -2755,6 +2755,7 @@ int Field_timestamp::store(longlong nr)
if ((nr=fix_datetime(nr))) if ((nr=fix_datetime(nr)))
{ {
long not_used;
part1=(long) (nr/LL(1000000)); part1=(long) (nr/LL(1000000));
part2=(long) (nr - (longlong) part1*LL(1000000)); part2=(long) (nr - (longlong) part1*LL(1000000));
l_time.year= (int) (part1/10000L); part1%=10000L; l_time.year= (int) (part1/10000L); part1%=10000L;
@ -2763,7 +2764,7 @@ int Field_timestamp::store(longlong nr)
l_time.hour= (int) (part2/10000L); part2%=10000L; l_time.hour= (int) (part2/10000L); part2%=10000L;
l_time.minute=(int) part2 / 100; l_time.minute=(int) part2 / 100;
l_time.second=(int) part2 % 100; l_time.second=(int) part2 % 100;
timestamp=my_gmt_sec(&l_time); timestamp=my_gmt_sec(&l_time, &not_used);
} }
else else
timestamp=0; timestamp=0;

View File

@ -1200,6 +1200,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
No check for auto events flag here - this write method should No check for auto events flag here - this write method should
never be called if auto-events are enabled 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)
{ {
if (thd->last_insert_id_used) if (thd->last_insert_id_used)
@ -1245,7 +1251,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err; goto err;
} }
} }
#if 0 #ifdef TO_BE_REMOVED
if (thd->variables.convert_set) if (thd->variables.convert_set)
{ {
char buf[256], *p; char buf[256], *p;
@ -1257,12 +1263,39 @@ bool MYSQL_LOG::write(Log_event* event_info)
goto err; goto err;
} }
#endif #endif
}
event_info->set_log_pos(this); /*
if (event_info->write(file) || If the user has set FOREIGN_KEY_CHECKS=0 we wrap every SQL
file == &log_file && flush_io_cache(file)) 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; goto err;
error=0; }
}
/* Write the SQL command */
event_info->set_log_pos(this);
if (event_info->write(file))
goto err;
/* Write log events to reset the 'run environment' of the SQL command */
if (thd && thd->options & OPTION_NO_FOREIGN_KEY_CHECKS)
{
Query_log_event e(thd, "SET FOREIGN_KEY_CHECKS=1", 24, 0);
e.set_log_pos(this);
if (e.write(file))
goto err;
}
/* /*
Tell for transactional table handlers up to which position in the Tell for transactional table handlers up to which position in the
@ -1283,6 +1316,9 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file) // we are writing to the real log (disk) if (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)) if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
{ {
/* /*
@ -1292,8 +1328,8 @@ bool MYSQL_LOG::write(Log_event* event_info)
handler if the log event type is appropriate. handler if the log event type is appropriate.
*/ */
if (event_info->get_type_code() == QUERY_EVENT if (event_info->get_type_code() == QUERY_EVENT ||
|| event_info->get_type_code() == EXEC_LOAD_EVENT) event_info->get_type_code() == EXEC_LOAD_EVENT)
{ {
error = ha_report_binlog_offset_and_commit(thd, log_file_name, error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file); file->pos_in_file);
@ -1303,6 +1339,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
/* we wrote to the real log, check automatic rotation */ /* we wrote to the real log, check automatic rotation */
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size); should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
} }
error=0;
err: err:
if (error) if (error)

View File

@ -461,7 +461,6 @@ bool mysql_rename_table(enum db_type base,
const char * old_name, const char * old_name,
const char *new_db, const char *new_db,
const char * new_name); 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_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list, int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list); List<Alter_drop> &drop_list);
@ -501,6 +500,7 @@ Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length, Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid); bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
#include <openssl/des.h>
struct st_des_keyblock struct st_des_keyblock
{ {
des_cblock key1, key2, key3; des_cblock key1, key2, key3;
@ -837,7 +837,7 @@ uint calc_days_in_year(uint year);
void get_date_from_daynr(long daynr,uint *year, uint *month, void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day); uint *day);
void init_time(void); 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); time_t str_to_timestamp(const char *str,uint length);
bool str_to_time(const char *str,uint length,TIME *l_time); bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date); longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);

View File

@ -566,7 +566,7 @@ static void close_connections(void)
unix_sock= INVALID_SOCKET; unix_sock= INVALID_SOCKET;
} }
#endif #endif
end_thr_alarm(); // Don't allow alarms end_thr_alarm(0); // Abort old alarms.
end_slave(); end_slave();
/* First signal all threads that it's time to die */ /* First signal all threads that it's time to die */
@ -875,6 +875,7 @@ void clean_up(bool print_message)
#endif #endif
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */ (void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
end_key_cache(); end_key_cache();
end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID #ifdef USE_RAID
end_raid(); end_raid();
#endif #endif
@ -940,7 +941,6 @@ static void clean_up_mutexes()
(void) pthread_mutex_destroy(&LOCK_crypt); (void) pthread_mutex_destroy(&LOCK_crypt);
(void) pthread_mutex_destroy(&LOCK_bytes_sent); (void) pthread_mutex_destroy(&LOCK_bytes_sent);
(void) pthread_mutex_destroy(&LOCK_bytes_received); (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_user_conn);
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
(void) pthread_mutex_destroy(&LOCK_rpl_status); (void) pthread_mutex_destroy(&LOCK_rpl_status);
@ -1501,7 +1501,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n"); and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size); 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, "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_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections); fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count); fprintf(stderr, "threads_connected=%d\n", thread_count);
@ -1509,7 +1508,7 @@ and this may fail.\n\n");
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\ key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
bytes of memory\n", ((ulong) keybuff_size + bytes of memory\n", ((ulong) keybuff_size +
(global_system_variables.read_buff_size + (global_system_variables.read_buff_size +
thd->variables.sortbuff_size) * global_system_variables.sortbuff_size) *
max_connections)/ 1024); max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n"); fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
@ -1538,14 +1537,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
Some pointers may be invalid and cause the dump to abort...\n"); Some pointers may be invalid and cause the dump to abort...\n");
safe_print_str("thd->query", thd->query, 1024); safe_print_str("thd->query", thd->query, 1024);
fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id); 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, "\ 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"); information that should help you find out what is causing the crash.\n");
fflush(stderr); fflush(stderr);
#endif /* HAVE_STACKTRACE */ #endif /* HAVE_STACKTRACE */
@ -1569,6 +1563,7 @@ information that should help you find out what is causing the crash.\n");
static void init_signals(void) static void init_signals(void)
{ {
sigset_t set; sigset_t set;
struct sigaction sa;
DBUG_ENTER("init_signals"); DBUG_ENTER("init_signals");
sigset(THR_KILL_SIGNAL,end_thread_signal); sigset(THR_KILL_SIGNAL,end_thread_signal);
@ -1576,7 +1571,6 @@ static void init_signals(void)
if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL)) if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
{ {
struct sigaction sa;
sa.sa_flags = SA_RESETHAND | SA_NODEFER; sa.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
@ -1618,15 +1612,23 @@ static void init_signals(void)
sigaddset(&set,SIGQUIT); sigaddset(&set,SIGQUIT);
sigaddset(&set,SIGTERM); sigaddset(&set,SIGTERM);
sigaddset(&set,SIGHUP); 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 #ifdef SIGTSTP
sigaddset(&set,SIGTSTP); sigaddset(&set,SIGTSTP);
#endif #endif
sigaddset(&set,THR_SERVER_ALARM); sigaddset(&set,THR_SERVER_ALARM);
sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT sigdelset(&set,THR_KILL_SIGNAL); // May be SIGINT
sigdelset(&set,THR_CLIENT_ALARM); // For alarms 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; DBUG_VOID_RETURN;
} }
@ -1894,7 +1896,7 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif #endif
const char *load_default_groups[]= { "mysqld","server",0 }; const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0 };
bool open_log(MYSQL_LOG *log, const char *hostname, bool open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension, const char *opt_name, const char *extension,
@ -1951,19 +1953,11 @@ static int init_common_variables(const char *conf_file_name, int argc,
} }
#endif #endif
#ifdef HAVE_TZNAME #ifdef HAVE_TZNAME
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
{ {
struct tm tm_tmp; struct tm tm_tmp;
localtime_r(&start_time,&tm_tmp); localtime_r(&start_time,&tm_tmp);
strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]); 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 #endif
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0) if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
@ -2075,7 +2069,6 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_sent,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_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_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST); (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
@ -2441,14 +2434,14 @@ The server will not act as a slave.");
if (opt_bootstrap) if (opt_bootstrap)
{ {
int error=bootstrap(stdin); int error=bootstrap(stdin);
end_thr_alarm(); // Don't allow alarms end_thr_alarm(1); // Don't allow alarms
unireg_abort(error ? 1 : 0); unireg_abort(error ? 1 : 0);
} }
if (opt_init_file) if (opt_init_file)
{ {
if (read_init_file(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); unireg_abort(1);
} }
} }
@ -2620,9 +2613,12 @@ int main(int argc, char **argv)
return 0; return 0;
if (Service.IsService(argv[2])) 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; use_opt_args=1;
opt_argc=argc; opt_argc= 2; // Skip service-name
opt_argv=argv; opt_argv=argv;
start_mode= 1; start_mode= 1;
Service.Init(argv[2], mysql_service); Service.Init(argv[2], mysql_service);

View File

@ -209,6 +209,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
sys_var_thd_bool sys_new_mode("new", &SV::new_mode); sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size", sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
&SV::read_buff_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", sys_var_thd_ulong sys_read_rnd_buff_size("read_rnd_buffer_size",
&SV::read_rnd_buff_size); &SV::read_rnd_buff_size);
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
@ -596,6 +597,7 @@ struct show_var_st init_vars[]= {
{"protocol_version", (char*) &protocol_version, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, {sys_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_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
{sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS},

View File

@ -1388,9 +1388,7 @@ static bool wait_for_relay_log_space(RELAY_LOG_INFO* rli)
while (rli->log_space_limit < rli->log_space_total && while (rli->log_space_limit < rli->log_space_total &&
!(slave_killed=io_slave_killed(thd,mi)) && !(slave_killed=io_slave_killed(thd,mi)) &&
!rli->ignore_log_space_limit) !rli->ignore_log_space_limit)
{
pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock);
}
thd->proc_info = save_proc_info; thd->proc_info = save_proc_info;
pthread_mutex_unlock(&rli->log_space_lock); pthread_mutex_unlock(&rli->log_space_lock);
DBUG_RETURN(slave_killed); DBUG_RETURN(slave_killed);
@ -2101,7 +2099,11 @@ static int exec_relay_log_event(THD* thd, RELAY_LOG_INFO* rli)
Log_event * ev = next_event(rli); Log_event * ev = next_event(rli);
DBUG_ASSERT(rli->sql_thd==thd); DBUG_ASSERT(rli->sql_thd==thd);
if (sql_slave_killed(thd,rli)) if (sql_slave_killed(thd,rli))
{
/* do not forget to free ev ! */
if (ev) delete ev;
return 1; return 1;
}
if (ev) if (ev)
{ {
int type_code = ev->get_type_code(); int type_code = ev->get_type_code();
@ -2376,6 +2378,18 @@ reconnect done to recover from failed read");
goto err; goto err;
} }
flush_master_info(mi); 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 < if (mi->rli.log_space_limit && mi->rli.log_space_limit <
mi->rli.log_space_total && mi->rli.log_space_total &&
!mi->rli.ignore_log_space_limit) !mi->rli.ignore_log_space_limit)
@ -2489,7 +2503,9 @@ slave_begin:
pthread_cond_broadcast(&rli->start_cond); pthread_cond_broadcast(&rli->start_cond);
//tell the I/O thread to take relay_log_space_limit into account from now on //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; rli->ignore_log_space_limit= 0;
pthread_mutex_unlock(&rli->log_space_lock);
if (init_relay_log_pos(rli, if (init_relay_log_pos(rli,
rli->group_relay_log_name, rli->group_relay_log_name,
@ -3221,7 +3237,12 @@ Log_event* next_event(RELAY_LOG_INFO* rli)
pthread_mutex_lock(&rli->log_space_lock); pthread_mutex_lock(&rli->log_space_lock);
// prevent the I/O thread from blocking next times // prevent the I/O thread from blocking next times
rli->ignore_log_space_limit= 1; rli->ignore_log_space_limit= 1;
// If the I/O thread is blocked, unblock it /*
If the I/O thread is blocked, unblock it.
Ok to broadcast after unlock, because the mutex is only destroyed in
~st_relay_log_info(), i.e. when rli is destroyed, and rli will not be
destroyed before we exit the present function.
*/
pthread_mutex_unlock(&rli->log_space_lock); pthread_mutex_unlock(&rli->log_space_lock);
pthread_cond_broadcast(&rli->log_space_cond); pthread_cond_broadcast(&rli->log_space_cond);
// Note that wait_for_update unlocks lock_log ! // Note that wait_for_update unlocks lock_log !

View File

@ -739,7 +739,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
query_cache_size_arg)); query_cache_size_arg));
free_cache(0); free_cache(0);
query_cache_size= query_cache_size_arg; query_cache_size= query_cache_size_arg;
DBUG_RETURN(init_cache()); DBUG_RETURN(::query_cache_size= init_cache());
} }
@ -1318,6 +1318,12 @@ ulong Query_cache::init_cache()
mem_bin_steps = 1; mem_bin_steps = 1;
mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2; mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
prev_size = 0; 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) while (mem_bin_size > min_allocation_unit)
{ {
mem_bin_num += mem_bin_count; mem_bin_num += mem_bin_count;
@ -1344,14 +1350,6 @@ ulong Query_cache::init_cache()
query_cache_size -= additional_data_size; query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex); 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 *) if (!(cache = (byte *)
my_malloc_lock(query_cache_size+additional_data_size, MYF(0)))) my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))

View File

@ -1421,6 +1421,24 @@ void select_insert::send_error(uint errcode,const char *err)
::send_error(thd,errcode,err); ::send_error(thd,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE); table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd); table->file->activate_all_index(thd);
/*
If at least one row has been inserted/modified and will stay in the table
(the table doesn't have transactions) (example: we got a duplicate key
error while inserting into a MyISAM table) we must write to the binlog (and
the error code will make the slave stop).
*/
if ((info.copied || info.deleted) && !table->file->has_transactions())
{
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions());
mysql_bin_log.write(&qinfo);
}
}
if (info.copied || info.deleted) if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1); query_cache_invalidate3(thd, table, 1);
ha_rollback_stmt(thd); ha_rollback_stmt(thd);
@ -1442,7 +1460,10 @@ bool select_insert::send_eof()
if (info.copied || info.deleted) if (info.copied || info.deleted)
query_cache_invalidate3(thd, table, 1); query_cache_invalidate3(thd, table, 1);
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */ /* Write to binlog before commiting transaction */
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
@ -1467,10 +1488,7 @@ bool select_insert::send_eof()
else else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields); thd->cuted_fields);
if (last_insert_id)
thd->insert_id(last_insert_id); // For update log
::send_ok(thd,info.copied+info.deleted,last_insert_id,buff); ::send_ok(thd,info.copied+info.deleted,last_insert_id,buff);
mysql_update_log.write(thd,thd->query,thd->query_length);
return 0; return 0;
} }
} }

View File

@ -1081,22 +1081,32 @@ mysql_rename_table(enum db_type base,
} }
/* /*
close table in this thread and force close + reopen in other threads Force all other threads to stop using the table
This assumes that the calling thread has lock on LOCK_open
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 ! 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)); DBUG_PRINT("enter",("table: %s", table->real_name));
DBUG_ENTER("wait_while_table_is_used");
safe_mutex_assert_owner(&LOCK_open);
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
/* Mark all tables that are in use as 'old' */ /* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd,table); // end threads waiting on lock mysql_lock_abort(thd, table); // end threads waiting on lock
#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
/* Wait until all there are no other threads that has this table open */ /* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key, while (remove_table_from_cache(thd,table->table_cache_key,
table->real_name)) table->real_name))
@ -1105,25 +1115,31 @@ static void safe_remove_from_cache(THD *thd,TABLE *table)
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--; dropping_tables--;
} }
#else
(void) remove_table_from_cache(thd,table->table_cache_key,
table->real_name);
#endif
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Close a cached table
bool close_cached_table(THD *thd,TABLE *table) SYNOPSIS
clsoe_cached_table()
thd Thread handler
table Table to remove from cache
NOTES
Function ends by signaling threads waiting for the table to try to
reopen the table.
PREREQUISITES
Lock on LOCK_open
Win32 clients must also have a WRITE LOCK on the table !
*/
static bool close_cached_table(THD *thd, TABLE *table)
{ {
DBUG_ENTER("close_cached_table"); DBUG_ENTER("close_cached_table");
safe_mutex_assert_owner(&LOCK_open);
if (table) wait_while_table_is_used(thd,table);
{
safe_remove_from_cache(thd,table);
/* Close lock if this is not got with LOCK TABLES */ /* Close lock if this is not got with LOCK TABLES */
if (thd->lock) if (thd->lock)
{ {
@ -1132,7 +1148,9 @@ bool close_cached_table(THD *thd,TABLE *table)
} }
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */ /* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table); 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); DBUG_RETURN(0);
} }
@ -1261,10 +1279,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id); sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
/* If we could open the table, close it */
if (table_list->table)
{
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
close_cached_table(thd,table_list->table); close_cached_table(thd, table);
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
}
if (lock_and_wait_for_table_name(thd,table_list)) if (lock_and_wait_for_table_name(thd,table_list))
{ {
error= -1; error= -1;
@ -1794,11 +1815,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else else
{ {
*fn_ext(new_name)=0; *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)) if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1; error= -1;
} }
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
} }
if (!error) if (!error)
@ -1807,12 +1827,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS: case LEAVE_AS_IS:
break; break;
case ENABLE: case ENABLE:
safe_remove_from_cache(thd,table); VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table);
VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->activate_all_index(thd); error= table->file->activate_all_index(thd);
/* COND_refresh will be signaled in close_thread_tables() */
break; break;
case DISABLE: 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); table->file->deactivate_non_unique_index(HA_POS_ERROR);
/* COND_refresh will be signaled in close_thread_tables() */
break; break;
} }
} }
@ -2247,7 +2273,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename close the original table at before doing the rename
*/ */
table_name=thd->strdup(table_name); // must be saved table_name=thd->strdup(table_name); // must be saved
if (close_cached_table(thd,table)) if (close_cached_table(thd, table))
{ // Aborted { // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name)); VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
@ -2281,6 +2307,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
This shouldn't happen. We solve this the safe way by This shouldn't happen. We solve this the safe way by
closing the locked table. closing the locked table.
*/ */
if (table)
close_cached_table(thd,table); close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; goto err;
@ -2291,6 +2318,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Not table locking or alter table with rename Not table locking or alter table with rename
free locks and remove old table free locks and remove old table
*/ */
if (table)
close_cached_table(thd,table); close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name)); VOID(quick_rm_table(old_db_type,db,old_name));
} }
@ -2311,6 +2339,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (close_data_tables(thd,db,table_name) || if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0)) reopen_tables(thd,1,0))
{ // This shouldn't happen { // This shouldn't happen
if (table)
close_cached_table(thd,table); // Remove lock for table close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_open));
goto err; goto err;

View File

@ -200,7 +200,6 @@ int mysql_update(THD *thd,
*/ */
uint length; uint length;
SORT_FIELD *sortorder; SORT_FIELD *sortorder;
List<Item> fields;
ha_rows examined_rows; ha_rows examined_rows;
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),

View File

@ -4324,6 +4324,7 @@ keyword:
| SHARE_SYM {} | SHARE_SYM {}
| SHUTDOWN {} | SHUTDOWN {}
| SLAVE {} | SLAVE {}
| SOUNDS_SYM {}
| SQL_CACHE_SYM {} | SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {} | SQL_BUFFER_RESULT {}
| SQL_NO_CACHE_SYM {} | SQL_NO_CACHE_SYM {}
@ -4348,8 +4349,8 @@ keyword:
| VARIABLES {} | VARIABLES {}
| VALUE_SYM {} | VALUE_SYM {}
| WORK_SYM {} | WORK_SYM {}
| X509_SYM {}
| YEAR_SYM {} | YEAR_SYM {}
| SOUNDS_SYM {}
; ;
/* Option functions */ /* Option functions */

View File

@ -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 */ /* Currently only my_time_zone is inited */
static long my_time_zone=0; static long my_time_zone=0;
pthread_mutex_t LOCK_timezone;
void init_time(void) void init_time(void)
{ {
@ -39,14 +38,14 @@ void init_time(void)
seconds= (time_t) time((time_t*) 0); seconds= (time_t) time((time_t*) 0);
localtime_r(&seconds,&tm_tmp); localtime_r(&seconds,&tm_tmp);
l_time= &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.year= (uint) l_time->tm_year+1900;
my_time.month= (uint) l_time->tm_mon+1; my_time.month= (uint) l_time->tm_mon+1;
my_time.day= (uint) l_time->tm_mday; my_time.day= (uint) l_time->tm_mday;
my_time.hour= (uint) l_time->tm_hour; my_time.hour= (uint) l_time->tm_hour;
my_time.minute= (uint) l_time->tm_min; my_time.minute= (uint) l_time->tm_min;
my_time.second= (uint) l_time->tm_sec; my_time.second= (uint) l_time->tm_sec;
VOID(my_gmt_sec(&my_time)); /* Init my_time_zone */ my_gmt_sec(&my_time, &my_time_zone); /* Init my_time_zone */
} }
/* /*
@ -57,26 +56,39 @@ void init_time(void)
*/ */
long my_gmt_sec(TIME *t) long my_gmt_sec(TIME *t, long *my_timezone)
{ {
uint loop; uint loop;
time_t tmp; time_t tmp;
struct tm *l_time,tm_tmp; struct tm *l_time,tm_tmp;
long diff; long diff, current_timezone;
if (t->hour >= 24) if (t->hour >= 24)
{ /* Fix for time-loop */ { /* Fix for time-loop */
t->day+=t->hour/24; t->day+=t->hour/24;
t->hour%=24; t->hour%=24;
} }
pthread_mutex_lock(&LOCK_timezone);
tmp=(time_t) ((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) - /*
Calculate the gmt time based on current time and timezone
The -1 on the end is to ensure that if have a date that exists twice
(like 2002-10-27 02:00:0 MET), we will find the initial date.
By doing -3600 we will have to call localtime_r() several times, but
I couldn't come up with a better way to get a repeatable result :(
We can't use mktime() as it's buggy on many platforms and not thread safe.
*/
tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
(long) days_at_timestart)*86400L + (long) t->hour*3600L + (long) days_at_timestart)*86400L + (long) t->hour*3600L +
(long) (t->minute*60 + t->second)) + (time_t) my_time_zone; (long) (t->minute*60 + t->second)) + (time_t) my_time_zone -
3600);
current_timezone= my_time_zone;
localtime_r(&tmp,&tm_tmp); localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp; l_time=&tm_tmp;
for (loop=0; for (loop=0;
loop < 3 && loop < 2 &&
(t->hour != (uint) l_time->tm_hour || (t->hour != (uint) l_time->tm_hour ||
t->minute != (uint) l_time->tm_min); t->minute != (uint) l_time->tm_min);
loop++) loop++)
@ -89,14 +101,16 @@ long my_gmt_sec(TIME *t)
days= -1; days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) + diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
(long) (60*((int) t->minute - (int) l_time->tm_min))); (long) (60*((int) t->minute - (int) l_time->tm_min)));
my_time_zone+=diff; current_timezone+= diff+3600; // Compensate for -3600 above
tmp+=(time_t) diff; tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp); localtime_r(&tmp,&tm_tmp);
l_time=&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 */ Fix that if we are in the not existing daylight saving time hour
if (loop == 3 && t->hour != (uint) l_time->tm_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; int days= t->day - l_time->tm_mday;
if (days < -1) if (days < -1)
@ -108,11 +122,9 @@ long my_gmt_sec(TIME *t)
if (diff == 3600) if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; // Move to next hour tmp+=3600 - t->minute*60 - t->second; // Move to next hour
else if (diff == -3600) 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_timezone= current_timezone;
my_time_zone=0; /* Wrong date */
pthread_mutex_unlock(&LOCK_timezone);
return (long) tmp; return (long) tmp;
} /* my_gmt_sec */ } /* my_gmt_sec */
@ -428,6 +440,8 @@ str_to_TIME(const char *str, uint length, TIME *l_time,bool fuzzy_date)
time_t str_to_timestamp(const char *str,uint length) time_t str_to_timestamp(const char *str,uint length)
{ {
TIME l_time; TIME l_time;
long not_used;
if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE) if (str_to_TIME(str,length,&l_time,0) == TIMESTAMP_NONE)
return(0); return(0);
if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR) if (l_time.year >= TIMESTAMP_MAX_YEAR || l_time.year < 1900+YY_PART_YEAR)
@ -435,7 +449,7 @@ time_t str_to_timestamp(const char *str,uint length)
current_thd->cuted_fields++; current_thd->cuted_fields++;
return(0); return(0);
} }
return(my_gmt_sec(&l_time)); return(my_gmt_sec(&l_time, &not_used));
} }