00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00034 #include "os0file.h"
00035
00036 #ifdef UNIV_NONINL
00037 #include "os0file.ic"
00038 #endif
00039
00040 #include "ut0mem.h"
00041 #include "srv0srv.h"
00042 #include "srv0start.h"
00043 #include "fil0fil.h"
00044 #include "buf0buf.h"
00045 #include <errno.h>
00046 #include <fcntl.h>
00047 #include <limits.h>
00048 #include <unistd.h>
00049 #ifndef UNIV_HOTBACKUP
00050 # include "os0sync.h"
00051 # include "os0thread.h"
00052 #else
00053 # ifdef __WIN__
00054
00055 # include <sys/types.h>
00056 # include <sys/stat.h>
00057 # endif
00058 #endif
00059
00060 #if defined(LINUX_NATIVE_AIO)
00061 #include <libaio.h>
00062 #endif
00063
00064
00065
00066
00067
00068 #ifndef __WIN__
00069
00070 UNIV_INTERN ulint os_innodb_umask
00071 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
00072 #else
00073
00074 UNIV_INTERN ulint os_innodb_umask = 0;
00075 #endif
00076
00077 #ifdef UNIV_DO_FLUSH
00078
00079
00080 UNIV_INTERN ibool os_do_not_call_flush_at_each_write = FALSE;
00081 #else
00082
00083 #endif
00084
00085 #ifndef UNIV_HOTBACKUP
00086
00087
00088 #define OS_FILE_N_SEEK_MUTEXES 16
00089 UNIV_INTERN os_mutex_t os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES];
00090
00091
00092 #define OS_AIO_MERGE_N_CONSECUTIVE 64
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00149 UNIV_INTERN ibool os_aio_print_debug = FALSE;
00150
00151 #ifdef UNIV_PFS_IO
00152
00153 UNIV_INTERN mysql_pfs_key_t innodb_file_data_key;
00154 UNIV_INTERN mysql_pfs_key_t innodb_file_log_key;
00155 UNIV_INTERN mysql_pfs_key_t innodb_file_temp_key;
00156 #endif
00157
00159 typedef struct os_aio_slot_struct os_aio_slot_t;
00160
00162 struct os_aio_slot_struct{
00163 ibool is_read;
00164 ulint pos;
00166 ibool reserved;
00167 time_t reservation_time;
00168 ulint len;
00170 byte* buf;
00171 ulint type;
00172 ulint offset;
00174 ulint offset_high;
00175 os_file_t file;
00176 const char* name;
00177 ibool io_already_done;
00182 fil_node_t* message1;
00183 void* message2;
00187 #ifdef WIN_ASYNC_IO
00188 HANDLE handle;
00190 OVERLAPPED control;
00192 #elif defined(LINUX_NATIVE_AIO)
00193 struct iocb control;
00194 int n_bytes;
00195 int ret;
00196 #endif
00197 };
00198
00200 typedef struct os_aio_array_struct os_aio_array_t;
00201
00203 struct os_aio_array_struct{
00204 os_mutex_t mutex;
00205 os_event_t not_full;
00209 os_event_t is_empty;
00213 ulint n_slots;
00216 ulint n_segments;
00221 ulint cur_seg;
00225 ulint n_reserved;
00228 os_aio_slot_t* slots;
00229 #ifdef __WIN__
00230 HANDLE* handles;
00237 #endif
00238
00239 #if defined(LINUX_NATIVE_AIO)
00240 io_context_t* aio_ctx;
00241
00242
00243
00244 struct io_event* aio_events;
00245
00246
00247
00248
00249 #endif
00250 };
00251
00252 #if defined(LINUX_NATIVE_AIO)
00253
00254 #define OS_AIO_REAP_TIMEOUT (500000000UL)
00255
00257 #define OS_AIO_IO_SETUP_RETRY_SLEEP (500000UL)
00258
00260 #define OS_AIO_IO_SETUP_RETRY_ATTEMPTS 5
00261 #endif
00262
00264 static os_event_t* os_aio_segment_wait_events = NULL;
00265
00268 static os_aio_array_t* os_aio_read_array = NULL;
00269 static os_aio_array_t* os_aio_write_array = NULL;
00270 static os_aio_array_t* os_aio_ibuf_array = NULL;
00271 static os_aio_array_t* os_aio_log_array = NULL;
00272 static os_aio_array_t* os_aio_sync_array = NULL;
00273
00274
00276 static ulint os_aio_n_segments = ULINT_UNDEFINED;
00277
00280 static ibool os_aio_recommend_sleep_for_read_threads = FALSE;
00281 #endif
00282
00283 UNIV_INTERN ulint os_n_file_reads = 0;
00284 UNIV_INTERN ulint os_bytes_read_since_printout = 0;
00285 UNIV_INTERN ulint os_n_file_writes = 0;
00286 UNIV_INTERN ulint os_n_fsyncs = 0;
00287 UNIV_INTERN ulint os_n_file_reads_old = 0;
00288 UNIV_INTERN ulint os_n_file_writes_old = 0;
00289 UNIV_INTERN ulint os_n_fsyncs_old = 0;
00290 UNIV_INTERN time_t os_last_printout;
00291
00292 UNIV_INTERN ibool os_has_said_disk_full = FALSE;
00293
00294 #ifndef UNIV_HOTBACKUP
00295
00296 static os_mutex_t os_file_count_mutex;
00297 #endif
00298
00299 UNIV_INTERN ulint os_file_n_pending_preads = 0;
00301 UNIV_INTERN ulint os_file_n_pending_pwrites = 0;
00303 UNIV_INTERN ulint os_n_pending_writes = 0;
00305 UNIV_INTERN ulint os_n_pending_reads = 0;
00306
00307
00311 UNIV_INTERN
00312 ulint
00313 os_get_os_version(void)
00314
00315 {
00316 #ifdef __WIN__
00317 OSVERSIONINFO os_info;
00318
00319 os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00320
00321 ut_a(GetVersionEx(&os_info));
00322
00323 if (os_info.dwPlatformId == VER_PLATFORM_WIN32s) {
00324 return(OS_WIN31);
00325 } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
00326 return(OS_WIN95);
00327 } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
00328 switch (os_info.dwMajorVersion) {
00329 case 3:
00330 case 4:
00331 return OS_WINNT;
00332 case 5:
00333 return (os_info.dwMinorVersion == 0) ? OS_WIN2000
00334 : OS_WINXP;
00335 case 6:
00336 return (os_info.dwMinorVersion == 0) ? OS_WINVISTA
00337 : OS_WIN7;
00338 default:
00339 return OS_WIN7;
00340 }
00341 } else {
00342 ut_error;
00343 return(0);
00344 }
00345 #else
00346 ut_error;
00347
00348 return(0);
00349 #endif
00350 }
00351
00352
00358 UNIV_INTERN
00359 ulint
00360 os_file_get_last_error(
00361
00362 ibool report_all_errors)
00364 {
00365 ulint err;
00366
00367 #ifdef __WIN__
00368
00369 err = (ulint) GetLastError();
00370
00371 if (report_all_errors
00372 || (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS)) {
00373
00374 ut_print_timestamp(stderr);
00375 fprintf(stderr,
00376 " InnoDB: Operating system error number %lu"
00377 " in a file operation.\n", (ulong) err);
00378
00379 if (err == ERROR_PATH_NOT_FOUND) {
00380 fprintf(stderr,
00381 "InnoDB: The error means the system"
00382 " cannot find the path specified.\n");
00383
00384 if (srv_is_being_started) {
00385 fprintf(stderr,
00386 "InnoDB: If you are installing InnoDB,"
00387 " remember that you must create\n"
00388 "InnoDB: directories yourself, InnoDB"
00389 " does not create them.\n");
00390 }
00391 } else if (err == ERROR_ACCESS_DENIED) {
00392 fprintf(stderr,
00393 "InnoDB: The error means mysqld does not have"
00394 " the access rights to\n"
00395 "InnoDB: the directory. It may also be"
00396 " you have created a subdirectory\n"
00397 "InnoDB: of the same name as a data file.\n");
00398 } else if (err == ERROR_SHARING_VIOLATION
00399 || err == ERROR_LOCK_VIOLATION) {
00400 fprintf(stderr,
00401 "InnoDB: The error means that another program"
00402 " is using InnoDB's files.\n"
00403 "InnoDB: This might be a backup or antivirus"
00404 " software or another instance\n"
00405 "InnoDB: of MySQL."
00406 " Please close it to get rid of this error.\n");
00407 } else if (err == ERROR_WORKING_SET_QUOTA
00408 || err == ERROR_NO_SYSTEM_RESOURCES) {
00409 fprintf(stderr,
00410 "InnoDB: The error means that there are no"
00411 " sufficient system resources or quota to"
00412 " complete the operation.\n");
00413 } else if (err == ERROR_OPERATION_ABORTED) {
00414 fprintf(stderr,
00415 "InnoDB: The error means that the I/O"
00416 " operation has been aborted\n"
00417 "InnoDB: because of either a thread exit"
00418 " or an application request.\n"
00419 "InnoDB: Retry attempt is made.\n");
00420 } else {
00421 fprintf(stderr,
00422 "InnoDB: Some operating system error numbers"
00423 " are described at\n"
00424 "InnoDB: "
00425 REFMAN
00426 "operating-system-error-codes.html\n");
00427 }
00428 }
00429
00430 fflush(stderr);
00431
00432 if (err == ERROR_FILE_NOT_FOUND) {
00433 return(OS_FILE_NOT_FOUND);
00434 } else if (err == ERROR_DISK_FULL) {
00435 return(OS_FILE_DISK_FULL);
00436 } else if (err == ERROR_FILE_EXISTS) {
00437 return(OS_FILE_ALREADY_EXISTS);
00438 } else if (err == ERROR_SHARING_VIOLATION
00439 || err == ERROR_LOCK_VIOLATION) {
00440 return(OS_FILE_SHARING_VIOLATION);
00441 } else if (err == ERROR_WORKING_SET_QUOTA
00442 || err == ERROR_NO_SYSTEM_RESOURCES) {
00443 return(OS_FILE_INSUFFICIENT_RESOURCE);
00444 } else if (err == ERROR_OPERATION_ABORTED) {
00445 return(OS_FILE_OPERATION_ABORTED);
00446 } else {
00447 return(100 + err);
00448 }
00449 #else
00450 err = (ulint) errno;
00451
00452 if (report_all_errors
00453 || (err != ENOSPC && err != EEXIST)) {
00454
00455 ut_print_timestamp(stderr);
00456 fprintf(stderr,
00457 " InnoDB: Operating system error number %lu"
00458 " in a file operation.\n", (ulong) err);
00459
00460 if (err == ENOENT) {
00461 fprintf(stderr,
00462 "InnoDB: The error means the system"
00463 " cannot find the path specified.\n");
00464
00465 if (srv_is_being_started) {
00466 fprintf(stderr,
00467 "InnoDB: If you are installing InnoDB,"
00468 " remember that you must create\n"
00469 "InnoDB: directories yourself, InnoDB"
00470 " does not create them.\n");
00471 }
00472 } else if (err == EACCES) {
00473 fprintf(stderr,
00474 "InnoDB: The error means mysqld does not have"
00475 " the access rights to\n"
00476 "InnoDB: the directory.\n");
00477 } else {
00478 if (strerror((int)err) != NULL) {
00479 fprintf(stderr,
00480 "InnoDB: Error number %lu"
00481 " means '%s'.\n",
00482 err, strerror((int)err));
00483 }
00484
00485 fprintf(stderr,
00486 "InnoDB: Some operating system"
00487 " error numbers are described at\n"
00488 "InnoDB: "
00489 REFMAN
00490 "operating-system-error-codes.html\n");
00491 }
00492 }
00493
00494 fflush(stderr);
00495
00496 switch (err) {
00497 case ENOSPC:
00498 return(OS_FILE_DISK_FULL);
00499 case ENOENT:
00500 return(OS_FILE_NOT_FOUND);
00501 case EEXIST:
00502 return(OS_FILE_ALREADY_EXISTS);
00503 case EXDEV:
00504 case ENOTDIR:
00505 case EISDIR:
00506 return(OS_FILE_PATH_ERROR);
00507 case EAGAIN:
00508 if (srv_use_native_aio) {
00509 return(OS_FILE_AIO_RESOURCES_RESERVED);
00510 }
00511 break;
00512 case EINTR:
00513 if (srv_use_native_aio) {
00514 return(OS_FILE_AIO_INTERRUPTED);
00515 }
00516 break;
00517 }
00518 return(100 + err);
00519 #endif
00520 }
00521
00522
00527 static
00528 ibool
00529 os_file_handle_error_cond_exit(
00530
00531 const char* name,
00532 const char* operation,
00533 ibool should_exit)
00535 {
00536 ulint err;
00537
00538 err = os_file_get_last_error(FALSE);
00539
00540 if (err == OS_FILE_DISK_FULL) {
00541
00542
00543 if (os_has_said_disk_full) {
00544
00545 return(FALSE);
00546 }
00547
00548 if (name) {
00549 ut_print_timestamp(stderr);
00550 fprintf(stderr,
00551 " InnoDB: Encountered a problem with"
00552 " file %s\n", name);
00553 }
00554
00555 ut_print_timestamp(stderr);
00556 fprintf(stderr,
00557 " InnoDB: Disk is full. Try to clean the disk"
00558 " to free space.\n");
00559
00560 os_has_said_disk_full = TRUE;
00561
00562 fflush(stderr);
00563
00564 return(FALSE);
00565 } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
00566
00567 return(TRUE);
00568 } else if (err == OS_FILE_AIO_INTERRUPTED) {
00569
00570 return(TRUE);
00571 } else if (err == OS_FILE_ALREADY_EXISTS
00572 || err == OS_FILE_PATH_ERROR) {
00573
00574 return(FALSE);
00575 } else if (err == OS_FILE_SHARING_VIOLATION) {
00576
00577 os_thread_sleep(10000000);
00578 return(TRUE);
00579 } else if (err == OS_FILE_INSUFFICIENT_RESOURCE) {
00580
00581 os_thread_sleep(100000);
00582 return(TRUE);
00583 } else if (err == OS_FILE_OPERATION_ABORTED) {
00584
00585 os_thread_sleep(100000);
00586 return(TRUE);
00587 } else {
00588 if (name) {
00589 fprintf(stderr, "InnoDB: File name %s\n", name);
00590 }
00591
00592 fprintf(stderr, "InnoDB: File operation call: '%s'.\n",
00593 operation);
00594
00595 if (should_exit) {
00596 fprintf(stderr, "InnoDB: Cannot continue operation.\n");
00597
00598 fflush(stderr);
00599
00600 exit(1);
00601 }
00602 }
00603
00604 return(FALSE);
00605 }
00606
00607
00610 static
00611 ibool
00612 os_file_handle_error(
00613
00614 const char* name,
00615 const char* operation)
00616 {
00617
00618 return(os_file_handle_error_cond_exit(name, operation, TRUE));
00619 }
00620
00621
00624 static
00625 ibool
00626 os_file_handle_error_no_exit(
00627
00628 const char* name,
00629 const char* operation)
00630 {
00631
00632 return(os_file_handle_error_cond_exit(name, operation, FALSE));
00633 }
00634
00635 #undef USE_FILE_LOCK
00636 #define USE_FILE_LOCK
00637 #if defined(UNIV_HOTBACKUP) || defined(__WIN__)
00638
00639
00640
00641 # undef USE_FILE_LOCK
00642 #endif
00643 #ifdef USE_FILE_LOCK
00644
00647 static
00648 int
00649 os_file_lock(
00650
00651 int fd,
00652 const char* name)
00653 {
00654 struct flock lk;
00655
00656 if (srv_read_only)
00657 return 0;
00658
00659 lk.l_type = F_WRLCK;
00660 lk.l_whence = SEEK_SET;
00661 lk.l_start = lk.l_len = 0;
00662 if (fcntl(fd, F_SETLK, &lk) == -1) {
00663 fprintf(stderr,
00664 "InnoDB: Unable to lock %s, error: %d\n", name, errno);
00665
00666 if (errno == EAGAIN || errno == EACCES) {
00667 fprintf(stderr,
00668 "InnoDB: Check that you do not already have"
00669 " another drizzled process\n"
00670 "InnoDB: using the same InnoDB data"
00671 " or log files.\n");
00672 }
00673
00674 return(-1);
00675 }
00676
00677 return(0);
00678 }
00679 #endif
00680
00681 #ifndef UNIV_HOTBACKUP
00682
00684 UNIV_INTERN
00685 void
00686 os_io_init_simple(void)
00687
00688 {
00689 ulint i;
00690
00691 os_file_count_mutex = os_mutex_create();
00692
00693 for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) {
00694 os_file_seek_mutexes[i] = os_mutex_create();
00695 }
00696 }
00697
00698
00702 UNIV_INTERN
00703 FILE*
00704 os_file_create_tmpfile(void)
00705
00706 {
00707 FILE* file = NULL;
00708 int fd = innobase_mysql_tmpfile();
00709
00710 if (fd >= 0) {
00711 file = fdopen(fd, "w+b");
00712 }
00713
00714 if (!file) {
00715 ut_print_timestamp(stderr);
00716 fprintf(stderr,
00717 " InnoDB: Error: unable to create temporary file;"
00718 " errno: %d\n", errno);
00719 if (fd >= 0) {
00720 close(fd);
00721 }
00722 }
00723
00724 return(file);
00725 }
00726 #endif
00727
00728
00734 UNIV_INTERN
00735 os_file_dir_t
00736 os_file_opendir(
00737
00738 const char* dirname,
00740 ibool error_is_fatal)
00745 {
00746 os_file_dir_t dir;
00747 #ifdef __WIN__
00748 LPWIN32_FIND_DATA lpFindFileData;
00749 char path[OS_FILE_MAX_PATH + 3];
00750
00751 ut_a(strlen(dirname) < OS_FILE_MAX_PATH);
00752
00753 strcpy(path, dirname);
00754 strcpy(path + strlen(path), "\\*");
00755
00756
00757
00758
00759
00760 lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
00761
00762 dir = FindFirstFile((LPCTSTR) path, lpFindFileData);
00763
00764 ut_free(lpFindFileData);
00765
00766 if (dir == INVALID_HANDLE_VALUE) {
00767
00768 if (error_is_fatal) {
00769 os_file_handle_error(dirname, "opendir");
00770 }
00771
00772 return(NULL);
00773 }
00774
00775 return(dir);
00776 #else
00777 dir = opendir(dirname);
00778
00779 if (dir == NULL && error_is_fatal) {
00780 os_file_handle_error(dirname, "opendir");
00781 }
00782
00783 return(dir);
00784 #endif
00785 }
00786
00787
00790 UNIV_INTERN
00791 int
00792 os_file_closedir(
00793
00794 os_file_dir_t dir)
00795 {
00796 #ifdef __WIN__
00797 BOOL ret;
00798
00799 ret = FindClose(dir);
00800
00801 if (!ret) {
00802 os_file_handle_error_no_exit(NULL, "closedir");
00803
00804 return(-1);
00805 }
00806
00807 return(0);
00808 #else
00809 int ret;
00810
00811 ret = closedir(dir);
00812
00813 if (ret) {
00814 os_file_handle_error_no_exit(NULL, "closedir");
00815 }
00816
00817 return(ret);
00818 #endif
00819 }
00820
00821
00825 UNIV_INTERN
00826 int
00827 os_file_readdir_next_file(
00828
00829 const char* dirname,
00830 os_file_dir_t dir,
00831 os_file_stat_t* info)
00832 {
00833 #ifdef __WIN__
00834 LPWIN32_FIND_DATA lpFindFileData;
00835 BOOL ret;
00836
00837 lpFindFileData = ut_malloc(sizeof(WIN32_FIND_DATA));
00838 next_file:
00839 ret = FindNextFile(dir, lpFindFileData);
00840
00841 if (ret) {
00842 ut_a(strlen((char *) lpFindFileData->cFileName)
00843 < OS_FILE_MAX_PATH);
00844
00845 if (strcmp((char *) lpFindFileData->cFileName, ".") == 0
00846 || strcmp((char *) lpFindFileData->cFileName, "..") == 0) {
00847
00848 goto next_file;
00849 }
00850
00851 strcpy(info->name, (char *) lpFindFileData->cFileName);
00852
00853 info->size = (ib_int64_t)(lpFindFileData->nFileSizeLow)
00854 + (((ib_int64_t)(lpFindFileData->nFileSizeHigh))
00855 << 32);
00856
00857 if (lpFindFileData->dwFileAttributes
00858 & FILE_ATTRIBUTE_REPARSE_POINT) {
00859
00860
00861
00862
00863
00864 info->type = OS_FILE_TYPE_LINK;
00865 } else if (lpFindFileData->dwFileAttributes
00866 & FILE_ATTRIBUTE_DIRECTORY) {
00867 info->type = OS_FILE_TYPE_DIR;
00868 } else {
00869
00870
00871
00872
00873 info->type = OS_FILE_TYPE_FILE;
00874 }
00875 }
00876
00877 ut_free(lpFindFileData);
00878
00879 if (ret) {
00880 return(0);
00881 } else if (GetLastError() == ERROR_NO_MORE_FILES) {
00882
00883 return(1);
00884 } else {
00885 os_file_handle_error_no_exit(dirname,
00886 "readdir_next_file");
00887 return(-1);
00888 }
00889 #else
00890 struct dirent* ent;
00891 char* full_path;
00892 int ret;
00893 struct stat statinfo;
00894 #ifdef HAVE_READDIR_R
00895 char dirent_buf[sizeof(struct dirent)
00896 + _POSIX_PATH_MAX + 100];
00897
00898
00899
00900 #endif
00901
00902 next_file:
00903
00904 #ifdef HAVE_READDIR_R
00905 ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
00906
00907 if (ret != 0
00908 #ifdef UNIV_AIX
00909
00910
00911
00912
00913 && ent != NULL
00914 #endif
00915 ) {
00916 fprintf(stderr,
00917 "InnoDB: cannot read directory %s, error %lu\n",
00918 dirname, (ulong)ret);
00919
00920 return(-1);
00921 }
00922
00923 if (ent == NULL) {
00924
00925
00926 return(1);
00927 }
00928
00929 ut_a(strlen(ent->d_name) < _POSIX_PATH_MAX + 100 - 1);
00930 #else
00931 ent = readdir(dir);
00932
00933 if (ent == NULL) {
00934
00935 return(1);
00936 }
00937 #endif
00938 ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH);
00939
00940 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
00941
00942 goto next_file;
00943 }
00944
00945 strcpy(info->name, ent->d_name);
00946
00947 full_path = static_cast<char* >(ut_malloc(strlen(dirname) + strlen(ent->d_name) + 10));
00948
00949 sprintf(full_path, "%s/%s", dirname, ent->d_name);
00950
00951 ret = stat(full_path, &statinfo);
00952
00953 if (ret) {
00954
00955 if (errno == ENOENT) {
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 ut_free(full_path);
00967
00968 goto next_file;
00969 }
00970
00971 os_file_handle_error_no_exit(full_path, "stat");
00972
00973 ut_free(full_path);
00974
00975 return(-1);
00976 }
00977
00978 info->size = (ib_int64_t)statinfo.st_size;
00979
00980 if (S_ISDIR(statinfo.st_mode)) {
00981 info->type = OS_FILE_TYPE_DIR;
00982 } else if (S_ISLNK(statinfo.st_mode)) {
00983 info->type = OS_FILE_TYPE_LINK;
00984 } else if (S_ISREG(statinfo.st_mode)) {
00985 info->type = OS_FILE_TYPE_FILE;
00986 } else {
00987 info->type = OS_FILE_TYPE_UNKNOWN;
00988 }
00989
00990 ut_free(full_path);
00991
00992 return(0);
00993 #endif
00994 }
00995
00996
01002 UNIV_INTERN
01003 ibool
01004 os_file_create_directory(
01005
01006 const char* pathname,
01008 ibool fail_if_exists)
01010 {
01011 #ifdef __WIN__
01012 BOOL rcode;
01013
01014 rcode = CreateDirectory((LPCTSTR) pathname, NULL);
01015 if (!(rcode != 0
01016 || (GetLastError() == ERROR_ALREADY_EXISTS
01017 && !fail_if_exists))) {
01018
01019 os_file_handle_error(pathname, "CreateDirectory");
01020
01021 return(FALSE);
01022 }
01023
01024 return (TRUE);
01025 #else
01026 int rcode;
01027
01028 rcode = mkdir(pathname, 0770);
01029
01030 if (!(rcode == 0 || (errno == EEXIST && !fail_if_exists))) {
01031
01032 os_file_handle_error(pathname, "mkdir");
01033
01034 return(FALSE);
01035 }
01036
01037 return (TRUE);
01038 #endif
01039 }
01040
01041
01047 UNIV_INTERN
01048 os_file_t
01049 os_file_create_simple_func(
01050
01051 const char* name,
01053 ulint create_mode,
01060 ulint access_type,
01062 ibool* success)
01063 {
01064 #ifdef __WIN__
01065 os_file_t file;
01066 DWORD create_flag;
01067 DWORD access;
01068 DWORD attributes = 0;
01069 ibool retry;
01070
01071 try_again:
01072 ut_a(name);
01073
01074 if (create_mode == OS_FILE_OPEN) {
01075 create_flag = OPEN_EXISTING;
01076 } else if (create_mode == OS_FILE_CREATE) {
01077 create_flag = CREATE_NEW;
01078 } else if (create_mode == OS_FILE_CREATE_PATH) {
01079
01080 *success = os_file_create_subdirs_if_needed(name);
01081 if (!*success) {
01082 ut_error;
01083 }
01084 create_flag = CREATE_NEW;
01085 create_mode = OS_FILE_CREATE;
01086 } else {
01087 create_flag = 0;
01088 ut_error;
01089 }
01090
01091 if (access_type == OS_FILE_READ_ONLY) {
01092 access = GENERIC_READ;
01093 } else if (access_type == OS_FILE_READ_WRITE) {
01094 access = GENERIC_READ | GENERIC_WRITE;
01095 } else {
01096 access = 0;
01097 ut_error;
01098 }
01099
01100 file = CreateFile((LPCTSTR) name,
01101 access,
01102 FILE_SHARE_READ | FILE_SHARE_WRITE,
01103
01104
01105 NULL,
01106 create_flag,
01107 attributes,
01108 NULL);
01110 if (file == INVALID_HANDLE_VALUE) {
01111 *success = FALSE;
01112
01113 retry = os_file_handle_error(name,
01114 create_mode == OS_FILE_OPEN ?
01115 "open" : "create");
01116 if (retry) {
01117 goto try_again;
01118 }
01119 } else {
01120 *success = TRUE;
01121 }
01122
01123 return(file);
01124 #else
01125 os_file_t file;
01126 int create_flag;
01127 ibool retry;
01128
01129 try_again:
01130 ut_a(name);
01131
01132 if (create_mode == OS_FILE_OPEN) {
01133 if (access_type == OS_FILE_READ_ONLY) {
01134 create_flag = O_RDONLY;
01135 } else {
01136 create_flag = O_RDWR;
01137 }
01138 } else if (create_mode == OS_FILE_CREATE) {
01139 create_flag = O_RDWR | O_CREAT | O_EXCL;
01140 } else if (create_mode == OS_FILE_CREATE_PATH) {
01141
01142 *success = os_file_create_subdirs_if_needed(name);
01143 if (!*success) {
01144 return (-1);
01145 }
01146 create_flag = O_RDWR | O_CREAT | O_EXCL;
01147 create_mode = OS_FILE_CREATE;
01148 } else {
01149 create_flag = 0;
01150 ut_error;
01151 }
01152
01153 if (create_mode == OS_FILE_CREATE) {
01154 file = open(name, create_flag, S_IRUSR | S_IWUSR
01155 | S_IRGRP | S_IWGRP);
01156 } else {
01157 file = open(name, create_flag);
01158 }
01159
01160 if (file == -1) {
01161 *success = FALSE;
01162
01163 retry = os_file_handle_error(name,
01164 create_mode == OS_FILE_OPEN ?
01165 "open" : "create");
01166 if (retry) {
01167 goto try_again;
01168 }
01169 #ifdef USE_FILE_LOCK
01170 } else if (access_type == OS_FILE_READ_WRITE
01171 && os_file_lock(file, name)) {
01172 *success = FALSE;
01173 close(file);
01174 file = -1;
01175 #endif
01176 } else {
01177 *success = TRUE;
01178 }
01179
01180 return(file);
01181 #endif
01182 }
01183
01184
01190 UNIV_INTERN
01191 os_file_t
01192 os_file_create_simple_no_error_handling_func(
01193
01194 const char* name,
01196 ulint create_mode,
01200 ulint access_type,
01204 ibool* success)
01205 {
01206 #ifdef __WIN__
01207 os_file_t file;
01208 DWORD create_flag;
01209 DWORD access;
01210 DWORD attributes = 0;
01211 DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
01212
01213 ut_a(name);
01214
01215 if (create_mode == OS_FILE_OPEN) {
01216 create_flag = OPEN_EXISTING;
01217 } else if (create_mode == OS_FILE_CREATE) {
01218 create_flag = CREATE_NEW;
01219 } else {
01220 create_flag = 0;
01221 ut_error;
01222 }
01223
01224 if (access_type == OS_FILE_READ_ONLY) {
01225 access = GENERIC_READ;
01226 } else if (access_type == OS_FILE_READ_WRITE) {
01227 access = GENERIC_READ | GENERIC_WRITE;
01228 } else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
01229 access = GENERIC_READ;
01230 share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ
01231 | FILE_SHARE_WRITE;
01235 } else {
01236 access = 0;
01237 ut_error;
01238 }
01239
01240 file = CreateFile((LPCTSTR) name,
01241 access,
01242 share_mode,
01243 NULL,
01244 create_flag,
01245 attributes,
01246 NULL);
01248 if (file == INVALID_HANDLE_VALUE) {
01249 *success = FALSE;
01250 } else {
01251 *success = TRUE;
01252 }
01253
01254 return(file);
01255 #else
01256 os_file_t file;
01257 int create_flag;
01258
01259 ut_a(name);
01260
01261 if (create_mode == OS_FILE_OPEN) {
01262 if (access_type == OS_FILE_READ_ONLY) {
01263 create_flag = O_RDONLY;
01264 } else {
01265 create_flag = O_RDWR;
01266 }
01267 } else if (create_mode == OS_FILE_CREATE) {
01268 create_flag = O_RDWR | O_CREAT | O_EXCL;
01269 } else {
01270 create_flag = 0;
01271 ut_error;
01272 }
01273
01274 if (create_mode == OS_FILE_CREATE) {
01275 file = open(name, create_flag, S_IRUSR | S_IWUSR
01276 | S_IRGRP | S_IWGRP);
01277 } else {
01278 file = open(name, create_flag);
01279 }
01280
01281 if (file == -1) {
01282 *success = FALSE;
01283 #ifdef USE_FILE_LOCK
01284 } else if (access_type == OS_FILE_READ_WRITE
01285 && os_file_lock(file, name)) {
01286 *success = FALSE;
01287 close(file);
01288 file = -1;
01289 #endif
01290 } else {
01291 *success = TRUE;
01292 }
01293
01294 return(file);
01295 #endif
01296 }
01297
01298
01300 UNIV_INTERN
01301 void
01302 os_file_set_nocache(
01303
01304 int fd,
01305 const char* file_name,
01306 const char* operation_name)
01309 {
01310
01311 #if defined(UNIV_SOLARIS) && defined(DIRECTIO_ON)
01312 if (directio(fd, DIRECTIO_ON) == -1) {
01313 int errno_save;
01314 errno_save = (int)errno;
01315 ut_print_timestamp(stderr);
01316 fprintf(stderr,
01317 " InnoDB: Failed to set DIRECTIO_ON "
01318 "on file %s: %s: %s, continuing anyway\n",
01319 file_name, operation_name, strerror(errno_save));
01320 }
01321 #elif defined(O_DIRECT)
01322 if (fcntl(fd, F_SETFL, O_DIRECT) == -1) {
01323 int errno_save;
01324 errno_save = (int)errno;
01325 ut_print_timestamp(stderr);
01326 fprintf(stderr,
01327 " InnoDB: Failed to set O_DIRECT "
01328 "on file %s: %s: %s, continuing anyway\n",
01329 file_name, operation_name, strerror(errno_save));
01330 if (errno_save == EINVAL) {
01331 ut_print_timestamp(stderr);
01332 fprintf(stderr,
01333 " InnoDB: O_DIRECT is known to result in "
01334 "'Invalid argument' on Linux on tmpfs, "
01335 "see MySQL Bug#26662\n");
01336 }
01337 }
01338 #else
01339 (void)fd;
01340 (void)file_name;
01341 (void)operation_name;
01342 #endif
01343 }
01344
01345
01351 UNIV_INTERN
01352 os_file_t
01353 os_file_create_func(
01354
01355 const char* name,
01357 ulint create_mode,
01365 ulint purpose,
01372 ulint type,
01373 ibool* success)
01374 {
01375 #ifdef __WIN__
01376 os_file_t file;
01377 DWORD share_mode = FILE_SHARE_READ;
01378 DWORD create_flag;
01379 DWORD attributes;
01380 ibool retry;
01381 try_again:
01382 ut_a(name);
01383
01384 if (create_mode == OS_FILE_OPEN_RAW) {
01385 create_flag = OPEN_EXISTING;
01386 share_mode = FILE_SHARE_WRITE;
01387 } else if (create_mode == OS_FILE_OPEN
01388 || create_mode == OS_FILE_OPEN_RETRY) {
01389 create_flag = OPEN_EXISTING;
01390 } else if (create_mode == OS_FILE_CREATE) {
01391 create_flag = CREATE_NEW;
01392 } else if (create_mode == OS_FILE_OVERWRITE) {
01393 create_flag = CREATE_ALWAYS;
01394 } else {
01395 create_flag = 0;
01396 ut_error;
01397 }
01398
01399 if (purpose == OS_FILE_AIO) {
01400
01401
01402 attributes = 0;
01403 #ifdef WIN_ASYNC_IO
01404 if (srv_use_native_aio) {
01405 attributes = attributes | FILE_FLAG_OVERLAPPED;
01406 }
01407 #endif
01408 #ifdef UNIV_NON_BUFFERED_IO
01409 # ifndef UNIV_HOTBACKUP
01410 if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
01411
01412
01413
01414 } else if (srv_win_file_flush_method
01415 == SRV_WIN_IO_UNBUFFERED) {
01416 attributes = attributes | FILE_FLAG_NO_BUFFERING;
01417 }
01418 # else
01419 attributes = attributes | FILE_FLAG_NO_BUFFERING;
01420 # endif
01421 #endif
01422 } else if (purpose == OS_FILE_NORMAL) {
01423 attributes = 0;
01424 #ifdef UNIV_NON_BUFFERED_IO
01425 # ifndef UNIV_HOTBACKUP
01426 if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
01427
01428
01429
01430 } else if (srv_win_file_flush_method
01431 == SRV_WIN_IO_UNBUFFERED) {
01432 attributes = attributes | FILE_FLAG_NO_BUFFERING;
01433 }
01434 # else
01435 attributes = attributes | FILE_FLAG_NO_BUFFERING;
01436 # endif
01437 #endif
01438 } else {
01439 attributes = 0;
01440 ut_error;
01441 }
01442
01443 file = CreateFile((LPCTSTR) name,
01444 GENERIC_READ | GENERIC_WRITE,
01445
01446 share_mode,
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457 NULL,
01458 create_flag,
01459 attributes,
01460 NULL);
01462 if (file == INVALID_HANDLE_VALUE) {
01463 *success = FALSE;
01464
01465
01466
01467
01468
01469
01470
01471
01472 if (srv_file_per_table) {
01473 retry = os_file_handle_error_no_exit(name,
01474 create_mode == OS_FILE_CREATE ?
01475 "create" : "open");
01476 } else {
01477 retry = os_file_handle_error(name,
01478 create_mode == OS_FILE_CREATE ?
01479 "create" : "open");
01480 }
01481
01482 if (retry) {
01483 goto try_again;
01484 }
01485 } else {
01486 *success = TRUE;
01487 }
01488
01489 return(file);
01490 #else
01491 os_file_t file;
01492 int create_flag;
01493 ibool retry;
01494 const char* mode_str = NULL;
01495
01496 try_again:
01497 ut_a(name);
01498
01499 if (create_mode == OS_FILE_OPEN || create_mode == OS_FILE_OPEN_RAW
01500 || create_mode == OS_FILE_OPEN_RETRY) {
01501 mode_str = "OPEN";
01502 if (srv_read_only)
01503 create_flag = O_RDONLY;
01504 else
01505 create_flag = O_RDWR;
01506 } else if (create_mode == OS_FILE_CREATE) {
01507 mode_str = "CREATE";
01508 create_flag = O_RDWR | O_CREAT | O_EXCL;
01509 } else if (create_mode == OS_FILE_OVERWRITE) {
01510 mode_str = "OVERWRITE";
01511 create_flag = O_RDWR | O_CREAT | O_TRUNC;
01512 } else {
01513 create_flag = 0;
01514 ut_error;
01515 }
01516
01517 ut_a(type == OS_LOG_FILE || type == OS_DATA_FILE);
01518 ut_a(purpose == OS_FILE_AIO || purpose == OS_FILE_NORMAL);
01519
01520 #ifdef O_SYNC
01521
01522
01523
01524 if (type == OS_LOG_FILE
01525 && srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
01526
01527 # if 0
01528 fprintf(stderr, "Using O_SYNC for file %s\n", name);
01529 # endif
01530
01531 create_flag = create_flag | O_SYNC;
01532 }
01533 #endif
01534
01535 file = open(name, create_flag, os_innodb_umask);
01536
01537 if (file == -1) {
01538 *success = FALSE;
01539
01540
01541
01542
01543
01544
01545
01546
01547 if (srv_file_per_table) {
01548 retry = os_file_handle_error_no_exit(name,
01549 create_mode == OS_FILE_CREATE ?
01550 "create" : "open");
01551 } else {
01552 retry = os_file_handle_error(name,
01553 create_mode == OS_FILE_CREATE ?
01554 "create" : "open");
01555 }
01556
01557 if (retry) {
01558 goto try_again;
01559 } else {
01560 return(file );
01561 }
01562 }
01563
01564
01565 *success = TRUE;
01566
01567
01568 if (type != OS_LOG_FILE
01569 && srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) {
01570
01571 os_file_set_nocache(file, name, mode_str);
01572 }
01573
01574
01575 if (srv_unix_file_flush_method == SRV_UNIX_ALL_O_DIRECT) {
01576 os_file_set_nocache(file, name, mode_str);
01577 }
01578
01579 #ifdef USE_FILE_LOCK
01580 if (create_mode != OS_FILE_OPEN_RAW && os_file_lock(file, name)) {
01581
01582 if (create_mode == OS_FILE_OPEN_RETRY) {
01583 int i;
01584 ut_print_timestamp(stderr);
01585 fputs(" InnoDB: Retrying to lock"
01586 " the first data file\n",
01587 stderr);
01588 for (i = 0; i < 100; i++) {
01589 os_thread_sleep(1000000);
01590 if (!os_file_lock(file, name)) {
01591 *success = TRUE;
01592 return(file);
01593 }
01594 }
01595 ut_print_timestamp(stderr);
01596 fputs(" InnoDB: Unable to open the first data file\n",
01597 stderr);
01598 }
01599
01600 *success = FALSE;
01601 close(file);
01602 file = -1;
01603 }
01604 #endif
01605
01606 return(file);
01607 #endif
01608 }
01609
01610
01613 UNIV_INTERN
01614 ibool
01615 os_file_delete_if_exists(
01616
01617 const char* name)
01618 {
01619 #ifdef __WIN__
01620 BOOL ret;
01621 ulint count = 0;
01622 loop:
01623
01624
01625
01626 ret = DeleteFile((LPCTSTR)name);
01627
01628 if (ret) {
01629 return(TRUE);
01630 }
01631
01632 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
01633
01634
01635 return(TRUE);
01636 }
01637
01638 count++;
01639
01640 if (count > 100 && 0 == (count % 10)) {
01641 fprintf(stderr,
01642 "InnoDB: Warning: cannot delete file %s\n"
01643 "InnoDB: Are you running ibbackup"
01644 " to back up the file?\n", name);
01645
01646 os_file_get_last_error(TRUE);
01647 }
01648
01649 os_thread_sleep(1000000);
01650
01651 if (count > 2000) {
01652
01653 return(FALSE);
01654 }
01655
01656 goto loop;
01657 #else
01658 int ret;
01659
01660 ret = unlink(name);
01661
01662 if (ret != 0 && errno != ENOENT) {
01663 os_file_handle_error_no_exit(name, "delete");
01664
01665 return(FALSE);
01666 }
01667
01668 return(TRUE);
01669 #endif
01670 }
01671
01672
01675 UNIV_INTERN
01676 ibool
01677 os_file_delete(
01678
01679 const char* name)
01680 {
01681 #ifdef __WIN__
01682 BOOL ret;
01683 ulint count = 0;
01684 loop:
01685
01686
01687
01688 ret = DeleteFile((LPCTSTR)name);
01689
01690 if (ret) {
01691 return(TRUE);
01692 }
01693
01694 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
01695
01696
01697
01698 return(FALSE);
01699 }
01700
01701 count++;
01702
01703 if (count > 100 && 0 == (count % 10)) {
01704 fprintf(stderr,
01705 "InnoDB: Warning: cannot delete file %s\n"
01706 "InnoDB: Are you running ibbackup"
01707 " to back up the file?\n", name);
01708
01709 os_file_get_last_error(TRUE);
01710 }
01711
01712 os_thread_sleep(1000000);
01713
01714 if (count > 2000) {
01715
01716 return(FALSE);
01717 }
01718
01719 goto loop;
01720 #else
01721 int ret;
01722
01723 ret = unlink(name);
01724
01725 if (ret != 0) {
01726 os_file_handle_error_no_exit(name, "delete");
01727
01728 return(FALSE);
01729 }
01730
01731 return(TRUE);
01732 #endif
01733 }
01734
01735
01740 UNIV_INTERN
01741 ibool
01742 os_file_rename_func(
01743
01744 const char* oldpath,
01746 const char* newpath)
01747 {
01748 #ifdef __WIN__
01749 BOOL ret;
01750
01751 ret = MoveFile((LPCTSTR)oldpath, (LPCTSTR)newpath);
01752
01753 if (ret) {
01754 return(TRUE);
01755 }
01756
01757 os_file_handle_error_no_exit(oldpath, "rename");
01758
01759 return(FALSE);
01760 #else
01761 int ret;
01762
01763 ret = rename(oldpath, newpath);
01764
01765 if (ret != 0) {
01766 os_file_handle_error_no_exit(oldpath, "rename");
01767
01768 return(FALSE);
01769 }
01770
01771 return(TRUE);
01772 #endif
01773 }
01774
01775
01780 UNIV_INTERN
01781 ibool
01782 os_file_close_func(
01783
01784 os_file_t file)
01785 {
01786 #ifdef __WIN__
01787 BOOL ret;
01788
01789 ut_a(file);
01790
01791 ret = CloseHandle(file);
01792
01793 if (ret) {
01794 return(TRUE);
01795 }
01796
01797 os_file_handle_error(NULL, "close");
01798
01799 return(FALSE);
01800 #else
01801 int ret;
01802
01803 ret = close(file);
01804
01805 if (ret == -1) {
01806 os_file_handle_error(NULL, "close");
01807
01808 return(FALSE);
01809 }
01810
01811 return(TRUE);
01812 #endif
01813 }
01814
01815 #ifdef UNIV_HOTBACKUP
01816
01819 UNIV_INTERN
01820 ibool
01821 os_file_close_no_error_handling(
01822
01823 os_file_t file)
01824 {
01825 #ifdef __WIN__
01826 BOOL ret;
01827
01828 ut_a(file);
01829
01830 ret = CloseHandle(file);
01831
01832 if (ret) {
01833 return(TRUE);
01834 }
01835
01836 return(FALSE);
01837 #else
01838 int ret;
01839
01840 ret = close(file);
01841
01842 if (ret == -1) {
01843
01844 return(FALSE);
01845 }
01846
01847 return(TRUE);
01848 #endif
01849 }
01850 #endif
01851
01852
01855 UNIV_INTERN
01856 ibool
01857 os_file_get_size(
01858
01859 os_file_t file,
01860 ulint* size,
01862 ulint* size_high)
01863 {
01864 #ifdef __WIN__
01865 DWORD high;
01866 DWORD low;
01867
01868 low = GetFileSize(file, &high);
01869
01870 if ((low == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) {
01871 return(FALSE);
01872 }
01873
01874 *size = low;
01875 *size_high = high;
01876
01877 return(TRUE);
01878 #else
01879 off_t offs;
01880
01881 offs = lseek(file, 0, SEEK_END);
01882
01883 if (offs == ((off_t)-1)) {
01884
01885 return(FALSE);
01886 }
01887
01888 if (sizeof(off_t) > 4) {
01889 *size = (ulint)(offs & 0xFFFFFFFFUL);
01890 *size_high = (ulint)(offs >> 32);
01891 } else {
01892 *size = (ulint) offs;
01893 *size_high = 0;
01894 }
01895
01896 return(TRUE);
01897 #endif
01898 }
01899
01900
01903 UNIV_INTERN
01904 ib_int64_t
01905 os_file_get_size_as_iblonglong(
01906
01907 os_file_t file)
01908 {
01909 ulint size;
01910 ulint size_high;
01911 ibool success;
01912
01913 success = os_file_get_size(file, &size, &size_high);
01914
01915 if (!success) {
01916
01917 return(-1);
01918 }
01919
01920 return((((ib_int64_t)size_high) << 32) + (ib_int64_t)size);
01921 }
01922
01923
01926 UNIV_INTERN
01927 ibool
01928 os_file_set_size(
01929
01930 const char* name,
01932 os_file_t file,
01933 ulint size,
01935 ulint size_high)
01936 {
01937 ib_int64_t current_size;
01938 ib_int64_t desired_size;
01939 ibool ret;
01940 byte* buf;
01941 byte* buf2;
01942 ulint buf_size;
01943
01944 ut_a(size == (size & 0xFFFFFFFF));
01945
01946 current_size = 0;
01947 desired_size = (ib_int64_t)size + (((ib_int64_t)size_high) << 32);
01948
01949
01950 buf_size = ut_min(64, (ulint) (desired_size / UNIV_PAGE_SIZE))
01951 * UNIV_PAGE_SIZE;
01952 buf2 = static_cast<unsigned char *>(ut_malloc(buf_size + UNIV_PAGE_SIZE));
01953
01954
01955 buf = static_cast<unsigned char *>(ut_align(buf2, UNIV_PAGE_SIZE));
01956
01957
01958 memset(buf, 0, buf_size);
01959
01960 if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) {
01961
01962 fprintf(stderr, "InnoDB: Progress in MB:");
01963 }
01964
01965 while (current_size < desired_size) {
01966 ulint n_bytes;
01967
01968 if (desired_size - current_size < (ib_int64_t) buf_size) {
01969 n_bytes = (ulint) (desired_size - current_size);
01970 } else {
01971 n_bytes = buf_size;
01972 }
01973
01974 ret = os_file_write(name, file, buf,
01975 (ulint)(current_size & 0xFFFFFFFF),
01976 (ulint)(current_size >> 32),
01977 n_bytes);
01978 if (!ret) {
01979 ut_free(buf2);
01980 goto error_handling;
01981 }
01982
01983
01984 if ((ib_int64_t) (current_size + n_bytes) / (ib_int64_t)(100 * 1024 * 1024)
01985 != current_size / (ib_int64_t)(100 * 1024 * 1024)) {
01986
01987 fprintf(stderr, " %lu00",
01988 (ulong) ((current_size + n_bytes)
01989 / (ib_int64_t)(100 * 1024 * 1024)));
01990 }
01991
01992 current_size += n_bytes;
01993 }
01994
01995 if (desired_size >= (ib_int64_t)(100 * 1024 * 1024)) {
01996
01997 fprintf(stderr, "\n");
01998 }
01999
02000 ut_free(buf2);
02001
02002 ret = os_file_flush(file);
02003
02004 if (ret) {
02005 return(TRUE);
02006 }
02007
02008 error_handling:
02009 return(FALSE);
02010 }
02011
02012
02015 UNIV_INTERN
02016 ibool
02017 os_file_set_eof(
02018
02019 FILE* file)
02020 {
02021 #ifdef __WIN__
02022 HANDLE h = (HANDLE) _get_osfhandle(fileno(file));
02023 return(SetEndOfFile(h));
02024 #else
02025 return(!ftruncate(fileno(file), ftell(file)));
02026 #endif
02027 }
02028
02029 #ifndef __WIN__
02030
02036 static
02037 int
02038 os_file_fsync(
02039
02040 os_file_t file)
02041 {
02042 int ret;
02043 int failures;
02044 ibool retry;
02045
02046 failures = 0;
02047
02048 do {
02049 ret = fsync(file);
02050
02051 os_n_fsyncs++;
02052
02053 if (ret == -1 && errno == ENOLCK) {
02054
02055 if (failures % 100 == 0) {
02056
02057 ut_print_timestamp(stderr);
02058 fprintf(stderr,
02059 " InnoDB: fsync(): "
02060 "No locks available; retrying\n");
02061 }
02062
02063 os_thread_sleep(200000 );
02064
02065 failures++;
02066
02067 retry = TRUE;
02068 } else {
02069
02070 retry = FALSE;
02071 }
02072 } while (retry);
02073
02074 return(ret);
02075 }
02076 #endif
02077
02078
02082 UNIV_INTERN
02083 ibool
02084 os_file_flush_func(
02085
02086 os_file_t file)
02087 {
02088 #ifdef __WIN__
02089 BOOL ret;
02090
02091 ut_a(file);
02092
02093 os_n_fsyncs++;
02094
02095 ret = FlushFileBuffers(file);
02096
02097 if (ret) {
02098 return(TRUE);
02099 }
02100
02101
02102
02103
02104
02105 if (srv_start_raw_disk_in_use && GetLastError()
02106 == ERROR_INVALID_FUNCTION) {
02107 return(TRUE);
02108 }
02109
02110 os_file_handle_error(NULL, "flush");
02111
02112
02113
02114 ut_error;
02115
02116 return(FALSE);
02117 #else
02118 int ret;
02119
02120 #if defined(HAVE_DARWIN_THREADS)
02121 # ifndef F_FULLFSYNC
02122
02123 # define F_FULLFSYNC 51
02124 # elif F_FULLFSYNC != 51
02125 # error "F_FULLFSYNC != 51: ABI incompatibility with Mac OS X 10.3"
02126 # endif
02127
02128
02129
02130
02131
02132 if (!srv_have_fullfsync) {
02133
02134
02135
02136 ret = os_file_fsync(file);
02137 } else {
02138 ret = fcntl(file, F_FULLFSYNC, NULL);
02139
02140 if (ret) {
02141
02142
02143 ret = os_file_fsync(file);
02144 }
02145 }
02146 #else
02147 ret = os_file_fsync(file);
02148 #endif
02149
02150 if (ret == 0) {
02151 return(TRUE);
02152 }
02153
02154
02155
02156
02157 if (srv_start_raw_disk_in_use && errno == EINVAL) {
02158
02159 return(TRUE);
02160 }
02161
02162 ut_print_timestamp(stderr);
02163
02164 fprintf(stderr,
02165 " InnoDB: Error: the OS said file flush did not succeed\n");
02166
02167 os_file_handle_error(NULL, "flush");
02168
02169
02170
02171 ut_error;
02172
02173 return(FALSE);
02174 #endif
02175 }
02176
02177 #ifndef __WIN__
02178
02181 static
02182 ssize_t
02183 os_file_pread(
02184
02185 os_file_t file,
02186 void* buf,
02187 ulint n,
02188 ulint offset,
02190 ulint offset_high)
02192 {
02193 off_t offs;
02194 #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
02195 ssize_t n_bytes;
02196 #endif
02197
02198 ut_a((offset & 0xFFFFFFFFUL) == offset);
02199
02200
02201
02202
02203 if (sizeof(off_t) > 4) {
02204 offs = (off_t)offset + (((off_t)offset_high) << 32);
02205
02206 } else {
02207 offs = (off_t)offset;
02208
02209 if (offset_high > 0) {
02210 fprintf(stderr,
02211 "InnoDB: Error: file read at offset > 4 GB\n");
02212 }
02213 }
02214
02215 os_n_file_reads++;
02216
02217 #if defined(HAVE_PREAD) && !defined(HAVE_BROKEN_PREAD)
02218 os_mutex_enter(os_file_count_mutex);
02219 os_file_n_pending_preads++;
02220 os_n_pending_reads++;
02221 os_mutex_exit(os_file_count_mutex);
02222
02223 n_bytes = pread(file, buf, (ssize_t)n, offs);
02224
02225 os_mutex_enter(os_file_count_mutex);
02226 os_file_n_pending_preads--;
02227 os_n_pending_reads--;
02228 os_mutex_exit(os_file_count_mutex);
02229
02230 return(n_bytes);
02231 #else
02232 {
02233 off_t ret_offset;
02234 ssize_t ret;
02235 #ifndef UNIV_HOTBACKUP
02236 ulint i;
02237 #endif
02238
02239 os_mutex_enter(os_file_count_mutex);
02240 os_n_pending_reads++;
02241 os_mutex_exit(os_file_count_mutex);
02242
02243 #ifndef UNIV_HOTBACKUP
02244
02245 i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
02246
02247 os_mutex_enter(os_file_seek_mutexes[i]);
02248 #endif
02249
02250 ret_offset = lseek(file, offs, SEEK_SET);
02251
02252 if (ret_offset < 0) {
02253 ret = -1;
02254 } else {
02255 ret = read(file, buf, (ssize_t)n);
02256 }
02257
02258 #ifndef UNIV_HOTBACKUP
02259 os_mutex_exit(os_file_seek_mutexes[i]);
02260 #endif
02261
02262 os_mutex_enter(os_file_count_mutex);
02263 os_n_pending_reads--;
02264 os_mutex_exit(os_file_count_mutex);
02265
02266 return(ret);
02267 }
02268 #endif
02269 }
02270
02271
02274 static
02275 ssize_t
02276 os_file_pwrite(
02277
02278 os_file_t file,
02279 const void* buf,
02280 ulint n,
02281 ulint offset,
02283 ulint offset_high)
02285 {
02286 ssize_t ret;
02287 off_t offs;
02288
02289 ut_a((offset & 0xFFFFFFFFUL) == offset);
02290
02291
02292
02293
02294 if (sizeof(off_t) > 4) {
02295 offs = (off_t)offset + (((off_t)offset_high) << 32);
02296 } else {
02297 offs = (off_t)offset;
02298
02299 if (offset_high > 0) {
02300 fprintf(stderr,
02301 "InnoDB: Error: file write"
02302 " at offset > 4 GB\n");
02303 }
02304 }
02305
02306 if (srv_fake_write)
02307 return(TRUE);
02308
02309 os_n_file_writes++;
02310
02311 #if defined(HAVE_PWRITE) && !defined(HAVE_BROKEN_PREAD)
02312 os_mutex_enter(os_file_count_mutex);
02313 os_file_n_pending_pwrites++;
02314 os_n_pending_writes++;
02315 os_mutex_exit(os_file_count_mutex);
02316
02317 ret = pwrite(file, buf, (ssize_t)n, offs);
02318
02319 os_mutex_enter(os_file_count_mutex);
02320 os_file_n_pending_pwrites--;
02321 os_n_pending_writes--;
02322 os_mutex_exit(os_file_count_mutex);
02323
02324 # ifdef UNIV_DO_FLUSH
02325 if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
02326 && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
02327 && !os_do_not_call_flush_at_each_write) {
02328
02329
02330
02331
02332
02333 ut_a(TRUE == os_file_flush(file));
02334 }
02335 # endif
02336
02337 return(ret);
02338 #else
02339 {
02340 off_t ret_offset;
02341 # ifndef UNIV_HOTBACKUP
02342 ulint i;
02343 # endif
02344
02345 os_mutex_enter(os_file_count_mutex);
02346 os_n_pending_writes++;
02347 os_mutex_exit(os_file_count_mutex);
02348
02349 # ifndef UNIV_HOTBACKUP
02350
02351 i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
02352
02353 os_mutex_enter(os_file_seek_mutexes[i]);
02354 # endif
02355
02356 ret_offset = lseek(file, offs, SEEK_SET);
02357
02358 if (ret_offset < 0) {
02359 ret = -1;
02360
02361 goto func_exit;
02362 }
02363
02364 ret = write(file, buf, (ssize_t)n);
02365
02366 # ifdef UNIV_DO_FLUSH
02367 if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC
02368 && srv_unix_file_flush_method != SRV_UNIX_NOSYNC
02369 && !os_do_not_call_flush_at_each_write) {
02370
02371
02372
02373
02374
02375 ut_a(TRUE == os_file_flush(file));
02376 }
02377 # endif
02378
02379 func_exit:
02380 # ifndef UNIV_HOTBACKUP
02381 os_mutex_exit(os_file_seek_mutexes[i]);
02382 # endif
02383
02384 os_mutex_enter(os_file_count_mutex);
02385 os_n_pending_writes--;
02386 os_mutex_exit(os_file_count_mutex);
02387
02388 return(ret);
02389 }
02390 #endif
02391 }
02392 #endif
02393
02394
02399 UNIV_INTERN
02400 ibool
02401 os_file_read_func(
02402
02403 os_file_t file,
02404 void* buf,
02405 ulint offset,
02407 ulint offset_high,
02409 ulint n)
02410 {
02411 #ifdef __WIN__
02412 BOOL ret;
02413 DWORD len;
02414 DWORD ret2;
02415 DWORD low;
02416 DWORD high;
02417 ibool retry;
02418 #ifndef UNIV_HOTBACKUP
02419 ulint i;
02420 #endif
02421
02422
02423
02424 ut_a((offset & 0xFFFFFFFFUL) == offset);
02425 ut_a((n & 0xFFFFFFFFUL) == n);
02426
02427 os_n_file_reads++;
02428 os_bytes_read_since_printout += n;
02429
02430 try_again:
02431 ut_ad(file);
02432 ut_ad(buf);
02433 ut_ad(n > 0);
02434
02435 low = (DWORD) offset;
02436 high = (DWORD) offset_high;
02437
02438 os_mutex_enter(os_file_count_mutex);
02439 os_n_pending_reads++;
02440 os_mutex_exit(os_file_count_mutex);
02441
02442 #ifndef UNIV_HOTBACKUP
02443
02444 i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
02445
02446 os_mutex_enter(os_file_seek_mutexes[i]);
02447 #endif
02448
02449 ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
02450
02451 if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
02452
02453 #ifndef UNIV_HOTBACKUP
02454 os_mutex_exit(os_file_seek_mutexes[i]);
02455 #endif
02456
02457 os_mutex_enter(os_file_count_mutex);
02458 os_n_pending_reads--;
02459 os_mutex_exit(os_file_count_mutex);
02460
02461 goto error_handling;
02462 }
02463
02464 ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
02465
02466 #ifndef UNIV_HOTBACKUP
02467 os_mutex_exit(os_file_seek_mutexes[i]);
02468 #endif
02469
02470 os_mutex_enter(os_file_count_mutex);
02471 os_n_pending_reads--;
02472 os_mutex_exit(os_file_count_mutex);
02473
02474 if (ret && len == n) {
02475 return(TRUE);
02476 }
02477 #else
02478 ibool retry;
02479 ssize_t ret;
02480
02481 os_bytes_read_since_printout += n;
02482
02483 try_again:
02484 ret = os_file_pread(file, buf, n, offset, offset_high);
02485
02486 if ((ulint)ret == n) {
02487
02488 return(TRUE);
02489 }
02490
02491 fprintf(stderr,
02492 "InnoDB: Error: tried to read %lu bytes at offset %lu %lu.\n"
02493 "InnoDB: Was only able to read %ld.\n",
02494 (ulong)n, (ulong)offset_high,
02495 (ulong)offset, (long)ret);
02496 #endif
02497 #ifdef __WIN__
02498 error_handling:
02499 #endif
02500 retry = os_file_handle_error(NULL, "read");
02501
02502 if (retry) {
02503 goto try_again;
02504 }
02505
02506 fprintf(stderr,
02507 "InnoDB: Fatal error: cannot read from file."
02508 " OS error number %lu.\n",
02509 #ifdef __WIN__
02510 (ulong) GetLastError()
02511 #else
02512 (ulong) errno
02513 #endif
02514 );
02515 fflush(stderr);
02516
02517 ut_error;
02518
02519 return(FALSE);
02520 }
02521
02522
02528 UNIV_INTERN
02529 ibool
02530 os_file_read_no_error_handling_func(
02531
02532 os_file_t file,
02533 void* buf,
02534 ulint offset,
02536 ulint offset_high,
02538 ulint n)
02539 {
02540 #ifdef __WIN__
02541 BOOL ret;
02542 DWORD len;
02543 DWORD ret2;
02544 DWORD low;
02545 DWORD high;
02546 ibool retry;
02547 #ifndef UNIV_HOTBACKUP
02548 ulint i;
02549 #endif
02550
02551
02552
02553 ut_a((offset & 0xFFFFFFFFUL) == offset);
02554 ut_a((n & 0xFFFFFFFFUL) == n);
02555
02556 os_n_file_reads++;
02557 os_bytes_read_since_printout += n;
02558
02559 try_again:
02560 ut_ad(file);
02561 ut_ad(buf);
02562 ut_ad(n > 0);
02563
02564 low = (DWORD) offset;
02565 high = (DWORD) offset_high;
02566
02567 os_mutex_enter(os_file_count_mutex);
02568 os_n_pending_reads++;
02569 os_mutex_exit(os_file_count_mutex);
02570
02571 #ifndef UNIV_HOTBACKUP
02572
02573 i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
02574
02575 os_mutex_enter(os_file_seek_mutexes[i]);
02576 #endif
02577
02578 ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
02579
02580 if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
02581
02582 #ifndef UNIV_HOTBACKUP
02583 os_mutex_exit(os_file_seek_mutexes[i]);
02584 #endif
02585
02586 os_mutex_enter(os_file_count_mutex);
02587 os_n_pending_reads--;
02588 os_mutex_exit(os_file_count_mutex);
02589
02590 goto error_handling;
02591 }
02592
02593 ret = ReadFile(file, buf, (DWORD) n, &len, NULL);
02594
02595 #ifndef UNIV_HOTBACKUP
02596 os_mutex_exit(os_file_seek_mutexes[i]);
02597 #endif
02598
02599 os_mutex_enter(os_file_count_mutex);
02600 os_n_pending_reads--;
02601 os_mutex_exit(os_file_count_mutex);
02602
02603 if (ret && len == n) {
02604 return(TRUE);
02605 }
02606 #else
02607 ibool retry;
02608 ssize_t ret;
02609
02610 os_bytes_read_since_printout += n;
02611
02612 try_again:
02613 ret = os_file_pread(file, buf, n, offset, offset_high);
02614
02615 if ((ulint)ret == n) {
02616
02617 return(TRUE);
02618 }
02619 #endif
02620 #ifdef __WIN__
02621 error_handling:
02622 #endif
02623 retry = os_file_handle_error_no_exit(NULL, "read");
02624
02625 if (retry) {
02626 goto try_again;
02627 }
02628
02629 return(FALSE);
02630 }
02631
02632
02636 UNIV_INTERN
02637 void
02638 os_file_read_string(
02639
02640 FILE* file,
02641 char* str,
02642 ulint size)
02643 {
02644 size_t flen;
02645
02646 if (size == 0) {
02647 return;
02648 }
02649
02650 rewind(file);
02651 flen = fread(str, 1, size - 1, file);
02652 str[flen] = '\0';
02653 }
02654
02655
02660 UNIV_INTERN
02661 ibool
02662 os_file_write_func(
02663
02664 const char* name,
02666 os_file_t file,
02667 const void* buf,
02668 ulint offset,
02670 ulint offset_high,
02672 ulint n)
02673 {
02674 #ifdef __WIN__
02675 BOOL ret;
02676 DWORD len;
02677 DWORD ret2;
02678 DWORD low;
02679 DWORD high;
02680 ulint n_retries = 0;
02681 ulint err;
02682 #ifndef UNIV_HOTBACKUP
02683 ulint i;
02684 #endif
02685
02686
02687
02688 ut_a((offset & 0xFFFFFFFFUL) == offset);
02689 ut_a((n & 0xFFFFFFFFUL) == n);
02690
02691 if (srv_fake_write)
02692 return(TRUE);
02693
02694 os_n_file_writes++;
02695
02696 ut_ad(file);
02697 ut_ad(buf);
02698 ut_ad(n > 0);
02699 retry:
02700 low = (DWORD) offset;
02701 high = (DWORD) offset_high;
02702
02703 os_mutex_enter(os_file_count_mutex);
02704 os_n_pending_writes++;
02705 os_mutex_exit(os_file_count_mutex);
02706
02707 #ifndef UNIV_HOTBACKUP
02708
02709 i = ((ulint) file) % OS_FILE_N_SEEK_MUTEXES;
02710
02711 os_mutex_enter(os_file_seek_mutexes[i]);
02712 #endif
02713
02714 ret2 = SetFilePointer(file, low, &high, FILE_BEGIN);
02715
02716 if (ret2 == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
02717
02718 #ifndef UNIV_HOTBACKUP
02719 os_mutex_exit(os_file_seek_mutexes[i]);
02720 #endif
02721
02722 os_mutex_enter(os_file_count_mutex);
02723 os_n_pending_writes--;
02724 os_mutex_exit(os_file_count_mutex);
02725
02726 ut_print_timestamp(stderr);
02727
02728 fprintf(stderr,
02729 " InnoDB: Error: File pointer positioning to"
02730 " file %s failed at\n"
02731 "InnoDB: offset %lu %lu. Operating system"
02732 " error number %lu.\n"
02733 "InnoDB: Some operating system error numbers"
02734 " are described at\n"
02735 "InnoDB: "
02736 REFMAN "operating-system-error-codes.html\n",
02737 name, (ulong) offset_high, (ulong) offset,
02738 (ulong) GetLastError());
02739
02740 return(FALSE);
02741 }
02742
02743 ret = WriteFile(file, buf, (DWORD) n, &len, NULL);
02744
02745
02746
02747
02748 # ifdef UNIV_DO_FLUSH
02749 if (!os_do_not_call_flush_at_each_write) {
02750 ut_a(TRUE == os_file_flush(file));
02751 }
02752 # endif
02753
02754 #ifndef UNIV_HOTBACKUP
02755 os_mutex_exit(os_file_seek_mutexes[i]);
02756 #endif
02757
02758 os_mutex_enter(os_file_count_mutex);
02759 os_n_pending_writes--;
02760 os_mutex_exit(os_file_count_mutex);
02761
02762 if (ret && len == n) {
02763
02764 return(TRUE);
02765 }
02766
02767
02768
02769
02770
02771 if (GetLastError() == ERROR_LOCK_VIOLATION && n_retries < 100) {
02772
02773 os_thread_sleep(1000000);
02774
02775 n_retries++;
02776
02777 goto retry;
02778 }
02779
02780 if (!os_has_said_disk_full) {
02781
02782 err = (ulint)GetLastError();
02783
02784 ut_print_timestamp(stderr);
02785
02786 fprintf(stderr,
02787 " InnoDB: Error: Write to file %s failed"
02788 " at offset %lu %lu.\n"
02789 "InnoDB: %lu bytes should have been written,"
02790 " only %lu were written.\n"
02791 "InnoDB: Operating system error number %lu.\n"
02792 "InnoDB: Check that your OS and file system"
02793 " support files of this size.\n"
02794 "InnoDB: Check also that the disk is not full"
02795 " or a disk quota exceeded.\n",
02796 name, (ulong) offset_high, (ulong) offset,
02797 (ulong) n, (ulong) len, (ulong) err);
02798
02799 if (strerror((int)err) != NULL) {
02800 fprintf(stderr,
02801 "InnoDB: Error number %lu means '%s'.\n",
02802 (ulong) err, strerror((int)err));
02803 }
02804
02805 fprintf(stderr,
02806 "InnoDB: Some operating system error numbers"
02807 " are described at\n"
02808 "InnoDB: "
02809 REFMAN "operating-system-error-codes.html\n");
02810
02811 os_has_said_disk_full = TRUE;
02812 }
02813
02814 return(FALSE);
02815 #else
02816 ssize_t ret;
02817
02818 ret = os_file_pwrite(file, buf, n, offset, offset_high);
02819
02820 if ((ulint)ret == n) {
02821
02822 return(TRUE);
02823 }
02824
02825 if (!os_has_said_disk_full) {
02826
02827 ut_print_timestamp(stderr);
02828
02829 fprintf(stderr,
02830 " InnoDB: Error: Write to file %s failed"
02831 " at offset %lu %lu.\n"
02832 "InnoDB: %lu bytes should have been written,"
02833 " only %ld were written.\n"
02834 "InnoDB: Operating system error number %lu.\n"
02835 "InnoDB: Check that your OS and file system"
02836 " support files of this size.\n"
02837 "InnoDB: Check also that the disk is not full"
02838 " or a disk quota exceeded.\n",
02839 name, offset_high, offset, n, (long int)ret,
02840 (ulint)errno);
02841 if (strerror(errno) != NULL) {
02842 fprintf(stderr,
02843 "InnoDB: Error number %lu means '%s'.\n",
02844 (ulint)errno, strerror(errno));
02845 }
02846
02847 fprintf(stderr,
02848 "InnoDB: Some operating system error numbers"
02849 " are described at\n"
02850 "InnoDB: "
02851 REFMAN "operating-system-error-codes.html\n");
02852
02853 os_has_said_disk_full = TRUE;
02854 }
02855
02856 return(FALSE);
02857 #endif
02858 }
02859
02860
02863 UNIV_INTERN
02864 ibool
02865 os_file_status(
02866
02867 const char* path,
02868 ibool* exists,
02869 os_file_type_t* type)
02870 {
02871 #ifdef __WIN__
02872 int ret;
02873 struct _stat statinfo;
02874
02875 ret = _stat(path, &statinfo);
02876 if (ret && (errno == ENOENT || errno == ENOTDIR)) {
02877
02878 *exists = FALSE;
02879 return(TRUE);
02880 } else if (ret) {
02881
02882
02883 os_file_handle_error_no_exit(path, "stat");
02884
02885 return(FALSE);
02886 }
02887
02888 if (_S_IFDIR & statinfo.st_mode) {
02889 *type = OS_FILE_TYPE_DIR;
02890 } else if (_S_IFREG & statinfo.st_mode) {
02891 *type = OS_FILE_TYPE_FILE;
02892 } else {
02893 *type = OS_FILE_TYPE_UNKNOWN;
02894 }
02895
02896 *exists = TRUE;
02897
02898 return(TRUE);
02899 #else
02900 int ret;
02901 struct stat statinfo;
02902
02903 ret = stat(path, &statinfo);
02904 if (ret && (errno == ENOENT || errno == ENOTDIR)) {
02905
02906 *exists = FALSE;
02907 return(TRUE);
02908 } else if (ret) {
02909
02910
02911 os_file_handle_error_no_exit(path, "stat");
02912
02913 return(FALSE);
02914 }
02915
02916 if (S_ISDIR(statinfo.st_mode)) {
02917 *type = OS_FILE_TYPE_DIR;
02918 } else if (S_ISLNK(statinfo.st_mode)) {
02919 *type = OS_FILE_TYPE_LINK;
02920 } else if (S_ISREG(statinfo.st_mode)) {
02921 *type = OS_FILE_TYPE_FILE;
02922 } else {
02923 *type = OS_FILE_TYPE_UNKNOWN;
02924 }
02925
02926 *exists = TRUE;
02927
02928 return(TRUE);
02929 #endif
02930 }
02931
02932
02935 UNIV_INTERN
02936 ibool
02937 os_file_get_status(
02938
02939 const char* path,
02940 os_file_stat_t* stat_info)
02942 {
02943 #ifdef __WIN__
02944 int ret;
02945 struct _stat statinfo;
02946
02947 ret = _stat(path, &statinfo);
02948 if (ret && (errno == ENOENT || errno == ENOTDIR)) {
02949
02950
02951 return(FALSE);
02952 } else if (ret) {
02953
02954
02955 os_file_handle_error_no_exit(path, "stat");
02956
02957 return(FALSE);
02958 }
02959 if (_S_IFDIR & statinfo.st_mode) {
02960 stat_info->type = OS_FILE_TYPE_DIR;
02961 } else if (_S_IFREG & statinfo.st_mode) {
02962 stat_info->type = OS_FILE_TYPE_FILE;
02963 } else {
02964 stat_info->type = OS_FILE_TYPE_UNKNOWN;
02965 }
02966
02967 stat_info->ctime = statinfo.st_ctime;
02968 stat_info->atime = statinfo.st_atime;
02969 stat_info->mtime = statinfo.st_mtime;
02970 stat_info->size = statinfo.st_size;
02971
02972 return(TRUE);
02973 #else
02974 int ret;
02975 struct stat statinfo;
02976
02977 ret = stat(path, &statinfo);
02978
02979 if (ret && (errno == ENOENT || errno == ENOTDIR)) {
02980
02981
02982 return(FALSE);
02983 } else if (ret) {
02984
02985
02986 os_file_handle_error_no_exit(path, "stat");
02987
02988 return(FALSE);
02989 }
02990
02991 if (S_ISDIR(statinfo.st_mode)) {
02992 stat_info->type = OS_FILE_TYPE_DIR;
02993 } else if (S_ISLNK(statinfo.st_mode)) {
02994 stat_info->type = OS_FILE_TYPE_LINK;
02995 } else if (S_ISREG(statinfo.st_mode)) {
02996 stat_info->type = OS_FILE_TYPE_FILE;
02997 } else {
02998 stat_info->type = OS_FILE_TYPE_UNKNOWN;
02999 }
03000
03001 stat_info->ctime = statinfo.st_ctime;
03002 stat_info->atime = statinfo.st_atime;
03003 stat_info->mtime = statinfo.st_mtime;
03004 stat_info->size = statinfo.st_size;
03005
03006 return(TRUE);
03007 #endif
03008 }
03009
03010
03011 #ifdef __WIN__
03012 # define OS_FILE_PATH_SEPARATOR '\\'
03013 #else
03014 # define OS_FILE_PATH_SEPARATOR '/'
03015 #endif
03016
03017
03045 UNIV_INTERN
03046 char*
03047 os_file_dirname(
03048
03049 const char* path)
03050 {
03051
03052 const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR);
03053 if (!last_slash) {
03054
03055
03056 return(mem_strdup("."));
03057 }
03058
03059
03060
03061 if (last_slash == path) {
03062
03063
03064 return(mem_strdup("/"));
03065 }
03066
03067
03068
03069 return(mem_strdupl(path, last_slash - path));
03070 }
03071
03072
03075 UNIV_INTERN
03076 ibool
03077 os_file_create_subdirs_if_needed(
03078
03079 const char* path)
03080 {
03081 char* subdir;
03082 ibool success, subdir_exists;
03083 os_file_type_t type;
03084
03085 subdir = os_file_dirname(path);
03086 if (strlen(subdir) == 1
03087 && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) {
03088
03089 mem_free(subdir);
03090
03091 return(TRUE);
03092 }
03093
03094
03095 success = os_file_status(subdir, &subdir_exists, &type);
03096 if (success && !subdir_exists) {
03097
03098 success = os_file_create_subdirs_if_needed(subdir);
03099 if (!success) {
03100 mem_free(subdir);
03101
03102 return(FALSE);
03103 }
03104 success = os_file_create_directory(subdir, FALSE);
03105 }
03106
03107 mem_free(subdir);
03108
03109 return(success);
03110 }
03111
03112 #ifndef UNIV_HOTBACKUP
03113
03116 static
03117 os_aio_slot_t*
03118 os_aio_array_get_nth_slot(
03119
03120 os_aio_array_t* array,
03121 ulint index)
03122 {
03123 ut_a(index < array->n_slots);
03124
03125 return((array->slots) + index);
03126 }
03127
03128 #if defined(LINUX_NATIVE_AIO)
03129
03132 static
03133 ibool
03134 os_aio_linux_create_io_ctx(
03135
03136 ulint max_events,
03137 io_context_t* io_ctx)
03138 {
03139 int ret;
03140 ulint retries = 0;
03141
03142 retry:
03143 memset(io_ctx, 0x0, sizeof(*io_ctx));
03144
03145
03146
03147
03148 ret = io_setup(max_events, io_ctx);
03149 if (ret == 0) {
03150 #if defined(UNIV_AIO_DEBUG)
03151 fprintf(stderr,
03152 "InnoDB: Linux native AIO:"
03153 " initialized io_ctx for segment\n");
03154 #endif
03155
03156 return(TRUE);
03157 }
03158
03159
03160
03161 switch (ret) {
03162 case -EAGAIN:
03163 if (retries == 0) {
03164
03165 ut_print_timestamp(stderr);
03166 fprintf(stderr,
03167 " InnoDB: Warning: io_setup() failed"
03168 " with EAGAIN. Will make %d attempts"
03169 " before giving up.\n",
03170 OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
03171 }
03172
03173 if (retries < OS_AIO_IO_SETUP_RETRY_ATTEMPTS) {
03174 ++retries;
03175 fprintf(stderr,
03176 "InnoDB: Warning: io_setup() attempt"
03177 " %lu failed.\n",
03178 retries);
03179 os_thread_sleep(OS_AIO_IO_SETUP_RETRY_SLEEP);
03180 goto retry;
03181 }
03182
03183
03184 ut_print_timestamp(stderr);
03185 fprintf(stderr,
03186 " InnoDB: Error: io_setup() failed"
03187 " with EAGAIN after %d attempts.\n",
03188 OS_AIO_IO_SETUP_RETRY_ATTEMPTS);
03189 break;
03190
03191 case -ENOSYS:
03192 ut_print_timestamp(stderr);
03193 fprintf(stderr,
03194 " InnoDB: Error: Linux Native AIO interface"
03195 " is not supported on this platform. Please"
03196 " check your OS documentation and install"
03197 " appropriate binary of InnoDB.\n");
03198
03199 break;
03200
03201 default:
03202 ut_print_timestamp(stderr);
03203 fprintf(stderr,
03204 " InnoDB: Error: Linux Native AIO setup"
03205 " returned following error[%d]\n", -ret);
03206 break;
03207 }
03208
03209 fprintf(stderr,
03210 "InnoDB: You can disable Linux Native AIO by"
03211 " setting innodb_native_aio = off in my.cnf\n");
03212 return(FALSE);
03213 }
03214 #endif
03215
03216
03221 static
03222 os_aio_array_t*
03223 os_aio_array_create(
03224
03225 ulint n,
03228 ulint n_segments)
03229 {
03230 os_aio_array_t* array;
03231 ulint i;
03232 os_aio_slot_t* slot;
03233 #ifdef WIN_ASYNC_IO
03234 OVERLAPPED* over;
03235 #elif defined(LINUX_NATIVE_AIO)
03236 struct io_event* aio_event = NULL;
03237 #endif
03238 ut_a(n > 0);
03239 ut_a(n_segments > 0);
03240
03241 array = static_cast<os_aio_array_t *>(ut_malloc(sizeof(os_aio_array_t)));
03242
03243 array->mutex = os_mutex_create();
03244 array->not_full = os_event_create(NULL);
03245 array->is_empty = os_event_create(NULL);
03246
03247 os_event_set(array->is_empty);
03248
03249 array->n_slots = n;
03250 array->n_segments = n_segments;
03251 array->n_reserved = 0;
03252 array->cur_seg = 0;
03253 array->slots = static_cast<os_aio_slot_t *>(ut_malloc(n * sizeof(os_aio_slot_t)));
03254 #ifdef __WIN__
03255 array->handles = ut_malloc(n * sizeof(HANDLE));
03256 #endif
03257
03258 #if defined(LINUX_NATIVE_AIO)
03259 array->aio_ctx = NULL;
03260 array->aio_events = NULL;
03261
03262
03263
03264 if (!srv_use_native_aio) {
03265 goto skip_native_aio;
03266 }
03267
03268
03269
03270
03271 array->aio_ctx = (io_context**) ut_malloc(n_segments *
03272 sizeof(*array->aio_ctx));
03273 for (i = 0; i < n_segments; ++i) {
03274 if (!os_aio_linux_create_io_ctx(n/n_segments,
03275 &array->aio_ctx[i])) {
03276
03277
03278
03279
03280
03281
03282 return(NULL);
03283 }
03284 }
03285
03286
03287 aio_event = (io_event*) ut_malloc(n * sizeof(io_event));
03288 memset(aio_event, 0x0, sizeof(io_event) * n);
03289 array->aio_events = aio_event;
03290
03291 skip_native_aio:
03292 #endif
03293 for (i = 0; i < n; i++) {
03294 slot = os_aio_array_get_nth_slot(array, i);
03295
03296 slot->pos = i;
03297 slot->reserved = FALSE;
03298 #ifdef WIN_ASYNC_IO
03299 slot->handle = CreateEvent(NULL,TRUE, FALSE, NULL);
03300
03301 over = &(slot->control);
03302
03303 over->hEvent = slot->handle;
03304
03305 *((array->handles) + i) = over->hEvent;
03306
03307 #elif defined(LINUX_NATIVE_AIO)
03308
03309 memset(&slot->control, 0x0, sizeof(slot->control));
03310 slot->n_bytes = 0;
03311 slot->ret = 0;
03312 #endif
03313 }
03314
03315 return(array);
03316 }
03317
03318
03320 static
03321 void
03322 os_aio_array_free(
03323
03324 os_aio_array_t* array)
03325 {
03326 #ifdef WIN_ASYNC_IO
03327 ulint i;
03328
03329 for (i = 0; i < array->n_slots; i++) {
03330 os_aio_slot_t* slot = os_aio_array_get_nth_slot(array, i);
03331 CloseHandle(slot->handle);
03332 }
03333 #endif
03334
03335 #ifdef __WIN__
03336 ut_free(array->handles);
03337 #endif
03338 os_mutex_free(array->mutex);
03339 os_event_free(array->not_full);
03340 os_event_free(array->is_empty);
03341
03342 #if defined(LINUX_NATIVE_AIO)
03343 if (srv_use_native_aio) {
03344 ut_free(array->aio_events);
03345 ut_free(array->aio_ctx);
03346 }
03347 #endif
03348
03349 ut_free(array->slots);
03350 ut_free(array);
03351 }
03352
03353
03354
03355
03356
03357
03358
03359
03360 UNIV_INTERN
03361 ibool
03362 os_aio_init(
03363
03364 ulint n_per_seg,
03365
03366 ulint n_read_segs,
03367 ulint n_write_segs,
03368 ulint n_slots_sync)
03369
03370 {
03371 ulint i;
03372 ulint n_segments = 2 + n_read_segs + n_write_segs;
03373
03374 ut_ad(n_segments >= 4);
03375
03376 os_io_init_simple();
03377
03378 for (i = 0; i < n_segments; i++) {
03379 srv_set_io_thread_op_info(i, "not started yet");
03380 }
03381
03382
03383
03384
03385 os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1);
03386 if (os_aio_ibuf_array == NULL) {
03387 goto err_exit;
03388 }
03389
03390 srv_io_thread_function[0] = "insert buffer thread";
03391
03392 os_aio_log_array = os_aio_array_create(n_per_seg, 1);
03393 if (os_aio_log_array == NULL) {
03394 goto err_exit;
03395 }
03396
03397 srv_io_thread_function[1] = "log thread";
03398
03399 os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg,
03400 n_read_segs);
03401 if (os_aio_read_array == NULL) {
03402 goto err_exit;
03403 }
03404
03405 for (i = 2; i < 2 + n_read_segs; i++) {
03406 ut_a(i < SRV_MAX_N_IO_THREADS);
03407 srv_io_thread_function[i] = "read thread";
03408 }
03409
03410 os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg,
03411 n_write_segs);
03412 if (os_aio_write_array == NULL) {
03413 goto err_exit;
03414 }
03415
03416 for (i = 2 + n_read_segs; i < n_segments; i++) {
03417 ut_a(i < SRV_MAX_N_IO_THREADS);
03418 srv_io_thread_function[i] = "write thread";
03419 }
03420
03421 os_aio_sync_array = os_aio_array_create(n_slots_sync, 1);
03422 if (os_aio_sync_array == NULL) {
03423 goto err_exit;
03424 }
03425
03426
03427 os_aio_n_segments = n_segments;
03428
03429 os_aio_validate();
03430
03431 os_aio_segment_wait_events = static_cast<os_event_t *>(ut_malloc(n_segments * sizeof(void*)));
03432
03433 for (i = 0; i < n_segments; i++) {
03434 os_aio_segment_wait_events[i] = os_event_create(NULL);
03435 }
03436
03437 os_last_printout = time(NULL);
03438
03439 return(TRUE);
03440
03441 err_exit:
03442 return(FALSE);
03443
03444 }
03445
03446
03447
03448 UNIV_INTERN
03449 void
03450 os_aio_free(void)
03451
03452 {
03453 ulint i;
03454
03455 os_aio_array_free(os_aio_ibuf_array);
03456 os_aio_ibuf_array = NULL;
03457 os_aio_array_free(os_aio_log_array);
03458 os_aio_log_array = NULL;
03459 os_aio_array_free(os_aio_read_array);
03460 os_aio_read_array = NULL;
03461 os_aio_array_free(os_aio_write_array);
03462 os_aio_write_array = NULL;
03463 os_aio_array_free(os_aio_sync_array);
03464 os_aio_sync_array = NULL;
03465
03466 for (i = 0; i < os_aio_n_segments; i++) {
03467 os_event_free(os_aio_segment_wait_events[i]);
03468 }
03469
03470 ut_free(os_aio_segment_wait_events);
03471 os_aio_segment_wait_events = 0;
03472 os_aio_n_segments = 0;
03473 }
03474
03475 #ifdef WIN_ASYNC_IO
03476
03479 static
03480 void
03481 os_aio_array_wake_win_aio_at_shutdown(
03482
03483 os_aio_array_t* array)
03484 {
03485 ulint i;
03486
03487 for (i = 0; i < array->n_slots; i++) {
03488
03489 SetEvent((array->slots + i)->handle);
03490 }
03491 }
03492 #endif
03493
03494
03497 UNIV_INTERN
03498 void
03499 os_aio_wake_all_threads_at_shutdown(void)
03500
03501 {
03502 ulint i;
03503
03504 #ifdef WIN_ASYNC_IO
03505
03506 os_aio_array_wake_win_aio_at_shutdown(os_aio_read_array);
03507 os_aio_array_wake_win_aio_at_shutdown(os_aio_write_array);
03508 os_aio_array_wake_win_aio_at_shutdown(os_aio_ibuf_array);
03509 os_aio_array_wake_win_aio_at_shutdown(os_aio_log_array);
03510
03511 #elif defined(LINUX_NATIVE_AIO)
03512
03513
03514
03515
03516
03517
03518 if (srv_use_native_aio) {
03519 return;
03520 }
03521
03522
03523 #endif
03524
03525
03526 for (i = 0; i < os_aio_n_segments; i++) {
03527
03528 os_event_set(os_aio_segment_wait_events[i]);
03529 }
03530 }
03531
03532
03535 UNIV_INTERN
03536 void
03537 os_aio_wait_until_no_pending_writes(void)
03538
03539 {
03540 os_event_wait(os_aio_write_array->is_empty);
03541 }
03542
03543
03547 static
03548 ulint
03549 os_aio_get_segment_no_from_slot(
03550
03551 os_aio_array_t* array,
03552 os_aio_slot_t* slot)
03553 {
03554 ulint segment;
03555 ulint seg_len;
03556
03557 if (array == os_aio_ibuf_array) {
03558 segment = 0;
03559
03560 } else if (array == os_aio_log_array) {
03561 segment = 1;
03562
03563 } else if (array == os_aio_read_array) {
03564 seg_len = os_aio_read_array->n_slots
03565 / os_aio_read_array->n_segments;
03566
03567 segment = 2 + slot->pos / seg_len;
03568 } else {
03569 ut_a(array == os_aio_write_array);
03570 seg_len = os_aio_write_array->n_slots
03571 / os_aio_write_array->n_segments;
03572
03573 segment = os_aio_read_array->n_segments + 2
03574 + slot->pos / seg_len;
03575 }
03576
03577 return(segment);
03578 }
03579
03580
03583 static
03584 ulint
03585 os_aio_get_array_and_local_segment(
03586
03587 os_aio_array_t** array,
03588 ulint global_segment)
03589 {
03590 ulint segment;
03591
03592 ut_a(global_segment < os_aio_n_segments);
03593
03594 if (global_segment == 0) {
03595 *array = os_aio_ibuf_array;
03596 segment = 0;
03597
03598 } else if (global_segment == 1) {
03599 *array = os_aio_log_array;
03600 segment = 0;
03601
03602 } else if (global_segment < os_aio_read_array->n_segments + 2) {
03603 *array = os_aio_read_array;
03604
03605 segment = global_segment - 2;
03606 } else {
03607 *array = os_aio_write_array;
03608
03609 segment = global_segment - (os_aio_read_array->n_segments + 2);
03610 }
03611
03612 return(segment);
03613 }
03614
03615
03619 static
03620 os_aio_slot_t*
03621 os_aio_array_reserve_slot(
03622
03623 ulint type,
03624 os_aio_array_t* array,
03625 fil_node_t* message1,
03627 void* message2,
03629 os_file_t file,
03630 const char* name,
03632 void* buf,
03634 ulint offset,
03636 ulint offset_high,
03638 ulint len)
03639 {
03640 os_aio_slot_t* slot = NULL;
03641 #ifdef WIN_ASYNC_IO
03642 OVERLAPPED* control;
03643
03644 #elif defined(LINUX_NATIVE_AIO)
03645
03646 struct iocb* iocb;
03647 off_t aio_offset;
03648
03649 #endif
03650 ulint i;
03651 ulint counter;
03652 ulint slots_per_seg;
03653 ulint local_seg;
03654
03655 #ifdef WIN_ASYNC_IO
03656 ut_a((len & 0xFFFFFFFFUL) == len);
03657 #endif
03658
03659
03660 slots_per_seg = array->n_slots / array->n_segments;
03661
03662
03663
03664
03665 local_seg = (offset >> (UNIV_PAGE_SIZE_SHIFT + 6))
03666 % array->n_segments;
03667
03668 loop:
03669 os_mutex_enter(array->mutex);
03670
03671 if (array->n_reserved == array->n_slots) {
03672 os_mutex_exit(array->mutex);
03673
03674 if (!srv_use_native_aio) {
03675
03676
03677
03678 os_aio_simulated_wake_handler_threads();
03679 }
03680
03681 os_event_wait(array->not_full);
03682
03683 goto loop;
03684 }
03685
03686
03687
03688
03689 for (i = local_seg * slots_per_seg, counter = 0;
03690 counter < array->n_slots; i++, counter++) {
03691
03692 i %= array->n_slots;
03693 slot = os_aio_array_get_nth_slot(array, i);
03694
03695 if (slot->reserved == FALSE) {
03696 goto found;
03697 }
03698 }
03699
03700
03701 ut_error;
03702
03703 found:
03704 ut_a(slot->reserved == FALSE);
03705 array->n_reserved++;
03706
03707 if (array->n_reserved == 1) {
03708 os_event_reset(array->is_empty);
03709 }
03710
03711 if (array->n_reserved == array->n_slots) {
03712 os_event_reset(array->not_full);
03713 }
03714
03715 slot->reserved = TRUE;
03716 slot->reservation_time = time(NULL);
03717 slot->message1 = message1;
03718 slot->message2 = message2;
03719 slot->file = file;
03720 slot->name = name;
03721 slot->len = len;
03722 slot->type = type;
03723 slot->buf = static_cast<unsigned char *>(buf);
03724 slot->offset = offset;
03725 slot->offset_high = offset_high;
03726 slot->io_already_done = FALSE;
03727
03728 #ifdef WIN_ASYNC_IO
03729 control = &(slot->control);
03730 control->Offset = (DWORD)offset;
03731 control->OffsetHigh = (DWORD)offset_high;
03732 ResetEvent(slot->handle);
03733
03734 #elif defined(LINUX_NATIVE_AIO)
03735
03736
03737 if (!srv_use_native_aio) {
03738 goto skip_native_aio;
03739 }
03740
03741
03742
03743 if (sizeof(aio_offset) == 8) {
03744 aio_offset = offset_high;
03745 aio_offset <<= 32;
03746 aio_offset += offset;
03747 } else {
03748 ut_a(offset_high == 0);
03749 aio_offset = offset;
03750 }
03751
03752 iocb = &slot->control;
03753
03754 if (type == OS_FILE_READ) {
03755 io_prep_pread(iocb, file, buf, len, aio_offset);
03756 } else {
03757 ut_a(type == OS_FILE_WRITE);
03758 io_prep_pwrite(iocb, file, buf, len, aio_offset);
03759 }
03760
03761 iocb->data = (void*)slot;
03762 slot->n_bytes = 0;
03763 slot->ret = 0;
03764
03765
03766
03767 skip_native_aio:
03768 #endif
03769 os_mutex_exit(array->mutex);
03770
03771 return(slot);
03772 }
03773
03774
03776 static
03777 void
03778 os_aio_array_free_slot(
03779
03780 os_aio_array_t* array,
03781 os_aio_slot_t* slot)
03782 {
03783 ut_ad(array);
03784 ut_ad(slot);
03785
03786 os_mutex_enter(array->mutex);
03787
03788 ut_ad(slot->reserved);
03789
03790 slot->reserved = FALSE;
03791
03792 array->n_reserved--;
03793
03794 if (array->n_reserved == array->n_slots - 1) {
03795 os_event_set(array->not_full);
03796 }
03797
03798 if (array->n_reserved == 0) {
03799 os_event_set(array->is_empty);
03800 }
03801
03802 #ifdef WIN_ASYNC_IO
03803
03804 ResetEvent(slot->handle);
03805
03806 #elif defined(LINUX_NATIVE_AIO)
03807
03808 if (srv_use_native_aio) {
03809 memset(&slot->control, 0x0, sizeof(slot->control));
03810 slot->n_bytes = 0;
03811 slot->ret = 0;
03812
03813 } else {
03814
03815
03816 ut_ad(slot->n_bytes == 0);
03817 ut_ad(slot->ret == 0);
03818 }
03819
03820 #endif
03821 os_mutex_exit(array->mutex);
03822 }
03823
03824
03826 static
03827 void
03828 os_aio_simulated_wake_handler_thread(
03829
03830 ulint global_segment)
03832 {
03833 os_aio_array_t* array;
03834 os_aio_slot_t* slot;
03835 ulint segment;
03836 ulint n;
03837 ulint i;
03838
03839 ut_ad(!srv_use_native_aio);
03840
03841 segment = os_aio_get_array_and_local_segment(&array, global_segment);
03842
03843 n = array->n_slots / array->n_segments;
03844
03845
03846
03847 os_mutex_enter(array->mutex);
03848
03849 for (i = 0; i < n; i++) {
03850 slot = os_aio_array_get_nth_slot(array, i + segment * n);
03851
03852 if (slot->reserved) {
03853
03854
03855 break;
03856 }
03857 }
03858
03859 os_mutex_exit(array->mutex);
03860
03861 if (i < n) {
03862 os_event_set(os_aio_segment_wait_events[global_segment]);
03863 }
03864 }
03865
03866
03868 UNIV_INTERN
03869 void
03870 os_aio_simulated_wake_handler_threads(void)
03871
03872 {
03873 ulint i;
03874
03875 if (srv_use_native_aio) {
03876
03877
03878 return;
03879 }
03880
03881 os_aio_recommend_sleep_for_read_threads = FALSE;
03882
03883 for (i = 0; i < os_aio_n_segments; i++) {
03884 os_aio_simulated_wake_handler_thread(i);
03885 }
03886 }
03887
03888
03893 UNIV_INTERN
03894 void
03895 os_aio_simulated_put_read_threads_to_sleep(void)
03896
03897 {
03898
03899
03900
03901
03902
03903 #ifdef __WIN__
03904 os_aio_array_t* array;
03905 ulint g;
03906
03907 if (srv_use_native_aio) {
03908
03909
03910 return;
03911 }
03912
03913 os_aio_recommend_sleep_for_read_threads = TRUE;
03914
03915 for (g = 0; g < os_aio_n_segments; g++) {
03916 os_aio_get_array_and_local_segment(&array, g);
03917
03918 if (array == os_aio_read_array) {
03919
03920 os_event_reset(os_aio_segment_wait_events[g]);
03921 }
03922 }
03923 #endif
03924 }
03925
03926 #if defined(LINUX_NATIVE_AIO)
03927
03930 static
03931 ibool
03932 os_aio_linux_dispatch(
03933
03934 os_aio_array_t* array,
03935 os_aio_slot_t* slot)
03936 {
03937 int ret;
03938 ulint io_ctx_index;
03939 struct iocb* iocb;
03940
03941 ut_ad(slot != NULL);
03942 ut_ad(array);
03943
03944 ut_a(slot->reserved);
03945
03946
03947
03948
03949
03950 iocb = &slot->control;
03951 io_ctx_index = (slot->pos * array->n_segments) / array->n_slots;
03952
03953 ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb);
03954
03955 #if defined(UNIV_AIO_DEBUG)
03956 fprintf(stderr,
03957 "io_submit[%c] ret[%d]: slot[%p] ctx[%p] seg[%lu]\n",
03958 (slot->type == OS_FILE_WRITE) ? 'w' : 'r', ret, slot,
03959 array->aio_ctx[io_ctx_index], (ulong)io_ctx_index);
03960 #endif
03961
03962
03963
03964 if (UNIV_UNLIKELY(ret != 1)) {
03965 errno = -ret;
03966 return(FALSE);
03967 }
03968
03969 return(TRUE);
03970 }
03971 #endif
03972
03973
03974
03978 UNIV_INTERN
03979 ibool
03980 os_aio_func(
03981
03982 ulint type,
03983 ulint mode,
03996 const char* name,
03998 os_file_t file,
03999 void* buf,
04001 ulint offset,
04003 ulint offset_high,
04005 ulint n,
04006 fil_node_t* message1,
04010 void* message2)
04014 {
04015 os_aio_array_t* array;
04016 os_aio_slot_t* slot;
04017 #ifdef WIN_ASYNC_IO
04018 ibool retval;
04019 BOOL ret = TRUE;
04020 DWORD len = (DWORD) n;
04021 struct fil_node_struct * dummy_mess1;
04022 void* dummy_mess2;
04023 ulint dummy_type;
04024 #endif
04025 #if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
04026 ibool retry;
04027 #endif
04028 ulint wake_later;
04029
04030 ut_ad(file);
04031 ut_ad(buf);
04032 ut_ad(n > 0);
04033 ut_ad(n % OS_FILE_LOG_BLOCK_SIZE == 0);
04034 ut_ad(offset % OS_FILE_LOG_BLOCK_SIZE == 0);
04035 ut_ad(os_aio_validate());
04036 #ifdef WIN_ASYNC_IO
04037 ut_ad((n & 0xFFFFFFFFUL) == n);
04038 #endif
04039
04040 wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
04041 mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER);
04042
04043 if (mode == OS_AIO_SYNC
04044 #ifdef WIN_ASYNC_IO
04045 && !srv_use_native_aio
04046 #endif
04047 ) {
04048
04049
04050
04051
04052
04053
04054
04055 if (type == OS_FILE_READ) {
04056 return(os_file_read(file, buf, offset,
04057 offset_high, n));
04058 }
04059
04060 ut_a(type == OS_FILE_WRITE);
04061
04062 return(os_file_write(name, file, buf, offset, offset_high, n));
04063 }
04064
04065 #if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
04066 try_again:
04067 #endif
04068 if (mode == OS_AIO_NORMAL) {
04069 if (type == OS_FILE_READ) {
04070 array = os_aio_read_array;
04071 } else {
04072 array = os_aio_write_array;
04073 }
04074 } else if (mode == OS_AIO_IBUF) {
04075 ut_ad(type == OS_FILE_READ);
04076
04077
04078
04079 wake_later = FALSE;
04080
04081 array = os_aio_ibuf_array;
04082 } else if (mode == OS_AIO_LOG) {
04083
04084 array = os_aio_log_array;
04085 } else if (mode == OS_AIO_SYNC) {
04086 array = os_aio_sync_array;
04087
04088 #if defined(LINUX_NATIVE_AIO)
04089
04090 ut_a(!srv_use_native_aio);
04091 #endif
04092 } else {
04093 array = NULL;
04094 ut_error;
04095 }
04096
04097 slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
04098 name, buf, offset, offset_high, n);
04099 if (type == OS_FILE_READ) {
04100 if (srv_use_native_aio) {
04101 os_n_file_reads++;
04102 os_bytes_read_since_printout += n;
04103 #ifdef WIN_ASYNC_IO
04104 ret = ReadFile(file, buf, (DWORD)n, &len,
04105 &(slot->control));
04106
04107 #elif defined(LINUX_NATIVE_AIO)
04108 if (!os_aio_linux_dispatch(array, slot)) {
04109 goto err_exit;
04110 }
04111 #endif
04112 } else {
04113 if (!wake_later) {
04114 os_aio_simulated_wake_handler_thread(
04115 os_aio_get_segment_no_from_slot(
04116 array, slot));
04117 }
04118 }
04119 } else if (type == OS_FILE_WRITE) {
04120 if (srv_use_native_aio) {
04121 os_n_file_writes++;
04122 #ifdef WIN_ASYNC_IO
04123 ret = WriteFile(file, buf, (DWORD)n, &len,
04124 &(slot->control));
04125
04126 #elif defined(LINUX_NATIVE_AIO)
04127 if (!os_aio_linux_dispatch(array, slot)) {
04128 goto err_exit;
04129 }
04130 #endif
04131 } else {
04132 if (!wake_later) {
04133 os_aio_simulated_wake_handler_thread(
04134 os_aio_get_segment_no_from_slot(
04135 array, slot));
04136 }
04137 }
04138 } else {
04139 ut_error;
04140 }
04141
04142 #ifdef WIN_ASYNC_IO
04143 if (srv_use_native_aio) {
04144 if ((ret && len == n)
04145 || (!ret && GetLastError() == ERROR_IO_PENDING)) {
04146
04147
04148 if (mode == OS_AIO_SYNC) {
04149
04150
04151
04152
04153
04154 retval = os_aio_windows_handle(ULINT_UNDEFINED,
04155 slot->pos,
04156 &dummy_mess1,
04157 &dummy_mess2,
04158 &dummy_type);
04159
04160 return(retval);
04161 }
04162
04163 return(TRUE);
04164 }
04165
04166 goto err_exit;
04167 }
04168 #endif
04169
04170 return(TRUE);
04171
04172 #if defined LINUX_NATIVE_AIO || defined WIN_ASYNC_IO
04173 err_exit:
04174 os_aio_array_free_slot(array, slot);
04175
04176 retry = os_file_handle_error(name,
04177 type == OS_FILE_READ
04178 ? "aio read" : "aio write");
04179 if (retry) {
04180
04181 goto try_again;
04182 }
04183
04184 return(FALSE);
04185 #endif
04186 }
04187
04188 #ifdef WIN_ASYNC_IO
04189
04197 UNIV_INTERN
04198 ibool
04199 os_aio_windows_handle(
04200
04201 ulint segment,
04209 ulint pos,
04211 fil_node_t**message1,
04216 void** message2,
04217 ulint* type)
04218 {
04219 ulint orig_seg = segment;
04220 os_aio_array_t* array;
04221 os_aio_slot_t* slot;
04222 ulint n;
04223 ulint i;
04224 ibool ret_val;
04225 BOOL ret;
04226 DWORD len;
04227 BOOL retry = FALSE;
04228
04229 if (segment == ULINT_UNDEFINED) {
04230 array = os_aio_sync_array;
04231 segment = 0;
04232 } else {
04233 segment = os_aio_get_array_and_local_segment(&array, segment);
04234 }
04235
04236
04237
04238
04239 ut_ad(os_aio_validate());
04240 ut_ad(segment < array->n_segments);
04241
04242 n = array->n_slots / array->n_segments;
04243
04244 if (array == os_aio_sync_array) {
04245 WaitForSingleObject(
04246 os_aio_array_get_nth_slot(array, pos)->handle,
04247 INFINITE);
04248 i = pos;
04249 } else {
04250 srv_set_io_thread_op_info(orig_seg, "wait Windows aio");
04251 i = WaitForMultipleObjects((DWORD) n,
04252 array->handles + segment * n,
04253 FALSE,
04254 INFINITE);
04255 }
04256
04257 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
04258 os_thread_exit(NULL);
04259 }
04260
04261 os_mutex_enter(array->mutex);
04262
04263 slot = os_aio_array_get_nth_slot(array, i + segment * n);
04264
04265 ut_a(slot->reserved);
04266
04267 if (orig_seg != ULINT_UNDEFINED) {
04268 srv_set_io_thread_op_info(orig_seg,
04269 "get windows aio return value");
04270 }
04271
04272 ret = GetOverlappedResult(slot->file, &(slot->control), &len, TRUE);
04273
04274 *message1 = slot->message1;
04275 *message2 = slot->message2;
04276
04277 *type = slot->type;
04278
04279 if (ret && len == slot->len) {
04280 ret_val = TRUE;
04281
04282 #ifdef UNIV_DO_FLUSH
04283 if (slot->type == OS_FILE_WRITE
04284 && !os_do_not_call_flush_at_each_write) {
04285 if (!os_file_flush(slot->file)) {
04286 ut_error;
04287 }
04288 }
04289 #endif
04290 } else if (os_file_handle_error(slot->name, "Windows aio")) {
04291
04292 retry = TRUE;
04293 } else {
04294
04295 ret_val = FALSE;
04296 }
04297
04298 os_mutex_exit(array->mutex);
04299
04300 if (retry) {
04301
04302
04303
04304 #ifdef UNIV_PFS_IO
04305
04306
04307
04308 struct PSI_file_locker* locker = NULL;
04309 register_pfs_file_io_begin(locker, slot->file, slot->len,
04310 (slot->type == OS_FILE_WRITE)
04311 ? PSI_FILE_WRITE
04312 : PSI_FILE_READ,
04313 __FILE__, __LINE__);
04314 #endif
04315
04316 ut_a((slot->len & 0xFFFFFFFFUL) == slot->len);
04317
04318 switch (slot->type) {
04319 case OS_FILE_WRITE:
04320 ret = WriteFile(slot->file, slot->buf,
04321 (DWORD) slot->len, &len,
04322 &(slot->control));
04323
04324 break;
04325 case OS_FILE_READ:
04326 ret = ReadFile(slot->file, slot->buf,
04327 (DWORD) slot->len, &len,
04328 &(slot->control));
04329
04330 break;
04331 default:
04332 ut_error;
04333 }
04334
04335 #ifdef UNIV_PFS_IO
04336 register_pfs_file_io_end(locker, len);
04337 #endif
04338
04339 if (!ret && GetLastError() == ERROR_IO_PENDING) {
04340
04341
04342
04343
04344
04345
04346 ret = GetOverlappedResult(slot->file,
04347 &(slot->control),
04348 &len, TRUE);
04349 }
04350
04351 ret_val = ret && len == slot->len;
04352 }
04353
04354 os_aio_array_free_slot(array, slot);
04355
04356 return(ret_val);
04357 }
04358 #endif
04359
04360 #if defined(LINUX_NATIVE_AIO)
04361
04372 static
04373 void
04374 os_aio_linux_collect(
04375
04376 os_aio_array_t* array,
04377 ulint segment,
04378 ulint seg_size)
04379 {
04380 int i;
04381 int ret;
04382 ulint start_pos;
04383 ulint end_pos;
04384 struct timespec timeout;
04385 struct io_event* events;
04386 struct io_context* io_ctx;
04387
04388
04389 ut_ad(array != NULL);
04390 ut_ad(seg_size > 0);
04391 ut_ad(segment < array->n_segments);
04392
04393
04394 events = &array->aio_events[segment * seg_size];
04395
04396
04397 io_ctx = array->aio_ctx[segment];
04398
04399
04400 start_pos = segment * seg_size;
04401
04402
04403 end_pos = start_pos + seg_size;
04404
04405 retry:
04406
04407
04408
04409
04410
04411 if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
04412 os_thread_exit(NULL);
04413 }
04414
04415
04416
04417 memset(events, 0, sizeof(*events) * seg_size);
04418 timeout.tv_sec = 0;
04419 timeout.tv_nsec = OS_AIO_REAP_TIMEOUT;
04420
04421 ret = io_getevents(io_ctx, 1, seg_size, events, &timeout);
04422
04423
04424
04425
04426
04427
04428 if (ret == -EAGAIN) {
04429 goto retry;
04430 }
04431
04432
04433
04434
04435
04436 if (ret == -EINTR) {
04437 goto retry;
04438 }
04439
04440
04441 if (ret == 0) {
04442 goto retry;
04443 }
04444
04445
04446 if (UNIV_UNLIKELY(ret < 0)) {
04447 ut_print_timestamp(stderr);
04448 fprintf(stderr,
04449 " InnoDB: unexpected ret_code[%d] from"
04450 " io_getevents()!\n", ret);
04451 ut_error;
04452 }
04453
04454 ut_a(ret > 0);
04455
04456 for (i = 0; i < ret; i++) {
04457 os_aio_slot_t* slot;
04458 struct iocb* control;
04459
04460 control = (struct iocb *)events[i].obj;
04461 ut_a(control != NULL);
04462
04463 slot = (os_aio_slot_t *) control->data;
04464
04465
04466 ut_a(slot != NULL);
04467 ut_a(slot->reserved);
04468
04469 #if defined(UNIV_AIO_DEBUG)
04470 fprintf(stderr,
04471 "io_getevents[%c]: slot[%p] ctx[%p]"
04472 " seg[%lu]\n",
04473 (slot->type == OS_FILE_WRITE) ? 'w' : 'r',
04474 slot, io_ctx, segment);
04475 #endif
04476
04477
04478 ut_a(slot->pos >= start_pos);
04479
04480
04481 ut_a(slot->pos < end_pos);
04482
04483
04484
04485 os_mutex_enter(array->mutex);
04486 slot->n_bytes = events[i].res;
04487 slot->ret = events[i].res2;
04488 slot->io_already_done = TRUE;
04489 os_mutex_exit(array->mutex);
04490 }
04491
04492 return;
04493 }
04494
04495
04503 UNIV_INTERN
04504 ibool
04505 os_aio_linux_handle(
04506
04507 ulint global_seg,
04513 fil_node_t**message1,
04514 void** message2,
04518 ulint* type)
04519 {
04520 ulint segment;
04521 os_aio_array_t* array;
04522 os_aio_slot_t* slot;
04523 ulint n;
04524 ulint i;
04525 ibool ret = FALSE;
04526
04527
04528 ut_a(global_seg != ULINT_UNDEFINED);
04529
04530
04531 segment = os_aio_get_array_and_local_segment(&array, global_seg);
04532 n = array->n_slots / array->n_segments;
04533
04534
04535 for (;;) {
04536 os_mutex_enter(array->mutex);
04537 for (i = 0; i < n; ++i) {
04538 slot = os_aio_array_get_nth_slot(
04539 array, i + segment * n);
04540 if (slot->reserved && slot->io_already_done) {
04541
04542 goto found;
04543 }
04544 }
04545
04546 os_mutex_exit(array->mutex);
04547
04548
04549
04550
04551
04552 srv_set_io_thread_op_info(global_seg,
04553 "waiting for completed aio requests");
04554 os_aio_linux_collect(array, segment, n);
04555 }
04556
04557 found:
04558
04559
04560
04561
04562 srv_set_io_thread_op_info(global_seg,
04563 "processing completed aio requests");
04564
04565
04566 ut_a(i < n);
04567
04568 ut_ad(slot != NULL);
04569 ut_ad(slot->reserved);
04570 ut_ad(slot->io_already_done);
04571
04572 *message1 = slot->message1;
04573 *message2 = slot->message2;
04574
04575 *type = slot->type;
04576
04577 if ((slot->ret == 0) && (slot->n_bytes == (long)slot->len)) {
04578 ret = TRUE;
04579
04580 #ifdef UNIV_DO_FLUSH
04581 if (slot->type == OS_FILE_WRITE
04582 && !os_do_not_call_flush_at_each_write)
04583 && !os_file_flush(slot->file) {
04584 ut_error;
04585 }
04586 #endif
04587 } else {
04588 errno = -slot->ret;
04589
04590
04591
04592
04593
04594
04595
04596
04597 os_file_handle_error(slot->name, "Linux aio");
04598
04599 ret = FALSE;
04600 }
04601
04602 os_mutex_exit(array->mutex);
04603
04604 os_aio_array_free_slot(array, slot);
04605
04606 return(ret);
04607 }
04608 #endif
04609
04610
04614 UNIV_INTERN
04615 ibool
04616 os_aio_simulated_handle(
04617
04618 ulint global_segment,
04623 fil_node_t**message1,
04628 void** message2,
04629 ulint* type)
04630 {
04631 os_aio_array_t* array;
04632 ulint segment;
04633 os_aio_slot_t* slot;
04634 os_aio_slot_t* slot2;
04635 os_aio_slot_t* consecutive_ios[OS_AIO_MERGE_N_CONSECUTIVE];
04636 ulint n_consecutive;
04637 ulint total_len;
04638 ulint offs;
04639 ulint lowest_offset;
04640 ulint biggest_age;
04641 ulint age;
04642 byte* combined_buf;
04643 byte* combined_buf2;
04644 ibool ret;
04645 ulint n;
04646 ulint i;
04647
04648
04649 *consecutive_ios = NULL;
04650
04651 memset(consecutive_ios, 0, sizeof(os_aio_slot_t*) * OS_AIO_MERGE_N_CONSECUTIVE);
04652 segment = os_aio_get_array_and_local_segment(&array, global_segment);
04653
04654 restart:
04655
04656
04657
04658 srv_set_io_thread_op_info(global_segment,
04659 "looking for i/o requests (a)");
04660 ut_ad(os_aio_validate());
04661 ut_ad(segment < array->n_segments);
04662
04663 n = array->n_slots / array->n_segments;
04664
04665
04666
04667 if (array == os_aio_read_array
04668 && os_aio_recommend_sleep_for_read_threads) {
04669
04670
04671
04672
04673 goto recommended_sleep;
04674 }
04675
04676 os_mutex_enter(array->mutex);
04677
04678 srv_set_io_thread_op_info(global_segment,
04679 "looking for i/o requests (b)");
04680
04681
04682
04683
04684 for (i = 0; i < n; i++) {
04685 slot = os_aio_array_get_nth_slot(array, i + segment * n);
04686
04687 if (slot->reserved && slot->io_already_done) {
04688
04689 if (os_aio_print_debug) {
04690 fprintf(stderr,
04691 "InnoDB: i/o for slot %lu"
04692 " already done, returning\n",
04693 (ulong) i);
04694 }
04695
04696 ret = TRUE;
04697
04698 goto slot_io_done;
04699 }
04700 }
04701
04702 n_consecutive = 0;
04703
04704
04705
04706
04707
04708 biggest_age = 0;
04709 lowest_offset = ULINT_MAX;
04710
04711 for (i = 0; i < n; i++) {
04712 slot = os_aio_array_get_nth_slot(array, i + segment * n);
04713
04714 if (slot->reserved) {
04715 age = (ulint)difftime(time(NULL),
04716 slot->reservation_time);
04717
04718 if ((age >= 2 && age > biggest_age)
04719 || (age >= 2 && age == biggest_age
04720 && slot->offset < lowest_offset)) {
04721
04722
04723 consecutive_ios[0] = slot;
04724
04725 n_consecutive = 1;
04726
04727 biggest_age = age;
04728 lowest_offset = slot->offset;
04729 }
04730 }
04731 }
04732
04733 if (n_consecutive == 0) {
04734
04735
04736
04737
04738 lowest_offset = ULINT_MAX;
04739
04740 for (i = 0; i < n; i++) {
04741 slot = os_aio_array_get_nth_slot(array,
04742 i + segment * n);
04743
04744 if (slot->reserved && slot->offset < lowest_offset) {
04745
04746
04747 consecutive_ios[0] = slot;
04748
04749 n_consecutive = 1;
04750
04751 lowest_offset = slot->offset;
04752 }
04753 }
04754 }
04755
04756 if (n_consecutive == 0) {
04757
04758
04759
04760 goto wait_for_io;
04761 }
04762
04763
04764
04765 ut_ad(n_consecutive != 0);
04766 ut_ad(consecutive_ios[0] != NULL);
04767
04768 slot = consecutive_ios[0];
04769
04770
04771
04772 consecutive_loop:
04773 for (i = 0; i < n; i++) {
04774 slot2 = os_aio_array_get_nth_slot(array, i + segment * n);
04775
04776 if (slot2->reserved && slot2 != slot
04777 && slot2->offset == slot->offset + slot->len
04778
04779 && slot->offset + slot->len > slot->offset
04780 && slot2->offset_high == slot->offset_high
04781 && slot2->type == slot->type
04782 && slot2->file == slot->file) {
04783
04784
04785
04786 consecutive_ios[n_consecutive] = slot2;
04787 n_consecutive++;
04788
04789 slot = slot2;
04790
04791 if (n_consecutive < OS_AIO_MERGE_N_CONSECUTIVE) {
04792
04793 goto consecutive_loop;
04794 } else {
04795 break;
04796 }
04797 }
04798 }
04799
04800 srv_set_io_thread_op_info(global_segment, "consecutive i/o requests");
04801
04802
04803
04804
04805
04806 total_len = 0;
04807 slot = consecutive_ios[0];
04808
04809 for (i = 0; i < n_consecutive; i++) {
04810 total_len += consecutive_ios[i]->len;
04811 }
04812
04813 if (n_consecutive == 1) {
04814
04815 combined_buf = slot->buf;
04816 combined_buf2 = NULL;
04817 } else {
04818 combined_buf2 = static_cast<unsigned char *>(ut_malloc(total_len + UNIV_PAGE_SIZE));
04819
04820 ut_a(combined_buf2);
04821
04822 combined_buf = static_cast<unsigned char *>(ut_align(combined_buf2, UNIV_PAGE_SIZE));
04823 }
04824
04825
04826
04827
04828
04829 os_mutex_exit(array->mutex);
04830
04831 if (slot->type == OS_FILE_WRITE && n_consecutive > 1) {
04832
04833 offs = 0;
04834
04835 for (i = 0; i < n_consecutive; i++) {
04836
04837 ut_memcpy(combined_buf + offs, consecutive_ios[i]->buf,
04838 consecutive_ios[i]->len);
04839 offs += consecutive_ios[i]->len;
04840 }
04841 }
04842
04843 srv_set_io_thread_op_info(global_segment, "doing file i/o");
04844
04845 if (os_aio_print_debug) {
04846 fprintf(stderr,
04847 "InnoDB: doing i/o of type %lu at offset %lu %lu,"
04848 " length %lu\n",
04849 (ulong) slot->type, (ulong) slot->offset_high,
04850 (ulong) slot->offset, (ulong) total_len);
04851 }
04852
04853
04854 if (slot->type == OS_FILE_WRITE) {
04855 ret = os_file_write(slot->name, slot->file, combined_buf,
04856 slot->offset, slot->offset_high,
04857 total_len);
04858 } else {
04859 ret = os_file_read(slot->file, combined_buf,
04860 slot->offset, slot->offset_high, total_len);
04861 }
04862
04863 ut_a(ret);
04864 srv_set_io_thread_op_info(global_segment, "file i/o done");
04865
04866 #if 0
04867 fprintf(stderr,
04868 "aio: %lu consecutive %lu:th segment, first offs %lu blocks\n",
04869 n_consecutive, global_segment, slot->offset / UNIV_PAGE_SIZE);
04870 #endif
04871
04872 if (slot->type == OS_FILE_READ && n_consecutive > 1) {
04873
04874 offs = 0;
04875
04876 for (i = 0; i < n_consecutive; i++) {
04877
04878 ut_memcpy(consecutive_ios[i]->buf, combined_buf + offs,
04879 consecutive_ios[i]->len);
04880 offs += consecutive_ios[i]->len;
04881 }
04882 }
04883
04884 if (combined_buf2) {
04885 ut_free(combined_buf2);
04886 }
04887
04888 os_mutex_enter(array->mutex);
04889
04890
04891
04892 for (i = 0; i < n_consecutive; i++) {
04893 consecutive_ios[i]->io_already_done = TRUE;
04894 }
04895
04896
04897
04898
04899
04900 slot_io_done:
04901
04902 ut_a(slot->reserved);
04903
04904 *message1 = slot->message1;
04905 *message2 = slot->message2;
04906
04907 *type = slot->type;
04908
04909 os_mutex_exit(array->mutex);
04910
04911 os_aio_array_free_slot(array, slot);
04912
04913 return(ret);
04914
04915 wait_for_io:
04916 srv_set_io_thread_op_info(global_segment, "resetting wait event");
04917
04918
04919
04920
04921 os_event_reset(os_aio_segment_wait_events[global_segment]);
04922
04923 os_mutex_exit(array->mutex);
04924
04925 recommended_sleep:
04926 srv_set_io_thread_op_info(global_segment, "waiting for i/o request");
04927
04928 os_event_wait(os_aio_segment_wait_events[global_segment]);
04929
04930 if (os_aio_print_debug) {
04931 fprintf(stderr,
04932 "InnoDB: i/o handler thread for i/o"
04933 " segment %lu wakes up\n",
04934 (ulong) global_segment);
04935 }
04936
04937 goto restart;
04938 }
04939
04940
04943 static
04944 ibool
04945 os_aio_array_validate(
04946
04947 os_aio_array_t* array)
04948 {
04949 os_aio_slot_t* slot;
04950 ulint n_reserved = 0;
04951 ulint i;
04952
04953 ut_a(array);
04954
04955 os_mutex_enter(array->mutex);
04956
04957 ut_a(array->n_slots > 0);
04958 ut_a(array->n_segments > 0);
04959
04960 for (i = 0; i < array->n_slots; i++) {
04961 slot = os_aio_array_get_nth_slot(array, i);
04962
04963 if (slot->reserved) {
04964 n_reserved++;
04965 ut_a(slot->len > 0);
04966 }
04967 }
04968
04969 ut_a(array->n_reserved == n_reserved);
04970
04971 os_mutex_exit(array->mutex);
04972
04973 return(TRUE);
04974 }
04975
04976
04979 UNIV_INTERN
04980 ibool
04981 os_aio_validate(void)
04982
04983 {
04984 os_aio_array_validate(os_aio_read_array);
04985 os_aio_array_validate(os_aio_write_array);
04986 os_aio_array_validate(os_aio_ibuf_array);
04987 os_aio_array_validate(os_aio_log_array);
04988 os_aio_array_validate(os_aio_sync_array);
04989
04990 return(TRUE);
04991 }
04992
04993
04998 static
04999 void
05000 os_aio_print_segment_info(
05001
05002 FILE* file,
05003 ulint* n_seg,
05004 os_aio_array_t* array)
05005 {
05006 ulint i;
05007
05008 ut_ad(array);
05009 ut_ad(n_seg);
05010 ut_ad(array->n_segments > 0);
05011
05012 if (array->n_segments == 1) {
05013 return;
05014 }
05015
05016 fprintf(file, " [");
05017 for (i = 0; i < array->n_segments; i++) {
05018 if (i != 0) {
05019 fprintf(file, ", ");
05020 }
05021
05022 fprintf(file, "%lu", n_seg[i]);
05023 }
05024 fprintf(file, "] ");
05025 }
05026
05027
05029 UNIV_INTERN
05030 void
05031 os_aio_print(
05032
05033 FILE* file)
05034 {
05035 os_aio_array_t* array;
05036 os_aio_slot_t* slot;
05037 ulint n_reserved;
05038 ulint n_res_seg[SRV_MAX_N_IO_THREADS];
05039 time_t current_time;
05040 double time_elapsed;
05041 double avg_bytes_read;
05042 ulint i;
05043
05044 for (i = 0; i < srv_n_file_io_threads; i++) {
05045 fprintf(file, "I/O thread %lu state: %s (%s)", (ulong) i,
05046 srv_io_thread_op_info[i],
05047 srv_io_thread_function[i]);
05048
05049 #ifndef __WIN__
05050 if (os_aio_segment_wait_events[i]->is_set) {
05051 fprintf(file, " ev set");
05052 }
05053 #endif
05054
05055 fprintf(file, "\n");
05056 }
05057
05058 fputs("Pending normal aio reads:", file);
05059
05060 array = os_aio_read_array;
05061 loop:
05062 ut_a(array);
05063
05064 os_mutex_enter(array->mutex);
05065
05066 ut_a(array->n_slots > 0);
05067 ut_a(array->n_segments > 0);
05068
05069 n_reserved = 0;
05070
05071 memset(n_res_seg, 0x0, sizeof(n_res_seg));
05072
05073 for (i = 0; i < array->n_slots; i++) {
05074 ulint seg_no;
05075
05076 slot = os_aio_array_get_nth_slot(array, i);
05077
05078 seg_no = (i * array->n_segments) / array->n_slots;
05079 if (slot->reserved) {
05080 n_reserved++;
05081 n_res_seg[seg_no]++;
05082 #if 0
05083 fprintf(stderr, "Reserved slot, messages %p %p\n",
05084 (void*) slot->message1,
05085 (void*) slot->message2);
05086 #endif
05087 ut_a(slot->len > 0);
05088 }
05089 }
05090
05091 ut_a(array->n_reserved == n_reserved);
05092
05093 fprintf(file, " %lu", (ulong) n_reserved);
05094
05095 os_aio_print_segment_info(file, n_res_seg, array);
05096
05097 os_mutex_exit(array->mutex);
05098
05099 if (array == os_aio_read_array) {
05100 fputs(", aio writes:", file);
05101
05102 array = os_aio_write_array;
05103
05104 goto loop;
05105 }
05106
05107 if (array == os_aio_write_array) {
05108 fputs(",\n ibuf aio reads:", file);
05109 array = os_aio_ibuf_array;
05110
05111 goto loop;
05112 }
05113
05114 if (array == os_aio_ibuf_array) {
05115 fputs(", log i/o's:", file);
05116 array = os_aio_log_array;
05117
05118 goto loop;
05119 }
05120
05121 if (array == os_aio_log_array) {
05122 fputs(", sync i/o's:", file);
05123 array = os_aio_sync_array;
05124
05125 goto loop;
05126 }
05127
05128 putc('\n', file);
05129 current_time = time(NULL);
05130 time_elapsed = 0.001 + difftime(current_time, os_last_printout);
05131
05132 fprintf(file,
05133 "Pending flushes (fsync) log: %lu; buffer pool: %lu\n"
05134 "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n",
05135 (ulong) fil_n_pending_log_flushes,
05136 (ulong) fil_n_pending_tablespace_flushes,
05137 (ulong) os_n_file_reads, (ulong) os_n_file_writes,
05138 (ulong) os_n_fsyncs);
05139
05140 if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) {
05141 fprintf(file,
05142 "%lu pending preads, %lu pending pwrites\n",
05143 (ulong) os_file_n_pending_preads,
05144 (ulong) os_file_n_pending_pwrites);
05145 }
05146
05147 if (os_n_file_reads == os_n_file_reads_old) {
05148 avg_bytes_read = 0.0;
05149 } else {
05150 avg_bytes_read = (double) os_bytes_read_since_printout
05151 / (os_n_file_reads - os_n_file_reads_old);
05152 }
05153
05154 fprintf(file,
05155 "%.2f reads/s, %lu avg bytes/read,"
05156 " %.2f writes/s, %.2f fsyncs/s\n",
05157 (os_n_file_reads - os_n_file_reads_old)
05158 / time_elapsed,
05159 (ulong)avg_bytes_read,
05160 (os_n_file_writes - os_n_file_writes_old)
05161 / time_elapsed,
05162 (os_n_fsyncs - os_n_fsyncs_old)
05163 / time_elapsed);
05164
05165 os_n_file_reads_old = os_n_file_reads;
05166 os_n_file_writes_old = os_n_file_writes;
05167 os_n_fsyncs_old = os_n_fsyncs;
05168 os_bytes_read_since_printout = 0;
05169
05170 os_last_printout = current_time;
05171 }
05172
05173
05175 UNIV_INTERN
05176 void
05177 os_aio_refresh_stats(void)
05178
05179 {
05180 os_n_file_reads_old = os_n_file_reads;
05181 os_n_file_writes_old = os_n_file_writes;
05182 os_n_fsyncs_old = os_n_fsyncs;
05183 os_bytes_read_since_printout = 0;
05184
05185 os_last_printout = time(NULL);
05186 }
05187
05188 #ifdef UNIV_DEBUG
05189
05193 UNIV_INTERN
05194 ibool
05195 os_aio_all_slots_free(void)
05196
05197 {
05198 os_aio_array_t* array;
05199 ulint n_res = 0;
05200
05201 array = os_aio_read_array;
05202
05203 os_mutex_enter(array->mutex);
05204
05205 n_res += array->n_reserved;
05206
05207 os_mutex_exit(array->mutex);
05208
05209 array = os_aio_write_array;
05210
05211 os_mutex_enter(array->mutex);
05212
05213 n_res += array->n_reserved;
05214
05215 os_mutex_exit(array->mutex);
05216
05217 array = os_aio_ibuf_array;
05218
05219 os_mutex_enter(array->mutex);
05220
05221 n_res += array->n_reserved;
05222
05223 os_mutex_exit(array->mutex);
05224
05225 array = os_aio_log_array;
05226
05227 os_mutex_enter(array->mutex);
05228
05229 n_res += array->n_reserved;
05230
05231 os_mutex_exit(array->mutex);
05232
05233 array = os_aio_sync_array;
05234
05235 os_mutex_enter(array->mutex);
05236
05237 n_res += array->n_reserved;
05238
05239 os_mutex_exit(array->mutex);
05240
05241 if (n_res == 0) {
05242
05243 return(TRUE);
05244 }
05245
05246 return(FALSE);
05247 }
05248 #endif
05249
05250 #endif