@@ -107,8 +107,9 @@ static ulint os_innodb_umask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
107
107
#else
108
108
/* * Umask for creating files */
109
109
static ulint os_innodb_umask = 0 ;
110
- static HANDLE completion_port;
111
- static HANDLE read_completion_port;
110
+ static HANDLE data_completion_port;
111
+ static HANDLE log_completion_port;
112
+
112
113
static DWORD fls_sync_io = FLS_OUT_OF_INDEXES;
113
114
#define IOCP_SHUTDOWN_KEY (ULONG_PTR)-1
114
115
#endif /* _WIN32 */
@@ -443,11 +444,17 @@ class AIO {
443
444
#endif /* LINUX_NATIVE_AIO */
444
445
445
446
#ifdef WIN_ASYNC_IO
446
-
447
+ HANDLE m_completion_port;
447
448
/* * Wake up all AIO threads in Windows native aio */
448
449
static void wake_at_shutdown () {
449
- PostQueuedCompletionStatus (completion_port, 0 , IOCP_SHUTDOWN_KEY, NULL );
450
- PostQueuedCompletionStatus (read_completion_port, 0 , IOCP_SHUTDOWN_KEY, NULL );
450
+ AIO *all_arrays[] = {s_reads, s_writes, s_log, s_ibuf };
451
+ for (size_t i = 0 ; i < array_elements (all_arrays); i++) {
452
+ AIO *a = all_arrays[i];
453
+ if (a) {
454
+ PostQueuedCompletionStatus (a->m_completion_port , 0 ,
455
+ IOCP_SHUTDOWN_KEY, 0 );
456
+ }
457
+ }
451
458
}
452
459
#endif /* WIN_ASYNC_IO */
453
460
@@ -3520,15 +3527,11 @@ SyncFileIO::execute(Slot* slot)
3520
3527
struct WinIoInit
3521
3528
{
3522
3529
WinIoInit () {
3523
- completion_port = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL , 0 , 0 );
3524
- read_completion_port = CreateIoCompletionPort (INVALID_HANDLE_VALUE, NULL , 0 , 0 ); ut_a (completion_port && read_completion_port);
3525
3530
fls_sync_io = FlsAlloc (win_free_syncio_event);
3526
3531
ut_a (fls_sync_io != FLS_OUT_OF_INDEXES);
3527
3532
}
3528
3533
3529
3534
~WinIoInit () {
3530
- CloseHandle (completion_port);
3531
- CloseHandle (read_completion_port);
3532
3535
FlsFree (fls_sync_io);
3533
3536
}
3534
3537
};
@@ -4300,11 +4303,17 @@ os_file_create_func(
4300
4303
*success = true ;
4301
4304
4302
4305
if (srv_use_native_aio && ((attributes & FILE_FLAG_OVERLAPPED) != 0 )) {
4303
- /* Bind the file handle to completion port */
4304
- ut_a (CreateIoCompletionPort (file, completion_port, 0 , 0 ));
4306
+ /* Bind the file handle to completion port. Completion port
4307
+ might not be created yet, in some stages of backup, but
4308
+ must always be there for the server.*/
4309
+ HANDLE port =(type == OS_LOG_FILE)?
4310
+ log_completion_port : data_completion_port;
4311
+ ut_a (port || srv_operation != SRV_OPERATION_NORMAL);
4312
+ if (port) {
4313
+ ut_a (CreateIoCompletionPort (file, port, 0 , 0 ));
4314
+ }
4305
4315
}
4306
4316
}
4307
-
4308
4317
} while (retry);
4309
4318
4310
4319
return (file);
@@ -5705,6 +5714,15 @@ os_aio_handler(
5705
5714
return (err);
5706
5715
}
5707
5716
5717
+ #ifdef WIN_ASYNC_IO
5718
+ static HANDLE new_completion_port ()
5719
+ {
5720
+ HANDLE h = CreateIoCompletionPort (INVALID_HANDLE_VALUE, 0 , 0 , 0 );
5721
+ ut_a (h);
5722
+ return h;
5723
+ }
5724
+ #endif
5725
+
5708
5726
/* * Constructor
5709
5727
@param[in] id The latch ID
5710
5728
@param[in] n Number of AIO slots
@@ -5721,6 +5739,9 @@ AIO::AIO(
5721
5739
,m_aio_ctx(),
5722
5740
m_events (m_slots.size())
5723
5741
# endif /* LINUX_NATIVE_AIO */
5742
+ #ifdef WIN_ASYNC_IO
5743
+ ,m_completion_port(new_completion_port())
5744
+ #endif
5724
5745
{
5725
5746
ut_a (n > 0 );
5726
5747
ut_a (m_n_segments > 0 );
@@ -5887,6 +5908,9 @@ AIO::~AIO()
5887
5908
ut_free (m_aio_ctx);
5888
5909
}
5889
5910
#endif /* LINUX_NATIVE_AIO */
5911
+ #if defined(WIN_ASYNC_IO)
5912
+ CloseHandle (m_completion_port);
5913
+ #endif
5890
5914
5891
5915
m_slots.clear ();
5892
5916
}
@@ -5973,6 +5997,12 @@ AIO::start(
5973
5997
return (false );
5974
5998
}
5975
5999
6000
+ #ifdef WIN_ASYNC_IO
6001
+ data_completion_port = s_writes->m_completion_port ;
6002
+ log_completion_port =
6003
+ s_log ? s_log->m_completion_port : data_completion_port;
6004
+ #endif
6005
+
5976
6006
n_segments += n_writers;
5977
6007
5978
6008
for (ulint i = start + n_readers; i < n_segments; ++i) {
@@ -6460,8 +6490,7 @@ therefore no other thread is allowed to do the freeing!
6460
6490
@param[out] type OS_FILE_WRITE or ..._READ
6461
6491
@return DB_SUCCESS or error code */
6462
6492
6463
- #define READ_SEGMENT (s ) (s < srv_n_read_io_threads)
6464
- #define WRITE_SEGMENT (s ) !READ_SEGMENT(s)
6493
+
6465
6494
6466
6495
static
6467
6496
dberr_t
@@ -6484,8 +6513,11 @@ os_aio_windows_handler(
6484
6513
we do not have to acquire the protecting mutex yet */
6485
6514
6486
6515
ut_ad (os_aio_validate_skip ());
6516
+ AIO *my_array;
6517
+ AIO::get_array_and_local_segment (&my_array, segment);
6487
6518
6488
- HANDLE port = READ_SEGMENT (segment) ? read_completion_port : completion_port;
6519
+ HANDLE port = my_array->m_completion_port ;
6520
+ ut_ad (port);
6489
6521
for (;;) {
6490
6522
DWORD len;
6491
6523
ret = GetQueuedCompletionStatus (port, &len, &key,
@@ -6507,25 +6539,26 @@ os_aio_windows_handler(
6507
6539
}
6508
6540
6509
6541
slot->n_bytes = len;
6542
+ ut_a (slot->array );
6543
+ HANDLE slot_port = slot->array ->m_completion_port ;
6544
+ if (slot_port != port) {
6545
+ /* there are no redirections between data and log */
6546
+ ut_ad (port == data_completion_port);
6547
+ ut_ad (slot_port != log_completion_port);
6510
6548
6511
- if (WRITE_SEGMENT (segment) && slot->type .is_read ()) {
6512
6549
/*
6513
- Redirect read completions to the dedicated completion port
6514
- and thread. We need to split read and write threads. If we do not
6515
- do that, and just allow all io threads process all IO, it is possible
6516
- to get stuck in a deadlock in buffer pool code,
6517
-
6518
- Currently, the problem is solved this way - "write io" threads
6519
- always get all completion notifications, from both async reads and
6520
- writes. Write completion is handled in the same thread that gets it.
6521
- Read completion is forwarded via PostQueueCompletionStatus())
6522
- to the second completion port dedicated solely to reads. One of the
6523
- "read io" threads waiting on this port will finally handle the IO.
6524
-
6525
- Forwarding IO completion this way costs a context switch , and this
6526
- seems tolerable since asynchronous reads are by far less frequent.
6550
+ Redirect completions to the dedicated completion port
6551
+ and threads.
6552
+
6553
+ "Write array" threads receive write,read and ibuf
6554
+ notifications, read and ibuf completions are redirected.
6555
+
6556
+ Forwarding IO completion this way costs a context switch,
6557
+ and this seems tolerable since asynchronous reads are by
6558
+ far less frequent.
6527
6559
*/
6528
- ut_a (PostQueuedCompletionStatus (read_completion_port, len, key, &slot->control ));
6560
+ ut_a (PostQueuedCompletionStatus (slot_port,
6561
+ len, key, &slot->control ));
6529
6562
}
6530
6563
else {
6531
6564
break ;
@@ -6586,7 +6619,6 @@ os_aio_windows_handler(
6586
6619
err = AIOHandler::post_io_processing (slot);
6587
6620
}
6588
6621
6589
- ut_a (slot->array );
6590
6622
slot->array ->release_with_mutex (slot);
6591
6623
6592
6624
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS
0 commit comments