mirror of
https://github.com/MariaDB/server.git
synced 2025-02-13 17:05:35 +01:00
Fix XtraDB LPBug #714143 :
Windows native async io is disabled. The patch uses completion ports for asynchronous IO notification , instead of formerly used notification via event . This also removes the limit of 64 async IOs per background IO thread (this limit was forced by using WaitForMultipleObjects in previous AIO implementation)
This commit is contained in:
parent
824ce5f3ea
commit
4bca1a786f
5 changed files with 181 additions and 293 deletions
CMakeLists.txt
storage
|
@ -59,7 +59,7 @@ IF (MSVC_VERSION GREATER 1400)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
|
|
||||||
SET(CMAKE_INSTALL_PREFIX "C:/MariaDB${MYSQL_BASE_VERSION}")
|
SET(CMAKE_INSTALL_PREFIX "C:/MariaDB${MYSQL_BASE_VERSION}" CACHE PATH "Default installation directory")
|
||||||
SET(INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}")
|
SET(INSTALL_ROOT "${CMAKE_INSTALL_PREFIX}")
|
||||||
# Set standard options
|
# Set standard options
|
||||||
ADD_DEFINITIONS(-DHAVE_YASSL)
|
ADD_DEFINITIONS(-DHAVE_YASSL)
|
||||||
|
|
|
@ -10916,12 +10916,12 @@ static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
|
||||||
static MYSQL_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
|
static MYSQL_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
|
||||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
"Number of background read I/O threads in InnoDB.",
|
"Number of background read I/O threads in InnoDB.",
|
||||||
NULL, NULL, 4, 1, 64, 0);
|
NULL, NULL, IF_WIN(1,4), 1, 64, 0);
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
|
static MYSQL_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
|
||||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
"Number of background write I/O threads in InnoDB.",
|
"Number of background write I/O threads in InnoDB.",
|
||||||
NULL, NULL, 4, 1, 64, 0);
|
NULL, NULL, IF_WIN(1,4), 1, 64, 0);
|
||||||
|
|
||||||
static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
|
static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
|
||||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||||
|
|
|
@ -152,8 +152,8 @@ log. */
|
||||||
#define OS_FILE_LOG 256 /* This can be ORed to type */
|
#define OS_FILE_LOG 256 /* This can be ORed to type */
|
||||||
/* @} */
|
/* @} */
|
||||||
|
|
||||||
#define OS_AIO_N_PENDING_IOS_PER_THREAD 32 /*!< Win NT does not allow more
|
#define OS_AIO_N_PENDING_IOS_PER_THREAD 256 /*!< Windows might be able to handle
|
||||||
than 64 */
|
more */
|
||||||
|
|
||||||
/** Modes for aio operations @{ */
|
/** Modes for aio operations @{ */
|
||||||
#define OS_AIO_NORMAL 21 /*!< Normal asynchronous i/o not for ibuf
|
#define OS_AIO_NORMAL 21 /*!< Normal asynchronous i/o not for ibuf
|
||||||
|
|
|
@ -121,6 +121,12 @@ typedef struct os_aio_slot_struct os_aio_slot_t;
|
||||||
|
|
||||||
/** The asynchronous i/o array slot structure */
|
/** The asynchronous i/o array slot structure */
|
||||||
struct os_aio_slot_struct{
|
struct os_aio_slot_struct{
|
||||||
|
#ifdef WIN_ASYNC_IO
|
||||||
|
OVERLAPPED control; /*!< Windows control block for the
|
||||||
|
aio request, MUST be first element in the structure*/
|
||||||
|
void *arr; /*!< Array this slot belongs to*/
|
||||||
|
#endif
|
||||||
|
|
||||||
ibool is_read; /*!< TRUE if a read operation */
|
ibool is_read; /*!< TRUE if a read operation */
|
||||||
ulint pos; /*!< index of the slot in the aio
|
ulint pos; /*!< index of the slot in the aio
|
||||||
array */
|
array */
|
||||||
|
@ -148,12 +154,6 @@ struct os_aio_slot_struct{
|
||||||
and which can be used to identify
|
and which can be used to identify
|
||||||
which pending aio operation was
|
which pending aio operation was
|
||||||
completed */
|
completed */
|
||||||
#ifdef WIN_ASYNC_IO
|
|
||||||
os_event_t event; /*!< event object we need in the
|
|
||||||
OVERLAPPED struct */
|
|
||||||
OVERLAPPED control; /*!< Windows control block for the
|
|
||||||
aio request */
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The asynchronous i/o array structure */
|
/** The asynchronous i/o array structure */
|
||||||
|
@ -182,15 +182,6 @@ struct os_aio_array_struct{
|
||||||
/*!< Number of reserved slots in the
|
/*!< Number of reserved slots in the
|
||||||
aio array outside the ibuf segment */
|
aio array outside the ibuf segment */
|
||||||
os_aio_slot_t* slots; /*!< Pointer to the slots in the array */
|
os_aio_slot_t* slots; /*!< Pointer to the slots in the array */
|
||||||
#ifdef __WIN__
|
|
||||||
os_native_event_t* native_events;
|
|
||||||
/*!< Pointer to an array of OS native
|
|
||||||
event handles where we copied the
|
|
||||||
handles from slots, in the same
|
|
||||||
order. This can be used in
|
|
||||||
WaitForMultipleObjects; used only in
|
|
||||||
Windows */
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Array of events used in simulated aio */
|
/** Array of events used in simulated aio */
|
||||||
|
@ -250,6 +241,14 @@ UNIV_INTERN ulint os_n_pending_writes = 0;
|
||||||
/** Number of pending read operations */
|
/** Number of pending read operations */
|
||||||
UNIV_INTERN ulint os_n_pending_reads = 0;
|
UNIV_INTERN ulint os_n_pending_reads = 0;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/** IO completion port used by background io threads */
|
||||||
|
static HANDLE completion_port;
|
||||||
|
/** Thread local storage index for the per-thread event used for synchronous IO */
|
||||||
|
static DWORD tls_sync_io = TLS_OUT_OF_INDEXES;
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************************//**
|
/***********************************************************************//**
|
||||||
Gets the operating system version. Currently works only on Windows.
|
Gets the operating system version. Currently works only on Windows.
|
||||||
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
|
@return OS_WIN95, OS_WIN31, OS_WINNT, OS_WIN2000 */
|
||||||
|
@ -286,6 +285,86 @@ os_get_os_version(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/*
|
||||||
|
Windows : Handling synchronous IO on files opened asynchronously.
|
||||||
|
|
||||||
|
If file is opened for asynchronous IO (FILE_FLAG_OVERLAPPED) and also bound to
|
||||||
|
a completion port, then every IO on this file would normally be enqueued to the
|
||||||
|
completion port. Sometimes however we would like to do a synchronous IO. This is
|
||||||
|
possible if we initialitze have overlapped.hEvent with a valid event and set its
|
||||||
|
lowest order bit to 1 (see MSDN ReadFile and WriteFile description for more info)
|
||||||
|
|
||||||
|
We'll create this special event once for each thread and store in thread local
|
||||||
|
storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************//**
|
||||||
|
Initialize tls index.for event handle used for synchronized IO on files that
|
||||||
|
might be opened with FILE_FLAG_OVERLAPPED.
|
||||||
|
*/
|
||||||
|
static void win_init_syncio_event()
|
||||||
|
{
|
||||||
|
tls_sync_io = TlsAlloc();
|
||||||
|
ut_a(tls_sync_io != TLS_OUT_OF_INDEXES);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************//**
|
||||||
|
Retrieve per-thread event for doing synchronous io on asyncronously opened files
|
||||||
|
*/
|
||||||
|
static HANDLE win_get_syncio_event()
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
if(tls_sync_io == TLS_OUT_OF_INDEXES){
|
||||||
|
win_init_syncio_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
h = (HANDLE)TlsGetValue(tls_sync_io);
|
||||||
|
if (h)
|
||||||
|
return h;
|
||||||
|
h = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||||
|
ut_a(h);
|
||||||
|
h = (HANDLE)((uintptr_t)h | 1);
|
||||||
|
TlsSetValue(tls_sync_io, h);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TLS destructor, inspired by Chromium code
|
||||||
|
http://src.chromium.org/svn/trunk/src/base/threading/thread_local_storage_win.cc
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void win_free_syncio_event()
|
||||||
|
{
|
||||||
|
HANDLE h = win_get_syncio_event();
|
||||||
|
if (h) {
|
||||||
|
CloseHandle(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NTAPI win_tls_thread_exit(PVOID module, DWORD reason, PVOID reserved) {
|
||||||
|
if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason)
|
||||||
|
win_free_syncio_event();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
#pragma comment(linker, "/INCLUDE:_tls_used")
|
||||||
|
#pragma comment(linker, "/INCLUDE:p_thread_callback_base")
|
||||||
|
#pragma const_seg(".CRT$XLB")
|
||||||
|
extern const PIMAGE_TLS_CALLBACK p_thread_callback_base;
|
||||||
|
const PIMAGE_TLS_CALLBACK p_thread_callback_base = win_tls_thread_exit;
|
||||||
|
#pragma data_seg()
|
||||||
|
#else
|
||||||
|
#pragma comment(linker, "/INCLUDE:__tls_used")
|
||||||
|
#pragma comment(linker, "/INCLUDE:_p_thread_callback_base")
|
||||||
|
#pragma data_seg(".CRT$XLB")
|
||||||
|
PIMAGE_TLS_CALLBACK p_thread_callback_base = win_tls_thread_exit;
|
||||||
|
#pragma data_seg()
|
||||||
|
#endif
|
||||||
|
#endif /*_WIN32 */
|
||||||
|
|
||||||
/***********************************************************************//**
|
/***********************************************************************//**
|
||||||
Retrieves the last error number if an error occurs in a file io function.
|
Retrieves the last error number if an error occurs in a file io function.
|
||||||
The number should be retrieved before any other OS calls (because they may
|
The number should be retrieved before any other OS calls (because they may
|
||||||
|
@ -611,6 +690,9 @@ os_io_init_simple(void)
|
||||||
for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
|
for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
|
||||||
os_file_seek_mutexes[i] = os_mutex_create(NULL);
|
os_file_seek_mutexes[i] = os_mutex_create(NULL);
|
||||||
}
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
win_init_syncio_event();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************//**
|
/***********************************************************************//**
|
||||||
|
@ -1325,6 +1407,8 @@ try_again:
|
||||||
#endif
|
#endif
|
||||||
#ifdef UNIV_NON_BUFFERED_IO
|
#ifdef UNIV_NON_BUFFERED_IO
|
||||||
# ifndef UNIV_HOTBACKUP
|
# ifndef UNIV_HOTBACKUP
|
||||||
|
if (type == OS_LOG_FILE)
|
||||||
|
attributes = attributes | FILE_FLAG_SEQUENTIAL_SCAN;
|
||||||
if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
|
if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
|
||||||
/* Do not use unbuffered i/o to log files because
|
/* Do not use unbuffered i/o to log files because
|
||||||
value 2 denotes that we do not flush the log at every
|
value 2 denotes that we do not flush the log at every
|
||||||
|
@ -1402,6 +1486,9 @@ try_again:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*success = TRUE;
|
*success = TRUE;
|
||||||
|
if (os_aio_use_native_aio && ((attributes & FILE_FLAG_OVERLAPPED) != 0)) {
|
||||||
|
ut_a(CreateIoCompletionPort(file, completion_port, 0, 0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(file);
|
return(file);
|
||||||
|
@ -2350,13 +2437,10 @@ _os_file_read(
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
DWORD ret2;
|
|
||||||
DWORD low;
|
DWORD low;
|
||||||
DWORD high;
|
DWORD high;
|
||||||
ibool retry;
|
ibool retry;
|
||||||
#ifndef UNIV_HOTBACKUP
|
OVERLAPPED overlapped;
|
||||||
ulint i;
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
|
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
|
||||||
no more than 32 bits. */
|
no more than 32 bits. */
|
||||||
|
@ -2378,33 +2462,18 @@ try_again:
|
||||||
os_n_pending_reads++;
|
os_n_pending_reads++;
|
||||||
os_mutex_exit(os_file_count_mutex);
|
os_mutex_exit(os_file_count_mutex);
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
memset (&overlapped, 0, sizeof (overlapped));
|
||||||
/* Protect the seek / read operation with a mutex */
|
overlapped.Offset = low;
|
||||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
overlapped.OffsetHigh = high;
|
||||||
|
overlapped.hEvent = win_get_syncio_event();
|
||||||
|
|
||||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
ret = ReadFile(file, buf, n, NULL, &overlapped);
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
if (ret) {
|
||||||
|
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, FALSE);
|
||||||
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
|
}
|
||||||
|
else if(GetLastError() == ERROR_IO_PENDING) {
|
||||||
if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
|
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE);
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_count_mutex);
|
|
||||||
os_n_pending_reads--;
|
|
||||||
os_mutex_exit(os_file_count_mutex);
|
|
||||||
|
|
||||||
goto error_handling;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
|
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_count_mutex);
|
os_mutex_enter(os_file_count_mutex);
|
||||||
os_n_pending_reads--;
|
os_n_pending_reads--;
|
||||||
|
@ -2433,9 +2502,6 @@ try_again:
|
||||||
(ulong)n, (ulong)offset_high,
|
(ulong)n, (ulong)offset_high,
|
||||||
(ulong)offset, (long)ret);
|
(ulong)offset, (long)ret);
|
||||||
#endif /* __WIN__ */
|
#endif /* __WIN__ */
|
||||||
#ifdef __WIN__
|
|
||||||
error_handling:
|
|
||||||
#endif
|
|
||||||
retry = os_file_handle_error(NULL, "read");
|
retry = os_file_handle_error(NULL, "read");
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
|
@ -2477,13 +2543,10 @@ os_file_read_no_error_handling(
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
DWORD ret2;
|
|
||||||
DWORD low;
|
DWORD low;
|
||||||
DWORD high;
|
DWORD high;
|
||||||
ibool retry;
|
ibool retry;
|
||||||
#ifndef UNIV_HOTBACKUP
|
OVERLAPPED overlapped;
|
||||||
ulint i;
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
|
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
|
||||||
no more than 32 bits. */
|
no more than 32 bits. */
|
||||||
|
@ -2505,33 +2568,19 @@ try_again:
|
||||||
os_n_pending_reads++;
|
os_n_pending_reads++;
|
||||||
os_mutex_exit(os_file_count_mutex);
|
os_mutex_exit(os_file_count_mutex);
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
/* Protect the seek / read operation with a mutex */
|
|
||||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
memset (&overlapped, 0, sizeof (overlapped));
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
overlapped.Offset = low;
|
||||||
|
overlapped.OffsetHigh = high;
|
||||||
|
overlapped.hEvent = win_get_syncio_event();
|
||||||
|
|
||||||
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
|
ret = ReadFile(file, buf, n, NULL, &overlapped);
|
||||||
|
if (ret) {
|
||||||
if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
|
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, FALSE);
|
||||||
|
}
|
||||||
#ifndef UNIV_HOTBACKUP
|
else if(GetLastError() == ERROR_IO_PENDING) {
|
||||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE);
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_count_mutex);
|
|
||||||
os_n_pending_reads--;
|
|
||||||
os_mutex_exit(os_file_count_mutex);
|
|
||||||
|
|
||||||
goto error_handling;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
|
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_count_mutex);
|
os_mutex_enter(os_file_count_mutex);
|
||||||
os_n_pending_reads--;
|
os_n_pending_reads--;
|
||||||
|
@ -2554,9 +2603,6 @@ try_again:
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
#endif /* __WIN__ */
|
#endif /* __WIN__ */
|
||||||
#ifdef __WIN__
|
|
||||||
error_handling:
|
|
||||||
#endif
|
|
||||||
retry = os_file_handle_error_no_exit(NULL, "read");
|
retry = os_file_handle_error_no_exit(NULL, "read");
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
|
@ -2609,14 +2655,11 @@ os_file_write(
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
DWORD ret2;
|
|
||||||
DWORD low;
|
DWORD low;
|
||||||
DWORD high;
|
DWORD high;
|
||||||
ulint n_retries = 0;
|
ulint n_retries = 0;
|
||||||
ulint err;
|
ulint err;
|
||||||
#ifndef UNIV_HOTBACKUP
|
OVERLAPPED overlapped;
|
||||||
ulint i;
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
|
/* On 64-bit Windows, ulint is 64 bits. But offset and n should be
|
||||||
no more than 32 bits. */
|
no more than 32 bits. */
|
||||||
|
@ -2636,56 +2679,18 @@ retry:
|
||||||
os_n_pending_writes++;
|
os_n_pending_writes++;
|
||||||
os_mutex_exit(os_file_count_mutex);
|
os_mutex_exit(os_file_count_mutex);
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
memset (&overlapped, 0, sizeof (overlapped));
|
||||||
/* Protect the seek / write operation with a mutex */
|
overlapped.Offset = low;
|
||||||
i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
|
overlapped.OffsetHigh = high;
|
||||||
|
overlapped.hEvent = win_get_syncio_event();
|
||||||
|
|
||||||
os_mutex_enter(os_file_seek_mutexes[i]);
|
ret = WriteFile(file, buf, n, NULL, &overlapped);
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
if (ret) {
|
||||||
|
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, FALSE);
|
||||||
ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
|
|
||||||
|
|
||||||
if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
|
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_count_mutex);
|
|
||||||
os_n_pending_writes--;
|
|
||||||
os_mutex_exit(os_file_count_mutex);
|
|
||||||
|
|
||||||
ut_print_timestamp(stderr);
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
" InnoDB: Error: File pointer positioning to"
|
|
||||||
" file %s failed at\n"
|
|
||||||
"InnoDB: offset %lu %lu. Operating system"
|
|
||||||
" error number %lu.\n"
|
|
||||||
"InnoDB: Some operating system error numbers"
|
|
||||||
" are described at\n"
|
|
||||||
"InnoDB: "
|
|
||||||
REFMAN "operating-system-error-codes.html\n",
|
|
||||||
name, (ulong) offset_high, (ulong) offset,
|
|
||||||
(ulong) GetLastError());
|
|
||||||
|
|
||||||
return(FALSE);
|
|
||||||
}
|
}
|
||||||
|
else if(GetLastError() == ERROR_IO_PENDING) {
|
||||||
ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
|
ret = GetOverlappedResult(file, &overlapped, (DWORD *)&len, TRUE);
|
||||||
|
|
||||||
/* Always do fsync to reduce the probability that when the OS crashes,
|
|
||||||
a database page is only partially physically written to disk. */
|
|
||||||
|
|
||||||
# ifdef UNIV_DO_FLUSH
|
|
||||||
if (!os_do_not_call_flush_at_each_write) {
|
|
||||||
ut_a(TRUE == os_file_flush(file));
|
|
||||||
}
|
}
|
||||||
# endif /* UNIV_DO_FLUSH */
|
|
||||||
|
|
||||||
#ifndef UNIV_HOTBACKUP
|
|
||||||
os_mutex_exit(os_file_seek_mutexes[i]);
|
|
||||||
#endif /* !UNIV_HOTBACKUP */
|
|
||||||
|
|
||||||
os_mutex_enter(os_file_count_mutex);
|
os_mutex_enter(os_file_count_mutex);
|
||||||
os_n_pending_writes--;
|
os_n_pending_writes--;
|
||||||
|
@ -3071,9 +3076,6 @@ os_aio_array_create(
|
||||||
os_aio_array_t* array;
|
os_aio_array_t* array;
|
||||||
ulint i;
|
ulint i;
|
||||||
os_aio_slot_t* slot;
|
os_aio_slot_t* slot;
|
||||||
#ifdef WIN_ASYNC_IO
|
|
||||||
OVERLAPPED* over;
|
|
||||||
#endif
|
|
||||||
ut_a(n > 0);
|
ut_a(n > 0);
|
||||||
ut_a(n_segments > 0);
|
ut_a(n_segments > 0);
|
||||||
|
|
||||||
|
@ -3089,23 +3091,11 @@ os_aio_array_create(
|
||||||
array->n_segments = n_segments;
|
array->n_segments = n_segments;
|
||||||
array->n_reserved = 0;
|
array->n_reserved = 0;
|
||||||
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
|
array->slots = ut_malloc(n * sizeof(os_aio_slot_t));
|
||||||
#ifdef __WIN__
|
|
||||||
array->native_events = ut_malloc(n * sizeof(os_native_event_t));
|
|
||||||
#endif
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
slot = os_aio_array_get_nth_slot(array, i);
|
slot = os_aio_array_get_nth_slot(array, i);
|
||||||
|
|
||||||
slot->pos = i;
|
slot->pos = i;
|
||||||
slot->reserved = FALSE;
|
slot->reserved = FALSE;
|
||||||
#ifdef WIN_ASYNC_IO
|
|
||||||
slot->event = os_event_create(NULL);
|
|
||||||
|
|
||||||
over = &(slot->control);
|
|
||||||
|
|
||||||
over->hEvent = slot->event->handle;
|
|
||||||
|
|
||||||
*((array->native_events) + i) = over->hEvent;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(array);
|
return(array);
|
||||||
|
@ -3119,18 +3109,7 @@ os_aio_array_free(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
os_aio_array_t* array) /*!< in, own: array to free */
|
os_aio_array_t* array) /*!< in, own: array to free */
|
||||||
{
|
{
|
||||||
#ifdef WIN_ASYNC_IO
|
|
||||||
ulint i;
|
|
||||||
|
|
||||||
for (i = 0; i < array->n_slots; i++) {
|
|
||||||
os_aio_slot_t* slot = os_aio_array_get_nth_slot(array, i);
|
|
||||||
os_event_free(slot->event);
|
|
||||||
}
|
|
||||||
#endif /* WIN_ASYNC_IO */
|
|
||||||
|
|
||||||
#ifdef __WIN__
|
|
||||||
ut_free(array->native_events);
|
|
||||||
#endif /* __WIN__ */
|
|
||||||
os_mutex_free(array->mutex);
|
os_mutex_free(array->mutex);
|
||||||
os_event_free(array->not_full);
|
os_event_free(array->not_full);
|
||||||
os_event_free(array->is_empty);
|
os_event_free(array->is_empty);
|
||||||
|
@ -3209,7 +3188,11 @@ os_aio_init(
|
||||||
}
|
}
|
||||||
|
|
||||||
os_last_printout = time(NULL);
|
os_last_printout = time(NULL);
|
||||||
|
#ifdef _WIN32
|
||||||
|
ut_a(completion_port == 0);
|
||||||
|
completion_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
|
||||||
|
ut_a(completion_port);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -3251,11 +3234,10 @@ os_aio_array_wake_win_aio_at_shutdown(
|
||||||
/*==================================*/
|
/*==================================*/
|
||||||
os_aio_array_t* array) /*!< in: aio array */
|
os_aio_array_t* array) /*!< in: aio array */
|
||||||
{
|
{
|
||||||
ulint i;
|
if(completion_port)
|
||||||
|
{
|
||||||
for (i = 0; i < array->n_slots; i++) {
|
ut_a(CloseHandle(completion_port));
|
||||||
|
completion_port = 0;
|
||||||
os_event_set((array->slots + i)->event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3480,7 +3462,8 @@ found:
|
||||||
control = &(slot->control);
|
control = &(slot->control);
|
||||||
control->Offset = (DWORD)offset;
|
control->Offset = (DWORD)offset;
|
||||||
control->OffsetHigh = (DWORD)offset_high;
|
control->OffsetHigh = (DWORD)offset_high;
|
||||||
os_event_reset(slot->event);
|
control->hEvent = 0;
|
||||||
|
slot->arr = array;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
os_mutex_exit(array->mutex);
|
os_mutex_exit(array->mutex);
|
||||||
|
@ -3517,9 +3500,6 @@ os_aio_array_free_slot(
|
||||||
os_event_set(array->is_empty);
|
os_event_set(array->is_empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN_ASYNC_IO
|
|
||||||
os_event_reset(slot->event);
|
|
||||||
#endif
|
|
||||||
os_mutex_exit(array->mutex);
|
os_mutex_exit(array->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3689,12 +3669,8 @@ os_aio(
|
||||||
os_aio_array_t* array;
|
os_aio_array_t* array;
|
||||||
os_aio_slot_t* slot;
|
os_aio_slot_t* slot;
|
||||||
#ifdef WIN_ASYNC_IO
|
#ifdef WIN_ASYNC_IO
|
||||||
ibool retval;
|
|
||||||
BOOL ret = TRUE;
|
|
||||||
DWORD len = (DWORD) n;
|
DWORD len = (DWORD) n;
|
||||||
struct fil_node_struct * dummy_mess1;
|
BOOL ret;
|
||||||
void* dummy_mess2;
|
|
||||||
ulint dummy_type;
|
|
||||||
#endif
|
#endif
|
||||||
ulint err = 0;
|
ulint err = 0;
|
||||||
ibool retry;
|
ibool retry;
|
||||||
|
@ -3713,26 +3689,23 @@ os_aio(
|
||||||
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
|
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
|
||||||
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
|
mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
|
||||||
|
|
||||||
if (mode == OS_AIO_SYNC
|
if (mode == OS_AIO_SYNC)
|
||||||
#ifdef WIN_ASYNC_IO
|
{
|
||||||
&& !os_aio_use_native_aio
|
ibool ret;
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
/* This is actually an ordinary synchronous read or write:
|
/* This is actually an ordinary synchronous read or write:
|
||||||
no need to use an i/o-handler thread. NOTE that if we use
|
no need to use an i/o-handler thread */
|
||||||
Windows async i/o, Windows does not allow us to use
|
|
||||||
ordinary synchronous os_file_read etc. on the same file,
|
|
||||||
therefore we have built a special mechanism for synchronous
|
|
||||||
wait in the Windows case. */
|
|
||||||
|
|
||||||
if (type == OS_FILE_READ) {
|
if (type == OS_FILE_READ) {
|
||||||
return(_os_file_read(file, buf, offset,
|
ret = _os_file_read(file, buf, offset,
|
||||||
offset_high, n, trx));
|
offset_high, n, trx);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
ut_a(type == OS_FILE_WRITE);
|
||||||
|
|
||||||
ut_a(type == OS_FILE_WRITE);
|
ret = os_file_write(name, file, buf, offset, offset_high, n);
|
||||||
|
}
|
||||||
return(os_file_write(name, file, buf, offset, offset_high, n));
|
ut_a(ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
try_again:
|
try_again:
|
||||||
|
@ -3775,6 +3748,8 @@ try_again:
|
||||||
|
|
||||||
ret = ReadFile(file, buf, (DWORD)n, &len,
|
ret = ReadFile(file, buf, (DWORD)n, &len,
|
||||||
&(slot->control));
|
&(slot->control));
|
||||||
|
if(!ret && GetLastError() != ERROR_IO_PENDING)
|
||||||
|
err = 1;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!wake_later) {
|
if (!wake_later) {
|
||||||
|
@ -3789,6 +3764,8 @@ try_again:
|
||||||
os_n_file_writes++;
|
os_n_file_writes++;
|
||||||
ret = WriteFile(file, buf, (DWORD)n, &len,
|
ret = WriteFile(file, buf, (DWORD)n, &len,
|
||||||
&(slot->control));
|
&(slot->control));
|
||||||
|
if(!ret && GetLastError() != ERROR_IO_PENDING)
|
||||||
|
err = 1;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (!wake_later) {
|
if (!wake_later) {
|
||||||
|
@ -3801,34 +3778,7 @@ try_again:
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN_ASYNC_IO
|
|
||||||
if (os_aio_use_native_aio) {
|
|
||||||
if ((ret && len == n)
|
|
||||||
|| (!ret && GetLastError() == ERROR_IO_PENDING)) {
|
|
||||||
/* aio was queued successfully! */
|
|
||||||
|
|
||||||
if (mode == OS_AIO_SYNC) {
|
|
||||||
/* We want a synchronous i/o operation on a
|
|
||||||
file where we also use async i/o: in Windows
|
|
||||||
we must use the same wait mechanism as for
|
|
||||||
async i/o */
|
|
||||||
|
|
||||||
retval = os_aio_windows_handle(ULINT_UNDEFINED,
|
|
||||||
slot->pos,
|
|
||||||
&dummy_mess1,
|
|
||||||
&dummy_mess2,
|
|
||||||
&dummy_type,
|
|
||||||
&space_id);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = 1; /* Fall through the next if */
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
/* aio was queued successfully! */
|
/* aio was queued successfully! */
|
||||||
|
|
||||||
|
@ -3881,52 +3831,21 @@ os_aio_windows_handle(
|
||||||
ulint* space_id)
|
ulint* space_id)
|
||||||
{
|
{
|
||||||
ulint orig_seg = segment;
|
ulint orig_seg = segment;
|
||||||
os_aio_array_t* array;
|
|
||||||
os_aio_slot_t* slot;
|
os_aio_slot_t* slot;
|
||||||
ulint n;
|
|
||||||
ulint i;
|
|
||||||
ibool ret_val;
|
ibool ret_val;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
DWORD len;
|
DWORD len;
|
||||||
BOOL retry = FALSE;
|
BOOL retry = FALSE;
|
||||||
|
ULONG_PTR dummy_key;
|
||||||
|
|
||||||
if (segment == ULINT_UNDEFINED) {
|
|
||||||
array = os_aio_sync_array;
|
ret = GetQueuedCompletionStatus(completion_port, &len, &dummy_key,
|
||||||
segment = 0;
|
(OVERLAPPED **)&slot, INFINITE);
|
||||||
} else {
|
|
||||||
segment = os_aio_get_array_and_local_segment(&array, segment);
|
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
|
||||||
|
os_thread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE! We only access constant fields in os_aio_array. Therefore
|
|
||||||
we do not have to acquire the protecting mutex yet */
|
|
||||||
|
|
||||||
ut_ad(os_aio_validate());
|
|
||||||
ut_ad(segment < array->n_segments);
|
|
||||||
|
|
||||||
n = array->n_slots;
|
|
||||||
|
|
||||||
if (array == os_aio_sync_array) {
|
|
||||||
os_event_wait(os_aio_array_get_nth_slot(array, pos)->event);
|
|
||||||
i = pos;
|
|
||||||
} else {
|
|
||||||
srv_set_io_thread_op_info(orig_seg, "wait Windows aio");
|
|
||||||
i = os_event_wait_multiple(n,
|
|
||||||
(array->native_events)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
os_mutex_enter(array->mutex);
|
|
||||||
|
|
||||||
slot = os_aio_array_get_nth_slot(array, i);
|
|
||||||
|
|
||||||
ut_a(slot->reserved);
|
|
||||||
|
|
||||||
if (orig_seg != ULINT_UNDEFINED) {
|
|
||||||
srv_set_io_thread_op_info(orig_seg,
|
|
||||||
"get windows aio return value");
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
|
|
||||||
|
|
||||||
*message1 = slot->message1;
|
*message1 = slot->message1;
|
||||||
*message2 = slot->message2;
|
*message2 = slot->message2;
|
||||||
|
@ -3951,8 +3870,6 @@ os_aio_windows_handle(
|
||||||
ret_val = FALSE;
|
ret_val = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
os_mutex_exit(array->mutex);
|
|
||||||
|
|
||||||
if (retry) {
|
if (retry) {
|
||||||
/* retry failed read/write operation synchronously.
|
/* retry failed read/write operation synchronously.
|
||||||
No need to hold array->mutex. */
|
No need to hold array->mutex. */
|
||||||
|
@ -3961,37 +3878,19 @@ os_aio_windows_handle(
|
||||||
|
|
||||||
switch (slot->type) {
|
switch (slot->type) {
|
||||||
case OS_FILE_WRITE:
|
case OS_FILE_WRITE:
|
||||||
ret = WriteFile(slot->file, slot->buf,
|
ret_val = os_file_write(slot->name, slot->file, slot->buf,
|
||||||
(DWORD) slot->len, &len,
|
slot->control.Offset, slot->control.OffsetHigh, slot->len);
|
||||||
&(slot->control));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case OS_FILE_READ:
|
case OS_FILE_READ:
|
||||||
ret = ReadFile(slot->file, slot->buf,
|
ret_val = os_file_read(slot->file, slot->buf,
|
||||||
(DWORD) slot->len, &len,
|
slot->control.Offset, slot->control.OffsetHigh, slot->len);
|
||||||
&(slot->control));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret && GetLastError() == ERROR_IO_PENDING) {
|
|
||||||
/* aio was queued successfully!
|
|
||||||
We want a synchronous i/o operation on a
|
|
||||||
file where we also use async i/o: in Windows
|
|
||||||
we must use the same wait mechanism as for
|
|
||||||
async i/o */
|
|
||||||
|
|
||||||
ret = GetOverlappedResult(slot->file,
|
|
||||||
&(slot->control),
|
|
||||||
&len, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret_val = ret && len == slot->len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os_aio_array_free_slot(array, slot);
|
os_aio_array_free_slot((os_aio_array_t *)slot->arr, slot);
|
||||||
|
|
||||||
return(ret_val);
|
return(ret_val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1274,13 +1274,7 @@ innobase_start_or_create_for_mysql(void)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* On Win 2000 and XP use async i/o */
|
/* On Win 2000 and XP use async i/o */
|
||||||
//os_aio_use_native_aio = TRUE;
|
os_aio_use_native_aio = TRUE;
|
||||||
os_aio_use_native_aio = FALSE;
|
|
||||||
fprintf(stderr,
|
|
||||||
"InnoDB: Windows native async i/o is disabled as default.\n"
|
|
||||||
"InnoDB: It is not applicable for the current"
|
|
||||||
" multi io threads implementation.\n");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (srv_file_flush_method_str == NULL) {
|
if (srv_file_flush_method_str == NULL) {
|
||||||
|
@ -1320,11 +1314,6 @@ innobase_start_or_create_for_mysql(void)
|
||||||
"async_unbuffered")) {
|
"async_unbuffered")) {
|
||||||
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
|
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
|
||||||
os_aio_use_native_aio = TRUE;
|
os_aio_use_native_aio = TRUE;
|
||||||
srv_n_read_io_threads = srv_n_write_io_threads = 1;
|
|
||||||
fprintf(stderr,
|
|
||||||
"InnoDB: 'async_unbuffered' was detected as innodb_flush_method.\n"
|
|
||||||
"InnoDB: Windows native async i/o is enabled.\n"
|
|
||||||
"InnoDB: And io threads are restricted.\n");
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|
Loading…
Add table
Reference in a new issue