diff options
author | unknown <heikki@hundin.mysql.fi> | 2002-03-21 18:03:09 +0200 |
---|---|---|
committer | unknown <heikki@hundin.mysql.fi> | 2002-03-21 18:03:09 +0200 |
commit | d3c0752b6aec6afef1f0dba85c9a0f1237843e6d (patch) | |
tree | 8484c3bb65d40af0743b44a24a788dc2d5cf7d48 /innobase/os | |
parent | 838c6427b278a016f968338468761dabcfecba29 (diff) | |
download | mariadb-git-d3c0752b6aec6afef1f0dba85c9a0f1237843e6d.tar.gz |
Many files:
Merge InnoDB-3.23.50
innobase/btr/btr0btr.c:
Merge InnoDB-3.23.50
innobase/btr/btr0cur.c:
Merge InnoDB-3.23.50
innobase/btr/btr0sea.c:
Merge InnoDB-3.23.50
innobase/buf/buf0buf.c:
Merge InnoDB-3.23.50
innobase/buf/buf0flu.c:
Merge InnoDB-3.23.50
innobase/dict/dict0dict.c:
Merge InnoDB-3.23.50
innobase/dict/dict0load.c:
Merge InnoDB-3.23.50
innobase/fil/fil0fil.c:
Merge InnoDB-3.23.50
innobase/fsp/fsp0fsp.c:
Merge InnoDB-3.23.50
innobase/include/buf0flu.h:
Merge InnoDB-3.23.50
innobase/include/dict0dict.h:
Merge InnoDB-3.23.50
innobase/include/fil0fil.h:
Merge InnoDB-3.23.50
innobase/include/fsp0fsp.h:
Merge InnoDB-3.23.50
innobase/include/log0log.h:
Merge InnoDB-3.23.50
innobase/include/log0recv.h:
Merge InnoDB-3.23.50
innobase/include/mem0mem.h:
Merge InnoDB-3.23.50
innobase/include/os0file.h:
Merge InnoDB-3.23.50
innobase/include/row0mysql.h:
Merge InnoDB-3.23.50
innobase/include/srv0srv.h:
Merge InnoDB-3.23.50
innobase/include/srv0start.h:
Merge InnoDB-3.23.50
innobase/include/trx0sys.h:
Merge InnoDB-3.23.50
innobase/include/ut0byte.h:
Merge InnoDB-3.23.50
innobase/include/ut0rnd.h:
Merge InnoDB-3.23.50
innobase/include/ut0ut.h:
Merge InnoDB-3.23.50
innobase/log/log0log.c:
Merge InnoDB-3.23.50
innobase/log/log0recv.c:
Merge InnoDB-3.23.50
innobase/mem/mem0mem.c:
Merge InnoDB-3.23.50
innobase/os/os0file.c:
Merge InnoDB-3.23.50
innobase/rem/rem0cmp.c:
Merge InnoDB-3.23.50
innobase/row/row0ins.c:
Merge InnoDB-3.23.50
innobase/row/row0mysql.c:
Merge InnoDB-3.23.50
innobase/row/row0sel.c:
Merge InnoDB-3.23.50
innobase/row/row0upd.c:
Merge InnoDB-3.23.50
innobase/srv/srv0srv.c:
Merge InnoDB-3.23.50
innobase/srv/srv0start.c:
Merge InnoDB-3.23.50
innobase/trx/trx0sys.c:
Merge InnoDB-3.23.50
innobase/ut/ut0mem.c:
Merge InnoDB-3.23.50
innobase/ut/ut0ut.c:
Merge InnoDB-3.23.50
sql/ha_innobase.cc:
Merge InnoDB-3.23.50
sql/ha_innobase.h:
Merge InnoDB-3.23.50
Diffstat (limited to 'innobase/os')
-rw-r--r-- | innobase/os/os0file.c | 295 |
1 files changed, 232 insertions, 63 deletions
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 2ae59e26f35..dd51227bbf6 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -10,17 +10,22 @@ Created 10/21/1995 Heikki Tuuri #include "os0sync.h" #include "ut0mem.h" #include "srv0srv.h" -#include "trx0sys.h" #include "fil0fil.h" #undef HAVE_FDATASYNC +#undef UNIV_NON_BUFFERED_IO + #ifdef POSIX_ASYNC_IO /* We assume in this case that the OS has standard Posix aio (at least SunOS 2.6, HP-UX 11i and AIX 4.3 have) */ #endif +/* If the following is set to TRUE, we do not call os_file_flush in every +os_file_write. We can set this TRUE if the doublewrite buffer is used. */ +ibool os_do_not_call_flush_at_each_write = FALSE; + /* We use these mutexes to protect lseek + file i/o operation, if the OS does not provide an atomic pread or pwrite, or similar */ #define OS_FILE_N_SEEK_MUTEXES 16 @@ -118,6 +123,9 @@ ulint os_n_file_writes_old = 0; ulint os_n_fsyncs_old = 0; time_t os_last_printout; +ibool os_has_said_disk_full = FALSE; + + /*************************************************************************** Gets the operating system version. Currently works only on Windows. */ @@ -167,27 +175,28 @@ os_file_get_last_error(void) err = (ulint) GetLastError(); - if (err != ERROR_FILE_EXISTS) { - fprintf(stderr, - "InnoDB: Operating system error number %li in a file operation.\n" + if (err != ERROR_FILE_EXISTS && err != ERROR_DISK_FULL) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Operating system error number %li in a file operation.\n" "InnoDB: See http://www.innodb.com/ibman.html for installation help.\n", (long) err); - if (err == ERROR_PATH_NOT_FOUND) { + if (err == ERROR_PATH_NOT_FOUND) { fprintf(stderr, "InnoDB: The error means the system cannot find the path specified.\n" "InnoDB: In installation you must create directories yourself, InnoDB\n" "InnoDB: does not create them.\n"); - } else if (err == ERROR_ACCESS_DENIED) { + } else if (err == ERROR_ACCESS_DENIED) { fprintf(stderr, "InnoDB: The error means mysqld does not have the access rights to\n" "InnoDB: the directory. It may also be you have created a subdirectory\n" "InnoDB: of the same name as a data file.\n"); - } else { + } else { fprintf(stderr, "InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n" "InnoDB: what the error number means.\n"); - } + } } if (err == ERROR_FILE_NOT_FOUND) { @@ -202,26 +211,28 @@ os_file_get_last_error(void) #else err = (ulint) errno; - if (err != EEXIST) { - fprintf(stderr, - "InnoDB: Operating system error number %li in a file operation.\n" + if (err != EEXIST && err != ENOSPC ) { + ut_print_timestamp(stderr); + + fprintf(stderr, + " InnoDB: Operating system error number %li in a file operation.\n" "InnoDB: See http://www.innodb.com/ibman.html for installation help.\n", (long) err); - if (err == ENOENT) { + if (err == ENOENT) { fprintf(stderr, "InnoDB: The error means the system cannot find the path specified.\n" "InnoDB: In installation you must create directories yourself, InnoDB\n" "InnoDB: does not create them.\n"); - } else if (err == EACCES) { + } else if (err == EACCES) { fprintf(stderr, "InnoDB: The error means mysqld does not have the access rights to\n" "InnoDB: the directory.\n"); - } else { + } else { fprintf(stderr, "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"); - } + } } if (err == ENOSPC ) { @@ -259,18 +270,26 @@ os_file_handle_error( err = os_file_get_last_error(); if (err == OS_FILE_DISK_FULL) { - fprintf(stderr, "\n"); + /* We only print a warning about disk full once */ + + if (os_has_said_disk_full) { + + return(FALSE); + } + if (name) { - fprintf(stderr, - "InnoDB: Encountered a problem with file %s.\n", - name); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Encountered a problem with file %s\n", name); } + + ut_print_timestamp(stderr); fprintf(stderr, - "InnoDB: Cannot continue operation.\n" - "InnoDB: Disk is full. Try to clean the disk to free space.\n" - "InnoDB: Delete a possible created file and restart.\n"); + " InnoDB: Disk is full. Try to clean the disk to free space.\n"); - exit(1); + os_has_said_disk_full = TRUE; + + return(FALSE); } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) { return(TRUE); @@ -291,6 +310,130 @@ os_file_handle_error( } /******************************************************************** +Creates the seek mutexes used in positioned reads and writes. */ + +void +os_io_init_simple(void) +/*===================*/ +{ + ulint i; + + for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) { + os_file_seek_mutexes[i] = os_mutex_create(NULL); + } +} + +/******************************************************************** +A simple function to open or create a file. */ + +os_file_t +os_file_create_simple( +/*==================*/ + /* 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; + ibool retry; + +try_again: + 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_SHARE_WRITE, + /* file can be read and written + also by other processes */ + NULL, /* default security attributes */ + create_flag, + attributes, + NULL); /* no template file */ + + if (file == INVALID_HANDLE_VALUE) { + *success = FALSE; + + retry = os_file_handle_error(file, name); + + if (retry) { + goto try_again; + } + } else { + *success = TRUE; + } + + return(file); +#else + os_file_t file; + int create_flag; + ibool retry; + +try_again: + 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 | S_IROTH | S_IWOTH); + } else { + file = open(name, create_flag); + } + + if (file == -1) { + *success = FALSE; + + retry = os_file_handle_error(file, name); + + if (retry) { + goto try_again; + } + } else { + *success = TRUE; + } + + return(file); +#endif +} +/******************************************************************** Opens an existing file or creates a new. */ os_file_t @@ -355,8 +498,9 @@ try_again: file = CreateFile(name, GENERIC_READ | GENERIC_WRITE, /* read and write access */ - FILE_SHARE_READ,/* file can be read by other - processes */ + FILE_SHARE_READ | FILE_SHARE_WRITE, + /* file can be read and written + also by other processes */ NULL, /* default security attributes */ create_flag, attributes, @@ -494,6 +638,11 @@ os_file_get_size( offs = lseek(file, 0, SEEK_END); + if (offs == ((off_t)-1)) { + + return(FALSE); + } + if (sizeof(off_t) > 4) { *size = (ulint)(offs & 0xFFFFFFFF); *size_high = (ulint)(offs >> 32); @@ -524,13 +673,11 @@ os_file_set_size( ib_longlong low; ulint n_bytes; ibool ret; - ibool retry; byte* buf; ulint i; ut_a(size == (size & 0xFFFFFFFF)); -try_again: /* We use a very big 8 MB buffer in writing because Linux may be extremely slow in fsync on 1 MB writes */ @@ -571,14 +718,6 @@ try_again: } error_handling: - retry = os_file_handle_error(file, name); - - if (retry) { - goto try_again; - } - - ut_error; - return(FALSE); } @@ -725,8 +864,7 @@ os_file_pwrite( 64-bit address */ if (sizeof(off_t) > 4) { - offs = (off_t)offset + (((off_t)offset_high) << 32); - + offs = (off_t)offset + (((off_t)offset_high) << 32); } else { offs = (off_t)offset; @@ -743,8 +881,8 @@ os_file_pwrite( if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC - && !trx_doublewrite) { - + && !os_do_not_call_flush_at_each_write) { + /* Always do fsync to reduce the probability that when the OS crashes, a database page is only partially physically written to disk. */ @@ -774,7 +912,7 @@ os_file_pwrite( if (srv_unix_file_flush_method != SRV_UNIX_LITTLESYNC && srv_unix_file_flush_method != SRV_UNIX_NOSYNC - && !trx_doublewrite) { + && !os_do_not_call_flush_at_each_write) { /* Always do fsync to reduce the probability that when the OS crashes, a database page is only partially @@ -899,13 +1037,12 @@ os_file_write( DWORD ret2; DWORD low; DWORD high; - ibool retry; ulint i; ut_a((offset & 0xFFFFFFFF) == offset); os_n_file_writes++; -try_again: + ut_ad(file); ut_ad(buf); ut_ad(n > 0); @@ -924,7 +1061,15 @@ try_again: os_mutex_exit(os_file_seek_mutexes[i]); - goto error_handling; + ut_print_timestamp(stderr); + + fprintf(stderr, +" InnoDB: Error: File pointer positioning to file %s failed at\n" +"InnoDB: offset %lu %lu. Operating system error number %lu.\n", + name, offset_high, offset, + (ulint)GetLastError()); + + return(FALSE); } ret = WriteFile(file, buf, n, &len, NULL); @@ -932,38 +1077,61 @@ try_again: /* Always do fsync to reduce the probability that when the OS crashes, a database page is only partially physically written to disk. */ - if (!trx_doublewrite) { + if (!os_do_not_call_flush_at_each_write) { ut_a(TRUE == os_file_flush(file)); } os_mutex_exit(os_file_seek_mutexes[i]); if (ret && len == n) { + return(TRUE); } + + if (!os_has_said_disk_full) { + + 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: Check that your OS and file system support files of this size.\n" +"InnoDB: Check also the disk is not full or a disk quota exceeded.\n", + name, offset_high, offset, n, len, + (ulint)GetLastError()); + + os_has_said_disk_full = TRUE; + } + + return(FALSE); #else - ibool retry; ssize_t ret; -try_again: ret = os_file_pwrite(file, buf, n, offset, offset_high); if ((ulint)ret == n) { + return(TRUE); } -#endif -#ifdef __WIN__ -error_handling: -#endif - retry = os_file_handle_error(file, name); - if (retry) { - goto try_again; - } + if (!os_has_said_disk_full) { - ut_error; + ut_print_timestamp(stderr); - return(FALSE); + 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: Check that your OS and file system support files of this size.\n" +"InnoDB: Check also the disk is not full or a disk quota exceeded.\n", + name, offset_high, offset, n, ret, (ulint)errno); + + os_has_said_disk_full = TRUE; + } + + return(FALSE); +#endif } /******************************************************************** @@ -1034,7 +1202,8 @@ os_aio_array_create( } /**************************************************************************** -Initializes the asynchronous io system. Creates separate aio array for +Initializes the asynchronous io system. Calls also os_io_init_simple. +Creates a separate aio array for non-ibuf read and write, a third aio array for the ibuf i/o, with just one segment, two aio arrays for log reads and writes with one segment, and a synchronous aio array of the specified size. The combined number of segments @@ -1061,6 +1230,8 @@ os_aio_init( ut_ad(n % n_segments == 0); ut_ad(n_segments >= 4); + os_io_init_simple(); + n_per_seg = n / n_segments; n_write_segs = (n_segments - 2) / 2; n_read_segs = n_segments - 2 - n_write_segs; @@ -1081,10 +1252,6 @@ os_aio_init( os_aio_validate(); - for (i = 0; i < OS_FILE_N_SEEK_MUTEXES; i++) { - os_file_seek_mutexes[i] = os_mutex_create(NULL); - } - os_aio_segment_wait_events = ut_malloc(n_segments * sizeof(void*)); for (i = 0; i < n_segments; i++) { @@ -1742,7 +1909,8 @@ os_aio_windows_handle( if (ret && len == slot->len) { ret_val = TRUE; - if (slot->type == OS_FILE_WRITE && !trx_doublewrite) { + if (slot->type == OS_FILE_WRITE + && !os_do_not_call_flush_at_each_write) { ut_a(TRUE == os_file_flush(slot->file)); } } else { @@ -1827,7 +1995,8 @@ os_aio_posix_handle( *message1 = slot->message1; *message2 = slot->message2; - if (slot->type == OS_FILE_WRITE && !trx_doublewrite) { + if (slot->type == OS_FILE_WRITE + && !os_do_not_call_flush_at_each_write) { ut_a(TRUE == os_file_flush(slot->file)); } |