diff options
author | unknown <monty@mashka.mysql.fi> | 2003-08-11 22:44:43 +0300 |
---|---|---|
committer | unknown <monty@mashka.mysql.fi> | 2003-08-11 22:44:43 +0300 |
commit | 034b44cb9ff914ceb6d32706a3a284eda00891b3 (patch) | |
tree | 3c0ddcb446b8be099c3ab2616c459a573ee3cf92 /innobase/os/os0file.c | |
parent | f4646c0d063fb541f48dd2824ecccea464a9958d (diff) | |
parent | 6db21de014d603477952c7a16449bcae40a70e5c (diff) | |
download | mariadb-git-034b44cb9ff914ceb6d32706a3a284eda00891b3.tar.gz |
Merge with 4.0.14
BitKeeper/etc/logging_ok:
auto-union
scripts/make_win_src_distribution.old:
Merge rename: scripts/make_win_src_distribution.sh -> scripts/make_win_src_distribution.old
BUILD/compile-pentium-debug-max:
Auto merged
BitKeeper/deleted/.del-sel000001.result~383913ae4505ec86:
Auto merged
BitKeeper/deleted/.del-sel000001.test~9567c1646058cc:
Auto merged
Build-tools/Bootstrap:
Auto merged
Build-tools/Do-compile:
Auto merged
Docs/Makefile.am:
Auto merged
client/get_password.c:
Auto merged
client/mysql.cc:
Auto merged
client/mysqltest.c:
Auto merged
extra/perror.c:
Auto merged
include/config-win.h:
Auto merged
include/my_sys.h:
Auto merged
innobase/btr/btr0cur.c:
Auto merged
innobase/btr/btr0pcur.c:
Auto merged
innobase/buf/buf0buf.c:
Auto merged
innobase/buf/buf0flu.c:
Auto merged
innobase/dict/dict0dict.c:
Auto merged
innobase/dict/dict0load.c:
Auto merged
innobase/include/buf0buf.h:
Auto merged
innobase/include/log0recv.h:
Auto merged
innobase/include/row0sel.h:
Auto merged
innobase/include/srv0srv.h:
Auto merged
innobase/include/ut0mem.h:
Auto merged
innobase/lock/lock0lock.c:
Auto merged
innobase/log/log0log.c:
Auto merged
innobase/mem/mem0pool.c:
Auto merged
innobase/os/os0file.c:
Auto merged
innobase/row/row0mysql.c:
Auto merged
innobase/row/row0sel.c:
Auto merged
innobase/srv/srv0srv.c:
Auto merged
innobase/srv/srv0start.c:
Auto merged
innobase/trx/trx0sys.c:
Auto merged
innobase/trx/trx0trx.c:
Auto merged
innobase/ut/ut0mem.c:
Auto merged
innobase/ut/ut0ut.c:
Auto merged
myisam/ft_boolean_search.c:
Auto merged
myisam/mi_check.c:
Auto merged
myisam/mi_extra.c:
Auto merged
myisam/mi_key.c:
Auto merged
myisam/myisamdef.h:
Auto merged
myisammrg/myrg_queue.c:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/r/ctype_latin1_de.result:
Auto merged
mysql-test/r/flush.result:
Auto merged
mysql-test/r/func_time.result:
Auto merged
mysql-test/r/grant_cache.result:
Auto merged
mysql-test/r/join.result:
Auto merged
mysql-test/r/join_outer.result:
Auto merged
mysql-test/r/range.result:
Auto merged
mysql-test/r/rpl000018.result:
Auto merged
mysql-test/r/rpl_insert_id.result:
Auto merged
mysql-test/r/rpl_master_pos_wait.result:
Auto merged
mysql-test/r/rpl_relayspace.result:
Auto merged
mysql-test/r/select_safe.result:
Auto merged
mysql-test/r/symlink.result:
Auto merged
mysql-test/r/type_date.result:
Auto merged
mysql-test/r/type_datetime.result:
Auto merged
mysql-test/t/alias.test:
Auto merged
mysql-test/t/ctype_latin1_de.test:
Auto merged
mysql-test/t/fulltext_left_join.test:
Auto merged
mysql-test/t/func_time.test:
Auto merged
mysql-test/t/handler.test:
Auto merged
mysql-test/t/heap.test:
Auto merged
mysql-test/t/join.test:
Auto merged
mysql-test/t/join_outer.test:
Auto merged
mysql-test/t/order_by.test:
Auto merged
mysql-test/t/range.test:
Auto merged
mysql-test/t/rpl000001.test:
Auto merged
mysql-test/t/rpl000018.test:
Auto merged
mysql-test/t/rpl_insert_id.test:
Auto merged
mysql-test/t/sel000100.test:
Auto merged
mysql-test/t/select_safe.test:
Auto merged
mysql-test/t/type_date.test:
Auto merged
mysql-test/t/type_datetime.test:
Auto merged
mysql-test/t/user_var.test:
Auto merged
mysys/default.c:
Auto merged
mysys/mf_format.c:
Auto merged
mysys/my_getopt.c:
Auto merged
mysys/thr_lock.c:
Auto merged
mysys/tree.c:
Auto merged
scripts/Makefile.am:
Auto merged
scripts/mysql_install_db.sh:
Auto merged
scripts/mysqld_safe.sh:
Auto merged
sql/Makefile.am:
Auto merged
sql/field_conv.cc:
Auto merged
sql/ha_innodb.h:
Auto merged
sql/ha_myisam.cc:
Auto merged
sql/ha_myisammrg.h:
Auto merged
sql/handler.cc:
Auto merged
sql/handler.h:
Auto merged
sql/item.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_timefunc.cc:
Auto merged
sql/net_serv.cc:
Auto merged
sql/nt_servc.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_cache.h:
Auto merged
sql/sql_db.cc:
Auto merged
sql/sql_delete.cc:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_list.h:
Auto merged
sql/sql_load.cc:
Auto merged
sql/sql_rename.cc:
Auto merged
sql/sql_repl.h:
Auto merged
sql/sql_update.cc:
Auto merged
sql/table.cc:
Auto merged
sql/table.h:
Auto merged
sql/uniques.cc:
Auto merged
support-files/mysql.spec.sh:
Auto merged
vio/viosocket.c:
Auto merged
BitKeeper/deleted/.del-ctype-latin1_de.c~c5d8f9208bceb98e:
merge
BitKeeper/deleted/.del-mini_client.cc~8677895ec8169183:
merge
acinclude.m4:
Merge with 4.0 (openssl patch)
client/mysqlbinlog.cc:
Merge with 4.0 in which we had added code from 4.1
(We are basicly only using the 4.1 code here)
configure.in:
Keep 4.1 file
heap/hp_open.c:
merge with 4.0
include/my_base.h:
merge with 4.0
include/my_global.h:
merge with 4.0
include/mysqld_error.h:
merge with 4.0
innobase/ha/ha0ha.c:
merge with 4.0
(Code should be same but we use indentaion from 4.0)
innobase/log/log0recv.c:
merge with 4.0
libmysql/libmysql.c:
Remove with 4.0 code that was ported from 4.1
libmysqld/lib_sql.cc:
merge with 4.0
myisam/mi_open.c:
Remove 4.0 specific code
myisam/myisamchk.c:
merge with 4.0
myisammrg/myrg_rkey.c:
merge with 4.0
mysql-test/r/alter_table.result:
May need to be fixed after merge
mysql-test/r/create.result:
May need to be fixed after merge
mysql-test/r/distinct.result:
May need to be fixed after merge
mysql-test/r/drop.result:
May need to be fixed after merge
mysql-test/r/fulltext.result:
May need to be fixed after merge
mysql-test/r/func_set.result:
May need to be fixed after merge
mysql-test/r/func_str.result:
May need to be fixed after merge
mysql-test/r/func_test.result:
May need to be fixed after merge
mysql-test/r/grant.result:
May need to be fixed after merge
mysql-test/r/group_by.result:
May need to be fixed after merge
mysql-test/r/handler.result:
May need to be fixed after merge
mysql-test/r/heap.result:
May need to be fixed after merge
mysql-test/r/innodb.result:
May need to be fixed after merge
mysql-test/r/insert.result:
May need to be fixed after merge
mysql-test/r/insert_select.result:
May need to be fixed after merge
mysql-test/r/key_diff.result:
May need to be fixed after merge
mysql-test/r/merge.result:
May need to be fixed after merge
mysql-test/r/myisam.result:
May need to be fixed after merge
mysql-test/r/order_by.result:
May need to be fixed after merge
mysql-test/r/query_cache.result:
May need to be fixed after merge
mysql-test/r/rpl_flush_log_loop.result:
May need to be fixed after merge
mysql-test/r/rpl_loaddata.result:
May need to be fixed after merge
mysql-test/r/rpl_log.result:
May need to be fixed after merge
mysql-test/r/rpl_log_pos.result:
May need to be fixed after merge
mysql-test/r/rpl_rotate_logs.result:
May need to be fixed after merge
mysql-test/r/select.result:
May need to be fixed after merge
mysql-test/r/union.result:
May need to be fixed after merge
mysql-test/r/user_var.result:
May need to be fixed after merge
mysql-test/t/alter_table.test:
merge with 4.0
mysql-test/t/create.test:
merge with 4.0
mysql-test/t/distinct.test:
merge with 4.0
mysql-test/t/drop.test:
merge with 4.0
mysql-test/t/flush.test:
merge with 4.0
mysql-test/t/fulltext.test:
merge with 4.0
mysql-test/t/func_set.test:
merge with 4.0
mysql-test/t/func_str.test:
merge with 4.0
mysql-test/t/func_test.test:
merge with 4.0
mysql-test/t/grant.test:
merge with 4.0
mysql-test/t/grant_cache.test:
merge with 4.0
mysql-test/t/innodb.test:
Add back EXPLAIN and SHOW KEYS statements, but make them independent of number of rows returned by InnoDB
mysql-test/t/insert.test:
merge with 4.0
mysql-test/t/insert_select.test:
merge with 4.0
mysql-test/t/merge.test:
merge with 4.0
mysql-test/t/query_cache.test:
merge with 4.0
mysql-test/t/rpl_flush_log_loop.test:
merge with 4.0
mysql-test/t/rpl_loaddata.test:
merge with 4.0
mysql-test/t/rpl_rotate_logs.test:
merge with 4.0
mysql-test/t/select.test:
merge with 4.0
mysql-test/t/symlink.test:
merge with 4.0
mysql-test/t/union.test:
merge with 4.0
mysys/charset.c:
merge with 4.0
scripts/mysql_fix_privilege_tables.sh:
merge with 4.0 (Add quoting for some variables)
sql/field.h:
merge with 4.0
sql/ha_innodb.cc:
merge with 4.0
sql/item_cmpfunc.cc:
merge with 4.0
sql/item_cmpfunc.h:
merge with 4.0
sql/item_func.h:
merge with 4.0
sql/item_strfunc.cc:
merge with 4.0
Fixed null handling with ELT()
sql/item_timefunc.h:
merge with 4.0
sql/lex.h:
merge with 4.0
sql/log.cc:
merge with 4.0
sql/log_event.cc:
Merge with 4.0
Cleanups:
- Indentation
- #endif comments
- Replace strmov() with *pos++= for two byte strings
- Moved variable declarations to start of functions
- Merged identical code (LOAD_EVENT)
- Added casts when subtracting pointers
Did a full diff between this and 4.0 to ensure that the file is correct after merge.
sql/log_event.h:
merge with 4.0
sql/mysql_priv.h:
merge with 4.0
sql/mysqld.cc:
merge with 4.0
sql/repl_failsafe.cc:
merge with 4.0
sql/set_var.cc:
merge with 4.0
sql/set_var.h:
merge with 4.0
sql/share/czech/errmsg.txt:
merge with 4.0
sql/share/danish/errmsg.txt:
merge with 4.0
sql/share/dutch/errmsg.txt:
merge with 4.0
sql/share/english/errmsg.txt:
merge with 4.0
sql/share/estonian/errmsg.txt:
merge with 4.0
sql/share/french/errmsg.txt:
merge with 4.0
sql/share/german/errmsg.txt:
merge with 4.0
sql/share/greek/errmsg.txt:
merge with 4.0
sql/share/hungarian/errmsg.txt:
merge with 4.0
sql/share/italian/errmsg.txt:
merge with 4.0
sql/share/japanese/errmsg.txt:
merge with 4.0
sql/share/korean/errmsg.txt:
merge with 4.0
sql/share/norwegian-ny/errmsg.txt:
merge with 4.0
sql/share/norwegian/errmsg.txt:
merge with 4.0
sql/share/polish/errmsg.txt:
merge with 4.0
sql/share/portuguese/errmsg.txt:
merge with 4.0
sql/share/romanian/errmsg.txt:
merge with 4.0
sql/share/russian/errmsg.txt:
merge with 4.0
sql/share/slovak/errmsg.txt:
merge with 4.0
sql/share/spanish/errmsg.txt:
merge with 4.0
sql/share/swedish/errmsg.txt:
merge with 4.0
sql/share/ukrainian/errmsg.txt:
merge with 4.0
sql/slave.cc:
Merge + some indentation fixes
sql/slave.h:
merge with 4.0
sql/sql_acl.cc:
merge with 4.0
Some end space removal to make it easier to do future merges
sql/sql_acl.h:
merge with 4.0
sql/sql_cache.cc:
merge with 4.0
sql/sql_class.h:
merge with 4.0
sql/sql_handler.cc:
merge with 4.0
sql/sql_lex.cc:
merge with 4.0
sql/sql_lex.h:
merge with 4.0
sql/sql_parse.cc:
merge with 4.0
sql/sql_repl.cc:
merge with 4.0
sql/sql_select.cc:
merge with 4.0
sql/sql_table.cc:
merge with 4.0
sql/sql_union.cc:
Merge with 4.0
Note that I couldn't find out how to merge OPTION_FOUND_ROWS handling so this has to be fixed later
sql/sql_yacc.yy:
merge with 4.0
Removed end space to make merge easier
vio/Makefile.am:
merge with 4.0
Diffstat (limited to 'innobase/os/os0file.c')
-rw-r--r-- | innobase/os/os0file.c | 383 |
1 files changed, 330 insertions, 53 deletions
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index e401503c4e3..e31fd1d9efe 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -60,6 +60,7 @@ struct os_aio_slot_struct{ ulint pos; /* index of the slot in the aio array */ ibool reserved; /* TRUE if this slot is reserved */ + time_t reservation_time;/* time when reserved */ ulint len; /* length of the block to read or write */ byte* buf; /* buffer used in i/o */ @@ -147,6 +148,12 @@ time_t os_last_printout; ibool os_has_said_disk_full = FALSE; +/* The mutex protecting the following counts of pending pread and pwrite +operations */ +os_mutex_t os_file_count_mutex; +ulint os_file_n_pending_preads = 0; +ulint os_file_n_pending_pwrites = 0; + /*************************************************************************** Gets the operating system version. Currently works only on Windows. */ @@ -204,9 +211,9 @@ os_file_get_last_error(void) if (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS) { ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Operating system error number %li in a file operation.\n" + " InnoDB: Operating system error number %lu in a file operation.\n" "InnoDB: See http://www.innodb.com/ibman.html for installation help.\n", - (long) err); + err); if (err == ERROR_PATH_NOT_FOUND) { fprintf(stderr, @@ -248,9 +255,9 @@ os_file_get_last_error(void) ut_print_timestamp(stderr); fprintf(stderr, - " InnoDB: Operating system error number %li in a file operation.\n" + " InnoDB: Operating system error number %lu in a file operation.\n" "InnoDB: See http://www.innodb.com/ibman.html for installation help.\n", - (long) err); + err); if (err == ENOENT) { fprintf(stderr, @@ -344,7 +351,8 @@ os_file_handle_error( fprintf(stderr, "InnoDB: File name %s\n", name); } - fprintf(stderr, "InnoDB: System call %s.\n", operation); + fprintf(stderr, "InnoDB: File operation call: '%s'.\n", + operation); fprintf(stderr, "InnoDB: Cannot continue operation.\n"); fflush(stderr); @@ -364,6 +372,8 @@ os_io_init_simple(void) { ulint i; + os_file_count_mutex = os_mutex_create(NULL); + for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) { os_file_seek_mutexes[i] = os_mutex_create(NULL); } @@ -415,9 +425,8 @@ try_again: file = CreateFile(name, access, - FILE_SHARE_READ | FILE_SHARE_WRITE, - /* file can be read and written - also by other processes */ + FILE_SHARE_READ,/* file can be read also by other + processes */ NULL, /* default security attributes */ create_flag, attributes, @@ -481,6 +490,101 @@ try_again: return(file); #endif } + +/******************************************************************** +A simple function to open or create a file. */ + +os_file_t +os_file_create_simple_no_error_handling( +/*====================================*/ + /* out, own: handle to the file, not defined if error, + error number can be retrieved with os_get_last_error */ + char* name, /* in: name of the file or path as a null-terminated + string */ + ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened + (if does not exist, error), or OS_FILE_CREATE if a new + file is created (if exists, error) */ + ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */ + ibool* success)/* out: TRUE if succeed, FALSE if error */ +{ +#ifdef __WIN__ + os_file_t file; + DWORD create_flag; + DWORD access; + DWORD attributes = 0; + + ut_a(name); + + if (create_mode == OS_FILE_OPEN) { + create_flag = OPEN_EXISTING; + } else if (create_mode == OS_FILE_CREATE) { + create_flag = CREATE_NEW; + } else { + create_flag = 0; + ut_error; + } + + if (access_type == OS_FILE_READ_ONLY) { + access = GENERIC_READ; + } else if (access_type == OS_FILE_READ_WRITE) { + access = GENERIC_READ | GENERIC_WRITE; + } else { + access = 0; + ut_error; + } + + file = CreateFile(name, + access, + FILE_SHARE_READ,/* file can be read also by other + processes */ + NULL, /* default security attributes */ + create_flag, + attributes, + NULL); /* no template file */ + + if (file == INVALID_HANDLE_VALUE) { + *success = FALSE; + } else { + *success = TRUE; + } + + return(file); +#else + os_file_t file; + int create_flag; + + ut_a(name); + + if (create_mode == OS_FILE_OPEN) { + if (access_type == OS_FILE_READ_ONLY) { + create_flag = O_RDONLY; + } else { + create_flag = O_RDWR; + } + } else if (create_mode == OS_FILE_CREATE) { + create_flag = O_RDWR | O_CREAT | O_EXCL; + } else { + create_flag = 0; + ut_error; + } + + if (create_mode == OS_FILE_CREATE) { + file = open(name, create_flag, S_IRUSR | S_IWUSR + | S_IRGRP | S_IWGRP); + } else { + file = open(name, create_flag); + } + + if (file == -1) { + *success = FALSE; + } else { + *success = TRUE; + } + + return(file); +#endif +} + /******************************************************************** Opens an existing file or creates a new. */ @@ -496,7 +600,11 @@ os_file_create( file is created (if exists, error), OS_FILE_OVERWRITE if a new is created or an old overwritten */ ulint purpose,/* in: OS_FILE_AIO, if asynchronous, non-buffered i/o - is desired, OS_FILE_NORMAL, if any normal file */ + is desired, OS_FILE_NORMAL, if any normal file; + NOTE that it also depends on type, os_aio_.. and srv_.. + variables whether we really use async i/o or + unbuffered i/o: look in the function source code for + the exact rules */ ulint type, /* in: OS_DATA_FILE or OS_LOG_FILE */ ibool* success)/* out: TRUE if succeed, FALSE if error */ { @@ -521,8 +629,8 @@ try_again: } if (purpose == OS_FILE_AIO) { - /* use asynchronous (overlapped) io and no buffering - of writes in the OS */ + /* If specified, use asynchronous (overlapped) io and no + buffering of writes in the OS */ attributes = 0; #ifdef WIN_ASYNC_IO if (os_aio_use_native_aio) { @@ -530,17 +638,13 @@ try_again: } #endif #ifdef UNIV_NON_BUFFERED_IO - if (type == OS_LOG_FILE) { + if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) { /* Do not use unbuffered i/o to log files because - to allow group commit to work when MySQL binlogging - is used we must separate log file write and log - file flush to disk. */ - } else { - if (srv_win_file_flush_method == - SRV_WIN_IO_UNBUFFERED) { - attributes = attributes - | FILE_FLAG_NO_BUFFERING; - } + value 2 denotes that we do not flush the log at every + commit, but only once per second */ + } else if (srv_win_file_flush_method == + SRV_WIN_IO_UNBUFFERED) { + attributes = attributes | FILE_FLAG_NO_BUFFERING; } #endif } else if (purpose == OS_FILE_NORMAL) { @@ -550,12 +654,9 @@ try_again: /* Do not use unbuffered i/o to log files because value 2 denotes that we do not flush the log at every commit, but only once per second */ - } else { - if (srv_win_file_flush_method == - SRV_WIN_IO_UNBUFFERED) { - attributes = attributes - | FILE_FLAG_NO_BUFFERING; - } + } else if (srv_win_file_flush_method == + SRV_WIN_IO_UNBUFFERED) { + attributes = attributes | FILE_FLAG_NO_BUFFERING; } #endif } else { @@ -566,9 +667,14 @@ try_again: file = CreateFile(name, GENERIC_READ | GENERIC_WRITE, /* read and write access */ - FILE_SHARE_READ | FILE_SHARE_WRITE, - /* file can be read and written - also by other processes */ + FILE_SHARE_READ,/* File can be read also by other + processes; we must give the read + permission because of ibbackup. We do + not give the write permission to + others because if one would succeed to + start 2 instances of mysqld on the + SAME files, that could cause severe + database corruption! */ NULL, /* default security attributes */ create_flag, attributes, @@ -592,30 +698,70 @@ try_again: os_file_t file; int create_flag; ibool retry; + const char* mode_str = NULL; + const char* type_str = NULL; + const char* purpose_str = NULL; try_again: ut_a(name); if (create_mode == OS_FILE_OPEN) { + mode_str = "OPEN"; + create_flag = O_RDWR; } else if (create_mode == OS_FILE_CREATE) { + mode_str = "CREATE"; + create_flag = O_RDWR | O_CREAT | O_EXCL; } else if (create_mode == OS_FILE_OVERWRITE) { + mode_str = "OVERWRITE"; + create_flag = O_RDWR | O_CREAT | O_TRUNC; } else { create_flag = 0; ut_error; } - UT_NOT_USED(purpose); + if (type == OS_LOG_FILE) { + type_str = "LOG"; + } else if (type == OS_DATA_FILE) { + type_str = "DATA"; + } else { + ut_a(0); + } + + if (purpose == OS_FILE_AIO) { + purpose_str = "AIO"; + } else if (purpose == OS_FILE_NORMAL) { + purpose_str = "NORMAL"; + } else { + ut_a(0); + } +/* printf("Opening file %s, mode %s, type %s, purpose %s\n", + name, mode_str, type_str, purpose_str); */ #ifdef O_SYNC - if ((!srv_use_doublewrite_buf || type != OS_DATA_FILE) + /* We let O_SYNC only affect log files; note that we map O_DSYNC to + O_SYNC because the datasync options seemed to corrupt files in 2001 + in both Linux and Solaris */ + if (type == OS_LOG_FILE && srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) { +/* printf("Using O_SYNC for file %s\n", name); */ + create_flag = create_flag | O_SYNC; } #endif +#ifdef O_DIRECT + /* We let O_DIRECT only affect data files */ + if (type != OS_LOG_FILE + && srv_unix_file_flush_method == SRV_UNIX_O_DIRECT) { + +/* printf("Using O_DIRECT for file %s\n", name); */ + + create_flag = create_flag | O_DIRECT; + } +#endif if (create_mode == OS_FILE_CREATE) { file = open(name, create_flag, os_innodb_umask); } else { @@ -677,6 +823,41 @@ os_file_close( } /*************************************************************************** +Closes a file handle. */ + +ibool +os_file_close_no_error_handling( +/*============================*/ + /* out: TRUE if success */ + os_file_t file) /* in, own: handle to a file */ +{ +#ifdef __WIN__ + BOOL ret; + + ut_a(file); + + ret = CloseHandle(file); + + if (ret) { + return(TRUE); + } + + return(FALSE); +#else + int ret; + + ret = close(file); + + if (ret == -1) { + + return(FALSE); + } + + return(TRUE); +#endif +} + +/*************************************************************************** Gets a file size. */ ibool @@ -849,6 +1030,7 @@ os_file_flush( #ifdef HAVE_FDATASYNC ret = fdatasync(file); #else +/* printf("Flushing to file %lu\n", (ulint)file); */ ret = fsync(file); #endif os_n_fsyncs++; @@ -896,6 +1078,7 @@ os_file_pread( offset */ { off_t offs; + ssize_t n_bytes; ut_a((offset & 0xFFFFFFFF) == offset); @@ -917,7 +1100,17 @@ os_file_pread( os_n_file_reads++; #ifdef HAVE_PREAD - return(pread(file, buf, n, offs)); + os_mutex_enter(os_file_count_mutex); + os_file_n_pending_preads++; + os_mutex_exit(os_file_count_mutex); + + n_bytes = pread(file, buf, n, offs); + + os_mutex_enter(os_file_count_mutex); + os_file_n_pending_preads--; + os_mutex_exit(os_file_count_mutex); + + return(n_bytes); #else { ssize_t ret; @@ -982,8 +1175,16 @@ os_file_pwrite( os_n_file_writes++; #ifdef HAVE_PWRITE + os_mutex_enter(os_file_count_mutex); + os_file_n_pending_pwrites++; + os_mutex_exit(os_file_count_mutex); + ret = pwrite(file, buf, n, offs); + os_mutex_enter(os_file_count_mutex); + os_file_n_pending_pwrites--; + os_mutex_exit(os_file_count_mutex); + if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC && !os_do_not_call_flush_at_each_write) { @@ -1157,6 +1358,7 @@ os_file_write( DWORD high; ulint i; ulint n_retries = 0; + ulint err; ut_a((offset & 0xFFFFFFFF) == offset); @@ -1224,18 +1426,27 @@ retry: if (!os_has_said_disk_full) { + err = (ulint)GetLastError(); + ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: Write to file %s failed at offset %lu %lu.\n" "InnoDB: %lu bytes should have been written, only %lu were written.\n" "InnoDB: Operating system error number %lu.\n" -"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" -"InnoDB: what the error number means.\n" "InnoDB: Check that your OS and file system support files of this size.\n" "InnoDB: Check also that the disk is not full or a disk quota exceeded.\n", name, offset_high, offset, n, (ulint)len, - (ulint)GetLastError()); + err); + + if (strerror((int)err) != NULL) { + fprintf(stderr, +"InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err)); + } + + fprintf(stderr, +"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n" +"InnoDB: about operating system error numbers.\n"); os_has_said_disk_full = TRUE; } @@ -1259,12 +1470,19 @@ retry: " InnoDB: Error: Write to file %s failed at offset %lu %lu.\n" "InnoDB: %lu bytes should have been written, only %ld were written.\n" "InnoDB: Operating system error number %lu.\n" -"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" -"InnoDB: what the error number means or use the perror program of MySQL.\n" "InnoDB: Check that your OS and file system support files of this size.\n" "InnoDB: Check also that the disk is not full or a disk quota exceeded.\n", name, offset_high, offset, n, (long int)ret, (ulint)errno); + if (strerror(errno) != NULL) { + fprintf(stderr, +"InnoDB: Error number %lu means '%s'.\n", (ulint)errno, strerror(errno)); + } + + fprintf(stderr, +"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n" +"InnoDB: about operating system error numbers.\n"); + os_has_said_disk_full = TRUE; } @@ -1372,19 +1590,35 @@ os_aio_init( os_io_init_simple(); + for (i = 0; i < n_segments; i++) { + srv_io_thread_op_info[i] = (char*)"not started yet"; + } + n_per_seg = n / n_segments; n_write_segs = (n_segments - 2) / 2; n_read_segs = n_segments - 2 - n_write_segs; /* printf("Array n per seg %lu\n", n_per_seg); */ + os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1); + + srv_io_thread_function[0] = (char*)"insert buffer thread"; + + os_aio_log_array = os_aio_array_create(n_per_seg, 1); + + srv_io_thread_function[1] = (char*)"log thread"; + os_aio_read_array = os_aio_array_create(n_read_segs * n_per_seg, n_read_segs); + for (i = 2; i < 2 + n_read_segs; i++) { + srv_io_thread_function[i] = (char*)"read thread"; + } + os_aio_write_array = os_aio_array_create(n_write_segs * n_per_seg, n_write_segs); - os_aio_ibuf_array = os_aio_array_create(n_per_seg, 1); - - os_aio_log_array = os_aio_array_create(n_per_seg, 1); + for (i = 2 + n_read_segs; i < n_segments; i++) { + srv_io_thread_function[i] = (char*)"write thread"; + } os_aio_sync_array = os_aio_array_create(n_slots_sync, 1); @@ -1677,6 +1911,7 @@ loop: } slot->reserved = TRUE; + slot->reservation_time = time(NULL); slot->message1 = message1; slot->message2 = message2; slot->file = file; @@ -2249,6 +2484,8 @@ os_aio_simulated_handle( ulint total_len; ulint offs; ulint lowest_offset; + ulint biggest_age; + ulint age; byte* combined_buf; byte* combined_buf2; ibool ret; @@ -2301,22 +2538,55 @@ restart: n_consecutive = 0; - /* Look for an i/o request at the lowest offset in the array - (we ignore the high 32 bits of the offset in these heuristics) */ + /* If there are at least 2 seconds old requests, then pick the oldest + one to prevent starvation. If several requests have the same age, + then pick the one at the lowest offset. */ + biggest_age = 0; lowest_offset = ULINT_MAX; - + for (i = 0; i < n; i++) { slot = os_aio_array_get_nth_slot(array, i + segment * n); - if (slot->reserved && slot->offset < lowest_offset) { + if (slot->reserved) { + age = (ulint)difftime(time(NULL), + slot->reservation_time); - /* Found an i/o request */ - consecutive_ios[0] = slot; + if ((age >= 2 && age > biggest_age) + || (age >= 2 && age == biggest_age + && slot->offset < lowest_offset)) { - n_consecutive = 1; + /* Found an i/o request */ + consecutive_ios[0] = slot; - lowest_offset = slot->offset; + n_consecutive = 1; + + biggest_age = age; + lowest_offset = slot->offset; + } + } + } + + if (n_consecutive == 0) { + /* There were no old requests. Look for an i/o request at the + lowest offset in the array (we ignore the high 32 bits of the + offset in these heuristics) */ + + lowest_offset = ULINT_MAX; + + for (i = 0; i < n; i++) { + slot = os_aio_array_get_nth_slot(array, + i + segment * n); + + if (slot->reserved && slot->offset < lowest_offset) { + + /* Found an i/o request */ + consecutive_ios[0] = slot; + + n_consecutive = 1; + + lowest_offset = slot->offset; + } } } @@ -2422,7 +2692,7 @@ consecutive_loop: + FIL_PAGE_LSN + 4) != mach_read_from_4(combined_buf + len2 + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN + 4)) { + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: ERROR: The page to be written seems corrupt!\n"); @@ -2583,14 +2853,15 @@ os_aio_print( double avg_bytes_read; ulint i; - if (buf_end - buf < 1000) { + if (buf_end - buf < 1200) { return; } for (i = 0; i < srv_n_file_io_threads; i++) { - buf += sprintf(buf, "I/O thread %lu state: %s\n", i, - srv_io_thread_op_info[i]); + buf += sprintf(buf, "I/O thread %lu state: %s (%s)\n", i, + srv_io_thread_op_info[i], + srv_io_thread_function[i]); } buf += sprintf(buf, "Pending normal aio reads:"); @@ -2665,6 +2936,12 @@ loop: "%lu OS file reads, %lu OS file writes, %lu OS fsyncs\n", os_n_file_reads, os_n_file_writes, os_n_fsyncs); + if (os_file_n_pending_preads != 0 || os_file_n_pending_pwrites != 0) { + buf += sprintf(buf, + "%lu pending preads, %lu pending pwrites\n", + os_file_n_pending_preads, os_file_n_pending_pwrites); + } + if (os_n_file_reads == os_n_file_reads_old) { avg_bytes_read = 0.0; } else { |