summaryrefslogtreecommitdiff
path: root/innobase/os/os0file.c
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-08-11 22:44:43 +0300
committerunknown <monty@mashka.mysql.fi>2003-08-11 22:44:43 +0300
commit034b44cb9ff914ceb6d32706a3a284eda00891b3 (patch)
tree3c0ddcb446b8be099c3ab2616c459a573ee3cf92 /innobase/os/os0file.c
parentf4646c0d063fb541f48dd2824ecccea464a9958d (diff)
parent6db21de014d603477952c7a16449bcae40a70e5c (diff)
downloadmariadb-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.c383
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 {