diff options
Diffstat (limited to 'mysys')
43 files changed, 1637 insertions, 572 deletions
diff --git a/mysys/.cvsignore b/mysys/.cvsignore deleted file mode 100644 index 056ecc2691c..00000000000 --- a/mysys/.cvsignore +++ /dev/null @@ -1,10 +0,0 @@ -.deps -.libs -Makefile -Makefile.in -st35l1t6 -test_charset -test_thr_alarm -test_thr_lock -test_vsnprintf -testhash diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 7afb800643c..21b04e7c968 100755 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -13,8 +13,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") - # Only the server link with this library, the client libraries and the client # executables all link with recompiles of source found in the "mysys" directory. # So we only need to create one version of this library, with the "static" @@ -39,7 +37,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_ 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 stacktrace.c + my_winerr.c my_winfile.c my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c stacktrace.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) diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 19017330654..68fde34ee07 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -64,7 +64,7 @@ endif 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 my_winfile.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ # test_dir_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES) @@ -134,5 +134,26 @@ test_base64$(EXEEXT): base64.c $(LIBRARIES) $(LINK) $(FLAGS) -DMAIN ./test_base64.c $(LDADD) $(LIBS) $(RM) -f ./test_base64.c +if HAVE_DTRACE_DASH_G +libmysys_a_LIBADD += probes_mysql.o +libmysys_a_DEPENDENCIES += probes_mysql.o dtrace_files dtrace_providers +CLEANFILES = probes_mysql.o dtrace_files dtrace_providers +DTRACEFILES = mf_keycache.o +DTRACEPROVIDER = probes_mysql.d +CLEANFILES += $(DTRACEPROVIDER) dtrace_sources + +dtrace_files: + echo $(DTRACEFILES) > $@ +dtrace_providers: probes_mysql.d + echo $(DTRACEPROVIDER) > $@ +probes_mysql.d: + -$(RM) -f probes_mysql.d + $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d + echo timestamp > dtrace_sources + +probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES) + $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@ +endif + # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 63bbceef29b..bf2576621ce 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -42,6 +42,7 @@ extern CHARSET_INFO my_charset_ucs2_roman_uca_ci; extern CHARSET_INFO my_charset_ucs2_persian_uca_ci; extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci; extern CHARSET_INFO my_charset_ucs2_hungarian_uca_ci; +extern CHARSET_INFO my_charset_ucs2_sinhala_uca_ci; #endif #ifdef HAVE_CHARSET_utf8 @@ -63,6 +64,7 @@ extern CHARSET_INFO my_charset_utf8_roman_uca_ci; extern CHARSET_INFO my_charset_utf8_persian_uca_ci; extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci; extern CHARSET_INFO my_charset_utf8_hungarian_uca_ci; +extern CHARSET_INFO my_charset_utf8_sinhala_uca_ci; #ifdef HAVE_UTF8_GENERAL_CS extern CHARSET_INFO my_charset_utf8_general_cs; #endif @@ -152,6 +154,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_persian_uca_ci); add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci); add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci); + add_compiled_collation(&my_charset_ucs2_sinhala_uca_ci); #endif #endif @@ -186,6 +189,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8_persian_uca_ci); add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); add_compiled_collation(&my_charset_utf8_hungarian_uca_ci); + add_compiled_collation(&my_charset_utf8_sinhala_uca_ci); #endif #endif diff --git a/mysys/charset.c b/mysys/charset.c index b1b91d716ba..ff4eb70acd0 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -42,7 +42,7 @@ get_collation_number_internal(const char *name) { CHARSET_INFO **cs; for (cs= all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; + cs < all_charsets + array_elements(all_charsets); cs++) { if ( cs[0] && cs[0]->name && @@ -249,12 +249,16 @@ static int add_collation(CHARSET_INFO *cs) { #if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci); + newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } else if (!strcmp(cs->csname, "utf8")) { #if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, &my_charset_utf8_unicode_ci); + newcs->ctype= my_charset_utf8_unicode_ci.ctype; + if (init_state_maps(newcs)) + return MY_XML_ERROR; #endif } else @@ -281,6 +285,8 @@ static int add_collation(CHARSET_INFO *cs) if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number])) all_charsets[cs->number]->state|= MY_CS_PUREASCII; + if (!my_charset_is_ascii_compatible(cs)) + all_charsets[cs->number]->state|= MY_CS_NONASCII; } } else @@ -384,7 +390,7 @@ char *get_charsets_dir(char *buf) DBUG_RETURN(res); } -CHARSET_INFO *all_charsets[256]={NULL}; +CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]={NULL}; CHARSET_INFO *default_charset_info = &my_charset_latin1; void add_compiled_collation(CHARSET_INFO *cs) @@ -440,7 +446,7 @@ uint get_charset_number(const char *charset_name, uint cs_flags) my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; + cs < all_charsets + array_elements(all_charsets); cs++) { if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && @@ -514,7 +520,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) my_pthread_once(&charsets_initialized, init_available_charsets); - if (!cs_number || cs_number >= array_elements(all_charsets)-1) + if (!cs_number || cs_number > array_elements(all_charsets)) return NULL; cs=get_internal_charset(cs_number, flags); diff --git a/mysys/default.c b/mysys/default.c index 4e9d4faae91..91a2728d009 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -41,6 +41,29 @@ #include <winbase.h> #endif +/** + arguments separator + + load_defaults() loads arguments from config file and put them + before the arguments from command line, this separator is used to + separate the arguments loaded from config file and arguments user + provided on command line. + + Options with value loaded from config file are always in the form + '--option=value', while for command line options, the value can be + given as the next argument. Thus we used a separator so that + handle_options() can distinguish them. + + Note: any other places that does not need to distinguish them + should skip the separator. + + The content of arguments separator does not matter, one should only + check the pointer, use "----args-separator----" here to ease debug + if someone misused it. + + See BUG#25192 +*/ +const char *args_separator= "----args-separator----"; const char *my_defaults_file=0; const char *my_defaults_group_suffix=0; char *my_defaults_extra_file=0; @@ -454,10 +477,11 @@ int my_load_defaults(const char *conf_file, const char **groups, goto err; res= (char**) (ptr+sizeof(alloc)); res[0]= **argv; /* Copy program name */ + /* set arguments separator */ + res[1]= (char *)args_separator; for (i=2 ; i < (uint) *argc ; i++) - res[i-1]=argv[0][i]; - res[i-1]=0; /* End pointer */ - (*argc)--; + res[i]=argv[0][i]; + res[i]=0; /* End pointer */ *argv=res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ if (default_directories) @@ -487,7 +511,7 @@ int my_load_defaults(const char *conf_file, const char **groups, or a forced default file */ if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (args.elements + *argc +1) *sizeof(char*)))) + (args.elements + *argc + 1 + 1) *sizeof(char*)))) goto err; res= (char**) (ptr+sizeof(alloc)); @@ -508,12 +532,16 @@ int my_load_defaults(const char *conf_file, const char **groups, --*argc; ++*argv; /* skip argument */ } + /* set arguments separator for arguments from config file and + command line */ + res[args.elements+1]= (char *)args_separator; + if (*argc) - memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1), + memcpy((uchar*) (res+1+args.elements+1), (char*) ((*argv)+1), (*argc-1)*sizeof(char*)); - res[args.elements+ *argc]=0; /* last null */ + res[args.elements+ *argc+1]=0; /* last null */ - (*argc)+=args.elements; + (*argc)+=args.elements+1; *argv= (char**) res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ delete_dynamic(&args); @@ -523,7 +551,8 @@ int my_load_defaults(const char *conf_file, const char **groups, printf("%s would have been started with the following arguments:\n", **argv); for (i=1 ; i < *argc ; i++) - printf("%s ", (*argv)[i]); + if ((*argv)[i] != args_separator) /* skip arguments separator */ + printf("%s ", (*argv)[i]); puts(""); exit(0); } diff --git a/mysys/default_modify.c b/mysys/default_modify.c index 88df0122da2..b214a1df445 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -21,7 +21,7 @@ #define BUFF_SIZE 1024 #define RESERVE 1024 /* Extend buffer with this extent */ -#ifdef __WIN__ +#ifdef _WIN32 #define NEWLINE "\r\n" #define NEWLINE_LEN 2 #else @@ -78,7 +78,7 @@ int modify_defaults_file(const char *file_location, const char *option, 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) @@ -213,7 +213,7 @@ int modify_defaults_file(const char *file_location, const char *option, 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), diff --git a/mysys/errors.c b/mysys/errors.c index 8d3303cac9f..4000c5c4e52 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -106,3 +106,8 @@ void wait_for_free_space(const char *filename, int errors) MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC ); VOID(sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC)); } + +const char **get_global_errmsgs() +{ + return globerrs; +} diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 8042dc2828b..139a61da1f0 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -112,6 +112,7 @@ #include <my_bit.h> #include <errno.h> #include <stdarg.h> +#include "probes_mysql.h" /* Some compilation flags have been added specifically for this module @@ -2555,6 +2556,15 @@ uchar *key_cache_read(KEY_CACHE *keycache, uint offset; int page_st; + if (MYSQL_KEYCACHE_READ_START_ENABLED()) + { + MYSQL_KEYCACHE_READ_START(my_filename(file), length, + (ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } + /* When the key cache is once initialized, we use the cache_lock to reliably distinguish the cases of normal operation, resizing, and @@ -2606,6 +2616,9 @@ uchar *key_cache_read(KEY_CACHE *keycache, /* Request the cache block that matches file/pos. */ keycache->global_cache_r_requests++; + + MYSQL_KEYCACHE_READ_BLOCK(keycache->key_cache_block_size); + block=find_key_block(keycache, file, filepos, level, 0, &page_st); if (!block) { @@ -2625,6 +2638,7 @@ uchar *key_cache_read(KEY_CACHE *keycache, { if (page_st != PAGE_READ) { + MYSQL_KEYCACHE_READ_MISS(); /* The requested page is to be read into the block buffer */ read_block(keycache, block, keycache->key_cache_block_size, read_length+offset, @@ -2649,6 +2663,10 @@ uchar *key_cache_read(KEY_CACHE *keycache, my_errno= -1; block->status|= BLOCK_ERROR; } + else + { + MYSQL_KEYCACHE_READ_HIT(); + } } /* block status may have added BLOCK_ERROR in the above 'if'. */ @@ -2701,7 +2719,16 @@ uchar *key_cache_read(KEY_CACHE *keycache, #ifndef THREAD /* This is only true if we where able to read everything in one block */ if (return_buffer) + { + if (MYSQL_KEYCACHE_READ_DONE_ENABLED()) + { + MYSQL_KEYCACHE_READ_DONE((ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } DBUG_RETURN(block->buffer); + } #endif next_block: buff+= read_length; @@ -2709,6 +2736,13 @@ uchar *key_cache_read(KEY_CACHE *keycache, offset= 0; } while ((length-= read_length)); + if (MYSQL_KEYCACHE_READ_DONE_ENABLED()) + { + MYSQL_KEYCACHE_READ_DONE((ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } goto end; } KEYCACHE_DBUG_PRINT("key_cache_read", ("keycache not initialized")); @@ -3047,6 +3081,15 @@ int key_cache_write(KEY_CACHE *keycache, uint offset; int page_st; + if (MYSQL_KEYCACHE_WRITE_START_ENABLED()) + { + MYSQL_KEYCACHE_WRITE_START(my_filename(file), length, + (ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } + /* When the key cache is once initialized, we use the cache_lock to reliably distinguish the cases of normal operation, resizing, and @@ -3082,6 +3125,8 @@ int key_cache_write(KEY_CACHE *keycache, /* Cache could be disabled in a later iteration. */ if (!keycache->can_be_used) goto no_key_cache; + + MYSQL_KEYCACHE_WRITE_BLOCK(keycache->key_cache_block_size); /* Start writing at the beginning of the cache block. */ filepos-= offset; /* Do not write beyond the end of the cache block. */ @@ -3295,6 +3340,15 @@ end: dec_counter_for_resize_op(keycache); keycache_pthread_mutex_unlock(&keycache->cache_lock); } + + if (MYSQL_KEYCACHE_WRITE_DONE_ENABLED()) + { + MYSQL_KEYCACHE_WRITE_DONE((ulong) (keycache->blocks_used * + keycache->key_cache_block_size), + (ulong) (keycache->blocks_unused * + keycache->key_cache_block_size)); + } + #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) DBUG_EXECUTE("exec", test_key_cache(keycache, "end of key_cache_write", 1);); diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c index 6227a05ce06..999e8cc7975 100644 --- a/mysys/mf_keycaches.c +++ b/mysys/mf_keycaches.c @@ -108,9 +108,9 @@ static my_bool safe_hash_init(SAFE_HASH *hash, uint elements, uchar *default_value) { DBUG_ENTER("safe_hash"); - if (hash_init(&hash->hash, &my_charset_bin, elements, - 0, 0, (hash_get_key) safe_hash_entry_get, - (void (*)(void*)) safe_hash_entry_free, 0)) + if (my_hash_init(&hash->hash, &my_charset_bin, elements, + 0, 0, (my_hash_get_key) safe_hash_entry_get, + (void (*)(void*)) safe_hash_entry_free, 0)) { hash->default_value= 0; DBUG_RETURN(1); @@ -137,7 +137,7 @@ static void safe_hash_free(SAFE_HASH *hash) */ if (hash->default_value) { - hash_free(&hash->hash); + my_hash_free(&hash->hash); rwlock_destroy(&hash->mutex); hash->default_value=0; } @@ -152,7 +152,7 @@ static uchar *safe_hash_search(SAFE_HASH *hash, const uchar *key, uint length) uchar *result; DBUG_ENTER("safe_hash_search"); rw_rdlock(&hash->mutex); - result= hash_search(&hash->hash, key, length); + result= my_hash_search(&hash->hash, key, length); rw_unlock(&hash->mutex); if (!result) result= hash->default_value; @@ -192,7 +192,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data)); rw_wrlock(&hash->mutex); - entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length); + entry= (SAFE_HASH_ENTRY*) my_hash_search(&hash->hash, key, length); if (data == hash->default_value) { @@ -206,7 +206,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, /* unlink entry from list */ if ((*entry->prev= entry->next)) entry->next->prev= entry->prev; - hash_delete(&hash->hash, (uchar*) entry); + my_hash_delete(&hash->hash, (uchar*) entry); goto end; } if (entry) @@ -277,7 +277,7 @@ static void safe_hash_change(SAFE_HASH *hash, uchar *old_data, uchar *new_data) { if ((*entry->prev= entry->next)) entry->next->prev= entry->prev; - hash_delete(&hash->hash, (uchar*) entry); + my_hash_delete(&hash->hash, (uchar*) entry); } else entry->data= new_data; diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index b1dbb22c687..b9013811b34 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -52,20 +52,13 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) 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 _WIN32 + if (my_win_chsize(fd, newlength)) + { + my_errno= errno; goto err; - if (SetEndOfFile(win_file)) - DBUG_RETURN(0); - my_errno= GetLastError(); - goto err; + } + DBUG_RETURN(0); #elif defined(HAVE_FTRUNCATE) if (ftruncate(fd, (off_t) newlength)) { diff --git a/mysys/my_create.c b/mysys/my_create.c index 5c9a1e027d2..d0436276d03 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -18,7 +18,7 @@ #include "mysys_err.h" #include <errno.h> #include <my_sys.h> -#if defined(__WIN__) +#if defined(_WIN32) #include <share.h> #endif @@ -41,16 +41,12 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, FileName, CreateFlags, access_flags, MyFlags)); #if !defined(NO_OPEN_3) - fd = open((char *) FileName, access_flags | O_CREAT, + fd= open((char *) FileName, access_flags | O_CREAT, CreateFlags ? CreateFlags : my_umask); -#elif defined(VMS) - fd = open((char *) FileName, access_flags | O_CREAT, 0, - "ctx=stm","ctx=bin"); -#elif defined(__WIN__) - fd= my_sopen((char *) FileName, access_flags | O_CREAT | O_BINARY, - SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); +#elif defined(_WIN32) + fd= my_win_open(FileName, access_flags | O_CREAT); #else - fd = open(FileName, access_flags); + fd= open(FileName, access_flags); #endif if ((MyFlags & MY_SYNC_DIR) && (fd >=0) && @@ -71,6 +67,7 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, if (unlikely(fd >= 0 && rc < 0)) { int tmp= my_errno; + my_close(fd, MyFlags); my_delete(FileName, MyFlags); my_errno= tmp; } diff --git a/mysys/my_delete.c b/mysys/my_delete.c index 22425ed95fd..3ab6ba399f9 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -36,7 +36,7 @@ int my_delete(const char *name, myf MyFlags) DBUG_RETURN(err); } /* my_delete */ -#if defined(__WIN__) && defined(__NT__) +#if defined(__WIN__) /* Delete file which is possibly not closed. diff --git a/mysys/my_dup.c b/mysys/my_dup.c index 55f5e0c0099..5fdd6e9f364 100644 --- a/mysys/my_dup.c +++ b/mysys/my_dup.c @@ -29,7 +29,11 @@ File my_dup(File file, myf MyFlags) const char *filename; DBUG_ENTER("my_dup"); DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags)); - fd = dup(file); +#ifdef _WIN32 + fd= my_win_dup(file); +#else + fd= dup(file); +#endif filename= (((uint) file < my_file_limit) ? my_file_info[(int) file].name : "Unknown"); DBUG_RETURN(my_register_filename(fd, filename, FILE_BY_DUP, diff --git a/mysys/my_error.c b/mysys/my_error.c index 2cf704d0089..e2523a39d0b 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -22,7 +22,6 @@ /* Max length of a error message. Should be kept in sync with MYSQL_ERRMSG_SIZE. */ #define ERRMSGSIZE (512) - /* Define some external variables for error handling */ /* @@ -49,11 +48,11 @@ */ static struct my_err_head { - struct my_err_head *meh_next; /* chain link */ - const char **meh_errmsgs; /* error messages array */ - int meh_first; /* error number matching array slot 0 */ - int meh_last; /* error number matching last slot */ -} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST}; + struct my_err_head *meh_next; /* chain link */ + const char** (*get_errmsgs) (); /* returns error message format */ + int meh_first; /* error number matching array slot 0 */ + int meh_last; /* error number matching last slot */ +} my_errmsgs_globerrs = {NULL, get_global_errmsgs, EE_ERROR_FIRST, EE_ERROR_LAST}; static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; @@ -67,12 +66,9 @@ static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; MyFlags Flags ... variable list - RETURN - What (*error_handler_hook)() returns: - 0 OK */ -int my_error(int nr, myf MyFlags, ...) +void my_error(int nr, myf MyFlags, ...) { const char *format; struct my_err_head *meh_p; @@ -88,15 +84,17 @@ int my_error(int nr, myf MyFlags, ...) /* get the error message string. Default, if NULL or empty string (""). */ if (! (format= (meh_p && (nr >= meh_p->meh_first)) ? - meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format) + meh_p->get_errmsgs()[nr - meh_p->meh_first] : NULL) || ! *format) (void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr); else { va_start(args,MyFlags); - (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args); + (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + sizeof(ebuff), format, args); va_end(args); } - DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags)); + (*error_handler_hook)(nr, ebuff, MyFlags); + DBUG_VOID_RETURN; } @@ -111,7 +109,7 @@ int my_error(int nr, myf MyFlags, ...) ... variable list */ -int my_printf_error(uint error, const char *format, myf MyFlags, ...) +void my_printf_error(uint error, const char *format, myf MyFlags, ...) { va_list args; char ebuff[ERRMSGSIZE]; @@ -120,9 +118,34 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...) error, MyFlags, errno, format)); va_start(args,MyFlags); - (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args); + (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + sizeof(ebuff), format, args); va_end(args); - DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags)); + (*error_handler_hook)(error, ebuff, MyFlags); + DBUG_VOID_RETURN; +} + +/* + Error with va_list + + SYNOPSIS + my_printv_error() + error Errno + format Format string + MyFlags Flags + ... variable list +*/ + +void my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) +{ + char ebuff[ERRMSGSIZE]; + DBUG_ENTER("my_printv_error"); + DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s", + error, MyFlags, errno, format)); + + (void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap); + (*error_handler_hook)(error, ebuff, MyFlags); + DBUG_VOID_RETURN; } /* @@ -135,9 +158,9 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...) MyFlags Flags */ -int my_message(uint error, const char *str, register myf MyFlags) +void my_message(uint error, const char *str, register myf MyFlags) { - return (*error_handler_hook)(error, str, MyFlags); + (*error_handler_hook)(error, str, MyFlags); } @@ -163,7 +186,7 @@ int my_message(uint error, const char *str, register myf MyFlags) != 0 Error */ -int my_error_register(const char **errmsgs, int first, int last) +int my_error_register(const char** (*get_errmsgs) (), int first, int last) { struct my_err_head *meh_p; struct my_err_head **search_meh_pp; @@ -172,7 +195,7 @@ int my_error_register(const char **errmsgs, int first, int last) if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head), MYF(MY_WME)))) return 1; - meh_p->meh_errmsgs= errmsgs; + meh_p->get_errmsgs= get_errmsgs; meh_p->meh_first= first; meh_p->meh_last= last; @@ -243,7 +266,7 @@ const char **my_error_unregister(int first, int last) *search_meh_pp= meh_p->meh_next; /* Save the return value and free the header. */ - errmsgs= meh_p->meh_errmsgs; + errmsgs= meh_p->get_errmsgs(); my_free((uchar*) meh_p, MYF(0)); return errmsgs; diff --git a/mysys/my_file.c b/mysys/my_file.c index 44bacf55307..ec0c9c425ea 100644 --- a/mysys/my_file.c +++ b/mysys/my_file.c @@ -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); diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index 44156da6ae3..879acac0111 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -41,24 +41,14 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) DBUG_ENTER("my_fopen"); DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %d", filename, flags, MyFlags)); - /* - if we are not creating, then we need to use my_access to make sure - the file exists since Windows doesn't handle files like "com1.sym" - very well - */ -#ifdef __WIN__ - if (check_if_legal_filename(filename)) - { - errno= EACCES; - fd= 0; - } - else + + make_ftype(type,flags); + +#ifdef _WIN32 + fd= my_win_fopen(filename, type); +#else + fd= fopen(filename, type); #endif - { - make_ftype(type,flags); - fd = fopen(filename, type); - } - if (fd != 0) { /* @@ -66,18 +56,20 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) 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= my_fileno(fd); + if ((uint)filedesc >= my_file_limit) { thread_safe_increment(my_stream_opened,&THR_LOCK_open); DBUG_RETURN(fd); /* safeguard */ } 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: 0x%lx", (long) fd)); DBUG_RETURN(fd); @@ -99,6 +91,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) /* Close a stream */ +/* Close a stream */ int my_fclose(FILE *fd, myf MyFlags) { int err,file; @@ -106,8 +99,13 @@ int my_fclose(FILE *fd, myf MyFlags) DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags)); pthread_mutex_lock(&THR_LOCK_open); - file=fileno(fd); - if ((err = fclose(fd)) < 0) + file= my_fileno(fd); +#ifndef _WIN32 + err= fclose(fd); +#else + err= my_win_fclose(fd); +#endif + if(err < 0) { my_errno=errno; if (MyFlags & (MY_FAE | MY_WME)) @@ -138,7 +136,12 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) Filedes, Flags, MyFlags)); make_ftype(type,Flags); - if ((fd = fdopen(Filedes, type)) == 0) +#ifdef _WIN32 + fd= my_win_fdopen(Filedes, type); +#else + fd= fdopen(Filedes, type); +#endif + if (!fd) { my_errno=errno; if (MyFlags & (MY_FAE | MY_WME)) diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index f3b5418b906..2059e1a9f18 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -56,11 +56,11 @@ size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags) { 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)) @@ -142,7 +142,7 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) 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; @@ -182,3 +182,14 @@ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused))) DBUG_PRINT("exit",("ftell: %lu",(ulong) pos)); DBUG_RETURN((my_off_t) pos); } /* my_ftell */ + + +/* Get a File corresponding to the stream*/ +int my_fileno(FILE *f) +{ +#ifdef _WIN32 + return my_win_fileno(f); +#else + return fileno(f); +#endif +} diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index c7f138c7337..38fa0313c5d 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -101,7 +101,105 @@ err: return res; } -#else /* FreeBSD elif linux */ +#elif defined(__WIN__) +
+/* Workaround for BUG#32082 (Definition of VOID in my_global.h conflicts with
+windows headers) */
+#ifdef VOID
+#undef VOID
+#define VOID void
+#endif
+ +#include <iphlpapi.h> + +/* + The following typedef is for dynamically loading + iphlpapi.dll / GetAdaptersAddresses. Dynamic loading is + used because GetAdaptersAddresses is not available on Windows 2000 + which MySQL still supports. Static linking would cause an unresolved export. +*/ +typedef DWORD (WINAPI *pfnGetAdaptersAddresses)(IN ULONG Family, + IN DWORD Flags,IN PVOID Reserved, + OUT PIP_ADAPTER_ADDRESSES pAdapterAddresses, + IN OUT PULONG pOutBufLen); + +/* + my_gethwaddr - Windows version + + @brief Retrieve MAC address from network hardware + + @param[out] to MAC address exactly six bytes + + @return Operation status + @retval 0 OK + @retval <>0 FAILED +*/ +my_bool my_gethwaddr(uchar *to) +{ + PIP_ADAPTER_ADDRESSES pAdapterAddresses; + PIP_ADAPTER_ADDRESSES pCurrAddresses; + IP_ADAPTER_ADDRESSES adapterAddresses; + ULONG address_len; + my_bool return_val= 1; + static pfnGetAdaptersAddresses fnGetAdaptersAddresses= + (pfnGetAdaptersAddresses)-1; + + if(fnGetAdaptersAddresses == (pfnGetAdaptersAddresses)-1) + { + /* Get the function from the DLL */ + fnGetAdaptersAddresses= (pfnGetAdaptersAddresses) + GetProcAddress(LoadLibrary("iphlpapi.dll"), + "GetAdaptersAddresses"); + } + if (!fnGetAdaptersAddresses) + return 1; /* failed to get function */ + address_len= sizeof (IP_ADAPTER_ADDRESSES); + + /* Get the required size for the address data. */ + if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, &adapterAddresses, &address_len) + == ERROR_BUFFER_OVERFLOW) + { + pAdapterAddresses= my_malloc(address_len, 0); + if (!pAdapterAddresses) + return 1; /* error, alloc failed */ + } + else + pAdapterAddresses= &adapterAddresses; /* one is enough don't alloc */ + + /* Get the hardware info. */ + if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &address_len) + == NO_ERROR) + { + pCurrAddresses= pAdapterAddresses; + + while (pCurrAddresses) + { + /* Look for ethernet cards. */ + if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD) + { + /* check for a good address */ + if (pCurrAddresses->PhysicalAddressLength < 6) + continue; /* bad address */ + + /* save 6 bytes of the address in the 'to' parameter */ + memcpy(to, pCurrAddresses->PhysicalAddress, 6); + + /* Network card found, we're done. */ + return_val= 0; + break; + } + pCurrAddresses= pCurrAddresses->Next; + } + } + + /* Clean up memory allocation. */ + if (pAdapterAddresses != &adapterAddresses) + my_free(pAdapterAddresses, 0); + + return return_val; +} + +#else /* __FreeBSD__ || __linux__ || __WIN__ */ /* just fail */ my_bool my_gethwaddr(uchar *to __attribute__((unused))) { diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index fc5662812b0..b91f46df0c4 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -121,6 +121,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *optp; uchar* *value; int error, i; + my_bool is_cmdline_arg= 1; LINT_INIT(opt_found); /* handle_options() assumes arg0 (program name) always exists */ @@ -130,10 +131,34 @@ int handle_options(int *argc, char ***argv, (*argv)++; /* --- || ---- */ init_variables(longopts, init_one_value); + /* + Search for args_separator, if found, then the first part of the + arguments are loaded from configs + */ + for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) + { + if (*pos == args_separator) + { + is_cmdline_arg= 0; + break; + } + } + for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { char **first= pos; char *cur_arg= *pos; + if (!is_cmdline_arg && (cur_arg == args_separator)) + { + is_cmdline_arg= 1; + + /* save the separator too if skip unkown options */ + if (my_getopt_skip_unknown) + (*argv)[argvpos++]= cur_arg; + else + (*argc)--; + continue; + } if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ { char *argument= 0; @@ -435,8 +460,12 @@ invalid value '%s'", } else if (optp->arg_type == REQUIRED_ARG && !optend) { - /* Check if there are more arguments after this one */ - if (!*++pos) + /* Check if there are more arguments after this one, + + Note: options loaded from config file that requires value + should always be in the form '--option=value'. + */ + if (!is_cmdline_arg || !*++pos) { if (my_getopt_print_errors) my_getopt_error_reporter(ERROR_LEVEL, diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h index c239cabb168..e4e62f47fed 100644 --- a/mysys/my_handler_errors.h +++ b/mysys/my_handler_errors.h @@ -1,3 +1,5 @@ +#ifndef MYSYS_MY_HANDLER_ERRORS_INCLUDED +#define MYSYS_MY_HANDLER_ERRORS_INCLUDED /* Errors a handler can give you @@ -66,3 +68,4 @@ static const char *handler_error_messages[]= "Too many active concurrent transactions" }; +#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ diff --git a/mysys/my_init.c b/mysys/my_init.c index 453c72f999f..1dc51f065ae 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -27,6 +27,8 @@ #ifdef _MSC_VER #include <locale.h> #include <crtdbg.h> +/* WSAStartup needs winsock library*/
+#pragma comment(lib, "ws2_32") #endif my_bool have_tcpip=0; static void my_win_init(void); diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index b50a606c8d8..d96e1048fd0 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -128,7 +128,7 @@ uchar* my_large_malloc_int(size_t size, myf my_flags) { if (my_flags & MY_WME) fprintf(stderr, - "Warning: Failed to allocate %lu bytesx from HugeTLB memory." + "Warning: Failed to allocate %lu bytes from HugeTLB memory." " errno %d\n", (ulong) size, errno); DBUG_RETURN(NULL); diff --git a/mysys/my_lib.c b/mysys/my_lib.c index c18d14fb549..033f8789b49 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -35,8 +35,7 @@ # if defined(HAVE_NDIR_H) # include <ndir.h> # endif -# if defined(__WIN__) -# include <dos.h> +# if defined(_WIN32) # ifdef __BORLANDC__ # include <dir.h> # endif @@ -92,7 +91,7 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b) } /* comp_names */ -#if !defined(__WIN__) +#if !defined(_WIN32) MY_DIR *my_dir(const char *path, myf MyFlags) { @@ -507,19 +506,24 @@ error: DBUG_RETURN((MY_DIR *) NULL); } /* my_dir */ -#endif /* __WIN__ */ +#endif /* _WIN32 */ /**************************************************************************** ** File status ** Note that MY_STAT is assumed to be same as struct stat ****************************************************************************/ -int my_fstat(int Filedes, MY_STAT *stat_area, + +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)); +#ifdef _WIN32 + DBUG_RETURN(my_win_fstat(Filedes, stat_area)); +#else DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area)); +#endif } @@ -531,11 +535,15 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) (long) stat_area, my_flags)); if ((m_used= (stat_area == NULL))) - if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) + if (!(stat_area= (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) goto error; - if (! stat((char *) path, (struct stat *) stat_area) ) - DBUG_RETURN(stat_area); - +#ifndef _WIN32 + if (! stat((char *) path, (struct stat *) stat_area) ) + DBUG_RETURN(stat_area); +#else + if (! my_win_stat(path, stat_area) ) + DBUG_RETURN(stat_area); +#endif DBUG_PRINT("error",("Got errno: %d from stat", errno)); my_errno= errno; if (m_used) /* Free if new area */ diff --git a/mysys/my_lock.c b/mysys/my_lock.c index c0522ee849d..62f39bd3b71 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -22,13 +22,113 @@ #undef NO_ALARM_LOOP #endif #include <my_alarm.h> -#ifdef __WIN__ -#include <sys/locking.h> -#endif #ifdef __NETWARE__ #include <nks/fsio.h> #endif +#ifdef _WIN32 +#define WIN_LOCK_INFINITE -1 +#define WIN_LOCK_SLEEP_MILLIS 100 + +static int win_lock(File fd, int locktype, my_off_t start, my_off_t length, + int timeout_sec) +{ + LARGE_INTEGER liOffset,liLength; + DWORD dwFlags; + OVERLAPPED ov= {0}; + HANDLE hFile= (HANDLE)my_get_osfhandle(fd); + DWORD lastError= 0; + int i; + int timeout_millis= timeout_sec * 1000; + + DBUG_ENTER("win_lock"); + + liOffset.QuadPart= start; + liLength.QuadPart= length; + + ov.Offset= liOffset.LowPart; + ov.OffsetHigh= liOffset.HighPart; + + if (locktype == F_UNLCK) + { + if (UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov)) + DBUG_RETURN(0); + /* + For compatibility with fcntl implementation, ignore error, + if region was not locked + */ + if (GetLastError() == ERROR_NOT_LOCKED) + { + SetLastError(0); + DBUG_RETURN(0); + } + goto error; + } + else if (locktype == F_RDLCK) + /* read lock is mapped to a shared lock. */ + dwFlags= 0; + else + /* write lock is mapped to an exclusive lock. */ + dwFlags= LOCKFILE_EXCLUSIVE_LOCK; + + /* + Drop old lock first to avoid double locking. + During analyze of Bug#38133 (Myisamlog test fails on Windows) + I met the situation that the program myisamlog locked the file + exclusively, then additionally shared, then did one unlock, and + then blocked on an attempt to lock it exclusively again. + Unlocking before every lock fixed the problem. + Note that this introduces a race condition. When the application + wants to convert an exclusive lock into a shared one, it will now + first unlock the file and then lock it shared. A waiting exclusive + lock could step in here. For reasons described in Bug#38133 and + Bug#41124 (Server hangs on Windows with --external-locking after + INSERT...SELECT) and in the review thread at + http://lists.mysql.com/commits/60721 it seems to be the better + option than not to unlock here. + If one day someone notices a way how to do file lock type changes + on Windows without unlocking before taking the new lock, please + change this code accordingly to fix the race condition. + */ + if (!UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov) && + (GetLastError() != ERROR_NOT_LOCKED)) + goto error; + + if (timeout_sec == WIN_LOCK_INFINITE) + { + if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov)) + DBUG_RETURN(0); + goto error; + } + + dwFlags|= LOCKFILE_FAIL_IMMEDIATELY; + timeout_millis= timeout_sec * 1000; + /* Try lock in a loop, until the lock is acquired or timeout happens */ + for(i= 0; ;i+= WIN_LOCK_SLEEP_MILLIS) + { + if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov)) + DBUG_RETURN(0); + + if (GetLastError() != ERROR_LOCK_VIOLATION) + goto error; + + if (i >= timeout_millis) + break; + Sleep(WIN_LOCK_SLEEP_MILLIS); + } + + /* timeout */ + errno= EAGAIN; + DBUG_RETURN(-1); + +error: + my_osmaperr(GetLastError()); + DBUG_RETURN(-1); +} +#endif + + + /* Lock a part of a file @@ -48,8 +148,9 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, #ifdef __NETWARE__ int nxErrno; #endif + DBUG_ENTER("my_lock"); - DBUG_PRINT("my",("Fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", + DBUG_PRINT("my",("fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", fd,locktype,(long) start,(long) length,MyFlags)); #ifdef VMS DBUG_RETURN(0); @@ -97,29 +198,16 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, DBUG_RETURN(0); } } -#elif defined(HAVE_LOCKING) - /* Windows */ +#elif defined(_WIN32) { - my_bool error= FALSE; - pthread_mutex_lock(&my_file_info[fd].mutex); - if (MyFlags & MY_SEEK_NOT_DONE) - { - if( my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE)) - == MY_FILEPOS_ERROR ) - { - /* - If my_seek fails my_errno will already contain an error code; - just unlock and return error code. - */ - DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno)); - pthread_mutex_unlock(&my_file_info[fd].mutex); - DBUG_RETURN(-1); - } - } - error= locking(fd,locktype,(ulong) length) && errno != EINVAL; - pthread_mutex_unlock(&my_file_info[fd].mutex); - if (!error) - DBUG_RETURN(0); + int timeout_sec; + if (MyFlags & MY_DONT_WAIT) + timeout_sec= 0; + else + timeout_sec= WIN_LOCK_INFINITE; + + if(win_lock(fd, locktype, start, length, timeout_sec) == 0) + DBUG_RETURN(0); } #else #if defined(HAVE_FCNTL) diff --git a/mysys/my_messnc.c b/mysys/my_messnc.c index e2431959b7a..e2dee3f6710 100644 --- a/mysys/my_messnc.c +++ b/mysys/my_messnc.c @@ -15,8 +15,8 @@ #include "mysys_priv.h" -int my_message_no_curses(uint error __attribute__((unused)), - const char *str, myf MyFlags) +void my_message_no_curses(uint error __attribute__((unused)), + const char *str, myf MyFlags) { DBUG_ENTER("my_message_no_curses"); DBUG_PRINT("enter",("message: %s",str)); @@ -34,5 +34,5 @@ int my_message_no_curses(uint error __attribute__((unused)), (void)fputs(str,stderr); (void)fputc('\n',stderr); (void)fflush(stderr); - DBUG_RETURN(0); + DBUG_VOID_RETURN; } diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 023a06fd896..303d8efaf30 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -27,17 +27,17 @@ int my_msync(int fd, void *addr, size_t len, int flags) return my_sync(fd, MYF(0)); } -#elif defined(__WIN__) +#elif defined(_WIN32) static SECURITY_ATTRIBUTES mmap_security_attributes= {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; diff --git a/mysys/my_open.c b/mysys/my_open.c index fe7f65c450b..79a4da242f9 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -17,9 +17,7 @@ #include "mysys_err.h" #include <my_dir.h> #include <errno.h> -#if defined(__WIN__) -#include <share.h> -#endif + /* Open a file @@ -43,29 +41,8 @@ File my_open(const char *FileName, int Flags, myf MyFlags) DBUG_ENTER("my_open"); DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", FileName, Flags, MyFlags)); -#if defined(__WIN__) - /* - Check that we don't try to open or create a file name that may - cause problems for us in the future (like PRN) - */ - if (check_if_legal_filename(FileName)) - { - errno= EACCES; - DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN, - EE_FILENOTFOUND, MyFlags)); - } -#ifndef __WIN__ - if (Flags & O_SHARE) - fd = sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, - MY_S_IREAD | MY_S_IWRITE); - else - fd = open((char *) FileName, Flags | O_BINARY, - MY_S_IREAD | MY_S_IWRITE); -#else - fd= my_sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, - MY_S_IREAD | MY_S_IWRITE); -#endif - +#if defined(_WIN32) + fd= my_win_open(FileName, Flags); #elif !defined(NO_OPEN_3) fd = open(FileName, Flags, my_umask); /* Normal unix */ #else @@ -94,11 +71,14 @@ int my_close(File fd, myf MyFlags) DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); pthread_mutex_lock(&THR_LOCK_open); +#ifndef _WIN32 do { err= close(fd); } while (err == -1 && errno == EINTR); - +#else + err= my_win_close(fd); +#endif if (err) { DBUG_PRINT("error",("Got error %d on close",err)); @@ -109,7 +89,7 @@ int my_close(File fd, myf MyFlags) if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN) { my_free(my_file_info[fd].name, MYF(0)); -#if defined(THREAD) && !defined(HAVE_PREAD) +#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) pthread_mutex_destroy(&my_file_info[fd].mutex); #endif my_file_info[fd].type = UNOPEN; @@ -141,11 +121,11 @@ File my_register_filename(File fd, const char *FileName, enum file_type 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) { -#if defined(THREAD) && !defined(HAVE_PREAD) +#if defined(THREAD) && !defined(HAVE_PREAD) my_errno= EMFILE; #else thread_safe_increment(my_file_opened,&THR_LOCK_open); @@ -160,7 +140,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type my_file_opened++; my_file_total_opened++; my_file_info[fd].type = type_of_file; -#if defined(THREAD) && !defined(HAVE_PREAD) +#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32) pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST); #endif pthread_mutex_unlock(&THR_LOCK_open); @@ -187,188 +167,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type DBUG_RETURN(-1); } -#ifdef __WIN__ - -extern void __cdecl _dosmaperr(unsigned long); - -/* - Open a file with sharing. Similar to _sopen() from libc, but allows managing - share delete on win32 - - SYNOPSIS - my_sopen() - path fully qualified file name - oflag operation flags - shflag share flag - pmode permission flags - - RETURN VALUE - File descriptor of opened file if success - -1 and sets errno if fails. -*/ - -File my_sopen(const char *path, int oflag, int shflag, int pmode) -{ - int fh; /* handle of opened file */ - int mask; - HANDLE osfh; /* OS handle of opened file */ - DWORD fileaccess; /* OS file access (requested) */ - DWORD fileshare; /* OS file sharing mode */ - DWORD filecreate; /* OS method of opening/creating */ - DWORD fileattrib; /* OS file attribute flags */ - SECURITY_ATTRIBUTES SecurityAttributes; - - SecurityAttributes.nLength= sizeof(SecurityAttributes); - SecurityAttributes.lpSecurityDescriptor= NULL; - SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT); - - /* - * decode the access flags - */ - switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { - case _O_RDONLY: /* read access */ - fileaccess= GENERIC_READ; - break; - case _O_WRONLY: /* write access */ - fileaccess= GENERIC_WRITE; - break; - case _O_RDWR: /* read and write access */ - fileaccess= GENERIC_READ | GENERIC_WRITE; - break; - default: /* error, bad oflag */ - errno= EINVAL; - _doserrno= 0L; /* not an OS error */ - return -1; - } - - /* - * decode sharing flags - */ - switch (shflag) { - case _SH_DENYRW: /* exclusive access except delete */ - fileshare= FILE_SHARE_DELETE; - break; - case _SH_DENYWR: /* share read and delete access */ - fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE; - break; - case _SH_DENYRD: /* share write and delete access */ - fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE; - break; - case _SH_DENYNO: /* share read, write and delete access */ - fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - break; - case _SH_DENYRWD: /* exclusive access */ - fileshare= 0L; - break; - case _SH_DENYWRD: /* share read access */ - fileshare= FILE_SHARE_READ; - break; - case _SH_DENYRDD: /* share write access */ - fileshare= FILE_SHARE_WRITE; - break; - case _SH_DENYDEL: /* share read and write access */ - fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE; - break; - default: /* error, bad shflag */ - errno= EINVAL; - _doserrno= 0L; /* not an OS error */ - return -1; - } - - /* - * decode open/create method flags - */ - switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) { - case 0: - case _O_EXCL: /* ignore EXCL w/o CREAT */ - filecreate= OPEN_EXISTING; - break; - - case _O_CREAT: - filecreate= OPEN_ALWAYS; - break; - - case _O_CREAT | _O_EXCL: - case _O_CREAT | _O_TRUNC | _O_EXCL: - filecreate= CREATE_NEW; - break; - - case _O_TRUNC: - case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */ - filecreate= TRUNCATE_EXISTING; - break; - - case _O_CREAT | _O_TRUNC: - filecreate= CREATE_ALWAYS; - break; - - default: - /* this can't happen ... all cases are covered */ - errno= EINVAL; - _doserrno= 0L; - return -1; - } - - /* - * decode file attribute flags if _O_CREAT was specified - */ - fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */ - if (oflag & _O_CREAT) - { - _umask((mask= _umask(0))); - - if (!((pmode & ~mask) & _S_IWRITE)) - fileattrib= FILE_ATTRIBUTE_READONLY; - } - - /* - * Set temporary file (delete-on-close) attribute if requested. - */ - if (oflag & _O_TEMPORARY) - { - fileattrib|= FILE_FLAG_DELETE_ON_CLOSE; - fileaccess|= DELETE; - } - - /* - * Set temporary file (delay-flush-to-disk) attribute if requested. - */ - if (oflag & _O_SHORT_LIVED) - fileattrib|= FILE_ATTRIBUTE_TEMPORARY; - - /* - * Set sequential or random access attribute if requested. - */ - if (oflag & _O_SEQUENTIAL) - fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN; - else if (oflag & _O_RANDOM) - fileattrib|= FILE_FLAG_RANDOM_ACCESS; - - /* - * try to open/create the file - */ - if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, - filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE) - { - /* - * OS call to open/create file failed! map the error, release - * 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 */ - return -1; /* return error to caller */ - } - - if ((fh= _open_osfhandle((intptr_t)osfh, - oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1) - { - _dosmaperr(GetLastError()); /* map error */ - CloseHandle(osfh); - } - return fh; /* return handle */ -} -#endif /* __WIN__ */ #ifdef EXTRA_DEBUG diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 3f62f150c91..eaabcb1b728 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -15,11 +15,15 @@ #include "mysys_priv.h" #include "mysys_err.h" +#include "my_base.h" +#include <m_string.h> #include <errno.h> -#ifdef HAVE_PREAD +#if defined (HAVE_PREAD) && !defined(_WIN32) #include <unistd.h> #endif + + /* Read a chunk of bytes from a file from a given position @@ -46,27 +50,39 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, { size_t readbytes; int error= 0; +#if !defined (HAVE_PREAD) && !defined (_WIN32) + int save_errno; +#endif DBUG_ENTER("my_pread"); - DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, (ulong) offset, (long) Buffer, (uint) Count, - MyFlags)); + DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d", + Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags)); for (;;) { -#ifndef __WIN__ - errno=0; /* Linux doesn't reset this */ -#endif -#ifndef HAVE_PREAD + errno= 0; /* Linux, Windows don't reset this on EOF/success */ +#if !defined (HAVE_PREAD) && !defined (_WIN32) pthread_mutex_lock(&my_file_info[Filedes].mutex); readbytes= (uint) -1; error= (lseek(Filedes, offset, MY_SEEK_SET) == (my_off_t) -1 || - (readbytes= read(Filedes, Buffer, (uint) Count)) != Count); + (readbytes= read(Filedes, Buffer, Count)) != Count); + save_errno= errno; pthread_mutex_unlock(&my_file_info[Filedes].mutex); + if (error) + errno= save_errno; #else - if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count))) - my_errno= errno ? errno : -1; +#if defined(_WIN32) + readbytes= my_win_pread(Filedes, Buffer, Count, offset); +#else + readbytes= pread(Filedes, Buffer, Count, offset); +#endif + error= (readbytes != Count); #endif - if (error || readbytes != Count) + if(error) { + my_errno= errno ? errno : -1; + if (errno == 0 || (readbytes != (size_t) -1 && + (MyFlags & (MY_NABP | MY_FNABP)))) + my_errno= HA_ERR_FILE_TOO_SHORT; + DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", (int) readbytes, (uint) Count,Filedes,my_errno)); #ifdef THREAD @@ -79,19 +95,19 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, #endif if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - if (readbytes == (size_t) -1) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - else if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); + if (readbytes == (size_t) -1) + my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); + else if (MyFlags & (MY_NABP | MY_FNABP)) + my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), + my_filename(Filedes),my_errno); } if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP))) - DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ + DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ } if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Read went ok; Return 0 */ - DBUG_RETURN(readbytes); /* purecov: inspected */ + DBUG_RETURN(0); /* Read went ok; Return 0 */ + DBUG_RETURN(readbytes); /* purecov: inspected */ } } /* my_pread */ @@ -117,42 +133,45 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, # 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; + size_t writtenbytes, written; uint errors; + DBUG_ENTER("my_pwrite"); - DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, (ulong) offset, (long) Buffer, (uint) Count, - MyFlags)); + DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d", + Filedes, offset, Buffer, (ulong)Count, MyFlags)); errors= 0; written= 0; for (;;) { -#ifndef HAVE_PREAD +#if !defined (HAVE_PREAD) && !defined (_WIN32) int error; - writenbytes= (size_t) -1; + writtenbytes= (size_t) -1; pthread_mutex_lock(&my_file_info[Filedes].mutex); error= (lseek(Filedes, offset, MY_SEEK_SET) != (my_off_t) -1 && - (writenbytes = write(Filedes, Buffer, (uint) Count)) == Count); + (writtenbytes= write(Filedes, Buffer, Count)) == Count); pthread_mutex_unlock(&my_file_info[Filedes].mutex); if (error) break; +#elif defined (_WIN32) + writtenbytes= my_win_pwrite(Filedes, Buffer, Count, offset); #else - if ((writenbytes= pwrite(Filedes, Buffer, Count,offset)) == Count) + writtenbytes= pwrite(Filedes, Buffer, Count, offset); +#endif + if(writtenbytes == Count) break; my_errno= errno; -#endif - if (writenbytes != (size_t) -1) - { /* Safegueard */ - written+=writenbytes; - Buffer+=writenbytes; - Count-=writenbytes; - offset+=writenbytes; + if (writtenbytes != (size_t) -1) + { + written+= writtenbytes; + Buffer+= writtenbytes; + Count-= writtenbytes; + offset+= writtenbytes; } - DBUG_PRINT("error",("Write only %u bytes", (uint) writenbytes)); + DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes)); #ifndef NO_BACKGROUND #ifdef THREAD if (my_thread_var->abort) @@ -165,15 +184,15 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, errors++; continue; } - if ((writenbytes && writenbytes != (size_t) -1) || my_errno == EINTR) + if ((writtenbytes && writtenbytes != (size_t) -1) || my_errno == EINTR) continue; /* Retry */ #endif if (MyFlags & (MY_NABP | MY_FNABP)) { if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG), - my_filename(Filedes),my_errno); + my_error(EE_WRITE, MYF(ME_BELL | ME_WAITTANG), + my_filename(Filedes),my_errno); } DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ } @@ -183,5 +202,5 @@ size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, DBUG_EXECUTE_IF("check", my_seek(Filedes, -1, SEEK_SET, MYF(0));); if (MyFlags & (MY_NABP | MY_FNABP)) DBUG_RETURN(0); /* Want only errors */ - DBUG_RETURN(writenbytes+written); /* purecov: inspected */ + DBUG_RETURN(writtenbytes+written); /* purecov: inspected */ } /* my_pwrite */ diff --git a/mysys/my_quick.c b/mysys/my_quick.c index 0ba20a5bdee..b93e7e17224 100644 --- a/mysys/my_quick.c +++ b/mysys/my_quick.c @@ -19,11 +19,19 @@ #include "my_nosys.h" +#ifdef _WIN32 +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, (uint) Count)) != Count) +#ifdef _WIN32 + 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) @@ -40,8 +48,13 @@ size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags) } -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) { +#ifdef _WIN32 + return my_win_write(Filedes, Buffer, Count); +#else + #ifndef DBUG_OFF size_t writtenbytes; #endif @@ -50,7 +63,7 @@ size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count) #ifndef DBUG_OFF writtenbytes = #endif - (size_t) write(Filedes,Buffer, (uint) Count)) != Count) + (size_t) write(Filedes,Buffer,Count)) != Count) { #ifndef DBUG_OFF if ((writtenbytes == 0 || writtenbytes == (size_t) -1) && errno == EINTR) @@ -64,4 +77,5 @@ size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count) return (size_t) -1; } return 0; +#endif } diff --git a/mysys/my_read.c b/mysys/my_read.c index 0c302d5b227..75f9dd64f1d 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -15,9 +15,9 @@ #include "mysys_priv.h" #include "mysys_err.h" +#include <my_base.h> #include <errno.h> - /* Read a chunk of bytes from a file with retry's if needed @@ -37,16 +37,25 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) { size_t readbytes, save_count; DBUG_ENTER("my_read"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); + DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", + Filedes, Buffer, (ulong) Count, MyFlags)); save_count= Count; for (;;) { - errno= 0; /* Linux doesn't reset this */ - if ((readbytes= read(Filedes, Buffer, (uint) Count)) != Count) + errno= 0; /* Linux, Windows don't reset this on EOF/success */ +#ifdef _WIN32 + readbytes= my_win_read(Filedes, Buffer, Count); +#else + readbytes= read(Filedes, Buffer, Count); +#endif + + if (readbytes != Count) { - my_errno= errno ? errno : -1; + my_errno= errno; + if (errno == 0 || (readbytes != (size_t) -1 && + (MyFlags & (MY_NABP | MY_FNABP)))) + my_errno= HA_ERR_FILE_TOO_SHORT; DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", (int) readbytes, (ulong) Count, Filedes, my_errno)); diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 2c661baeff7..8502c259353 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -45,36 +45,30 @@ 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) - if (MyFlags & MY_THREADSAFE) - { - pthread_mutex_lock(&my_file_info[fd].mutex); - newpos= lseek(fd, pos, whence); - pthread_mutex_unlock(&my_file_info[fd].mutex); - } - else +#if defined (_WIN32) + newpos= my_win_lseek(fd, pos, whence); +#else + newpos= lseek(fd, pos, whence); #endif - newpos= lseek(fd, pos, whence); if (newpos == (os_off_t) -1) { - my_errno=errno; - DBUG_PRINT("error",("lseek: %lu errno: %d", (ulong) newpos,errno)); + my_errno= 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 */ @@ -87,15 +81,15 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused))) { os_off_t pos; DBUG_ENTER("my_tell"); - DBUG_PRINT("my",("Fd: %d MyFlags: %d",fd, MyFlags)); + DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); DBUG_ASSERT(fd >= 0); -#ifdef HAVE_TELL - pos=tell(fd); +#if defined (HAVE_TELL) && !defined (_WIN32) + 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)); + my_errno= errno; + DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos)); DBUG_RETURN((my_off_t) pos); } /* my_tell */ diff --git a/mysys/my_static.c b/mysys/my_static.c index a21a3d11104..62e6d402315 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. 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 @@ -35,7 +35,7 @@ int NEAR my_umask=0664, NEAR my_umask_dir=0777; #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; @@ -87,9 +87,9 @@ ulong my_time_to_wait_for_lock=2; /* In seconds */ char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */ #endif void (*my_abort_hook)(int) = (void(*)(int)) exit; -int (*error_handler_hook)(uint error,const char *str,myf MyFlags)= +void (*error_handler_hook)(uint error,const char *str,myf MyFlags)= my_message_no_curses; -int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)= +void (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)= my_message_no_curses; #if defined(ENABLED_DEBUG_SYNC) diff --git a/mysys/my_static.h b/mysys/my_static.h index 90168b099a8..c336115bc35 100644 --- a/mysys/my_static.h +++ b/mysys/my_static.h @@ -1,3 +1,6 @@ +#ifndef MYSYS_MY_STATIC_INCLUDED +#define MYSYS_MY_STATIC_INCLUDED + /* Copyright (C) 2000 MySQL AB This program is free software; you can redistribute it and/or modify @@ -72,3 +75,5 @@ extern ulonglong query_performance_frequency, query_performance_offset; extern sigset_t my_signals; /* signals blocked by mf_brkhant */ #endif C_MODE_END + +#endif /* MYSYS_MY_STATIC_INCLUDED */ diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 97540f5eb48..6497ae59159 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -62,8 +62,8 @@ int my_sync(File fd, myf my_flags) res= fdatasync(fd); #elif defined(HAVE_FSYNC) res= fsync(fd); -#elif defined(__WIN__) - res= _commit(fd); +#elif defined(_WIN32) + res= my_win_fsync(fd); #else #error Cannot find a way to sync a file, durability in danger res= 0; /* No sync (strange OS) */ diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 0e62cde386e..a99cbfca30c 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -23,11 +23,7 @@ #include <signal.h> #ifdef THREAD -#ifdef USE_TLS pthread_key(struct st_my_thread_var*, THR_KEY_mysys); -#else -pthread_key(struct st_my_thread_var, THR_KEY_mysys); -#endif /* USE_TLS */ pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open, THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap, THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time, @@ -48,7 +44,9 @@ pthread_mutexattr_t my_fast_mutexattr; #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_mutexattr_t my_errorcheck_mutexattr; #endif - +#ifdef _MSC_VER +static void install_sigabrt_handler(); +#endif #ifdef TARGET_OS_LINUX /* @@ -153,15 +151,18 @@ my_bool my_thread_global_init(void) pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST); pthread_cond_init(&THR_COND_threads, NULL); -#if defined( __WIN__) || defined(OS2) - win_pthread_init(); -#endif + #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW); #endif #ifndef HAVE_GETHOSTBYNAME_R pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW); #endif + +#ifdef _MSC_VER + install_sigabrt_handler(); +#endif + if (my_thread_init()) { my_thread_global_end(); /* Clean up */ @@ -263,7 +264,6 @@ my_bool my_thread_init(void) (ulong) pthread_self()); #endif -#if !defined(__WIN__) || defined(USE_TLS) if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) { #ifdef EXTRA_DEBUG_THREADS @@ -272,26 +272,18 @@ my_bool my_thread_init(void) #endif goto end; } + +#ifdef _MSC_VER + install_sigabrt_handler(); +#endif + if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp)))) { error= 1; goto end; } pthread_setspecific(THR_KEY_mysys,tmp); - -#else /* defined(__WIN__) && !(defined(USE_TLS) */ - /* - Skip initialization if the thread specific variable is already initialized - */ - if (THR_KEY_mysys.id) - goto end; - tmp= &THR_KEY_mysys; -#endif -#if defined(__WIN__) && defined(EMBEDDED_LIBRARY) - tmp->pthread_self= (pthread_t) getpid(); -#else tmp->pthread_self= pthread_self(); -#endif pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST); pthread_cond_init(&tmp->suspend, NULL); tmp->init= 1; @@ -347,11 +339,7 @@ void my_thread_end(void) pthread_cond_destroy(&tmp->suspend); #endif pthread_mutex_destroy(&tmp->mutex); -#if !defined(__WIN__) || defined(USE_TLS) free(tmp); -#else - tmp->init= 0; -#endif /* Decrement counter for number of running threads. We are using this @@ -365,10 +353,7 @@ void my_thread_end(void) pthread_cond_signal(&THR_COND_threads); pthread_mutex_unlock(&THR_LOCK_threads); } - /* The following free has to be done, even if my_thread_var() is 0 */ -#if !defined(__WIN__) || defined(USE_TLS) pthread_setspecific(THR_KEY_mysys,0); -#endif } struct st_my_thread_var *_my_thread_var(void) @@ -406,6 +391,15 @@ const char *my_thread_name(void) } return tmp->name; } + +/* Return pointer to DBUG for holding current state */ + +extern void **my_thread_var_dbug() +{ + struct st_my_thread_var *tmp= + my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + return tmp && tmp->init ? &tmp->dbug : 0; +} #endif /* DBUG_OFF */ @@ -424,4 +418,30 @@ static uint get_thread_lib(void) return THD_LIB_OTHER; } +#ifdef _WIN32 +/* + In Visual Studio 2005 and later, default SIGABRT handler will overwrite + any unhandled exception filter set by the application and will try to + call JIT debugger. This is not what we want, this we calling __debugbreak + to stop in debugger, if process is being debugged or to generate + EXCEPTION_BREAKPOINT and then handle_segfault will do its magic. +*/ + +#if (_MSC_VER >= 1400) +static void my_sigabrt_handler(int sig) +{ + __debugbreak(); +} +#endif /*_MSC_VER >=1400 */ + +static void install_sigabrt_handler(void) +{ +#if (_MSC_VER >=1400) + /*abort() should not override our exception filter*/ + _set_abort_behavior(0,_CALL_REPORTFAULT); + signal(SIGABRT,my_sigabrt_handler); +#endif /* _MSC_VER >=1400 */ +} +#endif + #endif /* THREAD */ diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index 1134d40229a..e7d8073a163 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -16,12 +16,11 @@ /***************************************************************************** ** The following is a simple implementation of posix conditions *****************************************************************************/ +#if defined(_WIN32) #undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ #include "mysys_priv.h" -#if defined(THREAD) && defined(__WIN__) #include <m_string.h> -#undef getpid #include <process.h> #include <sys/timeb.h> diff --git a/mysys/my_winerr.c b/mysys/my_winerr.c new file mode 100644 index 00000000000..534078b6737 --- /dev/null +++ b/mysys/my_winerr.c @@ -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 <my_global.h> +#include <my_sys.h> + + +struct errentry +{ + unsigned long oscode; /* OS return value */ + int sysv_errno; /* 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].sysv_errno; + } + } + + /* 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); +} diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c new file mode 100644 index 00000000000..6a2cda5ba29 --- /dev/null +++ b/mysys/my_winfile.c @@ -0,0 +1,672 @@ +/* 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 */ + +/* + The purpose of this file is to provide implementation of file IO routines on + Windows that can be thought as drop-in replacement for corresponding C runtime + functionality. + + Compared to Windows CRT, this one + - does not have the same file descriptor + limitation (default is 16384 and can be increased further, whereas CRT poses + a hard limit of 2048 file descriptors) + - the file operations are not serialized + - positional IO pread/pwrite is ported here. + - no text mode for files, all IO is "binary" + + Naming convention: + All routines are prefixed with my_win_, e.g Posix open() is implemented with + my_win_open() + + Implemented are + - POSIX routines(e.g open, read, lseek ...) + - Some ANSI C stream routines (fopen, fdopen, fileno, fclose) + - Windows CRT equvalients (my_get_osfhandle, open_osfhandle) + + Worth to note: + - File descriptors used here are located in a range that is not compatible + with CRT on purpose. Attempt to use a file descriptor from Windows CRT library + range in my_win_* function will be punished with DBUG_ASSERT() + + - File streams (FILE *) are actually from the C runtime. The routines provided + here are useful only in scernarios that use low-level IO with my_win_fileno() +*/ + +#ifdef _WIN32 + +#include "mysys_priv.h" +#include <share.h> +#include <sys/stat.h> + +/* Associates a file descriptor with an existing operating-system file handle.*/ +File my_open_osfhandle(HANDLE handle, int oflag) +{ + int offset= -1; + uint i; + DBUG_ENTER("my_open_osfhandle"); + + pthread_mutex_lock(&THR_LOCK_open); + for(i= MY_FILE_MIN; i < my_file_limit;i++) + { + if(my_file_info[i].fhandle == 0) + { + 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); + if(offset == -1) + errno= EMFILE; /* to many file handles open */ + DBUG_RETURN(offset); +} + + +static void invalidate_fd(File fd) +{ + DBUG_ENTER("invalidate_fd"); + DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); + my_file_info[fd].fhandle= 0; + DBUG_VOID_RETURN; +} + + +/* Get Windows handle for a file descriptor */ +HANDLE my_get_osfhandle(File fd) +{ + DBUG_ENTER("my_get_osfhandle"); + DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); + DBUG_RETURN(my_file_info[fd].fhandle); +} + + +static int my_get_open_flags(File fd) +{ + DBUG_ENTER("my_get_osfhandle"); + DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); + DBUG_RETURN(my_file_info[fd].oflag); +} + + +/* + Open a file with sharing. Similar to _sopen() from libc, but allows managing + share delete on win32 + + SYNOPSIS + my_win_sopen() + path file name + oflag operation flags + shflag share flag + pmode permission flags + + RETURN VALUE + File descriptor of opened file if success + -1 and sets errno if fails. +*/ + +File my_win_sopen(const char *path, int oflag, int shflag, int pmode) +{ + int fh; /* handle of opened file */ + int mask; + HANDLE osfh; /* OS handle of opened file */ + DWORD fileaccess; /* OS file access (requested) */ + DWORD fileshare; /* OS file sharing mode */ + DWORD filecreate; /* OS method of opening/creating */ + DWORD fileattrib; /* OS file attribute flags */ + SECURITY_ATTRIBUTES SecurityAttributes; + + DBUG_ENTER("my_win_sopen"); + + if (check_if_legal_filename(path)) + { + errno= EACCES; + DBUG_RETURN(-1); + } + SecurityAttributes.nLength= sizeof(SecurityAttributes); + SecurityAttributes.lpSecurityDescriptor= NULL; + SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT); + + /* decode the access flags */ + switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { + case _O_RDONLY: /* read access */ + fileaccess= GENERIC_READ; + break; + case _O_WRONLY: /* write access */ + fileaccess= GENERIC_WRITE; + break; + case _O_RDWR: /* read and write access */ + fileaccess= GENERIC_READ | GENERIC_WRITE; + break; + default: /* error, bad oflag */ + errno= EINVAL; + DBUG_RETURN(-1); + } + + /* decode sharing flags */ + switch (shflag) { + case _SH_DENYRW: /* exclusive access except delete */ + fileshare= FILE_SHARE_DELETE; + break; + case _SH_DENYWR: /* share read and delete access */ + fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE; + break; + case _SH_DENYRD: /* share write and delete access */ + fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE; + break; + case _SH_DENYNO: /* share read, write and delete access */ + fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + break; + case _SH_DENYRWD: /* exclusive access */ + fileshare= 0L; + break; + case _SH_DENYWRD: /* share read access */ + fileshare= FILE_SHARE_READ; + break; + case _SH_DENYRDD: /* share write access */ + fileshare= FILE_SHARE_WRITE; + break; + case _SH_DENYDEL: /* share read and write access */ + fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + default: /* error, bad shflag */ + errno= EINVAL; + DBUG_RETURN(-1); + } + + /* decode open/create method flags */ + switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) { + case 0: + case _O_EXCL: /* ignore EXCL w/o CREAT */ + filecreate= OPEN_EXISTING; + break; + + case _O_CREAT: + filecreate= OPEN_ALWAYS; + break; + + case _O_CREAT | _O_EXCL: + case _O_CREAT | _O_TRUNC | _O_EXCL: + filecreate= CREATE_NEW; + break; + + case _O_TRUNC: + case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */ + filecreate= TRUNCATE_EXISTING; + break; + + case _O_CREAT | _O_TRUNC: + filecreate= CREATE_ALWAYS; + break; + + default: + /* this can't happen ... all cases are covered */ + errno= EINVAL; + DBUG_RETURN(-1); + } + + /* decode file attribute flags if _O_CREAT was specified */ + fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */ + if (oflag & _O_CREAT) + { + _umask((mask= _umask(0))); + + if (!((pmode & ~mask) & _S_IWRITE)) + fileattrib= FILE_ATTRIBUTE_READONLY; + } + + /* Set temporary file (delete-on-close) attribute if requested. */ + if (oflag & _O_TEMPORARY) + { + fileattrib|= FILE_FLAG_DELETE_ON_CLOSE; + fileaccess|= DELETE; + } + + /* Set temporary file (delay-flush-to-disk) attribute if requested.*/ + if (oflag & _O_SHORT_LIVED) + fileattrib|= FILE_ATTRIBUTE_TEMPORARY; + + /* Set sequential or random access attribute if requested. */ + if (oflag & _O_SEQUENTIAL) + fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN; + else if (oflag & _O_RANDOM) + fileattrib|= FILE_FLAG_RANDOM_ACCESS; + + /* try to open/create the file */ + if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, + filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE) + { + /* + OS call to open/create file failed! map the error, release + the lock, and return -1. note that it's not necessary to + call _free_osfhnd (it hasn't been used yet). + */ + my_osmaperr(GetLastError()); /* map error */ + DBUG_RETURN(-1); /* return error to caller */ + } + + if ((fh= my_open_osfhandle(osfh, + oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1) + { + CloseHandle(osfh); + } + + DBUG_RETURN(fh); /* return handle */ +} + + +File my_win_open(const char *path, int flags) +{ + DBUG_ENTER("my_win_open"); + DBUG_RETURN(my_win_sopen((char *) path, flags | _O_BINARY, _SH_DENYNO, + _S_IREAD | S_IWRITE)); +} + + +int my_win_close(File fd) +{ + DBUG_ENTER("my_win_close"); + if(CloseHandle(my_get_osfhandle(fd))) + { + invalidate_fd(fd); + DBUG_RETURN(0); + } + my_osmaperr(GetLastError()); + DBUG_RETURN(-1); +} + + +size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset) +{ + DWORD nBytesRead; + HANDLE hFile; + OVERLAPPED ov= {0}; + LARGE_INTEGER li; + + DBUG_ENTER("my_win_pread"); + + if(!Count) + DBUG_RETURN(0); +#ifdef _WIN64 + if(Count > UINT_MAX) + Count= UINT_MAX; +#endif + + hFile= (HANDLE)my_get_osfhandle(Filedes); + li.QuadPart= offset; + ov.Offset= li.LowPart; + ov.OffsetHigh= li.HighPart; + + if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, &ov)) + { + DWORD lastError= GetLastError(); + /* + ERROR_BROKEN_PIPE is returned when no more data coming + through e.g. a command pipe in windows : see MSDN on ReadFile. + */ + if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) + DBUG_RETURN(0); /*return 0 at EOF*/ + my_osmaperr(lastError); + DBUG_RETURN(-1); + } + DBUG_RETURN(nBytesRead); +} + + +size_t my_win_read(File Filedes, uchar *Buffer, size_t Count) +{ + DWORD nBytesRead; + HANDLE hFile; + + DBUG_ENTER("my_win_read"); + if(!Count) + DBUG_RETURN(0); +#ifdef _WIN64 + if(Count > UINT_MAX) + Count= UINT_MAX; +#endif + + hFile= (HANDLE)my_get_osfhandle(Filedes); + + if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, NULL)) + { + DWORD lastError= GetLastError(); + /* + ERROR_BROKEN_PIPE is returned when no more data coming + through e.g. a command pipe in windows : see MSDN on ReadFile. + */ + if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) + DBUG_RETURN(0); /*return 0 at EOF*/ + my_osmaperr(lastError); + DBUG_RETURN(-1); + } + DBUG_RETURN(nBytesRead); +} + + +size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count, + my_off_t offset) +{ + DWORD nBytesWritten; + HANDLE hFile; + OVERLAPPED ov= {0}; + LARGE_INTEGER li; + + DBUG_ENTER("my_win_pwrite"); + DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu", + Filedes, Buffer, (ulonglong)Count, (ulonglong)offset)); + + if(!Count) + DBUG_RETURN(0); + +#ifdef _WIN64 + if(Count > UINT_MAX) + Count= UINT_MAX; +#endif + + 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)) + { + my_osmaperr(GetLastError()); + DBUG_RETURN(-1); + } + else + DBUG_RETURN(nBytesWritten); +} + + +my_off_t my_win_lseek(File fd, my_off_t pos, int whence) +{ + LARGE_INTEGER offset; + LARGE_INTEGER newpos; + + DBUG_ENTER("my_win_lseek"); + + /* Check compatibility of Windows and Posix seek constants */ + compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR + && FILE_END == SEEK_END); + + offset.QuadPart= pos; + if(!SetFilePointerEx(my_get_osfhandle(fd), offset, &newpos, whence)) + { + my_osmaperr(GetLastError()); + newpos.QuadPart= -1; + } + DBUG_RETURN(newpos.QuadPart); +} + + +#ifndef FILE_WRITE_TO_END_OF_FILE +#define FILE_WRITE_TO_END_OF_FILE 0xffffffff +#endif +size_t my_win_write(File fd, const uchar *Buffer, size_t Count) +{ + DWORD nWritten; + OVERLAPPED ov; + OVERLAPPED *pov= NULL; + HANDLE hFile; + + DBUG_ENTER("my_win_write"); + DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer, + (ulonglong)Count)); + if(my_get_open_flags(fd) & _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(fd); + if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov)) + { + nWritten= (size_t)-1; + my_osmaperr(GetLastError()); + } + DBUG_RETURN((size_t)nWritten); +} + + +int my_win_chsize(File fd, my_off_t newlength) +{ + HANDLE hFile; + LARGE_INTEGER length; + DBUG_ENTER("my_win_chsize"); + + hFile= (HANDLE) my_get_osfhandle(fd); + length.QuadPart= newlength; + if (!SetFilePointerEx(hFile, length , NULL , FILE_BEGIN)) + goto err; + if (!SetEndOfFile(hFile)) + goto err; + DBUG_RETURN(0); +err: + my_osmaperr(GetLastError()); + my_errno= errno; + DBUG_RETURN(-1); +} + + +/* Get the 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"); + + 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); +} + + +File my_win_fileno(FILE *file) +{ + HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file)); + int retval= -1; + uint i; + + DBUG_ENTER("my_win_fileno"); + + for(i= MY_FILE_MIN; i < my_file_limit; i++) + { + if(my_file_info[i].fhandle == hFile) + { + retval= i; + break; + } + } + if(retval == -1) + /* try std stream */ + DBUG_RETURN(my_get_stdfile_descriptor(file)); + DBUG_RETURN(retval); +} + + +FILE *my_win_fopen(const char *filename, const char *type) +{ + FILE *file; + int flags= 0; + DBUG_ENTER("my_win_open"); + + /* + If we are not creating, then we need to use my_access to make sure + the file exists since Windows doesn't handle files like "com1.sym" + very well + */ + if (check_if_legal_filename(filename)) + { + errno= EACCES; + DBUG_RETURN(NULL); + } + + file= fopen(filename, type); + if(!file) + DBUG_RETURN(NULL); + + if(strchr(type,'a') != NULL) + flags= O_APPEND; + + /* + Register file handle in my_table_info. + Necessary for my_fileno() + */ + if(my_open_osfhandle((HANDLE)_get_osfhandle(fileno(file)), flags) < 0) + { + fclose(file); + DBUG_RETURN(NULL); + } + DBUG_RETURN(file); +} + + +FILE * my_win_fdopen(File fd, const char *type) +{ + FILE *file; + int crt_fd; + int flags= 0; + + DBUG_ENTER("my_win_fdopen"); + + if(strchr(type,'a') != NULL) + flags= O_APPEND; + /* Convert OS file handle to CRT file descriptor and then call fdopen*/ + crt_fd= _open_osfhandle((intptr_t)my_get_osfhandle(fd), flags); + if(crt_fd < 0) + file= NULL; + else + file= fdopen(crt_fd, type); + DBUG_RETURN(file); +} + + +int my_win_fclose(FILE *file) +{ + File fd; + + DBUG_ENTER("my_win_close"); + fd= my_fileno(file); + if(fd < 0) + DBUG_RETURN(-1); + if(fclose(file) < 0) + DBUG_RETURN(-1); + invalidate_fd(fd); + DBUG_RETURN(0); +} + + + +/* + 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) +*/ +int my_win_fstat(File fd, struct _stati64 *buf) +{ + int crt_fd; + int retval; + HANDLE hFile, hDup; + + DBUG_ENTER("my_win_fstat"); + + hFile= my_get_osfhandle(fd); + 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, buf); + if(retval == 0) + { + /* File size returned by stat is not accurate (may be outdated), fix it*/ + GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(buf->st_size))); + } + _close(crt_fd); + DBUG_RETURN(retval); +} + + + +int my_win_stat( const char *path, struct _stati64 *buf) +{ + DBUG_ENTER("my_win_stat"); + if(_stati64( path, buf) == 0) + { + /* File size returned by stat is not accurate (may be outdated), fix it*/ + WIN32_FILE_ATTRIBUTE_DATA data; + if (GetFileAttributesEx(path, GetFileExInfoStandard, &data)) + { + LARGE_INTEGER li; + li.LowPart= data.nFileSizeLow; + li.HighPart= data.nFileSizeHigh; + buf->st_size= li.QuadPart; + } + DBUG_RETURN(0); + } + DBUG_RETURN(-1); +} + + + +int my_win_fsync(File fd) +{ + DBUG_ENTER("my_win_fsync"); + if(FlushFileBuffers(my_get_osfhandle(fd))) + DBUG_RETURN(0); + my_osmaperr(GetLastError()); + DBUG_RETURN(-1); +} + + + +int my_win_dup(File fd) +{ + HANDLE hDup; + DBUG_ENTER("my_win_dup"); + if (DuplicateHandle(GetCurrentProcess(), my_get_osfhandle(fd), + GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + DBUG_RETURN(my_open_osfhandle(hDup, my_get_open_flags(fd))); + } + my_osmaperr(GetLastError()); + DBUG_RETURN(-1); +} + +#endif /*_WIN32*/ diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index ef2a20c2ddc..290351099a4 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -14,33 +14,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /***************************************************************************** -** Simulation of posix threads calls for WIN95 and NT +** Simulation of posix threads calls for Windows *****************************************************************************/ - +#if defined (_WIN32) /* SAFE_MUTEX will not work until the thread structure is up to date */ #undef SAFE_MUTEX - #include "mysys_priv.h" -#if defined(THREAD) && defined(__WIN__) -#include <m_string.h> -#undef getpid #include <process.h> +#include <signal.h> -static pthread_mutex_t THR_LOCK_thread; +static void install_sigabrt_handler(void); -struct pthread_map +struct thread_start_parameter { - HANDLE pthreadself; pthread_handler func; - void *param; + void *arg; }; -void win_pthread_init(void) -{ - pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST); -} - - /** Adapter to @c pthread_mutex_trylock() @@ -62,79 +52,81 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex) return EBUSY; } - -/* -** We have tried to use '_beginthreadex' instead of '_beginthread' here -** but in this case the program leaks about 512 characters for each -** created thread ! -** As we want to save the created thread handler for other threads to -** use and to be returned by pthread_self() (instead of the Win32 pseudo -** handler), we have to go trough pthread_start() to catch the returned handler -** in the new thread. -*/ - -pthread_handler_t pthread_start(void *param) +static unsigned int __stdcall pthread_start(void *p) { - pthread_handler func=((struct pthread_map *) param)->func; - void *func_param=((struct pthread_map *) param)->param; - my_thread_init(); /* Will always succeed in windows */ - pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */ - win_pthread_self=((struct pthread_map *) param)->pthreadself; - pthread_mutex_unlock(&THR_LOCK_thread); - free((char*) param); /* Free param from create */ - pthread_exit((void*) (*func)(func_param)); - return 0; /* Safety */ + struct thread_start_parameter *par= (struct thread_start_parameter *)p; + pthread_handler func= par->func; + void *arg= par->arg; + free(p); + (*func)(arg); + return 0; } int pthread_create(pthread_t *thread_id, pthread_attr_t *attr, - pthread_handler func, void *param) + pthread_handler func, void *param) { - HANDLE hThread; - struct pthread_map *map; + uintptr_t handle; + struct thread_start_parameter *par; + unsigned int stack_size; DBUG_ENTER("pthread_create"); - if (!(map=malloc(sizeof(*map)))) - DBUG_RETURN(-1); - map->func=func; - map->param=param; - pthread_mutex_lock(&THR_LOCK_thread); -#ifdef __BORLANDC__ - hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start, - attr->dwStackSize ? attr->dwStackSize : - 65535, (void*) map); -#else - hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start, - attr->dwStackSize ? attr->dwStackSize : - 65535, (void*) map); -#endif - DBUG_PRINT("info", ("hThread=%lu",(long) hThread)); - *thread_id=map->pthreadself=hThread; - pthread_mutex_unlock(&THR_LOCK_thread); + par= (struct thread_start_parameter *)malloc(sizeof(*par)); + if (!par) + goto error_return; - if (hThread == (HANDLE) -1) - { - int error=errno; - DBUG_PRINT("error", - ("Can't create thread to handle request (error %d)",error)); - DBUG_RETURN(error ? error : -1); - } - VOID(SetThreadPriority(hThread, attr->priority)) ; + par->func= func; + par->arg= param; + stack_size= attr?attr->dwStackSize:0; + + handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id); + if (!handle) + goto error_return; + DBUG_PRINT("info", ("thread id=%u",*thread_id)); + + /* Do not need thread handle, close it */ + CloseHandle((HANDLE)handle); DBUG_RETURN(0); + +error_return: + DBUG_PRINT("error", + ("Can't create thread to handle request (error %d)",errno)); + DBUG_RETURN(-1); } void pthread_exit(void *a) { - _endthread(); + _endthreadex(0); } -/* This is neaded to get the macro pthread_setspecific to work */ - -int win_pthread_setspecific(void *a,void *b,uint length) +int pthread_join(pthread_t thread, void **value_ptr) { - memcpy(a,b,length); + DWORD ret; + HANDLE handle; + + handle= OpenThread(SYNCHRONIZE, FALSE, thread); + if (!handle) + { + errno= EINVAL; + goto error_return; + } + + ret= WaitForSingleObject(handle, INFINITE); + + if(ret != WAIT_OBJECT_0) + { + errno= EINVAL; + goto error_return; + } + + CloseHandle(handle); return 0; + +error_return: + if(handle) + CloseHandle(handle); + return -1; } diff --git a/mysys/my_write.c b/mysys/my_write.c index d7eb390bdd2..3eac1364f46 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -20,14 +20,14 @@ /* 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; + size_t writtenbytes, written; uint errors; DBUG_ENTER("my_write"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); - errors=0; written=0; + DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", + Filedes, Buffer, (ulong) Count, MyFlags)); + errors= 0; written= 0; /* The behavior of write(fd, buf, 0) is not portable */ if (unlikely(!Count)) @@ -35,17 +35,22 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) for (;;) { - if ((writenbytes= write(Filedes, Buffer, Count)) == Count) +#ifdef _WIN32 + writtenbytes= my_win_write(Filedes, Buffer, Count); +#else + writtenbytes= write(Filedes, Buffer, Count); +#endif + if (writtenbytes == Count) break; - if (writenbytes != (size_t) -1) + if (writtenbytes != (size_t) -1) { /* Safeguard */ - written+=writenbytes; - Buffer+=writenbytes; - Count-=writenbytes; + written+= writtenbytes; + Buffer+= writtenbytes; + Count-= writtenbytes; } - my_errno=errno; + my_errno= errno; DBUG_PRINT("error",("Write only %ld bytes, error: %d", - (long) writenbytes, my_errno)); + (long) writtenbytes, my_errno)); #ifndef NO_BACKGROUND #ifdef THREAD if (my_thread_var->abort) @@ -59,19 +64,19 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) continue; } - if ((writenbytes == 0 || writenbytes == (size_t) -1)) + if ((writtenbytes == 0 || writtenbytes == (size_t) -1)) { if (my_errno == EINTR) { DBUG_PRINT("debug", ("my_write() was interrupted and returned %ld", - (long) writenbytes)); + (long) writtenbytes)); continue; /* Interrupted */ } - if (!writenbytes && !errors++) /* Retry once */ + if (!writtenbytes && !errors++) /* Retry once */ { /* We may come here if the file quota is exeeded */ - errno=EFBIG; /* Assume this is the error */ + errno= EFBIG; /* Assume this is the error */ continue; } } @@ -92,5 +97,5 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) } if (MyFlags & (MY_NABP | MY_FNABP)) DBUG_RETURN(0); /* Want only errors */ - DBUG_RETURN(writenbytes+written); + DBUG_RETURN(writtenbytes+written); } /* my_write */ diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 6e0959ae08c..4c4d6ea3598 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -42,3 +42,27 @@ extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time; #endif void my_error_unregister_all(void); + +#ifdef _WIN32 +/* my_winfile.c exports, should not be used outside mysys */ +extern File my_win_open(const char *path, int oflag); +extern int my_win_close(File fd); +extern size_t my_win_read(File fd, uchar *buffer, size_t count); +extern size_t my_win_write(File fd, const uchar *buffer, size_t count); +extern size_t my_win_pread(File fd, uchar *buffer, size_t count, + my_off_t offset); +extern size_t my_win_pwrite(File fd, const uchar *buffer, size_t count, + my_off_t offset); +extern my_off_t my_win_lseek(File fd, my_off_t pos, int whence); +extern int my_win_chsize(File fd, my_off_t newlength); +extern FILE* my_win_fopen(const char *filename, const char *type); +extern File my_win_fclose(FILE *file); +extern File my_win_fileno(FILE *file); +extern FILE* my_win_fdopen(File Filedes, const char *type); +extern int my_win_stat(const char *path, struct _stat64 *buf); +extern int my_win_fstat(File fd, struct _stat64 *buf); +extern int my_win_fsync(File fd); +extern File my_win_dup(File fd); +extern File my_win_sopen(const char *path, int oflag, int shflag, int perm); +extern File my_open_osfhandle(HANDLE handle, int oflag); +#endif diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 0e0e93cf220..4bb818b1b30 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -362,7 +362,7 @@ void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param) static inline my_bool -have_old_read_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner) +has_old_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner) { for ( ; data ; data=data->next) { @@ -572,7 +572,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, else if (!lock->write_wait.data || lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY || lock_type == TL_READ_HIGH_PRIORITY || - have_old_read_lock(lock->read.data, data->owner)) + has_old_lock(lock->read.data, data->owner)) /* Has old read lock */ { /* No important write-locks */ (*lock->read.last)=data; /* Add to running FIFO */ data->prev=lock->read.last; @@ -642,14 +642,36 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, } /* - The following test will not work if the old lock was a - TL_WRITE_ALLOW_WRITE, TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED in - the same thread, but this will never happen within MySQL. + The idea is to allow us to get a lock at once if we already have + a write lock or if there is no pending write locks and if all + write locks are of TL_WRITE_ALLOW_WRITE type. + + Note that, since lock requests for the same table are sorted in + such way that requests with higher thr_lock_type value come first, + lock being requested usually has equal or "weaker" type than one + which thread might have already acquired. + The exceptions are situations when: + - old lock type is TL_WRITE_ALLOW_READ and new lock type is + TL_WRITE_ALLOW_WRITE + - when old lock type is TL_WRITE_DELAYED + But these should never happen within MySQL. + Therefore it is OK to allow acquiring write lock on the table if + this thread already holds some write lock on it. + + (INSERT INTO t1 VALUES (f1()), where f1() is stored function which + tries to update t1, is an example of statement which requests two + different types of write lock on the same table). */ - if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || - (lock_type == TL_WRITE_ALLOW_WRITE && - !lock->write_wait.data && - lock->write.data->type == TL_WRITE_ALLOW_WRITE)) + DBUG_ASSERT(! has_old_lock(lock->write.data, data->owner) || + (lock_type <= lock->write.data->type && + ! ((lock_type < TL_WRITE_ALLOW_READ && + lock->write.data->type == TL_WRITE_ALLOW_READ) || + lock->write.data->type == TL_WRITE_DELAYED))); + + if ((lock_type == TL_WRITE_ALLOW_WRITE && + ! lock->write_wait.data && + lock->write.data->type == TL_WRITE_ALLOW_WRITE) || + has_old_lock(lock->write.data, data->owner)) { /* We have already got a write lock or all locks are @@ -998,6 +1020,7 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner) thr_multi_unlock(data,(uint) (pos-data)); DBUG_RETURN(result); } + DEBUG_SYNC_C("thr_multi_lock_after_thr_lock"); #ifdef MAIN printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(), (long) pos[0]->lock, pos[0]->type); fflush(stdout); |