Commit 6841f9ee authored by unknown's avatar unknown

Merge lgrimmer@build.mysql.com:/home/bk/mysql-4.0

into mysql.com:/space/my/mysql-4.0


BitKeeper/deleted/.del-internals.texi~62b6f580a41c2a43:
  Auto merged
parents d272a9e4 3f7dfc4d
/* Copyright (C) 2000 MySQL AB
/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -246,7 +246,7 @@ C_MODE_END
# endif
#endif /* TIME_WITH_SYS_TIME */
#ifdef HAVE_UNISTD_H
#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT)
#if defined(HAVE_OPENSSL) && !defined(__FreeBSD__) && !defined(NeXT) && !defined(__OpenBSD__)
#define crypt unistd_crypt
#endif
#include <unistd.h>
......@@ -640,6 +640,9 @@ typedef long my_ptrdiff_t;
typedef long long my_ptrdiff_t;
#endif
/* typedef used for length of string; Should be unsigned! */
typedef ulong size_str;
#define MY_ALIGN(A,L) (((A) + (L) - 1) & ~((L) - 1))
#define ALIGN_SIZE(A) MY_ALIGN((A),sizeof(double))
/* Size to make adressable obj. */
......
......@@ -301,6 +301,13 @@ os_aio(
are ignored */
void* message2);
/****************************************************************************
Wakes up all async i/o threads so that they know to exit themselves in
shutdown. */
void
os_aio_wake_all_threads_at_shutdown(void);
/*=====================================*/
/****************************************************************************
Waits until there are no pending writes in os_aio_write_array. There can
be other, synchronous, pending writes. */
......
......@@ -10,15 +10,16 @@ Created 9/6/1995 Heikki Tuuri
#define os0sync_h
#include "univ.i"
#include "ut0lst.h"
#ifdef __WIN__
#define os_fast_mutex_t CRITICAL_SECTION
typedef void* os_event_t;
typedef HANDLE os_event_t;
#else
typedef pthread_mutex_t os_fast_mutex_t;
typedef struct os_event_struct os_event_struct_t;
typedef os_event_struct_t* os_event_t;
struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */
......@@ -26,9 +27,9 @@ struct os_event_struct {
not reserved */
pthread_cond_t cond_var; /* condition variable is used in
waiting for the event */
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
/* list of all created events */
};
typedef struct os_event_struct os_event_struct_t;
typedef os_event_struct_t* os_event_t;
#endif
typedef struct os_mutex_struct os_mutex_str_t;
......@@ -38,6 +39,29 @@ typedef os_mutex_str_t* os_mutex_t;
#define OS_SYNC_TIME_EXCEEDED 1
/* Mutex protecting the thread count and event and OS 'slow' mutex lists */
extern os_mutex_t os_sync_mutex;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
extern ulint os_thread_count;
/* The following are approximate counters for debugging in Unix */
extern ulint os_event_count;
extern ulint os_mutex_count;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(void);
/*==============*/
/*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. */
void
os_sync_free(void);
/*==============*/
/*************************************************************
Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled.
......@@ -85,7 +109,10 @@ os_event_free(
/*==========*/
os_event_t event); /* in: event to free */
/**************************************************************
Waits for an event object until it is in the signaled state. */
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state). */
void
os_event_wait(
......
......@@ -41,7 +41,6 @@ typedef os_thread_t os_thread_id_t; /* In Unix we use the thread
the thread */
#endif
/* Define a function pointer type to use in a typecast */
typedef void* (*os_posix_f_t) (void*);
......@@ -83,12 +82,13 @@ os_thread_create(
os_thread_id_t* thread_id); /* out: id of the created
thread */
/*********************************************************************
A thread calling this function ends its execution. */
Exits the current thread. */
void
os_thread_exit(
/*===========*/
ulint code); /* in: exit code */
void* exit_value); /* in: exit value; in Windows this void*
is cast as a DWORD */
/*********************************************************************
Returns the thread identifier of current thread. */
......@@ -144,7 +144,6 @@ ulint
os_thread_get_last_error(void);
/*==========================*/
#ifndef UNIV_NONINL
#include "os0thread.ic"
#endif
......
......@@ -209,6 +209,12 @@ void
srv_init(void);
/*==========*/
/*************************************************************************
Frees the OS fast mutex created in srv_init(). */
void
srv_free(void);
/*==========*/
/*************************************************************************
Initializes the synchronization primitives, memory system, and the thread
local storage. */
......
......@@ -86,11 +86,12 @@ extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down;
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP
and then to SRV_SHUTDOWN_LAST_PHASE */
and then to SRV_SHUTDOWN_LAST_PHASE, and so on */
extern ulint srv_shutdown_state;
#define SRV_SHUTDOWN_CLEANUP 1
#define SRV_SHUTDOWN_LAST_PHASE 2
#define SRV_SHUTDOWN_EXIT_THREADS 3
#endif
......@@ -375,7 +375,7 @@ log_pad_current_log_block(void)
log_close();
log_release();
ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
ut_ad((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
== LOG_BLOCK_HDR_SIZE);
}
......@@ -999,6 +999,8 @@ log_group_file_header_flush(
byte* buf;
ulint dest_offset;
UT_NOT_USED(type);
ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(nth_file < group->n_files);
......@@ -1068,8 +1070,8 @@ log_group_write_buf(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
if (new_data_offset == 0) {
write_header = TRUE;
......@@ -2901,8 +2903,7 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn;
ulint arch_log_no;
if (srv_print_verbose_log)
{
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Starting shutdown...\n");
}
......@@ -3006,15 +3007,17 @@ logs_empty_and_mark_files_at_shutdown(void)
goto loop;
}
/* Make some checks that the server really is quiet */
ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
fil_write_flushed_lsn_to_data_files(lsn, arch_log_no);
fil_flush_file_spaces(FIL_TABLESPACE);
if (srv_print_verbose_log)
{
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n");
}
/* Make some checks that the server really is quiet */
ut_a(buf_all_freed());
ut_a(0 == ut_dulint_cmp(lsn, log_sys->lsn));
}
/**********************************************************
......
......@@ -295,7 +295,8 @@ os_file_handle_error(
/* out: TRUE if we should retry the
operation */
os_file_t file, /* in: file pointer */
char* name) /* in: name of a file or NULL */
char* name, /* in: name of a file or NULL */
const char* operation) /* in: type of operation */
{
ulint err;
......@@ -337,6 +338,7 @@ os_file_handle_error(
if (name) {
fprintf(stderr, "InnoDB: File name %s\n", name);
}
fprintf(stderr, "InnoDB: system call %s\n", operation);
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
......@@ -419,7 +421,9 @@ os_file_create_simple(
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
retry = os_file_handle_error(file, name);
retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ?
"open" : "create");
if (retry) {
goto try_again;
......@@ -460,7 +464,10 @@ os_file_create_simple(
if (file == -1) {
*success = FALSE;
retry = os_file_handle_error(file, name);
retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ?
"open" : "create");
if (retry) {
goto try_again;
......@@ -568,7 +575,9 @@ os_file_create(
if (file == INVALID_HANDLE_VALUE) {
*success = FALSE;
retry = os_file_handle_error(file, name);
retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ?
"open" : "create");
if (retry) {
goto try_again;
......@@ -615,7 +624,9 @@ os_file_create(
if (file == -1) {
*success = FALSE;
retry = os_file_handle_error(file, name);
retry = os_file_handle_error(file, name,
create_mode == OS_FILE_OPEN ?
"open" : "create");
if (retry) {
goto try_again;
......@@ -649,7 +660,7 @@ os_file_close(
return(TRUE);
}
os_file_handle_error(file, NULL);
os_file_handle_error(file, NULL, "close");
return(FALSE);
#else
int ret;
......@@ -657,7 +668,7 @@ os_file_close(
ret = close(file);
if (ret == -1) {
os_file_handle_error(file, NULL);
os_file_handle_error(file, NULL, "close");
return(FALSE);
}
......@@ -825,7 +836,7 @@ os_file_flush(
return(TRUE);
}
os_file_handle_error(file, NULL);
os_file_handle_error(file, NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
......@@ -858,7 +869,7 @@ os_file_flush(
fprintf(stderr,
" InnoDB: Error: the OS said file flush did not succeed\n");
os_file_handle_error(file, NULL);
os_file_handle_error(file, NULL, "flush");
/* It is a fatal error if a file flush does not succeed, because then
the database can get corrupt on disk */
......@@ -1099,7 +1110,7 @@ os_file_read(
#ifdef __WIN__
error_handling:
#endif
retry = os_file_handle_error(file, NULL);
retry = os_file_handle_error(file, NULL, "read");
if (retry) {
goto try_again;
......@@ -1295,7 +1306,6 @@ os_aio_array_create(
#endif
ut_a(n > 0);
ut_a(n_segments > 0);
ut_a(n % n_segments == 0);
array = ut_malloc(sizeof(os_aio_array_t));
......@@ -1405,6 +1415,50 @@ os_aio_init(
#endif
}
#ifdef WIN_ASYNC_IO
/****************************************************************************
Wakes up all async i/o threads in the array in Windows async i/o at
shutdown. */
static
void
os_aio_array_wake_win_aio_at_shutdown(
/*==================================*/
os_aio_array_t* array) /* in: aio array */
{
ulint i;
for (i = 0; i < array->n_slots; i++) {
os_event_set(*(array->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
be other, synchronous, pending writes. */
......@@ -1971,7 +2025,7 @@ os_aio(
os_aio_array_free_slot(array, slot);
retry = os_file_handle_error(file, name);
retry = os_file_handle_error(file, name, "aio");
if (retry) {
......@@ -2070,7 +2124,7 @@ os_aio_windows_handle(
ut_a(TRUE == os_file_flush(slot->file));
}
} else {
os_file_handle_error(slot->file, slot->name);
os_file_handle_error(slot->file, slot->name, "aio");
ret_val = FALSE;
}
......
......@@ -17,6 +17,7 @@ Created 9/6/1995 Heikki Tuuri
#endif
#include "ut0mem.h"
#include "srv0start.h"
/* Type definition for an operating system mutex struct */
struct os_mutex_struct{
......@@ -27,8 +28,74 @@ struct os_mutex_struct{
do not assume that the OS mutex
supports recursive locking, though
NT seems to do that */
UT_LIST_NODE_T(os_mutex_str_t) os_mutex_list;
/* list of all 'slow' OS mutexes created */
};
/* Mutex protecting the thread count and the lists of OS mutexes
and events */
os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
ulint os_thread_count = 0;
/* The list of all events created (not in Windows) */
UT_LIST_BASE_NODE_T(os_event_struct_t) os_event_list;
/* The list of all OS 'slow' mutexes */
UT_LIST_BASE_NODE_T(os_mutex_str_t) os_mutex_list;
/* The following are approximate counters for debugging in Unix */
ulint os_event_count = 0;
ulint os_mutex_count = 0;
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
void
os_sync_init(void)
/*==============*/
{
UT_LIST_INIT(os_event_list);
UT_LIST_INIT(os_mutex_list);
os_sync_mutex = os_mutex_create(NULL);
os_sync_mutex_inited = TRUE;
}
/*************************************************************
Frees created events (not in Windows) and OS 'slow' mutexes. */
void
os_sync_free(void)
/*==============*/
{
os_event_t event;
os_mutex_t mutex;
event = UT_LIST_GET_FIRST(os_event_list);
while (event) {
os_event_free(event);
event = UT_LIST_GET_FIRST(os_event_list);
}
mutex = UT_LIST_GET_FIRST(os_mutex_list);
while (mutex) {
os_mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(os_mutex_list);
}
}
/*************************************************************
Creates an event semaphore, i.e., a semaphore which may
just have two states: signaled and nonsignaled.
......@@ -43,7 +110,7 @@ os_event_create(
the event is created without a name */
{
#ifdef __WIN__
HANDLE event;
os_event_t event;
event = CreateEvent(NULL, /* No security attributes */
TRUE, /* Manual reset */
......@@ -75,6 +142,14 @@ os_event_create(
#endif
event->is_set = FALSE;
os_mutex_enter(os_sync_mutex);
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
os_event_count++;
os_mutex_exit(os_sync_mutex);
return(event);
#endif
}
......@@ -92,7 +167,7 @@ os_event_create_auto(
the event is created without a name */
{
#ifdef __WIN__
HANDLE event;
os_event_t event;
event = CreateEvent(NULL, /* No security attributes */
FALSE, /* Auto-reset */
......@@ -106,6 +181,8 @@ os_event_create_auto(
UT_NOT_USED(name);
ut_a(0);
return(NULL);
#endif
}
......@@ -185,12 +262,23 @@ os_event_free(
os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_event_list, os_event_list, event);
os_event_count--;
os_mutex_exit(os_sync_mutex);
ut_free(event);
#endif
}
/**************************************************************
Waits for an event object until it is in the signaled state. */
Waits for an event object until it is in the signaled state. If
srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS this also exits the
waiting thread when the event becomes signaled (or immediately if the
event is already in the signaled state). */
void
os_event_wait(
......@@ -206,12 +294,20 @@ os_event_wait(
err = WaitForSingleObject(event, INFINITE);
ut_a(err == WAIT_OBJECT_0);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
#else
os_fast_mutex_lock(&(event->os_mutex));
loop:
if (event->is_set == TRUE) {
os_fast_mutex_unlock(&(event->os_mutex));
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
/* Ok, we may return */
return;
......@@ -291,14 +387,17 @@ os_event_wait_multiple(
ut_a(event_array);
ut_a(n > 0);
index = WaitForMultipleObjects(n,
event_array,
index = WaitForMultipleObjects(n, event_array,
FALSE, /* Wait for any 1 event */
INFINITE); /* Infinite wait time
limit */
ut_a(index >= WAIT_OBJECT_0);
ut_a(index < WAIT_OBJECT_0 + n);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
}
return(index - WAIT_OBJECT_0);
#else
ut_a(n == 0);
......@@ -337,6 +436,16 @@ os_mutex_create(
mutex_str->handle = mutex;
mutex_str->count = 0;
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
return(mutex_str);
#else
os_fast_mutex_t* os_mutex;
......@@ -353,6 +462,16 @@ os_mutex_create(
mutex_str->handle = os_mutex;
mutex_str->count = 0;
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
if (os_sync_mutex_inited) {
os_mutex_exit(os_sync_mutex);
}
return(mutex_str);
#endif
}
......@@ -424,9 +543,22 @@ os_mutex_free(
#ifdef __WIN__
ut_a(mutex);
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_exit(os_sync_mutex);
ut_a(CloseHandle(mutex->handle));
ut_free(mutex);
#else
os_mutex_enter(os_sync_mutex);
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
os_mutex_exit(os_sync_mutex);
os_fast_mutex_free(mutex->handle);
ut_free(mutex->handle);
ut_free(mutex);
......@@ -451,6 +583,7 @@ os_fast_mutex_init(
#else
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif
os_mutex_count++;
#endif
}
......@@ -498,5 +631,6 @@ os_fast_mutex_free(
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
ut_a(0 == pthread_mutex_destroy(fast_mutex));
os_mutex_count--;
#endif
}
/******************************************************
The interface to the operating system
process and thread control primitives
The interface to the operating system thread control primitives
(c) 1995 Innobase Oy
......@@ -17,6 +16,7 @@ Created 9/8/1995 Heikki Tuuri
#endif
#include "srv0srv.h"
#include "os0sync.h"
/*******************************************************************
Compares two thread ids for equality. */
......@@ -102,6 +102,10 @@ os_thread_create(
os_thread_t thread;
ulint win_thread_id;
os_mutex_enter(os_sync_mutex);
os_thread_count++;
os_mutex_exit(os_sync_mutex);
thread = CreateThread(NULL, /* no security attributes */
0, /* default size stack */
(LPTHREAD_START_ROUTINE)start_f,
......@@ -144,6 +148,9 @@ os_thread_create(
exit(1);
}
#endif
os_mutex_enter(os_sync_mutex);
os_thread_count++;
os_mutex_exit(os_sync_mutex);
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ret = pthread_create(&pthread, pthread_attr_default, start_f, arg);
......@@ -170,6 +177,26 @@ os_thread_create(
#endif
}
/*********************************************************************
Exits the current thread. */
void
os_thread_exit(
/*===========*/
void* exit_value) /* in: exit value; in Windows this void*
is cast as a DWORD */
{
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. */
......
......@@ -1695,74 +1695,31 @@ srv_init(void)
}
/*************************************************************************
Initializes the synchronization primitives, memory system, and the thread
local storage. */
Frees the OS fast mutex created in srv_init(). */
void
srv_general_init(void)
/*==================*/
srv_free(void)
/*==========*/
{
sync_init();
mem_init(srv_mem_pool_size);
thr_local_init();
os_fast_mutex_free(&srv_conc_mutex);
}
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/*************************************************************************
Deinitializes the synchronization primitives, memory system, and the thread
Initializes the synchronization primitives, memory system, and the thread
local storage. */
void
srv_general_free(void)
srv_general_init(void)
/*==================*/
{
sync_close();
os_sync_init();
sync_init();
mem_init(srv_mem_pool_size);
thr_local_init();
}
#endif /* __NETWARE__ */
/*======================= InnoDB Server FIFO queue =======================*/
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires some cleanup of mutexes */
/*************************************************************************
Deinitializes the server. */
void
srv_free(void)
/*==========*/
{
srv_conc_slot_t* conc_slot;
srv_slot_t* slot;
ulint i;
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
slot = srv_table_get_nth_slot(i);
os_event_free(slot->event);
}
/* TODO: free(srv_sys->threads); */
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
slot = srv_mysql_table + i;
os_event_free(slot->event);
}
/* TODO: free(srv_mysql_table); */
for (i = 0; i < OS_THREAD_MAX_N; i++)
{
conc_slot = srv_conc_slots + i;
os_event_free(conc_slot->event);
}
}
#endif /* __NETWARE__ */
/*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads
......@@ -2700,6 +2657,8 @@ srv_error_monitor_thread(
srv_error_monitor_active = FALSE;
os_thread_exit(NULL);
#ifndef __WIN__
return(NULL);
#else
......@@ -3139,6 +3098,13 @@ srv_master_thread(
os_event_wait(event);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
/* This is only extra safety, the thread should exit
already when the event wait ends */
os_thread_exit(NULL);
}
/* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */
......
......@@ -1442,9 +1442,7 @@ innobase_start_or_create_for_mysql(void)
os_fast_mutex_unlock(&srv_os_test_mutex);
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
os_fast_mutex_free(&srv_os_test_mutex); /* all platforms? */
#endif /* __NETWARE__ */
os_fast_mutex_free(&srv_os_test_mutex);
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
......@@ -1470,6 +1468,8 @@ innobase_shutdown_for_mysql(void)
/*=============================*/
/* out: DB_SUCCESS or error code */
{
ulint i;
if (!srv_was_started) {
if (srv_is_being_started) {
ut_print_timestamp(stderr);
......@@ -1482,7 +1482,7 @@ innobase_shutdown_for_mysql(void)
return(DB_SUCCESS);
}
/* Flush buffer pool to disk, write the current lsn to
/* 1. Flush buffer pool to disk, write the current lsn to
the tablespace header(s), and copy all log data to archive */
logs_empty_and_mark_files_at_shutdown();
......@@ -1494,30 +1494,77 @@ innobase_shutdown_for_mysql(void)
srv_conc_n_threads);
}
#if defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/*
TODO: Fix this temporary solution
We are having a race condition occure with io_handler_thread threads.
When they yield in os_aio_simulated_handle during shutdown, this
thread was able to free the memory early.
*/
os_thread_yield();
/* 2. Make all threads created by InnoDB to exit */
srv_shutdown_state = SRV_SHUTDOWN_EXIT_THREADS;
/* All threads end up waiting for certain events. Put those events
to the signaled state. Then the threads will exit themselves in
os_thread_event_wait(). */
for (i = 0; i < 1000; i++) {
/* NOTE: IF YOU CREATE THREADS IN INNODB, YOU MUST EXIT THEM
HERE OR EARLIER */
/* 1. Let the lock timeout thread exit */
os_event_set(srv_lock_timeout_thread_event);
/* 2. srv error monitor thread exits automatically, no need
to do anything here */
/* 3. We wake the master thread so that it exits */
srv_wake_master_thread();
/* 4. Exit the i/o threads */
os_aio_wake_all_threads_at_shutdown();
os_mutex_enter(os_sync_mutex);
if (os_thread_count == 0) {
/* All the threads have exited or are just exiting;
NOTE that the threads may not have completed their
exit yet. Should we use pthread_join() to make sure
they have exited? Now we just sleep 0.1 seconds and
hope that is enough! */
os_mutex_exit(os_sync_mutex);
os_thread_sleep(100000);
break;
}
os_mutex_exit(os_sync_mutex);
os_thread_sleep(100000);
}
if (i == 1000) {
fprintf(stderr,
"InnoDB: Warning: %lu threads created by InnoDB had not exited at shutdown!\n",
os_thread_count);
}
/* 3. Free all InnoDB's own mutexes */
sync_close();
/* 4. Free all OS synchronization primitives (in Windows currently
events are not freed) */
/* TODO: Where should this be called? */
srv_free();
os_sync_free();
/* 5. Free all allocated memory (and the os_fast_mutex created in
ut0mem.c */
/* TODO: Where should this be called? */
srv_general_free();
#endif
/*
TODO: We should exit the i/o-handler and other utility threads
before freeing all memory. Now this can potentially cause a seg
fault!
*/
#if defined(NOT_WORKING_YET) || defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
/* NetWare requires this free */
ut_free_all_mem();
#endif
if (srv_print_verbose_log) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n");
}
return((int) DB_SUCCESS);
}
......@@ -235,8 +235,7 @@ mutex_create_func(
mutex->cline = cline;
/* Check that lock_word is aligned; this is important on Intel */
ut_a(((ulint)(&(mutex->lock_word))) % 4 == 0);
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
/* NOTE! The very first mutexes are not put to the mutex list */
......@@ -266,11 +265,14 @@ mutex_free(
ut_a(mutex_get_lock_word(mutex) == 0);
ut_a(mutex_get_waiters(mutex) == 0);
if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
mutex_enter(&mutex_list_mutex);
UT_LIST_REMOVE(list, mutex_list, mutex);
mutex_exit(&mutex_list_mutex);
}
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
......@@ -1230,13 +1232,26 @@ sync_init(void)
}
/**********************************************************************
Frees the resources in synchronization data structures. */
Frees the resources in InnoDB's own synchronization data structures. Use
os_sync_free() after calling this. */
void
sync_close(void)
/*===========*/
{
mutex_t* mutex;
sync_array_free(sync_primary_wait_array);
mutex = UT_LIST_GET_FIRST(mutex_list);
while (mutex) {
mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(mutex_list);
}
mutex_free(&mutex_list_mutex);
mutex_free(&sync_thread_mutex);
}
/***********************************************************************
......
......@@ -190,6 +190,8 @@ ut_free_all_mem(void)
os_fast_mutex_unlock(&ut_list_mutex);
ut_a(ut_total_allocated_memory == 0);
os_fast_mutex_free(&ut_list_mutex);
}
/**************************************************************************
......
......@@ -436,7 +436,6 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
(void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
......
......@@ -276,3 +276,8 @@ t1 0 a 1 a A 3 NULL NULL YES BTREE
t1 0 a 2 b A 300 NULL NULL YES BTREE
t1 1 b 1 b A 100 NULL NULL YES BTREE
drop table t1;
CREATE TABLE t1 (i int(10), index(i) );
ALTER TABLE t1 DISABLE KEYS;
INSERT DELAYED INTO t1 VALUES(1),(2),(3);
ALTER TABLE t1 ENABLE KEYS;
drop table t1;
......@@ -13,3 +13,15 @@ show tables like 't_';
Tables_in_test (t_)
t3
drop table t3;
create table t1 (a int);
select count(*) from T1;
count(*)
0
select count(*) from t1;
count(*)
0
select count(T1.a) from t1;
Unknown table 'T1' in field list
select count(bags.a) from t1 as Bags;
Unknown table 'bags' in field list
drop table t1;
......@@ -501,22 +501,62 @@ drop table t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
create table t1 (a int);
set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
set GLOBAL query_cache_size=1100;
set GLOBAL query_cache_size=1200;
set GLOBAL query_cache_size=1300;
set GLOBAL query_cache_size=1400;
set GLOBAL query_cache_size=1500;
set GLOBAL query_cache_size=1600;
set GLOBAL query_cache_size=1700;
set GLOBAL query_cache_size=1800;
set GLOBAL query_cache_size=1900;
select * from t1;
a
set GLOBAL query_cache_size=1024;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=10240;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=20480;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=40960;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 0
select * from t1;
a
set GLOBAL query_cache_size=51200;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 51200
select * from t1;
a
set GLOBAL query_cache_size=61440;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 1024
query_cache_size 61440
select * from t1;
a
set GLOBAL query_cache_size=81920;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 81920
select * from t1;
a
set GLOBAL query_cache_size=102400;
show global variables like "query_cache_size";
Variable_name Value
query_cache_size 102400
select * from t1;
a
drop table t1;
set GLOBAL query_cache_size=1048576;
create table t1 (i int not null);
create table t2 (i int not null);
......
......@@ -36,6 +36,8 @@ show binlog events from 79 limit 2,1;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.001 200 Query 1 200 use test; insert into t1 values (NULL)
flush logs;
create table t5 (a int);
drop table t5;
slave start;
flush logs;
slave stop;
......@@ -56,9 +58,11 @@ master-bin.001 1079 Query 1 1079 use test; drop table t1
master-bin.001 1127 Rotate 1 1127 master-bin.002;pos=4
show binlog events in 'master-bin.002';
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.002 4 Query 1 4 use test; create table t1 (n int)
master-bin.002 62 Query 1 62 use test; insert into t1 values (1)
master-bin.002 122 Query 1 122 use test; drop table t1
master-bin.002 4 Query 1 4 use test; create table t5 (a int)
master-bin.002 62 Query 1 62 use test; drop table t5
master-bin.002 110 Query 1 110 use test; create table t1 (n int)
master-bin.002 168 Query 1 168 use test; insert into t1 values (1)
master-bin.002 228 Query 1 228 use test; drop table t1
show master logs;
Log_name
master-bin.001
......@@ -79,14 +83,16 @@ slave-bin.001 311 Query 1 311 use test; create table t1 (word char(20) not null)
slave-bin.001 386 Create_file 1 386 db=test;table=t1;file_id=1;block_len=581
slave-bin.001 1065 Exec_load 1 1056 ;file_id=1
slave-bin.001 1088 Query 1 1079 use test; drop table t1
slave-bin.001 1136 Rotate 2 1136 slave-bin.002;pos=4
slave-bin.001 1136 Query 1 4 use test; create table t5 (a int)
slave-bin.001 1194 Query 1 62 use test; drop table t5
slave-bin.001 1242 Rotate 2 1242 slave-bin.002;pos=4
show binlog events in 'slave-bin.002' from 4;
Log_name Pos Event_type Server_id Orig_log_pos Info
slave-bin.002 4 Query 1 4 use test; create table t1 (n int)
slave-bin.002 62 Query 1 62 use test; insert into t1 values (1)
slave-bin.002 122 Query 1 122 use test; drop table t1
slave-bin.002 4 Query 1 110 use test; create table t1 (n int)
slave-bin.002 62 Query 1 168 use test; insert into t1 values (1)
slave-bin.002 122 Query 1 228 use test; drop table t1
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
127.0.0.1 root MASTER_PORT 1 master-bin.002 170 slave-relay-bin.002 1457 master-bin.002 Yes Yes 0 0 170 1461
127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1522 master-bin.002 Yes Yes 0 0 276 1526
show binlog events in 'slave-bin.005' from 4;
Error when executing command SHOW BINLOG EVENTS: Could not find target log
......@@ -133,3 +133,12 @@ analyze table t1;
show keys from t1;
drop table t1;
#
# Test of ALTER TABLE DELAYED
#
CREATE TABLE t1 (i int(10), index(i) );
ALTER TABLE t1 DISABLE KEYS;
INSERT DELAYED INTO t1 VALUES(1),(2),(3);
ALTER TABLE t1 ENABLE KEYS;
drop table t1;
#
# Test some error conditions
#
drop table if exists t1;
!$1146 insert into t1 values(1);
!$1146 delete from t1;
!$1146 update t1 set a=1;
create table t1 (a int);
!$1054 select count(test.t1.b) from t1;
!$1109 select count(not_existing_database.t1) from t1;
!$1109 select count(not_existing_database.t1.a) from t1;
--error 1044,1146
select count(not_existing_database.t1.a) from not_existing_database.t1;
!$1054 select 1 from t1 order by 2;
!$1054 select 1 from t1 group by 2;
!$1054 select 1 from t1 order by t1.b;
!$1054 select count(*),b from t1;
drop table t1;
#
# Test some error conditions
#
drop table if exists t1;
--error 1146
insert into t1 values(1);
--error 1146
delete from t1;
--error 1146
update t1 set a=1;
#
create table t1 (a int);
--error 1054
select count(test.t1.b) from t1;
--error 1109
select count(not_existing_database.t1) from t1;
--error 1109
select count(not_existing_database.t1.a) from t1;
--error 1044,1146
select count(not_existing_database.t1.a) from not_existing_database.t1;
--error 1054
select 1 from t1 order by 2;
--error 1054
select 1 from t1 group by 2;
--error 1054
select 1 from t1 order by t1.b;
--error 1054
select count(*),b from t1;
drop table t1;
......@@ -12,3 +12,14 @@ ALTER TABLE T2 RENAME T3;
show tables like 't_';
drop table t3;
#
# Test alias
#
create table t1 (a int);
select count(*) from T1;
select count(*) from t1;
--error 1109
select count(T1.a) from t1;
--error 1109
select count(bags.a) from t1 as Bags;
drop table t1;
......@@ -343,18 +343,35 @@ show status like "Qcache_queries_in_cache";
#
# Test of query cache resizing
#
create table t1 (a int);
set GLOBAL query_cache_size=1000;
show global variables like "query_cache_size";
set GLOBAL query_cache_size=1100;
set GLOBAL query_cache_size=1200;
set GLOBAL query_cache_size=1300;
set GLOBAL query_cache_size=1400;
set GLOBAL query_cache_size=1500;
set GLOBAL query_cache_size=1600;
set GLOBAL query_cache_size=1700;
set GLOBAL query_cache_size=1800;
set GLOBAL query_cache_size=1900;
select * from t1;
set GLOBAL query_cache_size=1024;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=10240;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=20480;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=40960;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=51200;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=61440;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=81920;
show global variables like "query_cache_size";
select * from t1;
set GLOBAL query_cache_size=102400;
show global variables like "query_cache_size";
select * from t1;
drop table t1;
#
# Temporary tables
......
......@@ -22,10 +22,32 @@ show binlog events from 79 limit 2;
show binlog events from 79 limit 2,1;
flush logs;
# We need an extra update before doing save_master_pos.
# Otherwise, an unlikely scenario may occur:
# * When the master's binlog_dump thread reads the end of master-bin.001,
# it send the rotate event which is at this end, plus a fake rotate event
# because it's starting to read a new binlog.
# save_master_pos will record the position of the first of the two rotate
# (because the fake one is not in the master's binlog anyway).
# * Later the slave waits for the position of the first rotate event,
# and it may quickly stop (in 'slave stop') without having received the fake
# one.
# So, depending on a few milliseconds, we end up with 2 rotate events in the
# relay log or one, which influences the output of SHOW SLAVE STATUS, making
# it not predictable and causing random test failures.
# To make it predictable, we do a useless update now, but which has the interest
# of making the slave catch both rotate events.
create table t5 (a int);
drop table t5;
# Sync slave and force it to start on another binary log
save_master_pos;
connection slave;
# Note that the above 'slave start' will cause a 3rd rotate event (a fake one)
# to go into the relay log (the master always sends a fake one when replication
# starts).
slave start;
sync_with_master;
flush logs;
......
......@@ -38,20 +38,21 @@
#endif
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);
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm;
static pthread_cond_t COND_alarm;
static sigset_t full_signal_set;
static QUEUE alarm_queue;
static uint max_used_alarms=0;
pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD
static pthread_cond_t COND_alarm;
static void *alarm_handler(void *arg);
#define reschedule_alarms() pthread_cond_signal(&COND_alarm)
#else
......@@ -78,6 +79,7 @@ void init_thr_alarm(uint max_alarms)
compare_ulong,NullS);
sigfillset(&full_signal_set); /* Neaded to block signals */
pthread_mutex_init(&LOCK_alarm,MY_MUTEX_INIT_FAST);
pthread_cond_init(&COND_alarm,NULL);
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
#if defined(HAVE_mit_thread)
sigset(THR_CLIENT_ALARM,thread_alarm); /* int. thread system calls */
......@@ -97,7 +99,6 @@ void init_thr_alarm(uint max_alarms)
{
pthread_attr_t thr_attr;
pthread_attr_init(&thr_attr);
pthread_cond_init(&COND_alarm,NULL);
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&thr_attr,8196);
......@@ -383,28 +384,45 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused)))
void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
if (alarm_aborted != 1)
if (alarm_aborted != 1) /* If memory not freed */
{
pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
alarm_aborted= -1; /* mark aborted */
if (alarm_queue.elements || (alarm_thread_running && free_structures))
{
if (pthread_equal(pthread_self(),alarm_thread))
alarm(1); /* Shut down everything soon */
else
reschedule_alarms();
}
if (free_structures)
{
struct timespec abstime;
/*
The following test is just for safety, the caller should not
depend on this
*/
DBUG_ASSERT(!alarm_queue.elements);
/* Wait until alarm thread dies */
set_timespec(abstime, 10); /* Wait up to 10 seconds */
while (alarm_thread_running)
{
int error= pthread_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime);
if (error == ETIME || error == ETIMEDOUT)
break; /* Don't wait forever */
}
if (!alarm_queue.elements)
{
delete_queue(&alarm_queue);
alarm_aborted= 1;
pthread_mutex_unlock(&LOCK_alarm);
if (!alarm_thread_running) /* Safety */
{
pthread_mutex_destroy(&LOCK_alarm);
pthread_cond_destroy(&COND_alarm);
}
}
}
else
......@@ -490,6 +508,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
puts("Starting alarm thread");
#endif
my_thread_init();
alarm_thread_running= 1;
pthread_mutex_lock(&LOCK_alarm);
for (;;)
{
......@@ -514,7 +533,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
}
}
}
else if (alarm_aborted)
else if (alarm_aborted == -1)
break;
else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm)))
{
......@@ -526,6 +545,8 @@ static void *alarm_handler(void *arg __attribute__((unused)))
process_alarm(0);
}
bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */
alarm_thread_running= 0;
pthread_cond_signal(&COND_alarm);
pthread_mutex_unlock(&LOCK_alarm);
pthread_exit(0);
return 0; /* Impossible */
......
......@@ -1454,7 +1454,11 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
{
const char* tmp = first + 1;
for (; *tmp != wild_many && *tmp != wild_one && *tmp != escape; tmp++) ;
#ifdef USE_MB
canDoTurboBM = (tmp == last) && !use_mb(default_charset_info);
#else
canDoTurboBM = tmp == last;
#endif
}
if (canDoTurboBM)
......
......@@ -422,7 +422,6 @@ bool mysql_rename_table(enum db_type base,
const char * old_name,
const char *new_db,
const char * new_name);
bool close_cached_table(THD *thd,TABLE *table);
int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
......@@ -458,6 +457,7 @@ Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
Field *find_field_in_table(THD *thd,TABLE *table,const char *name,uint length,
bool check_grant,bool allow_rowid);
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
struct st_des_keyblock
{
des_cblock key1, key2, key3;
......
......@@ -1520,7 +1520,6 @@ the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail.\n\n");
fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size);
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size);
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
fprintf(stderr, "max_connections=%ld\n", max_connections);
fprintf(stderr, "threads_connected=%d\n", thread_count);
......@@ -1528,7 +1527,7 @@ and this may fail.\n\n");
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
bytes of memory\n", ((ulong) keybuff_size +
(global_system_variables.read_buff_size +
thd->variables.sortbuff_size) *
global_system_variables.sortbuff_size) *
max_connections)/ 1024);
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
......@@ -1557,14 +1556,9 @@ the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
Some pointers may be invalid and cause the dump to abort...\n");
safe_print_str("thd->query", thd->query, 1024);
fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id);
fprintf(stderr, "\n\
Successfully dumped variables, if you ran with --log, take a look at the\n\
details of what thread %ld did to cause the crash. In some cases of really\n\
bad corruption, the values shown above may be invalid.\n\n",
thd->thread_id);
}
fprintf(stderr, "\
The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\
The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
information that should help you find out what is causing the crash.\n");
fflush(stderr);
#endif /* HAVE_STACKTRACE */
......@@ -1639,6 +1633,7 @@ static void init_signals(void)
sigaddset(&set,SIGHUP);
/* 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);
......@@ -2307,7 +2302,6 @@ The server will not act as a slave.");
using_update_log=1;
}
if (opt_bootstrap)
{
int error=bootstrap(stdin);
......
......@@ -731,7 +731,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
query_cache_size_arg));
free_cache(0);
query_cache_size= query_cache_size_arg;
DBUG_RETURN(init_cache());
DBUG_RETURN(::query_cache_size= init_cache());
}
......@@ -1282,6 +1282,12 @@ ulong Query_cache::init_cache()
mem_bin_steps = 1;
mem_bin_size = max_mem_bin_size >> QUERY_CACHE_MEM_BIN_STEP_PWR2;
prev_size = 0;
if (mem_bin_size <= min_allocation_unit)
{
DBUG_PRINT("qcache", ("too small query cache => query cache disabled"));
// TODO here (and above) should be warning in 4.1
goto err;
}
while (mem_bin_size > min_allocation_unit)
{
mem_bin_num += mem_bin_count;
......@@ -1308,14 +1314,6 @@ ulong Query_cache::init_cache()
query_cache_size -= additional_data_size;
STRUCT_LOCK(&structure_guard_mutex);
if (max_mem_bin_size <= min_allocation_unit)
{
DBUG_PRINT("qcache",
(" max bin size (%lu) <= min_allocation_unit => cache disabled",
max_mem_bin_size));
STRUCT_UNLOCK(&structure_guard_mutex);
goto err;
}
if (!(cache = (byte *)
my_malloc_lock(query_cache_size+additional_data_size, MYF(0))))
......
......@@ -912,22 +912,32 @@ mysql_rename_table(enum db_type base,
}
/*
close table in this thread and force close + reopen in other threads
This assumes that the calling thread has lock on LOCK_open
Force all other threads to stop using the table
SYNOPSIS
wait_while_table_is_used()
thd Thread handler
table Table to remove from cache
NOTES
When returning, the table will be unusable for other threads until
the table is closed.
PREREQUISITES
Lock on LOCK_open
Win32 clients must also have a WRITE LOCK on the table !
*/
static void safe_remove_from_cache(THD *thd,TABLE *table)
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_ENTER("wait_while_table_is_used");
safe_mutex_assert_owner(&LOCK_open);
VOID(table->file->extra(HA_EXTRA_FORCE_REOPEN)); // Close all data files
/* Mark all tables that are in use as 'old' */
mysql_lock_abort(thd,table); // end threads waiting on lock
mysql_lock_abort(thd, table); // end threads waiting on lock
#if defined(USING_TRANSACTIONS) || defined( __WIN__) || defined( __EMX__) || !defined(OS2)
/* Wait until all there are no other threads that has this table open */
while (remove_table_from_cache(thd,table->table_cache_key,
table->real_name))
......@@ -936,25 +946,31 @@ static void safe_remove_from_cache(THD *thd,TABLE *table)
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
dropping_tables--;
}
#else
(void) remove_table_from_cache(thd,table->table_cache_key,
table->real_name);
#endif
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
}
DBUG_VOID_RETURN;
}
/*
Close a cached table
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 !
*/
bool close_cached_table(THD *thd,TABLE *table)
static bool close_cached_table(THD *thd, TABLE *table)
{
DBUG_ENTER("close_cached_table");
safe_mutex_assert_owner(&LOCK_open);
if (table)
{
safe_remove_from_cache(thd,table);
wait_while_table_is_used(thd,table);
/* Close lock if this is not got with LOCK TABLES */
if (thd->lock)
{
......@@ -963,7 +979,9 @@ bool close_cached_table(THD *thd,TABLE *table)
}
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
thd->open_tables=unlink_open_table(thd,thd->open_tables,table);
}
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
DBUG_RETURN(0);
}
......@@ -1094,10 +1112,13 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
sprintf(tmp,"%s-%lx_%lx", from, current_pid, thd->thread_id);
/* If we could open the table, close it */
if (table_list->table)
{
pthread_mutex_lock(&LOCK_open);
close_cached_table(thd,table_list->table);
close_cached_table(thd, table);
pthread_mutex_unlock(&LOCK_open);
}
if (lock_and_wait_for_table_name(thd,table_list))
{
error= -1;
......@@ -1494,11 +1515,10 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
else
{
*fn_ext(new_name)=0;
close_cached_table(thd,table);
close_cached_table(thd, table);
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
error= -1;
}
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
}
if (!error)
......@@ -1507,12 +1527,18 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
case LEAVE_AS_IS:
break;
case ENABLE:
safe_remove_from_cache(thd,table);
VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table);
VOID(pthread_mutex_unlock(&LOCK_open));
error= table->file->activate_all_index(thd);
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
safe_remove_from_cache(thd,table);
VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table);
VOID(pthread_mutex_unlock(&LOCK_open));
table->file->deactivate_non_unique_index(HA_POS_ERROR);
/* COND_refresh will be signaled in close_thread_tables() */
break;
}
}
......@@ -1936,7 +1962,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
close the original table at before doing the rename
*/
table_name=thd->strdup(table_name); // must be saved
if (close_cached_table(thd,table))
if (close_cached_table(thd, table))
{ // Aborted
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
......@@ -1970,6 +1996,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
This shouldn't happen. We solve this the safe way by
closing the locked table.
*/
if (table)
close_cached_table(thd,table);
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
......@@ -1980,6 +2007,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
Not table locking or alter table with rename
free locks and remove old table
*/
if (table)
close_cached_table(thd,table);
VOID(quick_rm_table(old_db_type,db,old_name));
}
......@@ -2000,6 +2028,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (close_data_tables(thd,db,table_name) ||
reopen_tables(thd,1,0))
{ // This shouldn't happen
if (table)
close_cached_table(thd,table); // Remove lock for table
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
......
......@@ -3397,6 +3397,7 @@ keyword:
| USE_FRM {}
| VARIABLES {}
| WORK_SYM {}
| X509_SYM {}
| YEAR_SYM {};
/* Option functions */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment