From: Date: June 4 2008 1:08am Subject: commit into mysql-6.0-wtf:mysql-6.0-wtf branch (vvaintroub:2653) Bug#24509, WL#3049 List-Archive: http://lists.mysql.com/commits/47394 X-Bug: 24509 Message-Id: <200806032308.m53N8tct001990@mail.mysql.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0-wtf/ 2653 Vladislav Vaintroub 2008-06-04 Bug#24509 - 2048 file descriptor limit on windows needs increasing, also WL#3049 - improved Windows I/O The patch replaces the use of the POSIX I/O interfaces in mysys on Windows with the Win32 API calls (CreateFile, WriteFile, etc). The Windows HANDLE for the open file is stored in the my_file_info struct, along with a flag for append mode (because the Windows API does not support opening files in append mode in all cases) The default max open files has been increased to 16384 and can be increased further by setting --max-open-files= during the server start. Additionally, my_(f)stat() is changed to use __stati64 structure with 64 file size and timestamps. It will now return correct file size now, unlike C runtime stat() that may report outdated info. added: mysys/my_winerr.c modified: client/mysqlbinlog.cc client/mysqlslap.c client/readline.cc include/config-win.h include/my_dir.h include/my_global.h include/my_sys.h libmysql/CMakeLists.txt mysys/CMakeLists.txt mysys/Makefile.am mysys/default_modify.c mysys/my_chsize.c mysys/my_div.c mysys/my_file.c mysys/my_fopen.c mysys/my_fstream.c mysys/my_lib.c mysys/my_lock.c mysys/my_mmap.c mysys/my_open.c mysys/my_pread.c mysys/my_quick.c mysys/my_read.c mysys/my_seek.c mysys/my_static.c mysys/my_sync.c mysys/my_write.c storage/innobase/handler/ha_innodb.cc storage/myisam/mi_locking.c per-file comments: client/mysqlbinlog.cc Changed fileno() to my_fileno() client/mysqlslap.c Changed fileno() to my_fileno() client/readline.cc Changed fileno() to my_fileno() include/config-win.h Increase limit for number of open files on windows include/my_dir.h use struct _stati64 instead of struct stat for stat() family of functions, (because of 64 bit file size and timestamps) include/my_global.h - Increased MY_NFILE (default value for --max-open-files on Windows) to 16384 - Introduced MY_FILE_MIN the minimal file descriptor returned by my_open(). Useful on Windows to catch errors if somebody mixes C runtime functions with mysys IO, as C runtime descriptor are always smaller than MY_FILE_MIN (==2048 on Windows). - Don't use MY_STAT_STRUCT in stat() functions , use struct __stati64 instead (because the later has 64 bit file size and timestamps) include/my_sys.h - Extend my_file_info to include HANDLE and open flag on Windows. - Declare some new Windows IO functions and my_fileno() libmysql/CMakeLists.txt New file my_winerr.c mysys/CMakeLists.txt New file my_winerr.c mysys/Makefile.am New file my_winerr.c mysys/default_modify.c fileno()->my_fileno() mysys/my_chsize.c _get_osfhandle()->my_get_osfhandle() Use SetFilePointerEx instead of SetFilePointer in my_chsize (simpler API) mysys/my_div.c Ignore filedescriptors smaller than MY_FILE_MIN in my_filename() mysys/my_file.c Valid range for file descriptors is [MY_FILE_MIN,my_file_limit] mysys/my_fopen.c mysys native Windows IO - adapt my_fopen, my_fdopen and my_fclose mysys/my_fstream.c mysys native Windows IO - new function my_fileno() mysys/my_lib.c mysys native Windows IO - adaptations for stat() and my_fstat(). mysys/my_lock.c _get_osfhandle -> my_get_osfhandle mysys/my_mmap.c _get_osfhandle -> my_get_osfhandle mysys/my_open.c mysys native Windows IO - implement my_open() and my_close(). mysys/my_pread.c _get_osfhandle -> my_get_osfhandle mysys/my_quick.c mysys native Windows IO for my_quick_read() and my_quick_write() mysys/my_read.c mysys native Windows IO for my_read() mysys/my_seek.c mysys native Windows IO for my_seek() mysys/my_static.c Remove initialization for my_file_info_default, because my_file_info structure is now platform dependent. As global variable, it is initialized with all nulls anyway. mysys/my_sync.c mysys native Windows IO for my_sync() mysys/my_winerr.c New file my_winerr. Contains my_osmaperr modelled after undocumented C runtime function _dosmaperr(). The problem with _dosmaperr() used previously is that 1) it is nowhere documented and thus code relying on it is not guaranteed to work in subsequent releases on the C runtime 2) it is present only in static C runtime (mysqld does not link if compiled with /MD) mysys/my_write.c mysys native Windows IO for my_write. Atomic APPEND is handled via technique described in MSDN community content for WriteFile (and driver documentation) storage/innobase/handler/ha_innodb.cc mysys native Windows IO : correct innodb tmp file handling mysql_tmpfile does not return valid CRT file descriptor, thus it is not possible to do a dup() on it. Instead, the native file handle has to be duplicated and converted to CRT descriptor. storage/myisam/mi_locking.c mysys Windows native IO : replace _commit() with my_sync. _commit is not going to work for something that is not CRT file descriptor. === modified file 'client/mysqlbinlog.cc' --- a/client/mysqlbinlog.cc 2008-04-03 17:22:10 +0000 +++ b/client/mysqlbinlog.cc 2008-06-03 23:08:38 +0000 @@ -1840,7 +1840,7 @@ static Exit_status dump_local_log_entrie return ERROR_STOP; } #endif - if (init_io_cache(file, fileno(stdin), 0, READ_CACHE, (my_off_t) 0, + if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0, 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE))) { error("Failed to init IO cache."); === modified file 'client/mysqlslap.c' --- a/client/mysqlslap.c 2008-04-25 16:43:25 +0000 +++ b/client/mysqlslap.c 2008-06-03 23:08:38 +0000 @@ -1331,7 +1331,7 @@ get_options(int *argc,char ***argv) if (opt_csv_str[0] == '-') { - csv_file= fileno(stdout); + csv_file= my_fileno(stdout); } else { === modified file 'client/readline.cc' --- a/client/readline.cc 2007-05-10 09:59:39 +0000 +++ b/client/readline.cc 2008-06-03 23:08:38 +0000 @@ -33,7 +33,7 @@ LINE_BUFFER *batch_readline_init(ulong m if (!(line_buff=(LINE_BUFFER*) my_malloc(sizeof(*line_buff),MYF(MY_WME | MY_ZEROFILL)))) return 0; - if (init_line_buffer(line_buff,fileno(file),IO_SIZE,max_size)) + if (init_line_buffer(line_buff,my_fileno(file),IO_SIZE,max_size)) { my_free(line_buff,MYF(0)); return 0; === modified file 'include/config-win.h' --- a/include/config-win.h 2008-05-09 11:25:34 +0000 +++ b/include/config-win.h 2008-06-03 23:08:38 +0000 @@ -353,7 +353,7 @@ inline double ulonglong2double(ulonglong #define FN_DEVCHAR ':' #define FN_NETWORK_DRIVES /* Uses \\ to indicate network drives */ #define FN_NO_CASE_SENCE /* Files are not case-sensitive */ -#define OS_FILE_LIMIT 2048 +#define OS_FILE_LIMIT UINT_MAX /* No limit*/ #define DO_NOT_REMOVE_THREAD_WRAPPERS #define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V)) === modified file 'include/my_dir.h' --- a/include/my_dir.h 2006-12-23 19:17:15 +0000 +++ b/include/my_dir.h 2008-06-03 23:08:38 +0000 @@ -69,7 +69,11 @@ typedef struct my_stat #else +#if(_MSC_VER) +#define MY_STAT struct __stat64 /* 64 bit file size and timestamp */ +#else #define MY_STAT struct stat /* Orginal struct have what we need */ +#endif #endif /* USE_MY_STAT_STRUCT */ === modified file 'include/my_global.h' --- a/include/my_global.h 2008-05-08 20:43:28 +0000 +++ b/include/my_global.h 2008-06-03 23:08:38 +0000 @@ -469,15 +469,17 @@ C_MODE_END #include /* an assert that works at compile-time. only for constant expression */ -#ifndef __GNUC__ -#define compile_time_assert(X) do { } while(0) -#else +#if (_MSC_VER >=1400) +#define compile_time_assert(X) do { C_ASSERT(X); } while(0) +#elif defined (___GNUC__) #define compile_time_assert(X) \ do \ { \ char compile_time_assert[(X) ? 1 : -1] \ __attribute__ ((unused)); \ } while(0) +#else +#define compile_time_assert(X) do { } while(0) #endif /* Go around some bugs in different OS and compilers */ @@ -727,7 +729,30 @@ typedef SOCKET_SIZE_TYPE size_socket; #define FN_LIBCHAR '/' #define FN_ROOTDIR "/" #endif + +/* + MY_FILE_MIN is Windows speciality and is used to quickly detect + the mismatch of CRT and mysys file IO usage on Windows at runtime. + CRT file descriptors can be in the range 0-2047, whereas descriptors returned + by my_open() will start with 2048. If a file descriptor with value less then + MY_FILE_MIN is passed to mysys IO function, chances are it stemms from + open()/fileno() and not my_open()/my_fileno. + + On Unix, where the mysys functions are light wrappers around libc, MY_FILE_MIN + is logically 0. +*/ +#ifdef __WIN__ +#define MY_FILE_MIN 2048 +#else +#define MY_FILE_MIN 0 +#endif + +#ifndef __WIN__ #define MY_NFILE 64 /* This is only used to save filenames */ +#else +#define MY_NFILE (16384 + MY_FILE_MIN) /* This is used to store file handles */ +#endif + #ifndef OS_FILE_LIMIT #define OS_FILE_LIMIT 65535 #endif @@ -766,7 +791,6 @@ typedef SOCKET_SIZE_TYPE size_socket; #define NO_HASH /* Not needed anymore */ #ifdef __WIN__ #define NO_DIR_LIBRARY /* Not standar dir-library */ -#define USE_MY_STAT_STRUCT /* For my_lib */ #endif /* Some defines of functions for portability */ === modified file 'include/my_sys.h' --- a/include/my_sys.h 2008-05-08 16:01:15 +0000 +++ b/include/my_sys.h 2008-06-03 23:08:38 +0000 @@ -310,8 +310,12 @@ enum file_type struct st_my_file_info { - char * name; - enum file_type type; + char * name; +#ifdef __WIN__ + HANDLE fhandle; /* win32 file handle */ + int oflag; /* open flags, e.g O_APPEND */ +#endif + enum file_type type; #if defined(THREAD) && !defined(HAVE_PREAD) && !defined(__WIN__) pthread_mutex_t mutex; #endif @@ -617,8 +621,12 @@ extern void *my_memmem(const void *hayst #ifdef __WIN__ -extern int my_access(const char *path, int amode); -extern File my_sopen(const char *path, int oflag, int shflag, int pmode); +extern int my_access(const char *path, int amode); +extern File my_sopen(const char *path, int oflag, int shflag, int pmode); +extern void my_osmaperr(unsigned long last_error); +extern File my_open_osfhandle(HANDLE handle, int oflag); +extern HANDLE my_get_osfhandle(File fd); +extern int my_get_open_flags(File fd); #else #define my_access access #endif @@ -639,6 +647,7 @@ extern void init_glob_errs(void); extern FILE *my_fopen(const char *FileName,int Flags,myf MyFlags); extern FILE *my_fdopen(File Filedes,const char *name, int Flags,myf MyFlags); extern int my_fclose(FILE *fd,myf MyFlags); +extern File my_fileno(FILE *fd); extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); extern int my_sync(File fd, myf my_flags); extern int my_sync_dir(const char *dir_name, myf my_flags); @@ -904,7 +913,7 @@ extern int my_getncpus(); #define HAVE_MMAP #endif -void *my_mmap(void *, size_t, int, int, int, my_off_t); +void *my_mmap(void *, size_t, int, int, File, my_off_t); int my_munmap(void *, size_t); #endif === modified file 'libmysql/CMakeLists.txt' --- a/libmysql/CMakeLists.txt 2008-04-08 01:47:13 +0000 +++ b/libmysql/CMakeLists.txt 2008-06-03 23:08:38 +0000 @@ -98,7 +98,7 @@ SET(CLIENT_SOURCES ../mysys/array.c .. ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c - ../mysys/my_getsystime.c ../mysys/my_sync.c ${LIB_SOURCES}) + ../mysys/my_getsystime.c ../mysys/my_sync.c ../mysys/my_winerr.c ${LIB_SOURCES}) # Need to set USE_TLS for building the DLL, since __declspec(thread) # approach to thread local storage does not work properly in DLLs. === modified file 'mysys/CMakeLists.txt' --- a/mysys/CMakeLists.txt 2007-11-07 23:18:30 +0000 +++ b/mysys/CMakeLists.txt 2008-06-03 23:08:38 +0000 @@ -39,7 +39,7 @@ SET(MYSYS_SOURCES array.c charset-def.c my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c - my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c + my_winerr.c my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c my_atomic.c my_getncpus.c lf_dynarray.c lf_alloc-pin.c lf_hash.c) === modified file 'mysys/Makefile.am' --- a/mysys/Makefile.am 2008-04-01 15:13:57 +0000 +++ b/mysys/Makefile.am 2008-06-03 23:08:38 +0000 @@ -57,7 +57,7 @@ libmysys_a_SOURCES = my_init.c my_get EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ thr_mutex.c thr_rwlock.c \ CMakeLists.txt mf_soundex.c \ - my_conio.c my_wincond.c my_winthread.c + my_conio.c my_wincond.c my_winthread.c my_winerr.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ # test_dir_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES) === modified file 'mysys/default_modify.c' --- a/mysys/default_modify.c 2007-07-30 08:33:50 +0000 +++ b/mysys/default_modify.c 2008-06-03 23:08:38 +0000 @@ -80,7 +80,7 @@ int modify_defaults_file(const char *fil DBUG_RETURN(2); /* my_fstat doesn't use the flag parameter */ - if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) + if (my_fstat(my_fileno(cnf_file), &file_stat, MYF(0))) goto malloc_err; if (option && option_value) @@ -215,7 +215,7 @@ int modify_defaults_file(const char *fil if (opt_applied) { /* Don't write the file if there are no changes to be made */ - if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, + if (my_chsize(my_fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0, MYF(MY_WME)) || my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) || my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer), === modified file 'mysys/my_chsize.c' --- a/mysys/my_chsize.c 2007-05-10 09:59:39 +0000 +++ b/mysys/my_chsize.c 2008-06-03 23:08:38 +0000 @@ -52,19 +52,16 @@ int my_chsize(File fd, my_off_t newlengt if (oldsize > newlength) { -#if defined(HAVE_SETFILEPOINTER) - /* This is for the moment only true on windows */ - long is_success; - HANDLE win_file= (HANDLE) _get_osfhandle(fd); - long length_low, length_high; - length_low= (long) (ulong) newlength; - length_high= (long) ((ulonglong) newlength >> 32); - is_success= SetFilePointer(win_file, length_low, &length_high, FILE_BEGIN); - if (is_success == -1 && (my_errno= GetLastError()) != NO_ERROR) +#ifdef __WIN__ + HANDLE win_file= (HANDLE) my_get_osfhandle(fd); + LARGE_INTEGER length; + length.QuadPart = newlength; + if(!SetFilePointerEx(win_file, length , NULL , FILE_BEGIN)) goto err; if (SetEndOfFile(win_file)) DBUG_RETURN(0); - my_errno= GetLastError(); + my_osmaperr(GetLastError()); + my_errno= errno; goto err; #elif defined(HAVE_FTRUNCATE) if (ftruncate(fd, (off_t) newlength)) === modified file 'mysys/my_div.c' --- a/mysys/my_div.c 2007-05-10 09:59:39 +0000 +++ b/mysys/my_div.c 2008-06-03 23:08:38 +0000 @@ -28,7 +28,7 @@ char * my_filename(File fd) DBUG_ENTER("my_filename"); if ((uint) fd >= (uint) my_file_limit) DBUG_RETURN((char*) "UNKNOWN"); - if (fd >= 0 && my_file_info[fd].type != UNOPEN) + if (fd >= MY_FILE_MIN && my_file_info[fd].type != UNOPEN) { DBUG_RETURN(my_file_info[fd].name); } === modified file 'mysys/my_file.c' --- a/mysys/my_file.c 2006-12-23 19:20:40 +0000 +++ b/mysys/my_file.c 2008-06-03 23:08:38 +0000 @@ -97,6 +97,7 @@ uint my_set_max_open_files(uint files) DBUG_ENTER("my_set_max_open_files"); DBUG_PRINT("enter",("files: %u my_file_limit: %u", files, my_file_limit)); + files += MY_FILE_MIN; files= set_max_open_files(min(files, OS_FILE_LIMIT)); if (files <= MY_NFILE) DBUG_RETURN(files); === modified file 'mysys/my_fopen.c' --- a/mysys/my_fopen.c 2008-03-27 18:40:00 +0000 +++ b/mysys/my_fopen.c 2008-06-03 23:08:38 +0000 @@ -17,6 +17,7 @@ #include "my_static.h" #include #include "mysys_err.h" +#include static void make_ftype(char * to,int flag); @@ -66,18 +67,27 @@ FILE *my_fopen(const char *filename, int on some OS (SUNOS). Actually the filename save isn't that important so we can ignore if this doesn't work. */ - if ((uint) fileno(fd) >= my_file_limit) + int filedesc; +#ifndef __WIN__ + filedesc = my_fileno(fd); + if ((uint)filedesc >= my_file_limit) { thread_safe_increment(my_stream_opened,&THR_LOCK_open); DBUG_RETURN(fd); /* safeguard */ } +#else + filedesc = my_open_osfhandle((HANDLE)_get_osfhandle(fileno(fd)), flags); + if(filedesc < 0) + DBUG_RETURN(NULL); + +#endif pthread_mutex_lock(&THR_LOCK_open); - if ((my_file_info[fileno(fd)].name = (char*) + if ((my_file_info[filedesc].name = (char*) my_strdup(filename,MyFlags))) { my_stream_opened++; my_file_total_opened++; - my_file_info[fileno(fd)].type = STREAM_BY_FOPEN; + my_file_info[filedesc].type = STREAM_BY_FOPEN; pthread_mutex_unlock(&THR_LOCK_open); DBUG_PRINT("exit",("stream: %p", fd)); DBUG_RETURN(fd); @@ -97,8 +107,8 @@ FILE *my_fopen(const char *filename, int } /* my_fopen */ - /* Close a stream */ +/* Close a stream */ int my_fclose(FILE *fd, myf MyFlags) { int err,file; @@ -106,7 +116,7 @@ int my_fclose(FILE *fd, myf MyFlags) DBUG_PRINT("my",("stream: %p MyFlags: %d", fd, MyFlags)); pthread_mutex_lock(&THR_LOCK_open); - file=fileno(fd); + file= my_fileno(fd); if ((err = fclose(fd)) < 0) { my_errno=errno; @@ -138,7 +148,19 @@ FILE *my_fdopen(File Filedes, const char Filedes, Flags, MyFlags)); make_ftype(type,Flags); - if ((fd = fdopen(Filedes, type)) == 0) +#ifndef __WIN__ + fd = fdopen(Filedes, type); +#else + { + /* Convert OS file handle to CRT file descriptor and then call fdopen*/ + int crt_fd = _open_osfhandle((intptr_t)my_get_osfhandle(Filedes), Flags); + if(crt_fd < 0) + fd = 0; + else + fd = fdopen(crt_fd, type); + } +#endif + if(!fd) { my_errno=errno; if (MyFlags & (MY_FAE | MY_WME)) === modified file 'mysys/my_fstream.c' --- a/mysys/my_fstream.c 2008-04-09 01:07:00 +0000 +++ b/mysys/my_fstream.c 2008-06-03 23:08:38 +0000 @@ -56,11 +56,11 @@ size_t my_fread(FILE *stream, uchar *Buf { if (ferror(stream)) my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(fileno(stream)),errno); + my_filename(my_fileno(stream)),errno); else if (MyFlags & (MY_NABP | MY_FNABP)) my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(fileno(stream)),errno); + my_filename(my_fileno(stream)),errno); } my_errno=errno ? errno : -1; if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP)) @@ -144,7 +144,7 @@ size_t my_fwrite(FILE *stream, const uch if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), - my_filename(fileno(stream)),errno); + my_filename(my_fileno(stream)),errno); } writtenbytes= (size_t) -1; /* Return that we got error */ break; @@ -184,3 +184,53 @@ my_off_t my_ftell(FILE *stream, myf MyFl DBUG_PRINT("exit",("ftell: %lu",(ulong) pos)); DBUG_RETURN((my_off_t) pos); } /* my_ftell */ + +#ifdef __WIN__ +/* Get internal file descriptor for stdin,stdout or stderr */ +static File my_get_stdfile_descriptor(FILE *stream) +{ + HANDLE hFile; + DWORD nStdHandle; + DBUG_ENTER("my_get_stdfile_descriptor"); + DBUG_PRINT("my",("stream: %p", stream)); + + if(stream == stdin) + nStdHandle= STD_INPUT_HANDLE; + else if(stream == stdout) + nStdHandle= STD_OUTPUT_HANDLE; + else if(stream == stderr) + nStdHandle= STD_ERROR_HANDLE; + else + DBUG_RETURN(-1); + hFile= GetStdHandle(nStdHandle); + if(hFile != INVALID_HANDLE_VALUE) + DBUG_RETURN(my_open_osfhandle(hFile, 0)); + DBUG_RETURN(-1); +} +#endif + +/* Get a File corresponding to the stream*/ +int my_fileno(FILE *f) +{ +#ifndef __WIN__ + return fileno(f); +#else + HANDLE handle= (HANDLE)_get_osfhandle(fileno(f)); + int retval= -1; + uint i; + pthread_mutex_lock(&THR_LOCK_open); + for(i= MY_FILE_MIN; i < my_file_limit; i++) + { + if(my_file_info[i].fhandle == handle) + { + retval = i; + break; + } + } + pthread_mutex_unlock(&THR_LOCK_open); + if(retval == -1) + /* try std stream */ + return my_get_stdfile_descriptor(f); + return retval; +#endif +} === modified file 'mysys/my_lib.c' --- a/mysys/my_lib.c 2008-04-09 01:07:00 +0000 +++ b/mysys/my_lib.c 2008-06-03 23:08:38 +0000 @@ -514,12 +514,54 @@ error: ** Note that MY_STAT is assumed to be same as struct stat ****************************************************************************/ -int my_fstat(int Filedes, MY_STAT *stat_area, +#ifdef __WIN__ +/* + Quick and dirty my_fstat() implementation for Windows. + Use CRT fstat on temporarily allocated file descriptor. + Patch file size, because size that fstat returns is not + reliable (may be outdated) +*/ +static int win_fstat(HANDLE hFile, MY_STAT *stat_area) +{ + int crt_fd; + int retval; + HANDLE hDup; + + DBUG_ENTER("win_fstat"); + DBUG_PRINT("my",("hFile: %p",hFile)); + if(!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(), + &hDup ,0,FALSE,DUPLICATE_SAME_ACCESS)) + { + my_osmaperr(GetLastError()); + DBUG_RETURN(-1); + } + if ((crt_fd= _open_osfhandle((intptr_t)hDup,0)) < 0) + DBUG_RETURN(-1); + + retval= _fstati64(crt_fd, stat_area); + if(retval > 0) + { + /* File size returned by stat is not accurate (may be outdated), correct it*/ + GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(stat_area->st_size))); + } + _close(crt_fd); + DBUG_RETURN(retval); +} +#endif + +int my_fstat(File Filedes, MY_STAT *stat_area, myf MyFlags __attribute__((unused))) { DBUG_ENTER("my_fstat"); DBUG_PRINT("my",("fd: %d MyFlags: %d", Filedes, MyFlags)); +#ifndef __WIN__ DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area)); +#else + { + HANDLE hFile = my_get_osfhandle(Filedes); + DBUG_RETURN(win_fstat(hFile, stat_area)); + } +#endif } @@ -533,9 +575,24 @@ MY_STAT *my_stat(const char *path, MY_ST if ((m_used= (stat_area == NULL))) if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) goto error; - if (! stat((char *) path, (struct stat *) stat_area) ) +#ifndef __WIN__ + if (! _stati64((char *) path, (struct stat *) stat_area) ) + DBUG_RETURN(stat_area); +#else + if(!_stati64((char *) path, stat_area) ) + { + /* File size returned by stat is not accurate (may be outdated), correct it*/ + WIN32_FILE_ATTRIBUTE_DATA data; + if (GetFileAttributesEx(path, GetFileExInfoStandard, &data)) + { + LARGE_INTEGER li; + li.LowPart = data.nFileSizeLow; + li.HighPart = data.nFileSizeHigh; + stat_area->st_size = li.QuadPart; + } DBUG_RETURN(stat_area); - + } +#endif DBUG_PRINT("error",("Got errno: %d from stat", errno)); my_errno= errno; if (m_used) /* Free if new area */ === modified file 'mysys/my_lock.c' --- a/mysys/my_lock.c 2008-02-01 12:04:32 +0000 +++ b/mysys/my_lock.c 2008-06-03 23:08:38 +0000 @@ -107,7 +107,7 @@ int my_lock(File fd, int locktype, my_of LARGE_INTEGER liOffset,liLength; DWORD dwFlags; OVERLAPPED ov= {0}; - HANDLE hFile= (HANDLE)_get_osfhandle(fd); + HANDLE hFile= (HANDLE)my_get_osfhandle(fd); lastError= 0; === modified file 'mysys/my_mmap.c' --- a/mysys/my_mmap.c 2006-12-23 19:20:40 +0000 +++ b/mysys/my_mmap.c 2008-06-03 23:08:38 +0000 @@ -33,11 +33,11 @@ static SECURITY_ATTRIBUTES mmap_security {sizeof(SECURITY_ATTRIBUTES), 0, TRUE}; void *my_mmap(void *addr, size_t len, int prot, - int flags, int fd, my_off_t offset) + int flags, File fd, my_off_t offset) { HANDLE hFileMap; LPVOID ptr; - HANDLE hFile= (HANDLE)_get_osfhandle(fd); + HANDLE hFile= (HANDLE)my_get_osfhandle(fd); if (hFile == INVALID_HANDLE_VALUE) return MAP_FAILED; === modified file 'mysys/my_open.c' --- a/mysys/my_open.c 2008-04-08 01:47:13 +0000 +++ b/mysys/my_open.c 2008-06-03 23:08:38 +0000 @@ -94,10 +94,20 @@ int my_close(File fd, myf MyFlags) DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); pthread_mutex_lock(&THR_LOCK_open); +#ifndef __WIN__ do { err= close(fd); } while (err == -1 && errno == EINTR); +#else + if(!CloseHandle(my_get_osfhandle(fd))) + { + err = -1; + my_osmaperr(GetLastError()); + } + else + err = 0; +#endif if (err) { @@ -141,7 +151,7 @@ File my_register_filename(File fd, const type_of_file, uint error_message_number, myf MyFlags) { DBUG_ENTER("my_register_filename"); - if ((int) fd >= 0) + if ((int) fd >= MY_FILE_MIN) { if ((uint) fd >= my_file_limit) { @@ -159,7 +169,7 @@ File my_register_filename(File fd, const { my_file_opened++; my_file_total_opened++; - my_file_info[fd].type = type_of_file; + my_file_info[fd].type= type_of_file; #if defined(THREAD) && !defined(HAVE_PREAD) && !defined(__WIN__) pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST); #endif @@ -189,7 +199,40 @@ File my_register_filename(File fd, const #ifdef __WIN__ -extern void __cdecl _dosmaperr(unsigned long); +File my_open_osfhandle(HANDLE handle, int oflag) +{ + int offset= -1; + uint i; + pthread_mutex_lock(&THR_LOCK_open); + for(i= MY_FILE_MIN; i < my_file_limit;i++) + { + if(my_file_info[i].type == UNOPEN) + { + struct st_my_file_info *finfo = &(my_file_info[i]); + finfo->type= FILE_BY_OPEN; + finfo->fhandle= handle; + finfo->oflag= oflag; + offset = i; + break; + } + } + pthread_mutex_unlock(&THR_LOCK_open); + return offset; +} + + +HANDLE my_get_osfhandle(File fd) +{ + DBUG_ASSERT( fd >= MY_FILE_MIN && fd < my_file_limit); + return my_file_info[fd].fhandle; +} + +int my_get_open_flags(File fd) +{ + DBUG_ASSERT( fd >= MY_FILE_MIN && fd < my_file_limit); + return my_file_info[fd].oflag; +} + /* Open a file with sharing. Similar to _sopen() from libc, but allows managing @@ -355,14 +398,14 @@ File my_sopen(const char *path, int ofla * the lock, and return -1. note that it's not necessary to * call _free_osfhnd (it hasn't been used yet). */ - _dosmaperr(GetLastError()); /* map error */ + my_osmaperr(GetLastError()); /* map error */ return -1; /* return error to caller */ } - if ((fh= _open_osfhandle((intptr_t)osfh, + if ((fh= my_open_osfhandle(osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1) { - _dosmaperr(GetLastError()); /* map error */ + my_osmaperr(GetLastError()); /* map error */ CloseHandle(osfh); } === modified file 'mysys/my_pread.c' --- a/mysys/my_pread.c 2008-04-25 16:43:25 +0000 +++ b/mysys/my_pread.c 2008-06-03 23:08:38 +0000 @@ -21,7 +21,7 @@ #endif #ifdef __WIN__ -extern void _dosmaperr(DWORD); + /* Positional read and write on Windows. @@ -45,7 +45,7 @@ static size_t pread(File Filedes, uchar Count = UINT_MAX; #endif - hFile= (HANDLE)_get_osfhandle(Filedes); + hFile= (HANDLE)my_get_osfhandle(Filedes); li.QuadPart= offset; ov.Offset= li.LowPart; ov.OffsetHigh= li.HighPart; @@ -55,7 +55,7 @@ static size_t pread(File Filedes, uchar DWORD lastError = GetLastError(); if(lastError == ERROR_HANDLE_EOF) return 0; /*return 0 at EOF*/ - _dosmaperr(lastError); + my_osmaperr(lastError); return -1; } else @@ -77,14 +77,14 @@ static size_t pwrite(File Filedes, const Count = UINT_MAX; #endif - hFile= (HANDLE)_get_osfhandle(Filedes); + hFile= (HANDLE)my_get_osfhandle(Filedes); li.QuadPart= offset; ov.Offset= li.LowPart; ov.OffsetHigh= li.HighPart; if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov)) { - _dosmaperr(GetLastError()); + my_osmaperr(GetLastError()); return -1; } else @@ -189,7 +189,7 @@ size_t my_pread(File Filedes, uchar *Buf # Number of bytes read */ -size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, +size_t my_pwrite(File Filedes, const uchar *Buffer, size_t Count, my_off_t offset, myf MyFlags) { size_t writenbytes, written; === modified file 'mysys/my_quick.c' --- a/mysys/my_quick.c 2007-06-21 08:13:10 +0000 +++ b/mysys/my_quick.c 2008-06-03 23:08:38 +0000 @@ -19,11 +19,19 @@ #include "my_nosys.h" +#ifdef __WIN__ +extern size_t my_win_read(File Filedes,uchar *Buffer,size_t Count); +#endif + size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags) { size_t readbytes; - - if ((readbytes = read(Filedes, Buffer, Count)) != Count) +#ifdef __WIN__ + readbytes = my_win_read(Filedes, Buffer, Count); +#else + readbytes = read(Filedes, Buffer, Count); +#endif + if(readbytes != Count) { #ifndef DBUG_OFF if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR) @@ -39,10 +47,17 @@ size_t my_quick_read(File Filedes,uchar return (MyFlags & (MY_NABP | MY_FNABP)) ? 0 : readbytes; } +#ifdef __WIN__ +extern size_t my_win_write(File Filedes,const uchar *Buffer,size_t Count); +#endif -size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count) +size_t my_quick_write(File Filedes, const uchar *Buffer, size_t Count) { -#ifndef DBUG_OFF +#ifdef __WIN__ + return my_win_write(Filedes, Buffer, Count); +#else + +#if !defined (DBUG_OFF) size_t writtenbytes; #endif @@ -64,4 +79,5 @@ size_t my_quick_write(File Filedes,const return (size_t) -1; } return 0; +#endif } === modified file 'mysys/my_read.c' --- a/mysys/my_read.c 2008-03-27 18:40:00 +0000 +++ b/mysys/my_read.c 2008-06-03 23:08:38 +0000 @@ -17,6 +17,22 @@ #include "mysys_err.h" #include +#ifdef __WIN__ +size_t my_win_read(File Filedes, uchar *Buffer, size_t Count) +{ + DWORD nRead; + size_t readbytes; + HANDLE hFile = my_get_osfhandle(Filedes); + if (!ReadFile(hFile, Buffer, (DWORD)Count, &nRead, NULL)) + { + my_osmaperr(GetLastError()); + readbytes = -1; + } + else + readbytes = nRead; + return readbytes; +} +#endif /* Read a chunk of bytes from a file with retry's if needed @@ -44,7 +60,13 @@ size_t my_read(File Filedes, uchar *Buff for (;;) { errno= 0; /* Linux doesn't reset this */ - if ((readbytes= read(Filedes, Buffer, Count)) != Count) +#ifdef __WIN__ + readbytes = my_win_read(Filedes, Buffer, Count); +#else + readbytes = read(Filedes, Buffer, Count); +#endif + + if (readbytes != Count) { my_errno= errno ? errno : -1; DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", === modified file 'mysys/my_seek.c' --- a/mysys/my_seek.c 2008-02-01 12:04:32 +0000 +++ b/mysys/my_seek.c 2008-06-03 23:08:38 +0000 @@ -45,36 +45,43 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags __attribute__((unused))) { - reg1 os_off_t newpos= -1; + os_off_t newpos= -1; DBUG_ENTER("my_seek"); - DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", - fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos, - whence, MyFlags)); + DBUG_PRINT("my",("Fd: %d Pos: %llu Whence: %d MyFlags: %d", + fd, (ulonglong) pos, whence, MyFlags)); DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */ /* Make sure we are using a valid file descriptor! */ DBUG_ASSERT(fd != -1); -#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(__WIN__) - if (MyFlags & MY_THREADSAFE) +#if defined (__WIN__) + + /*Check Windows API seek constants are compatible with posix ones */ + compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR + && FILE_END == SEEK_END); + { - pthread_mutex_lock(&my_file_info[fd].mutex); - newpos= lseek(fd, pos, whence); - pthread_mutex_unlock(&my_file_info[fd].mutex); + LARGE_INTEGER pos1; + pos1.QuadPart = pos; + if(!SetFilePointerEx(my_get_osfhandle(fd), pos1, (PLARGE_INTEGER) &newpos, whence)) + { + my_osmaperr(GetLastError()); + newpos = -1; + } } - else -#endif +#else newpos= lseek(fd, pos, whence); +#endif if (newpos == (os_off_t) -1) { my_errno=errno; - DBUG_PRINT("error",("lseek: %lu errno: %d", (ulong) newpos,errno)); + DBUG_PRINT("error",("lseek: %llu errno: %d", (ulonglong) newpos,errno)); DBUG_RETURN(MY_FILEPOS_ERROR); } if ((my_off_t) newpos != pos) { - DBUG_PRINT("exit",("pos: %lu", (ulong) newpos)); + DBUG_PRINT("exit",("pos: %llu", (ulonglong) newpos)); } DBUG_RETURN((my_off_t) newpos); } /* my_seek */ @@ -89,13 +96,13 @@ my_off_t my_tell(File fd, myf MyFlags __ DBUG_ENTER("my_tell"); DBUG_PRINT("my",("Fd: %d MyFlags: %d",fd, MyFlags)); DBUG_ASSERT(fd >= 0); -#ifdef HAVE_TELL +#if defined (HAVE_TELL) && !defined (__WIN__) pos=tell(fd); #else - pos=lseek(fd, 0L, MY_SEEK_CUR); + pos=my_seek(fd, 0L, MY_SEEK_CUR,0); #endif if (pos == (os_off_t) -1) my_errno=errno; - DBUG_PRINT("exit",("pos: %lu", (ulong) pos)); + DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos)); DBUG_RETURN((my_off_t) pos); } /* my_tell */ === modified file 'mysys/my_static.c' --- a/mysys/my_static.c 2008-04-08 15:32:47 +0000 +++ b/mysys/my_static.c 2008-06-03 23:08:38 +0000 @@ -35,7 +35,7 @@ int NEAR my_umask=0664, NEAR my_umask_d #ifndef THREAD int NEAR my_errno=0; #endif -struct st_my_file_info my_file_info_default[MY_NFILE]= {{0,UNOPEN}}; +struct st_my_file_info my_file_info_default[MY_NFILE]; uint my_file_limit= MY_NFILE; struct st_my_file_info *my_file_info= my_file_info_default; === modified file 'mysys/my_sync.c' --- a/mysys/my_sync.c 2007-10-11 15:07:40 +0000 +++ b/mysys/my_sync.c 2008-06-03 23:08:38 +0000 @@ -63,7 +63,14 @@ int my_sync(File fd, myf my_flags) #elif defined(HAVE_FSYNC) res= fsync(fd); #elif defined(__WIN__) - res= _commit(fd); + res = 0; + if(FlushFileBuffers(my_get_osfhandle(fd))) + res= 0; + else + { + my_osmaperr(GetLastError()); + res = -1; + } #else #error Cannot find a way to sync a file, durability in danger res= 0; /* No sync (strange OS) */ === added file 'mysys/my_winerr.c' --- a/mysys/my_winerr.c 1970-01-01 00:00:00 +0000 +++ b/mysys/my_winerr.c 2008-06-03 23:08:38 +0000 @@ -0,0 +1,123 @@ +/* Copyright (C) 2008 MySQL AB + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Convert Windows API error (GetLastError() to Posix equivalent (errno) + The exported function my_osmaperr() is modelled after and borrows + heavily from undocumented _dosmaperr()(found of the static Microsoft C runtime). +*/ + +#include +#include + + +struct errentry +{ + unsigned long oscode; /* OS return value */ + int errnocode; /* System V error code */ +}; + +static struct errentry errtable[] = { + { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */ + { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */ + { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */ + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */ + { ERROR_ACCESS_DENIED, EACCES }, /* 5 */ + { ERROR_INVALID_HANDLE, EBADF }, /* 6 */ + { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */ + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */ + { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */ + { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */ + { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */ + { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */ + { ERROR_INVALID_DATA, EINVAL }, /* 13 */ + { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */ + { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */ + { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */ + { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */ + { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */ + { ERROR_BAD_NETPATH, ENOENT }, /* 53 */ + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */ + { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */ + { ERROR_FILE_EXISTS, EEXIST }, /* 80 */ + { ERROR_CANNOT_MAKE, EACCES }, /* 82 */ + { ERROR_FAIL_I24, EACCES }, /* 83 */ + { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */ + { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */ + { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */ + { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */ + { ERROR_DISK_FULL, ENOSPC }, /* 112 */ + { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */ + { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */ + { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */ + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */ + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */ + { ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */ + { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */ + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */ + { ERROR_NOT_LOCKED, EACCES }, /* 158 */ + { ERROR_BAD_PATHNAME, ENOENT }, /* 161 */ + { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */ + { ERROR_LOCK_FAILED, EACCES }, /* 167 */ + { ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */ + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */ + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */ + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */ +}; + +/* size of the table */ +#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0])) + +/* The following two constants must be the minimum and maximum +values in the (contiguous) range of Exec Failure errors. */ +#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG +#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN + +/* These are the low and high value in the range of errors that are +access violations */ +#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT +#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED + + +static int get_errno_from_oserr(unsigned long oserrno) +{ + int i; + + /* check the table for the OS error code */ + for (i = 0; i < ERRTABLESIZE; ++i) + { + if (oserrno == errtable[i].oscode) + { + return errtable[i].errnocode; + } + } + + /* The error code wasn't in the table. We check for a range of */ + /* EACCES errors or exec failure errors (ENOEXEC). Otherwise */ + /* EINVAL is returned. */ + + if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE) + return EACCES; + else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR) + return ENOEXEC; + else + return EINVAL; +} + +/* Set errno corresponsing to GetLastError() value */ +void my_osmaperr ( unsigned long oserrno) +{ + errno = get_errno_from_oserr(oserrno); +} === modified file 'mysys/my_write.c' --- a/mysys/my_write.c 2008-04-09 01:07:00 +0000 +++ b/mysys/my_write.c 2008-06-03 23:08:38 +0000 @@ -18,9 +18,40 @@ #include +#ifdef __WIN__ +#ifndef FILE_WRITE_TO_END_OF_FILE +#define FILE_WRITE_TO_END_OF_FILE 0xffffffff +#endif + +size_t my_win_write(File Filedes, const uchar *Buffer, size_t Count) +{ + DWORD nWritten; + OVERLAPPED ov; + OVERLAPPED *pov = NULL; + HANDLE hFile; + + if(my_get_open_flags(Filedes) & _O_APPEND) + { + /* Atomic append to the end of file is is done by special initialization of the + OVERLAPPED structure. See MSDN WriteFile documentation for more info */ + memset(&ov, 0, sizeof(ov)); + ov.Offset = FILE_WRITE_TO_END_OF_FILE; + ov.OffsetHigh = -1; + pov = &ov; + } + + hFile = my_get_osfhandle(Filedes); + if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov)) + { + nWritten = (size_t)-1; + my_osmaperr(GetLastError()); + } + return (size_t)nWritten; +} +#endif /* Write a chunk of bytes to a file */ -size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) +size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { size_t writenbytes, written; uint errors; @@ -35,8 +66,14 @@ size_t my_write(int Filedes, const uchar for (;;) { +#ifdef __WIN__ + if ((writenbytes= my_win_write(Filedes, Buffer, Count)) == Count) + break; +#else if ((writenbytes= write(Filedes, Buffer, Count)) == Count) break; +#endif + if (writenbytes != (size_t) -1) { /* Safeguard */ written+=writenbytes; === modified file 'storage/innobase/handler/ha_innodb.cc' --- a/storage/innobase/handler/ha_innodb.cc 2008-05-08 20:43:28 +0000 +++ b/storage/innobase/handler/ha_innodb.cc 2008-06-03 23:08:38 +0000 @@ -874,7 +874,29 @@ innobase_mysql_tmpfile(void) will be passed to fdopen(), it will be closed by invoking fclose(), which in turn will invoke close() instead of my_close(). */ + +#ifdef _WIN32 + /* Note that on Windows, the integer returned by mysql_tmpfile + has no relation to C runtime file descriptor. Here, we need + to call my_get_osfhandle to get the HANDLE and then convert it + to C runtime filedescriptor. */ + { + HANDLE hFile = my_get_osfhandle(fd); + HANDLE hDup; + BOOL bOK = + DuplicateHandle(GetCurrentProcess(), hFile, GetCurrentProcess(), + &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS); + if(bOK) { + fd2 = _open_osfhandle((intptr_t)hDup,0); + } + else { + my_osmaperr(GetLastError()); + fd2 = -1; + } + } +#else fd2 = dup(fd); +#endif if (fd2 < 0) { DBUG_PRINT("error",("Got error %d on dup",fd2)); my_errno=errno; === modified file 'storage/myisam/mi_locking.c' --- a/storage/myisam/mi_locking.c 2008-04-09 01:07:00 +0000 +++ b/storage/myisam/mi_locking.c 2008-06-03 23:08:38 +0000 @@ -460,8 +460,8 @@ int _mi_writeinfo(register MI_INFO *info #ifdef __WIN__ if (myisam_flush) { - _commit(share->kfile); - _commit(info->dfile); + my_sync(share->kfile,0); + my_sync(info->dfile,0); } #endif }