diff options
Diffstat (limited to 'mysys')
111 files changed, 6374 insertions, 3374 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 529cf89056d..877376a9f83 100755 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -19,24 +19,30 @@ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") # 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" # Thread Local Storage model. +# +# Exception is the embedded server that needs this library compiled with +# dynamic TLS, i.e. define USE_TLS INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys) -ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_modify.c +SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_modify.c errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c - mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_arr_appstr.c mf_tempdir.c + mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_arr_appstr.c mf_tempdir.c mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c - my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_compare.c - my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_init.c - my_lib.c my_lock.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c + my_div.c my_error.c my_file.c my_fopen.c my_fstream.c + my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_compare.c my_init.c + my_lib.c my_lock.c my_lockmem.c my_malloc.c my_messnc.c my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c - my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c + my_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 base64.c my_memmem.c - my_getpagesize.c) + thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c) + +IF(NOT SOURCE_SUBLIBS) + ADD_LIBRARY(mysys ${MYSYS_SOURCES}) +ENDIF(NOT SOURCE_SUBLIBS) diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 4bca72f770b..dd7d29c6a2f 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -19,49 +19,56 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a -LDADD = libmysys.a ../dbug/libdbug.a \ - ../strings/libmystrings.a -noinst_HEADERS = mysys_priv.h my_static.h +LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a $(top_builddir)/dbug/libdbug.a +noinst_HEADERS = mysys_priv.h my_static.h my_handler_errors.h libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ my_open.c my_create.c my_dup.c my_seek.c my_read.c \ my_pread.c my_write.c my_getpagesize.c \ - mf_keycache.c mf_keycaches.c my_crc32.c \ + mf_keycaches.c my_crc32.c \ mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ my_alloc.c safemalloc.c my_new.cc \ - my_fopen.c my_fstream.c my_getsystime.c \ + my_vle.c my_fopen.c my_fstream.c my_getsystime.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ my_symlink.c my_symlink2.c \ - mf_pack.c mf_unixpath.c mf_strip.c mf_arr_appstr.c \ + mf_pack.c mf_unixpath.c mf_arr_appstr.c \ mf_wcomp.c mf_wfile.c my_gethwaddr.c \ mf_qsort.c mf_qsort2.c mf_sort.c \ - ptr_cmp.c mf_radix.c queues.c \ - tree.c list.c hash.c array.c string.c typelib.c \ + ptr_cmp.c mf_radix.c queues.c my_getncpus.c \ + tree.c trie.c list.c hash.c array.c string.c typelib.c \ my_copy.c my_append.c my_lib.c \ my_delete.c my_rename.c my_redel.c \ - my_chsize.c my_lread.c my_lwrite.c my_clock.c \ + my_chsize.c my_clock.c \ my_quick.c my_lockmem.c my_static.c \ my_sync.c my_getopt.c my_mkdir.c \ default_modify.c default.c \ - my_compress.c checksum.c raid.cc \ - my_net.c my_compare.c my_sleep.c \ + my_compress.c checksum.c \ + my_net.c my_sleep.c \ charset.c charset-def.c my_bitmap.c my_bit.c md5.c \ rijndael.c my_aes.c sha1.c \ - my_netware.c my_largepage.c \ - my_memmem.c \ + my_compare.c my_netware.c my_largepage.c \ + my_memmem.c stacktrace.c \ my_windac.c my_access.c base64.c my_libwrap.c + +if NEED_THREAD +# mf_keycache is used only in the server, so it is safe to leave the file +# out of the non-threaded library. +# In fact, it will currently not compile without thread support. +libmysys_a_SOURCES += mf_keycache.c +endif + EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ - thr_mutex.c thr_rwlock.c mf_soundex.c my_conio.c \ - my_wincond.c my_winthread.c CMakeLists.txt + thr_mutex.c thr_rwlock.c \ + CMakeLists.txt mf_soundex.c \ + my_conio.c my_wincond.c my_winthread.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ # test_dir_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES) # test_charset_DEPENDENCIES= $(LIBRARIES) # charset2html_DEPENDENCIES= $(LIBRARIES) -EXTRA_PROGRAMS = DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ -DMYSQL_DATADIR="\"$(MYSQLDATAdir)\"" \ -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ @@ -81,6 +88,12 @@ FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@ # which automaticly removes the object files you use to compile a final program # +test_bitmap$(EXEEXT): my_bitmap.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN ./my_bitmap.c $(LDADD) $(LIBS) + +test_priority_queue$(EXEEXT): queues.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN ./queues.c $(LDADD) $(LIBS) + test_thr_alarm$(EXEEXT): thr_alarm.c $(LIBRARIES) $(CP) $(srcdir)/thr_alarm.c ./test_thr_alarm.c $(LINK) $(FLAGS) -DMAIN ./test_thr_alarm.c $(LDADD) $(LIBS) diff --git a/mysys/array.c b/mysys/array.c index f1303f705ba..db219eb2430 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2002, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2002, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Handling of arrays that can grow dynamicly. */ @@ -23,9 +25,10 @@ Initiate dynamic array SYNOPSIS - init_dynamic_array() + init_dynamic_array2() array Pointer to an array element_size Size of element + init_buffer Initial buffer pointer init_alloc Number of initial elements alloc_increment Increment for adding new elements @@ -34,14 +37,15 @@ init_alloc eilements. Array is usable even if space allocation failed, hence, the function never returns TRUE. + Static buffers must begin immediately after the array structure. RETURN VALUE FALSE Ok */ -my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, - uint init_alloc, - uint alloc_increment CALLER_INFO_PROTO) +my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, + void *init_buffer, uint init_alloc, + uint alloc_increment CALLER_INFO_PROTO) { DBUG_ENTER("init_dynamic_array"); if (!alloc_increment) @@ -52,20 +56,33 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, } if (!init_alloc) + { init_alloc=alloc_increment; + init_buffer= 0; + } array->elements=0; array->max_element=init_alloc; array->alloc_increment=alloc_increment; array->size_of_element=element_size; + if ((array->buffer= init_buffer)) + DBUG_RETURN(FALSE); /* Since the dynamic array is usable even if allocation fails here malloc should not throw an error */ - if (!(array->buffer= (char*) my_malloc_ci(element_size*init_alloc, MYF(0)))) + if (!(array->buffer= (uchar*) my_malloc_ci(element_size*init_alloc, MYF(0)))) array->max_element=0; DBUG_RETURN(FALSE); } +my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, + uint init_alloc, + uint alloc_increment CALLER_INFO_PROTO) +{ + /* placeholder to preserve ABI */ + return my_init_dynamic_array_ci(array, element_size, init_alloc, + alloc_increment); +} /* Insert element at the end of array. Allocate memory if needed. @@ -79,9 +96,9 @@ my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, FALSE Ok */ -my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element) +my_bool insert_dynamic(DYNAMIC_ARRAY *array, uchar* element) { - gptr buffer; + uchar* buffer; if (array->elements == array->max_element) { /* Call only when nessesary */ if (!(buffer=alloc_dynamic(array))) @@ -114,17 +131,32 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, gptr element) 0 Error */ -byte *alloc_dynamic(DYNAMIC_ARRAY *array) +uchar *alloc_dynamic(DYNAMIC_ARRAY *array) { if (array->elements == array->max_element) { char *new_ptr; + if (array->buffer == (uchar *)(array + 1)) + { + /* + In this senerio, the buffer is statically preallocated, + so we have to create an all-new malloc since we overflowed + */ + if (!(new_ptr= (char *) my_malloc((array->max_element+ + array->alloc_increment) * + array->size_of_element, + MYF(MY_WME)))) + return 0; + memcpy(new_ptr, array->buffer, + array->elements * array->size_of_element); + } + else if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+ - array->alloc_increment)* - array->size_of_element, - MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) + array->alloc_increment)* + array->size_of_element, + MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) return 0; - array->buffer=new_ptr; + array->buffer= (uchar*) new_ptr; array->max_element+=array->alloc_increment; } return array->buffer+(array->elements++ * array->size_of_element); @@ -143,7 +175,7 @@ byte *alloc_dynamic(DYNAMIC_ARRAY *array) 0 Array is empty */ -byte *pop_dynamic(DYNAMIC_ARRAY *array) +uchar *pop_dynamic(DYNAMIC_ARRAY *array) { if (array->elements) return array->buffer+(--array->elements * array->size_of_element); @@ -151,7 +183,7 @@ byte *pop_dynamic(DYNAMIC_ARRAY *array) } /* - Replace elemnent in array with given element and index + Replace element in array with given element and index SYNOPSIS set_dynamic() @@ -168,24 +200,13 @@ byte *pop_dynamic(DYNAMIC_ARRAY *array) FALSE Ok */ -my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) +my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx) { if (idx >= array->elements) { - if (idx >= array->max_element) - { - uint size; - char *new_ptr; - size=(idx+array->alloc_increment)/array->alloc_increment; - size*= array->alloc_increment; - if (!(new_ptr=(char*) my_realloc(array->buffer,size* - array->size_of_element, - MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) - return TRUE; - array->buffer=new_ptr; - array->max_element=size; - } - bzero((gptr) (array->buffer+array->elements*array->size_of_element), + if (idx >= array->max_element && allocate_dynamic(array, idx)) + return TRUE; + bzero((uchar*) (array->buffer+array->elements*array->size_of_element), (idx - array->elements)*array->size_of_element); array->elements=idx+1; } @@ -194,27 +215,79 @@ my_bool set_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) return FALSE; } + +/* + Ensure that dynamic array has enough elements + + SYNOPSIS + allocate_dynamic() + array + max_elements Numbers of elements that is needed + + NOTES + Any new allocated element are NOT initialized + + RETURN VALUE + FALSE Ok + TRUE Allocation of new memory failed +*/ + +my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements) +{ + if (max_elements >= array->max_element) + { + uint size; + uchar *new_ptr; + size= (max_elements + array->alloc_increment)/array->alloc_increment; + size*= array->alloc_increment; + if (array->buffer == (uchar *)(array + 1)) + { + /* + In this senerio, the buffer is statically preallocated, + so we have to create an all-new malloc since we overflowed + */ + if (!(new_ptr= (uchar *) my_malloc(size * + array->size_of_element, + MYF(MY_WME)))) + return 0; + memcpy(new_ptr, array->buffer, + array->elements * array->size_of_element); + } + else + + + if (!(new_ptr= (uchar*) my_realloc(array->buffer,size* + array->size_of_element, + MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) + return TRUE; + array->buffer= new_ptr; + array->max_element= size; + } + return FALSE; +} + + /* Get an element from array by given index SYNOPSIS get_dynamic() array - gptr Element to be returned. If idx > elements contain zeroes. + uchar* Element to be returned. If idx > elements contain zeroes. idx Index of element wanted. */ -void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) +void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx) { if (idx >= array->elements) { DBUG_PRINT("warning",("To big array idx: %d, array size is %d", - idx,array->elements)); + idx,array->elements)); bzero(element,array->size_of_element); return; } memcpy(element,array->buffer+idx*array->size_of_element, - (size_t) array->size_of_element); + (size_t) array->size_of_element); } @@ -228,6 +301,12 @@ void get_dynamic(DYNAMIC_ARRAY *array, gptr element, uint idx) void delete_dynamic(DYNAMIC_ARRAY *array) { + /* + Just mark as empty if we are using a static buffer + */ + if (array->buffer == (uchar *)(array + 1)) + array->elements= 0; + else if (array->buffer) { my_free(array->buffer,MYF(MY_WME)); @@ -242,15 +321,15 @@ void delete_dynamic(DYNAMIC_ARRAY *array) SYNOPSIS delete_dynamic_element() array - idx Index of element to be deleted + idx Index of element to be deleted */ void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) { - char *ptr=array->buffer+array->size_of_element*idx; + char *ptr= (char*) array->buffer+array->size_of_element*idx; array->elements--; memmove(ptr,ptr+array->size_of_element, - (array->elements-idx)*array->size_of_element); + (array->elements-idx)*array->size_of_element); } @@ -267,11 +346,42 @@ void freeze_size(DYNAMIC_ARRAY *array) { uint elements=max(array->elements,1); + /* + Do nothing if we are using a static buffer + */ + if (array->buffer == (uchar *)(array + 1)) + return; + if (array->buffer && array->max_element != elements) { - array->buffer=(char*) my_realloc(array->buffer, - elements*array->size_of_element, - MYF(MY_WME)); + array->buffer=(uchar*) my_realloc(array->buffer, + elements*array->size_of_element, + MYF(MY_WME)); array->max_element=elements; } } + + +/* + Get the index of a dynamic element + + SYNOPSIS + get_index_dynamic() + array Array + element Whose element index + +*/ + +int get_index_dynamic(DYNAMIC_ARRAY *array, uchar* element) +{ + size_t ret; + if (array->buffer > element) + return -1; + + ret= (element - array->buffer) / array->size_of_element; + if (ret > array->elements) + return -1; + + return ret; + +} diff --git a/mysys/base64.c b/mysys/base64.c index 17bf6f18c8e..e9b6203dba3 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,10 +13,13 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ -#include <base64.h> +#include <my_global.h> #include <m_string.h> /* strchr() */ +#include <m_ctype.h> /* my_isspace() */ +#include <base64.h> #ifndef MAIN @@ -115,7 +119,6 @@ pos(unsigned char c) } \ if (i == size) \ { \ - i= size + 1; \ break; \ } \ } @@ -124,44 +127,69 @@ pos(unsigned char c) /* Decode a base64 string - Note: We require that dst is pre-allocated to correct size. - See base64_needed_decoded_length(). + SYNOPSIS + base64_decode() + src Pointer to base64-encoded string + len Length of string at 'src' + dst Pointer to location where decoded data will be stored + end_ptr Pointer to variable that will refer to the character + after the end of the encoded data that were decoded. Can + be NULL. + + DESCRIPTION + + The base64-encoded data in the range ['src','*end_ptr') will be + decoded and stored starting at 'dst'. The decoding will stop + after 'len' characters have been read from 'src', or when padding + occurs in the base64-encoded data. In either case: if 'end_ptr' is + non-null, '*end_ptr' will be set to point to the character after + the last read character, even in the presence of error. - RETURN Number of bytes produced in dst or -1 in case of failure + NOTE + We require that 'dst' is pre-allocated to correct size. + + SEE ALSO + base64_needed_decoded_length(). + + RETURN VALUE + Number of bytes written at 'dst' or -1 in case of failure */ int -base64_decode(const char *src, size_t size, void *dst) +base64_decode(const char *src_base, size_t len, + void *dst, const char **end_ptr) { char b[3]; size_t i= 0; char *dst_base= (char *)dst; + char const *src= src_base; char *d= dst_base; size_t j; - while (i < size) + while (i < len) { unsigned c= 0; size_t mark= 0; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); c += pos(*src++); c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); c += pos(*src++); c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); - if (* src != '=') + if (*src != '=') c += pos(*src++); else { - i= size; + src += 2; /* There should be two bytes padding */ + i= len; mark= 2; c <<= 6; goto end; @@ -169,13 +197,14 @@ base64_decode(const char *src, size_t size, void *dst) c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); if (*src != '=') c += pos(*src++); else { - i= size; + src += 1; /* There should be one byte padding */ + i= len; mark= 1; goto end; } @@ -190,11 +219,14 @@ base64_decode(const char *src, size_t size, void *dst) *d++= b[j]; } - if (i != size) - { - return -1; - } - return (int) (d - dst_base); + if (end_ptr != NULL) + *end_ptr= src; + + /* + The variable 'i' is set to 'len' when padding has been read, so it + does not actually reflect the number of bytes read from 'src'. + */ + return i != len ? -1 : (int) (d - dst_base); } @@ -227,6 +259,7 @@ main(void) char * str; char * dst; + require(src); for (j= 0; j<src_len; j++) { char c= rand(); @@ -236,6 +269,7 @@ main(void) /* Encode */ needed_length= base64_needed_encoded_length(src_len); str= (char *) malloc(needed_length); + require(str); for (k= 0; k < needed_length; k++) str[k]= 0xff; /* Fill memory to check correct NUL termination */ require(base64_encode(src, src_len, str) == 0); @@ -243,7 +277,8 @@ main(void) /* Decode */ dst= (char *) malloc(base64_needed_decoded_length(strlen(str))); - dst_len= base64_decode(str, strlen(str), dst); + require(dst); + dst_len= base64_decode(str, strlen(str), dst, NULL); require(dst_len == src_len); if (memcmp(src, dst, src_len) != 0) diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 36ff4139d9c..cfd06d2f003 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 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 @@ -75,6 +75,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) CHARSET_INFO *cs; add_compiled_collation(&my_charset_bin); + add_compiled_collation(&my_charset_filename); add_compiled_collation(&my_charset_latin1); add_compiled_collation(&my_charset_latin1_bin); @@ -131,6 +132,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_ucs2 add_compiled_collation(&my_charset_ucs2_general_ci); add_compiled_collation(&my_charset_ucs2_bin); + add_compiled_collation(&my_charset_ucs2_general_mysql500_ci); #ifdef HAVE_UCA_COLLATIONS add_compiled_collation(&my_charset_ucs2_unicode_ci); add_compiled_collation(&my_charset_ucs2_icelandic_uca_ci); @@ -162,6 +164,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_utf8 add_compiled_collation(&my_charset_utf8_general_ci); add_compiled_collation(&my_charset_utf8_bin); + add_compiled_collation(&my_charset_utf8_general_mysql500_ci); #ifdef HAVE_UTF8_GENERAL_CS add_compiled_collation(&my_charset_utf8_general_cs); #endif diff --git a/mysys/charset.c b/mysys/charset.c index d1cca150308..952e045aefd 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -212,13 +214,16 @@ copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from) to->max_sort_char= from->max_sort_char; to->mbminlen= from->mbminlen; to->mbmaxlen= from->mbmaxlen; + to->state|= MY_CS_AVAILABLE | MY_CS_LOADED | + MY_CS_STRNXFRM | MY_CS_UNICODE; } static int add_collation(CHARSET_INFO *cs) { if (cs->name && (cs->number || - (cs->number=get_collation_number_internal(cs->name)))) + (cs->number=get_collation_number_internal(cs->name))) && + cs->number < array_elements(all_charsets)) { if (!all_charsets[cs->number]) { @@ -242,18 +247,18 @@ static int add_collation(CHARSET_INFO *cs) if (cs_copy_data(all_charsets[cs->number],cs)) return MY_XML_ERROR; + newcs->caseup_multiply= newcs->casedn_multiply= 1; + if (!strcmp(cs->csname,"ucs2") ) { #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; #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->state|= MY_CS_AVAILABLE | MY_CS_LOADED; #endif } else @@ -321,19 +326,18 @@ static int add_collation(CHARSET_INFO *cs) #define MY_CHARSET_INDEX "Index.xml" const char *charsets_dir= NULL; -static int charset_initialized=0; static my_bool my_read_charset_file(const char *filename, myf myflags) { - char *buf; + uchar *buf; int fd; - uint len, tmp_len; + size_t len, tmp_len; MY_STAT stat_info; if (!my_stat(filename, &stat_info, MYF(myflags)) || ((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) || - !(buf= (char *)my_malloc(len,myflags))) + !(buf= (uchar*) my_malloc(len,myflags))) return TRUE; if ((fd=my_open(filename,O_RDONLY,myflags)) < 0) @@ -343,7 +347,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) if (tmp_len != len) goto error; - if (my_parse_charset_xml(buf,len,add_collation)) + if (my_parse_charset_xml((char*) buf,len,add_collation)) { #ifdef NOT_YET printf("ERROR at line %d pos %d '%s'\n", @@ -353,7 +357,7 @@ static my_bool my_read_charset_file(const char *filename, myf myflags) #endif } - my_free(buf, myflags); + my_free(buf, myflags); return FALSE; error: @@ -384,7 +388,7 @@ char *get_charsets_dir(char *buf) DBUG_RETURN(res); } -CHARSET_INFO *all_charsets[256]; +CHARSET_INFO *all_charsets[256]={NULL}; CHARSET_INFO *default_charset_info = &my_charset_latin1; void add_compiled_collation(CHARSET_INFO *cs) @@ -393,69 +397,49 @@ void add_compiled_collation(CHARSET_INFO *cs) cs->state|= MY_CS_AVAILABLE; } -static void *cs_alloc(uint size) +static void *cs_alloc(size_t size) { return my_once_alloc(size, MYF(MY_WME)); } -#ifdef __NETWARE__ -my_bool STDCALL init_available_charsets(myf myflags) -#else -static my_bool init_available_charsets(myf myflags) -#endif +static my_pthread_once_t charsets_initialized= MY_PTHREAD_ONCE_INIT; +static my_pthread_once_t charsets_template= MY_PTHREAD_ONCE_INIT; + +static void init_available_charsets(void) { char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - my_bool error=FALSE; - /* - We have to use charset_initialized to not lock on THR_LOCK_charset - inside get_internal_charset... - */ - if (!charset_initialized) + CHARSET_INFO **cs; + + bzero(&all_charsets,sizeof(all_charsets)); + init_compiled_charsets(MYF(0)); + + /* Copy compiled charsets */ + for (cs=all_charsets; + cs < all_charsets+array_elements(all_charsets)-1 ; + cs++) { - CHARSET_INFO **cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); - if (!charset_initialized) + if (*cs) { - bzero(&all_charsets,sizeof(all_charsets)); - init_compiled_charsets(myflags); - - /* Copy compiled charsets */ - for (cs=all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; - cs++) - { - if (*cs) - { - if (cs[0]->ctype) - if (init_state_maps(*cs)) - *cs= NULL; - } - } - - strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); - error= my_read_charset_file(fname,myflags); - charset_initialized=1; + if (cs[0]->ctype) + if (init_state_maps(*cs)) + *cs= NULL; } - pthread_mutex_unlock(&THR_LOCK_charset); } - return error; + + strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); + my_read_charset_file(fname, MYF(0)); } void free_charsets(void) { - charset_initialized=0; + charsets_initialized= charsets_template; } - uint get_collation_number(const char *name) { - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); return get_collation_number_internal(name); } @@ -463,7 +447,7 @@ uint get_collation_number(const char *name) uint get_charset_number(const char *charset_name, uint cs_flags) { CHARSET_INFO **cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); for (cs= all_charsets; cs < all_charsets+array_elements(all_charsets)-1 ; @@ -480,7 +464,7 @@ uint get_charset_number(const char *charset_name, uint cs_flags) const char *get_charset_name(uint charset_number) { CHARSET_INFO *cs; - init_available_charsets(MYF(0)); + my_pthread_once(&charsets_initialized, init_available_charsets); cs=all_charsets[charset_number]; if (cs && (cs->number == charset_number) && cs->name ) @@ -494,29 +478,40 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) { char buf[FN_REFLEN]; CHARSET_INFO *cs; - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - pthread_mutex_lock(&THR_LOCK_charset); + if ((cs= all_charsets[cs_number])) { - if (!(cs->state & MY_CS_COMPILED) && !(cs->state & MY_CS_LOADED)) + if (cs->state & MY_CS_READY) /* if CS is already initialized */ + return cs; + + /* + To make things thread safe we are not allowing other threads to interfere + while we may changing the cs_info_table + */ + pthread_mutex_lock(&THR_LOCK_charset); + + if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */ { strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); my_read_charset_file(buf,flags); } - cs= (cs->state & MY_CS_AVAILABLE) ? cs : NULL; - } - if (cs && !(cs->state & MY_CS_READY)) - { - if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) || - (cs->coll->init && cs->coll->init(cs, cs_alloc))) - cs= NULL; + + if (cs->state & MY_CS_AVAILABLE) + { + if (!(cs->state & MY_CS_READY)) + { + if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) || + (cs->coll->init && cs->coll->init(cs, cs_alloc))) + cs= NULL; + else + cs->state|= MY_CS_READY; + } + } else - cs->state|= MY_CS_READY; + cs= NULL; + + pthread_mutex_unlock(&THR_LOCK_charset); } - pthread_mutex_unlock(&THR_LOCK_charset); return cs; } @@ -527,7 +522,7 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags) if (cs_number == default_charset_info->number) return default_charset_info; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); if (!cs_number || cs_number >= array_elements(all_charsets)-1) return NULL; @@ -549,7 +544,7 @@ CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags) { uint cs_number; CHARSET_INFO *cs; - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number=get_collation_number(cs_name); cs= cs_number ? get_internal_charset(cs_number,flags) : NULL; @@ -574,7 +569,7 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, DBUG_ENTER("get_charset_by_csname"); DBUG_PRINT("enter",("name: '%s'", cs_name)); - (void) init_available_charsets(MYF(0)); /* If it isn't initialized */ + my_pthread_once(&charsets_initialized, init_available_charsets); cs_number= get_charset_number(cs_name, cs_flags); cs= cs_number ? get_internal_charset(cs_number, flags) : NULL; @@ -590,6 +585,70 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, } +/** + Resolve character set by the character set name (utf8, latin1, ...). + + The function tries to resolve character set by the specified name. If + there is character set with the given name, it is assigned to the "cs" + parameter and FALSE is returned. If there is no such character set, + "default_cs" is assigned to the "cs" and TRUE is returned. + + @param[in] cs_name Character set name. + @param[in] default_cs Default character set. + @param[out] cs Variable to store character set. + + @return FALSE if character set was resolved successfully; TRUE if there + is no character set with given name. +*/ + +my_bool resolve_charset(const char *cs_name, + CHARSET_INFO *default_cs, + CHARSET_INFO **cs) +{ + *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0)); + + if (*cs == NULL) + { + *cs= default_cs; + return TRUE; + } + + return FALSE; +} + + +/** + Resolve collation by the collation name (utf8_general_ci, ...). + + The function tries to resolve collation by the specified name. If there + is collation with the given name, it is assigned to the "cl" parameter + and FALSE is returned. If there is no such collation, "default_cl" is + assigned to the "cl" and TRUE is returned. + + @param[out] cl Variable to store collation. + @param[in] cl_name Collation name. + @param[in] default_cl Default collation. + + @return FALSE if collation was resolved successfully; TRUE if there is no + collation with given name. +*/ + +my_bool resolve_collation(const char *cl_name, + CHARSET_INFO *default_cl, + CHARSET_INFO **cl) +{ + *cl= get_charset_by_name(cl_name, MYF(0)); + + if (*cl == NULL) + { + *cl= default_cl; + return TRUE; + } + + return FALSE; +} + + /* Escape string with backslashes (\) @@ -611,13 +670,13 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name, "big enough" RETURN VALUES - ~0 The escaped string did not fit in the to buffer - >=0 The length of the escaped string + (size_t) -1 The escaped string did not fit in the to buffer + # The length of the escaped string */ -ulong escape_string_for_mysql(CHARSET_INFO *charset_info, - char *to, ulong to_length, - const char *from, ulong length) +size_t escape_string_for_mysql(CHARSET_INFO *charset_info, + char *to, size_t to_length, + const char *from, size_t length) { const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); @@ -701,7 +760,7 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, } } *to= 0; - return overflow ? (ulong)~0 : (ulong) (to - to_start); + return overflow ? (size_t) -1 : (size_t) (to - to_start); } @@ -755,9 +814,9 @@ CHARSET_INFO *fs_character_set() >=0 The length of the escaped string */ -ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, - char *to, ulong to_length, - const char *from, ulong length) +size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, + char *to, size_t to_length, + const char *from, size_t length) { const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); @@ -810,43 +869,3 @@ ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info, *to= 0; return overflow ? (ulong)~0 : (ulong) (to - to_start); } - - -/** - @brief Find compatible character set with ctype. - - @param[in] original_cs Original character set - - @note - 128 my_charset_ucs2_general_uca ->192 my_charset_utf8_general_uca_ci - 129 my_charset_ucs2_icelandic_uca_ci ->193 my_charset_utf8_icelandic_uca_ci - 130 my_charset_ucs2_latvian_uca_ci ->194 my_charset_utf8_latvian_uca_ci - 131 my_charset_ucs2_romanian_uca_ci ->195 my_charset_utf8_romanian_uca_ci - 132 my_charset_ucs2_slovenian_uca_ci ->196 my_charset_utf8_slovenian_uca_ci - 133 my_charset_ucs2_polish_uca_ci ->197 my_charset_utf8_polish_uca_ci - 134 my_charset_ucs2_estonian_uca_ci ->198 my_charset_utf8_estonian_uca_ci - 135 my_charset_ucs2_spanish_uca_ci ->199 my_charset_utf8_spanish_uca_ci - 136 my_charset_ucs2_swedish_uca_ci ->200 my_charset_utf8_swedish_uca_ci - 137 my_charset_ucs2_turkish_uca_ci ->201 my_charset_utf8_turkish_uca_ci - 138 my_charset_ucs2_czech_uca_ci ->202 my_charset_utf8_czech_uca_ci - 139 my_charset_ucs2_danish_uca_ci ->203 my_charset_utf8_danish_uca_ci - 140 my_charset_ucs2_lithuanian_uca_ci->204 my_charset_utf8_lithuanian_uca_ci - 141 my_charset_ucs2_slovak_uca_ci ->205 my_charset_utf8_slovak_uca_ci - 142 my_charset_ucs2_spanish2_uca_ci ->206 my_charset_utf8_spanish2_uca_ci - 143 my_charset_ucs2_roman_uca_ci ->207 my_charset_utf8_roman_uca_ci - 144 my_charset_ucs2_persian_uca_ci ->208 my_charset_utf8_persian_uca_ci - - @return Compatible character set or NULL. -*/ - -CHARSET_INFO *get_compatible_charset_with_ctype(CHARSET_INFO *original_cs) -{ - CHARSET_INFO *compatible_cs= 0; - DBUG_ENTER("get_compatible_charset_with_ctype"); - if (!strcmp(original_cs->csname, "ucs2") && - (compatible_cs= get_charset(original_cs->number + 64, MYF(0))) && - (!compatible_cs->ctype || - strcmp(original_cs->name + 4, compatible_cs->name + 4))) - compatible_cs= 0; - DBUG_RETURN(compatible_cs); -} diff --git a/mysys/checksum.c b/mysys/checksum.c index 09e9c5b3730..1c7c9358d53 100644 --- a/mysys/checksum.c +++ b/mysys/checksum.c @@ -15,7 +15,8 @@ #include <my_global.h> -#include "my_sys.h" +#include <my_sys.h> +#include <zlib.h> /* Calculate a long checksum for a memoryblock. @@ -27,15 +28,15 @@ length length of the block */ -ha_checksum my_checksum(ha_checksum crc, const byte *pos, uint length) +ha_checksum my_checksum(ha_checksum crc, const uchar *pos, size_t length) { #ifdef NOT_USED - const byte *end=pos+length; + const uchar *end=pos+length; for ( ; pos != end ; pos++) crc=((crc << 8) + *((uchar*) pos)) + (crc >> (8*sizeof(ha_checksum)-8)); return crc; #else - return (ha_checksum)crc32((uint)crc, (const uchar *)pos, length); + return (ha_checksum)crc32((uint)crc, pos, (uint)length); #endif } diff --git a/mysys/default.c b/mysys/default.c index a55888ad05a..1c0f997520a 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /**************************************************************************** Add all options from files named "group".cnf from the default_directories @@ -97,9 +99,9 @@ static int search_default_file_with_ext(Process_option_func func, - Windows: C:/ - Windows: Directory above where the executable is located - Netware: sys:/etc/ - - Unix & OS/2: /etc/ + - Unix: /etc/ + - Unix: /etc/mysql/ - Unix: --sysconfdir=<path> (compile-time option) - - OS/2: getenv(ETC) - ALL: getenv(DEFAULT_HOME_ENV) - ALL: --defaults-extra-file=<path> (run-time option) - Unix: ~/ @@ -145,6 +147,7 @@ static char *remove_end_comment(char *ptr); RETURN 0 ok 1 given cinf_file doesn't exist + 2 out of memory The global variable 'my_defaults_group_suffix' is updated with value for --defaults_group_suffix @@ -152,7 +155,7 @@ static char *remove_end_comment(char *ptr); int my_search_option_files(const char *conf_file, int *argc, char ***argv, uint *args_used, Process_option_func func, - void *func_ctx) + void *func_ctx, const char **default_directories) { const char **dirs, *forced_default_file, *forced_extra_defaults; int error= 0; @@ -191,7 +194,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, if (!(extra_groups= (const char**)alloc_root(ctx->alloc, (2*group->count+1)*sizeof(char*)))) - goto err; + DBUG_RETURN(2); for (i= 0; i < group->count; i++) { @@ -200,7 +203,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, len= strlen(extra_groups[i]); if (!(ptr= alloc_root(ctx->alloc, (uint) (len+instance_len+1)))) - goto err; + DBUG_RETURN(2); extra_groups[i+group->count]= ptr; @@ -255,12 +258,11 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, } } - DBUG_RETURN(error); + DBUG_RETURN(0); err: fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); - exit(1); - return 0; /* Keep compiler happy */ + DBUG_RETURN(1); } @@ -273,7 +275,8 @@ err: handle_option_ctx structure. group_name The name of the group the option belongs to. option The very option to be processed. It is already - prepared to be used in argv (has -- prefix) + prepared to be used in argv (has -- prefix). If it + is NULL, we are handling a new group (section). DESCRIPTION This handler checks whether a group is one of the listed and adds an option @@ -292,11 +295,14 @@ static int handle_default_option(void *in_ctx, const char *group_name, char *tmp; struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx; + if (!option) + return 0; + if (find_type((char *)group_name, ctx->group, 3)) { - if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1))) + if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1))) return 1; - if (insert_dynamic(ctx->args, (gptr) &tmp)) + if (insert_dynamic(ctx->args, (uchar*) &tmp)) return 1; strmov(tmp, option); } @@ -356,18 +362,46 @@ int get_defaults_options(int argc, char **argv, return org_argc - argc; } +/* + Wrapper around my_load_defaults() for interface compatibility. + + SYNOPSIS + load_defaults() + conf_file Basename for configuration file to search for. + If this is a path, then only this file is read. + groups Which [group] entrys to read. + Points to an null terminated array of pointers + argc Pointer to argc of original program + argv Pointer to argv of original program + + NOTES + + This function is NOT thread-safe as it uses a global pointer internally. + See also notes for my_load_defaults(). + + RETURN + 0 ok + 1 The given conf_file didn't exists +*/ +int load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv) +{ + return my_load_defaults(conf_file, groups, argc, argv, &default_directories); +} /* Read options from configurations files SYNOPSIS - load_defaults() + my_load_defaults() conf_file Basename for configuration file to search for. If this is a path, then only this file is read. groups Which [group] entrys to read. Points to an null terminated array of pointers argc Pointer to argc of original program argv Pointer to argv of original program + default_directories Pointer to a location where a pointer to the list + of default directories will be stored IMPLEMENTATION @@ -383,13 +417,18 @@ int get_defaults_options(int argc, char **argv, that was put in *argv RETURN - 0 ok - 1 The given conf_file didn't exists + - If successful, 0 is returned. If 'default_directories' is not NULL, + a pointer to the array of default directory paths is stored to a location + it points to. That stored value must be passed to my_search_option_files() + later. + + - 1 is returned if the given conf_file didn't exist. In this case, the + value pointed to by default_directories is undefined. */ -int load_defaults(const char *conf_file, const char **groups, - int *argc, char ***argv) +int my_load_defaults(const char *conf_file, const char **groups, + int *argc, char ***argv, const char ***default_directories) { DYNAMIC_ARRAY args; TYPELIB group; @@ -399,10 +438,11 @@ int load_defaults(const char *conf_file, const char **groups, MEM_ROOT alloc; char *ptr,**res; struct handle_option_ctx ctx; + const char **dirs; DBUG_ENTER("load_defaults"); init_alloc_root(&alloc,512,0); - if ((default_directories= init_default_directories(&alloc)) == NULL) + if ((dirs= init_default_directories(&alloc)) == NULL) goto err; /* Check if the user doesn't want any default option processing @@ -423,6 +463,8 @@ int load_defaults(const char *conf_file, const char **groups, (*argc)--; *argv=res; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ + if (default_directories) + *default_directories= dirs; DBUG_RETURN(0); } @@ -441,7 +483,8 @@ int load_defaults(const char *conf_file, const char **groups, ctx.group= &group; error= my_search_option_files(conf_file, argc, argv, &args_used, - handle_default_option, (void *) &ctx); + handle_default_option, (void *) &ctx, + dirs); /* Here error contains <> 0 only if we have a fully specified conf_file or a forced default file @@ -453,7 +496,7 @@ int load_defaults(const char *conf_file, const char **groups, /* copy name + found arguments + command line arguments to new array */ res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */ - memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*)); + memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*)); /* Skip --defaults-xxx options */ (*argc)-= args_used; (*argv)+= args_used; @@ -469,7 +512,7 @@ int load_defaults(const char *conf_file, const char **groups, } if (*argc) - memcpy((gptr) (res+1+args.elements), (char*) ((*argv)+1), + memcpy((uchar*) (res+1+args.elements), (char*) ((*argv)+1), (*argc-1)*sizeof(char*)); res[args.elements+ *argc]=0; /* last null */ @@ -487,6 +530,10 @@ int load_defaults(const char *conf_file, const char **groups, puts(""); exit(0); } + + if (error == 0 && default_directories) + *default_directories= dirs; + DBUG_RETURN(error); err: @@ -541,7 +588,7 @@ static int search_default_file(Process_option_func opt_handler, # Returns pointer to the argument after the keyword. */ -static char *get_argument(const char *keyword, uint kwlen, +static char *get_argument(const char *keyword, size_t kwlen, char *ptr, char *name, uint line) { char *end; @@ -631,7 +678,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, strmov(name,config_file); } fn_format(name,name,"","",4); -#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(__NETWARE__) { MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(0))) @@ -745,10 +792,15 @@ static int search_default_file_with_ext(Process_option_func opt_handler, name,line); goto err; } - for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */ + /* Remove end space */ + for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; end[0]=0; - strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096)); + strmake(curr_gr, ptr, min((size_t) (end-ptr)+1, sizeof(curr_gr)-1)); + + /* signal that a new group is found */ + opt_handler(handler_ctx, curr_gr, NULL); + continue; } if (!found_group) @@ -766,7 +818,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; if (!value) { - strmake(strmov(option,"--"),ptr,(uint) (end-ptr)); + strmake(strmov(option,"--"),ptr, (size_t) (end-ptr)); if (opt_handler(handler_ctx, curr_gr, option)) goto err; } @@ -792,7 +844,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, value++; value_end--; } - ptr=strnmov(strmov(option,"--"),ptr,(uint) (end-ptr)); + ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr)); *ptr++= '='; for ( ; value != value_end; value++) @@ -887,15 +939,11 @@ void my_print_default_files(const char *conf_file) fputs(conf_file,stdout); else { - /* - If default_directories is already initialized, use it. Otherwise, - use a private MEM_ROOT. - */ - const char **dirs = default_directories; + const char **dirs; MEM_ROOT alloc; init_alloc_root(&alloc,512,0); - if (!dirs && (dirs= init_default_directories(&alloc)) == NULL) + if ((dirs= init_default_directories(&alloc)) == NULL) { fputs("Internal error initializing default directories list", stdout); } @@ -950,10 +998,10 @@ void print_defaults(const char *conf_file, const char **groups) } } puts("\nThe following options may be given as the first argument:\n\ ---print-defaults Print the program argument list and exit\n\ ---no-defaults Don't read default options from any options file\n\ ---defaults-file=# Only read default options from the given file #\n\ ---defaults-extra-file=# Read this file after the global files are read"); +--print-defaults Print the program argument list and exit.\n\ +--no-defaults Don't read default options from any option file.\n\ +--defaults-file=# Only read default options from the given file #.\n\ +--defaults-extra-file=# Read this file after the global files are read."); } #include <help_end.h> @@ -962,7 +1010,7 @@ void print_defaults(const char *conf_file, const char **groups) static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs) { char buf[FN_REFLEN]; - uint len; + size_t len; char *p; my_bool err __attribute__((unused)); @@ -987,23 +1035,23 @@ static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs) typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT); -static uint my_get_system_windows_directory(char *buffer, uint size) +static size_t my_get_system_windows_directory(char *buffer, size_t size) { - uint count; + size_t count; GET_SYSTEM_WINDOWS_DIRECTORY func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY) GetProcAddress(GetModuleHandle("kernel32.dll"), "GetSystemWindowsDirectoryA"); if (func_ptr) - return func_ptr(buffer, size); + return func_ptr(buffer, (uint) size); /* Windows NT 4.0 Terminal Server Edition: To retrieve the shared Windows directory, call GetSystemDirectory and trim the "System32" element from the end of the returned path. */ - count= GetSystemDirectory(buffer, size); + count= GetSystemDirectory(buffer, (uint) size); if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0) { count-= 8; @@ -1079,14 +1127,12 @@ static const char **init_default_directories(MEM_ROOT *alloc) #else errors += add_directory(alloc, "/etc/", dirs); + errors += add_directory(alloc, "/etc/mysql/", dirs); -#if defined(__EMX__) || defined(OS2) - if ((env= getenv("ETC"))) - errors += add_directory(alloc, env, dirs); -#elif defined(DEFAULT_SYSCONFDIR) +#if defined(DEFAULT_SYSCONFDIR) if (DEFAULT_SYSCONFDIR[0]) errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs); -#endif /* __EMX__ || __OS2__ */ +#endif /* DEFAULT_SYSCONFDIR */ #endif @@ -1096,8 +1142,7 @@ static const char **init_default_directories(MEM_ROOT *alloc) /* Placeholder for --defaults-extra-file=<path> */ errors += add_directory(alloc, "", dirs); -#if !defined(__WIN__) && !defined(__NETWARE__) && \ - !defined(__EMX__) && !defined(OS2) +#if !defined(__WIN__) && !defined(__NETWARE__) errors += add_directory(alloc, "~/", dirs); #endif diff --git a/mysys/default_modify.c b/mysys/default_modify.c index be40d3b3660..88df0122da2 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -39,11 +39,13 @@ static char *add_option(char *dst, const char *option_value, SYNOPSYS modify_defaults_file() file_location The location of configuration file to edit - option option to look for - option value The value of the option we would like to set - section_name the name of the section - remove_option This is true if we want to remove the option. - False otherwise. + option The name of the option to look for (can be NULL) + option value The value of the option we would like to set (can be NULL) + section_name The name of the section (must be NOT NULL) + remove_option This defines what we want to remove: + - MY_REMOVE_NONE -- nothing to remove; + - MY_REMOVE_OPTION -- remove the specified option; + - MY_REMOVE_SECTION -- remove the specified section; IMPLEMENTATION We open the option file first, then read the file line-by-line, looking for the section we need. At the same time we put these lines @@ -66,10 +68,9 @@ int modify_defaults_file(const char *file_location, const char *option, FILE *cnf_file; MY_STAT file_stat; char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; - uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; + size_t opt_len= 0, optval_len= 0, sect_len, new_opt_len, reserve_extended; + uint nr_newlines= 0, buffer_size; my_bool in_section= FALSE, opt_applied= 0; - uint reserve_extended; - uint new_opt_len; int reserve_occupied= 0; DBUG_ENTER("modify_defaults_file"); @@ -80,8 +81,11 @@ int modify_defaults_file(const char *file_location, const char *option, if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) goto malloc_err; - opt_len= (uint) strlen(option); - optval_len= (uint) strlen(option_value); + if (option && option_value) + { + opt_len= strlen(option); + optval_len= strlen(option_value); + } new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; @@ -103,7 +107,7 @@ int modify_defaults_file(const char *file_location, const char *option, MYF(MY_WME)))) goto malloc_err; - sect_len= (uint) strlen(section_name); + sect_len= strlen(section_name); for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); ) { @@ -118,8 +122,8 @@ int modify_defaults_file(const char *file_location, const char *option, continue; } - /* correct the option */ - if (in_section && !strncmp(src_ptr, option, opt_len) && + /* correct the option (if requested) */ + if (option && in_section && !strncmp(src_ptr, option, opt_len) && (*(src_ptr + opt_len) == '=' || my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) || *(src_ptr + opt_len) == '\0')) @@ -142,7 +146,12 @@ int modify_defaults_file(const char *file_location, const char *option, } else { - /* If going to new group and we have option to apply, do it now */ + /* + If we are going to the new group and have an option to apply, do + it now. If we are removing a single option or the whole section + this will only trigger opt_applied flag. + */ + if (in_section && !opt_applied && *src_ptr == '[') { dst_ptr= add_option(dst_ptr, option_value, option, remove_option); @@ -152,7 +161,10 @@ int modify_defaults_file(const char *file_location, const char *option, for (; nr_newlines; nr_newlines--) dst_ptr= strmov(dst_ptr, NEWLINE); - dst_ptr= strmov(dst_ptr, linebuff); + + /* Skip the section if MY_REMOVE_SECTION was given */ + if (!in_section || remove_option != MY_REMOVE_SECTION) + dst_ptr= strmov(dst_ptr, linebuff); } /* Look for a section */ if (*src_ptr == '[') @@ -166,18 +178,31 @@ int modify_defaults_file(const char *file_location, const char *option, {} if (*src_ptr != ']') + { + in_section= FALSE; continue; /* Missing closing parenthesis. Assume this was no group */ + } + + if (remove_option == MY_REMOVE_SECTION) + dst_ptr= dst_ptr - strlen(linebuff); + in_section= TRUE; } else in_section= FALSE; /* mark that this section is of no interest to us */ } } - /* File ended. */ - if (!opt_applied && !remove_option && in_section) + + /* + File ended. Apply an option or set opt_applied flag (in case of + MY_REMOVE_SECTION) so that the changes are saved. Do not do anything + if we are removing non-existent option. + */ + + if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION)) { /* New option still remains to apply at the end */ - if (*(dst_ptr - 1) != '\n') + if (!remove_option && *(dst_ptr - 1) != '\n') dst_ptr= strmov(dst_ptr, NEWLINE); dst_ptr= add_option(dst_ptr, option_value, option, remove_option); opt_applied= 1; @@ -191,7 +216,7 @@ int modify_defaults_file(const char *file_location, const char *option, if (my_chsize(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, file_buffer, (uint) (dst_ptr - file_buffer), + my_fwrite(cnf_file, (uchar*) file_buffer, (size_t) (dst_ptr - file_buffer), MYF(MY_NABP))) goto err; } diff --git a/mysys/errors.c b/mysys/errors.c index 0218996e3b9..4e93f872a55 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2001, 2003-2006, 2008 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -39,7 +40,7 @@ const char * NEAR globerrs[GLOBERRS]= "Can't get working dirctory (Errcode: %d)", "Can't change dir to '%s' (Errcode: %d)", "Warning: '%s' had %d links", - "%d files and %d streams is left open\n", + "Warning: %d files and %d streams is left open\n", "Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... (Expect up to %d secs delay for server to continue after freeing disk space)", "Can't create directory '%s' (Errcode: %d)", "Character set '%s' is not a compiled character set and is not specified in the '%s' file", @@ -50,6 +51,10 @@ const char * NEAR globerrs[GLOBERRS]= "Can't sync file '%s' to disk (Errcode: %d)", "Collation '%s' is not a compiled collation and is not specified in the '%s' file", "File '%s' not found (Errcode: %d)", + "File '%s' (fileno: %d) was not closed", + "Can't change ownership of the file '%s' (Errcode: %d)", + "Can't change permissions of the file '%s' (Errcode: %d)", + "Can't seek in file '%s' (Errcode: %d)" }; void init_glob_errs(void) @@ -78,7 +83,7 @@ void init_glob_errs() EE(EE_GETWD) = "Can't get working directory (Errcode: %d)"; EE(EE_SETWD) = "Can't change dir to '%s' (Errcode: %d)"; EE(EE_LINK_WARNING) = "Warning: '%s' had %d links"; - EE(EE_OPEN_WARNING) = "%d files and %d streams is left open\n"; + EE(EE_OPEN_WARNING) = "Warning: %d files and %d streams is left open\n"; EE(EE_DISK_FULL) = "Disk is full writing '%s'. Waiting for someone to free space..."; EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)"; EE(EE_UNKNOWN_CHARSET)= "Character set '%s' is not a compiled character set and is not specified in the %s file"; @@ -89,6 +94,10 @@ void init_glob_errs() EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)"; EE(EE_UNKNOWN_COLLATION)= "Collation '%s' is not a compiled collation and is not specified in the %s file"; EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)"; + EE(EE_FILE_NOT_CLOSED) = "File '%s' (fileno: %d) was not closed"; + EE(EE_CHANGE_OWNERSHIP) = "Can't change ownership of the file '%s' (Errcode: %d)"; + EE(EE_CHANGE_PERMISSIONS) = "Can't change permissions of the file '%s' (Errcode: %d)"; + EE(EE_CANT_SEEK) = "Can't seek in file '%s' (Errcode: %d)"; } #endif diff --git a/mysys/hash.c b/mysys/hash.c index f378b44130c..290eb78797a 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* The hash functions used for saveing keys */ /* One of key_length or key_length_offset must be given */ @@ -31,15 +33,15 @@ typedef struct st_hash_info { uint next; /* index to next key */ - byte *data; /* data for current entry */ + uchar *data; /* data for current entry */ } HASH_LINK; -static uint hash_mask(uint hashnr,uint buffmax,uint maxlength); +static uint my_hash_mask(size_t hashnr, size_t buffmax, size_t maxlength); static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, - uint length); +static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, + size_t length); -static uint calc_hash(const HASH *hash, const byte *key, uint length) +static uint calc_hash(const HASH *hash, const uchar *key, size_t length) { ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); @@ -73,13 +75,13 @@ static uint calc_hash(const HASH *hash, const byte *key, uint length) @retval 1 failure */ my_bool -_hash_init(HASH *hash,CHARSET_INFO *charset, - uint size,uint key_offset,uint key_length, - hash_get_key get_key, - void (*free_element)(void*),uint flags CALLER_INFO_PROTO) +_my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset, + ulong size, size_t key_offset, size_t key_length, + my_hash_get_key get_key, + void (*free_element)(void*), uint flags CALLER_INFO_PROTO) { - DBUG_ENTER("hash_init"); - DBUG_PRINT("enter",("hash: 0x%lx size: %d", (long) hash, size)); + DBUG_ENTER("my_hash_init"); + DBUG_PRINT("enter",("hash: 0x%lx size: %u", (long) hash, (uint) size)); hash->records=0; hash->key_offset=key_offset; @@ -90,7 +92,7 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, hash->flags=flags; hash->charset=charset; DBUG_RETURN(my_init_dynamic_array_ci(&hash->array, - sizeof(HASH_LINK), size, 0)); + sizeof(HASH_LINK), size, growth_size)); } @@ -98,14 +100,14 @@ _hash_init(HASH *hash,CHARSET_INFO *charset, Call hash->free on all elements in hash. SYNOPSIS - hash_free_elements() + my_hash_free_elements() hash hash table NOTES: Sets records to 0 */ -static inline void hash_free_elements(HASH *hash) +static inline void my_hash_free_elements(HASH *hash) { if (hash->free) { @@ -122,18 +124,18 @@ static inline void hash_free_elements(HASH *hash) Free memory used by hash. SYNOPSIS - hash_free() + my_hash_free() hash the hash to delete elements of - NOTES: Hash can't be reused without calling hash_init again. + NOTES: Hash can't be reused without calling my_hash_init again. */ -void hash_free(HASH *hash) +void my_hash_free(HASH *hash) { - DBUG_ENTER("hash_free"); - DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); + DBUG_ENTER("my_hash_free"); + DBUG_PRINT("enter",("hash: 0x%lx", (long) hash)); - hash_free_elements(hash); + my_hash_free_elements(hash); hash->free= 0; delete_dynamic(&hash->array); hash->blength= 0; @@ -154,44 +156,44 @@ void my_hash_reset(HASH *hash) DBUG_ENTER("my_hash_reset"); DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); - hash_free_elements(hash); + my_hash_free_elements(hash); reset_dynamic(&hash->array); /* Set row pointers so that the hash can be reused at once */ hash->blength= 1; DBUG_VOID_RETURN; } - /* some helper functions */ +/* some helper functions */ /* - This function is char* instead of byte* as HPUX11 compiler can't + This function is char* instead of uchar* as HPUX11 compiler can't handle inline functions that are not defined as native types */ static inline char* -hash_key(const HASH *hash, const byte *record, uint *length, - my_bool first) +my_hash_key(const HASH *hash, const uchar *record, size_t *length, + my_bool first) { if (hash->get_key) - return (*hash->get_key)(record,length,first); + return (char*) (*hash->get_key)(record,length,first); *length=hash->key_length; - return (byte*) record+hash->key_offset; + return (char*) record+hash->key_offset; } /* Calculate pos according to keys */ -static uint hash_mask(uint hashnr,uint buffmax,uint maxlength) +static uint my_hash_mask(size_t hashnr, size_t buffmax, size_t maxlength) { if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1)); return (hashnr & ((buffmax >> 1) -1)); } -static uint hash_rec_mask(const HASH *hash, HASH_LINK *pos, - uint buffmax, uint maxlength) +static uint my_hash_rec_mask(const HASH *hash, HASH_LINK *pos, + size_t buffmax, size_t maxlength) { - uint length; - byte *key= (byte*) hash_key(hash,pos->data,&length,0); - return hash_mask(calc_hash(hash,key,length),buffmax,maxlength); + size_t length; + uchar *key= (uchar*) my_hash_key(hash, pos->data, &length, 0); + return my_hash_mask(calc_hash(hash, key, length), buffmax, maxlength); } @@ -201,18 +203,18 @@ static #if !defined(__USLC__) && !defined(__sgi) inline #endif -unsigned int rec_hashnr(HASH *hash,const byte *record) +unsigned int rec_hashnr(HASH *hash,const uchar *record) { - uint length; - byte *key= (byte*) hash_key(hash,record,&length,0); + size_t length; + uchar *key= (uchar*) my_hash_key(hash, record, &length, 0); return calc_hash(hash,key,length); } -gptr hash_search(const HASH *hash, const byte *key, uint length) +uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) { HASH_SEARCH_STATE state; - return hash_first(hash, key, length, &state); + return my_hash_first(hash, key, length, &state); } /* @@ -222,18 +224,18 @@ gptr hash_search(const HASH *hash, const byte *key, uint length) Assigns the number of the found record to HASH_SEARCH_STATE state */ -gptr hash_first(const HASH *hash, const byte *key, uint length, - HASH_SEARCH_STATE *current_record) +uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint flag,idx; - DBUG_ENTER("hash_first"); + DBUG_ENTER("my_hash_first"); flag=1; if (hash->records) { - idx=hash_mask(calc_hash(hash,key,length ? length : hash->key_length), - hash->blength,hash->records); + idx= my_hash_mask(calc_hash(hash, key, length ? length : hash->key_length), + hash->blength, hash->records); do { pos= dynamic_element(&hash->array,idx,HASH_LINK*); @@ -246,7 +248,7 @@ gptr hash_first(const HASH *hash, const byte *key, uint length, if (flag) { flag=0; /* Reset flag */ - if (hash_rec_mask(hash,pos,hash->blength,hash->records) != idx) + if (my_hash_rec_mask(hash, pos, hash->blength, hash->records) != idx) break; /* Wrong link */ } } @@ -257,10 +259,10 @@ gptr hash_first(const HASH *hash, const byte *key, uint length, } /* Get next record with identical key */ - /* Can only be called if previous calls was hash_search */ + /* Can only be called if previous calls was my_hash_search */ -gptr hash_next(const HASH *hash, const byte *key, uint length, - HASH_SEARCH_STATE *current_record) +uchar* my_hash_next(const HASH *hash, const uchar *key, size_t length, + HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; uint idx; @@ -316,11 +318,11 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) != 0 key of record != key */ -static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, - uint length) +static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, + size_t length) { - uint rec_keylength; - byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); + size_t rec_keylength; + uchar *rec_key= (uchar*) my_hash_key(hash, pos->data, &rec_keylength, 1); return ((length && length != rec_keylength) || my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength, (uchar*) key, rec_keylength)); @@ -329,13 +331,20 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key, /* Write a hash-key to the hash-index */ -my_bool my_hash_insert(HASH *info,const byte *record) +my_bool my_hash_insert(HASH *info, const uchar *record) { int flag; - uint halfbuff,hash_nr,first_index,idx; - byte *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); + size_t idx,halfbuff,hash_nr,first_index; + uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; + if (HASH_UNIQUE & info->flags) + { + uchar *key= (uchar*) my_hash_key(info, record, &idx, 1); + if (my_hash_search(info, key, idx)) + return(TRUE); /* Duplicate entry */ + } + flag=0; if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) return(TRUE); /* No more memory */ @@ -351,7 +360,7 @@ my_bool my_hash_insert(HASH *info,const byte *record) pos=data+idx; hash_nr=rec_hashnr(info,pos->data); if (flag == 0) /* First loop; Check if ok */ - if (hash_mask(hash_nr,info->blength,info->records) != first_index) + if (my_hash_mask(hash_nr, info->blength, info->records) != first_index) break; if (!(hash_nr & halfbuff)) { /* Key will not move */ @@ -378,7 +387,7 @@ my_bool my_hash_insert(HASH *info,const byte *record) { /* Change link of previous LOW-key */ gpos->data=ptr_to_rec; - gpos->next=(uint) (pos-data); + gpos->next= (uint) (pos-data); flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); } gpos=pos; @@ -423,26 +432,26 @@ my_bool my_hash_insert(HASH *info,const byte *record) } /* Check if we are at the empty position */ - idx=hash_mask(rec_hashnr(info,record),info->blength,info->records+1); + idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1); pos=data+idx; if (pos == empty) { - pos->data=(byte*) record; + pos->data=(uchar*) record; pos->next=NO_RECORD; } else { /* Check if more records in same hash-nr family */ empty[0]=pos[0]; - gpos=data+hash_rec_mask(info,pos,info->blength,info->records+1); + gpos= data + my_hash_rec_mask(info, pos, info->blength, info->records + 1); if (pos == gpos) { - pos->data=(byte*) record; + pos->data=(uchar*) record; pos->next=(uint) (empty - data); } else { - pos->data=(byte*) record; + pos->data=(uchar*) record; pos->next=NO_RECORD; movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data)); } @@ -459,18 +468,18 @@ my_bool my_hash_insert(HASH *info,const byte *record) ** if there is a free-function it's called for record if found ******************************************************************************/ -my_bool hash_delete(HASH *hash,byte *record) +my_bool my_hash_delete(HASH *hash, uchar *record) { uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index; HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty; - DBUG_ENTER("hash_delete"); + DBUG_ENTER("my_hash_delete"); if (!hash->records) DBUG_RETURN(1); blength=hash->blength; data=dynamic_element(&hash->array,0,HASH_LINK*); /* Search after record with key */ - pos=data+ hash_mask(rec_hashnr(hash,record),blength,hash->records); + pos= data + my_hash_mask(rec_hashnr(hash, record), blength, hash->records); gpos = 0; while (pos->data != record) @@ -501,7 +510,7 @@ my_bool hash_delete(HASH *hash,byte *record) /* Move the last key (lastpos) */ lastpos_hashnr=rec_hashnr(hash,lastpos->data); /* pos is where lastpos should be */ - pos=data+hash_mask(lastpos_hashnr,hash->blength,hash->records); + pos= data + my_hash_mask(lastpos_hashnr, hash->blength, hash->records); if (pos == empty) /* Move to empty position. */ { empty[0]=lastpos[0]; @@ -509,7 +518,7 @@ my_bool hash_delete(HASH *hash,byte *record) } pos_hashnr=rec_hashnr(hash,pos->data); /* pos3 is where the pos should be */ - pos3= data+hash_mask(pos_hashnr,hash->blength,hash->records); + pos3= data + my_hash_mask(pos_hashnr, hash->blength, hash->records); if (pos != pos3) { /* pos is on wrong posit */ empty[0]=pos[0]; /* Save it here */ @@ -517,8 +526,8 @@ my_bool hash_delete(HASH *hash,byte *record) movelink(data,(uint) (pos-data),(uint) (pos3-data),empty_index); goto exit; } - pos2= hash_mask(lastpos_hashnr,blength,hash->records+1); - if (pos2 == hash_mask(pos_hashnr,blength,hash->records+1)) + pos2= my_hash_mask(lastpos_hashnr, blength, hash->records + 1); + if (pos2 == my_hash_mask(pos_hashnr, blength, hash->records + 1)) { /* Identical key-positions */ if (pos2 != hash->records) { @@ -537,7 +546,7 @@ my_bool hash_delete(HASH *hash,byte *record) exit: VOID(pop_dynamic(&hash->array)); if (hash->free) - (*hash->free)((byte*) record); + (*hash->free)((uchar*) record); DBUG_RETURN(0); } @@ -546,22 +555,39 @@ exit: This is much more efficent than using a delete & insert. */ -my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) +my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, + size_t old_key_length) { - uint idx,new_index,new_pos_index,blength,records,empty; + uint new_index,new_pos_index,blength,records; + size_t idx,empty; HASH_LINK org_link,*data,*previous,*pos; - DBUG_ENTER("hash_update"); + DBUG_ENTER("my_hash_update"); + + if (HASH_UNIQUE & hash->flags) + { + HASH_SEARCH_STATE state; + uchar *found, *new_key= (uchar*) my_hash_key(hash, record, &idx, 1); + if ((found= my_hash_first(hash, new_key, idx, &state))) + { + do + { + if (found != record) + DBUG_RETURN(1); /* Duplicate entry */ + } + while ((found= my_hash_next(hash, new_key, idx, &state))); + } + } data=dynamic_element(&hash->array,0,HASH_LINK*); blength=hash->blength; records=hash->records; /* Search after record with key */ - idx=hash_mask(calc_hash(hash, old_key,(old_key_length ? - old_key_length : - hash->key_length)), - blength,records); - new_index=hash_mask(rec_hashnr(hash,record),blength,records); + idx= my_hash_mask(calc_hash(hash, old_key, (old_key_length ? + old_key_length : + hash->key_length)), + blength, records); + new_index= my_hash_mask(rec_hashnr(hash, record), blength, records); if (idx == new_index) DBUG_RETURN(0); /* Nothing to do (No record check) */ previous=0; @@ -611,7 +637,7 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) DBUG_RETURN(0); } pos=data+new_index; - new_pos_index=hash_rec_mask(hash,pos,blength,records); + new_pos_index= my_hash_rec_mask(hash, pos, blength, records); if (new_index != new_pos_index) { /* Other record in wrong position */ data[empty] = *pos; @@ -629,7 +655,7 @@ my_bool hash_update(HASH *hash,byte *record,byte *old_key,uint old_key_length) } -byte *hash_element(HASH *hash,uint idx) +uchar *my_hash_element(HASH *hash, ulong idx) { if (idx < hash->records) return dynamic_element(&hash->array,idx,HASH_LINK*)->data; @@ -642,7 +668,8 @@ byte *hash_element(HASH *hash,uint idx) isn't changed */ -void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, byte *new_row) +void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, + uchar *new_row) { if (*current_record != NO_RECORD) /* Safety */ dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row; @@ -651,7 +678,7 @@ void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, byte *new_row) #ifndef DBUG_OFF -my_bool hash_check(HASH *hash) +my_bool my_hash_check(HASH *hash) { int error; uint i,rec_link,found,max_links,seek,links,idx; @@ -664,7 +691,7 @@ my_bool hash_check(HASH *hash) for (i=found=max_links=seek=0 ; i < records ; i++) { - if (hash_rec_mask(hash,data+i,blength,records) == i) + if (my_hash_rec_mask(hash, data + i, blength, records) == i) { found++; seek++; links=1; for (idx=data[i].next ; @@ -680,11 +707,12 @@ my_bool hash_check(HASH *hash) } hash_info=data+idx; seek+= ++links; - if ((rec_link=hash_rec_mask(hash,hash_info,blength,records)) != i) + if ((rec_link= my_hash_rec_mask(hash, hash_info, + blength, records)) != i) { - DBUG_PRINT("error", - ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d", - idx, i, (long) hash_info->data, rec_link)); + DBUG_PRINT("error", ("Record in wrong link at %d: Start %d " + "Record: 0x%lx Record-link %d", + idx, i, (long) hash_info->data, rec_link)); error=1; } else diff --git a/mysys/list.c b/mysys/list.c index ccc3f495093..aaadd686365 100644 --- a/mysys/list.c +++ b/mysys/list.c @@ -61,8 +61,8 @@ void list_free(LIST *root, uint free_data) { next=root->next; if (free_data) - my_free((gptr) root->data,MYF(0)); - my_free((gptr) root,MYF(0)); + my_free((uchar*) root->data,MYF(0)); + my_free((uchar*) root,MYF(0)); root=next; } } @@ -101,7 +101,7 @@ uint list_length(LIST *list) } -int list_walk(LIST *list, list_walk_action action, gptr argument) +int list_walk(LIST *list, list_walk_action action, uchar* argument) { int error=0; while (list) diff --git a/mysys/make-ccc b/mysys/make-ccc index 9c54185682a..b34bd80e1d1 100755 --- a/mysys/make-ccc +++ b/mysys/make-ccc @@ -1,4 +1,4 @@ rm -f .deps/* raid.o mf_iocache.o libmysys.a -ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c my_mkdir.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_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c +ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_malloc.c my_messnc.c my_mkdir.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_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c make raid.o mf_iocache.o my_lock.o ar -cr libmysys.a array.o raid.o mf_iocache.o my_lock.o diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c index a3abb3bc974..f0df0f3fa77 100644 --- a/mysys/mf_cache.c +++ b/mysys/mf_cache.c @@ -58,7 +58,7 @@ static my_bool cache_remove_open_tmp(IO_CACHE *cache __attribute__((unused)), */ my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, - uint cache_size, myf cache_myflags) + size_t cache_size, myf cache_myflags) { DBUG_ENTER("open_cached_file"); cache->dir= dir ? my_strdup(dir,MYF(cache_myflags & MY_WME)) : (char*) 0; diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c index d1672e55b65..1b428ded751 100644 --- a/mysys/mf_dirname.c +++ b/mysys/mf_dirname.c @@ -18,9 +18,9 @@ /* Functions definied in this file */ -uint dirname_length(const char *name) +size_t dirname_length(const char *name) { - register my_string pos,gpos; + register char *pos, *gpos; #ifdef BASKSLASH_MBTAIL CHARSET_INFO *fs= fs_character_set(); #endif @@ -47,21 +47,31 @@ uint dirname_length(const char *name) ) gpos=pos; } - return ((uint) (uint) (gpos+1-(char*) name)); + return (size_t) (gpos+1-(char*) name); } - /* Gives directory part of filename. Directory ends with '/' */ - /* Returns length of directory part */ +/* + Gives directory part of filename. Directory ends with '/' + + SYNOPSIS + dirname_part() + to Store directory name here + name Original name + to_length Store length of 'to' here + + RETURN + # Length of directory part in 'name' +*/ -uint dirname_part(my_string to, const char *name) +size_t dirname_part(char *to, const char *name, size_t *to_res_length) { - uint length; + size_t length; DBUG_ENTER("dirname_part"); DBUG_PRINT("enter",("'%s'",name)); length=dirname_length(name); - convert_dirname(to, name, name+length); + *to_res_length= (size_t) (convert_dirname(to, name, name+length) - to); DBUG_RETURN(length); } /* dirname */ @@ -74,7 +84,7 @@ uint dirname_part(my_string to, const char *name) to Store result here. Must be at least of size min(FN_REFLEN, strlen(from) + 1) to make room for adding FN_LIBCHAR at the end. - from Original filename + from Original filename. May be == to from_end Pointer at end of filename (normally end \0) IMPLEMENTATION @@ -102,6 +112,7 @@ char *convert_dirname(char *to, const char *from, const char *from_end) #ifdef BACKSLASH_MBTAIL CHARSET_INFO *fs= fs_character_set(); #endif + DBUG_ENTER("convert_dirname"); /* We use -2 here, becasue we need place for the last FN_LIBCHAR */ if (!from_end || (from_end - from) > FN_REFLEN-2) @@ -141,7 +152,7 @@ char *convert_dirname(char *to, const char *from, const char *from_end) } #else /* This is ok even if to == from, becasue we need to cut the string */ - to= strmake(to, from, (uint) (from_end-from)); + to= strmake(to, from, (size_t) (from_end-from)); #endif /* Add FN_LIBCHAR to the end of directory path */ @@ -150,5 +161,5 @@ char *convert_dirname(char *to, const char *from, const char *from_end) *to++=FN_LIBCHAR; *to=0; } - return to; /* Pointer to end of dir */ + DBUG_RETURN(to); /* Pointer to end of dir */ } /* convert_dirname */ diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c index 20e835fe641..da7fac3de73 100644 --- a/mysys/mf_fn_ext.c +++ b/mysys/mf_fn_ext.c @@ -33,21 +33,22 @@ points at the end ASCII(0) of the filename. */ -my_string fn_ext(const char *name) +char *fn_ext(const char *name) { - register my_string pos,gpos; + register const char *pos, *gpos; DBUG_ENTER("fn_ext"); DBUG_PRINT("mfunkt",("name: '%s'",name)); #if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR) || defined(BASKSLASH_MBTAIL) { char buff[FN_REFLEN]; - gpos=(my_string) name+dirname_part(buff,(char*) name); + size_t res_length; + gpos= name+ dirname_part(buff,(char*) name, &res_length); } #else if (!(gpos= strrchr(name, FN_LIBCHAR))) - gpos= (my_string) name; + gpos= name; #endif pos=strchr(gpos,FN_EXTCHAR); - DBUG_RETURN (pos ? pos : strend(gpos)); + DBUG_RETURN((char*) (pos ? pos : strend(gpos))); } /* fn_ext */ diff --git a/mysys/mf_format.c b/mysys/mf_format.c index 7a861c9f1e6..b0c7075aa9a 100644 --- a/mysys/mf_format.c +++ b/mysys/mf_format.c @@ -1,4 +1,6 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. 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 @@ -11,7 +13,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include <m_string.h> @@ -23,18 +26,19 @@ The arguments should be in unix format. */ -my_string fn_format(my_string to, const char *name, const char *dir, +char * fn_format(char * to, const char *name, const char *dir, const char *extension, uint flag) { - reg1 uint length; char dev[FN_REFLEN], buff[FN_REFLEN], *pos, *startpos; const char *ext; + reg1 size_t length; + size_t dev_length; DBUG_ENTER("fn_format"); DBUG_PRINT("enter",("name: %s dir: %s extension: %s flag: %d", name,dir,extension,flag)); /* Copy and skip directory */ - name+=(length=dirname_part(dev,(startpos=(my_string) name))); + name+=(length=dirname_part(dev, (startpos=(char *) name), &dev_length)); if (length == 0 || (flag & MY_REPLACE_DIR)) { /* Use given directory */ @@ -53,7 +57,8 @@ my_string fn_format(my_string to, const char *name, const char *dir, if (flag & MY_UNPACK_FILENAME) (void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */ - if ((pos= (char*) strchr(name,FN_EXTCHAR)) != NullS) + if (!(flag & MY_APPEND_EXT) && + (pos= (char*) strchr(name,FN_EXTCHAR)) != NullS) { if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */ { @@ -62,7 +67,7 @@ my_string fn_format(my_string to, const char *name, const char *dir, } else { - length=(uint) (pos-(char*) name); /* Change extension */ + length= (size_t) (pos-(char*) name); /* Change extension */ ext= extension; } } @@ -75,18 +80,19 @@ my_string fn_format(my_string to, const char *name, const char *dir, if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN ) { /* To long path, return original or NULL */ - uint tmp_length; + size_t tmp_length; if (flag & MY_SAFE_PATH) - return NullS; - tmp_length=strlength(startpos); - DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %d",dev,ext,length)); + DBUG_RETURN(NullS); + tmp_length= strlength(startpos); + DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %u",dev,ext, + (uint) length)); (void) strmake(to,startpos,min(tmp_length,FN_REFLEN-1)); } else { if (to == startpos) { - bmove(buff,(char*) name,length); /* Save name for last copy */ + bmove(buff,(uchar*) name,length); /* Save name for last copy */ name=buff; } pos=strmake(strmov(to,dev),name,length); @@ -108,18 +114,18 @@ my_string fn_format(my_string to, const char *name, const char *dir, } /* fn_format */ - /* - strlength(const string str) - Return length of string with end-space:s not counted. - */ +/* + strlength(const string str) + Return length of string with end-space:s not counted. +*/ -size_s strlength(const char *str) +size_t strlength(const char *str) { - reg1 my_string pos; - reg2 my_string found; + reg1 const char * pos; + reg2 const char * found; DBUG_ENTER("strlength"); - pos=found=(char*) str; + pos= found= str; while (*pos) { @@ -135,5 +141,5 @@ size_s strlength(const char *str) found=pos; while (*++pos == ' ') {}; } - DBUG_RETURN((size_s) (found-(char*) str)); + DBUG_RETURN((size_t) (found - str)); } /* strlength */ diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c index e42777aee8a..f517fcae70d 100644 --- a/mysys/mf_getdate.c +++ b/mysys/mf_getdate.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2004-2006 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Get date in a printable form: yyyy-mm-dd hh:mm:ss */ @@ -35,7 +37,7 @@ */ -void get_date(register my_string to, int flag, time_t date) +void get_date(register char * to, int flag, time_t date) { reg2 struct tm *start_time; time_t skr; @@ -43,7 +45,7 @@ void get_date(register my_string to, int flag, time_t date) struct tm tm_tmp; #endif - skr=date ? (time_t) date : time((time_t*) 0); + skr=date ? (time_t) date : my_time(0); #if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) if (flag & GETDATE_GMT) gmtime_r(&skr,&tm_tmp); diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 221b4d8b044..82dac7e0956 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Cashing of files with only does (sequential) read or writes of fixed- @@ -153,11 +154,11 @@ init_functions(IO_CACHE* info) # error */ -int init_io_cache(IO_CACHE *info, File file, uint cachesize, +int init_io_cache(IO_CACHE *info, File file, size_t cachesize, enum cache_type type, my_off_t seek_offset, pbool use_async_io, myf cache_myflags) { - uint min_cache; + size_t min_cache; my_off_t pos; my_off_t end_of_file= ~(my_off_t) 0; DBUG_ENTER("init_io_cache"); @@ -215,7 +216,7 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, /* Trim cache size if the file is very small */ if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) { - cachesize=(uint) (end_of_file-seek_offset)+IO_SIZE*2-1; + cachesize= (size_t) (end_of_file-seek_offset)+IO_SIZE*2-1; use_async_io=0; /* No need to use async */ } } @@ -224,11 +225,10 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, if (type != READ_NET && type != WRITE_NET) { /* Retry allocating memory in smaller blocks until we get one */ - cachesize=(uint) ((ulong) (cachesize + min_cache-1) & - (ulong) ~(min_cache-1)); + cachesize= ((cachesize + min_cache-1) & ~(min_cache-1)); for (;;) { - uint buffer_block; + size_t buffer_block; /* Unset MY_WAIT_IF_FULL bit if it is set, to prevent conflict with MY_ZEROFILL. @@ -237,12 +237,13 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, if (cachesize < min_cache) cachesize = min_cache; - buffer_block = cachesize; + buffer_block= cachesize; if (type == SEQ_READ_APPEND) buffer_block *= 2; if (cachesize == min_cache) flags|= (myf) MY_WME; - if ((info->buffer= (byte*) my_malloc(buffer_block, flags)) != 0) + + if ((info->buffer= (uchar*) my_malloc(buffer_block, flags)) != 0) { info->write_buffer=info->buffer; if (type == SEQ_READ_APPEND) @@ -253,11 +254,11 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, if (cachesize == min_cache) DBUG_RETURN(2); /* Can't alloc cache */ /* Try with less memory */ - cachesize= (uint) ((ulong) cachesize*3/4 & (ulong)~(min_cache-1)); + cachesize= (cachesize*3/4 & ~(min_cache-1)); } } - DBUG_PRINT("info",("init_io_cache: cachesize = %u",cachesize)); + DBUG_PRINT("info",("init_io_cache: cachesize = %lu", (ulong) cachesize)); info->read_length=info->buffer_length=cachesize; info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP); info->request_pos= info->read_pos= info->write_pos = info->buffer; @@ -356,7 +357,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, seek_offset <= my_b_tell(info)) { /* Reuse current buffer without flushing it to disk */ - byte *pos; + uchar *pos; if (info->type == WRITE_CACHE && type == READ_CACHE) { info->read_end=info->write_pos; @@ -458,22 +459,22 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, 1 Error: can't read requested characters */ -int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) +int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) { - uint length,diff_length,left_length; - my_off_t max_length, pos_in_file; + size_t length,diff_length,left_length, max_length; + my_off_t pos_in_file; DBUG_ENTER("_my_b_read"); - if ((left_length=(uint) (info->read_end-info->read_pos))) + if ((left_length= (size_t) (info->read_end-info->read_pos))) { DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */ - memcpy(Buffer,info->read_pos, (size_t) (left_length)); + memcpy(Buffer,info->read_pos, left_length); Buffer+=left_length; Count-=left_length; } /* pos_in_file always point on where info->buffer was read */ - pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer); + pos_in_file=info->pos_in_file+ (size_t) (info->read_end - info->buffer); /* Whenever a function which operates on IO_CACHE flushes/writes @@ -502,20 +503,20 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) } } - diff_length=(uint) (pos_in_file & (IO_SIZE-1)); - if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length))) + diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); + if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length))) { /* Fill first intern buffer */ - uint read_length; + size_t read_length; if (info->end_of_file <= pos_in_file) { /* End of file */ - info->error=(int) left_length; + info->error= (int) left_length; DBUG_RETURN(1); } - length=(Count & (uint) ~(IO_SIZE-1))-diff_length; - if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) - != (uint) length) + length=(Count & (size_t) ~(IO_SIZE-1))-diff_length; + if ((read_length= my_read(info->file,Buffer, length, info->myflags)) + != length) { - info->error= (read_length == (uint) -1 ? -1 : + info->error= (read_length == (size_t) -1 ? -1 : (int) (read_length+left_length)); DBUG_RETURN(1); } @@ -526,10 +527,10 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) diff_length=0; } - max_length=info->read_length-diff_length; + max_length= info->read_length-diff_length; if (info->type != READ_FIFO && max_length > (info->end_of_file - pos_in_file)) - max_length = info->end_of_file - pos_in_file; + max_length= (size_t) (info->end_of_file - pos_in_file); if (!max_length) { if (Count) @@ -539,21 +540,21 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count) } length=0; /* Didn't read any chars */ } - else if ((length=my_read(info->file,info->buffer,(uint) max_length, - info->myflags)) < Count || - length == (uint) -1) + else if ((length= my_read(info->file,info->buffer, max_length, + info->myflags)) < Count || + length == (size_t) -1) { - if (length != (uint) -1) - memcpy(Buffer,info->buffer,(size_t) length); + if (length != (size_t) -1) + memcpy(Buffer, info->buffer, length); info->pos_in_file= pos_in_file; - info->error= length == (uint) -1 ? -1 : (int) (length+left_length); + info->error= length == (size_t) -1 ? -1 : (int) (length+left_length); info->read_pos=info->read_end=info->buffer; DBUG_RETURN(1); } info->read_pos=info->buffer+Count; info->read_end=info->buffer+length; info->pos_in_file=pos_in_file; - memcpy(Buffer,info->buffer,(size_t) Count); + memcpy(Buffer, info->buffer, Count); DBUG_RETURN(0); } @@ -865,8 +866,9 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) /* Another thread did read the block already. */ } DBUG_PRINT("io_cache_share", ("reader awoke, going to process %u bytes", - cshare->read_end ? (uint) - (cshare->read_end - cshare->buffer) : 0)); + (uint) (cshare->read_end ? (size_t) + (cshare->read_end - cshare->buffer) : + 0))); /* Leave the lock. Do not call unlock_io_cache() later. The thread that @@ -958,33 +960,33 @@ static void unlock_io_cache(IO_CACHE *cache) 1 Error: can't read requested characters */ -int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count) +int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count) { my_off_t pos_in_file; - uint length, diff_length, left_length; + size_t length, diff_length, left_length; IO_CACHE_SHARE *cshare= cache->share; DBUG_ENTER("_my_b_read_r"); - if ((left_length= (uint) (cache->read_end - cache->read_pos))) + if ((left_length= (size_t) (cache->read_end - cache->read_pos))) { DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */ - memcpy(Buffer, cache->read_pos, (size_t) (left_length)); + memcpy(Buffer, cache->read_pos, left_length); Buffer+= left_length; Count-= left_length; } while (Count) { - int cnt, len; + size_t cnt, len; pos_in_file= cache->pos_in_file + (cache->read_end - cache->buffer); - diff_length= (uint) (pos_in_file & (IO_SIZE-1)); + diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); length=IO_ROUND_UP(Count+diff_length)-diff_length; length= ((length <= cache->read_length) ? length + IO_ROUND_DN(cache->read_length - length) : length - IO_ROUND_UP(length - cache->read_length)); if (cache->type != READ_FIFO && (length > (cache->end_of_file - pos_in_file))) - length= (uint) (cache->end_of_file - pos_in_file); + length= (size_t) (cache->end_of_file - pos_in_file); if (length == 0) { cache->error= (int) left_length; @@ -1019,12 +1021,12 @@ int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count) DBUG_RETURN(1); } } - len= (int) my_read(cache->file, cache->buffer, length, cache->myflags); + len= my_read(cache->file, cache->buffer, length, cache->myflags); } - DBUG_PRINT("io_cache_share", ("read %d bytes", len)); + DBUG_PRINT("io_cache_share", ("read %lu bytes", (ulong) len)); - cache->read_end= cache->buffer + (len == -1 ? 0 : len); - cache->error= (len == (int)length ? 0 : len); + cache->read_end= cache->buffer + (len == (size_t) -1 ? 0 : len); + cache->error= (len == length ? 0 : (int) len); cache->pos_in_file= pos_in_file; /* Copy important values to the share. */ @@ -1045,19 +1047,20 @@ int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count) cache->read_end= cshare->read_end; cache->pos_in_file= cshare->pos_in_file; - len= (int) ((cache->error == -1) ? -1 : cache->read_end - cache->buffer); + len= ((cache->error == -1) ? (size_t) -1 : + (size_t) (cache->read_end - cache->buffer)); } cache->read_pos= cache->buffer; cache->seek_not_done= 0; - if (len <= 0) + if (len == 0 || len == (size_t) -1) { - DBUG_PRINT("io_cache_share", ("reader error. len %d left %u", - len, left_length)); + DBUG_PRINT("io_cache_share", ("reader error. len %lu left %lu", + (ulong) len, (ulong) left_length)); cache->error= (int) left_length; DBUG_RETURN(1); } - cnt= ((uint) len > Count) ? (int) Count : len; - memcpy(Buffer, cache->read_pos, (size_t) cnt); + cnt= (len > Count) ? Count : len; + memcpy(Buffer, cache->read_pos, cnt); Count -= cnt; Buffer+= cnt; left_length+= cnt; @@ -1085,7 +1088,7 @@ int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count) */ static void copy_to_read_buffer(IO_CACHE *write_cache, - const byte *write_buffer, uint write_length) + const uchar *write_buffer, size_t write_length) { IO_CACHE_SHARE *cshare= write_cache->share; @@ -1096,7 +1099,7 @@ static void copy_to_read_buffer(IO_CACHE *write_cache, */ while (write_length) { - uint copy_length= min(write_length, write_cache->buffer_length); + size_t copy_length= min(write_length, write_cache->buffer_length); int __attribute__((unused)) rc; rc= lock_io_cache(write_cache, write_cache->pos_in_file); @@ -1132,33 +1135,32 @@ static void copy_to_read_buffer(IO_CACHE *write_cache, 1 Failed to read */ -int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) +int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count) { - uint length,diff_length,left_length,save_count; - my_off_t max_length, pos_in_file; + size_t length, diff_length, left_length, save_count, max_length; + my_off_t pos_in_file; save_count=Count; /* first, read the regular buffer */ - if ((left_length=(uint) (info->read_end-info->read_pos))) + if ((left_length=(size_t) (info->read_end-info->read_pos))) { DBUG_ASSERT(Count > left_length); /* User is not using my_b_read() */ - memcpy(Buffer,info->read_pos, (size_t) (left_length)); + memcpy(Buffer,info->read_pos, left_length); Buffer+=left_length; Count-=left_length; } lock_append_buffer(info); /* pos_in_file always point on where info->buffer was read */ - if ((pos_in_file=info->pos_in_file+(uint) (info->read_end - info->buffer)) >= - info->end_of_file) + if ((pos_in_file=info->pos_in_file + + (size_t) (info->read_end - info->buffer)) >= info->end_of_file) goto read_append_buffer; /* With read-append cache we must always do a seek before we read, because the write could have moved the file pointer astray */ - if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) - == MY_FILEPOS_ERROR) + if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) == MY_FILEPOS_ERROR) { info->error= -1; unlock_append_buffer(info); @@ -1166,16 +1168,17 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) } info->seek_not_done=0; - diff_length=(uint) (pos_in_file & (IO_SIZE-1)); + diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); /* now the second stage begins - read from file descriptor */ - if (Count >= (uint) (IO_SIZE+(IO_SIZE-diff_length))) - { /* Fill first intern buffer */ - uint read_length; + if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length))) + { + /* Fill first intern buffer */ + size_t read_length; - length=(Count & (uint) ~(IO_SIZE-1))-diff_length; - if ((read_length=my_read(info->file,Buffer,(uint) length,info->myflags)) == - (uint)-1) + length=(Count & (size_t) ~(IO_SIZE-1))-diff_length; + if ((read_length= my_read(info->file,Buffer, length, + info->myflags)) == (size_t) -1) { info->error= -1; unlock_append_buffer(info); @@ -1185,7 +1188,7 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) Buffer+=read_length; pos_in_file+=read_length; - if (read_length != (uint) length) + if (read_length != length) { /* We only got part of data; Read the rest of the data from the @@ -1197,9 +1200,9 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) diff_length=0; } - max_length=info->read_length-diff_length; + max_length= info->read_length-diff_length; if (max_length > (info->end_of_file - pos_in_file)) - max_length = info->end_of_file - pos_in_file; + max_length= (size_t) (info->end_of_file - pos_in_file); if (!max_length) { if (Count) @@ -1208,9 +1211,8 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) } else { - length=my_read(info->file,info->buffer,(uint) max_length, - info->myflags); - if (length == (uint) -1) + length= my_read(info->file,info->buffer, max_length, info->myflags); + if (length == (size_t) -1) { info->error= -1; unlock_append_buffer(info); @@ -1218,7 +1220,7 @@ int _my_b_seq_read(register IO_CACHE *info, byte *Buffer, uint Count) } if (length < Count) { - memcpy(Buffer,info->buffer,(size_t) length); + memcpy(Buffer, info->buffer, length); Count -= length; Buffer += length; @@ -1247,9 +1249,9 @@ read_append_buffer: { /* First copy the data to Count */ - uint len_in_buff = (uint) (info->write_pos - info->append_read_pos); - uint copy_len; - uint transfer_len; + size_t len_in_buff = (size_t) (info->write_pos - info->append_read_pos); + size_t copy_len; + size_t transfer_len; DBUG_ASSERT(info->append_read_pos <= info->write_pos); /* @@ -1294,15 +1296,16 @@ read_append_buffer: 0 Success 1 An error has occurred; IO_CACHE to error state. */ -int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) + +int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count) { - uint length,read_length,diff_length,left_length,use_length,org_Count; - my_off_t max_length; + size_t length,read_length,diff_length,left_length,use_length,org_Count; + size_t max_length; my_off_t next_pos_in_file; - byte *read_buffer; + uchar *read_buffer; memcpy(Buffer,info->read_pos, - (size_t) (left_length=(uint) (info->read_end-info->read_pos))); + (left_length= (size_t) (info->read_end-info->read_pos))); Buffer+=left_length; org_Count=Count; Count-=left_length; @@ -1321,15 +1324,15 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) info->error= -1; return(1); } - if (! (read_length = (uint) info->aio_result.result.aio_return) || - read_length == (uint) -1) + if (! (read_length= (size_t) info->aio_result.result.aio_return) || + read_length == (size_t) -1) { my_errno=0; /* For testing */ - info->error= (read_length == (uint) -1 ? -1 : + info->error= (read_length == (size_t) -1 ? -1 : (int) (read_length+left_length)); return(1); } - info->pos_in_file+=(uint) (info->read_end - info->request_pos); + info->pos_in_file+= (size_t) (info->read_end - info->request_pos); if (info->request_pos != info->buffer) info->request_pos=info->buffer; @@ -1360,7 +1363,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) if (info->aio_read_pos > info->pos_in_file) { my_errno=EINVAL; - return(info->read_length= -1); + return(info->read_length= (size_t) -1); } #endif /* Copy found bytes to buffer */ @@ -1373,7 +1376,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) info->read_pos+=length; } else - next_pos_in_file=(info->pos_in_file+ (uint) + next_pos_in_file=(info->pos_in_file+ (size_t) (info->read_end - info->request_pos)); /* If reading large blocks, or first read or read with skip */ @@ -1392,11 +1395,11 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) return (1); } - read_length=IO_SIZE*2- (uint) (next_pos_in_file & (IO_SIZE-1)); + read_length=IO_SIZE*2- (size_t) (next_pos_in_file & (IO_SIZE-1)); if (Count < read_length) { /* Small block, read to cache */ if ((read_length=my_read(info->file,info->request_pos, - read_length, info->myflags)) == (uint) -1) + read_length, info->myflags)) == (size_t) -1) return info->error= -1; use_length=min(Count,read_length); memcpy(Buffer,info->request_pos,(size_t) use_length); @@ -1416,10 +1419,10 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) } else { /* Big block, don't cache it */ - if ((read_length=my_read(info->file,Buffer,(uint) Count,info->myflags)) + if ((read_length= my_read(info->file,Buffer, Count,info->myflags)) != Count) { - info->error= read_length == (uint) -1 ? -1 : read_length+left_length; + info->error= read_length == (size_t) -1 ? -1 : read_length+left_length; return 1; } info->read_pos=info->read_end=info->request_pos; @@ -1427,12 +1430,12 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) } } - /* Read next block with asyncronic io */ - max_length=info->end_of_file - next_pos_in_file; + /* Read next block with asyncronic io */ diff_length=(next_pos_in_file & (IO_SIZE-1)); + max_length= info->read_length - diff_length; + if (max_length > info->end_of_file - next_pos_in_file) + max_length= (size_t) (info->end_of_file - next_pos_in_file); - if (max_length > (my_off_t) info->read_length - diff_length) - max_length= (my_off_t) info->read_length - diff_length; if (info->request_pos != info->buffer) read_buffer=info->buffer; else @@ -1441,9 +1444,9 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) if (max_length) { info->aio_result.result.aio_errno=AIO_INPROGRESS; /* Marker for test */ - DBUG_PRINT("aioread",("filepos: %ld length: %ld", - (ulong) next_pos_in_file,(ulong) max_length)); - if (aioread(info->file,read_buffer,(int) max_length, + DBUG_PRINT("aioread",("filepos: %ld length: %lu", + (ulong) next_pos_in_file, (ulong) max_length)); + if (aioread(info->file,read_buffer, max_length, (my_off_t) next_pos_in_file,MY_SEEK_SET, &info->aio_result.result)) { /* Skip async io */ @@ -1453,7 +1456,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) if (info->request_pos != info->buffer) { bmove(info->buffer,info->request_pos, - (uint) (info->read_end - info->read_pos)); + (size_t) (info->read_end - info->read_pos)); info->request_pos=info->buffer; info->read_pos-=info->read_length; info->read_end-=info->read_length; @@ -1473,7 +1476,7 @@ int _my_b_async_read(register IO_CACHE *info, byte *Buffer, uint Count) int _my_b_get(IO_CACHE *info) { - byte buff; + uchar buff; IO_CACHE_CALLBACK pre_read,post_read; if ((pre_read = info->pre_read)) (*pre_read)(info); @@ -1494,9 +1497,9 @@ int _my_b_get(IO_CACHE *info) -1 On error; my_errno contains error code. */ -int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) +int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count) { - uint rest_length,length; + size_t rest_length,length; if (info->pos_in_file+info->buffer_length > info->end_of_file) { @@ -1504,7 +1507,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) return info->error = -1; } - rest_length=(uint) (info->write_end - info->write_pos); + rest_length= (size_t) (info->write_end - info->write_pos); memcpy(info->write_pos,Buffer,(size_t) rest_length); Buffer+=rest_length; Count-=rest_length; @@ -1514,7 +1517,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) return 1; if (Count >= IO_SIZE) { /* Fill first intern buffer */ - length=Count & (uint) ~(IO_SIZE-1); + length=Count & (size_t) ~(IO_SIZE-1); if (info->seek_not_done) { /* @@ -1530,7 +1533,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) } info->seek_not_done=0; } - if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP)) + if (my_write(info->file, Buffer, length, info->myflags | MY_NABP)) return info->error= -1; #ifdef THREAD @@ -1565,9 +1568,9 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count) the write buffer before we are ready with it. */ -int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count) +int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count) { - uint rest_length,length; + size_t rest_length,length; #ifdef THREAD /* @@ -1578,10 +1581,10 @@ int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count) #endif lock_append_buffer(info); - rest_length=(uint) (info->write_end - info->write_pos); + rest_length= (size_t) (info->write_end - info->write_pos); if (Count <= rest_length) goto end; - memcpy(info->write_pos,Buffer,(size_t) rest_length); + memcpy(info->write_pos, Buffer, rest_length); Buffer+=rest_length; Count-=rest_length; info->write_pos+=rest_length; @@ -1592,8 +1595,8 @@ int my_b_append(register IO_CACHE *info, const byte *Buffer, uint Count) } if (Count >= IO_SIZE) { /* Fill first intern buffer */ - length=Count & (uint) ~(IO_SIZE-1); - if (my_write(info->file,Buffer,(uint) length,info->myflags | MY_NABP)) + length=Count & (size_t) ~(IO_SIZE-1); + if (my_write(info->file,Buffer, length, info->myflags | MY_NABP)) { unlock_append_buffer(info); return info->error= -1; @@ -1611,7 +1614,7 @@ end: } -int my_b_safe_write(IO_CACHE *info, const byte *Buffer, uint Count) +int my_b_safe_write(IO_CACHE *info, const uchar *Buffer, size_t Count) { /* Sasha: We are not writing this with the ? operator to avoid hitting @@ -1631,10 +1634,10 @@ int my_b_safe_write(IO_CACHE *info, const byte *Buffer, uint Count) we will never get a seek over the end of the buffer */ -int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, +int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count, my_off_t pos) { - uint length; + size_t length; int error=0; #ifdef THREAD @@ -1654,7 +1657,7 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, /* Write the part of the block that is before buffer */ length= (uint) (info->pos_in_file - pos); if (my_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP)) - info->error=error=-1; + info->error= error= -1; Buffer+=length; pos+= length; Count-= length; @@ -1664,10 +1667,10 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, } /* Check if we want to write inside the used part of the buffer.*/ - length= (uint) (info->write_end - info->buffer); + length= (size_t) (info->write_end - info->buffer); if (pos < info->pos_in_file + length) { - uint offset= (uint) (pos - info->pos_in_file); + size_t offset= (size_t) (pos - info->pos_in_file); length-=offset; if (length > Count) length=Count; @@ -1700,15 +1703,19 @@ int my_block_write(register IO_CACHE *info, const byte *Buffer, uint Count, #endif -int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) +int my_b_flush_io_cache(IO_CACHE *info, + int need_append_buffer_lock __attribute__((unused))) { - uint length; - my_bool append_cache; + size_t length; my_off_t pos_in_file; + my_bool append_cache= (info->type == SEQ_READ_APPEND); DBUG_ENTER("my_b_flush_io_cache"); + DBUG_PRINT("enter", ("cache: 0x%lx", (long) info)); - if (!(append_cache = (info->type == SEQ_READ_APPEND))) - need_append_buffer_lock=0; +#ifdef THREAD + if (!append_cache) + need_append_buffer_lock= 0; +#endif if (info->type == WRITE_CACHE || append_cache) { @@ -1719,7 +1726,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) } LOCK_APPEND_BUFFER; - if ((length=(uint) (info->write_pos - info->write_buffer))) + if ((length=(size_t) (info->write_pos - info->write_buffer))) { #ifdef THREAD /* @@ -1827,8 +1834,8 @@ int end_io_cache(IO_CACHE *info) info->alloced_buffer=0; if (info->file != -1) /* File doesn't exist */ error= my_b_flush_io_cache(info,1); - my_free((gptr) info->buffer,MYF(MY_WME)); - info->buffer=info->read_pos=(byte*) 0; + my_free((uchar*) info->buffer,MYF(MY_WME)); + info->buffer=info->read_pos=(uchar*) 0; } if (info->type == SEQ_READ_APPEND) { diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 790fd9974c4..828145b7931 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000-2004, 2006 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* More functions to be used with IO_CACHE files @@ -24,6 +26,51 @@ #include <stdarg.h> #include <m_ctype.h> +/* + Copy contents of an IO_CACHE to a file. + + SYNOPSIS + my_b_copy_to_file() + cache IO_CACHE to copy from + file File to copy to + + DESCRIPTION + Copy the contents of the cache to the file. The cache will be + re-inited to a read cache and will read from the beginning of the + cache. + + If a failure to write fully occurs, the cache is only copied + partially. + + TODO + Make this function solid by handling partial reads from the cache + in a correct manner: it should be atomic. + + RETURN VALUE + 0 All OK + 1 An error occured +*/ +int +my_b_copy_to_file(IO_CACHE *cache, FILE *file) +{ + size_t bytes_in_cache; + DBUG_ENTER("my_b_copy_to_file"); + + /* Reinit the cache to read from the beginning of the cache */ + if (reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE)) + DBUG_RETURN(1); + bytes_in_cache= my_b_bytes_in_cache(cache); + do + { + if (my_fwrite(file, cache->read_pos, bytes_in_cache, + MYF(MY_WME | MY_NABP)) == (size_t) -1) + DBUG_RETURN(1); + cache->read_pos= cache->read_end; + } while ((bytes_in_cache= my_b_fill(cache))); + DBUG_RETURN(0); +} + + my_off_t my_b_append_tell(IO_CACHE* info) { /* @@ -131,18 +178,24 @@ void my_b_seek(IO_CACHE *info,my_off_t pos) /* - Fill buffer. Note that this assumes that you have already used - all characters in the CACHE, independent of the read_pos value! - return: 0 on error or EOF (info->error = -1 on error) - number of characters + Fill buffer of the cache. + + NOTES + This assumes that you have already used all characters in the CACHE, + independent of the read_pos value! + + RETURN + 0 On error or EOF (info->error = -1 on error) + # Number of characters */ -uint my_b_fill(IO_CACHE *info) + +size_t my_b_fill(IO_CACHE *info) { my_off_t pos_in_file=(info->pos_in_file+ - (uint) (info->read_end - info->buffer)); - my_off_t max_length; - uint diff_length,length; + (size_t) (info->read_end - info->buffer)); + size_t diff_length, length, max_length; + if (info->seek_not_done) { /* File touched, do seek */ if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) == @@ -153,17 +206,18 @@ uint my_b_fill(IO_CACHE *info) } info->seek_not_done=0; } - diff_length=(uint) (pos_in_file & (IO_SIZE-1)); - max_length= (my_off_t) (info->end_of_file - pos_in_file); - if (max_length > (my_off_t) (info->read_length-diff_length)) - max_length=(my_off_t) (info->read_length-diff_length); + diff_length=(size_t) (pos_in_file & (IO_SIZE-1)); + max_length=(info->read_length-diff_length); + if (max_length >= (info->end_of_file - pos_in_file)) + max_length= (size_t) (info->end_of_file - pos_in_file); + if (!max_length) { info->error= 0; return 0; /* EOF */ } - else if ((length=my_read(info->file,info->buffer,(uint) max_length, - info->myflags)) == (uint) -1) + if ((length= my_read(info->file,info->buffer,max_length, + info->myflags)) == (size_t) -1) { info->error= -1; return 0; @@ -182,18 +236,20 @@ uint my_b_fill(IO_CACHE *info) If buffer is full then to[max_length-1] will be set to \0. */ -uint my_b_gets(IO_CACHE *info, char *to, uint max_length) +size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length) { char *start = to; - uint length; + size_t length; max_length--; /* Save place for end \0 */ + /* Calculate number of characters in buffer */ if (!(length= my_b_bytes_in_cache(info)) && !(length= my_b_fill(info))) return 0; + for (;;) { - char *pos,*end; + uchar *pos, *end; if (length > max_length) length=max_length; for (pos=info->read_pos,end=pos+length ; pos < end ;) @@ -202,7 +258,7 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length) { info->read_pos=pos; *to='\0'; - return (uint) (to-start); + return (size_t) (to-start); } } if (!(max_length-=length)) @@ -210,7 +266,7 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length) /* Found enough charcters; Return found string */ info->read_pos=pos; *to='\0'; - return (uint) (to-start); + return (size_t) (to-start); } if (!(length=my_b_fill(info))) return 0; @@ -221,26 +277,22 @@ uint my_b_gets(IO_CACHE *info, char *to, uint max_length) my_off_t my_b_filelength(IO_CACHE *info) { if (info->type == WRITE_CACHE) - { return my_b_tell(info); - } - else - { - info->seek_not_done=1; - return my_seek(info->file,0L,MY_SEEK_END,MYF(0)); - } + + info->seek_not_done= 1; + return my_seek(info->file, 0L, MY_SEEK_END, MYF(0)); } /* Simple printf version. Supports '%s', '%d', '%u', "%ld" and "%lu" Used for logging in MySQL - returns number of written character, or (uint) -1 on error + returns number of written character, or (size_t) -1 on error */ -uint my_b_printf(IO_CACHE *info, const char* fmt, ...) +size_t my_b_printf(IO_CACHE *info, const char* fmt, ...) { - int result; + size_t result; va_list args; va_start(args,fmt); result=my_b_vprintf(info, fmt, args); @@ -249,12 +301,13 @@ uint my_b_printf(IO_CACHE *info, const char* fmt, ...) } -uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) +size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) { - uint out_length=0; + size_t out_length= 0; uint minimum_width; /* as yet unimplemented */ uint minimum_width_sign; uint precision; /* as yet unimplemented for anything but %b */ + my_bool is_zero_padded; /* Store the location of the beginning of a format directive, for the @@ -268,19 +321,17 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) { /* Copy everything until '%' or end of string */ const char *start=fmt; - uint length; + size_t length; for (; (*fmt != '\0') && (*fmt != '%'); fmt++) ; - length= (uint) (fmt - start); + length= (size_t) (fmt - start); out_length+=length; - if (my_b_write(info, start, length)) + if (my_b_write(info, (const uchar*) start, length)) goto err; if (*fmt == '\0') /* End of format */ - { return out_length; - } /* By this point, *fmt must be a percent; Keep track of this location and @@ -290,15 +341,34 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) backtrack= fmt; fmt++; + is_zero_padded= FALSE; + minimum_width_sign= 1; minimum_width= 0; precision= 0; - minimum_width_sign= 1; /* Skip if max size is used (to be compatible with printf) */ - while (*fmt == '-') { fmt++; minimum_width_sign= -1; } - if (*fmt == '*') { + +process_flags: + switch (*fmt) + { + case '-': + minimum_width_sign= -1; fmt++; goto process_flags; + case '0': + is_zero_padded= TRUE; fmt++; goto process_flags; + case '#': + /** @todo Implement "#" conversion flag. */ fmt++; goto process_flags; + case ' ': + /** @todo Implement " " conversion flag. */ fmt++; goto process_flags; + case '+': + /** @todo Implement "+" conversion flag. */ fmt++; goto process_flags; + } + + if (*fmt == '*') + { precision= (int) va_arg(args, int); fmt++; - } else { + } + else + { while (my_isdigit(&my_charset_latin1, *fmt)) { minimum_width=(minimum_width * 10) + (*fmt - '0'); fmt++; @@ -306,12 +376,15 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) } minimum_width*= minimum_width_sign; - if (*fmt == '.') { + if (*fmt == '.') + { fmt++; if (*fmt == '*') { precision= (int) va_arg(args, int); fmt++; - } else { + } + else + { while (my_isdigit(&my_charset_latin1, *fmt)) { precision=(precision * 10) + (*fmt - '0'); fmt++; @@ -322,60 +395,75 @@ uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) if (*fmt == 's') /* String parameter */ { reg2 char *par = va_arg(args, char *); - uint length2 = (uint) strlen(par); - /* TODO: implement minimum width and precision */ + size_t length2 = strlen(par); + /* TODO: implement precision */ out_length+= length2; - if (my_b_write(info, par, length2)) + if (my_b_write(info, (uchar*) par, length2)) goto err; } else if (*fmt == 'b') /* Sized buffer parameter, only precision makes sense */ { char *par = va_arg(args, char *); out_length+= precision; - if (my_b_write(info, par, precision)) + if (my_b_write(info, (uchar*) par, precision)) goto err; } else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ { register int iarg; - uint length2; + size_t length2; char buff[17]; iarg = va_arg(args, int); if (*fmt == 'd') - length2= (uint) (int10_to_str((long) iarg,buff, -10) - buff); + length2= (size_t) (int10_to_str((long) iarg,buff, -10) - buff); else - length2= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff); + length2= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff); + + /* minimum width padding */ + if (minimum_width > length2) + { + char *buffz; + + buffz= my_alloca(minimum_width - length2); + if (is_zero_padded) + memset(buffz, '0', minimum_width - length2); + else + memset(buffz, ' ', minimum_width - length2); + my_b_write(info, buffz, minimum_width - length2); + my_afree(buffz); + } + out_length+= length2; - if (my_b_write(info, buff, length2)) + if (my_b_write(info, (uchar*) buff, length2)) goto err; } else if ((*fmt == 'l' && fmt[1] == 'd') || fmt[1] == 'u') /* long parameter */ { register long iarg; - uint length2; + size_t length2; char buff[17]; iarg = va_arg(args, long); if (*++fmt == 'd') - length2= (uint) (int10_to_str(iarg,buff, -10) - buff); + length2= (size_t) (int10_to_str(iarg,buff, -10) - buff); else - length2= (uint) (int10_to_str(iarg,buff,10)- buff); + length2= (size_t) (int10_to_str(iarg,buff,10)- buff); out_length+= length2; - if (my_b_write(info, buff, length2)) + if (my_b_write(info, (uchar*) buff, length2)) goto err; } else { /* %% or unknown code */ - if (my_b_write(info, backtrack, (uint) (fmt - backtrack))) + if (my_b_write(info, (uchar*) backtrack, (size_t) (fmt-backtrack))) goto err; - out_length+= (uint) (fmt - backtrack); + out_length+= fmt-backtrack; } } return out_length; err: - return (uint) -1; + return (size_t) -1; } diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index e3f2295fc78..6c6723ba197 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /** @file @@ -110,6 +111,7 @@ #include <keycache.h> #include "my_static.h" #include <m_string.h> +#include <my_bit.h> #include <errno.h> #include <stdarg.h> @@ -151,14 +153,6 @@ #define KEYCACHE_DEBUG_LOG "my_key_cache_debug.log" */ -#if defined(MSDOS) && !defined(M_IC80386) -/* we nead much memory */ -#undef my_malloc_lock -#undef my_free_lock -#define my_malloc_lock(A,B) halloc((long) (A/IO_SIZE),IO_SIZE) -#define my_free_lock(A,B) hfree(A) -#endif /* defined(MSDOS) && !defined(M_IC80386) */ - #define STRUCT_PTR(TYPE, MEMBER, a) \ (TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER)) @@ -216,7 +210,7 @@ struct st_block_link struct st_hash_link *hash_link; /* backward ptr to referring hash_link */ KEYCACHE_WQUEUE wqueue[2]; /* queues on waiting requests for new/old pages */ uint requests; /* number of requests for the block */ - byte *buffer; /* buffer for the block page */ + uchar *buffer; /* buffer for the block page */ uint offset; /* beginning of modified data in the buffer */ uint length; /* end of data in the buffer */ uint status; /* state of the block */ @@ -347,15 +341,9 @@ static int fail_hlink(HASH_LINK *hlink); static int cache_empty(KEY_CACHE *keycache); #endif -static uint next_power(uint value) +static inline uint next_power(uint value) { - uint old_value= 1; - while (value) - { - old_value= value; - value&= value-1; - } - return (old_value << 1); + return (uint) my_round_up_to_next_power((uint32) value) << 1; } @@ -477,11 +465,11 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root + ALIGN_SIZE((sizeof(HASH_LINK*) * keycache->hash_entries))); - bzero((byte*) keycache->block_root, + bzero((uchar*) keycache->block_root, keycache->disk_blocks * sizeof(BLOCK_LINK)); - bzero((byte*) keycache->hash_root, + bzero((uchar*) keycache->hash_root, keycache->hash_entries * sizeof(HASH_LINK*)); - bzero((byte*) keycache->hash_link_root, + bzero((uchar*) keycache->hash_link_root, keycache->hash_links * sizeof(HASH_LINK)); keycache->hash_links_used= 0; keycache->free_hash_list= NULL; @@ -513,9 +501,9 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, keycache->disk_blocks, (long) keycache->block_root, keycache->hash_entries, (long) keycache->hash_root, keycache->hash_links, (long) keycache->hash_link_root)); - bzero((gptr) keycache->changed_blocks, + bzero((uchar*) keycache->changed_blocks, sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH); - bzero((gptr) keycache->file_blocks, + bzero((uchar*) keycache->file_blocks, sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH); } else @@ -533,12 +521,12 @@ err: keycache->blocks= 0; if (keycache->block_mem) { - my_large_free((gptr) keycache->block_mem, MYF(0)); + my_large_free((uchar*) keycache->block_mem, MYF(0)); keycache->block_mem= NULL; } if (keycache->block_root) { - my_free((gptr) keycache->block_root, MYF(0)); + my_free((uchar*) keycache->block_root, MYF(0)); keycache->block_root= NULL; } my_errno= error; @@ -759,9 +747,9 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) { if (keycache->block_mem) { - my_large_free((gptr) keycache->block_mem, MYF(0)); + my_large_free((uchar*) keycache->block_mem, MYF(0)); keycache->block_mem= NULL; - my_free((gptr) keycache->block_root, MYF(0)); + my_free((uchar*) keycache->block_root, MYF(0)); keycache->block_root= NULL; } keycache->disk_blocks= -1; @@ -2084,7 +2072,7 @@ restart: ((size_t) keycache->blocks_used) * keycache->key_cache_block_size; block->buffer= ADD_TO_PTR(keycache->block_mem, block_mem_offset, - byte*); + uchar*); keycache->blocks_used++; DBUG_ASSERT(!block->next_used); } @@ -2437,7 +2425,7 @@ static void read_block(KEY_CACHE *keycache, BLOCK_LINK *block, uint read_length, uint min_length, my_bool primary) { - uint got_length; + size_t got_length; /* On entry cache_lock is locked */ @@ -2548,15 +2536,15 @@ static void read_block(KEY_CACHE *keycache, have to be a multiple of key_cache_block_size; */ -byte *key_cache_read(KEY_CACHE *keycache, - File file, my_off_t filepos, int level, - byte *buff, uint length, - uint block_length __attribute__((unused)), - int return_buffer __attribute__((unused))) +uchar *key_cache_read(KEY_CACHE *keycache, + File file, my_off_t filepos, int level, + uchar *buff, uint length, + uint block_length __attribute__((unused)), + int return_buffer __attribute__((unused))) { my_bool locked_and_incremented= FALSE; int error=0; - byte *start= buff; + uchar *start= buff; DBUG_ENTER("key_cache_read"); DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u", (uint) file, (ulong) filepos, length)); @@ -2630,7 +2618,7 @@ byte *key_cache_read(KEY_CACHE *keycache, */ keycache->global_cache_read++; keycache_pthread_mutex_unlock(&keycache->cache_lock); - error= (my_pread(file, (byte*) buff, read_length, + error= (my_pread(file, (uchar*) buff, read_length, filepos + offset, MYF(MY_NABP)) != 0); keycache_pthread_mutex_lock(&keycache->cache_lock); goto next_block; @@ -2735,7 +2723,7 @@ no_key_cache: if (locked_and_incremented) keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pread(file, (byte*) buff, length, filepos, MYF(MY_NABP))) + if (my_pread(file, (uchar*) buff, length, filepos, MYF(MY_NABP))) error= 1; if (locked_and_incremented) keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -2747,7 +2735,7 @@ end: keycache_pthread_mutex_unlock(&keycache->cache_lock); } DBUG_PRINT("exit", ("error: %d", error )); - DBUG_RETURN(error ? (byte*) 0 : start); + DBUG_RETURN(error ? (uchar*) 0 : start); } @@ -2773,7 +2761,7 @@ end: int key_cache_insert(KEY_CACHE *keycache, File file, my_off_t filepos, int level, - byte *buff, uint length) + uchar *buff, uint length) { int error= 0; DBUG_ENTER("key_cache_insert"); @@ -3023,7 +3011,7 @@ int key_cache_insert(KEY_CACHE *keycache, int key_cache_write(KEY_CACHE *keycache, File file, my_off_t filepos, int level, - byte *buff, uint length, + uchar *buff, uint length, uint block_length __attribute__((unused)), int dont_write) { @@ -3118,7 +3106,7 @@ int key_cache_write(KEY_CACHE *keycache, /* Used in the server. */ keycache->global_cache_write++; keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pwrite(file, (byte*) buff, read_length, filepos + offset, + if (my_pwrite(file, (uchar*) buff, read_length, filepos + offset, MYF(MY_NABP | MY_WAIT_IF_FULL))) error=1; keycache_pthread_mutex_lock(&keycache->cache_lock); @@ -3296,7 +3284,7 @@ no_key_cache: keycache->global_cache_write++; if (locked_and_incremented) keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pwrite(file, (byte*) buff, length, filepos, + if (my_pwrite(file, (uchar*) buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL))) error=1; if (locked_and_incremented) @@ -3499,7 +3487,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache, As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH we are guarunteed no thread will change them */ - my_qsort((byte*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); + my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); keycache_pthread_mutex_lock(&keycache->cache_lock); /* @@ -3931,11 +3919,11 @@ restart: if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | BLOCK_REASSIGNED))) { - struct st_hash_link *next_hash_link; - my_off_t next_diskpos; - File next_file; - uint next_status; - uint hash_requests; + struct st_hash_link *UNINIT_VAR(next_hash_link); + my_off_t UNINIT_VAR(next_diskpos); + File UNINIT_VAR(next_file); + uint UNINIT_VAR(next_status); + uint UNINIT_VAR(hash_requests); total_found++; found++; @@ -4039,7 +4027,7 @@ restart: #endif err: if (cache != cache_buff) - my_free((gptr) cache, MYF(0)); + my_free((uchar*) cache, MYF(0)); if (last_errno) errno=last_errno; /* Return first error */ DBUG_RETURN(last_errno != 0); diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c index 51ad54159e5..6227a05ce06 100644 --- a/mysys/mf_keycaches.c +++ b/mysys/mf_keycaches.c @@ -44,9 +44,9 @@ typedef struct st_safe_hash_entry { - byte *key; + uchar *key; uint length; - byte *data; + uchar *data; struct st_safe_hash_entry *next, **prev; } SAFE_HASH_ENTRY; @@ -57,7 +57,7 @@ typedef struct st_safe_hash_with_default rw_lock_t mutex; #endif HASH hash; - byte *default_value; + uchar *default_value; SAFE_HASH_ENTRY *root; } SAFE_HASH; @@ -71,18 +71,18 @@ typedef struct st_safe_hash_with_default static void safe_hash_entry_free(SAFE_HASH_ENTRY *entry) { DBUG_ENTER("free_assign_entry"); - my_free((gptr) entry, MYF(0)); + my_free((uchar*) entry, MYF(0)); DBUG_VOID_RETURN; } /* Get key and length for a SAFE_HASH_ENTRY */ -static byte *safe_hash_entry_get(SAFE_HASH_ENTRY *entry, uint *length, - my_bool not_used __attribute__((unused))) +static uchar *safe_hash_entry_get(SAFE_HASH_ENTRY *entry, size_t *length, + my_bool not_used __attribute__((unused))) { *length=entry->length; - return (byte*) entry->key; + return (uchar*) entry->key; } @@ -105,7 +105,7 @@ static byte *safe_hash_entry_get(SAFE_HASH_ENTRY *entry, uint *length, */ static my_bool safe_hash_init(SAFE_HASH *hash, uint elements, - byte *default_value) + uchar *default_value) { DBUG_ENTER("safe_hash"); if (hash_init(&hash->hash, &my_charset_bin, elements, @@ -147,9 +147,9 @@ static void safe_hash_free(SAFE_HASH *hash) Return the value stored for a key or default value if no key */ -static byte *safe_hash_search(SAFE_HASH *hash, const byte *key, uint length) +static uchar *safe_hash_search(SAFE_HASH *hash, const uchar *key, uint length) { - byte *result; + uchar *result; DBUG_ENTER("safe_hash_search"); rw_rdlock(&hash->mutex); result= hash_search(&hash->hash, key, length); @@ -183,8 +183,8 @@ static byte *safe_hash_search(SAFE_HASH *hash, const byte *key, uint length) 1 error (Can only be EOM). In this case my_message() is called. */ -static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length, - byte *data) +static my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, + uchar *data) { SAFE_HASH_ENTRY *entry; my_bool error= 0; @@ -206,7 +206,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length, /* unlink entry from list */ if ((*entry->prev= entry->next)) entry->next->prev= entry->prev; - hash_delete(&hash->hash, (byte*) entry); + hash_delete(&hash->hash, (uchar*) entry); goto end; } if (entry) @@ -222,7 +222,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length, error= 1; goto end; } - entry->key= (byte*) (entry +1); + entry->key= (uchar*) (entry +1); memcpy((char*) entry->key, (char*) key, length); entry->length= length; entry->data= data; @@ -231,7 +231,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length, entry->next->prev= &entry->next; entry->prev= &hash->root; hash->root= entry; - if (my_hash_insert(&hash->hash, (byte*) entry)) + if (my_hash_insert(&hash->hash, (uchar*) entry)) { /* This can only happen if hash got out of memory */ my_free((char*) entry, MYF(0)); @@ -261,7 +261,7 @@ end: default value. */ -static void safe_hash_change(SAFE_HASH *hash, byte *old_data, byte *new_data) +static void safe_hash_change(SAFE_HASH *hash, uchar *old_data, uchar *new_data) { SAFE_HASH_ENTRY *entry, *next; DBUG_ENTER("safe_hash_set"); @@ -277,7 +277,7 @@ static void safe_hash_change(SAFE_HASH *hash, byte *old_data, byte *new_data) { if ((*entry->prev= entry->next)) entry->next->prev= entry->prev; - hash_delete(&hash->hash, (byte*) entry); + hash_delete(&hash->hash, (uchar*) entry); } else entry->data= new_data; @@ -299,7 +299,7 @@ static SAFE_HASH key_cache_hash; my_bool multi_keycache_init(void) { - return safe_hash_init(&key_cache_hash, 16, (byte*) dflt_key_cache); + return safe_hash_init(&key_cache_hash, 16, (uchar*) dflt_key_cache); } @@ -325,7 +325,7 @@ void multi_keycache_free(void) key cache to use */ -KEY_CACHE *multi_key_cache_search(byte *key, uint length) +KEY_CACHE *multi_key_cache_search(uchar *key, uint length) { if (!key_cache_hash.hash.records) return dflt_key_cache; @@ -349,15 +349,15 @@ KEY_CACHE *multi_key_cache_search(byte *key, uint length) */ -my_bool multi_key_cache_set(const byte *key, uint length, +my_bool multi_key_cache_set(const uchar *key, uint length, KEY_CACHE *key_cache) { - return safe_hash_set(&key_cache_hash, key, length, (byte*) key_cache); + return safe_hash_set(&key_cache_hash, key, length, (uchar*) key_cache); } void multi_key_cache_change(KEY_CACHE *old_data, KEY_CACHE *new_data) { - safe_hash_change(&key_cache_hash, (byte*) old_data, (byte*) new_data); + safe_hash_change(&key_cache_hash, (uchar*) old_data, (uchar*) new_data); } diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c index ffa83cb20ec..f6a7b3d86ba 100644 --- a/mysys/mf_loadpath.c +++ b/mysys/mf_loadpath.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include <m_string.h> @@ -23,7 +25,7 @@ /* if there is no path, prepend with own_path_prefix if given */ /* else unpack path according to current dir */ -my_string my_load_path(my_string to, const char *path, +char * my_load_path(char * to, const char *path, const char *own_path_prefix) { char buff[FN_REFLEN]; @@ -34,21 +36,22 @@ my_string my_load_path(my_string to, const char *path, if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) || test_if_hard_path(path)) - VOID(strmov(buff,path)); + VOID(strnmov(buff, path, FN_REFLEN)); else if ((is_cur=(path[0] == FN_CURLIB && path[1] == FN_LIBCHAR)) || - (is_prefix((gptr) path,FN_PARENTDIR)) || + (is_prefix(path,FN_PARENTDIR)) || ! own_path_prefix) { if (is_cur) is_cur=2; /* Remove current dir */ if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)+is_cur),MYF(0))) - VOID(strcat(buff,path+is_cur)); + VOID(strncat(buff, path+is_cur, FN_REFLEN-1)); else - VOID(strmov(buff,path)); /* Return org file name */ + VOID(strnmov(buff, path, FN_REFLEN)); /* Return org file name */ } else - VOID(strxmov(buff,own_path_prefix,path,NullS)); - strmov(to,buff); + VOID(strxnmov(buff, FN_REFLEN, own_path_prefix,path, NullS)); + strnmov(to, buff, FN_REFLEN); + to[FN_REFLEN-1]= '\0'; DBUG_PRINT("exit",("to: %s",to)); DBUG_RETURN(to); } /* my_load_path */ diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 4caa8e5ba0e..0f150fa063e 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -11,7 +11,7 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mysys_priv.h" #include <m_string.h> @@ -24,17 +24,17 @@ #include <descrip.h> #endif /* VMS */ -static my_string NEAR_F expand_tilde(my_string *path); +static char * NEAR_F expand_tilde(char * *path); /* Pack a dirname ; Changes HOME to ~/ and current dev to ./ */ /* from is a dirname (from dirname() ?) ending with FN_LIBCHAR */ /* to may be == from */ -void pack_dirname(my_string to, const char *from) +void pack_dirname(char * to, const char *from) { int cwd_err; - uint d_length,length,UNINIT_VAR(buff_length); - my_string start; + size_t d_length,length,UNINIT_VAR(buff_length); + char * start; char buff[FN_REFLEN]; DBUG_ENTER("pack_dirname"); @@ -49,13 +49,13 @@ void pack_dirname(my_string to, const char *from) if (!(cwd_err= my_getwd(buff,FN_REFLEN,MYF(0)))) { - buff_length= (uint) strlen(buff); - d_length=(uint) (start-to); + buff_length= strlen(buff); + d_length= (size_t) (start-to); if ((start == to || - (buff_length == d_length && !bcmp(buff,start,d_length))) && + (buff_length == d_length && !memcmp(buff,start,d_length))) && *start != FN_LIBCHAR && *start) { /* Put current dir before */ - bchange(to,d_length,buff,buff_length,(uint) strlen(to)+1); + bchange((uchar*) to, d_length, (uchar*) buff, buff_length, strlen(to)+1); } } @@ -64,13 +64,13 @@ void pack_dirname(my_string to, const char *from) length=0; if (home_dir) { - length= (uint) strlen(home_dir); + length= strlen(home_dir); if (home_dir[length-1] == FN_LIBCHAR) length--; /* Don't test last '/' */ } if (length > 1 && length < d_length) { /* test if /xx/yy -> ~/yy */ - if (bcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR) + if (memcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR) { to[0]=FN_HOMELIB; /* Filename begins with ~ */ (void) strmov_overlapp(to+1,to+length); @@ -80,7 +80,7 @@ void pack_dirname(my_string to, const char *from) { /* Test if cwd is ~/... */ if (length > 1 && length < buff_length) { - if (bcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR) + if (memcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR) { buff[0]=FN_HOMELIB; (void) strmov_overlapp(buff+1,buff+length); @@ -88,7 +88,7 @@ void pack_dirname(my_string to, const char *from) } if (is_prefix(to,buff)) { - length= (uint) strlen(buff); + length= strlen(buff); if (to[length]) (void) strmov_overlapp(to,to+length); /* Remove everything before */ else @@ -105,21 +105,32 @@ void pack_dirname(my_string to, const char *from) } /* pack_dirname */ - /* remove unwanted chars from dirname */ - /* if "/../" removes prev dir; "/~/" removes all before ~ */ - /* "//" is same as "/", except on Win32 at start of a file */ - /* "/./" is removed */ - /* Unpacks home_dir if "~/.." used */ - /* Unpacks current dir if if "./.." used */ +/* + remove unwanted chars from dirname + + SYNOPSIS + cleanup_dirname() + to Store result here + from Dirname to fix. May be same as to + + IMPLEMENTATION + "/../" removes prev dir + "/~/" removes all before ~ + //" is same as "/", except on Win32 at start of a file + "/./" is removed + Unpacks home_dir if "~/.." used + Unpacks current dir if if "./.." used -uint cleanup_dirname(register my_string to, const char *from) - /* to may be == from */ + RETURN + # length of new name +*/ +size_t cleanup_dirname(register char *to, const char *from) { - reg5 uint length; - reg2 my_string pos; - reg3 my_string from_ptr; - reg4 my_string start; + reg5 size_t length; + reg2 char * pos; + reg3 char * from_ptr; + reg4 char * start; char parent[5], /* for "FN_PARENTDIR" */ buff[FN_REFLEN+1],*end_parentdir; #ifdef BACKSLASH_MBTAIL @@ -129,17 +140,17 @@ uint cleanup_dirname(register my_string to, const char *from) DBUG_PRINT("enter",("from: '%s'",from)); start=buff; - from_ptr=(my_string) from; + from_ptr=(char *) from; #ifdef FN_DEVCHAR if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0) { /* Skip device part */ - length=(uint) (pos-from_ptr)+1; + length=(size_t) (pos-from_ptr)+1; start=strnmov(buff,from_ptr,length); from_ptr+=length; } #endif parent[0]=FN_LIBCHAR; - length=(uint) (strmov(parent+1,FN_PARENTDIR)-parent); + length=(size_t) (strmov(parent+1,FN_PARENTDIR)-parent); for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++) { #ifdef BACKSLASH_MBTAIL @@ -155,7 +166,7 @@ uint cleanup_dirname(register my_string to, const char *from) *pos = FN_LIBCHAR; if (*pos == FN_LIBCHAR) { - if ((uint) (pos-start) > length && bcmp(pos-length,parent,length) == 0) + if ((size_t) (pos-start) > length && memcmp(pos-length,parent,length) == 0) { /* If .../../; skip prev */ pos-=length; if (pos != start) @@ -186,7 +197,7 @@ uint cleanup_dirname(register my_string to, const char *from) end_parentdir=pos; while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */ pos--; - if (pos[1] == FN_HOMELIB || bcmp(pos,parent,length) == 0) + if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0) { /* Don't remove ~user/ */ pos=strmov(end_parentdir+1,parent); *pos=FN_LIBCHAR; @@ -194,8 +205,8 @@ uint cleanup_dirname(register my_string to, const char *from) } } } - else if ((uint) (pos-start) == length-1 && - !bcmp(start,parent+1,length-1)) + else if ((size_t) (pos-start) == length-1 && + !memcmp(start,parent+1,length-1)) start=pos; /* Starts with "../" */ else if (pos-start > 0 && pos[-1] == FN_LIBCHAR) { @@ -216,7 +227,7 @@ uint cleanup_dirname(register my_string to, const char *from) } (void) strmov(to,buff); DBUG_PRINT("exit",("to: '%s'",to)); - DBUG_RETURN((uint) (pos-buff)); + DBUG_RETURN((size_t) (pos-buff)); } /* cleanup_dirname */ @@ -239,7 +250,7 @@ void symdirget(char *dir) if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK)) { File file; - uint length; + size_t length; char temp= *(--pos); /* May be "/" or "\" */ strmov(pos,".sym"); file= my_open(dir, O_RDONLY, MYF(0)); @@ -256,7 +267,7 @@ void symdirget(char *dir) if (pos == buff || pos[-1] != FN_LIBCHAR) *pos++=FN_LIBCHAR; - strmake(dir,buff, (uint) (pos-buff)); + strmake(dir,buff, (size_t) (pos-buff)); } my_close(file, MYF(0)); } @@ -281,9 +292,9 @@ void symdirget(char *dir) the caller. */ -uint normalize_dirname(char *to, const char *from) +size_t normalize_dirname(char *to, const char *from) { - uint length; + size_t length; char buff[FN_REFLEN]; DBUG_ENTER("normalize_dirname"); @@ -293,7 +304,7 @@ uint normalize_dirname(char *to, const char *from) properly). */ (void) intern_filename(buff, from); - length= (uint) strlen(buff); /* Fix that '/' is last */ + length= strlen(buff); /* Fix that '/' is last */ if (length && #ifdef FN_DEVCHAR buff[length - 1] != FN_DEVCHAR && @@ -329,9 +340,9 @@ uint normalize_dirname(char *to, const char *from) Length of new directory name (= length of to) */ -uint unpack_dirname(my_string to, const char *from) +size_t unpack_dirname(char * to, const char *from) { - uint length,h_length; + size_t length, h_length; char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; DBUG_ENTER("unpack_dirname"); @@ -342,15 +353,15 @@ uint unpack_dirname(my_string to, const char *from) suffix=buff+1; tilde_expansion=expand_tilde(&suffix); if (tilde_expansion) { - length-=(uint) (suffix-buff)-1; - if (length+(h_length= (uint) strlen(tilde_expansion)) <= FN_REFLEN) + length-= (size_t) (suffix-buff)-1; + if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN) { if ((h_length > 0) && (tilde_expansion[h_length-1] == FN_LIBCHAR)) h_length--; if (buff+h_length < suffix) bmove(buff+h_length,suffix,length); else - bmove_upp(buff+h_length+length,suffix+length,length); + bmove_upp((uchar*) buff+h_length+length, (uchar*) suffix+length, length); bmove(buff,tilde_expansion,h_length); } } @@ -366,7 +377,7 @@ uint unpack_dirname(my_string to, const char *from) /* Expand tilde to home or user-directory */ /* Path is reset to point at FN_LIBCHAR after ~xxx */ -static my_string NEAR_F expand_tilde(my_string *path) +static char * NEAR_F expand_tilde(char * *path) { if (path[0][0] == FN_LIBCHAR) return home_dir; /* ~/ expanded to home */ @@ -388,7 +399,7 @@ static my_string NEAR_F expand_tilde(my_string *path) } } #endif - return (my_string) 0; + return (char *) 0; } @@ -409,13 +420,13 @@ static my_string NEAR_F expand_tilde(my_string *path) */ -uint unpack_filename(my_string to, const char *from) +size_t unpack_filename(char * to, const char *from) { - uint length,n_length; + size_t length, n_length, buff_length; char buff[FN_REFLEN]; DBUG_ENTER("unpack_filename"); - length=dirname_part(buff,from); /* copy & convert dirname */ + length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */ n_length=unpack_dirname(buff,buff); if (n_length+strlen(from+length) < FN_REFLEN) { @@ -432,10 +443,10 @@ uint unpack_filename(my_string to, const char *from) /* Used before system command's like open(), create() .. */ /* Returns used length of to; total length should be FN_REFLEN */ -uint system_filename(my_string to, const char *from) +size_t system_filename(char * to, const char *from) { #ifndef FN_C_BEFORE_DIR - return (uint) (strmake(to,from,FN_REFLEN-1)-to); + return (size_t) (strmake(to,from,FN_REFLEN-1)-to); #else /* VMS */ /* change 'dev:lib/xxx' to 'dev:[lib]xxx' */ @@ -445,8 +456,9 @@ uint system_filename(my_string to, const char *from) /* change '/x/y/z to '[x.y]x' */ /* change 'dev:/x' to 'dev:[000000]x' */ - int libchar_found,length; - my_string to_pos,from_pos,pos; + int libchar_found; + size_t length; + char * to_pos,from_pos,pos; char buff[FN_REFLEN]; DBUG_ENTER("system_filename"); @@ -456,7 +468,7 @@ uint system_filename(my_string to, const char *from) if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skip device part */ { pos++; - to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos)); + to_pos=strnmov(to,from_pos,(size_t) (pos-from_pos)); from_pos=pos; } else @@ -487,115 +499,30 @@ uint system_filename(my_string to, const char *from) from_pos+strlen(FN_PARENTDIR) == pos) to_pos=strmov(to_pos,FN_C_PARENT_DIR); /* Found '../' */ else - to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos)); + to_pos=strnmov(to_pos,from_pos,(size_t) (pos-from_pos)); from_pos=pos+1; } *(to_pos++)=FN_C_AFTER_DIR; } - length=(int) (strmov(to_pos,from_pos)-to); + length= (size_t) (strmov(to_pos,from_pos)-to); DBUG_PRINT("exit",("name: '%s'",to)); - DBUG_RETURN((uint) length); + DBUG_RETURN(length); #endif } /* system_filename */ /* Fix a filename to intern (UNIX format) */ -my_string intern_filename(my_string to, const char *from) +char *intern_filename(char *to, const char *from) { -#ifndef VMS - { - uint length; - char buff[FN_REFLEN]; - if (from == to) - { /* Dirname may destroy from */ - strmov(buff,from); - from=buff; - } - length=dirname_part(to,from); /* Copy dirname & fix chars */ - (void) strcat(to,from+length); - return (to); - } -#else /* VMS */ - - /* change 'dev:[lib]xxx' to 'dev:lib/xxx' */ - /* change 'dev:xxx' to 'dev:xxx' */ - /* change 'dev:x/y/[.lib]' to 'dev:x/y/lib/ */ - /* change '[.lib]' to './lib/' */ - /* change '[x.y]' or '[x.][y]' or '[x][.y]' to '/x/y/' */ - /* change '[000000.x] or [x.000000]' to '/x/' */ - - int par_length,root_length; - my_string pos,from_pos,to_pos,end_pos; + size_t length, to_length; char buff[FN_REFLEN]; - - convert_dirname(buff,from,NullS); /* change '<>' to '[]' */ - from_pos=buff; - if ((pos=strrchr(from_pos,FN_DEVCHAR))) /* Skip device part */ - { - pos++; - to_pos=strnmov(to,from_pos,(size_s) (pos-from_pos)); - from_pos=pos; + if (from == to) + { /* Dirname may destroy from */ + strmov(buff,from); + from=buff; } - else - to_pos=to; - - root_length=strlen(FN_C_ROOT_DIR); - if ((pos = strchr(from_pos,FN_C_BEFORE_DIR)) && - (end_pos = strrchr(pos+1,FN_C_AFTER_DIR))) - { - to_pos=strnmov(to_pos,from_pos,(size_s) (pos-from_pos)); - /* Copy all between ':' and '[' */ - from_pos=pos+1; - if (strinstr(from_pos,FN_C_ROOT_DIR) == 1 && - (from_pos[root_length] == FN_C_DIR_SEP || - from_pos[root_length] == FN_C_AFTER_DIR)) - { - from_pos+=root_length+1; - } - else if (*from_pos == FN_C_DIR_SEP) - *(to_pos++) = FN_CURLIB; /* Set ./ first */ - *(to_pos++) = FN_LIBCHAR; - - par_length=strlen(FN_C_PARENT_DIR); - pos=to_pos; - for (; from_pos <= end_pos ; from_pos++) - { - switch (*from_pos) { - case FN_C_DIR_SEP: - case FN_C_AFTER_DIR: - if (pos != to_pos) - { - if ((int) (to_pos-pos) == root_length && - is_suffix(pos,FN_C_ROOT_DIR)) - to_pos=pos; /* remove root-pos */ - else - { - *(to_pos++)=FN_LIBCHAR; /* Find lib */ - pos=to_pos; - } - } - break; - case FN_C_BEFORE_DIR: - break; - case '-': /* *(FN_C_PARENT_DIR): */ - if (to_pos[-1] == FN_LIBCHAR && - strncmp(from_pos,FN_C_PARENT_DIR,par_length) == 0) - { /* Change '-' to '..' */ - to_pos=strmov(to_pos,FN_PARENTDIR); - *(to_pos++)=FN_LIBCHAR; - pos=to_pos; - from_pos+=par_length-1; - break; - } - /* Fall through */ - default: - *(to_pos++)= *from_pos; - break; - } - } - } - (void) strmov(to_pos,from_pos); + length= dirname_part(to, from, &to_length); /* Copy dirname & fix chars */ + (void) strmov(to + to_length,from+length); return (to); -#endif /* VMS */ } /* intern_filename */ diff --git a/mysys/mf_path.c b/mysys/mf_path.c index 9af6173b417..73e73cb7f76 100644 --- a/mysys/mf_path.c +++ b/mysys/mf_path.c @@ -29,22 +29,24 @@ static char *find_file_in_path(char *to,const char *name); own_path_name_part is concatinated to result. my_path puts result in to and returns to */ -my_string my_path(my_string to, const char *progname, - const char *own_pathname_part) +char * my_path(char * to, const char *progname, + const char *own_pathname_part) { - my_string start,end,prog; + char *start, *end, *prog; + size_t to_length; DBUG_ENTER("my_path"); start=to; /* Return this */ - if (progname && (dirname_part(to, progname) || + if (progname && (dirname_part(to, progname, &to_length) || find_file_in_path(to,progname) || - ((prog=getenv("_")) != 0 && dirname_part(to,prog)))) + ((prog=getenv("_")) != 0 && + dirname_part(to, prog, &to_length)))) { VOID(intern_filename(to,to)); if (!test_if_hard_path(to)) { if (!my_getwd(curr_dir,FN_REFLEN,MYF(0))) - bchange(to,0,curr_dir, (uint) strlen(curr_dir), (uint) strlen(to)+1); + bchange((uchar*) to, 0, (uchar*) curr_dir, strlen(curr_dir), strlen(to)+1); } } else @@ -72,7 +74,7 @@ my_string my_path(my_string to, const char *progname, /* test if file without filename is found in path */ /* Returns to if found and to has dirpart if found, else NullS */ -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#if defined(__WIN__) #define F_OK 0 #define PATH_SEP ';' #define PROGRAM_EXTENSION ".exe" diff --git a/mysys/mf_radix.c b/mysys/mf_radix.c index 6b750181558..582ca76b8f8 100644 --- a/mysys/mf_radix.c +++ b/mysys/mf_radix.c @@ -25,7 +25,7 @@ /* Radixsort */ -void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_s size_of_element, uchar **buffer) +void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_t size_of_element, uchar **buffer) { uchar **end,**ptr,**buffer_ptr; uint32 *count_ptr,*count_end,count[256]; @@ -34,7 +34,7 @@ void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_s size_of end=base+number_of_elements; count_end=count+256; for (pass=(int) size_of_element-1 ; pass >= 0 ; pass--) { - bzero((gptr) count,sizeof(uint32)*256); + bzero((uchar*) count,sizeof(uint32)*256); for (ptr= base ; ptr < end ; ptr++) count[ptr[0][pass]]++; if (count[0] == number_of_elements) diff --git a/mysys/mf_same.c b/mysys/mf_same.c index e7cdb012c9f..6738dc8051e 100644 --- a/mysys/mf_same.c +++ b/mysys/mf_same.c @@ -25,14 +25,15 @@ Returns 'to'. */ -my_string fn_same(char *to, const char *name, int flag) +char * fn_same(char *to, const char *name, int flag) { char dev[FN_REFLEN]; const char *ext; + size_t dev_length; DBUG_ENTER("fn_same"); DBUG_PRINT("enter",("to: %s name: %s flag: %d",to,name,flag)); - if ((ext=strrchr(name+dirname_part(dev,name),FN_EXTCHAR)) == 0) + if ((ext=strrchr(name+dirname_part(dev, name, &dev_length),FN_EXTCHAR)) == 0) ext=""; DBUG_RETURN(fn_format(to,to,dev,ext,flag)); diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c index a0c74642cb0..686ebbc1d14 100644 --- a/mysys/mf_sort.c +++ b/mysys/mf_sort.c @@ -18,7 +18,7 @@ #include "mysys_priv.h" #include <m_string.h> -void my_string_ptr_sort(void *base, uint items, size_s size) +void my_string_ptr_sort(uchar *base, uint items, size_t size) { #if INT_MAX > 65536L uchar **ptr=0; @@ -27,15 +27,15 @@ void my_string_ptr_sort(void *base, uint items, size_s size) (ptr= (uchar**) my_malloc(items*sizeof(char*),MYF(0)))) { radixsort_for_str_ptr((uchar**) base,items,size,ptr); - my_free((gptr) ptr,MYF(0)); + my_free((uchar*) ptr,MYF(0)); } else #endif { if (size && items) { - uint size_arg=size; - my_qsort2(base,items,sizeof(byte*),get_ptr_compare(size),(void*) &size_arg); + my_qsort2(base,items, sizeof(uchar*), get_ptr_compare(size), + (void*) &size); } } } diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c index fa393d1a94a..fe30d8c81af 100644 --- a/mysys/mf_soundex.c +++ b/mysys/mf_soundex.c @@ -42,11 +42,11 @@ static char get_scode(CHARSET_INFO * cs, char **ptr,pbool remove_garbage); /* outputed string is 4 byte long */ /* out_pntr can be == in_pntr */ -void soundex(CHARSET_INFO * cs,register my_string out_pntr, my_string in_pntr, +void soundex(CHARSET_INFO * cs,register char * out_pntr, char * in_pntr, pbool remove_garbage) { char ch,last_ch; - reg3 my_string end; + reg3 char * end; register uchar *map=cs->to_upper; if (remove_garbage) diff --git a/mysys/mf_strip.c b/mysys/mf_strip.c deleted file mode 100644 index 712b0e1d28a..00000000000 --- a/mysys/mf_strip.c +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* T|mmer en str{ng p{ slut_space */ - -#include "mysys_priv.h" - -/* - strip_sp(my_string str) - Strips end-space from string and returns new length. -*/ - -size_s strip_sp(register my_string str) -{ - reg2 my_string found; - reg3 my_string start; - - start=found=str; - - while (*str) - { - if (*str != ' ') - { - while (*++str && *str != ' ') {}; - if (!*str) - return (size_s) (str-start); /* Return stringlength */ - } - found=str; - while (*++str == ' ') {}; - } - *found= '\0'; /* Stripp at first space */ - return (size_s) (found-start); -} /* strip_sp */ diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c index bcd003920f1..87282e350aa 100644 --- a/mysys/mf_tempdir.c +++ b/mysys/mf_tempdir.c @@ -1,4 +1,6 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2002, 2004-2007 MySQL AB, 2008 Sun Microsystems, Inc. + Use is subject to license terms. 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 @@ -11,12 +13,13 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include <m_string.h> -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) #define DELIM ';' #else #define DELIM ':' @@ -26,14 +29,17 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) { char *end, *copy; char buff[FN_REFLEN]; + DBUG_ENTER("init_tmpdir"); + DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); + pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5)) - return TRUE; + goto err; if (!pathlist || !pathlist[0]) { /* Get default temporary directory */ pathlist=getenv("TMPDIR"); /* Use this if possible */ -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) if (!pathlist) pathlist=getenv("TEMP"); if (!pathlist) @@ -44,12 +50,13 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) } do { + size_t length; end=strcend(pathlist, DELIM); - convert_dirname(buff, pathlist, end); - if (!(copy=my_strdup(buff, MYF(MY_WME)))) - return TRUE; - if (insert_dynamic(&tmpdir->full_list, (gptr)©)) - return TRUE; + strmake(buff, pathlist, (uint) (end-pathlist)); + length= cleanup_dirname(buff, buff); + if (!(copy= my_strndup(buff, length, MYF(MY_WME))) || + insert_dynamic(&tmpdir->full_list, (uchar*) ©)) + DBUG_RETURN(TRUE); pathlist=end+1; } while (*end); @@ -57,12 +64,20 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) tmpdir->list=(char **)tmpdir->full_list.buffer; tmpdir->max=tmpdir->full_list.elements-1; tmpdir->cur=0; - return FALSE; + DBUG_RETURN(FALSE); + +err: + delete_dynamic(&tmpdir->full_list); /* Safe to free */ + pthread_mutex_destroy(&tmpdir->mutex); + DBUG_RETURN(TRUE); } + char *my_tmpdir(MY_TMPDIR *tmpdir) { char *dir; + if (!tmpdir->max) + return tmpdir->list[0]; pthread_mutex_lock(&tmpdir->mutex); dir=tmpdir->list[tmpdir->cur]; tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1; @@ -73,6 +88,8 @@ char *my_tmpdir(MY_TMPDIR *tmpdir) void free_tmpdir(MY_TMPDIR *tmpdir) { uint i; + if (!tmpdir->full_list.elements) + return; for (i=0; i<=tmpdir->max; i++) my_free(tmpdir->list[i], MYF(0)); delete_dynamic(&tmpdir->full_list); diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index 9460f27b104..40016210de4 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -136,6 +136,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, if (org_file >= 0 && file < 0) { int tmp=my_errno; + close(org_file); (void) my_delete(to, MYF(MY_WME | ME_NOINPUT)); my_errno=tmp; } diff --git a/mysys/mf_unixpath.c b/mysys/mf_unixpath.c index 11292e231ba..75f8de14879 100644 --- a/mysys/mf_unixpath.c +++ b/mysys/mf_unixpath.c @@ -19,7 +19,7 @@ /* convert filename to unix style filename */ /* If MSDOS converts '\' to '/' */ -void to_unix_path(my_string to __attribute__((unused))) +void to_unix_path(char * to __attribute__((unused))) { #if FN_LIBCHAR != '/' { diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c index b574d158b9e..3a6dc1225f8 100644 --- a/mysys/mf_wfile.c +++ b/mysys/mf_wfile.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Functions for finding files with wildcards */ @@ -29,12 +31,12 @@ /* Store wildcard-string in a easyer format */ -WF_PACK *wf_comp(my_string str) +WF_PACK *wf_comp(char * str) { uint ant; int not_pos; - register my_string pos; - my_string buffer; + register char * pos; + char * buffer; WF_PACK *ret; DBUG_ENTER("wf_comp"); @@ -53,13 +55,13 @@ WF_PACK *wf_comp(my_string str) for (pos=str ; *pos ; pos++) ant+= test(*pos == ' ' || *pos == ','); - if ((ret= (WF_PACK*) my_malloc((uint) ant*(sizeof(my_string*)+2)+ + if ((ret= (WF_PACK*) my_malloc((uint) ant*(sizeof(char **)+2)+ sizeof(WF_PACK)+ (uint) strlen(str)+1, MYF(MY_WME))) == 0) DBUG_RETURN((WF_PACK *) NULL); - ret->wild= (my_string*) (ret+1); - buffer= (my_string) (ret->wild+ant); + ret->wild= (char **) (ret+1); + buffer= (char *) (ret->wild+ant); ant=0; for (pos=str ; *pos ; str= pos) @@ -119,6 +121,6 @@ void wf_end(WF_PACK *buffer) { DBUG_ENTER("wf_end"); if (buffer) - my_free((gptr) buffer,MYF(0)); + my_free(buffer, MYF(0)); DBUG_VOID_RETURN; } /* wf_end */ diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c index bada0a55a6a..f4ca3d9f9ab 100644 --- a/mysys/mulalloc.c +++ b/mysys/mulalloc.c @@ -31,11 +31,11 @@ NULL */ -gptr my_multi_malloc(myf myFlags, ...) +void* my_multi_malloc(myf myFlags, ...) { va_list args; char **ptr,*start,*res; - uint tot_length,length; + size_t tot_length,length; DBUG_ENTER("my_multi_malloc"); va_start(args,myFlags); @@ -59,5 +59,5 @@ gptr my_multi_malloc(myf myFlags, ...) res+=ALIGN_SIZE(length); } va_end(args); - DBUG_RETURN((gptr) start); + DBUG_RETURN((void*) start); } diff --git a/mysys/my_access.c b/mysys/my_access.c index 9ee20cc942b..210946d50a8 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -53,24 +53,111 @@ int my_access(const char *path, int amode) #endif /* __WIN__ */ -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) /* List of file names that causes problem on windows NOTE that one can also not have file names of type CON.TXT + + NOTE: it is important to keep "CLOCK$" on the first place, + we skip it in check_if_legal_tablename. */ - static const char *reserved_names[]= { - "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", - "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", - "LPT7", "LPT8", "LPT9", "CLOCK$", + "CLOCK$", + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", NullS }; #define MAX_RESERVED_NAME_LENGTH 6 + +/* + Looks up a null-terminated string in a list, + case insensitively. + + SYNOPSIS + str_list_find() + list list of items + str item to find + + RETURN + 0 ok + 1 reserved file name +*/ +static int str_list_find(const char **list, const char *str) +{ + const char **name; + for (name= list; *name; name++) + { + if (!my_strcasecmp(&my_charset_latin1, *name, str)) + return 1; + } + return 0; +} + + +/* + A map for faster reserved_names lookup, + helps to avoid loops in many cases. + 1 - can be the first letter + 2 - can be the second letter + 4 - can be the third letter +*/ +static char reserved_map[256]= +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* !"#$%&'()*+,-./ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0123456789:;<=>? */ + 0,1,0,1,0,0,0,0,0,0,0,0,7,4,5,2, /* @ABCDEFGHIJKLMNO */ + 3,0,2,0,4,2,0,0,4,0,0,0,0,0,0,0, /* PQRSTUVWXYZ[\]^_ */ + 0,1,0,1,0,0,0,0,0,0,0,0,7,4,5,2, /* bcdefghijklmno */ + 3,0,2,0,4,2,0,0,4,0,0,0,0,0,0,0, /* pqrstuvwxyz{|}~. */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* ................ */ +}; + + +/* + Check if a table name may cause problems + + SYNOPSIS + check_if_legal_tablename + name Table name (without any extensions) + + DESCRIPTION + We don't check 'CLOCK$' because dollar sign is encoded as @0024, + making table file name 'CLOCK@0024', which is safe. + This is why we start lookup from the second element + (i.e. &reserver_name[1]) + + RETURN + 0 ok + 1 reserved file name +*/ + +int check_if_legal_tablename(const char *name) +{ + DBUG_ENTER("check_if_legal_tablename"); + DBUG_RETURN((reserved_map[(uchar) name[0]] & 1) && + (reserved_map[(uchar) name[1]] & 2) && + (reserved_map[(uchar) name[2]] & 4) && + str_list_find(&reserved_names[1], name)); +} + + +#if defined(__WIN__) || defined(__EMX__) + + /* Check if a path will access a reserverd file name that may cause problems @@ -110,12 +197,5 @@ int check_if_legal_filename(const char *path) } DBUG_RETURN(0); } -#endif - -#ifdef OS2 -int check_if_legal_filename(const char *path) -{ - return 0; -} -#endif /* OS2 */ +#endif /* defined(__WIN__) || defined(__EMX__) */ diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index fc5f9df22f0..6a5fad822a6 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Routines to handle mallocing of results which will be freed the same time */ @@ -44,8 +45,8 @@ reported as error in first alloc_root() on this memory root. */ -void init_alloc_root(MEM_ROOT *mem_root, uint block_size, - uint pre_alloc_size __attribute__((unused))) +void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, + size_t pre_alloc_size __attribute__((unused))) { DBUG_ENTER("init_alloc_root"); DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); @@ -91,8 +92,8 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size, before allocation. */ -void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, - uint pre_alloc_size __attribute__((unused))) +void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, + size_t pre_alloc_size __attribute__((unused))) { DBUG_ASSERT(alloc_root_inited(mem_root)); @@ -100,7 +101,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) if (pre_alloc_size) { - uint size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)); + size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)); if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size) { USED_MEM *mem, **prev= &mem_root->free; @@ -121,7 +122,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, { /* remove block from the list and free it */ *prev= mem->next; - my_free((gptr) mem, MYF(0)); + my_free(mem, MYF(0)); } else prev= &mem->next; @@ -146,7 +147,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, uint block_size, } -gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) +void *alloc_root(MEM_ROOT *mem_root, size_t length) { #if defined(HAVE_purify) && defined(EXTRA_DEBUG) reg1 USED_MEM *next; @@ -155,32 +156,48 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) DBUG_ASSERT(alloc_root_inited(mem_root)); - Size+=ALIGN_SIZE(sizeof(USED_MEM)); - if (!(next = (USED_MEM*) my_malloc(Size,MYF(MY_WME)))) + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + if (mem_root->error_handler) + (*mem_root->error_handler)(); + DBUG_SET("-d,simulate_out_of_memory"); + DBUG_RETURN((void*) 0); /* purecov: inspected */ + }); + + length+=ALIGN_SIZE(sizeof(USED_MEM)); + if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME)))) { if (mem_root->error_handler) (*mem_root->error_handler)(); - DBUG_RETURN((gptr) 0); /* purecov: inspected */ + DBUG_RETURN((uchar*) 0); /* purecov: inspected */ } next->next= mem_root->used; - next->size= Size; + next->size= length; mem_root->used= next; DBUG_PRINT("exit",("ptr: 0x%lx", (long) (((char*) next)+ ALIGN_SIZE(sizeof(USED_MEM))))); - DBUG_RETURN((gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)))); + DBUG_RETURN((uchar*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)))); #else - uint get_size, block_size; - gptr point; + size_t get_size, block_size; + uchar* point; reg1 USED_MEM *next= 0; reg2 USED_MEM **prev; DBUG_ENTER("alloc_root"); DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); DBUG_ASSERT(alloc_root_inited(mem_root)); - Size= ALIGN_SIZE(Size); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + /* Avoid reusing an already allocated block */ + if (mem_root->error_handler) + (*mem_root->error_handler)(); + DBUG_SET("-d,simulate_out_of_memory"); + DBUG_RETURN((void*) 0); /* purecov: inspected */ + }); + length= ALIGN_SIZE(length); if ((*(prev= &mem_root->free)) != NULL) { - if ((*prev)->left < Size && + if ((*prev)->left < length && mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP && (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP) { @@ -190,20 +207,20 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) mem_root->used= next; mem_root->first_block_usage= 0; } - for (next= *prev ; next && next->left < Size ; next= next->next) + for (next= *prev ; next && next->left < length ; next= next->next) prev= &next->next; } if (! next) { /* Time to alloc new block */ block_size= mem_root->block_size * (mem_root->block_num >> 2); - get_size= Size+ALIGN_SIZE(sizeof(USED_MEM)); + get_size= length+ALIGN_SIZE(sizeof(USED_MEM)); get_size= max(get_size, block_size); if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME)))) { if (mem_root->error_handler) (*mem_root->error_handler)(); - DBUG_RETURN((gptr) 0); /* purecov: inspected */ + DBUG_RETURN((void*) 0); /* purecov: inspected */ } mem_root->block_num++; next->next= *prev; @@ -212,9 +229,9 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) *prev=next; } - point= (gptr) ((char*) next+ (next->size-next->left)); + point= (uchar*) ((char*) next+ (next->size-next->left)); /*TODO: next part may be unneded due to mem_root->first_block_usage counter*/ - if ((next->left-= Size) < mem_root->min_malloc) + if ((next->left-= length) < mem_root->min_malloc) { /* Full block */ *prev= next->next; /* Remove block from list */ next->next= mem_root->used; @@ -222,7 +239,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) mem_root->first_block_usage= 0; } DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point)); - DBUG_RETURN(point); + DBUG_RETURN((void*) point); #endif } @@ -246,11 +263,11 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size) in case of success or NULL if out of memory. */ -gptr multi_alloc_root(MEM_ROOT *root, ...) +void *multi_alloc_root(MEM_ROOT *root, ...) { va_list args; char **ptr, *start, *res; - uint tot_length, length; + size_t tot_length, length; DBUG_ENTER("multi_alloc_root"); va_start(args, root); @@ -274,7 +291,7 @@ gptr multi_alloc_root(MEM_ROOT *root, ...) res+= ALIGN_SIZE(length); } va_end(args); - DBUG_RETURN((gptr) start); + DBUG_RETURN((void*) start); } #define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left) @@ -335,8 +352,6 @@ void free_root(MEM_ROOT *root, myf MyFlags) DBUG_ENTER("free_root"); DBUG_PRINT("enter",("root: 0x%lx flags: %u", (long) root, (uint) MyFlags)); - if (!root) /* QQ: Should be deleted */ - DBUG_VOID_RETURN; /* purecov: inspected */ if (MyFlags & MY_MARK_BLOCKS_FREE) { mark_blocks_free(root); @@ -349,13 +364,13 @@ void free_root(MEM_ROOT *root, myf MyFlags) { old=next; next= next->next ; if (old != root->pre_alloc) - my_free((gptr) old,MYF(0)); + my_free(old,MYF(0)); } for (next=root->free ; next ;) { old=next; next= next->next; if (old != root->pre_alloc) - my_free((gptr) old,MYF(0)); + my_free(old,MYF(0)); } root->used=root->free=0; if (root->pre_alloc) @@ -396,12 +411,13 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr) } -char *strdup_root(MEM_ROOT *root,const char *str) +char *strdup_root(MEM_ROOT *root, const char *str) { - return strmake_root(root, str, (uint) strlen(str)); + return strmake_root(root, str, strlen(str)); } -char *strmake_root(MEM_ROOT *root,const char *str, uint len) + +char *strmake_root(MEM_ROOT *root, const char *str, size_t len) { char *pos; if ((pos=alloc_root(root,len+1))) @@ -413,7 +429,7 @@ char *strmake_root(MEM_ROOT *root,const char *str, uint len) } -char *memdup_root(MEM_ROOT *root,const char *str,uint len) +void *memdup_root(MEM_ROOT *root, const void *str, size_t len) { char *pos; if ((pos=alloc_root(root,len))) diff --git a/mysys/my_append.c b/mysys/my_append.c index 274f2110575..d8789f95d95 100644 --- a/mysys/my_append.c +++ b/mysys/my_append.c @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <sys/stat.h> #include <m_string.h> @@ -28,21 +27,22 @@ struct utimbuf { }; #endif - /* Append a file to another */ - -int my_append(const char *from, const char *to, myf MyFlags) +/* + Append a file to another + NOTES + Don't set MY_FNABP or MY_NABP bits on when calling this function +*/ - /* Dont set MY_FNABP or MY_NABP bits on - when calling this funktion */ +int my_append(const char *from, const char *to, myf MyFlags) { - uint Count; + size_t Count; File from_file,to_file; - char buff[IO_SIZE]; + uchar buff[IO_SIZE]; DBUG_ENTER("my_append"); DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); - from_file=to_file= -1; + from_file= to_file= -1; if ((from_file=my_open(from,O_RDONLY,MyFlags)) >= 0) { diff --git a/mysys/my_bit.c b/mysys/my_bit.c index 81d63246e7a..2881eb1ebd2 100644 --- a/mysys/my_bit.c +++ b/mysys/my_bit.c @@ -13,23 +13,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Some useful bit functions */ +#include <my_global.h> -#include "mysys_priv.h" - -/* - Find smallest X in 2^X >= value - This can be used to divide a number with value by doing a shift instead -*/ +#ifndef HAVE_INLINE +/* the following will cause all inline functions to be instantiated */ +#define HAVE_INLINE +#undef STATIC_INLINE +#define STATIC_INLINE extern +#endif -uint my_bit_log2(ulong value) -{ - uint bit; - for (bit=0 ; value > 1 ; value>>=1, bit++) ; - return bit; -} +#include <my_bit.h> -static char nbits[256] = { +const char _my_bits_nbits[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, @@ -48,30 +43,29 @@ static char nbits[256] = { 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, }; -uint my_count_bits(ulonglong v) -{ -#if SIZEOF_LONG_LONG > 4 - /* The following code is a bit faster on 16 bit machines than if we would - only shift v */ - ulong v2=(ulong) (v >> 32); - return (uint) (uchar) (nbits[(uchar) v] + - nbits[(uchar) (v >> 8)] + - nbits[(uchar) (v >> 16)] + - nbits[(uchar) (v >> 24)] + - nbits[(uchar) (v2)] + - nbits[(uchar) (v2 >> 8)] + - nbits[(uchar) (v2 >> 16)] + - nbits[(uchar) (v2 >> 24)]); -#else - return (uint) (uchar) (nbits[(uchar) v] + - nbits[(uchar) (v >> 8)] + - nbits[(uchar) (v >> 16)] + - nbits[(uchar) (v >> 24)]); -#endif -} - -uint my_count_bits_ushort(ushort v) -{ - return nbits[v]; -} +/* + perl -e 'print map{", 0x".unpack H2,pack B8,unpack b8,chr$_}(0..255)' +*/ +const uchar _my_bits_reverse_table[256]={ +0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, +0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, +0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, +0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, +0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, +0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, +0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, +0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, +0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, +0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, +0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, +0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, +0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, +0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, +0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, +0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, +0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, +0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, +0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, +0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index beb67bb419b..e4e4f61357c 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Handling of uchar arrays as large bitmaps. @@ -19,25 +21,69 @@ API limitations (or, rather asserted safety assumptions, to encourage correct programming) - * the size of the used bitmap is less than ~(uint) 0 - * it's a multiple of 8 (for efficiency reasons) - * when arguments are a bitmap and a bit number, the number - must be within bitmap size - * bitmap_set_prefix() is an exception - one can use ~0 to set all bits - * when both arguments are bitmaps, they must be of the same size - * bitmap_intersect() is an exception :) - (for for Bitmap::intersect(ulonglong map2buff)) - - If THREAD is defined all bitmap operations except bitmap_init/bitmap_free - are thread-safe. + * the internal size is a set of 32 bit words + * the number of bits specified in creation can be any number > 0 + * there are THREAD safe versions of most calls called bitmap_lock_* + many of those are not used and not compiled normally but the code + already exist for them in an #ifdef:ed part. These can only be used + if THREAD was specified in bitmap_init TODO: Make assembler THREAD safe versions of these using test-and-set instructions + + Original version created by Sergei Golubchik 2001 - 2004. + New version written and test program added and some changes to the interface + was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats + Kindahl. */ #include "mysys_priv.h" #include <my_bitmap.h> #include <m_string.h> +#include <my_bit.h> + +void create_last_word_mask(MY_BITMAP *map) +{ + /* Get the number of used bits (1..8) in the last byte */ + unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U); + + /* + Create a mask with the upper 'unused' bits set and the lower 'used' + bits clear. The bits within each byte is stored in big-endian order. + */ + unsigned char const mask= (~((1 << used) - 1)) & 255; + + /* + The first bytes are to be set to zero since they represent real bits + in the bitvector. The last bytes are set to 0xFF since they represent + bytes not used by the bitvector. Finally the last byte contains bits + as set by the mask above. + */ + unsigned char *ptr= (unsigned char*)&map->last_word_mask; + + map->last_word_ptr= map->bitmap + no_words_in_map(map)-1; + switch (no_bytes_in_map(map) & 3) { + case 1: + map->last_word_mask= ~0U; + ptr[0]= mask; + return; + case 2: + map->last_word_mask= ~0U; + ptr[0]= 0; + ptr[1]= mask; + return; + case 3: + map->last_word_mask= 0U; + ptr[2]= mask; + ptr[3]= 0xFFU; + return; + case 0: + map->last_word_mask= 0U; + ptr[3]= mask; + return; + } +} + static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) { @@ -47,6 +93,7 @@ static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) #endif } + static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) { #ifdef THREAD @@ -56,29 +103,83 @@ static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) } -my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, - my_bool thread_safe) +static inline uint get_first_set(uint32 value, uint word_pos) { - DBUG_ENTER("bitmap_init"); + uchar *byte_ptr= (uchar*)&value; + uchar byte_value; + uint byte_pos, bit_pos; - DBUG_ASSERT((bitmap_size & 7) == 0); - bitmap_size/=8; - if (!(map->bitmap=buf) && - !(map->bitmap= (uchar*) my_malloc(bitmap_size + - (thread_safe ? - sizeof(pthread_mutex_t) : 0), - MYF(MY_WME | MY_ZEROFILL)))) - DBUG_RETURN(1); - map->bitmap_size=bitmap_size; -#ifdef THREAD - if (thread_safe) + for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++) { - map->mutex=(pthread_mutex_t *)(map->bitmap+bitmap_size); - pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); + byte_value= *byte_ptr; + if (byte_value) + { + for (bit_pos=0; ; bit_pos++) + if (byte_value & (1 << bit_pos)) + return (word_pos*32) + (byte_pos*8) + bit_pos; + } } + return MY_BIT_NONE; +} + + +static inline uint get_first_not_set(uint32 value, uint word_pos) +{ + uchar *byte_ptr= (uchar*)&value; + uchar byte_value; + uint byte_pos, bit_pos; + + for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++) + { + byte_value= *byte_ptr; + if (byte_value != 0xFF) + { + for (bit_pos=0; ; bit_pos++) + if (!(byte_value & (1 << bit_pos))) + return (word_pos*32) + (byte_pos*8) + bit_pos; + } + } + return MY_BIT_NONE; +} + + +my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, + my_bool thread_safe __attribute__((unused))) +{ + DBUG_ENTER("bitmap_init"); + if (!buf) + { + uint size_in_bytes= bitmap_buffer_size(n_bits); + uint extra= 0; +#ifdef THREAD + if (thread_safe) + { + size_in_bytes= ALIGN_SIZE(size_in_bytes); + extra= sizeof(pthread_mutex_t); + } + map->mutex= 0; +#endif + if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME)))) + DBUG_RETURN(1); +#ifdef THREAD + if (thread_safe) + { + map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes); + pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); + } +#endif + } +#ifdef THREAD else - map->mutex=0; + { + DBUG_ASSERT(thread_safe == 0); + } #endif + + map->bitmap= buf; + map->n_bits= n_bits; + create_last_word_mask(map); + bitmap_clear_all(map); DBUG_RETURN(0); } @@ -99,15 +200,6 @@ void bitmap_free(MY_BITMAP *map) } -void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) -{ - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); - bitmap_lock(map); - bitmap_fast_set_bit(map, bitmap_bit); - bitmap_unlock(map); -} - - /* test if bit already set and set it if it was not (thread unsafe method) @@ -123,7 +215,7 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) { - uchar *value= map->bitmap + (bitmap_bit / 8); + uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8); uchar bit= 1 << ((bitmap_bit) & 7); uchar res= (*value) & bit; *value|= bit; @@ -147,194 +239,205 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_set(map, bitmap_bit); bitmap_unlock(map); return res; } -uint bitmap_set_next(MY_BITMAP *map) -{ - uchar *bitmap=map->bitmap; - uint bit_found = MY_BIT_NONE; - uint bitmap_size=map->bitmap_size; - uint i; +/* + test if bit already set and clear it if it was set(thread unsafe method) - DBUG_ASSERT(map->bitmap); - bitmap_lock(map); - for (i=0; i < bitmap_size ; i++, bitmap++) - { - if (*bitmap != 0xff) - { /* Found slot with free bit */ - uint b; - for (b=0; ; b++) - { - if (!(*bitmap & (1 << b))) - { - *bitmap |= 1<<b; - bit_found = (i*8)+b; - break; - } - } - break; /* Found bit */ - } - } - bitmap_unlock(map); - return bit_found; -} + SYNOPSIS + bitmap_fast_test_and_set() + MAP bit map struct + BIT bit number + RETURN + 0 bit was not set + !=0 bit was set +*/ -void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit) +my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); - bitmap_lock(map); - bitmap_fast_clear_bit(map, bitmap_bit); - bitmap_unlock(map); + uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); + uchar bit= 1 << ((bitmap_bit) & 7); + uchar res= (*byte) & bit; + *byte&= ~bit; + return res; } -void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) +my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { - uint prefix_bytes, prefix_bits; - - DBUG_ASSERT(map->bitmap && - (prefix_size <= map->bitmap_size*8 || prefix_size == (uint) ~0)); + my_bool res; + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); bitmap_lock(map); - set_if_smaller(prefix_size, map->bitmap_size*8); - if ((prefix_bytes= prefix_size / 8)) - memset(map->bitmap, 0xff, prefix_bytes); - if ((prefix_bits= prefix_size & 7)) - map->bitmap[prefix_bytes++]= (1 << prefix_bits)-1; - if (prefix_bytes < map->bitmap_size) - bzero(map->bitmap+prefix_bytes, map->bitmap_size-prefix_bytes); + res= bitmap_fast_test_and_clear(map, bitmap_bit); bitmap_unlock(map); + return res; } -void bitmap_clear_all(MY_BITMAP *map) +uint bitmap_set_next(MY_BITMAP *map) { - bitmap_set_prefix(map, 0); + uint bit_found; + DBUG_ASSERT(map->bitmap); + if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE) + bitmap_set_bit(map, bit_found); + return bit_found; } -void bitmap_set_all(MY_BITMAP *map) +void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) { - bitmap_set_prefix(map, ~0); + uint prefix_bytes, prefix_bits, d; + uchar *m= (uchar *)map->bitmap; + + DBUG_ASSERT(map->bitmap && + (prefix_size <= map->n_bits || prefix_size == (uint) ~0)); + set_if_smaller(prefix_size, map->n_bits); + if ((prefix_bytes= prefix_size / 8)) + memset(m, 0xff, prefix_bytes); + m+= prefix_bytes; + if ((prefix_bits= prefix_size & 7)) + *(m++)= (1 << prefix_bits)-1; + if ((d= no_bytes_in_map(map)-prefix_bytes)) + bzero(m, d); } my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_bits= prefix_size & 7, res= 0; - uchar *m= map->bitmap, *end_prefix= map->bitmap+prefix_size/8, - *end= map->bitmap+map->bitmap_size; + uint prefix_bits= prefix_size % 32; + my_bitmap_map *word_ptr= map->bitmap, last_word; + my_bitmap_map *end_prefix= word_ptr + prefix_size / 32; + DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits); - DBUG_ASSERT(map->bitmap && prefix_size <= map->bitmap_size*8); - - bitmap_lock((MY_BITMAP *)map); - while (m < end_prefix) - if (*m++ != 0xff) - goto ret; + /* 1: Words that should be filled with 1 */ + for (; word_ptr < end_prefix; word_ptr++) + if (*word_ptr != 0xFFFFFFFF) + return FALSE; - if (prefix_bits && *m++ != (1 << prefix_bits)-1) - goto ret; + last_word= *map->last_word_ptr & ~map->last_word_mask; - while (m < end) - if (*m++ != 0) - goto ret; + /* 2: Word which contains the end of the prefix (if any) */ + if (prefix_bits) + { + if (word_ptr == map->last_word_ptr) + return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1); + else if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1)) + return FALSE; + word_ptr++; + } - res=1; -ret: - bitmap_unlock((MY_BITMAP *)map); - return res; + /* 3: Words that should be filled with 0 */ + for (; word_ptr < map->last_word_ptr; word_ptr++) + if (*word_ptr != 0) + return FALSE; + + /* + We can end up here in two situations: + 1) We went through the whole bitmap in step 1. This will happen if the + whole bitmap is filled with 1 and prefix_size is a multiple of 32 + (i.e. the prefix does not end in the middle of a word). + In this case word_ptr will be larger than map->last_word_ptr. + 2) We have gone through steps 1-3 and just need to check that also + the last word is 0. + */ + return word_ptr > map->last_word_ptr || last_word == 0; } -my_bool bitmap_is_clear_all(const MY_BITMAP *map) -{ - return bitmap_is_prefix(map, 0); -} - my_bool bitmap_is_set_all(const MY_BITMAP *map) { - return bitmap_is_prefix(map, map->bitmap_size*8); + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end= map->last_word_ptr; + + for (; data_ptr < end; data_ptr++) + if (*data_ptr != 0xFFFFFFFF) + return FALSE; + if ((*map->last_word_ptr | map->last_word_mask) != 0xFFFFFFFF) + return FALSE; + return TRUE; } -my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit) +my_bool bitmap_is_clear_all(const MY_BITMAP *map) { - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); - return bitmap_fast_is_set(map, bitmap_bit); + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end= map->last_word_ptr; + + for (; data_ptr < end; data_ptr++) + if (*data_ptr) + return FALSE; + if (*map->last_word_ptr & ~map->last_word_mask) + return FALSE; + return TRUE; } +/* Return TRUE if map1 is a subset of map2 */ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { - uint res=0; - uchar *m1=map1->bitmap, *m2=map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->bitmap_size==map2->bitmap_size); - bitmap_lock((MY_BITMAP *)map1); - bitmap_lock((MY_BITMAP *)map2); - - end= m1+map1->bitmap_size; + map1->n_bits==map2->n_bits); - while (m1 < end) - { - if ((*m1++) & ~(*m2++)) - goto ret; - } + end= map1->last_word_ptr; + for (; m1 < end; m1++, m2++) + if (*m1 & ~(*m2)) + return FALSE; - res=1; -ret: - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock((MY_BITMAP *)map1); - return res; + if ((*map1->last_word_ptr & ~map1->last_word_mask) & + ~(*map2->last_word_ptr & ~map2->last_word_mask)) + return FALSE; + return TRUE; } +/* True if bitmaps has any common bits */ -my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) +my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { - uint res; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->bitmap_size==map2->bitmap_size); - bitmap_lock((MY_BITMAP *)map1); - bitmap_lock((MY_BITMAP *)map2); + map1->n_bits==map2->n_bits); - res= memcmp(map1->bitmap, map2->bitmap, map1->bitmap_size)==0; + end= map1->last_word_ptr; + for (; m1 < end; m1++, m2++) + if (*m1 & *m2) + return TRUE; - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock((MY_BITMAP *)map1); - return res; + if ((*map1->last_word_ptr & ~map1->last_word_mask) & + (*map2->last_word_ptr & ~map2->last_word_mask)) + return TRUE; + return FALSE; } void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) { - uchar *to=map->bitmap, *from=map2->bitmap, *end; - uint len=map->bitmap_size, len2=map2->bitmap_size; + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + uint len= no_words_in_map(map), len2 = no_words_in_map(map2); DBUG_ASSERT(map->bitmap && map2->bitmap); - bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); end= to+min(len,len2); + for (; to < end; to++, from++) + *to &= *from; - while (to < end) - *to++ &= *from++; + if (len >= len2) + map->bitmap[len2 - 1] &= ~map2->last_word_mask; if (len2 < len) { end+=len-len2; - while (to < end) - *to++=0; + for (; to < end; to++) + *to= 0; } - - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock(map); } @@ -361,47 +464,258 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) { uchar use_byte= use_bit ? 0xff : 0; - uchar *to= map->bitmap + from_byte; - uchar *end= map->bitmap + map->bitmap_size; + uchar *to= (uchar *)map->bitmap + from_byte; + uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8; - while (to < end) - *to++= use_byte; + for (; to < end; to++) + *to= use_byte; } void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { - uchar *to=map->bitmap, *from=map2->bitmap, *end; + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->n_bits==map2->n_bits); + end= map->last_word_ptr; + + for (; to <= end; to++, from++) + *to &= ~(*from); +} + +void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) +{ + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; DBUG_ASSERT(map->bitmap && map2->bitmap && - map->bitmap_size==map2->bitmap_size); + map->n_bits==map2->n_bits); + end= map->last_word_ptr; + + for (; to <= end; to++, from++) + *to |= *from; +} + + +void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) +{ + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->n_bits==map2->n_bits); + end= map->last_word_ptr; + + for (; to <= end; to++, from++) + *to ^= *from; +} + + +void bitmap_invert(MY_BITMAP *map) +{ + my_bitmap_map *to= map->bitmap, *end; + DBUG_ASSERT(map->bitmap); + end= map->last_word_ptr; + + for (; to <= end; to++) + *to ^= 0xFFFFFFFF; +} + + +uint bitmap_bits_set(const MY_BITMAP *map) +{ + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end= map->last_word_ptr; + uint res= 0; + DBUG_ASSERT(map->bitmap); + + for (; data_ptr < end; data_ptr++) + res+= my_count_bits_uint32(*data_ptr); + + /*Reset last bits to zero*/ + res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask); + return res; +} + + +void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) +{ + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->n_bits==map2->n_bits); + end= map->last_word_ptr; + + for (; to <= end; to++, from++) + *to = *from; +} + + +uint bitmap_get_first_set(const MY_BITMAP *map) +{ + uint word_pos; + my_bitmap_map *data_ptr, *end= map->last_word_ptr; + + DBUG_ASSERT(map->bitmap); + data_ptr= map->bitmap; + + for (word_pos=0; data_ptr < end; data_ptr++, word_pos++) + if (*data_ptr) + return get_first_set(*data_ptr, word_pos); + + return get_first_set(*map->last_word_ptr & ~map->last_word_mask, word_pos); +} + + +uint bitmap_get_first(const MY_BITMAP *map) +{ + uint word_pos; + my_bitmap_map *data_ptr, *end= map->last_word_ptr; + + DBUG_ASSERT(map->bitmap); + data_ptr= map->bitmap; + + for (word_pos=0; data_ptr < end; data_ptr++, word_pos++) + if (*data_ptr != 0xFFFFFFFF) + return get_first_not_set(*data_ptr, word_pos); + + return get_first_not_set(*map->last_word_ptr | map->last_word_mask, word_pos); +} + + +uint bitmap_lock_set_next(MY_BITMAP *map) +{ + uint bit_found; bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); + bit_found= bitmap_set_next(map); + bitmap_unlock(map); + return bit_found; +} + + +void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) +{ + bitmap_lock(map); + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_clear_bit(map, bitmap_bit); + bitmap_unlock(map); +} - end= to+map->bitmap_size; - while (to < end) - *to++ &= ~(*from++); +#ifdef NOT_USED +my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size) +{ + my_bool res; + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_prefix(map, prefix_size); + bitmap_unlock((MY_BITMAP *)map); + return res; +} - bitmap_unlock((MY_BITMAP *)map2); + +void bitmap_lock_set_all(MY_BITMAP *map) +{ + bitmap_lock(map); + bitmap_set_all(map); bitmap_unlock(map); } -void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) +void bitmap_lock_clear_all(MY_BITMAP *map) { - uchar *to=map->bitmap, *from=map2->bitmap, *end; + bitmap_lock(map); + bitmap_clear_all(map); + bitmap_unlock(map); +} - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->bitmap_size==map2->bitmap_size); + +void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size) +{ + bitmap_lock(map); + bitmap_set_prefix(map, prefix_size); + bitmap_unlock(map); +} + + +my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_clear_all(map); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +my_bool bitmap_lock_is_set_all(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_set_all(map); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit) +{ + my_bool res; + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_set(map, bitmap_bit); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + uint res; + bitmap_lock((MY_BITMAP *)map1); + bitmap_lock((MY_BITMAP *)map2); + res= bitmap_is_subset(map1, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock((MY_BITMAP *)map1); + return res; +} + + +my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + uint res; + + DBUG_ASSERT(map1->bitmap && map2->bitmap && + map1->n_bits==map2->n_bits); + bitmap_lock((MY_BITMAP *)map1); + bitmap_lock((MY_BITMAP *)map2); + res= bitmap_cmp(map1, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock((MY_BITMAP *)map1); + return res; +} + + +void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2) +{ bitmap_lock(map); bitmap_lock((MY_BITMAP *)map2); + bitmap_intersect(map, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock(map); +} - end= to+map->bitmap_size; - while (to < end) - *to++ |= *from++; +void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2) +{ + bitmap_lock(map); + bitmap_lock((MY_BITMAP *)map2); + bitmap_subtract(map, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock(map); +} + +void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2) +{ + bitmap_lock(map); + bitmap_lock((MY_BITMAP *)map2); + bitmap_union(map, map2); bitmap_unlock((MY_BITMAP *)map2); bitmap_unlock(map); } @@ -414,19 +728,12 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) RETURN Number of set bits in the bitmap. */ - -uint bitmap_bits_set(const MY_BITMAP *map) -{ - uchar *m= map->bitmap; - uchar *end= m + map->bitmap_size; - uint res= 0; - - DBUG_ASSERT(map->bitmap); +uint bitmap_lock_bits_set(const MY_BITMAP *map) +{ + uint res; bitmap_lock((MY_BITMAP *)map); - while (m < end) - { - res+= my_count_bits_ushort(*m++); - } + DBUG_ASSERT(map->bitmap); + res= bitmap_bits_set(map); bitmap_unlock((MY_BITMAP *)map); return res; } @@ -439,33 +746,40 @@ uint bitmap_bits_set(const MY_BITMAP *map) RETURN Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set. */ +uint bitmap_lock_get_first(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP*)map); + res= bitmap_get_first(map); + bitmap_unlock((MY_BITMAP*)map); + return res; +} -uint bitmap_get_first(const MY_BITMAP *map) + +uint bitmap_lock_get_first_set(const MY_BITMAP *map) { - uchar *bitmap=map->bitmap; - uint bit_found = MY_BIT_NONE; - uint bitmap_size=map->bitmap_size; - uint i; + uint res; + bitmap_lock((MY_BITMAP*)map); + res= bitmap_get_first_set(map); + bitmap_unlock((MY_BITMAP*)map); + return res; +} - DBUG_ASSERT(map->bitmap); - bitmap_lock((MY_BITMAP *)map); - for (i=0; i < bitmap_size ; i++, bitmap++) - { - if (*bitmap != 0xff) - { /* Found slot with free bit */ - uint b; - for (b=0; ; b++) - { - if (!(*bitmap & (1 << b))) - { - bit_found = (i*8)+b; - break; - } - } - break; /* Found bit */ - } - } - bitmap_unlock((MY_BITMAP *)map); - return bit_found; + +void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit) +{ + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_lock(map); + bitmap_set_bit(map, bitmap_bit); + bitmap_unlock(map); } + +void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit) +{ + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_lock(map); + bitmap_flip_bit(map, bitmap_bit); + bitmap_unlock(map); +} +#endif diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index a5dd1564692..b1dbb22c687 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -40,12 +40,12 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) { my_off_t oldsize; - char buff[IO_SIZE]; + uchar buff[IO_SIZE]; DBUG_ENTER("my_chsize"); DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength, MyFlags)); - if ((oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength) + if ((oldsize= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength) DBUG_RETURN(0); DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize)); @@ -98,11 +98,11 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) bfill(buff, IO_SIZE, filler); while (newlength-oldsize > IO_SIZE) { - if (my_write(fd,(byte*) buff,IO_SIZE,MYF(MY_NABP))) + if (my_write(fd, buff, IO_SIZE, MYF(MY_NABP))) goto err; oldsize+= IO_SIZE; } - if (my_write(fd,(byte*) buff,(uint) (newlength-oldsize),MYF(MY_NABP))) + if (my_write(fd,buff,(size_t) (newlength-oldsize), MYF(MY_NABP))) goto err; DBUG_RETURN(0); diff --git a/mysys/my_clock.c b/mysys/my_clock.c index c5fa516a622..adc755028d5 100644 --- a/mysys/my_clock.c +++ b/mysys/my_clock.c @@ -13,17 +13,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "my_global.h" -#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__NETWARE__) #include "mysys_priv.h" #include <sys/times.h> #endif long my_clock(void) { -#if !defined(MSDOS) && !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(__NETWARE__) struct tms tmsbuf; VOID(times(&tmsbuf)); return (tmsbuf.tms_utime + tmsbuf.tms_stime); diff --git a/mysys/my_compare.c b/mysys/my_compare.c index f58c081b1cc..532ac0a28b5 100644 --- a/mysys/my_compare.c +++ b/mysys/my_compare.c @@ -15,8 +15,7 @@ #include "my_compare.h" - -int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length, +int ha_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length, uchar *b, uint b_length, my_bool part_key, my_bool skip_end_space) { @@ -172,7 +171,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, next_key_length=key_length-b_length-pack_length; if (piks && - (flag=mi_compare_text(keyseg->charset,a,a_length,b,b_length, + (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0), (my_bool)!(nextflag & SEARCH_PREFIX)))) @@ -185,7 +184,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, { uint length=(uint) (end-a), a_length=length, b_length=length; if (piks && - (flag= mi_compare_text(keyseg->charset, a, a_length, b, b_length, + (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0), (my_bool)!(nextflag & SEARCH_PREFIX)))) @@ -233,7 +232,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, next_key_length=key_length-b_length-pack_length; if (piks && - (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length, + (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && next_key_length <= 0), (my_bool) ((nextflag & (SEARCH_FIND | diff --git a/mysys/my_compress.c b/mysys/my_compress.c index c054bf155b1..a3d9d56915e 100644 --- a/mysys/my_compress.c +++ b/mysys/my_compress.c @@ -24,12 +24,20 @@ #include <zlib.h> /* -** This replaces the packet with a compressed packet -** Returns 1 on error -** *complen is 0 if the packet wasn't compressed + This replaces the packet with a compressed packet + + SYNOPSIS + my_compress() + packet Data to compress. This is is replaced with the compressed data. + len Length of data to compress at 'packet' + complen out: 0 if packet was not compressed + + RETURN + 1 error. 'len' is not changed' + 0 ok. In this case 'len' contains the size of the compressed packet */ -my_bool my_compress(byte *packet, ulong *len, ulong *complen) +my_bool my_compress(uchar *packet, size_t *len, size_t *complen) { DBUG_ENTER("my_compress"); if (*len < MIN_COMPRESS_LENGTH) @@ -39,27 +47,36 @@ my_bool my_compress(byte *packet, ulong *len, ulong *complen) } else { - byte *compbuf=my_compress_alloc(packet,len,complen); + uchar *compbuf=my_compress_alloc(packet,len,complen); if (!compbuf) DBUG_RETURN(*complen ? 0 : 1); memcpy(packet,compbuf,*len); - my_free(compbuf,MYF(MY_WME)); } + my_free(compbuf,MYF(MY_WME)); + } DBUG_RETURN(0); } -byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen) +uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen) { - byte *compbuf; + uchar *compbuf; + uLongf tmp_complen; + int res; *complen= *len * 120 / 100 + 12; - if (!(compbuf= (byte *) my_malloc(*complen,MYF(MY_WME)))) + + if (!(compbuf= (uchar *) my_malloc(*complen, MYF(MY_WME)))) return 0; /* Not enough memory */ - if (compress((Bytef*) compbuf,(ulong *) complen, (Bytef*) packet, - (uLong) *len ) != Z_OK) + + tmp_complen= (uint) *complen; + res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len); + *complen= tmp_complen; + + if (res != Z_OK) { - my_free(compbuf,MYF(MY_WME)); + my_free(compbuf, MYF(MY_WME)); return 0; } + if (*complen >= *len) { *complen= 0; @@ -67,31 +84,181 @@ byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen) DBUG_PRINT("note",("Packet got longer on compression; Not compressed")); return 0; } - swap_variables(ulong, *len, *complen); /* *len is now packet length */ + /* Store length of compressed packet in *len */ + swap_variables(size_t, *len, *complen); return compbuf; } -my_bool my_uncompress (byte *packet, ulong *len, ulong *complen) +/* + Uncompress packet + + SYNOPSIS + my_uncompress() + packet Compressed data. This is is replaced with the orignal data. + len Length of compressed data + complen Length of the packet buffer (must be enough for the original + data) + + RETURN + 1 error + 0 ok. In this case 'complen' contains the updated size of the + real data. +*/ + +my_bool my_uncompress(uchar *packet, size_t len, size_t *complen) { + uLongf tmp_complen; DBUG_ENTER("my_uncompress"); + if (*complen) /* If compressed */ { - byte *compbuf= (byte *) my_malloc(*complen,MYF(MY_WME)); + uchar *compbuf= (uchar *) my_malloc(*complen,MYF(MY_WME)); int error; if (!compbuf) DBUG_RETURN(1); /* Not enough memory */ - if ((error=uncompress((Bytef*) compbuf, complen, (Bytef*) packet, *len)) - != Z_OK) + + tmp_complen= (uint) *complen; + error= uncompress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, + (uLong) len); + *complen= tmp_complen; + if (error != Z_OK) { /* Probably wrong packet */ DBUG_PRINT("error",("Can't uncompress packet, error: %d",error)); my_free(compbuf, MYF(MY_WME)); DBUG_RETURN(1); } - *len= *complen; - memcpy(packet, compbuf, *len); + memcpy(packet, compbuf, *complen); my_free(compbuf, MYF(MY_WME)); } + else + *complen= len; DBUG_RETURN(0); } + +/* + Internal representation of the frm blob is: + + ver 4 bytes + orglen 4 bytes + complen 4 bytes +*/ + +#define BLOB_HEADER 12 + + +/* + packfrm is a method used to compress the frm file for storage in a + handler. This method was developed for the NDB handler and has been moved + here to serve also other uses. + + SYNOPSIS + packfrm() + data Data reference to frm file data. + len Length of frm file data + out:pack_data Reference to the pointer to the packed frm data + out:pack_len Length of packed frm file data + + NOTES + data is replaced with compressed content + + RETURN VALUES + 0 Success + >0 Failure +*/ + +int packfrm(uchar *data, size_t len, + uchar **pack_data, size_t *pack_len) +{ + int error; + size_t org_len, comp_len, blob_len; + uchar *blob; + DBUG_ENTER("packfrm"); + DBUG_PRINT("enter", ("data: 0x%lx len: %lu", (long) data, (ulong) len)); + + error= 1; + org_len= len; + if (my_compress((uchar*)data, &org_len, &comp_len)) + goto err; + + DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", (ulong) org_len, + (ulong) comp_len)); + DBUG_DUMP("compressed", data, org_len); + + error= 2; + blob_len= BLOB_HEADER + org_len; + if (!(blob= (uchar*) my_malloc(blob_len,MYF(MY_WME)))) + goto err; + + /* Store compressed blob in machine independent format */ + int4store(blob, 1); + int4store(blob+4, (uint32) len); + int4store(blob+8, (uint32) org_len); /* compressed length */ + + /* Copy frm data into blob, already in machine independent format */ + memcpy(blob+BLOB_HEADER, data, org_len); + + *pack_data= blob; + *pack_len= blob_len; + error= 0; + + DBUG_PRINT("exit", ("pack_data: 0x%lx pack_len: %lu", + (long) *pack_data, (ulong) *pack_len)); +err: + DBUG_RETURN(error); + +} + +/* + unpackfrm is a method used to decompress the frm file received from a + handler. This method was developed for the NDB handler and has been moved + here to serve also other uses for other clustered storage engines. + + SYNOPSIS + unpackfrm() + pack_data Data reference to packed frm file data + out:unpack_data Reference to the pointer to the unpacked frm data + out:unpack_len Length of unpacked frm file data + + RETURN VALUES¨ + 0 Success + >0 Failure +*/ + +int unpackfrm(uchar **unpack_data, size_t *unpack_len, + const uchar *pack_data) +{ + uchar *data; + size_t complen, orglen; + ulong ver; + DBUG_ENTER("unpackfrm"); + DBUG_PRINT("enter", ("pack_data: 0x%lx", (long) pack_data)); + + ver= uint4korr(pack_data); + orglen= uint4korr(pack_data+4); + complen= uint4korr(pack_data+8); + + DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu", + ver, (ulong) complen, (ulong) orglen)); + DBUG_DUMP("blob->data", pack_data + BLOB_HEADER, complen); + + if (ver != 1) + DBUG_RETURN(1); + if (!(data= my_malloc(max(orglen, complen), MYF(MY_WME)))) + DBUG_RETURN(2); + memcpy(data, pack_data + BLOB_HEADER, complen); + + if (my_uncompress(data, complen, &orglen)) + { + my_free(data, MYF(0)); + DBUG_RETURN(3); + } + + *unpack_data= data; + *unpack_len= orglen; + + DBUG_PRINT("exit", ("frmdata: 0x%lx len: %lu", (long) *unpack_data, + (ulong) *unpack_len)); + DBUG_RETURN(0); +} #endif /* HAVE_COMPRESS */ diff --git a/mysys/my_conio.c b/mysys/my_conio.c index def15674f26..5dbd31193a9 100644 --- a/mysys/my_conio.c +++ b/mysys/my_conio.c @@ -29,10 +29,10 @@ static HANDLE my_coninpfh= 0; /* console input */ if found useful they are to be exported in mysys */ + /* int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time) - NOTES creates a mutex with given name and tries to lock it time msec. mutex name is appended with id to allow system wide or process wide @@ -41,8 +41,8 @@ static HANDLE my_coninpfh= 0; /* console input */ RETURN 0 thread owns mutex <>0 error - */ + static int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time) { @@ -69,7 +69,6 @@ int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time) /* int my_pthread_auto_mutex_free(HANDLE* ph) - NOTES releases a mutex. @@ -103,7 +102,7 @@ int my_pthread_auto_mutex_free(HANDLE* ph) /* - char* my_cgets(char *string, unsigned long clen, unsigned long* plen) + char* my_cgets() NOTES Replaces _cgets from libc to support input of more than 255 chars. @@ -121,10 +120,12 @@ int my_pthread_auto_mutex_free(HANDLE* ph) NULL Error */ -char* my_cgets(char *buffer, unsigned long clen, unsigned long* plen) + +char* my_cgets(char *buffer, size_t clen, size_t* plen) { ULONG state; char *result; + DWORD plen_res; CONSOLE_SCREEN_BUFFER_INFO csbi; pthread_auto_mutex_decl(my_conio_cs); @@ -170,8 +171,9 @@ char* my_cgets(char *buffer, unsigned long clen, unsigned long* plen) clen= min(clen, 65535); do { - clen= min(clen, (unsigned long)csbi.dwSize.X*csbi.dwSize.Y); - if (!ReadConsole((HANDLE)my_coninpfh, (LPVOID)buffer, clen - 1, plen, NULL)) + clen= min(clen, (size_t) csbi.dwSize.X*csbi.dwSize.Y); + if (!ReadConsole((HANDLE)my_coninpfh, (LPVOID)buffer, (DWORD) clen - 1, &plen_res, + NULL)) { result= NULL; clen>>= 1; @@ -183,6 +185,7 @@ char* my_cgets(char *buffer, unsigned long clen, unsigned long* plen) } } while (GetLastError() == ERROR_NOT_ENOUGH_MEMORY); + *plen= plen_res; /* We go here on error reading the string (Ctrl-C for example) */ if (!*plen) diff --git a/mysys/my_copy.c b/mysys/my_copy.c index a98fe1302f0..8058c22a9d5 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000-2003, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,12 +12,13 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <my_dir.h> /* for stat */ #include <m_string.h> +#include "mysys_err.h" #if defined(HAVE_UTIME_H) #include <utime.h> #elif defined(HAVE_SYS_UTIME_H) @@ -52,13 +53,12 @@ struct utimbuf { int my_copy(const char *from, const char *to, myf MyFlags) { - uint Count; + size_t Count; my_bool new_file_stat= 0; /* 1 if we could stat "to" */ int create_flag; File from_file,to_file; - char buff[IO_SIZE]; + uchar buff[IO_SIZE]; MY_STAT stat_buff,new_stat_buff; - int res; DBUG_ENTER("my_copy"); DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); @@ -83,10 +83,12 @@ int my_copy(const char *from, const char *to, myf MyFlags) MyFlags)) < 0) goto err; - while ((Count=my_read(from_file,buff,IO_SIZE,MyFlags)) != 0) + while ((Count=my_read(from_file, buff, sizeof(buff), MyFlags)) != 0) + { if (Count == (uint) -1 || my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP))) goto err; + } /* sync the destination file */ if (MyFlags & MY_SYNC) @@ -102,9 +104,23 @@ int my_copy(const char *from, const char *to, myf MyFlags) if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) DBUG_RETURN(0); /* File copyed but not stat */ - res= chmod(to, stat_buff.st_mode & 07777); /* Copy modes */ -#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) - res= chown(to, stat_buff.st_uid,stat_buff.st_gid); /* Copy ownership */ + /* Copy modes */ + if (chmod(to, stat_buff.st_mode & 07777)) + { + my_errno= errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), from, errno); + goto err; + } +#if !defined(__WIN__) && !defined(__NETWARE__) + /* Copy ownership */ + if (chown(to, stat_buff.st_uid,stat_buff.st_gid)) + { + my_errno= errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), from, errno); + goto err; + } #endif #if !defined(VMS) && !defined(__ZTC__) if (MyFlags & MY_COPYTIME) diff --git a/mysys/my_create.c b/mysys/my_create.c index c535ae73a0a..5c9a1e027d2 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -13,12 +13,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include <my_dir.h> #include "mysys_err.h" #include <errno.h> -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#include <my_sys.h> +#if defined(__WIN__) #include <share.h> #endif @@ -40,26 +40,26 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", FileName, CreateFlags, access_flags, MyFlags)); -#if !defined(NO_OPEN_3) && !defined(__EMX__) - fd = open((my_string) FileName, access_flags | O_CREAT, +#if !defined(NO_OPEN_3) + fd = open((char *) FileName, access_flags | O_CREAT, CreateFlags ? CreateFlags : my_umask); #elif defined(VMS) - fd = open((my_string) FileName, access_flags | O_CREAT, 0, + fd = open((char *) FileName, access_flags | O_CREAT, 0, "ctx=stm","ctx=bin"); -#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) - if (access_flags & O_SHARE) - fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, - SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); - else - fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY, - MY_S_IREAD | MY_S_IWRITE); #elif defined(__WIN__) - fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, + fd= my_sopen((char *) FileName, access_flags | O_CREAT | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); #else fd = open(FileName, access_flags); #endif + if ((MyFlags & MY_SYNC_DIR) && (fd >=0) && + my_sync_dir_by_file(FileName, MyFlags)) + { + my_close(fd, MyFlags); + fd= -1; + } + rc= my_register_filename(fd, FileName, FILE_BY_CREATE, EE_CANTCREATEFILE, MyFlags); /* diff --git a/mysys/my_delete.c b/mysys/my_delete.c index bac3e2513e1..22425ed95fd 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -15,6 +15,7 @@ #include "mysys_priv.h" #include "mysys_err.h" +#include <my_sys.h> int my_delete(const char *name, myf MyFlags) { @@ -29,6 +30,9 @@ int my_delete(const char *name, myf MyFlags) my_error(EE_DELETE,MYF(ME_BELL+ME_WAITTANG+(MyFlags & ME_NOINPUT)), name,errno); } + else if ((MyFlags & MY_SYNC_DIR) && + my_sync_dir_by_file(name, MyFlags)) + err= -1; DBUG_RETURN(err); } /* my_delete */ @@ -56,16 +60,20 @@ int nt_share_delete(const char *name, myf MyFlags) ulong cnt; DBUG_ENTER("nt_share_delete"); DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags)); - + for (cnt= GetTickCount(); cnt; cnt--) { sprintf(buf, "%s.%08X.deleted", name, cnt); if (MoveFile(name, buf)) break; - + if ((errno= GetLastError()) == ERROR_ALREADY_EXISTS) continue; - + + /* This happened during tests with MERGE tables. */ + if (errno == ERROR_ACCESS_DENIED) + continue; + DBUG_PRINT("warning", ("Failed to rename %s to %s, errno: %d", name, buf, errno)); break; diff --git a/mysys/my_div.c b/mysys/my_div.c index 656c6cfde91..d29d3668852 100644 --- a/mysys/my_div.c +++ b/mysys/my_div.c @@ -23,7 +23,7 @@ fd File descriptor */ -my_string my_filename(File fd) +char * my_filename(File fd) { DBUG_ENTER("my_filename"); if ((uint) fd >= (uint) my_file_limit) diff --git a/mysys/my_dup.c b/mysys/my_dup.c index 2c6a42726e4..55f5e0c0099 100644 --- a/mysys/my_dup.c +++ b/mysys/my_dup.c @@ -13,12 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include "mysys_err.h" #include <my_dir.h> #include <errno.h> -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) +#if defined(__WIN__) #include <share.h> #endif diff --git a/mysys/my_error.c b/mysys/my_error.c index 836f851322b..20d8438a712 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -1,4 +1,6 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. 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 @@ -11,7 +13,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -19,6 +22,10 @@ #include <stdarg.h> #include <m_ctype.h> +/* 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 */ /* @@ -30,8 +37,6 @@ my_printf_error(ER_CODE, format, MYF(N), ...) */ -char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE]; - /* Message texts are registered into a linked list of 'my_err_head' structs. Each struct contains (1.) an array of pointers to C character strings with @@ -52,8 +57,10 @@ static struct my_err_head 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}; + static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; + /* Error message to user @@ -73,9 +80,8 @@ int my_error(int nr, myf MyFlags, ...) const char *format; struct my_err_head *meh_p; va_list args; - char ebuff[ERRMSGSIZE + 20]; + char ebuff[ERRMSGSIZE]; DBUG_ENTER("my_error"); - DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno)); /* Search for the error messages array, which could contain the message. */ @@ -83,11 +89,6 @@ int my_error(int nr, myf MyFlags, ...) if (nr <= meh_p->meh_last) break; -#ifdef SHARED_LIBRARY - if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0]) - init_glob_errs(); -#endif - /* 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) @@ -101,6 +102,7 @@ int my_error(int nr, myf MyFlags, ...) DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags)); } + /* Error as printf @@ -115,7 +117,7 @@ int my_error(int nr, myf MyFlags, ...) int my_printf_error(uint error, const char *format, myf MyFlags, ...) { va_list args; - char ebuff[ERRMSGSIZE+20]; + char ebuff[ERRMSGSIZE]; DBUG_ENTER("my_printf_error"); DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s", error, MyFlags, errno, format)); @@ -189,7 +191,7 @@ int my_error_register(const char **errmsgs, int first, int last) /* Error numbers must be unique. No overlapping is allowed. */ if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) { - my_free((gptr)meh_p, MYF(0)); + my_free((uchar*)meh_p, MYF(0)); return 1; } @@ -245,7 +247,24 @@ const char **my_error_unregister(int first, int last) /* Save the return value and free the header. */ errmsgs= meh_p->meh_errmsgs; - my_free((gptr) meh_p, MYF(0)); + my_free((uchar*) meh_p, MYF(0)); return errmsgs; } + + +void my_error_unregister_all(void) +{ + struct my_err_head *cursor, *saved_next; + + for (cursor= my_errmsgs_globerrs.meh_next; cursor != NULL; cursor= saved_next) + { + /* We need this ptr, but we're about to free its container, so save it. */ + saved_next= cursor->meh_next; + + my_free((uchar*) cursor, MYF(0)); + } + my_errmsgs_globerrs.meh_next= NULL; /* Freed in first iteration above. */ + + my_errmsgs_list= &my_errmsgs_globerrs; +} diff --git a/mysys/my_file.c b/mysys/my_file.c index c97a512f8a1..f8e0c9e7bad 100644 --- a/mysys/my_file.c +++ b/mysys/my_file.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "my_static.h" @@ -32,7 +34,7 @@ May be more or less than max_file_limit! */ -#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) && !defined(HAVE_mit_thread) +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) #ifndef RLIM_INFINITY #define RLIM_INFINITY ((uint) 0xffffffff) @@ -71,27 +73,8 @@ static uint set_max_open_files(uint max_file_limit) DBUG_RETURN(max_file_limit); } -#elif defined (OS2) - -static uint set_max_open_files(uint max_file_limit) -{ - LONG cbReqCount; - ULONG cbCurMaxFH0; - APIRET ulrc; - DBUG_ENTER("set_max_open_files"); - - /* get current limit */ - cbReqCount = 0; - DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH0); - - /* set new limit */ - if ((cbReqCount = max_file_limit - cbCurMaxFH0) > 0) - ulrc = DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH); - DBUG_RETURN(cbCurMaxFH0); -} - #else -static int set_max_open_files(uint max_file_limit) +static uint set_max_open_files(uint max_file_limit) { /* We don't know the limit. Return best guess */ return min(max_file_limit, OS_FILE_LIMIT); @@ -125,7 +108,10 @@ uint my_set_max_open_files(uint files) DBUG_RETURN(MY_NFILE); /* Copy any initialized files */ - memcpy((char*) tmp, (char*) my_file_info, sizeof(*tmp) * my_file_limit); + memcpy((char*) tmp, (char*) my_file_info, + sizeof(*tmp) * min(my_file_limit, files)); + bzero((char*) (tmp + my_file_limit), + max((int) (files- my_file_limit), 0)*sizeof(*tmp)); my_free_open_file_info(); /* Free if already allocated */ my_file_info= tmp; my_file_limit= files; @@ -139,8 +125,12 @@ void my_free_open_file_info() DBUG_ENTER("my_free_file_info"); if (my_file_info != my_file_info_default) { + /* Copy data back for my_print_open_files */ + memcpy((char*) my_file_info_default, my_file_info, + sizeof(*my_file_info_default)* MY_NFILE); my_free((char*) my_file_info, MYF(0)); my_file_info= my_file_info_default; + my_file_limit= MY_NFILE; } DBUG_VOID_RETURN; } diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index b56be263ba4..72991490d75 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -18,7 +18,11 @@ #include <errno.h> #include "mysys_err.h" -static void make_ftype(my_string to,int flag); +#if defined(__FreeBSD__) +extern int getosreldate(void); +#endif + +static void make_ftype(char * to,int flag); /* Open a file as stream @@ -76,6 +80,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) my_strdup(filename,MyFlags))) { my_stream_opened++; + my_file_total_opened++; my_file_info[fileno(fd)].type = STREAM_BY_FOPEN; pthread_mutex_unlock(&THR_LOCK_open); DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); @@ -96,8 +101,137 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) } /* my_fopen */ - /* Close a stream */ +#if defined(_WIN32) + +static FILE *my_win_freopen(const char *path, const char *mode, FILE *stream) +{ + int handle_fd, fd= _fileno(stream); + HANDLE osfh; + + DBUG_ASSERT(path && stream); + + /* Services don't have stdout/stderr on Windows, so _fileno returns -1. */ + if (fd < 0) + { + if (!freopen(path, mode, stream)) + return NULL; + + fd= _fileno(stream); + } + + if ((osfh= CreateFile(path, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, + OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, + NULL)) == INVALID_HANDLE_VALUE) + return NULL; + + if ((handle_fd= _open_osfhandle((intptr_t)osfh, + _O_APPEND | _O_TEXT)) == -1) + { + CloseHandle(osfh); + return NULL; + } + + if (_dup2(handle_fd, fd) < 0) + { + CloseHandle(osfh); + return NULL; + } + + _close(handle_fd); + + return stream; +} + +#elif defined(__FreeBSD__) + +/* No close operation hook. */ + +static int no_close(void *cookie __attribute__((unused))) +{ + return 0; +} + +/* + A hack around a race condition in the implementation of freopen. + + The race condition steams from the fact that the current fd of + the stream is closed before its number is used to duplicate the + new file descriptor. This defeats the desired atomicity of the + close and duplicate of dup2(). + + See PR number 79887 for reference: + http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 +*/ + +static FILE *my_freebsd_freopen(const char *path, const char *mode, FILE *stream) +{ + int old_fd; + FILE *result; + + flockfile(stream); + + old_fd= fileno(stream); + + /* Use a no operation close hook to avoid having the fd closed. */ + stream->_close= no_close; + + /* Relies on the implicit dup2 to close old_fd. */ + result= freopen(path, mode, stream); + + /* If successful, the _close hook was replaced. */ + + if (result == NULL) + close(old_fd); + else + funlockfile(result); + + return result; +} + +#endif + + +/** + Change the file associated with a file stream. + + @param path Path to file. + @param mode Mode of the stream. + @param stream File stream. + + @note + This function is used to redirect stdout and stderr to a file and + subsequently to close and reopen that file for log rotation. + + @retval A FILE pointer on success. Otherwise, NULL. +*/ + +FILE *my_freopen(const char *path, const char *mode, FILE *stream) +{ + FILE *result; + +#if defined(_WIN32) + result= my_win_freopen(path, mode, stream); +#elif defined(__FreeBSD__) + /* + XXX: Once the fix is ported to the stable releases, this should + be dependent upon the specific FreeBSD versions. Check at: + http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 + */ + if (getosreldate() > 900027) + result= freopen(path, mode, stream); + else + result= my_freebsd_freopen(path, mode, stream); +#else + result= freopen(path, mode, stream); +#endif + + return result; +} + +/* Close a stream */ int my_fclose(FILE *fd, myf MyFlags) { int err,file; @@ -192,7 +326,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) a+ == O_RDWR|O_APPEND|O_CREAT */ -static void make_ftype(register my_string to, register int flag) +static void make_ftype(register char * to, register int flag) { /* check some possible invalid combinations */ DBUG_ASSERT((flag & (O_TRUNC | O_APPEND)) != (O_TRUNC | O_APPEND)); diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index 718e9bc0a28..929a59db9cd 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2001, 2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2001, 2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* USE_MY_STREAM isn't set because we can't thrust my_fclose! */ @@ -28,24 +30,31 @@ #define fseek(A,B,C) fseeko((A),(B),(C)) #endif - /* Read a chunk of bytes from a file */ - /* Returns (uint) -1 if error as my_read() */ +/* + Read a chunk of bytes from a FILE + + SYNOPSIS + my_fread() + stream File descriptor + Buffer Buffer to read to + Count Number of bytes to read + MyFlags Flags on what to do on error -uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags) - /* File descriptor */ - /* Buffer must be at least count bytes */ - /* Max number of bytes returnd */ - /* Flags on what to do on error */ + RETURN + (size_t) -1 Error + # Number of bytes read + */ + +size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags) { - uint readbytes; + size_t readbytes; DBUG_ENTER("my_fread"); DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d", - (long) stream, (long) Buffer, Count, MyFlags)); + (long) stream, (long) Buffer, (uint) Count, MyFlags)); - if ((readbytes = (uint) fread(Buffer,sizeof(char),(size_t) Count,stream)) - != Count) + if ((readbytes= fread(Buffer, sizeof(char), Count, stream)) != Count) { - DBUG_PRINT("error",("Read only %d bytes",readbytes)); + DBUG_PRINT("error",("Read only %d bytes", (int) readbytes)); if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { if (ferror(stream)) @@ -58,7 +67,7 @@ uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags) } my_errno=errno ? errno : -1; if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN((uint) -1); /* Return with error */ + DBUG_RETURN((size_t) -1); /* Return with error */ } if (MyFlags & (MY_NABP | MY_FNABP)) DBUG_RETURN(0); /* Read ok */ @@ -67,40 +76,48 @@ uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags) /* -** Write a chunk of bytes to a stream -** Returns (uint) -1 if error as my_write() -** Does retries if interrupted + Write a chunk of bytes to a stream + + my_fwrite() + stream File descriptor + Buffer Buffer to write from + Count Number of bytes to write + MyFlags Flags on what to do on error + + RETURN + (size_t) -1 Error + # Number of bytes written */ -uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags) +size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) { - uint writenbytes=0; - off_t seekptr; + size_t writtenbytes =0; + my_off_t seekptr; #if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) uint errors; #endif DBUG_ENTER("my_fwrite"); DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d", - (long) stream, (long) Buffer, Count, MyFlags)); + (long) stream, (long) Buffer, (uint) Count, MyFlags)); #if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) errors=0; #endif - seekptr=ftell(stream); + seekptr= ftell(stream); for (;;) { - uint writen; - if ((writen = (uint) fwrite((char*) Buffer,sizeof(char), - (size_t) Count, stream)) != Count) + size_t written; + if ((written = (size_t) fwrite((char*) Buffer,sizeof(char), + Count, stream)) != Count) { - DBUG_PRINT("error",("Write only %d bytes",writenbytes)); + DBUG_PRINT("error",("Write only %d bytes", (int) writtenbytes)); my_errno=errno; - if (writen != (uint) -1) + if (written != (size_t) -1) { - seekptr+=writen; - Buffer+=writen; - writenbytes+=writen; - Count-=writen; + seekptr+=written; + Buffer+=written; + writtenbytes+=written; + Count-=written; } #ifdef EINTR if (errno == EINTR) @@ -130,21 +147,21 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags) my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), my_filename(fileno(stream)),errno); } - writenbytes=(uint) -1; /* Return that we got error */ + writtenbytes= (size_t) -1; /* Return that we got error */ break; } } if (MyFlags & (MY_NABP | MY_FNABP)) - writenbytes=0; /* Everything OK */ + writtenbytes= 0; /* Everything OK */ else - writenbytes+=writen; + writtenbytes+= written; break; } - DBUG_RETURN(writenbytes); + DBUG_RETURN(writtenbytes); } /* my_fwrite */ - /* Seek to position in file */ - /* ARGSUSED */ + +/* Seek to position in file */ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, myf MyFlags __attribute__((unused))) @@ -157,8 +174,7 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, } /* my_seek */ - /* Tell current position of file */ - /* ARGSUSED */ +/* Tell current position of file */ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused))) { diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index 01abc02058b..6e49169a0b8 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2004 MySQL AB +/* + Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* get hardware address for an interface */ /* if there are many available, any non-zero one can be used */ @@ -20,15 +22,6 @@ #include <m_string.h> #ifndef MAIN -static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) -{ - uint i, res=1; - - for (i=0; i < len; i++) - if ((*to++= *from++)) - res=0; - return res; -} #ifdef __FreeBSD__ @@ -41,10 +34,11 @@ static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) my_bool my_gethwaddr(uchar *to) { size_t len; - uchar *buf, *next, *end, *addr; + char *buf, *next, *end; struct if_msghdr *ifm; struct sockaddr_dl *sdl; - int i, res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; + int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; + char zero_array[ETHER_ADDR_LEN] = {0}; if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) goto err; @@ -60,9 +54,9 @@ my_bool my_gethwaddr(uchar *to) ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_IFINFO) { - sdl = (struct sockaddr_dl *)(ifm + 1); - addr=LLADDR(sdl); - res=memcpy_and_test(to, addr, ETHER_ADDR_LEN); + sdl= (struct sockaddr_dl *)(ifm + 1); + memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN); + res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; } } @@ -78,8 +72,9 @@ err: my_bool my_gethwaddr(uchar *to) { - int fd, res=1; + int fd, res= 1; struct ifreq ifr; + char zero_array[ETHER_ADDR_LEN] = {0}; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) @@ -88,9 +83,13 @@ my_bool my_gethwaddr(uchar *to) bzero(&ifr, sizeof(ifr)); strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1); - do { + do + { if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) - res=memcpy_and_test(to, (uchar *)&ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); + { + memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); + res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; + } } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6'); close(fd); @@ -98,7 +97,7 @@ err: return res; } -#else +#else /* FreeBSD elif linux */ /* just fail */ my_bool my_gethwaddr(uchar *to __attribute__((unused))) { diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c new file mode 100644 index 00000000000..d8a3069bce4 --- /dev/null +++ b/mysys/my_getncpus.c @@ -0,0 +1,42 @@ +/* + Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* get the number of (online) CPUs */ + +#include "mysys_priv.h" +#include <unistd.h> + +#ifdef _SC_NPROCESSORS_ONLN + +static int ncpus=0; + +int my_getncpus() +{ + if (!ncpus) + ncpus= sysconf(_SC_NPROCESSORS_ONLN); + return ncpus; +} + +#else +/* unknown */ +int my_getncpus() +{ + return 2; +} + +#endif + diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 1a26dc56483..a1669110219 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2002-2007 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include <my_global.h> #include <m_string.h> @@ -21,22 +22,31 @@ #include <mysys_err.h> #include <my_getopt.h> #include <errno.h> +#include <m_string.h> + +typedef void (*init_func_p)(const struct my_option *option, void *variable, + longlong value); static void default_reporter(enum loglevel level, const char *format, ...); my_error_reporter my_getopt_error_reporter= &default_reporter; static int findopt(char *optpat, uint length, const struct my_option **opt_res, - char **ffname); + const char **ffname); my_bool getopt_compare_strings(const char *s, const char *t, uint length); static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); -static longlong getopt_ll_limit_value(longlong, const struct my_option *); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); -static void init_variables(const struct my_option *options); -static int setval(const struct my_option *opts, gptr *value, char *argument, +static double getopt_double(char *arg, const struct my_option *optp, int *err); +static void init_variables(const struct my_option *options, + init_func_p init_one_value); +static void init_one_value(const struct my_option *option, void *variable, + longlong value); +static void fini_one_value(const struct my_option *option, void *variable, + longlong value); +static int setval(const struct my_option *opts, void *value, char *argument, my_bool set_maximum_value); static char *check_struct_option(char *cur_arg, char *key_name); @@ -61,6 +71,13 @@ char *disabled_my_option= (char*) "0"; my_bool my_getopt_print_errors= 1; +/* + This is a flag that can be set in client programs. 1 means that + my_getopt will skip over options it does not know how to handle. +*/ + +my_bool my_getopt_skip_unknown= 0; + static void default_reporter(enum loglevel level, const char *format, ...) { @@ -86,10 +103,9 @@ static void default_reporter(enum loglevel level, one. Call function 'get_one_option()' once for each option. */ -static gptr* (*getopt_get_addr)(const char *, uint, const struct my_option *); +static my_getopt_value getopt_get_addr; -void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint, - const struct my_option *)) +void my_getopt_register_get_addr(my_getopt_value func_addr) { getopt_get_addr= func_addr; } @@ -98,22 +114,25 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_get_one_option get_one_option) { - uint opt_found, argvpos= 0, length, i; + uint UNINIT_VAR(opt_found), argvpos= 0, length; my_bool end_of_options= 0, must_be_var, set_maximum_value, option_is_loose; - char **pos, **pos_end, *optend, *UNINIT_VAR(prev_found), - *opt_str, key_name[FN_REFLEN]; + char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN]; + const char *UNINIT_VAR(prev_found); const struct my_option *optp; - gptr *value; - int error; + void *value; + int error, i; - LINT_INIT(opt_found); + /* handle_options() assumes arg0 (program name) always exists */ + DBUG_ASSERT(argc && *argc >= 1); + DBUG_ASSERT(argv && *argv); (*argc)--; /* Skip the program name */ (*argv)++; /* --- || ---- */ - init_variables(longopts); + init_variables(longopts, init_one_value); for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { + char **first= pos; char *cur_arg= *pos; if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ { @@ -127,6 +146,10 @@ int handle_options(int *argc, char ***argv, { /* --set-variable, or -O */ if (*cur_arg == 'O') { + my_getopt_error_reporter(WARNING_LEVEL, + "%s: Option '-O' is deprecated. " + "Use --variable-name=value instead.", + my_progname); must_be_var= 1; if (!(*++cur_arg)) /* If not -Ovar=# */ @@ -146,6 +169,11 @@ int handle_options(int *argc, char ***argv, } else if (!getopt_compare_strings(cur_arg, "-set-variable", 13)) { + my_getopt_error_reporter(WARNING_LEVEL, + "%s: Option '--set-variable' is deprecated. " + "Use --variable-name=value instead.", + my_progname); + must_be_var= 1; if (cur_arg[13] == '=') { @@ -198,7 +226,6 @@ int handle_options(int *argc, char ***argv, Find first the right option. Return error in case of an ambiguous, or unknown option */ - LINT_INIT(prev_found); optp= longopts; if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) { @@ -220,12 +247,11 @@ int handle_options(int *argc, char ***argv, /* We were called with a special prefix, we can reuse opt_found */ - opt_str+= (special_opt_prefix_lengths[i] + 1); + opt_str+= special_opt_prefix_lengths[i] + 1; + length-= special_opt_prefix_lengths[i] + 1; if (i == OPT_LOOSE) option_is_loose= 1; - if ((opt_found= findopt(opt_str, length - - (special_opt_prefix_lengths[i] + 1), - &optp, &prev_found))) + if ((opt_found= findopt(opt_str, length, &optp, &prev_found))) { if (opt_found > 1) { @@ -249,7 +275,7 @@ int handle_options(int *argc, char ***argv, break; case OPT_ENABLE: optend= (optend && *optend == '0' && !(*(optend + 1))) ? - disabled_my_option : (char*) "1"; + disabled_my_option : (char*) "1"; break; case OPT_MAXIMUM: set_maximum_value= 1; @@ -258,11 +284,25 @@ int handle_options(int *argc, char ***argv, } break; /* break from the inner loop, main loop continues */ } + i= -1; /* restart the loop */ } } } if (!opt_found) { + if (my_getopt_skip_unknown) + { + /* + preserve all the components of this unknown option, this may + occurr when the user provides options like: "-O foo" or + "--set-variable foo" (note that theres a space in there) + Generally, these kind of options are to be avoided + */ + do { + (*argv)[argvpos++]= *first++; + } while (first <= pos); + continue; + } if (must_be_var) { if (my_getopt_print_errors) @@ -276,9 +316,9 @@ int handle_options(int *argc, char ***argv, else { if (my_getopt_print_errors) - my_getopt_error_reporter(option_is_loose ? + my_getopt_error_reporter(option_is_loose ? WARNING_LEVEL : ERROR_LEVEL, - "%s: unknown option '--%s'", + "%s: unknown option '--%s'", my_progname, cur_arg); if (!option_is_loose) return EXIT_UNKNOWN_OPTION; @@ -331,9 +371,13 @@ int handle_options(int *argc, char ***argv, my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } + error= 0; value= optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp) : optp->value; - + (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : + optp->value; + if (error) + return error; + if (optp->arg_type == NO_ARG) { if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) @@ -361,31 +405,33 @@ int handle_options(int *argc, char ***argv, else { my_getopt_error_reporter(WARNING_LEVEL, - "%s: ignoring option '--%s' due to \ -invalid value '%s'", + "%s: ignoring option '--%s' due to " + "invalid value '%s'", my_progname, optp->name, optend); continue; } - get_one_option(optp->id, optp, - *((my_bool*) value) ? - (char*) "1" : disabled_my_option); + if (get_one_option(optp->id, optp, + *((my_bool*) value) ? + (char*) "1" : disabled_my_option)) + return EXIT_ARGUMENT_INVALID; continue; } argument= optend; } else if (optp->arg_type == OPT_ARG && - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) - { - if (optend == disabled_my_option) - *((my_bool*) value)= (my_bool) 0; - else - { - if (!optend) /* No argument -> enable option */ - *((my_bool*) value)= (my_bool) 1; - else - argument= optend; - } - } + (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) || + (optp->var_type & GET_TYPE_MASK) == GET_ENUM)) + { + if (optend == disabled_my_option) + init_one_value(optp, value, 0); + else + { + if (!optend) /* No argument -> enable option */ + init_one_value(optp, value, 1); + else + argument= optend; + } + } else if (optp->arg_type == REQUIRED_ARG && !optend) { /* Check if there are more arguments after this one */ @@ -426,7 +472,8 @@ invalid value '%s'", optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; continue; } else if (optp->arg_type == REQUIRED_ARG || @@ -445,7 +492,8 @@ invalid value '%s'", { if (optp->var_type == GET_BOOL) *((my_bool*) optp->value)= (my_bool) 1; - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; continue; } /* Check if there are more arguments after this one */ @@ -470,7 +518,8 @@ invalid value '%s'", my_progname, argument, optp->name); return error; } - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; break; } } @@ -478,7 +527,7 @@ invalid value '%s'", { if (my_getopt_print_errors) my_getopt_error_reporter(ERROR_LEVEL, - "%s: unknown option '-%c'", + "%s: unknown option '-%c'", my_progname, *optend); return EXIT_UNKNOWN_OPTION; } @@ -493,7 +542,8 @@ invalid value '%s'", my_progname, argument, optp->name); return error; } - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; (*argc)--; /* option handled (short or long), decrease argument count */ } @@ -560,15 +610,14 @@ static char *check_struct_option(char *cur_arg, char *key_name) Will set the option value to given value */ -static int setval(const struct my_option *opts, gptr *value, char *argument, +static int setval(const struct my_option *opts, void *value, char *argument, my_bool set_maximum_value) { int err= 0; if (value && argument) { - gptr *result_pos= ((set_maximum_value) ? - opts->u_max_value : value); + void *result_pos= ((set_maximum_value) ? opts->u_max_value : value); if (!result_pos) return EXIT_NO_PTR_TO_VARIABLE; @@ -595,6 +644,9 @@ static int setval(const struct my_option *opts, gptr *value, char *argument, case GET_ULL: *((ulonglong*) result_pos)= getopt_ull(argument, opts, &err); break; + case GET_DOUBLE: + *((double*) result_pos)= getopt_double(argument, opts, &err); + break; case GET_STR: *((char**) result_pos)= argument; break; @@ -604,6 +656,29 @@ static int setval(const struct my_option *opts, gptr *value, char *argument, if (!(*((char**) result_pos)= my_strdup(argument, MYF(MY_WME)))) return EXIT_OUT_OF_MEMORY; break; + case GET_ENUM: + { + int type= find_type(argument, opts->typelib, 2); + if (type < 1) + { + /* + Accept an integer representation of the enumerated item. + */ + char *endptr; + ulong arg= strtoul(argument, &endptr, 10); + if (*endptr || arg >= opts->typelib->count) + return EXIT_ARGUMENT_INVALID; + *((ulong*) result_pos)= arg; + } + else + *((ulong*) result_pos)= type - 1; + } + break; + case GET_SET: + *((ulonglong*)result_pos)= find_typeset(argument, opts->typelib, &err); + if (err) + return EXIT_ARGUMENT_INVALID; + break; default: /* dummy default to avoid compiler warnings */ break; } @@ -638,10 +713,10 @@ static int setval(const struct my_option *opts, gptr *value, char *argument, static int findopt(char *optpat, uint length, const struct my_option **opt_res, - char **ffname) + const char **ffname) { uint count; - struct my_option *opt= (struct my_option *) *opt_res; + const struct my_option *opt= *opt_res; for (count= 0; opt->name; opt++) { @@ -652,8 +727,9 @@ static int findopt(char *optpat, uint length, return 1; if (!count) { + /* We only need to know one prev */ count= 1; - *ffname= (char *) opt->name; /* We only need to know one prev */ + *ffname= opt->name; } else if (strcmp(*ffname, opt->name)) { @@ -695,7 +771,7 @@ my_bool getopt_compare_strings(register const char *s, register const char *t, be k|K for kilo, m|M for mega or g|G for giga. */ -static longlong eval_num_suffix (char *argument, int *error, char *option_name) +static longlong eval_num_suffix(char *argument, int *error, char *option_name) { char *endchar; longlong num; @@ -741,7 +817,7 @@ static longlong eval_num_suffix (char *argument, int *error, char *option_name) static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) { longlong num=eval_num_suffix(arg, err, (char*) optp->name); - return getopt_ll_limit_value(num, optp); + return getopt_ll_limit_value(num, optp, NULL); } /* @@ -751,11 +827,11 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) Returns "fixed" value. */ -static longlong getopt_ll_limit_value(longlong num, - const struct my_option *optp) +longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, + my_bool *fix) { longlong old= num; - bool trunc= FALSE; + my_bool adjusted= FALSE; char buf1[255], buf2[255]; ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L); @@ -763,7 +839,29 @@ static longlong getopt_ll_limit_value(longlong num, optp->max_value) /* if max value is not set -> no upper limit */ { num= (ulonglong) optp->max_value; - trunc= TRUE; + adjusted= TRUE; + } + + switch ((optp->var_type & GET_TYPE_MASK)) { + case GET_INT: + if (num > (longlong) INT_MAX) + { + num= ((longlong) INT_MAX); + adjusted= TRUE; + } + break; + case GET_LONG: +#if SIZEOF_LONG < SIZEOF_LONG_LONG + if (num > (longlong) LONG_MAX) + { + num= ((longlong) LONG_MAX); + adjusted= TRUE; + } +#endif + break; + default: + DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_LL); + break; } num= ((num - optp->sub_size) / block_size); @@ -772,10 +870,13 @@ static longlong getopt_ll_limit_value(longlong num, if (num < optp->min_value) { num= optp->min_value; - trunc= TRUE; + if (old < optp->min_value) + adjusted= TRUE; } - if (trunc) + if (fix) + *fix= adjusted; + else if (adjusted) my_getopt_error_reporter(WARNING_LEVEL, "option '%s': signed value %s adjusted to %s", optp->name, llstr(old, buf1), llstr(num, buf2)); @@ -797,9 +898,9 @@ static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err) ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, - bool *fix) + my_bool *fix) { - bool adjusted= FALSE; + my_bool adjusted= FALSE; ulonglong old= num; char buf1[255], buf2[255]; @@ -841,66 +942,157 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, if (num < (ulonglong) optp->min_value) { num= (ulonglong) optp->min_value; - adjusted= TRUE; + if (old < (ulonglong) optp->min_value) + adjusted= TRUE; } - if (adjusted) + if (fix) + *fix= adjusted; + else if (adjusted) my_getopt_error_reporter(WARNING_LEVEL, "option '%s': unsigned value %s adjusted to %s", optp->name, ullstr(old, buf1), ullstr(num, buf2)); - if (fix) - *fix= adjusted; - return num; } /* + Get double value withing ranges + + Evaluates and returns the value that user gave as an argument to a variable. + + RETURN + decimal value of arg + + In case of an error, prints an error message and sets *err to + EXIT_ARGUMENT_INVALID. Otherwise err is not touched +*/ + +static double getopt_double(char *arg, const struct my_option *optp, int *err) +{ + double num; + int error; + char *end= arg + 1000; /* Big enough as *arg is \0 terminated */ + num= my_strtod(arg, &end, &error); + if (end[0] != 0 || error) + { + fprintf(stderr, + "%s: ERROR: Invalid decimal value for option '%s'\n", + my_progname, optp->name); + *err= EXIT_ARGUMENT_INVALID; + return 0.0; + } + if (optp->max_value && num > (double) optp->max_value) + num= (double) optp->max_value; + return max(num, (double) optp->min_value); +} + +/* Init one value to it's default values SYNOPSIS init_one_value() - optp Option to initialize - value Pointer to variable + option Option to initialize + value Pointer to variable */ -static void init_one_value(const struct my_option *optp, gptr *variable, +static void init_one_value(const struct my_option *option, void *variable, longlong value) { DBUG_ENTER("init_one_value"); - - switch ((optp->var_type & GET_TYPE_MASK)) { + switch ((option->var_type & GET_TYPE_MASK)) { case GET_BOOL: *((my_bool*) variable)= (my_bool) value; break; case GET_INT: - *((int*) variable)= (int) getopt_ll_limit_value(value, optp); + *((int*) variable)= (int) getopt_ll_limit_value((int) value, option, NULL); + break; + case GET_ENUM: + *((ulong*) variable)= (ulong) value; break; case GET_UINT: - *((uint*) variable)= (uint) getopt_ull_limit_value(value, optp, NULL); + *((uint*) variable)= (uint) getopt_ull_limit_value((uint) value, option, NULL); break; case GET_LONG: - *((long*) variable)= (long) getopt_ll_limit_value(value, optp); + *((long*) variable)= (long) getopt_ll_limit_value((long) value, option, NULL); break; case GET_ULONG: - *((ulong*) variable)= (ulong) getopt_ull_limit_value(value, optp, NULL); + *((ulong*) variable)= (ulong) getopt_ull_limit_value((ulong) value, option, NULL); break; case GET_LL: - *((longlong*) variable)= (longlong) getopt_ll_limit_value(value, optp); + *((longlong*) variable)= (longlong) getopt_ll_limit_value((longlong) value, option, NULL); break; case GET_ULL: - *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value(value, optp, - NULL); + *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL); + break; + case GET_SET: + *((ulonglong*) variable)= (ulonglong) value; + break; + case GET_DOUBLE: + *((double*) variable)= (double) value; + break; + case GET_STR: + /* + Do not clear variable value if it has no default value. + The default value may already be set. + NOTE: To avoid compiler warnings, we first cast longlong to intptr, + so that the value has the same size as a pointer. + */ + if ((char*) (intptr) value) + *((char**) variable)= (char*) (intptr) value; + break; + case GET_STR_ALLOC: + /* + Do not clear variable value if it has no default value. + The default value may already be set. + NOTE: To avoid compiler warnings, we first cast longlong to intptr, + so that the value has the same size as a pointer. + */ + if ((char*) (intptr) value) + { + my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR)); + *((char**) variable)= my_strdup((char*) (intptr) value, MYF(MY_WME)); + } break; default: /* dummy default to avoid compiler warnings */ break; } + DBUG_VOID_RETURN; +} + + +/* + Init one value to it's default values + SYNOPSIS + init_one_value() + option Option to initialize + value Pointer to variable +*/ + +static void fini_one_value(const struct my_option *option, void *variable, + longlong value __attribute__ ((unused))) +{ + DBUG_ENTER("fini_one_value"); + switch ((option->var_type & GET_TYPE_MASK)) { + case GET_STR_ALLOC: + my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR)); + *((char**) variable)= NULL; + break; + default: /* dummy default to avoid compiler warnings */ + break; + } DBUG_VOID_RETURN; } +void my_cleanup_options(const struct my_option *options) +{ + init_variables(options, fini_one_value); +} + + /* initialize all variables to their default values @@ -914,12 +1106,13 @@ static void init_one_value(const struct my_option *optp, gptr *variable, for a value and initialize. */ -static void init_variables(const struct my_option *options) +static void init_variables(const struct my_option *options, + init_func_p init_one_value) { DBUG_ENTER("init_variables"); for (; options->name; options++) { - gptr *variable; + void *variable; DBUG_PRINT("options", ("name: '%s'", options->name)); /* We must set u_max_value first as for some variables @@ -931,7 +1124,7 @@ static void init_variables(const struct my_option *options) if (options->value) init_one_value(options, options->value, options->def_value); if (options->var_type & GET_ASK_ADDR && - (variable= (*getopt_get_addr)("", 0, options))) + (variable= (*getopt_get_addr)("", 0, options, 0))) init_one_value(options, variable, options->def_value); } DBUG_VOID_RETURN; @@ -1024,7 +1217,8 @@ void my_print_help(const struct my_option *options) void my_print_variables(const struct my_option *options) { - uint name_space= 34, length; + uint name_space= 34, length, nr; + ulonglong bit, llvalue; char buff[255]; const struct my_option *optp; @@ -1033,8 +1227,8 @@ void my_print_variables(const struct my_option *options) printf("--------------------------------- -----------------------------\n"); for (optp= options; optp->id; optp++) { - gptr *value= (optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, optp) : optp->value); + void *value= (optp->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, optp, 0) : optp->value); if (value) { printf("%s ", optp->name); @@ -1042,6 +1236,21 @@ void my_print_variables(const struct my_option *options) for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { + case GET_SET: + if (!(llvalue= *(ulonglong*) value)) + printf("%s\n", "(No default value)"); + else + for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1) + { + if (!(bit & llvalue)) + continue; + llvalue&= ~bit; + printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr)); + } + break; + case GET_ENUM: + printf("%s\n", get_type(optp->typelib, *(ulong*) value)); + break; case GET_STR: case GET_STR_ALLOC: /* fall through */ printf("%s\n", *((char**) value) ? *((char**) value) : @@ -1069,6 +1278,9 @@ void my_print_variables(const struct my_option *options) longlong2str(*((ulonglong*) value), buff, 10); printf("%s\n", buff); break; + case GET_DOUBLE: + printf("%g\n", *(double*) value); + break; default: printf("(Disabled)\n"); break; diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index 2fd7eed7778..ebe6cea842b 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -17,11 +17,18 @@ /* thus to get the current time we should use the system function with the highest possible resolution */ +/* + TODO: in functions my_micro_time() and my_micro_time_and_time() there + exists some common code that should be merged into a function. +*/ + +#include "mysys_priv.h" +#include "my_static.h" + #ifdef __NETWARE__ #include <nks/time.h> #endif -#include "mysys_priv.h" ulonglong my_getsystime() { #ifdef HAVE_CLOCK_GETTIME @@ -29,28 +36,15 @@ ulonglong my_getsystime() clock_gettime(CLOCK_REALTIME, &tp); return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; #elif defined(__WIN__) -#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) - static __int64 offset=0, freq; LARGE_INTEGER t_cnt; - if (!offset) + if (query_performance_frequency) { - /* strictly speaking there should be a mutex to protect - initialization section. But my_getsystime() is called from - UUID() code, and UUID() calls are serialized with a mutex anyway - */ - LARGE_INTEGER li; - FILETIME ft; - GetSystemTimeAsFileTime(&ft); - li.LowPart=ft.dwLowDateTime; - li.HighPart=ft.dwHighDateTime; - offset=li.QuadPart-OFFSET_TO_EPOC; - QueryPerformanceFrequency(&li); - freq=li.QuadPart; QueryPerformanceCounter(&t_cnt); - offset-=t_cnt.QuadPart/freq*10000000+t_cnt.QuadPart%freq*10000000/freq; + return ((t_cnt.QuadPart / query_performance_frequency * 10000000) + + ((t_cnt.QuadPart % query_performance_frequency) * 10000000 / + query_performance_frequency) + query_performance_offset); } - QueryPerformanceCounter(&t_cnt); - return t_cnt.QuadPart/freq*10000000+t_cnt.QuadPart%freq*10000000/freq+offset; + return 0; #elif defined(__NETWARE__) NXTime_t tm; NXGetTime(NX_SINCE_1970, NX_NSECONDS, &tm); @@ -62,3 +56,176 @@ ulonglong my_getsystime() return (ulonglong)tv.tv_sec*10000000+(ulonglong)tv.tv_usec*10; #endif } + + +/* + Return current time + + SYNOPSIS + my_time() + flags If MY_WME is set, write error if time call fails + +*/ + +time_t my_time(myf flags __attribute__((unused))) +{ + time_t t; +#ifdef HAVE_GETHRTIME + (void) my_micro_time_and_time(&t); + return t; +#else + /* The following loop is here beacuse time() may fail on some systems */ + while ((t= time(0)) == (time_t) -1) + { + if (flags & MY_WME) + fprintf(stderr, "%s: Warning: time() call failed\n", my_progname); + } + return t; +#endif +} + + +/* + Return time in micro seconds + + SYNOPSIS + my_micro_time() + + NOTES + This function is to be used to measure performance in micro seconds. + As it's not defined whats the start time for the clock, this function + us only useful to measure time between two moments. + + For windows platforms we need the frequency value of the CUP. This is + initalized in my_init.c through QueryPerformanceFrequency(). + + If Windows platform doesn't support QueryPerformanceFrequency() we will + obtain the time via GetClockCount, which only supports milliseconds. + + RETURN + Value in microseconds from some undefined point in time +*/ + +ulonglong my_micro_time() +{ +#if defined(__WIN__) + ulonglong newtime; + GetSystemTimeAsFileTime((FILETIME*)&newtime); + return (newtime/10); +#elif defined(HAVE_GETHRTIME) + return gethrtime()/1000; +#else + ulonglong newtime; + struct timeval t; + /* + The following loop is here because gettimeofday may fail on some systems + */ + while (gettimeofday(&t, NULL) != 0) + {} + newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; + return newtime; +#endif /* defined(__WIN__) */ +} + + +/* + Return time in seconds and timer in microseconds (not different start!) + + SYNOPSIS + my_micro_time_and_time() + time_arg Will be set to seconds since epoch (00:00:00 UTC, + January 1, 1970) + + NOTES + This function is to be useful when we need both the time and microtime. + For example in MySQL this is used to get the query time start of a query + and to measure the time of a query (for the slow query log) + + IMPLEMENTATION + Value of time is as in time() call. + Value of microtime is same as my_micro_time(), which may be totally + unrealated to time() + + RETURN + Value in microseconds from some undefined point in time +*/ + +#define DELTA_FOR_SECONDS LL(500000000) /* Half a second */ + +ulonglong my_micro_time_and_time(time_t *time_arg) +{ +#if defined(__WIN__) + ulonglong newtime; + GetSystemTimeAsFileTime((FILETIME*)&newtime); + *time_arg= (time_t) ((newtime - OFFSET_TO_EPOCH) / 10000000); + return (newtime/10); +#elif defined(HAVE_GETHRTIME) + /* + Solaris has a very slow time() call. We optimize this by using the very + fast gethrtime() call and only calling time() every 1/2 second + */ + static hrtime_t prev_gethrtime= 0; + static time_t cur_time= 0; + hrtime_t cur_gethrtime; + + pthread_mutex_lock(&THR_LOCK_time); + cur_gethrtime= gethrtime(); + /* + Due to bugs in the Solaris (x86) implementation of gethrtime(), + the time returned by it might not be monotonic. Don't use the + cached time(2) value if this is a case. + */ + if ((prev_gethrtime > cur_gethrtime) || + ((cur_gethrtime - prev_gethrtime) > DELTA_FOR_SECONDS)) + { + cur_time= time(0); + prev_gethrtime= cur_gethrtime; + } + *time_arg= cur_time; + pthread_mutex_unlock(&THR_LOCK_time); + return cur_gethrtime/1000; +#else + ulonglong newtime; + struct timeval t; + /* + The following loop is here because gettimeofday may fail on some systems + */ + while (gettimeofday(&t, NULL) != 0) + {} + *time_arg= t.tv_sec; + newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; + return newtime; +#endif /* defined(__WIN__) */ +} + + +/* + Returns current time + + SYNOPSIS + my_time_possible_from_micro() + microtime Value from very recent my_micro_time() + + NOTES + This function returns the current time. The microtime argument is only used + if my_micro_time() uses a function that can safely be converted to the + current time. + + RETURN + current time +*/ + +time_t my_time_possible_from_micro(ulonglong microtime __attribute__((unused))) +{ +#if defined(__WIN__) + time_t t; + while ((t= time(0)) == (time_t) -1) + {} + return t; +#elif defined(HAVE_GETHRTIME) + return my_time(0); /* Cached time */ +#else + return (time_t) (microtime / 1000000); +#endif /* defined(__WIN__) */ +} + diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index 3870a5d61b0..dc9718d710d 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* my_setwd() and my_getwd() works with intern_filenames !! */ @@ -21,39 +23,46 @@ #ifdef HAVE_GETWD #include <sys/param.h> #endif -#if defined(MSDOS) || defined(__WIN__) +#if defined(__WIN__) #include <m_ctype.h> #include <dos.h> #include <direct.h> #endif -#if defined(OS2) -#include <direct.h> -#endif -#ifdef __EMX__ -/* chdir2 support also drive change */ -#define chdir _chdir2 -#endif +/* Gets current working directory in buff. + + SYNPOSIS + my_getwd() + buf Buffer to store result. Can be curr_dir[]. + size Size of buffer + MyFlags Flags - /* Gets current working directory in buff. Directory is allways ended - with FN_LIBCHAR */ - /* One must pass a buffer to my_getwd. One can allways use - curr_dir[] */ + NOTES + Directory is allways ended with FN_LIBCHAR -int my_getwd(my_string buf, uint size, myf MyFlags) + RESULT + 0 ok + # error +*/ + +int my_getwd(char * buf, size_t size, myf MyFlags) { - my_string pos; + char * pos; DBUG_ENTER("my_getwd"); - DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", (long) buf,size,MyFlags)); + DBUG_PRINT("my",("buf: 0x%lx size: %u MyFlags %d", + (long) buf, (uint) size, MyFlags)); + + if (size < 1) + return(-1); -#if ! defined(MSDOS) if (curr_dir[0]) /* Current pos is saved here */ VOID(strmake(buf,&curr_dir[0],size-1)); else -#endif { #if defined(HAVE_GETCWD) - if (!getcwd(buf,size-2) && MyFlags & MY_WME) + if (size < 2) + return(-1); + if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME) { my_errno=errno; my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); @@ -66,6 +75,8 @@ int my_getwd(my_string buf, uint size, myf MyFlags) strmake(buf,pathname,size-1); } #elif defined(VMS) + if (size < 2) + return(-1); if (!getcwd(buf,size-2,1) && MyFlags & MY_WME) { my_errno=errno; @@ -81,61 +92,26 @@ int my_getwd(my_string buf, uint size, myf MyFlags) pos[0]= FN_LIBCHAR; pos[1]=0; } - (void) strmake(&curr_dir[0],buf,(size_s) (FN_REFLEN-1)); + (void) strmake(&curr_dir[0],buf, (size_t) (FN_REFLEN-1)); } DBUG_RETURN(0); } /* my_getwd */ - /* Set new working directory */ +/* Set new working directory */ int my_setwd(const char *dir, myf MyFlags) { int res; - size_s length; - my_string start,pos; -#if defined(VMS) || defined(MSDOS) || defined(OS2) + size_t length; + char *start, *pos; +#if defined(VMS) char buff[FN_REFLEN]; #endif DBUG_ENTER("my_setwd"); DBUG_PRINT("my",("dir: '%s' MyFlags %d", dir, MyFlags)); - start=(my_string) dir; -#if defined(MSDOS) || defined(OS2) /* OS2/MSDOS chdir can't change drive */ -#if !defined(_DDL) && !defined(WIN32) - if ((pos=(char*) strchr(dir,FN_DEVCHAR)) != 0) - { - uint drive,drives; - - pos++; /* Skip FN_DEVCHAR */ - drive=(uint) (my_toupper(&my_charset_latin1,dir[0])-'A'+1); - drives= (uint) -1; - if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32) - { -#ifdef OS2 - _chdrive(drive); - drives = _getdrive(); -#else - _dos_setdrive(drive,&drives); - _dos_getdrive(&drives); -#endif - } - if (drive != drives) - { - *pos='\0'; /* Dir is now only drive */ - my_errno=errno; - my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),dir,ENOENT); - DBUG_RETURN(-1); - } - dir=pos; /* drive changed, change now path */ - } -#endif - if (*((pos=strend(dir)-1)) == FN_LIBCHAR && pos != dir) - { - strmov(buff,dir)[-1]=0; /* Remove last '/' */ - dir=buff; - } -#endif /* MSDOS*/ + start=(char *) dir; if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0)) dir=FN_ROOTDIR; #ifdef VMS @@ -160,7 +136,7 @@ int my_setwd(const char *dir, myf MyFlags) { if (test_if_hard_path(start)) { /* Hard pathname */ - pos=strmake(&curr_dir[0],start,(size_s) FN_REFLEN-1); + pos= strmake(&curr_dir[0],start,(size_t) FN_REFLEN-1); if (pos[-1] != FN_LIBCHAR) { length=(uint) (pos-(char*) curr_dir); diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h new file mode 100644 index 00000000000..44c79466e84 --- /dev/null +++ b/mysys/my_handler_errors.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2008 MySQL AB + Use is subject to license terms. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* + Errors a handler can give you +*/ + +static const char *handler_error_messages[]= +{ + "Didn't find key on read or update", + "Duplicate key on write or update", + "Internal (unspecified) error in handler", + "Someone has changed the row since it was read (while the table was locked to prevent it)", + "Wrong index given to function", + "Undefined handler error 125", + "Index file is crashed", + "Record file is crashed", + "Out of memory in engine", + "Undefined handler error 129", + "Incorrect file format", + "Command not supported by database", + "Old database file", + "No record read before update", + "Record was already deleted (or record file crashed)", + "No more room in record file", + "No more room in index file", + "No more records (read after end of file)", + "Unsupported extension used for table", + "Too big row", + "Wrong create options", + "Duplicate unique key or constraint on write or update", + "Unknown character set used in table", + "Conflicting table definitions in sub-tables of MERGE table", + "Table is crashed and last repair failed", + "Table was marked as crashed and should be repaired", + "Lock timed out; Retry transaction", + "Lock table is full; Restart program with a larger locktable", + "Updates are not allowed under a read only transactions", + "Lock deadlock; Retry transaction", + "Foreign key constraint is incorrectly formed", + "Cannot add a child row", + "Cannot delete a parent row", + "No savepoint with that name", + "Non unique key block size", + "The table does not exist in engine", + "The table already existed in storage engine", + "Could not connect to storage engine", + "Unexpected null pointer found when using spatial index", + "The table changed in storage engine", + "There's no partition in table for the given value", + "Row-based binlogging of row failed", + "Index needed in foreign key constraint", + "Upholding foreign key constraints would lead to a duplicate key error in " + "some other table", + "Table needs to be upgraded before it can be used", + "Table is read only", + "Failed to get next auto increment value", + "Failed to set row auto increment value", + "Unknown (generic) error from engine", + "Record is the same", + "It is not possible to log this statement", + "The event was corrupt, leading to illegal data being read", + "The table is of a new format not supported by this version", + "The event could not be processed no other hanlder error happened", + "Got a fatal error during initialzaction of handler", + "File to short; Expected more data in file", + "Read page with wrong checksum", + "Too many active concurrent transactions" +}; + diff --git a/mysys/my_init.c b/mysys/my_init.c index a6b04276dd2..deb62603e9a 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "my_static.h" @@ -30,7 +32,6 @@ #endif my_bool have_tcpip=0; static void my_win_init(void); -static my_bool win32_have_tcpip(void); static my_bool win32_init_tcp_ip(); #else #define my_win_init() @@ -43,6 +44,7 @@ static void netware_init(); my_bool my_init_done= 0; uint mysys_usage_id= 0; /* Incremented for each my_init() */ +ulong my_thread_stack_size= 65536; static ulong atoi_octal(const char *str) { @@ -69,32 +71,33 @@ static ulong atoi_octal(const char *str) my_bool my_init(void) { - my_string str; + char * str; if (my_init_done) return 0; my_init_done=1; mysys_usage_id++; my_umask= 0660; /* Default umask for new files */ my_umask_dir= 0700; /* Default umask for new directories */ + init_glob_errs(); #if defined(THREAD) if (my_thread_global_init()) return 1; -#if defined(SAFE_MUTEX) +# if defined(SAFE_MUTEX) safe_mutex_global_init(); /* Must be called early */ -#endif /* SAFE_MUTEX */ -#endif /* THREAD */ +# endif +#endif +#if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) + fastmutex_global_init(); /* Must be called early */ +#endif netware_init(); #ifdef THREAD #if defined(HAVE_PTHREAD_INIT) pthread_init(); /* Must be called before DBUG_ENTER */ #endif -#if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined( __WIN__) && !defined(__NETWARE__) sigfillset(&my_signals); /* signals blocked by mf_brkhant */ #endif #endif /* THREAD */ -#ifdef UNIXWARE_7 - (void) isatty(0); /* Go around connect() bug in UW7 */ -#endif { DBUG_ENTER("my_init"); DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown")); @@ -135,25 +138,37 @@ void my_end(int infoflag) */ FILE *info_file= DBUG_FILE; my_bool print_info= (info_file != stderr); - DBUG_ENTER("my_end"); + + if (!my_init_done) + return; + + /* + We do not use DBUG_ENTER here, as after cleanup DBUG is no longer + operational, so we cannot use DBUG_RETURN. + */ + DBUG_PRINT("info",("Shutting down: infoflag: %d print_info: %d", + infoflag, print_info)); if (!info_file) { info_file= stderr; print_info= 0; } - DBUG_PRINT("info",("Shutting down: print_info: %d", print_info)); if ((infoflag & MY_CHECK_ERROR) || print_info) { /* Test if some file is left open */ if (my_file_opened | my_stream_opened) { - sprintf(errbuff[0],EE(EE_OPEN_WARNING),my_file_opened,my_stream_opened); - (void) my_message_no_curses(EE_OPEN_WARNING,errbuff[0],ME_BELL); - DBUG_PRINT("error",("%s",errbuff[0])); + char ebuff[512]; + my_snprintf(ebuff, sizeof(ebuff), EE(EE_OPEN_WARNING), + my_file_opened, my_stream_opened); + my_message_no_curses(EE_OPEN_WARNING, ebuff, ME_BELL); + DBUG_PRINT("error", ("%s", ebuff)); + my_print_open_files(); } } free_charsets(); + my_error_unregister_all(); my_once_free(); if ((infoflag & MY_GIVE_INFO) || print_info) @@ -181,11 +196,11 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #endif -#if ( defined(MSDOS) || defined(__NETWARE__) ) && !defined(__WIN__) +#if defined(__NETWARE__) && !defined(__WIN__) fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC); #endif #if defined(SAFEMALLOC) - TERMINATE(stderr); /* Give statistic on screen */ + TERMINATE(stderr, (infoflag & MY_GIVE_INFO) != 0); #elif defined(__WIN__) && defined(_MSC_VER) _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); @@ -197,6 +212,10 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", _CrtDumpMemoryLeaks(); #endif } + else if (infoflag & MY_CHECK_ERROR) + { + TERMINATE(stderr, 0); /* Print memory leaks on screen */ + } if (!(infoflag & MY_DONT_FREE_DBUG)) { @@ -210,7 +229,8 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", Check on destroying of mutexes. A few may be left that will get cleaned up by C++ destructors */ - safe_mutex_end(infoflag & MY_GIVE_INFO ? stderr : (FILE *) 0); + safe_mutex_end((infoflag & (MY_GIVE_INFO | MY_CHECK_ERROR)) ? stderr : + (FILE *) 0); #endif /* defined(SAFE_MUTEX) */ #endif /* THREAD */ @@ -224,39 +244,18 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", #ifdef __WIN__ -/* - This code is specially for running MySQL, but it should work in - other cases too. - - Inizializzazione delle variabili d'ambiente per Win a 32 bit. - - Vengono inserite nelle variabili d'ambiente (utilizzando cosi' - le funzioni getenv e putenv) i valori presenti nelle chiavi - del file di registro: - - HKEY_LOCAL_MACHINE\software\MySQL - - Se la kiave non esiste nonn inserisce nessun valore -*/ - -/* Crea la stringa d'ambiente */ - -void setEnvString(char *ret, const char *name, const char *value) -{ - DBUG_ENTER("setEnvString"); - strxmov(ret, name,"=",value,NullS); - DBUG_VOID_RETURN ; -} /* - my_paramter_handler - Invalid paramter handler we will use instead of the one "baked" into the CRT - for MSC v8. This one just prints out what invalid parameter was encountered. - By providing this routine, routines like lseek will return -1 when we expect them - to instead of crash. + my_parameter_handler + + Invalid parameter handler we will use instead of the one "baked" + into the CRT for MSC v8. This one just prints out what invalid + parameter was encountered. By providing this routine, routines like + lseek will return -1 when we expect them to instead of crash. */ -void my_parameter_handler(const wchar_t * expression, const wchar_t * function, - const wchar_t * file, unsigned int line, + +void my_parameter_handler(const wchar_t * expression, const wchar_t * function, + const wchar_t * file, unsigned int line, uintptr_t pReserved) { DBUG_PRINT("my",("Expression: %s function: %s file: %s, line: %d", @@ -294,17 +293,6 @@ int handle_rtc_failure(int err_type, const char *file, int line, static void my_win_init(void) { - HKEY hSoftMysql ; - DWORD dimName = 256 ; - DWORD dimData = 1024 ; - DWORD dimNameValueBuffer = 256 ; - DWORD dimDataValueBuffer = 1024 ; - DWORD indexValue = 0 ; - long retCodeEnumValue ; - char NameValueBuffer[256] ; - char DataValueBuffer[1024] ; - char EnvString[1271] ; - const char *targetKey = "Software\\MySQL" ; DBUG_ENTER("my_win_init"); #if defined(_MSC_VER) @@ -330,42 +318,105 @@ static void my_win_init(void) _tzset(); - /* apre la chiave HKEY_LOCAL_MACHINES\software\MySQL */ - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)targetKey,0, - KEY_READ,&hSoftMysql) != ERROR_SUCCESS) - DBUG_VOID_RETURN; - - /* - ** Ne legge i valori e li inserisce nell'ambiente - ** suppone che tutti i valori letti siano di tipo stringa + '\0' - ** Legge il valore con indice 0 e lo scarta - */ - retCodeEnumValue = RegEnumValue(hSoftMysql, indexValue++, - (LPTSTR)NameValueBuffer, &dimNameValueBuffer, - NULL, NULL, (LPBYTE)DataValueBuffer, - &dimDataValueBuffer) ; - - while (retCodeEnumValue != ERROR_NO_MORE_ITEMS) + + + + + + + + + + + + + + + + + + + + + + + + + /* The following is used by time functions */ +#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) +#define MS 10000000 { - char *my_env; - /* Crea la stringa d'ambiente */ - setEnvString(EnvString, NameValueBuffer, DataValueBuffer) ; - - /* Inserisce i dati come variabili d'ambiente */ - my_env=strdup(EnvString); /* variable for putenv must be allocated ! */ - putenv(my_env) ; + FILETIME ft; + LARGE_INTEGER li, t_cnt; + DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency)); + if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) + query_performance_frequency= 0; + else + { + GetSystemTimeAsFileTime(&ft); + li.LowPart= ft.dwLowDateTime; + li.HighPart= ft.dwHighDateTime; + query_performance_offset= li.QuadPart-OFFSET_TO_EPOC; + QueryPerformanceCounter(&t_cnt); + query_performance_offset-= (t_cnt.QuadPart / + query_performance_frequency * MS + + t_cnt.QuadPart % + query_performance_frequency * MS / + query_performance_frequency); + } + } - dimNameValueBuffer = dimName ; - dimDataValueBuffer = dimData ; + { + /* + Open HKEY_LOCAL_MACHINE\SOFTWARE\MySQL and set any strings found + there as environment variables + */ + HKEY key_handle; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)"SOFTWARE\\MySQL", + 0, KEY_READ, &key_handle) == ERROR_SUCCESS) + { + LONG ret; + DWORD index= 0; + DWORD type; + char key_name[256], key_data[1024]; + DWORD key_name_len= sizeof(key_name) - 1; + DWORD key_data_len= sizeof(key_data) - 1; + + while ((ret= RegEnumValue(key_handle, index++, + key_name, &key_name_len, + NULL, &type, (LPBYTE)&key_data, + &key_data_len)) != ERROR_NO_MORE_ITEMS) + { + char env_string[sizeof(key_name) + sizeof(key_data) + 2]; + + if (ret == ERROR_MORE_DATA) + { + /* Registry value larger than 'key_data', skip it */ + DBUG_PRINT("error", ("Skipped registry value that was too large")); + } + else if (ret == ERROR_SUCCESS) + { + if (type == REG_SZ) + { + strxmov(env_string, key_name, "=", key_data, NullS); + + /* variable for putenv must be allocated ! */ + putenv(strdup(env_string)) ; + } + } + else + { + /* Unhandled error, break out of loop */ + break; + } + + key_name_len= sizeof(key_name) - 1; + key_data_len= sizeof(key_data) - 1; + } - retCodeEnumValue = RegEnumValue(hSoftMysql, indexValue++, - NameValueBuffer, &dimNameValueBuffer, - NULL, NULL, (LPBYTE)DataValueBuffer, - &dimDataValueBuffer) ; + RegCloseKey(key_handle) ; + } } - - /* chiude la chiave */ - RegCloseKey(hSoftMysql) ; DBUG_VOID_RETURN ; } diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index 082b6368a64..ecb61802842 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -1,4 +1,6 @@ -/* Copyright (C) 2004 MySQL AB +/* + Copyright (c) 2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. 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 @@ -11,7 +13,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" @@ -26,8 +29,8 @@ #endif static uint my_get_large_page_size_int(void); -static gptr my_large_malloc_int(size_t size, myf my_flags); -static my_bool my_large_free_int(gptr ptr, myf my_flags); +static uchar* my_large_malloc_int(size_t size, myf my_flags); +static my_bool my_large_free_int(uchar* ptr, myf my_flags); /* Gets the size of large pages from the OS */ @@ -48,9 +51,9 @@ uint my_get_large_page_size(void) my_malloc_lock() in case of failure */ -gptr my_large_malloc(size_t size, myf my_flags) +uchar* my_large_malloc(size_t size, myf my_flags) { - gptr ptr; + uchar* ptr; DBUG_ENTER("my_large_malloc"); if (my_use_large_pages && my_large_page_size) @@ -70,7 +73,7 @@ gptr my_large_malloc(size_t size, myf my_flags) to my_free_lock() in case of failure */ -void my_large_free(gptr ptr, myf my_flags __attribute__((unused))) +void my_large_free(uchar* ptr, myf my_flags __attribute__((unused))) { DBUG_ENTER("my_large_free"); @@ -113,15 +116,15 @@ finish: #if HAVE_DECL_SHM_HUGETLB /* Linux-specific large pages allocator */ -gptr my_large_malloc_int(size_t size, myf my_flags) +uchar* my_large_malloc_int(size_t size, myf my_flags) { int shmid; - gptr ptr; + uchar* ptr; struct shmid_ds buf; DBUG_ENTER("my_large_malloc_int"); /* Align block size to my_large_page_size */ - size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size; + size= MY_ALIGN(size, (size_t) my_large_page_size); shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) @@ -134,8 +137,8 @@ gptr my_large_malloc_int(size_t size, myf my_flags) DBUG_RETURN(NULL); } - ptr = shmat(shmid, NULL, 0); - if (ptr == (void *)-1) + ptr = (uchar*) shmat(shmid, NULL, 0); + if (ptr == (uchar *) -1) { if (my_flags& MY_WME) fprintf(stderr, "Warning: Failed to attach shared memory segment," @@ -156,7 +159,7 @@ gptr my_large_malloc_int(size_t size, myf my_flags) /* Linux-specific large pages deallocator */ -my_bool my_large_free_int(byte *ptr, myf my_flags __attribute__((unused))) +my_bool my_large_free_int(uchar *ptr, myf my_flags __attribute__((unused))) { DBUG_ENTER("my_large_free_int"); DBUG_RETURN(shmdt(ptr) == 0); diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 76f27cfb645..c18d14fb549 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -14,9 +14,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TODO: check for overun of memory for names. */ -/* Convert MSDOS-TIME to standar time_t */ +/* Convert MSDOS-TIME to standar time_t (still needed?) */ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <m_string.h> #include <my_dir.h> /* Structs used by my_dir,includes sys/types */ @@ -25,9 +24,7 @@ # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) #else -#ifndef OS2 # define dirent direct -#endif # define NAMLEN(dirent) (dirent)->d_namlen # if defined(HAVE_SYS_NDIR_H) # include <sys/ndir.h> @@ -38,7 +35,7 @@ # if defined(HAVE_NDIR_H) # include <ndir.h> # endif -# if defined(MSDOS) || defined(__WIN__) +# if defined(__WIN__) # include <dos.h> # ifdef __BORLANDC__ # include <dir.h> @@ -81,7 +78,7 @@ void my_dirend(MY_DIR *buffer) ALIGN_SIZE(sizeof(MY_DIR)))); free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) + ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0)); - my_free((gptr) buffer,MYF(0)); + my_free((uchar*) buffer,MYF(0)); } DBUG_VOID_RETURN; } /* my_dirend */ @@ -95,7 +92,7 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b) } /* comp_names */ -#if !defined(MSDOS) && !defined(__WIN__) +#if !defined(__WIN__) MY_DIR *my_dir(const char *path, myf MyFlags) { @@ -117,7 +114,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) pthread_mutex_lock(&THR_LOCK_open); #endif - dirp = opendir(directory_file_name(tmp_path,(my_string) path)); + dirp = opendir(directory_file_name(tmp_path,(char *) path)); #if defined(__amiga__) if ((dirp->dd_fd) < 0) /* Directory doesn't exists */ goto error; @@ -135,7 +132,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), ENTRIES_START_SIZE, ENTRIES_INCREMENT)) { - my_free((gptr) buffer,MYF(0)); + my_free((uchar*) buffer,MYF(0)); goto error; } init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); @@ -171,7 +168,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) else finfo.mystat= NULL; - if (push_dynamic(dir_entries_storage, (gptr)&finfo)) + if (push_dynamic(dir_entries_storage, (uchar*)&finfo)) goto error; } @@ -211,13 +208,13 @@ MY_DIR *my_dir(const char *path, myf MyFlags) * Returns pointer to dst; */ -my_string directory_file_name (my_string dst, const char *src) +char * directory_file_name (char * dst, const char *src) { #ifndef VMS /* Process as Unix format: just remove test the final slash. */ - my_string end; + char * end; if (src[0] == 0) src= (char*) "."; /* Use empty as current */ @@ -233,7 +230,7 @@ my_string directory_file_name (my_string dst, const char *src) long slen; long rlen; - my_string ptr, rptr; + char * ptr, rptr; char bracket; struct FAB fab = cc$rms_fab; struct NAM nam = cc$rms_nam; @@ -348,7 +345,7 @@ my_string directory_file_name (my_string dst, const char *src) #endif /* VMS */ } /* directory_file_name */ -#elif defined(WIN32) +#else /* ***************************************************************************** @@ -387,7 +384,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) *tmp_file++= '.'; /* From current dev-dir */ if (tmp_file[-1] != FN_LIBCHAR) *tmp_file++ =FN_LIBCHAR; - tmp_file[0]='*'; /* MSDOS needs this !??? */ + tmp_file[0]='*'; /* Windows needs this !??? */ tmp_file[1]='.'; tmp_file[2]='*'; tmp_file[3]='\0'; @@ -404,7 +401,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), ENTRIES_START_SIZE, ENTRIES_INCREMENT)) { - my_free((gptr) buffer,MYF(0)); + my_free((uchar*) buffer,MYF(0)); goto error; } init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); @@ -478,7 +475,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) else finfo.mystat= NULL; - if (push_dynamic(dir_entries_storage, (gptr)&finfo)) + if (push_dynamic(dir_entries_storage, (uchar*)&finfo)) goto error; } #ifdef __BORLANDC__ @@ -510,109 +507,7 @@ error: DBUG_RETURN((MY_DIR *) NULL); } /* my_dir */ -#else /* MSDOS and not WIN32 */ - - -/****************************************************************************** -** At MSDOS you always get stat of files, but time is in packed MSDOS-format -******************************************************************************/ - -MY_DIR *my_dir(const char* path, myf MyFlags) -{ - char *buffer; - MY_DIR *result= 0; - FILEINFO finfo; - DYNAMIC_ARRAY *dir_entries_storage; - MEM_ROOT *names_storage; - struct find_t find; - ushort mode; - char tmp_path[FN_REFLEN],*tmp_file,attrib; - DBUG_ENTER("my_dir"); - DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); - - /* Put LIB-CHAR as last path-character if not there */ - - tmp_file=tmp_path; - if (!*path) - *tmp_file++ ='.'; /* From current dir */ - tmp_file= strmov(tmp_file,path); - if (tmp_file[-1] == FN_DEVCHAR) - *tmp_file++= '.'; /* From current dev-dir */ - if (tmp_file[-1] != FN_LIBCHAR) - *tmp_file++ =FN_LIBCHAR; - tmp_file[0]='*'; /* MSDOS needs this !??? */ - tmp_file[1]='.'; - tmp_file[2]='*'; - tmp_file[3]='\0'; - - if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find)) - goto error; - - if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + - ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) + - sizeof(MEM_ROOT), MyFlags))) - goto error; - - dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); - names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) + - ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))); - - if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), - ENTRIES_START_SIZE, ENTRIES_INCREMENT)) - { - my_free((gptr) buffer,MYF(0)); - goto error; - } - init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); - - /* MY_DIR structure is allocated and completly initialized at this point */ - result= (MY_DIR*)buffer; - - do - { - if (!(finfo.name= strdup_root(names_storage, find.name))) - goto error; - - if (MyFlags & MY_WANT_STAT) - { - if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, - sizeof(MY_STAT)))) - goto error; - - bzero(finfo.mystat, sizeof(MY_STAT)); - finfo.mystat->st_size= find.size; - mode= MY_S_IREAD; attrib= find.attrib; - if (!(attrib & _A_RDONLY)) - mode|= MY_S_IWRITE; - if (attrib & _A_SUBDIR) - mode|= MY_S_IFDIR; - finfo.mystat->st_mode= mode; - finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time; - } - else - finfo.mystat= NULL; - - if (push_dynamic(dir_entries_storage, (gptr)&finfo)) - goto error; - - } while (_dos_findnext(&find) == 0); - - result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; - result->number_off_files= dir_entries_storage->elements; - - if (!(MyFlags & MY_DONT_SORT)) - my_qsort((void *) result->dir_entry, result->number_off_files, - sizeof(FILEINFO), (qsort_cmp) comp_names); - DBUG_RETURN(result); - -error: - my_dirend(result); - if (MyFlags & MY_FAE+MY_WME) - my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno); - DBUG_RETURN((MY_DIR *) NULL); -} /* my_dir */ - -#endif /* WIN32 && MSDOS */ +#endif /* __WIN__ */ /**************************************************************************** ** File status @@ -638,13 +533,13 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) if ((m_used= (stat_area == NULL))) if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) goto error; - if (! stat((my_string) path, (struct stat *) stat_area) ) + if (! stat((char *) path, (struct stat *) stat_area) ) DBUG_RETURN(stat_area); DBUG_PRINT("error",("Got errno: %d from stat", errno)); my_errno= errno; if (m_used) /* Free if new area */ - my_free((gptr) stat_area,MYF(0)); + my_free((uchar*) stat_area,MYF(0)); error: if (my_flags & (MY_FAE+MY_WME)) diff --git a/mysys/my_lock.c b/mysys/my_lock.c index a07f0c072a0..c0522ee849d 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -25,11 +25,6 @@ #ifdef __WIN__ #include <sys/locking.h> #endif -#ifdef __EMX__ -#define INCL_BASE -#define INCL_NOPMAPI -#include <os2emx.h> -#endif #ifdef __NETWARE__ #include <nks/fsio.h> #endif @@ -102,11 +97,6 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, DBUG_RETURN(0); } } -#elif defined(__EMX__) || defined(OS2) - - if (!_lock64( fd, locktype, start, length, MyFlags)) - DBUG_RETURN(0); - #elif defined(HAVE_LOCKING) /* Windows */ { diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c index a58a5a340b1..b96331cd3cf 100644 --- a/mysys/my_lockmem.c +++ b/mysys/my_lockmem.c @@ -25,17 +25,17 @@ struct st_mem_list { LIST list; - byte *page; + uchar *page; uint size; }; LIST *mem_list; -byte *my_malloc_lock(uint size,myf MyFlags) +uchar *my_malloc_lock(uint size,myf MyFlags) { int success; uint pagesize=sysconf(_SC_PAGESIZE); - byte *ptr; + uchar *ptr; struct st_mem_list *element; DBUG_ENTER("my_malloc_lock"); @@ -46,7 +46,7 @@ byte *my_malloc_lock(uint size,myf MyFlags) my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size); DBUG_RETURN(0); } - success = mlock((byte*) ptr,size); + success = mlock((uchar*) ptr,size); if (success != 0 && geteuid() == 0) { DBUG_PRINT("warning",("Failed to lock memory. errno %d\n", @@ -59,11 +59,11 @@ byte *my_malloc_lock(uint size,myf MyFlags) /* Add block in a list for munlock */ if (!(element=(struct st_mem_list*) my_malloc(sizeof(*element),MyFlags))) { - VOID(munlock((byte*) ptr,size)); + VOID(munlock((uchar*) ptr,size)); free(ptr); DBUG_RETURN(0); } - element->list.data=(byte*) element; + element->list.data=(uchar*) element; element->page=ptr; element->size=size; pthread_mutex_lock(&THR_LOCK_malloc); @@ -74,7 +74,7 @@ byte *my_malloc_lock(uint size,myf MyFlags) } -void my_free_lock(byte *ptr,myf Myflags __attribute__((unused))) +void my_free_lock(uchar *ptr,myf Myflags __attribute__((unused))) { LIST *list; struct st_mem_list *element=0; @@ -85,14 +85,14 @@ void my_free_lock(byte *ptr,myf Myflags __attribute__((unused))) element=(struct st_mem_list*) list->data; if (ptr == element->page) { /* Found locked mem */ - VOID(munlock((byte*) ptr,element->size)); + VOID(munlock((uchar*) ptr,element->size)); mem_list=list_delete(mem_list,list); break; } } pthread_mutex_unlock(&THR_LOCK_malloc); if (element) - my_free((gptr) element,MYF(0)); + my_free((uchar*) element,MYF(0)); free(ptr); /* Free even if not locked */ } diff --git a/mysys/my_lread.c b/mysys/my_lread.c deleted file mode 100644 index 1399b197119..00000000000 --- a/mysys/my_lread.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2000 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 */ - -#include "mysys_priv.h" -#include "mysys_err.h" - - /* Read a chunk of bytes from a file */ - -uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags) - /* File descriptor */ - /* Buffer must be at least count bytes */ - /* Max number of bytes returnd */ - /* Flags on what to do on error */ -{ - uint32 readbytes; - DBUG_ENTER("my_lread"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); - - DBUG_PRINT("error", ("Deprecated my_lread() function should not be used.")); - - /* Temp hack to get count to int32 while read wants int */ - if ((readbytes = (uint32) read(Filedes, Buffer, (uint) Count)) != Count) - { - my_errno=errno; - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - if (readbytes == MY_FILE_ERROR) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),errno); - else - if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),errno); - } - if (readbytes == MY_FILE_ERROR || MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN((uint32) -1); /* Return med felkod */ - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Ok vid l{sning */ - DBUG_RETURN(readbytes); -} /* my_lread */ diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c deleted file mode 100644 index d26825397e3..00000000000 --- a/mysys/my_lwrite.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2000 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 */ - -#include "mysys_priv.h" -#include "mysys_err.h" - - /* Write a chunk of bytes to a file */ - -uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags) -{ - uint32 writenbytes; - DBUG_ENTER("my_lwrite"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); - - DBUG_PRINT("error", ("Deprecated my_lwrite() function should not be used.")); - - /* Temp hack to get count to int32 while write wants int */ - if ((writenbytes = (uint32) write(Filedes, Buffer, (uint) Count)) != Count) - { - my_errno=errno; - if (writenbytes == (uint32) -1 || 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),errno); - } - DBUG_RETURN((uint32) -1); /* Return med felkod */ - } - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Ok vid l{sning */ - DBUG_RETURN(writenbytes); -} /* my_lwrite */ diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 256b14a9605..9deffeeae69 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #ifdef SAFEMALLOC /* We don't need SAFEMALLOC here */ #undef SAFEMALLOC @@ -23,35 +25,45 @@ /* My memory allocator */ -gptr my_malloc(size_t size, myf my_flags) +void *my_malloc(size_t size, myf my_flags) { - gptr point; + void* point; DBUG_ENTER("my_malloc"); DBUG_PRINT("my",("size: %lu my_flags: %d", (ulong) size, my_flags)); if (!size) size=1; /* Safety */ - if ((point = (char*)malloc(size)) == NULL) + + point= (char *) malloc(size); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + free(point); + point= NULL; + }); + + if (point == NULL) { my_errno=errno; if (my_flags & MY_FAE) error_handler_hook=fatal_error_handler_hook; if (my_flags & (MY_FAE+MY_WME)) my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH),size); + DBUG_EXECUTE_IF("simulate_out_of_memory", + DBUG_SET("-d,simulate_out_of_memory");); if (my_flags & MY_FAE) exit(1); } else if (my_flags & MY_ZEROFILL) bzero(point,size); DBUG_PRINT("exit",("ptr: 0x%lx", (long) point)); - DBUG_RETURN(point); + DBUG_RETURN((void*) point); } /* my_malloc */ /* Free memory allocated with my_malloc */ /*ARGSUSED*/ -void my_no_flags_free(gptr ptr) +void my_no_flags_free(void* ptr) { DBUG_ENTER("my_free"); DBUG_PRINT("my",("ptr: 0x%lx", (long) ptr)); @@ -63,32 +75,32 @@ void my_no_flags_free(gptr ptr) /* malloc and copy */ -gptr my_memdup(const byte *from, size_t length, myf my_flags) +void* my_memdup(const void *from, size_t length, myf my_flags) { - gptr ptr; - if ((ptr=my_malloc(length,my_flags)) != 0) - memcpy((byte*) ptr, (byte*)from, length); + void *ptr; + if ((ptr= my_malloc(length,my_flags)) != 0) + memcpy(ptr, from, length); return(ptr); } char *my_strdup(const char *from, myf my_flags) { - gptr ptr; + char *ptr; size_t length= strlen(from)+1; - if ((ptr=my_malloc(length,my_flags)) != 0) - memcpy((byte*) ptr, (byte*) from, length); - return((my_string) ptr); + if ((ptr= (char*) my_malloc(length, my_flags))) + memcpy((uchar*) ptr, (uchar*) from,(size_t) length); + return(ptr); } -char *my_strdup_with_length(const char *from, size_t length, myf my_flags) +char *my_strndup(const char *from, size_t length, myf my_flags) { - gptr ptr; - if ((ptr=my_malloc(length+1,my_flags)) != 0) + char *ptr; + if ((ptr= (char*) my_malloc(length+1,my_flags)) != 0) { - memcpy((byte*) ptr, (byte*) from, length); - ((char*) ptr)[length]=0; + memcpy((uchar*) ptr, (uchar*) from, length); + ptr[length]=0; } return((char*) ptr); } diff --git a/mysys/my_memmem.c b/mysys/my_memmem.c index 9230337409d..c000f14bc66 100644 --- a/mysys/my_memmem.c +++ b/mysys/my_memmem.c @@ -22,8 +22,9 @@ Returns a pointer to the beginning of the substring, needle, or NULL if the substring is not found in haystack. */ + void *my_memmem(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen) + const void *needle, size_t needlelen) { const unsigned char *cursor; const unsigned char *last_possible_needle_location = diff --git a/mysys/my_mkdir.c b/mysys/my_mkdir.c index 25176e4b823..676c6c1cd51 100644 --- a/mysys/my_mkdir.c +++ b/mysys/my_mkdir.c @@ -26,7 +26,7 @@ int my_mkdir(const char *dir, int Flags, myf MyFlags) DBUG_ENTER("my_dir"); DBUG_PRINT("enter",("dir: %s",dir)); -#if defined(__WIN__) || defined(OS2) +#if defined(__WIN__) if (mkdir((char*) dir)) #else if (mkdir((char*) dir, Flags & my_umask_dir)) diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 147bdfdcbf2..023a06fd896 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -35,22 +35,19 @@ static SECURITY_ATTRIBUTES mmap_security_attributes= void *my_mmap(void *addr, size_t len, int prot, int flags, int fd, my_off_t offset) { - DWORD flProtect=0; HANDLE hFileMap; LPVOID ptr; HANDLE hFile= (HANDLE)_get_osfhandle(fd); if (hFile == INVALID_HANDLE_VALUE) return MAP_FAILED; - flProtect|=SEC_COMMIT; - hFileMap=CreateFileMapping(hFile, &mmap_security_attributes, PAGE_READWRITE, 0, (DWORD) len, NULL); if (hFileMap == 0) return MAP_FAILED; ptr=MapViewOfFile(hFileMap, - flags & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, + prot & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, (DWORD)(offset >> 32), (DWORD)offset, len); /* diff --git a/mysys/my_net.c b/mysys/my_net.c index adabae4b99a..4dbd7bc3b8f 100644 --- a/mysys/my_net.c +++ b/mysys/my_net.c @@ -19,7 +19,7 @@ #include <m_string.h> /* for thread safe my_inet_ntoa */ -#if !defined(MSDOS) && !defined(__WIN__) +#if !defined(__WIN__) #include <netdb.h> #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> @@ -30,9 +30,10 @@ #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif -#endif /* !defined(MSDOS) && !defined(__WIN__) */ +#endif /* !defined(__WIN__) */ #include "my_net.h" + void my_inet_ntoa(struct in_addr in, char *buf) { char *ptr; @@ -42,8 +43,7 @@ void my_inet_ntoa(struct in_addr in, char *buf) pthread_mutex_unlock(&THR_LOCK_net); } - -/* This file is not needed if my_gethostbyname_r is a macro */ +/* This code is not needed if my_gethostbyname_r is a macro */ #if !defined(my_gethostbyname_r) /* @@ -111,9 +111,12 @@ extern pthread_mutex_t LOCK_gethostbyname_r; is finished with the structure. */ -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) +struct hostent * +my_gethostbyname_r(const char *name, + struct hostent *result __attribute__((unused)), + char *buffer __attribute__((unused)), + int buflen __attribute__((unused)), + int *h_errnop) { struct hostent *hp; pthread_mutex_lock(&LOCK_gethostbyname_r); diff --git a/mysys/my_new.cc b/mysys/my_new.cc index 377d9be22a8..edc393a5b55 100644 --- a/mysys/my_new.cc +++ b/mysys/my_new.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2001, 2003-2006 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2001, 2003-2006 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* This is a replacement of new/delete operators to be used when compiling diff --git a/mysys/my_once.c b/mysys/my_once.c index d83eba95b9d..b6f6656fce2 100644 --- a/mysys/my_once.c +++ b/mysys/my_once.c @@ -36,10 +36,10 @@ No DBUG_ENTER... here to get smaller dbug-startup */ -gptr my_once_alloc(unsigned int Size, myf MyFlags) +void* my_once_alloc(size_t Size, myf MyFlags) { - uint get_size,max_left; - gptr point; + size_t get_size, max_left; + uchar* point; reg1 USED_MEM *next; reg2 USED_MEM **prev; @@ -63,34 +63,36 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags) my_errno=errno; if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),get_size); - return((gptr) 0); + return((uchar*) 0); } - DBUG_PRINT("test",("my_once_malloc %u byte malloced",get_size)); + DBUG_PRINT("test",("my_once_malloc %lu byte malloced", (ulong) get_size)); next->next= 0; next->size= get_size; next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); *prev=next; } - point= (gptr) ((char*) next+ (next->size-next->left)); + point= (uchar*) ((char*) next+ (next->size-next->left)); next->left-= Size; - return(point); + if (MyFlags & MY_ZEROFILL) + bzero(point, Size); + return((void*) point); } /* my_once_alloc */ char *my_once_strdup(const char *src,myf myflags) { - uint len= (uint) strlen(src)+1; - char *dst=my_once_alloc(len, myflags); + size_t len= strlen(src)+1; + uchar *dst= my_once_alloc(len, myflags); if (dst) memcpy(dst, src, len); - return dst; + return (char*) dst; } -char *my_once_memdup(const char *src, uint len, myf myflags) +void *my_once_memdup(const void *src, size_t len, myf myflags) { - char *dst=my_once_alloc(len, myflags); + uchar *dst= my_once_alloc(len, myflags); if (dst) memcpy(dst, src, len); return dst; @@ -112,7 +114,7 @@ void my_once_free(void) for (next=my_once_root_block ; next ; ) { old=next; next= next->next ; - free((gptr) old); + free((uchar*) old); } my_once_root_block=0; diff --git a/mysys/my_open.c b/mysys/my_open.c index 9e1da1d3f07..fe7f65c450b 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -13,12 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include "mysys_err.h" #include <my_dir.h> #include <errno.h> -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#if defined(__WIN__) #include <share.h> #endif @@ -44,7 +43,7 @@ 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(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#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) @@ -57,21 +56,22 @@ File my_open(const char *FileName, int Flags, myf MyFlags) } #ifndef __WIN__ if (Flags & O_SHARE) - fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, + fd = sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); else - fd = open((my_string) FileName, Flags | O_BINARY, + fd = open((char *) FileName, Flags | O_BINARY, MY_S_IREAD | MY_S_IWRITE); #else - fd= my_sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, + fd= my_sopen((char *) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); #endif #elif !defined(NO_OPEN_3) fd = open(FileName, Flags, my_umask); /* Normal unix */ #else - fd = open((my_string) FileName, Flags); + fd = open((char *) FileName, Flags); #endif + DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN, EE_FILENOTFOUND, MyFlags)); } /* my_open */ @@ -125,52 +125,66 @@ int my_close(File fd, myf MyFlags) SYNOPSIS my_register_filename() - fd - FileName - type_file_type + fd File number opened, -1 if error on open + FileName File name + type_file_type How file was created + error_message_number Error message number if caller got error (fd == -1) + MyFlags Flags for my_close() + + RETURN + -1 error + # Filenumber + */ 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 ((uint) fd >= my_file_limit) { #if defined(THREAD) && !defined(HAVE_PREAD) - (void) my_close(fd,MyFlags); - my_errno=EMFILE; - if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG), - FileName, my_errno); - return(-1); -#endif + my_errno= EMFILE; +#else thread_safe_increment(my_file_opened,&THR_LOCK_open); - return(fd); /* safeguard */ + DBUG_RETURN(fd); /* safeguard */ +#endif } - pthread_mutex_lock(&THR_LOCK_open); - if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) + else { - my_file_opened++; - my_file_info[fd].type = type_of_file; + pthread_mutex_lock(&THR_LOCK_open); + if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) + { + my_file_opened++; + my_file_total_opened++; + my_file_info[fd].type = type_of_file; #if defined(THREAD) && !defined(HAVE_PREAD) - pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST); + pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST); #endif + pthread_mutex_unlock(&THR_LOCK_open); + DBUG_PRINT("exit",("fd: %d",fd)); + DBUG_RETURN(fd); + } pthread_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("fd: %d",fd)); - return(fd); + my_errno= ENOMEM; } - pthread_mutex_unlock(&THR_LOCK_open); (void) my_close(fd, MyFlags); - my_errno=ENOMEM; } else - my_errno=errno; - DBUG_PRINT("error",("Got error %d on open",my_errno)); + my_errno= errno; + + DBUG_PRINT("error",("Got error %d on open", my_errno)); if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) + { + if (my_errno == EMFILE) + error_message_number= EE_OUT_OF_FILERESOURCES; + DBUG_PRINT("error",("print err: %d",error_message_number)); my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG), - FileName, my_errno); - return(fd); + FileName, my_errno); + } + DBUG_RETURN(-1); } #ifdef __WIN__ @@ -355,3 +369,24 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode) return fh; /* return handle */ } #endif /* __WIN__ */ + + +#ifdef EXTRA_DEBUG + +void my_print_open_files(void) +{ + if (my_file_opened | my_stream_opened) + { + uint i; + for (i= 0 ; i < my_file_limit ; i++) + { + if (my_file_info[i].type != UNOPEN) + { + fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i); + fputc('\n', stderr); + } + } + } +} + +#endif diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 44415709371..f3282e2e9bb 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2001, 2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2001, 2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -21,17 +23,36 @@ #include <unistd.h> #endif - /* Read a chunk of bytes from a file */ +/* + Read a chunk of bytes from a file from a given position -uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, - myf MyFlags) + SYNOPSIOS + my_pread() + Filedes File decsriptor + Buffer Buffer to read data into + Count Number of bytes to read + offset Position to read from + MyFlags Flags + + NOTES + This differs from the normal pread() call in that we don't care + to set the position in the file back to the original position + if the system doesn't support pread(). + + RETURN + (size_t) -1 Error + # Number of bytes read +*/ + +size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, + myf MyFlags) { - uint readbytes; - int error; + size_t readbytes; + int error= 0; DBUG_ENTER("my_pread"); DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, (ulong) offset, (long) Buffer, Count, MyFlags)); - + Filedes, (ulong) offset, (long) Buffer, (uint) Count, + MyFlags)); for (;;) { #ifndef __WIN__ @@ -40,19 +61,19 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, #ifndef HAVE_PREAD pthread_mutex_lock(&my_file_info[Filedes].mutex); readbytes= (uint) -1; - error= (lseek(Filedes, offset, MY_SEEK_SET) == -1L || - (readbytes = (uint) read(Filedes, Buffer, Count)) != Count); + error= (lseek(Filedes, offset, MY_SEEK_SET) == (my_off_t) -1 || + (readbytes= read(Filedes, Buffer, (uint) Count)) != Count); pthread_mutex_unlock(&my_file_info[Filedes].mutex); #else - error=((readbytes = (uint) pread(Filedes, Buffer, Count, offset)) != Count); + if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count))) + my_errno= errno ? errno : -1; #endif - if (error) + if (error || readbytes != Count) { - my_errno=errno; DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", - (int) readbytes, Count,Filedes,my_errno)); + (int) readbytes, (uint) Count,Filedes,my_errno)); #ifdef THREAD - if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) + if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR) { DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d", (int) readbytes)); @@ -61,14 +82,14 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, #endif if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - if ((int) readbytes == -1) + 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 ((int) readbytes == -1 || (MyFlags & (MY_FNABP | MY_NABP))) + if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP))) DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ } if (MyFlags & (MY_NABP | MY_FNABP)) @@ -78,42 +99,63 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, } /* my_pread */ - /* Write a chunk of bytes to a file */ +/* + Write a chunk of bytes to a file at a given position -uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, - myf MyFlags) + SYNOPSIOS + my_pwrite() + Filedes File decsriptor + Buffer Buffer to write data from + Count Number of bytes to write + offset Position to write to + MyFlags Flags + + NOTES + This differs from the normal pwrite() call in that we don't care + to set the position in the file back to the original position + if the system doesn't support pwrite() + + RETURN + (size_t) -1 Error + # Number of bytes read +*/ + +size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count, + my_off_t offset, myf MyFlags) { - uint writenbytes,errors; - ulong written; + size_t writenbytes, written; + uint errors; DBUG_ENTER("my_pwrite"); - DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %d MyFlags: %d", - Filedes, (ulong) offset, (long) Buffer, Count, MyFlags)); - errors=0; written=0L; + DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", + Filedes, (ulong) offset, (long) Buffer, (uint) Count, + MyFlags)); + errors= 0; + written= 0; for (;;) { #ifndef HAVE_PREAD int error; - writenbytes= (uint) -1; + writenbytes= (size_t) -1; pthread_mutex_lock(&my_file_info[Filedes].mutex); - error=(lseek(Filedes, offset, MY_SEEK_SET) != -1L && - (writenbytes = (uint) write(Filedes, Buffer, Count)) == Count); + error= (lseek(Filedes, offset, MY_SEEK_SET) != (my_off_t) -1 && + (writenbytes = write(Filedes, Buffer, (uint) Count)) == Count); pthread_mutex_unlock(&my_file_info[Filedes].mutex); if (error) break; #else - if ((writenbytes = (uint) pwrite(Filedes, Buffer, Count,offset)) == Count) + if ((writenbytes= pwrite(Filedes, Buffer, Count,offset)) == Count) break; + my_errno= errno; #endif - if ((int) writenbytes != -1) + if (writenbytes != (size_t) -1) { /* Safegueard */ written+=writenbytes; Buffer+=writenbytes; Count-=writenbytes; offset+=writenbytes; } - my_errno=errno; - DBUG_PRINT("error",("Write only %d bytes",writenbytes)); + DBUG_PRINT("error",("Write only %u bytes", (uint) writenbytes)); #ifndef NO_BACKGROUND #ifdef THREAD if (my_thread_var->abort) @@ -126,8 +168,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, errors++; continue; } - if ((writenbytes > 0 && (uint) writenbytes != (uint) -1) || - my_errno == EINTR) + if ((writenbytes && writenbytes != (size_t) -1) || my_errno == EINTR) continue; /* Retry */ #endif if (MyFlags & (MY_NABP | MY_FNABP)) @@ -142,6 +183,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, else break; /* Return bytes written */ } + 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 */ diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index 0422e0c6512..aba3e47d754 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -23,7 +23,7 @@ #include <m_string.h> #include <thr_alarm.h> -#if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread) +#if (defined(__BSD__) || defined(_BSDI_VERSION)) #define SCHED_POLICY SCHED_RR #else #define SCHED_POLICY SCHED_OTHER @@ -51,8 +51,6 @@ int my_pthread_getprio(pthread_t thread_id) int policy; if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param)) { - DBUG_PRINT("thread",("policy: %d priority: %d", - policy,tmp_sched_param.sched_priority)); return tmp_sched_param.sched_priority; } #endif @@ -77,9 +75,6 @@ void my_pthread_attr_setprio(pthread_attr_t *attr, int priority) #ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC #undef pthread_getspecific -#ifdef HAVE_UNIXWARE7_THREADS -#define pthread_getspecific thr_getspecific -#endif void *my_pthread_getspecific_imp(pthread_key_t key) { @@ -191,7 +186,7 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res) ** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty ****************************************************************************/ -#if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(sigwait) && !defined(__WIN__) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(OS2) +#if !defined(HAVE_SIGWAIT) && !defined(sigwait) && !defined(__WIN__) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) #if !defined(DONT_USE_SIGSUSPEND) @@ -430,7 +425,7 @@ int sigwait(sigset_t *setp, int *sigp) ** Patches for AIX and DEC OSF/1 3.2 *****************************************************************************/ -#if (defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) && !defined(HAVE_UNIXWARE7_THREADS)) || defined(HAVE_DEC_3_2_THREADS) +#if defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) #include <netdb.h> diff --git a/mysys/my_quick.c b/mysys/my_quick.c index 15549dfb751..0ba20a5bdee 100644 --- a/mysys/my_quick.c +++ b/mysys/my_quick.c @@ -19,14 +19,14 @@ #include "my_nosys.h" -uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags) +size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags) { - uint readbytes; + size_t readbytes; - if ((readbytes = (uint) read(Filedes, Buffer, Count)) != Count) + if ((readbytes = read(Filedes, Buffer, (uint) Count)) != Count) { #ifndef DBUG_OFF - if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) + if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR) { DBUG_PRINT("error", ("my_quick_read() was interrupted and returned %d" ". This function does not retry the read!", @@ -40,20 +40,20 @@ uint my_quick_read(File Filedes,byte *Buffer,uint Count,myf MyFlags) } -uint my_quick_write(File Filedes,const byte *Buffer,uint Count) +size_t my_quick_write(File Filedes,const uchar *Buffer,size_t Count) { #ifndef DBUG_OFF - uint writtenbytes; + size_t writtenbytes; #endif if (( #ifndef DBUG_OFF writtenbytes = #endif - (uint) write(Filedes,Buffer,Count)) != Count) + (size_t) write(Filedes,Buffer, (uint) Count)) != Count) { #ifndef DBUG_OFF - if ((writtenbytes == 0 || (int) writtenbytes == -1) && errno == EINTR) + if ((writtenbytes == 0 || writtenbytes == (size_t) -1) && errno == EINTR) { DBUG_PRINT("error", ("my_quick_write() was interrupted and returned %d" ". This function does not retry the write!", @@ -61,7 +61,7 @@ uint my_quick_write(File Filedes,const byte *Buffer,uint Count) } #endif my_errno=errno; - return (uint) -1; + return (size_t) -1; } return 0; } diff --git a/mysys/my_read.c b/mysys/my_read.c index a6c45340b0c..0c302d5b227 100644 --- a/mysys/my_read.c +++ b/mysys/my_read.c @@ -33,43 +33,44 @@ N number of bytes read. */ -uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags) +size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) { - uint readbytes, save_count; + size_t readbytes, save_count; DBUG_ENTER("my_read"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - Filedes, (long) Buffer, Count, MyFlags)); + DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", + Filedes, (long) Buffer, (ulong) Count, MyFlags)); save_count= Count; for (;;) { errno= 0; /* Linux doesn't reset this */ - if ((readbytes= (uint) read(Filedes, Buffer, Count)) != Count) + if ((readbytes= read(Filedes, Buffer, (uint) Count)) != Count) { my_errno= errno ? errno : -1; - DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", - (int) readbytes, Count, Filedes, my_errno)); + DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", + (int) readbytes, (ulong) Count, Filedes, + my_errno)); #ifdef THREAD if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) { - DBUG_PRINT("debug", ("my_read() was interrupted and returned %d", - (int) readbytes)); + DBUG_PRINT("debug", ("my_read() was interrupted and returned %ld", + (long) readbytes)); continue; /* Interrupted */ } #endif if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) { - if ((int) readbytes == -1) + 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 ((int) readbytes == -1 || + if (readbytes == (size_t) -1 || ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ - if (readbytes > 0 && (MyFlags & MY_FULL_IO)) + if (readbytes != (size_t) -1 && (MyFlags & MY_FULL_IO)) { Buffer+= readbytes; Count-= readbytes; diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c index 43fbb0c1eee..a55282e03a0 100644 --- a/mysys/my_realloc.c +++ b/mysys/my_realloc.c @@ -22,13 +22,24 @@ /* My memory re allocator */ -gptr my_realloc(gptr oldpoint, uint size, myf my_flags) +/** + @brief wrapper around realloc() + + @param oldpoint pointer to currently allocated area + @param size new size requested, must be >0 + @param my_flags flags + + @note if size==0 realloc() may return NULL; my_realloc() treats this as an + error which is not the intention of realloc() +*/ +void* my_realloc(void* oldpoint, size_t size, myf my_flags) { - gptr point; + void *point; DBUG_ENTER("my_realloc"); - DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d", (long) oldpoint, size, - my_flags)); + DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) oldpoint, + (ulong) size, my_flags)); + DBUG_ASSERT(size > 0); if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR)) DBUG_RETURN(my_malloc(size,my_flags)); #ifdef USE_HALLOC @@ -48,7 +59,7 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags) free(oldpoint); } #else - if ((point = (char*)realloc(oldpoint,size)) == NULL) + if ((point= (uchar*) realloc(oldpoint,size)) == NULL) { if (my_flags & MY_FREE_ON_ERROR) my_free(oldpoint, my_flags); diff --git a/mysys/my_redel.c b/mysys/my_redel.c index adbd73c627c..f8d43d221ca 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000-2003, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,9 +12,9 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <my_dir.h> #include <m_string.h> @@ -78,11 +78,8 @@ end: int my_copystat(const char *from, const char *to, int MyFlags) { struct stat statbuf; -#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) - int res; -#endif /* MSDOS */ - if (stat((char*) from, &statbuf)) + if (stat(from, &statbuf)) { my_errno=errno; if (MyFlags & (MY_FAE+MY_WME)) @@ -91,16 +88,31 @@ int my_copystat(const char *from, const char *to, int MyFlags) } if ((statbuf.st_mode & S_IFMT) != S_IFREG) return 1; - VOID(chmod(to, statbuf.st_mode & 07777)); /* Copy modes */ -#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) + /* Copy modes */ + if (chmod(to, statbuf.st_mode & 07777)) + { + my_errno= errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), from, errno); + return -1; + } + +#if !defined(__WIN__) && !defined(__NETWARE__) if (statbuf.st_nlink > 1 && MyFlags & MY_LINK_WARNING) { if (MyFlags & MY_LINK_WARNING) my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink); } - res= chown(to, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */ -#endif /* MSDOS */ + /* Copy ownership */ + if (chown(to, statbuf.st_uid, statbuf.st_gid)) + { + my_errno= errno; + if (MyFlags & (MY_FAE+MY_WME)) + my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), from, errno); + return -1; + } +#endif /* !__WIN__ && !__NETWARE__ */ #ifndef VMS #ifndef __ZTC__ diff --git a/mysys/my_rename.c b/mysys/my_rename.c index c4aeb95b2c0..39e6056a9e4 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -13,12 +13,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include <my_dir.h> #include "mysys_err.h" - +#include "m_string.h" #undef my_rename + /* On unix rename deletes to file if it exists */ int my_rename(const char *from, const char *to, myf MyFlags) @@ -61,5 +61,19 @@ int my_rename(const char *from, const char *to, myf MyFlags) if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); } + else if (MyFlags & MY_SYNC_DIR) + { +#ifdef NEED_EXPLICIT_SYNC_DIR + /* do only the needed amount of syncs: */ + char dir_from[FN_REFLEN], dir_to[FN_REFLEN]; + size_t dir_from_length, dir_to_length; + dirname_part(dir_from, from, &dir_from_length); + dirname_part(dir_to, to, &dir_to_length); + if (my_sync_dir(dir_from, MyFlags) || + (strcmp(dir_from, dir_to) && + my_sync_dir(dir_to, MyFlags))) + error= -1; +#endif + } DBUG_RETURN(error); } /* my_rename */ diff --git a/mysys/my_seek.c b/mysys/my_seek.c index 5c1a6c44b6f..08b3873ac9a 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,9 +12,11 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" +#include "mysys_err.h" /* Seek to a position in a file. @@ -42,10 +45,9 @@ actual error. */ -my_off_t my_seek(File fd, my_off_t pos, int whence, - myf MyFlags __attribute__((unused))) +my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags) { - reg1 os_off_t newpos; + reg1 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, @@ -69,6 +71,8 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, if (newpos == (os_off_t) -1) { my_errno=errno; + if (MyFlags & MY_WME) + my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); DBUG_PRINT("error",("lseek: %lu errno: %d", (ulong) newpos,errno)); DBUG_RETURN(MY_FILEPOS_ERROR); } @@ -83,7 +87,7 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, /* Tell current position of file */ /* ARGSUSED */ -my_off_t my_tell(File fd, myf MyFlags __attribute__((unused))) +my_off_t my_tell(File fd, myf MyFlags) { os_off_t pos; DBUG_ENTER("my_tell"); @@ -95,7 +99,12 @@ my_off_t my_tell(File fd, myf MyFlags __attribute__((unused))) pos=lseek(fd, 0L, MY_SEEK_CUR); #endif if (pos == (os_off_t) -1) + { my_errno=errno; + if (MyFlags & MY_WME) + my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); + DBUG_PRINT("error", ("tell: %lu errno: %d", (ulong) pos, my_errno)); + } DBUG_PRINT("exit",("pos: %lu", (ulong) pos)); DBUG_RETURN((my_off_t) pos); } /* my_tell */ diff --git a/mysys/my_sleep.c b/mysys/my_sleep.c index 50e6fae17fc..87170e4af41 100644 --- a/mysys/my_sleep.c +++ b/mysys/my_sleep.c @@ -24,8 +24,6 @@ void my_sleep(ulong m_seconds) delay(m_seconds/1000+1); #elif defined(__WIN__) Sleep(m_seconds/1000+1); /* Sleep() has millisecond arg */ -#elif defined(OS2) - DosSleep(m_seconds/1000+1); #elif defined(HAVE_SELECT) struct timeval t; t.tv_sec= m_seconds / 1000000L; diff --git a/mysys/my_static.c b/mysys/my_static.c index 3f6754f67a0..8390e09284a 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000-2008 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,27 +13,27 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Static variables for mysys library. All definied here for easy making of a shared library */ -#if !defined(stdin) || defined(OS2) #include "mysys_priv.h" #include "my_static.h" #include "my_alarm.h" -#endif my_bool timed_mutexes= 0; /* from my_init */ -my_string home_dir=0; +char * home_dir=0; const char *my_progname=0; char NEAR curr_dir[FN_REFLEN]= {0}, NEAR home_dir_buff[FN_REFLEN]= {0}; ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0; +ulong my_file_total_opened= 0; int NEAR my_umask=0664, NEAR my_umask_dir=0777; #ifndef THREAD int NEAR my_errno=0; @@ -75,8 +76,8 @@ uint sf_malloc_prehunc=0, /* If you have problem with core- */ size_t sf_malloc_cur_memory= 0L; /* Current memory usage */ size_t sf_malloc_max_memory= 0L; /* Maximum memory usage */ uint sf_malloc_count= 0; /* Number of times NEW() was called */ -byte *sf_min_adress= (byte*) ~(unsigned long) 0L, - *sf_max_adress= (byte*) 0L; +uchar *sf_min_adress= (uchar*) ~(unsigned long) 0L, + *sf_max_adress= (uchar*) 0L; /* Root of the linked list of struct st_irem */ struct st_irem *sf_malloc_root = NULL; @@ -84,13 +85,6 @@ struct st_irem *sf_malloc_root = NULL; int volatile my_have_got_alarm=0; /* declare variable to reset */ ulong my_time_to_wait_for_lock=2; /* In seconds */ - /* - We need to have this define here as otherwise linking will fail - on OSF1 when compiling --without-raid --with-debug - */ - -const char *raid_type_string[]={"none","striped"}; - /* from errors.c */ #ifdef SHARED_LIBRARY char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */ @@ -101,6 +95,19 @@ int (*error_handler_hook)(uint error,const char *str,myf MyFlags)= int (*fatal_error_handler_hook)(uint error,const char *str,myf MyFlags)= my_message_no_curses; +#if defined(ENABLED_DEBUG_SYNC) +/** + Global pointer to be set if callback function is defined + (e.g. in mysqld). See sql/debug_sync.cc. +*/ +void (*debug_sync_C_callback_ptr)(const char *, size_t); +#endif /* defined(ENABLED_DEBUG_SYNC) */ + +#ifdef __WIN__ +/* from my_getsystime.c */ +ulonglong query_performance_frequency, query_performance_offset; +#endif + /* How to disable options */ my_bool NEAR my_disable_locking=0; my_bool NEAR my_disable_async_io=0; diff --git a/mysys/my_static.h b/mysys/my_static.h index b438c936225..90168b099a8 100644 --- a/mysys/my_static.h +++ b/mysys/my_static.h @@ -44,8 +44,8 @@ struct st_irem struct st_irem *next; /* Linked list of structures */ struct st_irem *prev; /* Other link */ char *filename; /* File in which memory was new'ed */ + size_t datasize; /* Size requested */ uint32 linenum; /* Line number in above file */ - uint32 datasize; /* Size requested */ uint32 SpecialValue; /* Underrun marker value */ }; @@ -60,12 +60,14 @@ extern const char *soundex_map; extern USED_MEM* my_once_root_block; extern uint my_once_extra; -extern byte *sf_min_adress,*sf_max_adress; +extern uchar *sf_min_adress,*sf_max_adress; extern uint sf_malloc_count; extern struct st_irem *sf_malloc_root; extern struct st_my_file_info my_file_info_default[MY_NFILE]; +extern ulonglong query_performance_frequency, query_performance_offset; + #if defined(THREAD) && !defined(__WIN__) extern sigset_t my_signals; /* signals blocked by mf_brkhant */ #endif diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c index 8239f357d24..e4526a23d29 100644 --- a/mysys/my_symlink.c +++ b/mysys/my_symlink.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. +/* + Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -84,20 +86,12 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags) if (MyFlags & MY_WME) my_error(EE_CANT_SYMLINK, MYF(0), linkname, content, errno); } + else if ((MyFlags & MY_SYNC_DIR) && my_sync_dir_by_file(linkname, MyFlags)) + result= -1; DBUG_RETURN(result); #endif /* HAVE_READLINK */ } -/* - Resolve all symbolic links in path - 'to' may be equal to 'filename' - - Because purify gives a lot of UMR errors when using realpath(), - this code is disabled when using purify. - - If MY_RESOLVE_LINK is given, only do realpath if the file is a link. -*/ - #if defined(SCO) #define BUFF_LEN 4097 #elif defined(MAXPATHLEN) @@ -121,11 +115,14 @@ int my_is_symlink(const char *filename __attribute__((unused))) #endif } +/* + Resolve all symbolic links in path + 'to' may be equal to 'filename' +*/ -int my_realpath(char *to, const char *filename, - myf MyFlags __attribute__((unused))) +int my_realpath(char *to, const char *filename, myf MyFlags) { -#if defined(HAVE_REALPATH) && !defined(HAVE_purify) && !defined(HAVE_BROKEN_REALPATH) +#if defined(HAVE_REALPATH) && !defined(HAVE_BROKEN_REALPATH) int result=0; char buff[BUFF_LEN]; char *ptr; @@ -166,6 +163,6 @@ int my_realpath(char *to, const char *filename, } #else my_load_path(to, filename, NullS); -#endif +#endif return 0; } diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index ee0a45cf93b..7c3ddbb911c 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -33,9 +33,13 @@ File my_create_with_symlink(const char *linkname, const char *filename, int create_link; char abs_linkname[FN_REFLEN]; DBUG_ENTER("my_create_with_symlink"); + DBUG_PRINT("enter", ("linkname: %s filename: %s", + linkname ? linkname : "(null)", + filename ? filename : "(null)")); if (my_disable_symlinks) { + DBUG_PRINT("info", ("Symlinks disabled")); /* Create only the file, not the link and file */ create_link= 0; if (linkname) diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 64fce3aac21..17f0d4ddd5d 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2003 MySQL AB +/* + Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -48,13 +50,24 @@ int my_sync(File fd, myf my_flags) do { -#if defined(HAVE_FDATASYNC) +#if defined(F_FULLFSYNC) + /* + In Mac OS X >= 10.3 this call is safer than fsync() (it forces the + disk's cache and guarantees ordered writes). + */ + if (!(res= fcntl(fd, F_FULLFSYNC, 0))) + break; /* ok */ + /* Some file systems don't support F_FULLFSYNC and fail above: */ + DBUG_PRINT("info",("fcntl(F_FULLFSYNC) failed, falling back")); +#endif +#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC res= fdatasync(fd); #elif defined(HAVE_FSYNC) res= fsync(fd); #elif defined(__WIN__) res= _commit(fd); #else +#error Cannot find a way to sync a file, durability in danger res= 0; /* No sync (strange OS) */ #endif } while (res == -1 && errno == EINTR); @@ -66,10 +79,99 @@ int my_sync(File fd, myf my_flags) my_errno= -1; /* Unknown error */ if ((my_flags & MY_IGNORE_BADFD) && (er == EBADF || er == EINVAL || er == EROFS)) + { + DBUG_PRINT("info", ("ignoring errno %d", er)); res= 0; + } else if (my_flags & MY_WME) my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno); } DBUG_RETURN(res); } /* my_sync */ + +static const char cur_dir_name[]= {FN_CURLIB, 0}; + + +/* + Force directory information to disk. + + SYNOPSIS + my_sync_dir() + dir_name the name of the directory + my_flags flags (MY_WME etc) + + RETURN + 0 if ok, !=0 if error +*/ + +#ifdef NEED_EXPLICIT_SYNC_DIR + +int my_sync_dir(const char *dir_name, myf my_flags) +{ + File dir_fd; + int res= 0; + const char *correct_dir_name; + DBUG_ENTER("my_sync_dir"); + DBUG_PRINT("my",("Dir: '%s' my_flags: %d", dir_name, my_flags)); + /* Sometimes the path does not contain an explicit directory */ + correct_dir_name= (dir_name[0] == 0) ? cur_dir_name : dir_name; + /* + Syncing a dir may give EINVAL on tmpfs on Linux, which is ok. + EIO on the other hand is very important. Hence MY_IGNORE_BADFD. + */ + if ((dir_fd= my_open(correct_dir_name, O_RDONLY, MYF(my_flags))) >= 0) + { + if (my_sync(dir_fd, MYF(my_flags | MY_IGNORE_BADFD))) + res= 2; + if (my_close(dir_fd, MYF(my_flags))) + res= 3; + } + else + res= 1; + DBUG_RETURN(res); +} + +#else /* NEED_EXPLICIT_SYNC_DIR */ + +int my_sync_dir(const char *dir_name __attribute__((unused)), + myf my_flags __attribute__((unused))) +{ + return 0; +} + +#endif /* NEED_EXPLICIT_SYNC_DIR */ + + +/* + Force directory information to disk. + + SYNOPSIS + my_sync_dir_by_file() + file_name the name of a file in the directory + my_flags flags (MY_WME etc) + + RETURN + 0 if ok, !=0 if error +*/ + +#ifdef NEED_EXPLICIT_SYNC_DIR + +int my_sync_dir_by_file(const char *file_name, myf my_flags) +{ + char dir_name[FN_REFLEN]; + size_t dir_name_length; + dirname_part(dir_name, file_name, &dir_name_length); + return my_sync_dir(dir_name, my_flags); +} + +#else /* NEED_EXPLICIT_SYNC_DIR */ + +int my_sync_dir_by_file(const char *file_name __attribute__((unused)), + myf my_flags __attribute__((unused))) +{ + return 0; +} + +#endif /* NEED_EXPLICIT_SYNC_DIR */ + diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 21d2e9bb2ca..076e6eb9b0a 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000-2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Functions to handle initializating and allocationg of all mysys & debug @@ -31,7 +33,7 @@ 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_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time, THR_LOCK_myisam_mmap; pthread_cond_t THR_COND_threads; @@ -53,12 +55,12 @@ pthread_mutexattr_t my_errorcheck_mutexattr; #ifdef TARGET_OS_LINUX /* - Dummy thread spawned in my_thread_global_init() below to avoid - race conditions in NPTL pthread_exit code. + Dummy thread spawned in my_thread_global_init() below to avoid + race conditions in NPTL pthread_exit code. */ static pthread_handler_t -nptl_pthread_exit_hack_handler(void *arg __attribute__((unused))) +nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) { /* Do nothing! */ pthread_exit(0); @@ -67,6 +69,7 @@ nptl_pthread_exit_hack_handler(void *arg __attribute__((unused))) #endif /* TARGET_OS_LINUX */ + static uint get_thread_lib(void); /* @@ -151,6 +154,7 @@ my_bool my_thread_global_init(void) pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST); pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST); 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(); @@ -215,6 +219,7 @@ void my_thread_global_end(void) pthread_mutex_destroy(&THR_LOCK_myisam_mmap); pthread_mutex_destroy(&THR_LOCK_heap); pthread_mutex_destroy(&THR_LOCK_net); + pthread_mutex_destroy(&THR_LOCK_time); pthread_mutex_destroy(&THR_LOCK_charset); if (all_threads_killed) { @@ -229,7 +234,7 @@ void my_thread_global_end(void) #endif } -static long thread_id=0; +static my_thread_id thread_id= 0; /* Allocate thread specific memory for the thread, used by mysys and dbug @@ -257,15 +262,16 @@ my_bool my_thread_init(void) my_bool error=0; #ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self()); + fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n", + (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 - fprintf(stderr,"my_thread_init() called more than once in thread %ld\n", - pthread_self()); + fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n", + (long) pthread_self()); #endif goto end; } @@ -285,7 +291,9 @@ my_bool my_thread_init(void) tmp= &THR_KEY_mysys; #endif #if defined(__WIN__) && defined(EMBEDDED_LIBRARY) - tmp->thread_self= (pthread_t)getpid(); + 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); @@ -295,6 +303,11 @@ my_bool my_thread_init(void) tmp->id= ++thread_id; ++THR_thread_count; pthread_mutex_unlock(&THR_LOCK_threads); +#ifndef DBUG_OFF + /* Generate unique name for thread */ + (void) my_thread_name(); +#endif + end: return error; } @@ -318,8 +331,8 @@ void my_thread_end(void) tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); #ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_end(): tmp: 0x%lx thread_id=%ld\n", - (long) tmp, pthread_self()); + fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n", + (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L); #endif if (tmp && tmp->init) { @@ -327,16 +340,17 @@ void my_thread_end(void) /* tmp->dbug is allocated inside DBUG library */ if (tmp->dbug) { + DBUG_POP(); free(tmp->dbug); tmp->dbug=0; } #endif -#if !defined(__bsdi__) && !defined(__OpenBSD__) || defined(HAVE_mit_thread) +#if !defined(__bsdi__) && !defined(__OpenBSD__) /* bsdi and openbsd 3.5 dumps core here */ pthread_cond_destroy(&tmp->suspend); #endif pthread_mutex_destroy(&tmp->mutex); -#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) +#if !defined(__WIN__) || defined(USE_TLS) free(tmp); #else tmp->init= 0; @@ -355,24 +369,14 @@ void my_thread_end(void) pthread_mutex_unlock(&THR_LOCK_threads); } /* The following free has to be done, even if my_thread_var() is 0 */ -#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) +#if !defined(__WIN__) || defined(USE_TLS) pthread_setspecific(THR_KEY_mysys,0); #endif } struct st_my_thread_var *_my_thread_var(void) { - struct st_my_thread_var *tmp= - my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); -#if defined(USE_TLS) - /* This can only happen in a .DLL */ - if (!tmp) - { - my_thread_init(); - tmp=my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - } -#endif - return tmp; + return my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); } @@ -380,17 +384,9 @@ struct st_my_thread_var *_my_thread_var(void) Get name of current thread. ****************************************************************************/ -#define UNKNOWN_THREAD -1 - -long my_thread_id() +my_thread_id my_thread_dbug_id() { -#if defined(HAVE_PTHREAD_GETSEQUENCE_NP) - return pthread_getsequence_np(pthread_self()); -#elif (defined(__sun) || defined(__sgi) || defined(__linux__)) && !defined(HAVE_mit_thread) - return pthread_self(); -#else return my_thread_var->id; -#endif } #ifdef DBUG_OFF @@ -407,8 +403,8 @@ const char *my_thread_name(void) struct st_my_thread_var *tmp=my_thread_var; if (!tmp->name[0]) { - long id=my_thread_id(); - sprintf(name_buff,"T@%ld", id); + my_thread_id id= my_thread_dbug_id(); + sprintf(name_buff,"T@%lu", (ulong) id); strmake(tmp->name,name_buff,THREAD_NAME_SIZE); } return tmp->name; diff --git a/mysys/my_vle.c b/mysys/my_vle.c new file mode 100644 index 00000000000..09f297eb553 --- /dev/null +++ b/mysys/my_vle.c @@ -0,0 +1,109 @@ +/* Copyright (C) 2005 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 */ + +/* + Variable length encoding. + + A method to store an arbitrary-size non-negative integer. We let the + most significant bit of the number indicate that the next byte + should be contatenated to form the real number. +*/ + +#include "my_vle.h" + +/* + Function to encode an unsigned long as VLE. The bytes for the VLE + will be written to the location pointed to by 'out'. The maximum + number of bytes written will be 'max'. + + PARAMETERS + + out Pointer to beginning of where to store VLE bytes. + max Maximum number of bytes to write. + n Number to encode. + + RETURN VALUE + On success, one past the end of the array containing the VLE + bytes. On failure, the 'out' pointer is returned. +*/ + +uchar* +my_vle_encode(uchar* out, size_t max, ulong n) +{ + uchar buf[my_vle_sizeof(n)]; + uchar *ptr= buf; + size_t len; + + do + { + *ptr++= (uchar) (n & 0x7F); + n>>= 7; + } + while (n > 0); + + len= ptr - buf; + + if (len <= max) + { + /* + The bytes are stored in reverse order in 'buf'. Let's write them + in correct order to the output buffer and set the MSB at the + same time. + */ + while (ptr-- > buf) + { + uchar v= *ptr; + if (ptr > buf) + v|= 0x80; + *out++= v; + } + } + + return out; +} + +/* + Function to decode a VLE representation of an integral value. + + + PARAMETERS + + result_ptr Pointer to an unsigned long where the value will be written. + vle Pointer to the VLE bytes. + + RETURN VALUE + + One-past the end of the VLE bytes. The routine will never read + more than sizeof(*result_ptr) + 1 bytes. +*/ + +uchar const* +my_vle_decode(ulong *result_ptr, uchar const *vle) +{ + ulong result= 0; + size_t cnt= 1; + + do + { + result<<= 7; + result|= (*vle & 0x7F); + } + while ((*vle++ & 0x80) && ++cnt <= sizeof(*result_ptr) + 1); + + if (cnt <= sizeof(*result_ptr) + 1) + *result_ptr= result; + + return vle; +} diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index b55df3569e0..43edac3ccbd 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /***************************************************************************** ** The following is a simple implementation of posix conditions @@ -121,7 +123,6 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, LeaveCriticalSection(&cond->lock_waiting); LeaveCriticalSection(mutex); - result= WaitForMultipleObjects(2, cond->events, FALSE, timeout); EnterCriticalSection(&cond->lock_waiting); @@ -202,7 +203,7 @@ int pthread_attr_setprio(pthread_attr_t *connect_att,int priority) int pthread_attr_destroy(pthread_attr_t *connect_att) { - bzero((gptr) connect_att,sizeof(*connect_att)); + bzero((uchar*) connect_att,sizeof(*connect_att)); return 0; } diff --git a/mysys/my_windac.c b/mysys/my_windac.c index c711093b48f..f846853f7be 100644 --- a/mysys/my_windac.c +++ b/mysys/my_windac.c @@ -194,8 +194,8 @@ error: FreeSid(everyone_sid); if (htoken) CloseHandle(htoken); - my_free((gptr) sa, MYF(MY_ALLOW_ZERO_PTR)); - my_free((gptr) dacl, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*) sa, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*) dacl, MYF(MY_ALLOW_ZERO_PTR)); *psa= 0; return 1; } @@ -215,8 +215,8 @@ void my_security_attr_free(SECURITY_ATTRIBUTES *sa) My_security_attr *attr= (My_security_attr*) (((char*)sa) + ALIGN_SIZE(sizeof(*sa))); FreeSid(attr->everyone_sid); - my_free((gptr) attr->dacl, MYF(0)); - my_free((gptr) sa, MYF(0)); + my_free((uchar*) attr->dacl, MYF(0)); + my_free((uchar*) sa, MYF(0)); } } diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index e94369bec32..611307f5f34 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -1,4 +1,6 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2001, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. + Use is subject to license terms. 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 @@ -11,7 +13,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /***************************************************************************** ** Simulation of posix threads calls for WIN95 and NT @@ -137,4 +140,36 @@ int win_pthread_setspecific(void *a,void *b,uint length) return 0; } + +/* + One time initialization. For simplicity, we assume initializer thread + does not exit within init_routine(). +*/ +int my_pthread_once(my_pthread_once_t *once_control, + void (*init_routine)(void)) +{ + LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, + MY_PTHREAD_ONCE_INIT); + switch(state) + { + case MY_PTHREAD_ONCE_INIT: + /* This is initializer thread */ + (*init_routine)(); + *once_control= MY_PTHREAD_ONCE_DONE; + break; + + case MY_PTHREAD_ONCE_INPROGRESS: + /* init_routine in progress. Wait for its completion */ + while(*once_control == MY_PTHREAD_ONCE_INPROGRESS) + { + Sleep(1); + } + break; + case MY_PTHREAD_ONCE_DONE: + /* Nothing to do */ + break; + } + return 0; +} + #endif diff --git a/mysys/my_write.c b/mysys/my_write.c index 8de0469d0f9..f261c768dcb 100644 --- a/mysys/my_write.c +++ b/mysys/my_write.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2001, 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2001, 2004-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ #include "mysys_priv.h" #include "mysys_err.h" @@ -21,14 +23,14 @@ /* Write a chunk of bytes to a file */ -uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) +size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags) { - uint writenbytes,errors; - ulong written; + size_t writenbytes, written; + uint errors; DBUG_ENTER("my_write"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %d MyFlags: %d", - Filedes, (long) Buffer, Count, MyFlags)); - errors=0; written=0L; + DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", + Filedes, (long) Buffer, (ulong) Count, MyFlags)); + errors=0; written=0; /* The behavior of write(fd, buf, 0) is not portable */ if (unlikely(!Count)) @@ -36,17 +38,17 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) for (;;) { - if ((writenbytes = (uint) write(Filedes, Buffer, Count)) == Count) + if ((writenbytes= write(Filedes, Buffer, Count)) == Count) break; - if ((int) writenbytes != -1) + if (writenbytes != (size_t) -1) { /* Safeguard */ written+=writenbytes; Buffer+=writenbytes; Count-=writenbytes; } my_errno=errno; - DBUG_PRINT("error",("Write only %d bytes, error: %d", - writenbytes,my_errno)); + DBUG_PRINT("error",("Write only %ld bytes, error: %d", + (long) writenbytes, my_errno)); #ifndef NO_BACKGROUND #ifdef THREAD if (my_thread_var->abort) @@ -60,12 +62,12 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags) continue; } - if ((writenbytes == 0 || (int) writenbytes == -1)) + if ((writenbytes == 0 || writenbytes == (size_t) -1)) { if (my_errno == EINTR) { - DBUG_PRINT("debug", ("my_write() was interrupted and returned %d", - (int) writenbytes)); + DBUG_PRINT("debug", ("my_write() was interrupted and returned %ld", + (long) writenbytes)); continue; /* Interrupted */ } diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 8a636e94626..6e0959ae08c 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -28,7 +28,7 @@ #include <my_pthread.h> extern pthread_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; extern pthread_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; -extern pthread_mutex_t THR_LOCK_charset; +extern pthread_mutex_t THR_LOCK_charset, THR_LOCK_time; #else #include <my_no_pthread.h> #endif @@ -40,3 +40,5 @@ extern pthread_mutex_t THR_LOCK_charset; #ifndef EDQUOT #define EDQUOT (-1) #endif + +void my_error_unregister_all(void); diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index 33c28160a4c..24ab6a1ea9c 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -22,15 +22,15 @@ #include "mysys_priv.h" #include <myisampack.h> -static int ptr_compare(uint *compare_length, uchar **a, uchar **b); -static int ptr_compare_0(uint *compare_length, uchar **a, uchar **b); -static int ptr_compare_1(uint *compare_length, uchar **a, uchar **b); -static int ptr_compare_2(uint *compare_length, uchar **a, uchar **b); -static int ptr_compare_3(uint *compare_length, uchar **a, uchar **b); +static int ptr_compare(size_t *compare_length, uchar **a, uchar **b); +static int ptr_compare_0(size_t *compare_length, uchar **a, uchar **b); +static int ptr_compare_1(size_t *compare_length, uchar **a, uchar **b); +static int ptr_compare_2(size_t *compare_length, uchar **a, uchar **b); +static int ptr_compare_3(size_t *compare_length, uchar **a, uchar **b); /* Get a pointer to a optimal byte-compare function for a given size */ -qsort2_cmp get_ptr_compare (uint size) +qsort2_cmp get_ptr_compare (size_t size) { if (size < 4) return (qsort2_cmp) ptr_compare; @@ -51,7 +51,7 @@ qsort2_cmp get_ptr_compare (uint size) #define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N] -static int ptr_compare(uint *compare_length, uchar **a, uchar **b) +static int ptr_compare(size_t *compare_length, uchar **a, uchar **b) { reg3 int length= *compare_length; reg1 uchar *first,*last; @@ -66,7 +66,7 @@ static int ptr_compare(uint *compare_length, uchar **a, uchar **b) } -static int ptr_compare_0(uint *compare_length,uchar **a, uchar **b) +static int ptr_compare_0(size_t *compare_length,uchar **a, uchar **b) { reg3 int length= *compare_length; reg1 uchar *first,*last; @@ -87,7 +87,7 @@ static int ptr_compare_0(uint *compare_length,uchar **a, uchar **b) } -static int ptr_compare_1(uint *compare_length,uchar **a, uchar **b) +static int ptr_compare_1(size_t *compare_length,uchar **a, uchar **b) { reg3 int length= *compare_length-1; reg1 uchar *first,*last; @@ -108,7 +108,7 @@ static int ptr_compare_1(uint *compare_length,uchar **a, uchar **b) return (0); } -static int ptr_compare_2(uint *compare_length,uchar **a, uchar **b) +static int ptr_compare_2(size_t *compare_length,uchar **a, uchar **b) { reg3 int length= *compare_length-2; reg1 uchar *first,*last; @@ -130,7 +130,7 @@ static int ptr_compare_2(uint *compare_length,uchar **a, uchar **b) return (0); } -static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b) +static int ptr_compare_3(size_t *compare_length,uchar **a, uchar **b) { reg3 int length= *compare_length-3; reg1 uchar *first,*last; @@ -153,7 +153,7 @@ static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b) return (0); } -void my_store_ptr(byte *buff, uint pack_length, my_off_t pos) +void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos) { switch (pack_length) { #if SIZEOF_OFF_T > 4 @@ -171,7 +171,7 @@ void my_store_ptr(byte *buff, uint pack_length, my_off_t pos) return; } -my_off_t my_get_ptr(byte *ptr, uint pack_length) +my_off_t my_get_ptr(uchar *ptr, size_t pack_length) { my_off_t pos; switch (pack_length) { @@ -184,7 +184,7 @@ my_off_t my_get_ptr(byte *ptr, uint pack_length) case 4: pos= (my_off_t) mi_uint4korr(ptr); break; case 3: pos= (my_off_t) mi_uint3korr(ptr); break; case 2: pos= (my_off_t) mi_uint2korr(ptr); break; - case 1: pos= (my_off_t) mi_uint2korr(ptr); break; + case 1: pos= (my_off_t) *(uchar*) ptr; break; default: DBUG_ASSERT(0); return 0; } return pos; diff --git a/mysys/queues.c b/mysys/queues.c index 6b88420a1cd..9c85e493141 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000, 2005 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 @@ -16,6 +16,10 @@ /* Code for generell handling of priority Queues. Implemention of queues from "Algoritms in C" by Robert Sedgewick. + An optimisation of _downheap suggested in Exercise 7.51 in "Data + Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition + was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm + of queue_fix was implemented. */ #include "mysys_priv.h" @@ -45,11 +49,11 @@ */ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, - pbool max_at_top, int (*compare) (void *, byte *, byte *), + pbool max_at_top, int (*compare) (void *, uchar *, uchar *), void *first_cmp_arg) { DBUG_ENTER("init_queue"); - if ((queue->root= (byte **) my_malloc((max_elements+1)*sizeof(void*), + if ((queue->root= (uchar **) my_malloc((max_elements+1)*sizeof(void*), MYF(MY_WME))) == 0) DBUG_RETURN(1); queue->elements=0; @@ -57,11 +61,51 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, queue->first_cmp_arg=first_cmp_arg; queue->max_elements=max_elements; queue->offset_to_key=offset_to_key; - queue->max_at_top= max_at_top ? (-1 ^ 1) : 0; + queue_set_max_at_top(queue, max_at_top); DBUG_RETURN(0); } + +/* + Init queue, uses init_queue internally for init work but also accepts + auto_extent as parameter + + SYNOPSIS + init_queue_ex() + queue Queue to initialise + max_elements Max elements that will be put in queue + offset_to_key Offset to key in element stored in queue + Used when sending pointers to compare function + max_at_top Set to 1 if you want biggest element on top. + compare Compare function for elements, takes 3 arguments. + first_cmp_arg First argument to compare function + auto_extent When the queue is full and there is insert operation + extend the queue. + + NOTES + Will allocate max_element pointers for queue array + + RETURN + 0 ok + 1 Could not allocate memory +*/ + +int init_queue_ex(QUEUE *queue, uint max_elements, uint offset_to_key, + pbool max_at_top, int (*compare) (void *, uchar *, uchar *), + void *first_cmp_arg, uint auto_extent) +{ + int ret; + DBUG_ENTER("init_queue_ex"); + + if ((ret= init_queue(queue, max_elements, offset_to_key, max_at_top, compare, + first_cmp_arg))) + DBUG_RETURN(ret); + + queue->auto_extent= auto_extent; + DBUG_RETURN(0); +} + /* Reinitialize queue for other usage @@ -85,7 +129,7 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, */ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, - pbool max_at_top, int (*compare) (void *, byte *, byte *), + pbool max_at_top, int (*compare) (void *, uchar *, uchar *), void *first_cmp_arg) { DBUG_ENTER("reinit_queue"); @@ -93,7 +137,7 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, queue->compare=compare; queue->first_cmp_arg=first_cmp_arg; queue->offset_to_key=offset_to_key; - queue->max_at_top= max_at_top ? (-1 ^ 1) : 0; + queue_set_max_at_top(queue, max_at_top); resize_queue(queue, max_elements); DBUG_RETURN(0); } @@ -118,11 +162,11 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, int resize_queue(QUEUE *queue, uint max_elements) { - byte **new_root; + uchar **new_root; DBUG_ENTER("resize_queue"); if (queue->max_elements == max_elements) DBUG_RETURN(0); - if ((new_root= (byte **) my_realloc((void *)queue->root, + if ((new_root= (uchar **) my_realloc((void *)queue->root, (max_elements+1)*sizeof(void*), MYF(MY_WME))) == 0) DBUG_RETURN(1); @@ -152,7 +196,7 @@ void delete_queue(QUEUE *queue) DBUG_ENTER("delete_queue"); if (queue->root) { - my_free((gptr) queue->root,MYF(0)); + my_free((uchar*) queue->root,MYF(0)); queue->root=0; } DBUG_VOID_RETURN; @@ -161,19 +205,17 @@ void delete_queue(QUEUE *queue) /* Code for insert, search and delete of elements */ -void queue_insert(register QUEUE *queue, byte *element) +void queue_insert(register QUEUE *queue, uchar *element) { reg2 uint idx, next; - int cmp; DBUG_ASSERT(queue->elements < queue->max_elements); queue->root[0]= element; idx= ++queue->elements; /* max_at_top swaps the comparison if we want to order by desc */ - while ((cmp= queue->compare(queue->first_cmp_arg, - element + queue->offset_to_key, - queue->root[(next= idx >> 1)] + - queue->offset_to_key)) && - (cmp ^ queue->max_at_top) < 0) + while ((queue->compare(queue->first_cmp_arg, + element + queue->offset_to_key, + queue->root[(next= idx >> 1)] + + queue->offset_to_key) * queue->max_at_top) < 0) { queue->root[idx]= queue->root[next]; idx= next; @@ -181,12 +223,37 @@ void queue_insert(register QUEUE *queue, byte *element) queue->root[idx]= element; } +/* + Does safe insert. If no more space left on the queue resize it. + Return codes: + 0 - OK + 1 - Cannot allocate more memory + 2 - auto_extend is 0, the operation would + +*/ + +int queue_insert_safe(register QUEUE *queue, uchar *element) +{ + + if (queue->elements == queue->max_elements) + { + if (!queue->auto_extent) + return 2; + else if (resize_queue(queue, queue->max_elements + queue->auto_extent)) + return 1; + } + + queue_insert(queue, element); + return 0; +} + + /* Remove item from queue */ /* Returns pointer to removed element */ -byte *queue_remove(register QUEUE *queue, uint idx) +uchar *queue_remove(register QUEUE *queue, uint idx) { - byte *element; + uchar *element; DBUG_ASSERT(idx < queue->max_elements); element= queue->root[++idx]; /* Intern index starts from 1 */ queue->root[idx]= queue->root[queue->elements--]; @@ -203,13 +270,14 @@ void queue_replaced(QUEUE *queue) } #endif - /* Fix heap when index have changed */ +#ifndef OLD_VERSION void _downheap(register QUEUE *queue, uint idx) { - byte *element; - uint elements,half_queue,next_index,offset_to_key; - int cmp; + uchar *element; + uint elements,half_queue,offset_to_key, next_index; + my_bool first= TRUE; + uint start_idx= idx; offset_to_key=queue->offset_to_key; element=queue->root[idx]; @@ -221,35 +289,402 @@ void _downheap(register QUEUE *queue, uint idx) if (next_index < elements && (queue->compare(queue->first_cmp_arg, queue->root[next_index]+offset_to_key, - queue->root[next_index+1]+offset_to_key) ^ + queue->root[next_index+1]+offset_to_key) * queue->max_at_top) > 0) next_index++; - if ((cmp=queue->compare(queue->first_cmp_arg, - queue->root[next_index]+offset_to_key, - element+offset_to_key)) == 0 || - (cmp ^ queue->max_at_top) > 0) + if (first && + (((queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + element+offset_to_key) * queue->max_at_top) >= 0))) + { + queue->root[idx]= element; + return; + } + queue->root[idx]=queue->root[next_index]; + idx=next_index; + first= FALSE; + } + + next_index= idx >> 1; + while (next_index > start_idx) + { + if ((queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + element+offset_to_key) * + queue->max_at_top) < 0) break; queue->root[idx]=queue->root[next_index]; idx=next_index; + next_index= idx >> 1; } queue->root[idx]=element; } - -static int queue_fix_cmp(QUEUE *queue, void **a, void **b) +#else + /* + The old _downheap version is kept for comparisons with the benchmark + suit or new benchmarks anyone wants to run for comparisons. + */ + /* Fix heap when index have changed */ +void _downheap(register QUEUE *queue, uint idx) { - return queue->compare(queue->first_cmp_arg, - (byte*) (*a)+queue->offset_to_key, - (byte*) (*b)+queue->offset_to_key); + uchar *element; + uint elements,half_queue,next_index,offset_to_key; + + offset_to_key=queue->offset_to_key; + element=queue->root[idx]; + half_queue=(elements=queue->elements) >> 1; + + while (idx <= half_queue) + { + next_index=idx+idx; + if (next_index < elements && + (queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + queue->root[next_index+1]+offset_to_key) * + queue->max_at_top) > 0) + next_index++; + if ((queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + element+offset_to_key) * queue->max_at_top) >= 0) + break; + queue->root[idx]=queue->root[next_index]; + idx=next_index; + } + queue->root[idx]=element; } + +#endif + /* - Fix heap when every element was changed, - actually, it can be done better, in linear time, not in n*log(n) + Fix heap when every element was changed. */ void queue_fix(QUEUE *queue) { - my_qsort2(queue->root+1,queue->elements, sizeof(void *), - (qsort2_cmp)queue_fix_cmp, queue); + uint i; + for (i= queue->elements >> 1; i > 0; i--) + _downheap(queue, i); +} + +#ifdef MAIN + /* + A test program for the priority queue implementation. + It can also be used to benchmark changes of the implementation + Build by doing the following in the directory mysys + make test_priority_queue + ./test_priority_queue + + Written by Mikael Ronström, 2005 + */ + +static uint num_array[1025]; +static uint tot_no_parts= 0; +static uint tot_no_loops= 0; +static uint expected_part= 0; +static uint expected_num= 0; +static bool max_ind= 0; +static bool fix_used= 0; +static ulonglong start_time= 0; + +static bool is_divisible_by(uint num, uint divisor) +{ + uint quotient= num / divisor; + if (quotient * divisor == num) + return TRUE; + return FALSE; +} + +void calculate_next() +{ + uint part= expected_part, num= expected_num; + uint no_parts= tot_no_parts; + if (max_ind) + { + do + { + while (++part <= no_parts) + { + if (is_divisible_by(num, part) && + (num <= ((1 << 21) + part))) + { + expected_part= part; + expected_num= num; + return; + } + } + part= 0; + } while (--num); + } + else + { + do + { + while (--part > 0) + { + if (is_divisible_by(num, part)) + { + expected_part= part; + expected_num= num; + return; + } + } + part= no_parts + 1; + } while (++num); + } +} + +void calculate_end_next(uint part) +{ + uint no_parts= tot_no_parts, num; + num_array[part]= 0; + if (max_ind) + { + expected_num= 0; + for (part= no_parts; part > 0 ; part--) + { + if (num_array[part]) + { + num= num_array[part] & 0x3FFFFF; + if (num >= expected_num) + { + expected_num= num; + expected_part= part; + } + } + } + if (expected_num == 0) + expected_part= 0; + } + else + { + expected_num= 0xFFFFFFFF; + for (part= 1; part <= no_parts; part++) + { + if (num_array[part]) + { + num= num_array[part] & 0x3FFFFF; + if (num <= expected_num) + { + expected_num= num; + expected_part= part; + } + } + } + if (expected_num == 0xFFFFFFFF) + expected_part= 0; + } + return; +} +static int test_compare(void *null_arg, uchar *a, uchar *b) +{ + uint a_num= (*(uint*)a) & 0x3FFFFF; + uint b_num= (*(uint*)b) & 0x3FFFFF; + uint a_part, b_part; + if (a_num > b_num) + return +1; + if (a_num < b_num) + return -1; + a_part= (*(uint*)a) >> 22; + b_part= (*(uint*)b) >> 22; + if (a_part < b_part) + return +1; + if (a_part > b_part) + return -1; + return 0; +} + +bool check_num(uint num_part) +{ + uint part= num_part >> 22; + uint num= num_part & 0x3FFFFF; + if (part == expected_part) + if (num == expected_num) + return FALSE; + printf("Expect part %u Expect num 0x%x got part %u num 0x%x max_ind %u fix_used %u \n", + expected_part, expected_num, part, num, max_ind, fix_used); + return TRUE; +} + + +void perform_insert(QUEUE *queue) +{ + uint i= 1, no_parts= tot_no_parts; + uint backward_start= 0; + + expected_part= 1; + expected_num= 1; + + if (max_ind) + backward_start= 1 << 21; + + do + { + uint num= (i + backward_start); + if (max_ind) + { + while (!is_divisible_by(num, i)) + num--; + if (max_ind && (num > expected_num || + (num == expected_num && i < expected_part))) + { + expected_num= num; + expected_part= i; + } + } + num_array[i]= num + (i << 22); + if (fix_used) + queue_element(queue, i-1)= (uchar*)&num_array[i]; + else + queue_insert(queue, (uchar*)&num_array[i]); + } while (++i <= no_parts); + if (fix_used) + { + queue->elements= no_parts; + queue_fix(queue); + } +} + +bool perform_ins_del(QUEUE *queue, bool max_ind) +{ + uint i= 0, no_loops= tot_no_loops, j= tot_no_parts; + do + { + uint num_part= *(uint*)queue_top(queue); + uint part= num_part >> 22; + if (check_num(num_part)) + return TRUE; + if (j++ >= no_loops) + { + calculate_end_next(part); + queue_remove(queue, (uint) 0); + } + else + { + calculate_next(); + if (max_ind) + num_array[part]-= part; + else + num_array[part]+= part; + queue_top(queue)= (uchar*)&num_array[part]; + queue_replaced(queue); + } + } while (++i < no_loops); + return FALSE; +} + +bool do_test(uint no_parts, uint l_max_ind, bool l_fix_used) +{ + QUEUE queue; + bool result; + max_ind= l_max_ind; + fix_used= l_fix_used; + init_queue(&queue, no_parts, 0, max_ind, test_compare, NULL); + tot_no_parts= no_parts; + tot_no_loops= 1024; + perform_insert(&queue); + if ((result= perform_ins_del(&queue, max_ind))) + delete_queue(&queue); + if (result) + { + printf("Error\n"); + return TRUE; + } + return FALSE; +} + +static void start_measurement() +{ + start_time= my_getsystime(); } + +static void stop_measurement() +{ + ulonglong stop_time= my_getsystime(); + uint time_in_micros; + stop_time-= start_time; + stop_time/= 10; /* Convert to microseconds */ + time_in_micros= (uint)stop_time; + printf("Time expired is %u microseconds \n", time_in_micros); +} + +static void benchmark_test() +{ + QUEUE queue_real; + QUEUE *queue= &queue_real; + uint i, add; + fix_used= TRUE; + max_ind= FALSE; + tot_no_parts= 1024; + init_queue(queue, tot_no_parts, 0, max_ind, test_compare, NULL); + /* + First benchmark whether queue_fix is faster than using queue_insert + for sizes of 16 partitions. + */ + for (tot_no_parts= 2, add=2; tot_no_parts < 128; + tot_no_parts+= add, add++) + { + printf("Start benchmark queue_fix, tot_no_parts= %u \n", tot_no_parts); + start_measurement(); + for (i= 0; i < 128; i++) + { + perform_insert(queue); + queue_remove_all(queue); + } + stop_measurement(); + + fix_used= FALSE; + printf("Start benchmark queue_insert\n"); + start_measurement(); + for (i= 0; i < 128; i++) + { + perform_insert(queue); + queue_remove_all(queue); + } + stop_measurement(); + } + /* + Now benchmark insertion and deletion of 16400 elements. + Used in consecutive runs this shows whether the optimised _downheap + is faster than the standard implementation. + */ + printf("Start benchmarking _downheap \n"); + start_measurement(); + perform_insert(queue); + for (i= 0; i < 65536; i++) + { + uint num, part; + num= *(uint*)queue_top(queue); + num+= 16; + part= num >> 22; + num_array[part]= num; + queue_top(queue)= (uchar*)&num_array[part]; + queue_replaced(queue); + } + for (i= 0; i < 16; i++) + queue_remove(queue, (uint) 0); + queue_remove_all(queue); + stop_measurement(); +} + +int main() +{ + int i, add= 1; + for (i= 1; i < 1024; i+=add, add++) + { + printf("Start test for priority queue of size %u\n", i); + if (do_test(i, 0, 1)) + return -1; + if (do_test(i, 1, 1)) + return -1; + if (do_test(i, 0, 0)) + return -1; + if (do_test(i, 1, 0)) + return -1; + } + benchmark_test(); + printf("OK\n"); + return 0; +} +#endif diff --git a/mysys/raid.cc b/mysys/raid.cc deleted file mode 100644 index 0fbe1810208..00000000000 --- a/mysys/raid.cc +++ /dev/null @@ -1,798 +0,0 @@ -/* Copyright (C) 2000 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 */ - -/* - - RAID support for MySQL. Raid 0 (stiping) only implemented yet. - - Why RAID? Why it must be in MySQL? - - This is because then you can: - 1. Have bigger tables than your OS limit. In time of writing this - we are hitting to 2GB limit under linux/ext2 - 2. You can get more speed from IO bottleneck by putting - Raid dirs on different physical disks. - 3. Getting more fault tolerance (not implemented yet) - - Why not to use RAID: - - 1. You are losing some processor power to calculate things, - do more syscalls and interrupts. - - Functionality is supplied by two classes: RaidFd and RaidName. - RaidFd supports funtionality over file descriptors like - open/create/write/seek/close. RaidName supports functionality - like rename/delete where we have no relations to filedescriptors. - RaidName can be prorably unchanged for different Raid levels. RaidFd - have to be virtual I think ;). - You can speed up some calls in MySQL code by skipping RAID code. - For example LOAD DATA INFILE never needs to read RAID-ed files. - This can be done adding proper "#undef my_read" or similar undef-s - in your code. Check out the raid.h! - - Some explanation about _seek_vector[] - This is seek cache. RAID seeks too much and we cacheing this. We - fool it and just storing new position in file to _seek_vector. - When there is no seeks to do, we are putting RAID_SEEK_DONE into it. - Any other value requires seeking to that position. - - TODO: - - - - Implement other fancy things like RAID 1 (mirroring) and RAID 5. - Should not to be very complex. - - - Optimize big blob writes by resorting write buffers and writing - big chunks at once instead of doing many syscalls. - after thinking I - found this is useless. This is because same thing one can do with just - increasing RAID_CHUNKSIZE. Monty, what do you think? tonu. - - - If needed, then implement missing syscalls. One known to miss is stat(); - - - Make and use a thread safe dynamic_array buffer. The used one - will not work if needs to be extended at the same time someone is - accessing it. - - - tonu@mysql.com & monty@mysql.com -*/ - -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - -#include "mysys_priv.h" -#include <my_dir.h> -#include <m_string.h> -#include <assert.h> - -#if defined(USE_RAID) && !defined(MYSQL_CLIENT) - -#define RAID_SEEK_DONE ~(off_t) 0 -#define RAID_SIZE_UNKNOWN ~(my_off_t) 0 - -DYNAMIC_ARRAY RaidFd::_raid_map; - - -/* --------------- C compatibility ---------------*/ - -extern "C" { - - void init_raid(void) - { - /* Allocate memory for global file to raid map */ - my_init_dynamic_array(&RaidFd::_raid_map, sizeof(RaidFd*), 4096, 1024); - } - void end_raid(void) - { - /* Free memory used by raid */ - delete_dynamic(&RaidFd::_raid_map); - } - - bool is_raid(File fd) - { - return RaidFd::IsRaid(fd); - } - - File my_raid_create(const char *FileName, int CreateFlags, int access_flags, - uint raid_type, uint raid_chunks, ulong raid_chunksize, - myf MyFlags) - { - DBUG_ENTER("my_raid_create"); - DBUG_PRINT("enter",("Filename: %s CreateFlags: %d access_flags: %d MyFlags: %d", - FileName, CreateFlags, access_flags, MyFlags)); - if (raid_type) - { - RaidFd *raid = new RaidFd(raid_type, raid_chunks , raid_chunksize); - File res = raid->Create(FileName,CreateFlags,access_flags,MyFlags); - if (res < 0 || set_dynamic(&RaidFd::_raid_map,(char*) &raid,res)) - { - delete raid; - DBUG_RETURN(-1); - } - DBUG_RETURN(res); - } - else - DBUG_RETURN(my_create(FileName, CreateFlags, access_flags, MyFlags)); - } - - File my_raid_open(const char *FileName, int Flags, - uint raid_type, uint raid_chunks, ulong raid_chunksize, - myf MyFlags) - { - DBUG_ENTER("my_raid_open"); - DBUG_PRINT("enter",("Filename: %s Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); - if (raid_type) - { - RaidFd *raid = new RaidFd(raid_type, raid_chunks , raid_chunksize); - File res = raid->Open(FileName,Flags,MyFlags); - if (res < 0 || set_dynamic(&RaidFd::_raid_map,(char*) &raid,res)) - { - delete raid; - DBUG_RETURN(-1); - } - DBUG_RETURN(res); - } - else - DBUG_RETURN(my_open(FileName, Flags, MyFlags)); - } - - my_off_t my_raid_seek(File fd, my_off_t pos,int whence,myf MyFlags) - { - DBUG_ENTER("my_raid_seek"); - DBUG_PRINT("enter",("Fd: %d pos: %lu whence: %d MyFlags: %d", - fd, (ulong) pos, whence, MyFlags)); - - if (is_raid(fd)) - { - assert(pos != MY_FILEPOS_ERROR); - - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Seek(pos,whence,MyFlags)); - } - else - DBUG_RETURN(my_seek(fd, pos, whence, MyFlags)); - } - - my_off_t my_raid_tell(File fd,myf MyFlags) - { - DBUG_ENTER("my_raid_tell"); - DBUG_PRINT("enter",("Fd: %d MyFlags: %d", - fd, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Tell(MyFlags)); - } - else - DBUG_RETURN(my_tell(fd, MyFlags)); - } - - uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags) - { - DBUG_ENTER("my_raid_write"); - DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - fd, Buffer, Count, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Write(Buffer,Count,MyFlags)); - } else - DBUG_RETURN(my_write(fd,Buffer,Count,MyFlags)); - } - - uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags) - { - DBUG_ENTER("my_raid_read"); - DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - fd, Buffer, Count, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Read(Buffer,Count,MyFlags)); - } else - DBUG_RETURN(my_read(fd,Buffer,Count,MyFlags)); - } - - uint my_raid_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, - myf MyFlags) - { - DBUG_ENTER("my_raid_pread"); - DBUG_PRINT("enter", - ("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d", - Filedes, Buffer, Count, offset, MyFlags)); - if (is_raid(Filedes)) - { - assert(offset != MY_FILEPOS_ERROR); - - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,Filedes,RaidFd**)); - /* Returning value isn't important because real seek is done later. */ - raid->Seek(offset,MY_SEEK_SET,MyFlags); - DBUG_RETURN(raid->Read(Buffer,Count,MyFlags)); - } - else - DBUG_RETURN(my_pread(Filedes, Buffer, Count, offset, MyFlags)); - } - - uint my_raid_pwrite(int Filedes, const byte *Buffer, uint Count, - my_off_t offset, myf MyFlags) - { - DBUG_ENTER("my_raid_pwrite"); - DBUG_PRINT("enter", - ("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d", - Filedes, Buffer, Count, offset, MyFlags)); - if (is_raid(Filedes)) - { - assert(offset != MY_FILEPOS_ERROR); - - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,Filedes,RaidFd**)); - /* Returning value isn't important because real seek is done later. */ - raid->Seek(offset,MY_SEEK_SET,MyFlags); - DBUG_RETURN(raid->Write(Buffer,Count,MyFlags)); - } - else - DBUG_RETURN(my_pwrite(Filedes, Buffer, Count, offset, MyFlags)); - } - - int my_raid_lock(File fd, int locktype, my_off_t start, my_off_t length, - myf MyFlags) - { - DBUG_ENTER("my_raid_lock"); - DBUG_PRINT("enter",("Fd: %d start: %lu length: %lu MyFlags: %d", - fd, (ulong) start, (ulong) length, MyFlags)); - if (my_disable_locking) - DBUG_RETURN(0); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Lock(locktype, start, length, MyFlags)); - } - else - DBUG_RETURN(my_lock(fd, locktype, start, length, MyFlags)); - } - - int my_raid_close(File fd, myf MyFlags) - { - DBUG_ENTER("my_raid_close"); - DBUG_PRINT("enter",("Fd: %d MyFlags: %d", - fd, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - RaidFd *tmp=0; - set_dynamic(&RaidFd::_raid_map,(char*) &tmp,fd); - int res = raid->Close(MyFlags); - delete raid; - DBUG_RETURN(res); - } - else - DBUG_RETURN(my_close(fd, MyFlags)); - } - - int my_raid_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) - { - DBUG_ENTER("my_raid_chsize"); - DBUG_PRINT("enter",("Fd: %d newlength: %lu MyFlags: %d", - fd, (ulong) newlength, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Chsize(fd, newlength, filler, MyFlags)); - } - else - DBUG_RETURN(my_chsize(fd, newlength, filler, MyFlags)); - } - - int my_raid_rename(const char *from, const char *to, - uint raid_chunks, myf MyFlags) - { - char from_tmp[FN_REFLEN]; - char to_tmp[FN_REFLEN]; - DBUG_ENTER("my_raid_rename"); - - uint from_pos = dirname_length(from); - uint to_pos = dirname_length(to); - memcpy(from_tmp, from, from_pos); - memcpy(to_tmp, to, to_pos); - for (uint i = 0 ; i < raid_chunks ; i++ ) - { - sprintf(from_tmp+from_pos,"%02x/%s", i, from + from_pos); - sprintf(to_tmp+to_pos,"%02x/%s", i, to+ to_pos); - /* Convert if not unix */ - unpack_filename(from_tmp, from_tmp); - unpack_filename(to_tmp,to_tmp); - if (my_rename(from_tmp, to_tmp, MyFlags)) - DBUG_RETURN(-1); - } - DBUG_RETURN(0); - } - - int my_raid_delete(const char *from, uint raid_chunks, myf MyFlags) - { - char from_tmp[FN_REFLEN]; - uint from_pos = dirname_length(from); - DBUG_ENTER("my_raid_delete"); - - if (!raid_chunks) - DBUG_RETURN(my_delete(from,MyFlags)); - for (uint i = 0 ; i < raid_chunks ; i++ ) - { - memcpy(from_tmp, from, from_pos); - sprintf(from_tmp+from_pos,"%02x/%s", i, from + from_pos); - /* Convert if not unix */ - unpack_filename(from_tmp, from_tmp); - if (my_delete(from_tmp, MyFlags)) - DBUG_RETURN(-1); - } - DBUG_RETURN(0); - } - - int my_raid_redel(const char *old_name, const char *new_name, - uint raid_chunks, myf MyFlags) - { - char new_name_buff[FN_REFLEN], old_name_buff[FN_REFLEN]; - char *new_end, *old_end; - uint i,old_length,new_length; - int error=0; - DBUG_ENTER("my_raid_redel"); - - old_end=old_name_buff+dirname_part(old_name_buff,old_name); - old_length=dirname_length(old_name); - new_end=new_name_buff+dirname_part(new_name_buff,new_name); - new_length=dirname_length(new_name); - for (i=0 ; i < raid_chunks ; i++) - { - MY_STAT status; - sprintf(new_end,"%02x",i); - if (my_stat(new_name_buff,&status, MYF(0))) - { - DBUG_PRINT("info",("%02x exists, skipping directory creation",i)); - } - else - { - if (my_mkdir(new_name_buff,0777,MYF(0))) - { - DBUG_PRINT("error",("mkdir failed for %02x",i)); - DBUG_RETURN(-1); - } - } - strxmov(strend(new_end),"/",new_name+new_length,NullS); - sprintf(old_end,"%02x/%s",i, old_name+old_length); - if (my_redel(old_name_buff, new_name_buff, MyFlags)) - error=1; - } - DBUG_RETURN(error); - } -} - -int my_raid_fstat(int fd, MY_STAT *stat_area, myf MyFlags ) -{ - DBUG_ENTER("my_raid_fstat"); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Fstat(fd, stat_area, MyFlags)); - } - else - DBUG_RETURN(my_fstat(fd, stat_area, MyFlags)); -} - - -/* -------------- RaidFd base class begins ----------------*/ -/* - RaidFd - raided file is identified by file descriptor - this is useful when we open/write/read/close files -*/ - - -bool RaidFd:: -IsRaid(File fd) -{ - DBUG_ENTER("RaidFd::IsRaid"); - DBUG_RETURN((uint) fd < _raid_map.elements && - *dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); -} - - -RaidFd:: -RaidFd(uint raid_type, uint raid_chunks, ulong raid_chunksize) - :_raid_type(raid_type), _raid_chunks(raid_chunks), - _raid_chunksize(raid_chunksize), _position(0), _size(RAID_SIZE_UNKNOWN), - _fd_vector(0) -{ - DBUG_ENTER("RaidFd::RaidFd"); - DBUG_PRINT("enter",("RaidFd_type: %u Disks: %u Chunksize: %lu", - raid_type, raid_chunks, raid_chunksize)); - - /* TODO: Here we should add checks if the malloc fails */ - _seek_vector=0; /* In case of errors */ - my_multi_malloc(MYF(MY_WME), - &_seek_vector,sizeof(off_t)*_raid_chunks, - &_fd_vector, sizeof(File) *_raid_chunks, - NullS); - if (!RaidFd::_raid_map.buffer) - { /* Not initied */ - pthread_mutex_lock(&THR_LOCK_open); /* Ensure that no other thread */ - if (!RaidFd::_raid_map.buffer) /* has done init in between */ - init_raid(); - pthread_mutex_unlock(&THR_LOCK_open); - } - DBUG_VOID_RETURN; -} - - -RaidFd:: -~RaidFd() { - DBUG_ENTER("RaidFd::~RaidFd"); - /* We don't have to free _fd_vector ! */ - my_free((char*) _seek_vector, MYF(MY_ALLOW_ZERO_PTR)); - DBUG_VOID_RETURN; -} - - -File RaidFd:: -Create(const char *FileName, int CreateFlags, int access_flags, myf MyFlags) -{ - char RaidFdFileName[FN_REFLEN]; - DBUG_ENTER("RaidFd::Create"); - DBUG_PRINT("enter", - ("FileName: %s CreateFlags: %d access_flags: %d MyFlags: %d", - FileName, CreateFlags, access_flags, MyFlags)); - char DirName[FN_REFLEN]; - uint pos = dirname_part(DirName, FileName); - MY_STAT status; - if (!_seek_vector) - DBUG_RETURN(-1); /* Not enough memory */ - - uint i = _raid_chunks-1; - do - { - /* Create subdir */ - (void)sprintf(RaidFdFileName,"%s%02x", DirName,i); - unpack_dirname(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ - if (my_stat(RaidFdFileName,&status, MYF(0))) - { - DBUG_PRINT("info",("%02x exists, skipping directory creation",i)); - } - else - { - if (my_mkdir(RaidFdFileName,0777,MYF(0))) - { - DBUG_PRINT("error",("mkdir failed for %d",i)); - goto error; - } - } - /* Create file */ - sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); - unpack_filename(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ - _fd = my_create(RaidFdFileName, CreateFlags ,access_flags, (myf)MyFlags); - if (_fd < 0) - goto error; - _fd_vector[i]=_fd; - _seek_vector[i]=RAID_SEEK_DONE; - } while (i--); - _size=0; - DBUG_RETURN(_fd); /* Last filenr is pointer to map */ - -error: - { - int save_errno=my_errno; - while (++i < _raid_chunks) - { - my_close(_fd_vector[i],MYF(0)); - sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); - unpack_filename(RaidFdFileName,RaidFdFileName); - my_delete(RaidFdFileName,MYF(0)); - } - my_errno=save_errno; - } - DBUG_RETURN(-1); -} - - -File RaidFd:: -Open(const char *FileName, int Flags, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Open"); - DBUG_PRINT("enter",("FileName: %s Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); - char DirName[FN_REFLEN]; - uint pos = dirname_part(DirName, FileName); - if (!_seek_vector) - DBUG_RETURN(-1); /* Not enough memory */ - - for( uint i = 0 ; i < _raid_chunks ; i++ ) - { - char RaidFdFileName[FN_REFLEN]; - sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); - unpack_filename(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ - _fd = my_open(RaidFdFileName, Flags, MyFlags); - if (_fd < 0) - { - int save_errno=my_errno; - while (i-- != 0) - my_close(_fd_vector[i],MYF(0)); - my_errno=save_errno; - DBUG_RETURN(_fd); - } - _fd_vector[i]=_fd; - _seek_vector[i]=RAID_SEEK_DONE; - } - Seek(0L,MY_SEEK_END,MYF(0)); // Trick. We just need to know, how big the file is - DBUG_PRINT("info",("MYD file logical size: %llu", _size)); - DBUG_RETURN(_fd); -} - - -int RaidFd:: -Write(const byte *Buffer, uint Count, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Write"); - DBUG_PRINT("enter",("Count: %d MyFlags: %d", - Count, MyFlags)); - const byte *bufptr = Buffer; - uint res=0, GotBytes, ReadNowCount; - - // Loop until data is written - do { - Calculate(); - // Do seeks when neccessary - if (_seek_vector[_this_block] != RAID_SEEK_DONE) - { - if (my_seek(_fd_vector[_this_block], _seek_vector[_this_block], - MY_SEEK_SET, - MyFlags) == MY_FILEPOS_ERROR) - DBUG_RETURN(-1); - _seek_vector[_this_block]=RAID_SEEK_DONE; - } - ReadNowCount = min(Count, _remaining_bytes); - GotBytes = my_write(_fd_vector[_this_block], bufptr, ReadNowCount, - MyFlags); - DBUG_PRINT("loop",("Wrote bytes: %d", GotBytes)); - if (GotBytes == MY_FILE_ERROR) - DBUG_RETURN(-1); - res+= GotBytes; - if (MyFlags & (MY_NABP | MY_FNABP)) - GotBytes=ReadNowCount; - bufptr += GotBytes; - Count -= GotBytes; - _position += GotBytes; - } while(Count); - set_if_bigger(_size,_position); - DBUG_RETURN(res); -} - - -int RaidFd:: -Read(const byte *Buffer, uint Count, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Read"); - DBUG_PRINT("enter",("Count: %d MyFlags: %d", - Count, MyFlags)); - byte *bufptr = (byte *)Buffer; - uint res= 0, GotBytes, ReadNowCount; - - // Loop until all data is read (Note that Count may be 0) - while (Count) - { - Calculate(); - // Do seek when neccessary - if (_seek_vector[_this_block] != RAID_SEEK_DONE) - { - if (my_seek(_fd_vector[_this_block], _seek_vector[_this_block], - MY_SEEK_SET, - MyFlags) == MY_FILEPOS_ERROR) - DBUG_RETURN(-1); - _seek_vector[_this_block]=RAID_SEEK_DONE; - } - // and read - ReadNowCount = min(Count, _remaining_bytes); - GotBytes = my_read(_fd_vector[_this_block], bufptr, ReadNowCount, - MyFlags & ~(MY_NABP | MY_FNABP)); - DBUG_PRINT("loop",("Got bytes: %u", GotBytes)); - if (GotBytes == MY_FILE_ERROR) - DBUG_RETURN(-1); - if (!GotBytes) // End of file. - { - DBUG_RETURN((MyFlags & (MY_NABP | MY_FNABP)) ? -1 : (int) res); - } - res+= GotBytes; - bufptr += GotBytes; - Count -= GotBytes; - _position += GotBytes; - } - DBUG_RETURN((MyFlags & (MY_NABP | MY_FNABP)) ? 0 : res); -} - - -int RaidFd:: -Lock(int locktype, my_off_t start, my_off_t length, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Lock"); - DBUG_PRINT("enter",("locktype: %d start: %lu length: %lu MyFlags: %d", - locktype, (ulong) start, (ulong) length, MyFlags)); - my_off_t bufptr = start; - // Loop until all data is locked - while(length) - { - Calculate(); - for (uint i = _this_block ; (i < _raid_chunks) && length ; i++ ) - { - uint ReadNowCount = min(length, _remaining_bytes); - uint GotBytes = my_lock(_fd_vector[i], locktype, bufptr, ReadNowCount, - MyFlags); - if ((int) GotBytes == -1) - DBUG_RETURN(-1); - bufptr += ReadNowCount; - length -= ReadNowCount; - Calculate(); - } - } - DBUG_RETURN(0); -} - - -int RaidFd:: -Close(myf MyFlags) -{ - DBUG_ENTER("RaidFd::Close"); - DBUG_PRINT("enter",("MyFlags: %d", - MyFlags)); - for (uint i = 0 ; i < _raid_chunks ; ++i ) - { - int err = my_close(_fd_vector[i], MyFlags); - if (err != 0) - DBUG_RETURN(err); - } - /* _fd_vector is erased when RaidFd is released */ - DBUG_RETURN(0); -} - - -my_off_t RaidFd:: -Seek(my_off_t pos,int whence,myf MyFlags) -{ - DBUG_ENTER("RaidFd::Seek"); - DBUG_PRINT("enter",("Pos: %lu Whence: %d MyFlags: %d", - (ulong) pos, whence, MyFlags)); - switch (whence) { - case MY_SEEK_CUR: - // FIXME: This is wrong, what is going on there - // Just I am relied on fact that MySQL 3.23.7 never uses MY_SEEK_CUR - // for anything else except things like ltell() - break; - case MY_SEEK_SET: - if ( _position != pos) // we can be already in right place - { - uint i; - off_t _rounds; - _position = pos; - Calculate(); - _rounds = _total_block / _raid_chunks; // INT() assumed - _rounds*= _raid_chunksize; - for (i = 0; i < _raid_chunks ; i++ ) - if ( i < _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize; - else if ( i == _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize -_remaining_bytes; - else // if ( i > _this_block ) - _seek_vector[i] = _rounds; - } - break; - case MY_SEEK_END: - if (_size==RAID_SIZE_UNKNOWN) // We don't know table size yet - { - uint i; - _position = 0; - for (i = 0; i < _raid_chunks ; i++ ) - { - my_off_t newpos = my_seek(_fd_vector[i], 0L, MY_SEEK_END, MyFlags); - if (newpos == MY_FILEPOS_ERROR) - DBUG_RETURN (MY_FILEPOS_ERROR); - _seek_vector[i]=RAID_SEEK_DONE; - _position += newpos; - } - _size=_position; - } - else if (_position != _size) // Aren't we also already in the end? - { - uint i; - off_t _rounds; - _position = _size; - Calculate(); - _rounds = _total_block / _raid_chunks; // INT() assumed - _rounds*= _raid_chunksize; - for (i = 0; i < _raid_chunks ; i++ ) - if ( i < _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize; - else if ( i == _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize - _remaining_bytes; - else // if ( i > _this_block ) - _seek_vector[i] = _rounds; - _position=_size; - } - } - DBUG_RETURN(_position); -} - - -my_off_t RaidFd:: -Tell(myf MyFlags) -{ - DBUG_ENTER("RaidFd::Tell"); - DBUG_PRINT("enter",("MyFlags: %d _position: %lu", - MyFlags, (ulong) _position)); - DBUG_RETURN(_position); -} - -int RaidFd:: -Chsize(File fd, my_off_t newlength, int filler, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Chsize"); - DBUG_PRINT("enter",("Fd: %d newlength: %lu MyFlags: %d", - fd, (ulong) newlength, MyFlags)); - _position = newlength; - Calculate(); - uint _rounds = _total_block / _raid_chunks; // INT() assumed - for (uint i = 0; i < _raid_chunks ; i++ ) - { - int newpos; - if ( i < _this_block ) - newpos = my_chsize(_fd_vector[i], - _this_block * _raid_chunksize + (_rounds + 1) * - _raid_chunksize, filler, MyFlags); - else if ( i == _this_block ) - newpos = my_chsize(_fd_vector[i], - _this_block * _raid_chunksize + _rounds * - _raid_chunksize + (newlength % _raid_chunksize), - filler, MyFlags); - else // this means: i > _this_block - newpos = my_chsize(_fd_vector[i], - _this_block * _raid_chunksize + _rounds * - _raid_chunksize, filler, MyFlags); - if (newpos) - DBUG_RETURN(1); - } - DBUG_RETURN(0); -} - - -int RaidFd:: -Fstat(int fd, MY_STAT *stat_area, myf MyFlags ) -{ - DBUG_ENTER("RaidFd::Fstat"); - DBUG_PRINT("enter",("fd: %d MyFlags: %d",fd,MyFlags)); - uint i; - int error=0; - MY_STAT status; - stat_area->st_size=0; - stat_area->st_mtime=0; - stat_area->st_atime=0; - stat_area->st_ctime=0; - - for(i=0 ; i < _raid_chunks ; i++) - { - if (my_fstat(_fd_vector[i],&status,MyFlags)) - error=1; - stat_area->st_size+=status.st_size; - set_if_bigger(stat_area->st_mtime,status.st_mtime); - set_if_bigger(stat_area->st_atime,status.st_atime); - set_if_bigger(stat_area->st_ctime,status.st_ctime); - } - DBUG_RETURN(error); -} - -#endif /* defined(USE_RAID) && !defined(MYSQL_CLIENT) */ diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 4287f9ce52c..ec5382d0296 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2002-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* * Memory sub-system, written by Bjorn Benson @@ -52,7 +53,7 @@ (equivalent to realloc()) FREE( pPtr ) Free memory allocated by NEW (equivalent to free()) - TERMINATE(file) End system, report errors and stats on file + TERMINATE(file,flag) End system, report errors and stats on file I personally use two more functions, but have not included them here: char *STRSAVE( sPtr ) Save a copy of the string in dynamic memory char *RENEW( pPtr, uSize ) @@ -83,7 +84,7 @@ static int sf_malloc_tampered= 0; /* Static functions prototypes */ -static int check_ptr(const char *where, byte *ptr, const char *sFile, +static int check_ptr(const char *where, uchar *ptr, const char *sFile, uint uLine); static int _checkchunk(struct st_irem *pRec, const char *sFile, uint uLine); @@ -120,10 +121,10 @@ static int _checkchunk(struct st_irem *pRec, const char *sFile, uint uLine); /* Allocate some memory. */ -gptr _mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) +void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) { struct st_irem *irem; - char *data; + uchar *data; DBUG_ENTER("_mymalloc"); DBUG_PRINT("enter",("Size: %lu", (ulong) size)); @@ -140,6 +141,11 @@ gptr _mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) size + /* size requested */ 4 + /* overrun mark */ sf_malloc_endhunc); + DBUG_EXECUTE_IF("simulate_out_of_memory", + { + free(irem); + irem= NULL; + }); } /* Check if there isn't anymore memory avaiable */ if (!irem) @@ -148,33 +154,36 @@ gptr _mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) error_handler_hook=fatal_error_handler_hook; if (MyFlags & (MY_FAE+MY_WME)) { - char buff[SC_MAXWIDTH]; + char buff[256]; my_errno=errno; sprintf(buff,"Out of memory at line %d, '%s'", lineno, filename); my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); - sprintf(buff,"needed %u byte (%ldk), memory in use: %ld bytes (%ldk)", - (uint) size, (uint) (size + 1023L) / 1024L, - sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / 1024L); + sprintf(buff,"needed %lu byte (%luk), memory in use: %lu bytes (%luk)", + (ulong) size, (ulong) (size + 1023L) / 1024L, + (ulong) sf_malloc_max_memory, + (ulong) (sf_malloc_max_memory + 1023L) / 1024L); my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); } DBUG_PRINT("error",("Out of memory, in use: %ld at line %d, '%s'", - sf_malloc_max_memory,lineno, filename)); + (ulong) sf_malloc_max_memory, lineno, filename)); + DBUG_EXECUTE_IF("simulate_out_of_memory", + DBUG_SET("-d,simulate_out_of_memory");); if (MyFlags & MY_FAE) exit(1); - DBUG_RETURN ((gptr) 0); + DBUG_RETURN ((void*) 0); } /* Fill up the structure */ - data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + + data= (((uchar*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + sf_malloc_prehunc); *((uint32*) (data-sizeof(uint32)))= MAGICKEY; data[size + 0]= MAGICEND0; data[size + 1]= MAGICEND1; data[size + 2]= MAGICEND2; data[size + 3]= MAGICEND3; - irem->filename= (my_string) filename; + irem->filename= (char *) filename; irem->linenum= lineno; - irem->datasize= (uint32) size; + irem->datasize= size; irem->prev= NULL; /* Add this remember structure to the linked list */ @@ -190,16 +199,19 @@ gptr _mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) sf_malloc_count++; pthread_mutex_unlock(&THR_LOCK_malloc); + MEM_CHECK_ADDRESSABLE(data, size); /* Set the memory to the aribtrary wierd value */ if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick) bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL)); + if (!(MyFlags & MY_ZEROFILL)) + MEM_UNDEFINED(data, size); /* Return a pointer to the real data */ - DBUG_PRINT("exit",("ptr: 0x%lx", (long) data)); + DBUG_PRINT("exit",("ptr: %p", data)); if (sf_min_adress > data) sf_min_adress= data; if (sf_max_adress < data) sf_max_adress= data; - DBUG_RETURN ((gptr) data); + DBUG_RETURN((void*) data); } @@ -208,8 +220,8 @@ gptr _mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) Free then old memoryblock */ -gptr _myrealloc(register gptr ptr, register size_t size, - const char *filename, uint lineno, myf MyFlags) +void *_myrealloc(register void *ptr, register size_t size, + const char *filename, uint lineno, myf MyFlags) { struct st_irem *irem; char *data; @@ -221,8 +233,8 @@ gptr _myrealloc(register gptr ptr, register size_t size, if (!sf_malloc_quick) (void) _sanity (filename, lineno); - if (check_ptr("Reallocating", (byte*) ptr, filename, lineno)) - DBUG_RETURN((gptr) NULL); + if (check_ptr("Reallocating", (uchar*) ptr, filename, lineno)) + DBUG_RETURN((uchar*) NULL); irem= (struct st_irem *) (((char*) ptr) - ALIGN_SIZE(sizeof(struct st_irem))- sf_malloc_prehunc); @@ -233,13 +245,13 @@ gptr _myrealloc(register gptr ptr, register size_t size, DBUG_PRINT("safe",("Reallocating unallocated data at line %d, '%s'", lineno, filename)); (void) fflush(stderr); - DBUG_RETURN((gptr) NULL); + DBUG_RETURN((uchar*) NULL); } if ((data= _mymalloc(size,filename,lineno,MyFlags))) /* Allocate new area */ { size=min(size, irem->datasize); /* Move as much as possibly */ - memcpy((byte*) data, ptr, (size_t) size); /* Copy old data */ + memcpy((uchar*) data, ptr, (size_t) size); /* Copy old data */ _myfree(ptr, filename, lineno, 0); /* Free not needed area */ } else @@ -255,17 +267,17 @@ gptr _myrealloc(register gptr ptr, register size_t size, /* Deallocate some memory. */ -void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags) +void _myfree(void *ptr, const char *filename, uint lineno, myf myflags) { struct st_irem *irem; DBUG_ENTER("_myfree"); - DBUG_PRINT("enter",("ptr: 0x%lx", (long) ptr)); + DBUG_PRINT("enter",("ptr: %p", ptr)); if (!sf_malloc_quick) (void) _sanity (filename, lineno); if ((!ptr && (myflags & MY_ALLOW_ZERO_PTR)) || - check_ptr("Freeing",(byte*) ptr,filename,lineno)) + check_ptr("Freeing",(uchar*) ptr,filename,lineno)) DBUG_VOID_RETURN; /* Calculate the address of the remember structure */ @@ -309,7 +321,9 @@ void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags) if (!sf_malloc_quick) bfill(ptr, irem->datasize, (pchar) FREE_VAL); #endif + MEM_NOACCESS(ptr, irem->datasize); *((uint32*) ((char*) ptr- sizeof(uint32)))= ~MAGICKEY; + MEM_NOACCESS((char*) ptr - sizeof(uint32), sizeof(uint32)); /* Actually free the memory */ free((char*) irem); DBUG_VOID_RETURN; @@ -317,7 +331,7 @@ void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags) /* Check if we have a wrong pointer */ -static int check_ptr(const char *where, byte *ptr, const char *filename, +static int check_ptr(const char *where, uchar *ptr, const char *filename, uint lineno) { if (!ptr) @@ -353,12 +367,15 @@ static int check_ptr(const char *where, byte *ptr, const char *filename, /* - TERMINATE(FILE *file) - Report on all the memory pieces that have not been - free'ed as well as the statistics. + Report on all the memory pieces that have not been free'ed + + SYNOPSIS + TERMINATE() + file Write output to this file + flag If <> 0, also write statistics */ -void TERMINATE(FILE *file) +void TERMINATE(FILE *file, uint flag) { struct st_irem *irem; DBUG_ENTER("TERMINATE"); @@ -389,12 +406,12 @@ void TERMINATE(FILE *file) { if (file) { - fprintf(file, "Warning: Memory that was not free'ed (%ld bytes):\n", - sf_malloc_cur_memory); + fprintf(file, "Warning: Memory that was not free'ed (%lu bytes):\n", + (ulong) sf_malloc_cur_memory); (void) fflush(file); } - DBUG_PRINT("safe",("Memory that was not free'ed (%ld bytes):", - sf_malloc_cur_memory)); + DBUG_PRINT("safe",("Memory that was not free'ed (%lu bytes):", + (ulong) sf_malloc_cur_memory)); while (irem) { char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + @@ -402,32 +419,57 @@ void TERMINATE(FILE *file) if (file) { fprintf(file, - "\t%6u bytes at 0x%09lx, allocated at line %4u in '%s'", - irem->datasize, (long) data, irem->linenum, irem->filename); + "\t%6lu bytes at %p, allocated at line %4u in '%s'", + (ulong) irem->datasize, data, irem->linenum, irem->filename); fprintf(file, "\n"); (void) fflush(file); } DBUG_PRINT("safe", - ("%6u bytes at 0x%09lx, allocated at line %4d in '%s'", - irem->datasize, (long) data, irem->linenum, irem->filename)); + ("%6lu bytes at %p, allocated at line %4d in '%s'", + (ulong) irem->datasize, + data, irem->linenum, irem->filename)); irem= irem->next; } } /* Report the memory usage statistics */ - if (file) + if (file && flag) { - fprintf(file, "Maximum memory usage: %ld bytes (%ldk)\n", - sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / 1024L); + fprintf(file, "Maximum memory usage: %lu bytes (%luk)\n", + (ulong) sf_malloc_max_memory, + (ulong) (sf_malloc_max_memory + 1023L) / 1024L); (void) fflush(file); } - DBUG_PRINT("safe",("Maximum memory usage: %ld bytes (%ldk)", - sf_malloc_max_memory, (sf_malloc_max_memory + 1023L) / - 1024L)); + DBUG_PRINT("safe",("Maximum memory usage: %lu bytes (%luk)", + (ulong) sf_malloc_max_memory, + (ulong) (sf_malloc_max_memory + 1023L) /1024L)); pthread_mutex_unlock(&THR_LOCK_malloc); DBUG_VOID_RETURN; } +/* + Report where a piece of memory was allocated + + This is usefull to call from withing a debugger +*/ + + +void sf_malloc_report_allocated(void *memory) +{ + struct st_irem *irem; + for (irem= sf_malloc_root ; irem ; irem=irem->next) + { + char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) + + sf_malloc_prehunc); + if (data <= (char*) memory && (char*) memory <= data + irem->datasize) + { + printf("%lu bytes at %p, allocated at line %u in '%s'\n", + (ulong) irem->datasize, data, irem->linenum, irem->filename); + break; + } + } +} + /* Returns 0 if chunk is ok */ static int _checkchunk(register struct st_irem *irem, const char *filename, @@ -445,8 +487,8 @@ static int _checkchunk(register struct st_irem *irem, const char *filename, irem->filename, irem->linenum); fprintf(stderr, " discovered at %s:%d\n", filename, lineno); (void) fflush(stderr); - DBUG_PRINT("safe",("Underrun at 0x%lx, allocated at %s:%d", - (long) data, irem->filename, irem->linenum)); + DBUG_PRINT("safe",("Underrun at %p, allocated at %s:%d", + data, irem->filename, irem->linenum)); flag=1; } @@ -461,10 +503,8 @@ static int _checkchunk(register struct st_irem *irem, const char *filename, irem->filename, irem->linenum); fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno); (void) fflush(stderr); - DBUG_PRINT("safe",("Overrun at 0x%lx, allocated at %s:%d", - (long) data, - irem->filename, - irem->linenum)); + DBUG_PRINT("safe",("Overrun at %p, allocated at %s:%d", + data, irem->filename, irem->linenum)); flag=1; } return(flag); @@ -503,12 +543,12 @@ int _sanity(const char *filename, uint lineno) /* malloc and copy */ -gptr _my_memdup(const byte *from, size_t length, const char *filename, +void *_my_memdup(const void *from, size_t length, const char *filename, uint lineno, myf MyFlags) { - gptr ptr; - if ((ptr=_mymalloc(length,filename,lineno,MyFlags)) != 0) - memcpy((byte*) ptr, (byte*) from,(size_t) length); + void *ptr; + if ((ptr= _mymalloc(length,filename,lineno,MyFlags)) != 0) + memcpy(ptr, from, length); return(ptr); } /*_my_memdup */ @@ -516,23 +556,23 @@ gptr _my_memdup(const byte *from, size_t length, const char *filename, char *_my_strdup(const char *from, const char *filename, uint lineno, myf MyFlags) { - gptr ptr; + char *ptr; size_t length= strlen(from)+1; - if ((ptr=_mymalloc(length,filename,lineno,MyFlags)) != 0) - memcpy((byte*) ptr, (byte*) from,(size_t) length); - return((char*) ptr); + if ((ptr= (char*) _mymalloc(length,filename,lineno,MyFlags)) != 0) + memcpy((uchar*) ptr, (uchar*) from, (size_t) length); + return(ptr); } /* _my_strdup */ -char *_my_strdup_with_length(const char *from, size_t length, +char *_my_strndup(const char *from, size_t length, const char *filename, uint lineno, myf MyFlags) { - gptr ptr; - if ((ptr=_mymalloc(length+1,filename,lineno,MyFlags)) != 0) + char *ptr; + if ((ptr= (char*) _mymalloc(length+1,filename,lineno,MyFlags)) != 0) { - memcpy((byte*) ptr, (byte*) from,(size_t) length); + memcpy((uchar*) ptr, (uchar*) from, (size_t) length); ptr[length]=0; } - return((char *) ptr); + return(ptr); } diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c new file mode 100644 index 00000000000..b2eae0fb4c6 --- /dev/null +++ b/mysys/stacktrace.c @@ -0,0 +1,977 @@ +/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + + +/* Workaround for Bug#32082: VOID redefinition on Win results in compile errors*/ +#define DONT_DEFINE_VOID 1 + +#include <my_global.h> +#include <my_stacktrace.h> + +#ifndef __WIN__ +#include <signal.h> +#include <my_pthread.h> +#include <m_string.h> +#ifdef HAVE_STACKTRACE +#include <unistd.h> +#include <strings.h> + +#ifdef __linux__ +#include <ctype.h> /* isprint */ +#include <sys/syscall.h> /* SYS_gettid */ +#endif + +#if HAVE_EXECINFO_H +#include <execinfo.h> +#endif + +#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) + +static char *heap_start; + +#ifdef HAVE_BSS_START +extern char *__bss_start; +#endif + +void my_init_stacktrace() +{ +#ifdef HAVE_BSS_START + heap_start = (char*) &__bss_start; +#endif +} + +#ifdef __linux__ + +static void print_buffer(char *buffer, size_t count) +{ + const char s[]= " "; + for (; count && *buffer; --count) + { + my_write_stderr(isprint(*buffer) ? buffer : s, 1); + ++buffer; + } +} + +/** + Access the pages of this process through /proc/self/task/<tid>/mem + in order to safely print the contents of a memory address range. + + @param addr The address at the start of the memory region. + @param max_len The length of the memory region. + + @return Zero on success. +*/ +static int safe_print_str(const char *addr, int max_len) +{ + int fd; + pid_t tid; + off_t offset; + ssize_t nbytes= 0; + size_t total, count; + char buf[256]; + + tid= (pid_t) syscall(SYS_gettid); + + sprintf(buf, "/proc/self/task/%d/mem", tid); + + if ((fd= open(buf, O_RDONLY)) < 0) + return -1; + + /* Ensure that off_t can hold a pointer. */ + compile_time_assert(sizeof(off_t) >= sizeof(intptr)); + + total= max_len; + offset= (intptr) addr; + + /* Read up to the maximum number of bytes. */ + while (total) + { + count= min(sizeof(buf), total); + + if ((nbytes= pread(fd, buf, count, offset)) < 0) + { + /* Just in case... */ + if (errno == EINTR) + continue; + else + break; + } + + /* Advance offset into memory. */ + total-= nbytes; + offset+= nbytes; + addr+= nbytes; + + /* Output the printable characters. */ + print_buffer(buf, nbytes); + + /* Break if less than requested... */ + if ((count - nbytes)) + break; + } + + /* Output a new line if something was printed. */ + if (total != (size_t) max_len) + my_safe_printf_stderr("%s", "\n"); + + if (nbytes == -1) + my_safe_printf_stderr("Can't read from address %p\n", addr); + + close(fd); + + return 0; +} + +#endif + +void my_safe_print_str(const char* val, int max_len) +{ + char *heap_end; + +#ifdef __linux__ + if (!safe_print_str(val, max_len)) + return; +#endif + + heap_end= (char*) sbrk(0); + + if (!PTR_SANE(val)) + { + my_safe_printf_stderr("%s", "is an invalid pointer\n"); + return; + } + + for (; max_len && PTR_SANE(val) && *val; --max_len) + my_write_stderr((val++), 1); + my_safe_printf_stderr("%s", "\n"); +} + +#if defined(HAVE_PRINTSTACK) + +/* Use Solaris' symbolic stack trace routine. */ +#include <ucontext.h> + +void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)), + ulong thread_stack __attribute__((unused))) +{ + if (printstack(fileno(stderr)) == -1) + my_safe_printf_stderr("%s", + "Error when traversing the stack, stack appears corrupt.\n"); + else + my_safe_printf_stderr("%s" + "Please read " + "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n" + "and follow instructions on how to resolve the stack trace.\n" + "Resolved stack trace is much more helpful in diagnosing the\n" + "problem, so please do resolve it\n"); +} + +#elif HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) + +#if BACKTRACE_DEMANGLE + +char __attribute__ ((weak)) * +my_demangle(const char *mangled_name __attribute__((unused)), + int *status __attribute__((unused))) +{ + return NULL; +} + +static void my_demangle_symbols(char **addrs, int n) +{ + int status, i; + char *begin, *end, *demangled; + + for (i= 0; i < n; i++) + { + demangled= NULL; + begin= strchr(addrs[i], '('); + end= begin ? strchr(begin, '+') : NULL; + + if (begin && end) + { + *begin++= *end++= '\0'; + demangled= my_demangle(begin, &status); + if (!demangled || status) + { + demangled= NULL; + begin[-1]= '('; + end[-1]= '+'; + } + } + + if (demangled) + my_safe_printf_stderr("%s(%s+%s\n", addrs[i], demangled, end); + else + my_safe_printf_stderr("%s\n", addrs[i]); + } +} + +#endif /* BACKTRACE_DEMANGLE */ + +void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) +{ + void *addrs[128]; + char **strings= NULL; + int n = backtrace(addrs, array_elements(addrs)); + my_safe_printf_stderr("stack_bottom = %p thread_stack 0x%lx\n", + stack_bottom, thread_stack); +#if BACKTRACE_DEMANGLE + if ((strings= backtrace_symbols(addrs, n))) + { + my_demangle_symbols(strings, n); + free(strings); + } +#endif +#if HAVE_BACKTRACE_SYMBOLS_FD + if (!strings) + { + backtrace_symbols_fd(addrs, n, fileno(stderr)); + } +#endif +} + +#elif defined(TARGET_OS_LINUX) + +#ifdef __i386__ +#define SIGRETURN_FRAME_OFFSET 17 +#endif + +#ifdef __x86_64__ +#define SIGRETURN_FRAME_OFFSET 23 +#endif + +#if defined(__alpha__) && defined(__GNUC__) +/* + The only way to backtrace without a symbol table on alpha + is to find stq fp,N(sp), and the first byte + of the instruction opcode will give us the value of N. From this + we can find where the old value of fp is stored +*/ + +#define MAX_INSTR_IN_FUNC 10000 + +inline uchar** find_prev_fp(uint32* pc, uchar** fp) +{ + int i; + for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) + { + uchar* p = (uchar*)pc; + if (p[2] == 222 && p[3] == 35) + { + return (uchar**)((uchar*)fp - *(short int*)p); + } + } + return 0; +} + +inline uint32* find_prev_pc(uint32* pc, uchar** fp) +{ + int i; + for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) + { + char* p = (char*)pc; + if (p[1] == 0 && p[2] == 94 && p[3] == -73) + { + uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp))); + return prev_pc; + } + } + return 0; +} +#endif /* defined(__alpha__) && defined(__GNUC__) */ + +void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) +{ + uchar** fp; + uint frame_count = 0, sigreturn_frame_count; +#if defined(__alpha__) && defined(__GNUC__) + uint32* pc; +#endif + LINT_INIT(fp); + + +#ifdef __i386__ + __asm __volatile__ ("movl %%ebp,%0" + :"=r"(fp) + :"r"(fp)); +#endif +#ifdef __x86_64__ + __asm __volatile__ ("movq %%rbp,%0" + :"=r"(fp) + :"r"(fp)); +#endif +#if defined(__alpha__) && defined(__GNUC__) + __asm __volatile__ ("mov $30,%0" + :"=r"(fp) + :"r"(fp)); +#endif + if (!fp) + { + my_safe_printf_stderr("%s", + "frame pointer is NULL, did you compile with\n" + "-fomit-frame-pointer? Aborting backtrace!\n"); + return; + } + + if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp) + { + ulong tmp= min(0x10000,thread_stack); + /* Assume that the stack starts at the previous even 65K */ + stack_bottom= (uchar*) (((ulong) &fp + tmp) & ~(ulong) 0xFFFF); + my_safe_printf_stderr("Cannot determine thread, fp=%p, " + "backtrace may not be correct.\n", fp); + } + if (fp > (uchar**) stack_bottom || + fp < (uchar**) stack_bottom - thread_stack) + { + my_safe_printf_stderr("Bogus stack limit or frame pointer, " + "fp=%p, stack_bottom=%p, thread_stack=%ld, " + "aborting backtrace.\n", + fp, stack_bottom, thread_stack); + return; + } + + my_safe_printf_stderr("%s", + "Stack range sanity check OK, backtrace follows:\n"); +#if defined(__alpha__) && defined(__GNUC__) + my_safe_printf_stderr("%s", + "Warning: Alpha stacks are difficult -" + "will be taking some wild guesses, stack trace may be incorrect or " + "terminate abruptly\n"); + + /* On Alpha, we need to get pc */ + __asm __volatile__ ("bsr %0, do_next; do_next: " + :"=r"(pc) + :"r"(pc)); +#endif /* __alpha__ */ + + /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */ + sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1; + + while (fp < (uchar**) stack_bottom) + { +#if defined(__i386__) || defined(__x86_64__) + uchar** new_fp = (uchar**)*fp; + my_safe_printf_stderr("%p\n", + frame_count == sigreturn_frame_count ? + *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1)); +#endif /* defined(__386__) || defined(__x86_64__) */ + +#if defined(__alpha__) && defined(__GNUC__) + uchar** new_fp = find_prev_fp(pc, fp); + if (frame_count == sigreturn_frame_count - 1) + { + new_fp += 90; + } + + if (fp && pc) + { + pc = find_prev_pc(pc, fp); + if (pc) + my_safe_printf_stderr("%p\n", pc); + else + { + my_safe_printf_stderr("%s", + "Not smart enough to deal with the rest of this stack\n"); + goto end; + } + } + else + { + my_safe_printf_stderr("%s", + "Not smart enough to deal with the rest of this stack\n"); + goto end; + } +#endif /* defined(__alpha__) && defined(__GNUC__) */ + if (new_fp <= fp ) + { + my_safe_printf_stderr("New value of fp=%p failed sanity check, " + "terminating stack trace!\n", new_fp); + goto end; + } + fp = new_fp; + ++frame_count; + } + my_safe_printf_stderr("%s", + "Stack trace seems successful - bottom reached\n"); + +end: + my_safe_printf_stderr("%s", + "Please read " + "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n" + "and follow instructions on how to resolve the stack trace.\n" + "Resolved stack trace is much more helpful in diagnosing the\n" + "problem, so please do resolve it\n"); +} +#endif /* TARGET_OS_LINUX */ +#endif /* HAVE_STACKTRACE */ + +/* Produce a core for the thread */ +void my_write_core(int sig) +{ +#ifdef HAVE_gcov + extern void __gcov_flush(void); +#endif + signal(sig, SIG_DFL); +#ifdef HAVE_gcov + /* + For GCOV build, crashing will prevent the writing of code coverage + information from this process, causing gcov output to be incomplete. + So we force the writing of coverage information here before terminating. + */ + __gcov_flush(); +#endif + pthread_kill(pthread_self(), sig); +#if defined(P_MYID) && !defined(SCO) + /* On Solaris, the above kill is not enough */ + sigsend(P_PID,P_MYID,sig); +#endif +} + +#else /* __WIN__*/ + +#include <dbghelp.h> +#include <tlhelp32.h> + +/* + Stack tracing on Windows is implemented using Debug Helper library(dbghelp.dll) + We do not redistribute dbghelp and the one comes with older OS (up to Windows 2001) + is missing some important functions like functions StackWalk64 or MinidumpWriteDump. + Hence, we have to load functions at runtime using LoadLibrary/GetProcAddress. +*/ + +typedef DWORD (WINAPI *SymSetOptions_FctType)(DWORD dwOptions); +typedef BOOL (WINAPI *SymGetModuleInfo64_FctType) + (HANDLE,DWORD64,PIMAGEHLP_MODULE64) ; +typedef BOOL (WINAPI *SymGetSymFromAddr64_FctType) + (HANDLE,DWORD64,PDWORD64,PIMAGEHLP_SYMBOL64) ; +typedef BOOL (WINAPI *SymGetLineFromAddr64_FctType) + (HANDLE,DWORD64,PDWORD,PIMAGEHLP_LINE64); +typedef BOOL (WINAPI *SymInitialize_FctType) + (HANDLE,PSTR,BOOL); +typedef BOOL (WINAPI *StackWalk64_FctType) + (DWORD,HANDLE,HANDLE,LPSTACKFRAME64,PVOID,PREAD_PROCESS_MEMORY_ROUTINE64, + PFUNCTION_TABLE_ACCESS_ROUTINE64,PGET_MODULE_BASE_ROUTINE64 , + PTRANSLATE_ADDRESS_ROUTINE64); +typedef BOOL (WINAPI *MiniDumpWriteDump_FctType)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL + IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL + ); + +static SymSetOptions_FctType pSymSetOptions; +static SymGetModuleInfo64_FctType pSymGetModuleInfo64; +static SymGetSymFromAddr64_FctType pSymGetSymFromAddr64; +static SymInitialize_FctType pSymInitialize; +static StackWalk64_FctType pStackWalk64; +static SymGetLineFromAddr64_FctType pSymGetLineFromAddr64; +static MiniDumpWriteDump_FctType pMiniDumpWriteDump; + +static EXCEPTION_POINTERS *exception_ptrs; + +#define MODULE64_SIZE_WINXP 576 +#define STACKWALK_MAX_FRAMES 64 + +void my_init_stacktrace() +{ +} + +/* + Dynamically load dbghelp functions +*/ +BOOL init_dbghelp_functions() +{ + static BOOL first_time= TRUE; + static BOOL rc; + HMODULE hDbghlp; + + if(first_time) + { + first_time= FALSE; + hDbghlp= LoadLibrary("dbghelp"); + if(!hDbghlp) + { + rc= FALSE; + return rc; + } + pSymSetOptions= (SymSetOptions_FctType) + GetProcAddress(hDbghlp,"SymSetOptions"); + pSymInitialize= (SymInitialize_FctType) + GetProcAddress(hDbghlp,"SymInitialize"); + pSymGetModuleInfo64= (SymGetModuleInfo64_FctType) + GetProcAddress(hDbghlp,"SymGetModuleInfo64"); + pSymGetLineFromAddr64= (SymGetLineFromAddr64_FctType) + GetProcAddress(hDbghlp,"SymGetLineFromAddr64"); + pSymGetSymFromAddr64=(SymGetSymFromAddr64_FctType) + GetProcAddress(hDbghlp,"SymGetSymFromAddr64"); + pStackWalk64= (StackWalk64_FctType) + GetProcAddress(hDbghlp,"StackWalk64"); + pMiniDumpWriteDump = (MiniDumpWriteDump_FctType) + GetProcAddress(hDbghlp,"MiniDumpWriteDump"); + + rc = (BOOL)(pSymSetOptions && pSymInitialize && pSymGetModuleInfo64 + && pSymGetLineFromAddr64 && pSymGetSymFromAddr64 && pStackWalk64); + } + return rc; +} + +void my_set_exception_pointers(EXCEPTION_POINTERS *ep) +{ + exception_ptrs = ep; +} + + +/* + Get symbol path - semicolon-separated list of directories to search for debug + symbols. We expect PDB in the same directory as corresponding exe or dll, + so the path is build from directories of the loaded modules. If environment + variable _NT_SYMBOL_PATH is set, it's value appended to the symbol search path +*/ +static void get_symbol_path(char *path, size_t size) +{ + HANDLE hSnap; + char *envvar; + + path[0]= '\0'; + /* + Enumerate all modules, and add their directories to the path. + Avoid duplicate entries. + */ + hSnap= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + if (hSnap != INVALID_HANDLE_VALUE) + { + BOOL ret; + MODULEENTRY32 mod; + mod.dwSize= sizeof(MODULEENTRY32); + for (ret= Module32First(hSnap, &mod); ret; ret= Module32Next(hSnap, &mod)) + { + char *module_dir= mod.szExePath; + char *p= strrchr(module_dir,'\\'); + if (!p) + { + /* + Path separator was not found. Not known to happen, if ever happens, + will indicate current directory. + */ + module_dir[0]= '.'; + p= module_dir + 1; + } + *p++= ';'; + *p= '\0'; + + if (!strstr(path, module_dir)) + { + size_t dir_len = strlen(module_dir); + if (size > dir_len) + { + strncat(path, module_dir, size-1); + size -= dir_len; + } + } + } + CloseHandle(hSnap); + } + + /* Add _NT_SYMBOL_PATH, if present. */ + envvar= getenv("_NT_SYMBOL_PATH"); + if(envvar && size) + { + strncat(path, envvar, size-1); + } +} + +#define MAX_SYMBOL_PATH 32768 + +/* Platform SDK in VS2003 does not have definition for SYMOPT_NO_PROMPTS*/ +#ifndef SYMOPT_NO_PROMPTS +#define SYMOPT_NO_PROMPTS 0 +#endif + +void my_print_stacktrace(uchar* unused1, ulong unused2) +{ + HANDLE hProcess= GetCurrentProcess(); + HANDLE hThread= GetCurrentThread(); + static IMAGEHLP_MODULE64 module= {sizeof(module)}; + static IMAGEHLP_SYMBOL64_PACKAGE package; + DWORD64 addr; + DWORD machine; + int i; + CONTEXT context; + STACKFRAME64 frame={0}; + static char symbol_path[MAX_SYMBOL_PATH]; + + if(!exception_ptrs || !init_dbghelp_functions()) + return; + + /* Copy context, as stackwalking on original will unwind the stack */ + context = *(exception_ptrs->ContextRecord); + /*Initialize symbols.*/ + pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); + get_symbol_path(symbol_path, sizeof(symbol_path)); + pSymInitialize(hProcess, symbol_path, TRUE); + + /*Prepare stackframe for the first StackWalk64 call*/ + frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat; +#if (defined _M_IX86) + machine= IMAGE_FILE_MACHINE_I386; + frame.AddrFrame.Offset= context.Ebp; + frame.AddrPC.Offset= context.Eip; + frame.AddrStack.Offset= context.Esp; +#elif (defined _M_X64) + machine = IMAGE_FILE_MACHINE_AMD64; + frame.AddrFrame.Offset= context.Rbp; + frame.AddrPC.Offset= context.Rip; + frame.AddrStack.Offset= context.Rsp; +#else + /*There is currently no need to support IA64*/ +#pragma error ("unsupported architecture") +#endif + + package.sym.SizeOfStruct= sizeof(package.sym); + package.sym.MaxNameLength= sizeof(package.name); + + /*Walk the stack, output useful information*/ + for(i= 0; i< STACKWALK_MAX_FRAMES;i++) + { + DWORD64 function_offset= 0; + DWORD line_offset= 0; + IMAGEHLP_LINE64 line= {sizeof(line)}; + BOOL have_module= FALSE; + BOOL have_symbol= FALSE; + BOOL have_source= FALSE; + + if(!pStackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0)) + break; + addr= frame.AddrPC.Offset; + + have_module= pSymGetModuleInfo64(hProcess,addr,&module); +#ifdef _M_IX86 + if(!have_module) + { + /* + ModuleInfo structure has been "compatibly" extended in releases after XP, + and its size was increased. To make XP dbghelp.dll function + happy, pretend passing the old structure. + */ + module.SizeOfStruct= MODULE64_SIZE_WINXP; + have_module= pSymGetModuleInfo64(hProcess, addr, &module); + } +#endif + + have_symbol= pSymGetSymFromAddr64(hProcess, addr, &function_offset, + &(package.sym)); + have_source= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line); + + my_safe_printf_stderr("%p ", addr); + if(have_module) + { + char *base_image_name= strrchr(module.ImageName, '\\'); + if(base_image_name) + base_image_name++; + else + base_image_name= module.ImageName; + my_safe_printf_stderr("%s!", base_image_name); + } + if(have_symbol) + my_safe_printf_stderr("%s()", package.sym.Name); + + else if(have_module) + my_safe_printf_stderr("%s", "???"); + + if(have_source) + { + char *base_file_name= strrchr(line.FileName, '\\'); + if(base_file_name) + base_file_name++; + else + base_file_name= line.FileName; + my_safe_printf_stderr("[%s:%u]", + base_file_name, line.LineNumber); + } + my_safe_printf_stderr("%s", "\n"); + } +} + + +/* + Write dump. The dump is created in current directory, + file name is constructed from executable name plus + ".dmp" extension +*/ +void my_write_core(int unused) +{ + char path[MAX_PATH]; + char dump_fname[MAX_PATH]= "core.dmp"; + MINIDUMP_EXCEPTION_INFORMATION info; + HANDLE hFile; + + if(!exception_ptrs || !init_dbghelp_functions() || !pMiniDumpWriteDump) + return; + + info.ExceptionPointers= exception_ptrs; + info.ClientPointers= FALSE; + info.ThreadId= GetCurrentThreadId(); + + if(GetModuleFileName(NULL, path, sizeof(path))) + { + _splitpath(path, NULL, NULL,dump_fname,NULL); + strncat(dump_fname, ".dmp", sizeof(dump_fname)); + } + + hFile= CreateFile(dump_fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, 0); + if(hFile) + { + /* Create minidump */ + if(pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), + hFile, MiniDumpNormal, &info, 0, 0)) + { + my_safe_printf_stderr("Minidump written to %s\n", + _fullpath(path, dump_fname, sizeof(path)) ? + path : dump_fname); + } + else + { + my_safe_printf_stderr("MiniDumpWriteDump() failed, last error %u\n", + (uint) GetLastError()); + } + CloseHandle(hFile); + } + else + { + my_safe_printf_stderr("CreateFile(%s) failed, last error %u\n", + dump_fname, (uint) GetLastError()); + } +} + + +void my_safe_print_str(const char *val, int len) +{ + __try + { + my_write_stderr(val, len); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + my_safe_printf_stderr("%s", "is an invalid string pointer\n"); + } +} +#endif /*__WIN__*/ + + +#ifdef __WIN__ +size_t my_write_stderr(const void *buf, size_t count) +{ + DWORD bytes_written; + SetFilePointer(GetStdHandle(STD_ERROR_HANDLE), 0, NULL, FILE_END); + WriteFile(GetStdHandle(STD_ERROR_HANDLE), buf, count, &bytes_written, NULL); + return bytes_written; +} +#else +size_t my_write_stderr(const void *buf, size_t count) +{ + return (size_t) write(STDERR_FILENO, buf, count); +} +#endif + + +static const char digits[]= "0123456789abcdef"; + +char *my_safe_utoa(int base, ulonglong val, char *buf) +{ + *buf--= 0; + do { + *buf--= digits[val % base]; + } while ((val /= base) != 0); + return buf + 1; +} + + +char *my_safe_itoa(int base, longlong val, char *buf) +{ + char *orig_buf= buf; + const my_bool is_neg= (val < 0); + *buf--= 0; + + if (is_neg) + val= -val; + if (is_neg && base == 16) + { + int ix; + val-= 1; + for (ix= 0; ix < 16; ++ix) + buf[-ix]= '0'; + } + + do { + *buf--= digits[val % base]; + } while ((val /= base) != 0); + + if (is_neg && base == 10) + *buf--= '-'; + + if (is_neg && base == 16) + { + int ix; + buf= orig_buf - 1; + for (ix= 0; ix < 16; ++ix, --buf) + { + switch (*buf) + { + case '0': *buf= 'f'; break; + case '1': *buf= 'e'; break; + case '2': *buf= 'd'; break; + case '3': *buf= 'c'; break; + case '4': *buf= 'b'; break; + case '5': *buf= 'a'; break; + case '6': *buf= '9'; break; + case '7': *buf= '8'; break; + case '8': *buf= '7'; break; + case '9': *buf= '6'; break; + case 'a': *buf= '5'; break; + case 'b': *buf= '4'; break; + case 'c': *buf= '3'; break; + case 'd': *buf= '2'; break; + case 'e': *buf= '1'; break; + case 'f': *buf= '0'; break; + } + } + } + return buf+1; +} + + +static const char *check_longlong(const char *fmt, my_bool *have_longlong) +{ + *have_longlong= FALSE; + if (*fmt == 'l') + { + fmt++; + if (*fmt != 'l') + *have_longlong= (sizeof(long) == sizeof(longlong)); + else + { + fmt++; + *have_longlong= TRUE; + } + } + return fmt; +} + +static size_t my_safe_vsnprintf(char *to, size_t size, + const char* format, va_list ap) +{ + char *start= to; + char *end= start + size - 1; + for (; *format; ++format) + { + my_bool have_longlong = FALSE; + if (*format != '%') + { + if (to == end) /* end of buffer */ + break; + *to++= *format; /* copy ordinary char */ + continue; + } + ++format; /* skip '%' */ + + format= check_longlong(format, &have_longlong); + + switch (*format) + { + case 'd': + case 'i': + case 'u': + case 'x': + case 'p': + { + longlong ival= 0; + ulonglong uval = 0; + if (*format == 'p') + have_longlong= (sizeof(void *) == sizeof(longlong)); + if (have_longlong) + { + if (*format == 'u') + uval= va_arg(ap, ulonglong); + else + ival= va_arg(ap, longlong); + } + else + { + if (*format == 'u') + uval= va_arg(ap, unsigned int); + else + ival= va_arg(ap, int); + } + + { + char buff[22]; + const int base= (*format == 'x' || *format == 'p') ? 16 : 10; + char *val_as_str= (*format == 'u') ? + my_safe_utoa(base, uval, &buff[sizeof(buff)-1]) : + my_safe_itoa(base, ival, &buff[sizeof(buff)-1]); + + /* Strip off "ffffffff" if we have 'x' format without 'll' */ + if (*format == 'x' && !have_longlong && ival < 0) + val_as_str+= 8; + + while (*val_as_str && to < end) + *to++= *val_as_str++; + continue; + } + } + case 's': + { + const char *val= va_arg(ap, char*); + if (!val) + val= "(null)"; + while (*val && to < end) + *to++= *val++; + continue; + } + } + } + *to= 0; + return to - start; +} + + +size_t my_safe_snprintf(char* to, size_t n, const char* fmt, ...) +{ + size_t result; + va_list args; + va_start(args,fmt); + result= my_safe_vsnprintf(to, n, fmt, args); + va_end(args); + return result; +} + + +size_t my_safe_printf_stderr(const char* fmt, ...) +{ + char to[512]; + size_t result; + va_list args; + va_start(args,fmt); + result= my_safe_vsnprintf(to, sizeof(to), fmt, args); + va_end(args); + my_write_stderr(to, result); + return result; +} diff --git a/mysys/string.c b/mysys/string.c index b301dacd091..e3a99580c29 100644 --- a/mysys/string.c +++ b/mysys/string.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2001, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000, 2001, 2005-2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Code for handling strings with can grow dynamicly. @@ -24,15 +26,15 @@ #include <m_string.h> my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, - uint init_alloc, uint alloc_increment) + size_t init_alloc, size_t alloc_increment) { - uint length; + size_t length; DBUG_ENTER("init_dynamic_string"); if (!alloc_increment) alloc_increment=128; length=1; - if (init_str && (length= (uint) strlen(init_str)+1) < init_alloc) + if (init_str && (length= strlen(init_str)+1) < init_alloc) init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment; if (!init_alloc) init_alloc=alloc_increment; @@ -73,7 +75,7 @@ my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str) } -my_bool dynstr_realloc(DYNAMIC_STRING *str, ulong additional_size) +my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size) { DBUG_ENTER("dynstr_realloc"); @@ -96,12 +98,12 @@ my_bool dynstr_append(DYNAMIC_STRING *str, const char *append) my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, - uint length) + size_t length) { char *new_ptr; if (str->length+length >= str->max_length) { - uint new_length=(str->length+length+str->alloc_increment)/ + size_t new_length=(str->length+length+str->alloc_increment)/ str->alloc_increment; new_length*=str->alloc_increment; if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME)))) @@ -116,19 +118,29 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, } -/** Concatenates any number of strings, escapes any OS quote in the result then - * surround the whole affair in another set of quotes which is finally appended - * to specified DYNAMIC_STRING. This function is especially useful when - * building strings to be executed with the system() function. - * @param str Dynamic String which will have addtional strings appended. - * @param append String to be appended. - * @param ... Optional. Additional string(s) to be appended. - * - * @note The final argument in the list must be NullS even if no additional - * options are passed. - * - * @return True = Success. - */ +my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) +{ + str->length-=n; + str->str[str->length]= '\0'; + return FALSE; +} + +/* + Concatenates any number of strings, escapes any OS quote in the result then + surround the whole affair in another set of quotes which is finally appended + to specified DYNAMIC_STRING. This function is especially useful when + building strings to be executed with the system() function. + + @param str Dynamic String which will have addtional strings appended. + @param append String to be appended. + @param ... Optional. Additional string(s) to be appended. + + @note The final argument in the list must be NullS even if no additional + options are passed. + + @return True = Success. +*/ + my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) { #ifdef __WIN__ diff --git a/mysys/test_charset.c b/mysys/test_charset.c index 08154e67863..d867b49304e 100644 --- a/mysys/test_charset.c +++ b/mysys/test_charset.c @@ -77,7 +77,7 @@ int main(int argc, char **argv) { _print_csinfo(cs); fflush(stdout); -#define NOT_USED_ANYMORE +#ifdef NOT_USED_ANYMORE cs_list = list_charsets(MYF(MY_CS_COMPILED | MY_CS_CONFIG)); printf("LIST OF CHARSETS (compiled + *.conf):\n%s\n", cs_list); my_free(cs_list,MYF(0)); diff --git a/mysys/test_dir.c b/mysys/test_dir.c index f1e4987371b..54e6c99e21e 100644 --- a/mysys/test_dir.c +++ b/mysys/test_dir.c @@ -15,7 +15,6 @@ /* TODO: Test all functions */ -#define USES_TYPES #include "mysys_priv.h" #include "my_dir.h" diff --git a/mysys/testhash.c b/mysys/testhash.c index fd2bc73b2ae..2add2ebd2d7 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -38,11 +38,11 @@ my_bool hash_check(HASH *hash); void free_record(void *record); -static byte *hash2_key(const byte *rec,uint *length, +static uchar *hash2_key(const uchar *rec,uint *length, my_bool not_used __attribute__((unused))) { *length=(uint) (uchar) rec[reclength-1]; - return (byte*) rec; + return (uchar*) rec; } /* main program */ @@ -196,7 +196,7 @@ static int do_test() pos=0; while ((recpos=hash_element(&hash,0))) { - record=(byte*) my_malloc(reclength,MYF(MY_FAE)); + record=(uchar*) my_malloc(reclength,MYF(MY_FAE)); memcpy(record,recpos,reclength); record[reclength-1]=rnd(5)+1; if (my_hash_insert(&hash2,record)) @@ -249,7 +249,6 @@ err: static int get_options(int argc, char **argv) { char *pos,*progname; - DEBUGGER_OFF; progname= argv[0]; @@ -269,7 +268,6 @@ static int get_options(int argc, char **argv) printf("Usage: %s [-?ABIKLWv] [-m#] [-t#]\n",progname); exit(0); case '#': - DEBUGGER_ON; DBUG_PUSH (++pos); break; } diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index 94ef309097a..6541fab138b 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* To avoid problems with alarms in debug code, we disable DBUG here */ #define FORCE_DBUG_OFF @@ -38,10 +40,10 @@ uint thr_client_alarm; static int alarm_aborted=1; /* No alarm thread */ my_bool thr_alarm_inited= 0; volatile my_bool alarm_thread_running= 0; - +time_t next_alarm_expire_time= ~ (time_t) 0; static sig_handler process_alarm_part2(int sig); -#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) +#if !defined(__WIN__) static pthread_mutex_t LOCK_alarm; static pthread_cond_t COND_alarm; @@ -60,7 +62,7 @@ static void *alarm_handler(void *arg); static sig_handler thread_alarm(int sig __attribute__((unused))); static int compare_ulong(void *not_used __attribute__((unused)), - byte *a_ptr,byte* b_ptr) + uchar *a_ptr,uchar* b_ptr) { ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr); return (a < b) ? -1 : (a == b) ? 0 : 1; @@ -71,6 +73,7 @@ void init_thr_alarm(uint max_alarms) sigset_t s; DBUG_ENTER("init_thr_alarm"); alarm_aborted=0; + next_alarm_expire_time= ~ (time_t) 0; init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, compare_ulong,NullS); sigfillset(&full_signal_set); /* Neaded to block signals */ @@ -150,21 +153,28 @@ void resize_thr_alarm(uint max_alarms) my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) { - ulong now; + time_t now; +#ifndef USE_ONE_SIGNAL_HAND sigset_t old_mask; +#endif my_bool reschedule; + struct st_my_thread_var *current_my_thread_var= my_thread_var; DBUG_ENTER("thr_alarm"); DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec)); - now=(ulong) time((time_t*) 0); + now= my_time(0); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); +#endif pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ if (alarm_aborted > 0) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); +#endif DBUG_RETURN(1); } if (alarm_aborted < 0) @@ -178,14 +188,14 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) fprintf(stderr,"Warning: thr_alarm queue is full\n"); *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); +#endif DBUG_RETURN(1); } max_used_alarms=alarm_queue.elements+1; } - reschedule= (!alarm_queue.elements || - (int) (((ALARM*) queue_top(&alarm_queue))->expire_time - now) > - (int) sec); + reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec; if (!alarm_data) { if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME)))) @@ -193,7 +203,9 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) DBUG_PRINT("info", ("failed my_malloc()")); *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); +#endif DBUG_RETURN(1); } alarm_data->malloced=1; @@ -202,20 +214,26 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) alarm_data->malloced=0; alarm_data->expire_time=now+sec; alarm_data->alarmed=0; - alarm_data->thread=pthread_self(); - queue_insert(&alarm_queue,(byte*) alarm_data); + alarm_data->thread= current_my_thread_var->pthread_self; + alarm_data->thread_id= current_my_thread_var->id; + queue_insert(&alarm_queue,(uchar*) alarm_data); /* Reschedule alarm if the current one has more than sec left */ if (reschedule) { DBUG_PRINT("info", ("reschedule")); if (pthread_equal(pthread_self(),alarm_thread)) + { alarm(sec); /* purecov: inspected */ + next_alarm_expire_time= now + sec; + } else reschedule_alarms(); /* Reschedule alarms */ } pthread_mutex_unlock(&LOCK_alarm); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); +#endif (*alrm)= &alarm_data->alarmed; DBUG_RETURN(0); } @@ -228,21 +246,25 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) void thr_end_alarm(thr_alarm_t *alarmed) { ALARM *alarm_data; +#ifndef USE_ONE_SIGNAL_HAND sigset_t old_mask; +#endif uint i, found=0; DBUG_ENTER("thr_end_alarm"); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); +#endif pthread_mutex_lock(&LOCK_alarm); - alarm_data= (ALARM*) ((byte*) *alarmed - offsetof(ALARM,alarmed)); + alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); for (i=0 ; i < alarm_queue.elements ; i++) { if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data) { queue_remove(&alarm_queue,i),MYF(0); if (alarm_data->malloced) - my_free((gptr) alarm_data,MYF(0)); + my_free((uchar*) alarm_data,MYF(0)); found++; #ifdef DBUG_OFF break; @@ -259,7 +281,9 @@ void thr_end_alarm(thr_alarm_t *alarmed) (long) *alarmed)); } pthread_mutex_unlock(&LOCK_alarm); +#ifndef USE_ONE_SIGNAL_HAND pthread_sigmask(SIG_SETMASK,&old_mask,NULL); +#endif DBUG_VOID_RETURN; } @@ -284,7 +308,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) #if defined(MAIN) && !defined(__bsdi__) printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ #endif return; @@ -303,7 +327,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) #endif process_alarm_part2(sig); #ifndef USE_ALARM_THREAD -#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND) +#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND) my_sigset(THR_SERVER_ALARM,process_alarm); #endif pthread_mutex_unlock(&LOCK_alarm); @@ -349,7 +373,7 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) } else { - ulong now=(ulong) time((time_t*) 0); + ulong now=(ulong) my_time(0); ulong next=now+10-(now%10); while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now) { @@ -378,10 +402,18 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) alarm(0); /* Remove old alarm */ #endif alarm((uint) (alarm_data->expire_time-now)); + next_alarm_expire_time= alarm_data->expire_time; } #endif } } + else + { + /* + Ensure that next time we call thr_alarm(), we will schedule a new alarm + */ + next_alarm_expire_time= ~(time_t) 0; + } DBUG_VOID_RETURN; } @@ -450,7 +482,7 @@ void end_thr_alarm(my_bool free_structures) Remove another thread from the alarm */ -void thr_alarm_kill(pthread_t thread_id) +void thr_alarm_kill(my_thread_id thread_id) { uint i; if (alarm_aborted) @@ -458,12 +490,11 @@ void thr_alarm_kill(pthread_t thread_id) pthread_mutex_lock(&LOCK_alarm); for (i=0 ; i < alarm_queue.elements ; i++) { - if (pthread_equal(((ALARM*) queue_element(&alarm_queue,i))->thread, - thread_id)) + if (((ALARM*) queue_element(&alarm_queue,i))->thread_id == thread_id) { ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); tmp->expire_time=0; - queue_insert(&alarm_queue,(byte*) tmp); + queue_insert(&alarm_queue,(uchar*) tmp); reschedule_alarms(); break; } @@ -479,7 +510,7 @@ void thr_alarm_info(ALARM_INFO *info) info->max_used_alarms= max_used_alarms; if ((info->active_alarms= alarm_queue.elements)) { - ulong now=(ulong) time((time_t*) 0); + ulong now=(ulong) my_time(0); long time_diff; ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue); time_diff= (long) (alarm_data->expire_time - now); @@ -494,12 +525,12 @@ void thr_alarm_info(ALARM_INFO *info) */ -static sig_handler thread_alarm(int sig) +static sig_handler thread_alarm(int sig __attribute__((unused))) { #ifdef MAIN printf("thread_alarm\n"); fflush(stdout); #endif -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,thread_alarm); /* int. thread system calls */ #endif } @@ -527,7 +558,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) { if (alarm_queue.elements) { - ulong sleep_time,now=time((time_t*) 0); + ulong sleep_time,now= my_time(0); if (alarm_aborted) sleep_time=now+1; else @@ -536,6 +567,7 @@ static void *alarm_handler(void *arg __attribute__((unused))) { abstime.tv_sec=sleep_time; abstime.tv_nsec=0; + next_alarm_expire_time= sleep_time; if ((error=pthread_cond_timedwait(&COND_alarm,&LOCK_alarm,&abstime)) && error != ETIME && error != ETIMEDOUT) { @@ -548,12 +580,16 @@ static void *alarm_handler(void *arg __attribute__((unused))) } else if (alarm_aborted == -1) break; - else if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) + else { + next_alarm_expire_time= ~ (time_t) 0; + if ((error=pthread_cond_wait(&COND_alarm,&LOCK_alarm))) + { #ifdef MAIN - printf("Got error: %d from ptread_cond_wait (errno: %d)\n", - error,errno); + printf("Got error: %d from ptread_cond_wait (errno: %d)\n", + error,errno); #endif + } } process_alarm(0); } @@ -567,151 +603,12 @@ static void *alarm_handler(void *arg __attribute__((unused))) #endif /* USE_ALARM_THREAD */ /***************************************************************************** - thr_alarm for OS/2 -*****************************************************************************/ - -#elif defined(__EMX__) || defined(OS2) - -#define INCL_BASE -#define INCL_NOPMAPI -#include <os2.h> - -static pthread_mutex_t LOCK_alarm; -static sigset_t full_signal_set; -static QUEUE alarm_queue; -pthread_t alarm_thread; - -#ifdef USE_ALARM_THREAD -static pthread_cond_t COND_alarm; -static void *alarm_handler(void *arg); -#define reschedule_alarms() pthread_cond_signal(&COND_alarm) -#else -#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) -#endif - -sig_handler process_alarm(int sig __attribute__((unused))) -{ - sigset_t old_mask; - ALARM *alarm_data; - DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements)); -} - - -/* - Remove another thread from the alarm -*/ - -void thr_alarm_kill(pthread_t thread_id) -{ - uint i; - - pthread_mutex_lock(&LOCK_alarm); - for (i=0 ; i < alarm_queue.elements ; i++) - { - if (pthread_equal(((ALARM*) queue_element(&alarm_queue,i))->thread, - thread_id)) - { - ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); - tmp->expire_time=0; - queue_insert(&alarm_queue,(byte*) tmp); - reschedule_alarms(); - break; - } - } - pthread_mutex_unlock(&LOCK_alarm); -} - -bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm) -{ - APIRET rc; - if (alarm_aborted) - { - alarm->alarmed.crono=0; - alarm->alarmed.event=0; - return 1; - } - if (rc = DosCreateEventSem(NULL,(HEV *) &alarm->alarmed.event, - DC_SEM_SHARED,FALSE)) - { - printf("Error creating event semaphore! [%d] \n",rc); - alarm->alarmed.crono=0; - alarm->alarmed.event=0; - return 1; - } - if (rc = DosAsyncTimer((long) sec*1000L, (HSEM) alarm->alarmed.event, - (HTIMER *) &alarm->alarmed.crono)) - { - printf("Error starting async timer! [%d] \n",rc); - DosCloseEventSem((HEV) alarm->alarmed.event); - alarm->alarmed.crono=0; - alarm->alarmed.event=0; - return 1; - } /* endif */ - (*alrm)= &alarm->alarmed; - return 1; -} - - -bool thr_got_alarm(thr_alarm_t *alrm_ptr) -{ - thr_alarm_t alrm= *alrm_ptr; - APIRET rc; - - if (alrm->crono) - { - rc = DosWaitEventSem((HEV) alrm->event, SEM_IMMEDIATE_RETURN); - if (rc == 0) { - DosCloseEventSem((HEV) alrm->event); - alrm->crono = 0; - alrm->event = 0; - } /* endif */ - } - return !alrm->crono || alarm_aborted; -} - - -void thr_end_alarm(thr_alarm_t *alrm_ptr) -{ - thr_alarm_t alrm= *alrm_ptr; - if (alrm->crono) - { - DosStopTimer((HTIMER) alrm->crono); - DosCloseEventSem((HEV) alrm->event); - alrm->crono = 0; - alrm->event = 0; - } -} - -void end_thr_alarm(my_bool free_structures) -{ - DBUG_ENTER("end_thr_alarm"); - alarm_aborted=1; /* No more alarms */ - DBUG_VOID_RETURN; -} - -void init_thr_alarm(uint max_alarm) -{ - DBUG_ENTER("init_thr_alarm"); - alarm_aborted=0; /* Yes, Gimmie alarms */ - DBUG_VOID_RETURN; -} - -void thr_alarm_info(ALARM_INFO *info) -{ - bzero((char*) info, sizeof(*info)); -} - -void resize_thr_alarm(uint max_alarms) -{ -} - -/***************************************************************************** thr_alarm for win95 *****************************************************************************/ #else /* __WIN__ */ -void thr_alarm_kill(pthread_t thread_id) +void thr_alarm_kill(my_thread_id thread_id) { /* Can't do this yet */ } @@ -737,7 +634,7 @@ my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm) } -bool thr_got_alarm(thr_alarm_t *alrm_ptr) +my_bool thr_got_alarm(thr_alarm_t *alrm_ptr) { thr_alarm_t alrm= *alrm_ptr; MSG msg; @@ -823,7 +720,7 @@ static void *test_thread(void *arg) for (i=1 ; i <= 10 ; i++) { wait_time=param ? 11-i : i; - start_time=time((time_t*) 0); + start_time= my_time(0); if (thr_alarm(&got_alarm,wait_time,0)) { printf("Thread: %s Alarms aborted\n",my_thread_name()); @@ -885,7 +782,7 @@ static void *test_thread(void *arg) } } printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(), - (int) (time((time_t*) 0)-start_time), wait_time); fflush(stdout); + (int) (my_time(0)-start_time), wait_time); fflush(stdout); thr_end_alarm(&got_alarm); fflush(stdout); } @@ -893,7 +790,7 @@ static void *test_thread(void *arg) thread_count--; VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ pthread_mutex_unlock(&LOCK_thread_count); - free((gptr) arg); + free((uchar*) arg); return 0; } @@ -902,13 +799,11 @@ static sig_handler print_signal_warning(int sig) { printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); fflush(stdout); -#ifdef DONT_REMEMBER_SIGNAL +#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif -#ifndef OS2 if (sig == SIGALRM) alarm(2); /* reschedule alarm */ -#endif } #endif /* USE_ONE_SIGNAL_HAND */ @@ -925,7 +820,6 @@ static void *signal_hand(void *arg __attribute__((unused))) VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ pthread_mutex_unlock(&LOCK_thread_count); -#ifndef OS2 sigemptyset(&set); /* Catch all signals */ sigaddset(&set,SIGINT); sigaddset(&set,SIGQUIT); @@ -940,7 +834,6 @@ static void *signal_hand(void *arg __attribute__((unused))) #else puts("Starting signal handling thread"); #endif -#endif /* OS2 */ printf("server alarm: %d thread alarm: %d\n", THR_SERVER_ALARM, thr_client_alarm); DBUG_PRINT("info",("Starting signal and alarm handling thread")); @@ -963,9 +856,7 @@ static void *signal_hand(void *arg __attribute__((unused))) case SIGINT: case SIGQUIT: case SIGTERM: -#ifndef OS2 case SIGHUP: -#endif printf("Aborting nicely\n"); end_thr_alarm(0); break; @@ -975,13 +866,11 @@ static void *signal_hand(void *arg __attribute__((unused))) exit(1); return 0; /* Keep some compilers happy */ #endif -#ifndef OS2 #ifdef USE_ONE_SIGNAL_HAND case THR_SERVER_ALARM: process_alarm(sig); break; #endif -#endif /* OS2 */ } } } @@ -997,13 +886,13 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) MY_INIT(argv[0]); if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') + { DBUG_PUSH(argv[1]+2); - + } pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_thread_count,NULL); /* Start a alarm handling thread */ -#ifndef OS2 sigemptyset(&set); sigaddset(&set,SIGINT); sigaddset(&set,SIGQUIT); @@ -1021,7 +910,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set, thr_client_alarm); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); #endif -#endif /* OS2 */ pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 33803feaadb..97aa51b3ddf 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1,5 +1,5 @@ -/* Copyright (c) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. - Use is subject to license terms. +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -12,7 +12,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Read and write locks for Posix threads. All tread must acquire @@ -72,7 +73,7 @@ multiple read locks. */ #if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG) -#define DBUG_OFF +#define FORCE_DBUG_OFF #endif #include "mysys_priv.h" @@ -122,12 +123,11 @@ thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs) static uint found_errors=0; static int check_lock(struct st_lock_list *list, const char* lock_type, - const char *where, my_bool same_owner, bool no_cond) + const char *where, my_bool same_owner, my_bool no_cond) { THR_LOCK_DATA *data,**prev; uint count=0; - THR_LOCK_OWNER *first_owner; - LINT_INIT(first_owner); + THR_LOCK_OWNER *UNINIT_VAR(first_owner); prev= &list->data; if (list->data) @@ -344,8 +344,9 @@ void thr_lock_delete(THR_LOCK *lock) void thr_lock_info_init(THR_LOCK_INFO *info) { - info->thread= pthread_self(); - info->thread_id= my_thread_id(); /* for debugging */ + struct st_my_thread_var *tmp= my_thread_var; + info->thread= tmp->pthread_self; + info->thread_id= tmp->id; info->n_cursors= 0; } @@ -396,6 +397,29 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, struct timespec wait_timeout; enum enum_thr_lock_result result= THR_LOCK_ABORTED; my_bool can_deadlock= test(data->owner->info->n_cursors); + DBUG_ENTER("wait_for_lock"); + + /* + One can use this to signal when a thread is going to wait for a lock. + See debug_sync.cc. + + Beware of waiting for a signal here. The lock has aquired its mutex. + While waiting on a signal here, the locking thread could not aquire + the mutex to release the lock. One could lock up the table + completely. + + In detail it works so: When thr_lock() tries to acquire a table + lock, it locks the lock->mutex, checks if it can have the lock, and + if not, it calls wait_for_lock(). Here it unlocks the table lock + while waiting on a condition. The sync point is located before this + wait for condition. If we have a waiting action here, we hold the + the table locks mutex all the time. Any attempt to look at the table + lock by another thread blocks it immediately on lock->mutex. This + can easily become an unexpected and unobvious blockage. So be + warned: Do not request a WAIT_FOR action for the 'wait_for_lock' + sync point unless you really know what you do. + */ + DEBUG_SYNC_C("wait_for_lock"); if (!in_wait_list) { @@ -404,6 +428,8 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, wait->last= &data->next; } + statistic_increment(locks_waited, &THR_LOCK_lock); + /* Set up control struct to allow others to abort locks */ thread_var->current_mutex= &data->lock->mutex; thread_var->current_cond= cond; @@ -431,13 +457,21 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, if the predicate is true. */ if (data->cond == 0) + { + DBUG_PRINT("thr_lock", ("lock granted/aborted")); break; + } if (rc == ETIMEDOUT || rc == ETIME) { + /* purecov: begin inspected */ + DBUG_PRINT("thr_lock", ("lock timed out")); result= THR_LOCK_WAIT_TIMEOUT; break; + /* purecov: end */ } } + DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d", + thread_var->abort, in_wait_list)); if (data->cond || data->type == TL_UNLOCK) { @@ -453,13 +487,13 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, } else { + DBUG_PRINT("thr_lock", ("lock aborted")); check_locks(data->lock, "aborted wait_for_lock", 0); } } else { result= THR_LOCK_SUCCESS; - statistic_increment(locks_waited, &THR_LOCK_lock); if (data->lock->get_status) (*data->lock->get_status)(data->status_param, 0); check_locks(data->lock,"got wait_for_lock",0); @@ -471,7 +505,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, thread_var->current_mutex= 0; thread_var->current_cond= 0; pthread_mutex_unlock(&thread_var->mutex); - return result; + DBUG_RETURN(result); } @@ -490,7 +524,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, data->type=lock_type; data->owner= owner; /* Must be reset ! */ VOID(pthread_mutex_lock(&lock->mutex)); - DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx type: %d", + DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", (long) data, data->owner->info->thread_id, (long) lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? @@ -509,7 +543,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, and the read lock is not TL_READ_NO_INSERT */ - DBUG_PRINT("lock",("write locked by thread: %ld", + DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", lock->write.data->owner->info->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && @@ -598,10 +632,14 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, { if (lock->write.data->type == TL_WRITE_ONLY) { - /* We are not allowed to get a lock in this case */ - data->type=TL_UNLOCK; - result= THR_LOCK_ABORTED; /* Can't wait for this one */ - goto end; + /* Allow lock owner to bypass TL_WRITE_ONLY. */ + if (!thr_lock_owner_equal(data->owner, lock->write.data->owner)) + { + /* We are not allowed to get a lock in this case */ + data->type=TL_UNLOCK; + result= THR_LOCK_ABORTED; /* Can't wait for this one */ + goto end; + } } /* @@ -631,7 +669,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } - DBUG_PRINT("lock",("write locked by thread: %ld", + DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx", lock->write.data->owner->info->thread_id)); } else @@ -667,7 +705,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, goto end; } } - DBUG_PRINT("lock",("write locked by thread: %ld type: %d", + DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d", lock->read.data->owner->info->thread_id, data->type)); } wait_queue= &lock->write_wait; @@ -681,6 +719,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, lock_owner= lock->read.data ? lock->read.data : lock->write.data; if (lock_owner && lock_owner->owner->info == owner->info) { + DBUG_PRINT("lock",("deadlock")); result= THR_LOCK_DEADLOCK; goto end; } @@ -693,7 +732,7 @@ end: static inline void free_all_read_locks(THR_LOCK *lock, - bool using_concurrent_insert) + my_bool using_concurrent_insert) { THR_LOCK_DATA *data=lock->read_wait.data; @@ -729,8 +768,10 @@ static inline void free_all_read_locks(THR_LOCK *lock, } lock->read_no_write_count++; } - DBUG_PRINT("lock",("giving read lock to thread: %ld", + /* purecov: begin inspected */ + DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", data->owner->info->thread_id)); + /* purecov: end */ data->cond=0; /* Mark thread free */ VOID(pthread_cond_signal(cond)); } while ((data=data->next)); @@ -747,7 +788,7 @@ void thr_unlock(THR_LOCK_DATA *data) THR_LOCK *lock=data->lock; enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); - DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx", + DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", (long) data, data->owner->info->thread_id, (long) lock)); pthread_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock",0); @@ -835,8 +876,10 @@ static void wake_up_waiters(THR_LOCK *lock) if (data->type == TL_WRITE_CONCURRENT_INSERT && (*lock->check_status)(data->status_param)) data->type=TL_WRITE; /* Upgrade lock */ - DBUG_PRINT("lock",("giving write lock of type %d to thread: %ld", + /* purecov: begin inspected */ + DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", data->type, data->owner->info->thread_id)); + /* purecov: end */ { pthread_cond_t *cond=data->cond; data->cond=0; /* Mark thread free */ @@ -916,7 +959,7 @@ end: */ -#define LOCK_CMP(A,B) ((byte*) (A->lock) - (uint) ((A)->type) < (byte*) (B->lock)- (uint) ((B)->type)) +#define LOCK_CMP(A,B) ((uchar*) (A->lock) - (uint) ((A)->type) < (uchar*) (B->lock)- (uint) ((B)->type)) static void sort_locks(THR_LOCK_DATA **data,uint count) { @@ -1030,7 +1073,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) thr_unlock(*pos); else { - DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: %ld lock: 0x%lx", + DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: 0x%lx lock: 0x%lx", (long) *pos, (*pos)->owner->info->thread_id, (long) (*pos)->lock)); } @@ -1043,7 +1086,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) TL_WRITE_ONLY to abort any new accesses to the lock */ -void thr_abort_locks(THR_LOCK *lock) +void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock) { THR_LOCK_DATA *data; DBUG_ENTER("thr_abort_locks"); @@ -1065,7 +1108,7 @@ void thr_abort_locks(THR_LOCK *lock) lock->read_wait.last= &lock->read_wait.data; lock->write_wait.last= &lock->write_wait.data; lock->read_wait.data=lock->write_wait.data=0; - if (lock->write.data) + if (upgrade_lock && lock->write.data) lock->write.data->type=TL_WRITE_ONLY; pthread_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; @@ -1078,7 +1121,7 @@ void thr_abort_locks(THR_LOCK *lock) This is used to abort all locks for a specific thread */ -my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread) +my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) { THR_LOCK_DATA *data; my_bool found= FALSE; @@ -1087,7 +1130,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread) pthread_mutex_lock(&lock->mutex); for (data= lock->read_wait.data; data ; data= data->next) { - if (pthread_equal(thread, data->owner->info->thread)) + if (data->owner->info->thread_id == thread_id) /* purecov: tested */ { DBUG_PRINT("info",("Aborting read-wait lock")); data->type= TL_UNLOCK; /* Mark killed */ @@ -1104,7 +1147,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread) } for (data= lock->write_wait.data; data ; data= data->next) { - if (pthread_equal(thread, data->owner->info->thread)) + if (data->owner->info->thread_id == thread_id) /* purecov: tested */ { DBUG_PRINT("info",("Aborting write-wait lock")); data->type= TL_UNLOCK; @@ -1124,10 +1167,223 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread) } +/* + Downgrade a WRITE_* to a lower WRITE level + SYNOPSIS + thr_downgrade_write_lock() + in_data Lock data of thread downgrading its lock + new_lock_type New write lock type + RETURN VALUE + NONE + DESCRIPTION + This can be used to downgrade a lock already owned. When the downgrade + occurs also other waiters, both readers and writers can be allowed to + start. + The previous lock is often TL_WRITE_ONLY but can also be + TL_WRITE and TL_WRITE_ALLOW_READ. The normal downgrade variants are + TL_WRITE_ONLY => TL_WRITE_ALLOW_READ After a short exclusive lock + TL_WRITE_ALLOW_READ => TL_WRITE_ALLOW_WRITE After discovering that the + operation didn't need such a high lock. + TL_WRITE_ONLY => TL_WRITE after a short exclusive lock while holding a + write table lock + TL_WRITE_ONLY => TL_WRITE_ALLOW_WRITE After a short exclusive lock after + already earlier having dongraded lock to TL_WRITE_ALLOW_WRITE + The implementation is conservative and rather don't start rather than + go on unknown paths to start, the common cases are handled. + + NOTE: + In its current implementation it is only allowed to downgrade from + TL_WRITE_ONLY. In this case there are no waiters. Thus no wake up + logic is required. +*/ + +void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, + enum thr_lock_type new_lock_type) +{ + THR_LOCK *lock=in_data->lock; +#ifndef DBUG_OFF + enum thr_lock_type old_lock_type= in_data->type; +#endif +#ifdef TO_BE_REMOVED + THR_LOCK_DATA *data, *next; + bool start_writers= FALSE; + bool start_readers= FALSE; +#endif + DBUG_ENTER("thr_downgrade_write_only_lock"); + + pthread_mutex_lock(&lock->mutex); + DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY); + DBUG_ASSERT(old_lock_type > new_lock_type); + in_data->type= new_lock_type; + check_locks(lock,"after downgrading lock",0); + +#if TO_BE_REMOVED + switch (old_lock_type) + { + case TL_WRITE_ONLY: + case TL_WRITE: + case TL_WRITE_LOW_PRIORITY: + /* + Previous lock was exclusive we are now ready to start up most waiting + threads. + */ + switch (new_lock_type) + { + case TL_WRITE_ALLOW_READ: + /* Still cannot start WRITE operations. Can only start readers. */ + start_readers= TRUE; + break; + case TL_WRITE: + case TL_WRITE_LOW_PRIORITY: + /* + Still cannot start anything, but new requests are no longer + aborted. + */ + break; + case TL_WRITE_ALLOW_WRITE: + /* + We can start both writers and readers. + */ + start_writers= TRUE; + start_readers= TRUE; + break; + case TL_WRITE_CONCURRENT_INSERT: + case TL_WRITE_DELAYED: + /* + This routine is not designed for those. Lock will be downgraded + but no start of waiters will occur. This is not the optimal but + should be a correct behaviour. + */ + break; + default: + DBUG_ASSERT(0); + } + break; + case TL_WRITE_DELAYED: + case TL_WRITE_CONCURRENT_INSERT: + /* + This routine is not designed for those. Lock will be downgraded + but no start of waiters will occur. This is not the optimal but + should be a correct behaviour. + */ + break; + case TL_WRITE_ALLOW_READ: + DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); + /* + Previously writers were not allowed to start, now it is ok to + start them again. Readers are already allowed so no reason to + handle them. + */ + start_writers= TRUE; + break; + default: + DBUG_ASSERT(0); + break; + } + if (start_writers) + { + /* + At this time the only active writer can be ourselves. Thus we need + not worry about that there are other concurrent write operations + active on the table. Thus we only need to worry about starting + waiting operations. + We also only come here with TL_WRITE_ALLOW_WRITE as the new + lock type, thus we can start other writers also of the same type. + If we find a lock at exclusive level >= TL_WRITE_LOW_PRIORITY we + don't start any more operations that would be mean those operations + will have to wait for things started afterwards. + */ + DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); + for (data=lock->write_wait.data; data ; data= next) + { + /* + All WRITE requests compatible with new lock type are also + started + */ + next= data->next; + if (start_writers && data->type == new_lock_type) + { + pthread_cond_t *cond= data->cond; + /* + It is ok to start this waiter. + Move from being first in wait queue to be last in write queue. + */ + if (((*data->prev)= data->next)) + data->next->prev= data->prev; + else + lock->write_wait.last= data->prev; + data->prev= lock->write.last; + lock->write.last= &data->next; + data->next= 0; + check_locks(lock, "Started write lock after downgrade",0); + data->cond= 0; + pthread_cond_signal(cond); + } + else + { + /* + We found an incompatible lock, we won't start any more write + requests to avoid letting writers pass other writers in the + queue. + */ + start_writers= FALSE; + if (data->type >= TL_WRITE_LOW_PRIORITY) + { + /* + We have an exclusive writer in the queue so we won't start + readers either. + */ + start_readers= FALSE; + } + } + } + } + if (start_readers) + { + DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE || + new_lock_type == TL_WRITE_ALLOW_READ); + /* + When we come here we know that the write locks are + TL_WRITE_ALLOW_WRITE or TL_WRITE_ALLOW_READ. This means that reads + are ok + */ + for (data=lock->read_wait.data; data ; data=next) + { + next= data->next; + /* + All reads are ok to start now except TL_READ_NO_INSERT when + write lock is TL_WRITE_ALLOW_READ. + */ + if (new_lock_type != TL_WRITE_ALLOW_READ || + data->type != TL_READ_NO_INSERT) + { + pthread_cond_t *cond= data->cond; + if (((*data->prev)= data->next)) + data->next->prev= data->prev; + else + lock->read_wait.last= data->prev; + data->prev= lock->read.last; + lock->read.last= &data->next; + data->next= 0; + + if (data->type == TL_READ_NO_INSERT) + lock->read_no_write_count++; + check_locks(lock, "Started read lock after downgrade",0); + data->cond= 0; + pthread_cond_signal(cond); + } + } + } + check_locks(lock,"after starting waiters after downgrading lock",0); +#endif + pthread_mutex_unlock(&lock->mutex); + DBUG_VOID_RETURN; +} /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ -my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type) { THR_LOCK *lock=data->lock; DBUG_ENTER("thr_upgrade_write_delay_lock"); @@ -1140,7 +1396,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) } check_locks(lock,"before upgrading lock",0); /* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */ - data->type=TL_WRITE; /* Upgrade lock */ + data->type= new_lock_type; /* Upgrade lock */ /* Check if someone has given us the lock */ if (!data->cond) @@ -1179,6 +1435,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) { THR_LOCK *lock=data->lock; + enum thr_lock_type write_lock_type; DBUG_ENTER("thr_reschedule_write_lock"); pthread_mutex_lock(&lock->mutex); @@ -1188,6 +1445,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) DBUG_RETURN(0); } + write_lock_type= data->type; data->type=TL_WRITE_DELAYED; if (lock->update_status) (*lock->update_status)(data->status_param); @@ -1206,7 +1464,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) free_all_read_locks(lock,0); pthread_mutex_unlock(&lock->mutex); - DBUG_RETURN(thr_upgrade_write_delay_lock(data)); + DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type)); } @@ -1343,6 +1601,10 @@ static void test_get_status(void* param __attribute__((unused)), { } +static void test_update_status(void* param __attribute__((unused))) +{ +} + static void test_copy_status(void* to __attribute__((unused)) , void *from __attribute__((unused))) { @@ -1402,7 +1664,7 @@ static void *test_thread(void *arg) thread_count--; VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ pthread_mutex_unlock(&LOCK_thread_count); - free((gptr) arg); + free((uchar*) arg); return 0; } @@ -1435,7 +1697,7 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) { thr_lock_init(locks+i); locks[i].check_status= test_check_status; - locks[i].update_status=test_get_status; + locks[i].update_status=test_update_status; locks[i].copy_status= test_copy_status; locks[i].get_status= test_get_status; } diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 53ee907e0a3..0a7b9a5c015 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* + Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 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 @@ -11,7 +12,8 @@ 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 */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* This makes a wrapper for mutex handling to make it easier to debug mutex */ @@ -247,7 +249,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, { fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex at %s, line %d\n", - mp->count-1, my_thread_id(), file, line); + mp->count-1, my_thread_dbug_id(), file, line); fflush(stderr); abort(); } @@ -259,8 +261,8 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, - struct timespec *abstime, - const char *file, uint line) + const struct timespec *abstime, + const char *file, uint line) { int error; pthread_mutex_lock(&mp->global); @@ -285,7 +287,7 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, { fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex at %s, line %d (error: %d (%d))\n", - mp->count-1, my_thread_id(), file, line, error, error); + mp->count-1, my_thread_dbug_id(), file, line, error, error); fflush(stderr); abort(); } @@ -391,3 +393,108 @@ void safe_mutex_end(FILE *file __attribute__((unused))) } #endif /* THREAD && SAFE_MUTEX */ + +#if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) + +#include "mysys_priv.h" +#include "my_static.h" +#include <m_string.h> + +#include <m_ctype.h> +#include <hash.h> +#include <myisampack.h> +#include <mysys_err.h> +#include <my_sys.h> + +#undef pthread_mutex_t +#undef pthread_mutex_init +#undef pthread_mutex_lock +#undef pthread_mutex_trylock +#undef pthread_mutex_unlock +#undef pthread_mutex_destroy +#undef pthread_cond_wait +#undef pthread_cond_timedwait + +ulong mutex_delay(ulong delayloops) +{ + ulong i; + volatile ulong j; + + j = 0; + + for (i = 0; i < delayloops * 50; i++) + j += i; + + return(j); +} + +#define MY_PTHREAD_FASTMUTEX_SPINS 8 +#define MY_PTHREAD_FASTMUTEX_DELAY 4 + +static int cpu_count= 0; + +int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, + const pthread_mutexattr_t *attr) +{ + if ((cpu_count > 1) && (attr == MY_MUTEX_INIT_FAST)) + mp->spins= MY_PTHREAD_FASTMUTEX_SPINS; + else + mp->spins= 0; + mp->rng_state= 1; + return pthread_mutex_init(&mp->mutex, attr); +} + +/** + Park-Miller random number generator. A simple linear congruential + generator that operates in multiplicative group of integers modulo n. + + x_{k+1} = (x_k g) mod n + + Popular pair of parameters: n = 2^32 − 5 = 4294967291 and g = 279470273. + The period of the generator is about 2^31. + Largest value that can be returned: 2147483646 (RAND_MAX) + + Reference: + + S. K. Park and K. W. Miller + "Random number generators: good ones are hard to find" + Commun. ACM, October 1988, Volume 31, No 10, pages 1192-1201. +*/ + +static double park_rng(my_pthread_fastmutex_t *mp) +{ + mp->rng_state= ((my_ulonglong)mp->rng_state * 279470273U) % 4294967291U; + return (mp->rng_state / 2147483647.0); +} + +int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp) +{ + int res; + uint i; + uint maxdelay= MY_PTHREAD_FASTMUTEX_DELAY; + + for (i= 0; i < mp->spins; i++) + { + res= pthread_mutex_trylock(&mp->mutex); + + if (res == 0) + return 0; + + if (res != EBUSY) + return res; + + mutex_delay(maxdelay); + maxdelay += park_rng(mp) * MY_PTHREAD_FASTMUTEX_DELAY + 1; + } + return pthread_mutex_lock(&mp->mutex); +} + + +void fastmutex_global_init(void) +{ +#ifdef _SC_NPROCESSORS_CONF + cpu_count= sysconf(_SC_NPROCESSORS_CONF); +#endif +} + +#endif /* defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) */ diff --git a/mysys/tree.c b/mysys/tree.c index 2e6868e0777..ef33f75b7c6 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -93,7 +93,7 @@ void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, if (default_alloc_size < DEFAULT_ALLOC_SIZE) default_alloc_size= DEFAULT_ALLOC_SIZE; default_alloc_size= MY_ALIGN(default_alloc_size, DEFAULT_ALIGN_SIZE); - bzero((gptr) &tree->null_element,sizeof(tree->null_element)); + bzero((uchar*) &tree->null_element,sizeof(tree->null_element)); tree->root= &tree->null_element; tree->compare=compare; tree->size_of_element=size > 0 ? (uint) size : 0; @@ -247,12 +247,12 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, else { *((void**) (element+1))= (void*) ((void **) (element+1)+1); - memcpy((byte*) *((void **) (element+1)),key, + memcpy((uchar*) *((void **) (element+1)),key, (size_t) (key_size-sizeof(void*))); } } else - memcpy((byte*) element+tree->offset_to_key,key,(size_t) key_size); + memcpy((uchar*) element+tree->offset_to_key,key,(size_t) key_size); element->count=1; /* May give warning in purify */ tree->elements_in_tree++; rb_insert(tree,parent,element); /* rebalance tree */ @@ -326,7 +326,7 @@ int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg) if (tree->free) (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size; - my_free((gptr) element,MYF(0)); + my_free((uchar*) element,MYF(0)); tree->elements_in_tree--; return 0; } diff --git a/mysys/trie.c b/mysys/trie.c new file mode 100644 index 00000000000..5738b9b866b --- /dev/null +++ b/mysys/trie.c @@ -0,0 +1,236 @@ +/* Copyright (C) 2005 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 */ + +/* + Implementation of trie and Aho-Corasick automaton. + Supports only charsets that can be compared byte-wise. + + TODO: + Add character frequencies. Can increase lookup speed + up to 30%. + Implement character-wise comparision. +*/ + + +#include "mysys_priv.h" +#include <m_string.h> +#include <my_trie.h> +#include <my_base.h> + + +/* + SYNOPSIS + TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset); + + DESCRIPTION + Allocates or initializes a `TRIE' object. If `trie' is a `NULL' + pointer, the function allocates, initializes, and returns a new + object. Otherwise, the object is initialized and the address of + the object is returned. If `trie_init()' allocates a new object, + it will be freed when `trie_free()' is called. + + RETURN VALUE + An initialized `TRIE*' object. `NULL' if there was insufficient + memory to allocate a new object. +*/ + +TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset) +{ + MEM_ROOT mem_root; + DBUG_ENTER("trie_init"); + DBUG_ASSERT(charset); + init_alloc_root(&mem_root, + (sizeof(TRIE_NODE) * 128) + ALLOC_ROOT_MIN_BLOCK_SIZE, + sizeof(TRIE_NODE) * 128); + if (! trie) + { + if (! (trie= (TRIE *)alloc_root(&mem_root, sizeof(TRIE)))) + { + free_root(&mem_root, MYF(0)); + DBUG_RETURN(NULL); + } + } + + memcpy(&trie->mem_root, &mem_root, sizeof(MEM_ROOT)); + trie->root.leaf= 0; + trie->root.c= 0; + trie->root.next= NULL; + trie->root.links= NULL; + trie->root.fail= NULL; + trie->charset= charset; + trie->nnodes= 0; + trie->nwords= 0; + DBUG_RETURN(trie); +} + + +/* + SYNOPSIS + void trie_free (TRIE *trie); + trie - valid pointer to `TRIE' + + DESCRIPTION + Frees the memory allocated for a `trie'. + + RETURN VALUE + None. +*/ + +void trie_free (TRIE *trie) +{ + MEM_ROOT mem_root; + DBUG_ENTER("trie_free"); + DBUG_ASSERT(trie); + memcpy(&mem_root, &trie->mem_root, sizeof(MEM_ROOT)); + free_root(&mem_root, MYF(0)); + DBUG_VOID_RETURN; +} + + +/* + SYNOPSIS + my_bool trie_insert (TRIE *trie, const uchar *key, uint keylen); + trie - valid pointer to `TRIE' + key - valid pointer to key to insert + keylen - non-0 key length + + DESCRIPTION + Inserts new key into trie. + + RETURN VALUE + Upon successful completion, `trie_insert' returns `FALSE'. Otherwise + `TRUE' is returned. + + NOTES + If this function fails you must assume `trie' is broken. + However it can be freed with trie_free(). +*/ + +my_bool trie_insert (TRIE *trie, const uchar *key, uint keylen) +{ + TRIE_NODE *node; + TRIE_NODE *next; + uchar p; + uint k; + DBUG_ENTER("trie_insert"); + DBUG_ASSERT(trie && key && keylen); + node= &trie->root; + trie->root.fail= NULL; + for (k= 0; k < keylen; k++) + { + p= key[k]; + for (next= node->links; next; next= next->next) + if (next->c == p) + break; + + if (! next) + { + TRIE_NODE *tmp= (TRIE_NODE *)alloc_root(&trie->mem_root, + sizeof(TRIE_NODE)); + if (! tmp) + DBUG_RETURN(TRUE); + tmp->leaf= 0; + tmp->c= p; + tmp->links= tmp->fail= tmp->next= NULL; + trie->nnodes++; + if (! node->links) + { + node->links= tmp; + } + else + { + for (next= node->links; next->next; next= next->next) /* no-op */; + next->next= tmp; + } + node= tmp; + } + else + { + node= next; + } + } + node->leaf= keylen; + trie->nwords++; + DBUG_RETURN(FALSE); +} + + +/* + SYNOPSIS + my_bool trie_prepare (TRIE *trie); + trie - valid pointer to `TRIE' + + DESCRIPTION + Constructs Aho-Corasick automaton. + + RETURN VALUE + Upon successful completion, `trie_prepare' returns `FALSE'. Otherwise + `TRUE' is returned. +*/ + +my_bool ac_trie_prepare (TRIE *trie) +{ + TRIE_NODE **tmp_nodes; + TRIE_NODE *node; + uint32 fnode= 0; + uint32 lnode= 0; + DBUG_ENTER("trie_prepare"); + DBUG_ASSERT(trie); + + tmp_nodes= (TRIE_NODE **)my_malloc(trie->nnodes * sizeof(TRIE_NODE *), MYF(0)); + if (! tmp_nodes) + DBUG_RETURN(TRUE); + + trie->root.fail= &trie->root; + for (node= trie->root.links; node; node= node->next) + { + node->fail= &trie->root; + tmp_nodes[lnode++]= node; + } + + while (fnode < lnode) + { + TRIE_NODE *current= (TRIE_NODE *)tmp_nodes[fnode++]; + for (node= current->links; node; node= node->next) + { + TRIE_NODE *fail= current->fail; + tmp_nodes[lnode++]= node; + while (! (node->fail= trie_goto(&trie->root, fail, node->c))) + fail= fail->fail; + } + } + my_free((uchar*)tmp_nodes, MYF(0)); + DBUG_RETURN(FALSE); +} + + +/* + SYNOPSIS + void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state); + trie - valid pointer to `TRIE' + state - value pointer to `AC_TRIE_STATE' + + DESCRIPTION + Initializes `AC_TRIE_STATE' object. +*/ + +void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state) +{ + DBUG_ENTER("ac_trie_init"); + DBUG_ASSERT(trie && state); + state->trie= trie; + state->node= &trie->root; + DBUG_VOID_RETURN; +} diff --git a/mysys/typelib.c b/mysys/typelib.c index 4d5f9cc8eba..8a839e87e59 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. +/* + Copyright (c) 2000-2004, 2006, 2007 MySQL AB, 2009 Sun Microsystems, Inc. Use is subject to license terms. This program is free software; you can redistribute it and/or modify @@ -12,7 +13,8 @@ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ /* Functions to handle typelib */ @@ -21,6 +23,30 @@ #include <m_ctype.h> +static const char field_separator=','; + +int find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) +{ + int res; + const char **ptr; + + if ((res= find_type((char *) x, typelib, 2)) <= 0) + { + ptr= typelib->type_names; + if (!*x) + fprintf(stderr, "No option given to %s\n", option); + else + fprintf(stderr, "Unknown option to %s: %s\n", option, x); + fprintf(stderr, "Alternatives are: '%s'", *ptr); + while (*++ptr) + fprintf(stderr, ",'%s'", *ptr); + fprintf(stderr, "\n"); + exit(1); + } + return res; +} + + /* Search after a string in a list of strings. Endspace in x is not compared. @@ -32,6 +58,7 @@ If & 1 accept only whole names If & 2 don't expand if half field If & 4 allow #number# as type + If & 8 use ',' as string terminator NOTES If part, uniq field is found and full_name == 0 then x is expanded @@ -43,11 +70,12 @@ >0 Offset+1 in typelib for matched string */ -int find_type(my_string x, TYPELIB *typelib, uint full_name) + +int find_type(char *x, const TYPELIB *typelib, uint full_name) { int find,pos; int UNINIT_VAR(findpos); /* guarded by find */ - reg1 my_string i; + reg1 char * i; reg2 const char *j; DBUG_ENTER("find_type"); DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib)); @@ -61,16 +89,18 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name) for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) { for (i=x ; - *i && my_toupper(&my_charset_latin1,*i) == + *i && (!(full_name & 8) || *i != field_separator) && + my_toupper(&my_charset_latin1,*i) == my_toupper(&my_charset_latin1,*j) ; i++, j++) ; if (! *j) { while (*i == ' ') i++; /* skip_end_space */ - if (! *i) + if (! *i || ((full_name & 8) && *i == field_separator)) DBUG_RETURN(pos+1); } - if (! *i && (!*j || !(full_name & 1))) + if ((!*i && (!(full_name & 8) || *i != field_separator)) && + (!*j || !(full_name & 1))) { find++; findpos=pos; @@ -98,7 +128,7 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name) /* Get name of type nr 'nr' */ /* Warning first type is 1, 0 = empty field */ -void make_type(register my_string to, register uint nr, +void make_type(register char * to, register uint nr, register TYPELIB *typelib) { DBUG_ENTER("make_type"); @@ -122,6 +152,53 @@ const char *get_type(TYPELIB *typelib, uint nr) /* + Create an integer value to represent the supplied comma-seperated + string where each string in the TYPELIB denotes a bit position. + + SYNOPSIS + find_typeset() + x string to decompose + lib TYPELIB (struct of pointer to values + count) + err index (not char position) of string element which was not + found or 0 if there was no error + + RETURN + a integer representation of the supplied string +*/ + +my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) +{ + my_ulonglong result; + int find; + char *i; + DBUG_ENTER("find_set"); + DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) lib)); + + if (!lib->count) + { + DBUG_PRINT("exit",("no count")); + DBUG_RETURN(0); + } + result= 0; + *err= 0; + while (*x) + { + (*err)++; + i= x; + while (*x && *x != field_separator) + x++; + if (x[0] && x[1]) /* skip separator if found */ + x++; + if ((find= find_type(i, lib, 2 | 8) - 1) < 0) + DBUG_RETURN(0); + result|= (ULL(1) << find); + } + *err= 0; + DBUG_RETURN(result); +} /* find_set */ + + +/* Create a copy of a specified TYPELIB structure. SYNOPSIS |