- basic data structures
- os_aio_read_array, os_aio_write_array, os_aio_ibuf_array, os_aio_log_array, os_aio_sync_array
152 struct os_aio_array_struct{
153 os_mutex_t mutex; /*!< the mutex protecting the aio array */
154 os_event_t not_full;
155 /*!< The event which is set to the
156 signaled state when there is space in
157 the aio outside the ibuf segment */
158 os_event_t is_empty;
159 /*!< The event which is set to the
160 signaled state when there are no
161 pending i/os in this array */
162 ulint n_slots;/*!< Total number of slots in the aio
163 array. This must be divisible by
164 n_threads. */
165 ulint n_segments;
166 /*!< Number of segments in the aio
167 array of pending aio requests. A
168 thread can wait separately for any one
169 of the segments. */
170 ulint n_reserved;
171 /*!< Number of reserved slots in the
172 aio array outside the ibuf segment */
173 os_aio_slot_t* slots; /*!< Pointer to the slots in the array */
- the procedure
os_aio_init(
3043 ulint n_per_seg, /*<! in: maximum number of pending aio
3044 operations allowed per segment */
3045 ulint n_read_segs, /*<! in: number of reader threads */
3046 ulint n_write_segs, /*<! in: number of writer threads */
3047 ulint n_slots_sync) /*<! in: number of slots in the sync aio
3048 array */
3072 os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
3073 n_read_segs);
so each array contains (SRV_N_PENDING_IOS_PER_THREAD*srv_n_read_io_threads) slots.
os_aio_array_create(
2985 ulint n, /*!< in: maximum number of pending aio operations
2986 allowed; n must be divisible by n_segments */
2987 ulint n_segments) /*!< in: number of segments in the aio array */
2988 {
Malloc memory of the array and initialising the slots, this is the place we want!
[io handler thread for each slot in the array]
1. srv0start.c
/* Create i/o-handler threads: */
1336
1337 for (i = 0; i < srv_n_file_io_threads; i++) {
1338 n[i] = i;
1339
1340 os_thread_create(io_handler_thread, n + i, thread_ids + i);
1341 }
this function os_thread_create created threads as much as srv_n_file_io_threads, which equals to srv_n_read_threads + srv_n_write_threads +2/*log & buf*/
the first parameter io_handler_thread is the call back function and "n + i" is a parameter for io_handler_thread, means the thread will execute io_handler_thread as soon as it's created. n+i=i?Obviously ...
os_thread_create, this is the place we want!
2. srv0start.c
/********************************************************************//**
472 I/o-handler thread function.
473 @return OS_THREAD_DUMMY_RETURN */
474 static
475 os_thread_ret_t
476 io_handler_thread(
477 /*==============*/
478 void* arg) /*!< in: pointer to the number of the segment in
479 the aio array */
480 {
481 ulint segment;
482 ulint i;
483
484 segment = *((ulint*)arg);
485
490 for (i = 0;; i++) {
491 fil_aio_wait(segment);
492
493 mutex_enter(&ios_mutex);
494 ios++;
495 mutex_exit(&ios_mutex);
496 }
497
498 /* We count the number of threads in os_thread_exit(). A created
499 thread should always use that to exit and not use return() to exit.
500 The thread actually never comes here because it is exited in an
501 os_event_wait(). */
502
503 os_thread_exit(NULL);
504
505 OS_THREAD_DUMMY_RETURN;
506 }
segment = n+i = i . e.g. segment range from 0-10 if srv_n_read_threads = srv_n_write_threads = 4.
3. fil0fil.c
/**********************************************************************//**
4400 Waits for an aio operation to complete. This function is used to write the
4401 handler for completed requests. The aio array of pending requests is divided
4402 into segments (see os0file.c for more info). The thread specifies which
4403 segment it wants to wait for. */
4404 UNIV_INTERN
4405 void
4406 fil_aio_wait(
4407 /*=========*/
4408 ulint segment) /*!< in: the number of the segment in the aio
4409 array to wait for */
4410 {
4428 srv_set_io_thread_op_info(segment, "simulated aio handle");
4429
4430 ret = os_aio_simulated_handle(segment, &fil_node,
4431 &message, &type);
4. os0file.c
/**********************************************************************//**
3780 Does simulated aio. This function should be called by an i/o-handler
3781 thread.
3782 @return TRUE if the aio operation succeeded */
3783 UNIV_INTERN
3784 ibool
3785 os_aio_simulated_handle(
3786 /*====================*/
3787 ulint global_segment, /*!< in: the number of the segment in the aio
3788 arrays to wait for; segment 0 is the ibuf
3789 i/o thread, segment 1 the log i/o thread,
3790 then follow the non-ibuf read threads, and as
3791 the last are the non-ibuf write threads */
3792 fil_node_t**message1, /*!< out: the messages passed with the aio
3793 request; note that also in the case where
3794 the aio operation failed, these output
3795 parameters are valid and can be used to
3796 restart the operation, for example */
3797 void** message2,
3798 ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
//get segment in specific array
3817 segment = os_aio_get_array_and_local_segment(&array, global_segment);
4013 /* Do the i/o with ordinary, synchronous i/o functions: */
4014 if (slot->type == OS_FILE_WRITE) {
4015 ret = os_file_write(slot->name, slot->file, combined_buf,
4016 slot->offset, slot->offset_high,
4017 total_len);
4018 } else {
4019 ret = os_file_read(slot->file, combined_buf,
4020 slot->offset, slot->offset_high, total_len);
4021 }
This function does the real i/o and deals many situation:
(1) pick the oldest io request if exists two simultaneously,
(2) pick the nearest io request if two are the same age,
(3) collect the consecutive io and execute them at one time.
Sincerely,
ZHOU Yuan <j0sf>
No comments:
Post a Comment