summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rwxr-xr-xmysys/CMakeLists.txt22
-rw-r--r--mysys/Makefile.am45
-rw-r--r--mysys/array.c192
-rw-r--r--mysys/base64.c79
-rw-r--r--mysys/charset-def.c5
-rw-r--r--mysys/charset.c267
-rw-r--r--mysys/checksum.c9
-rw-r--r--mysys/default.c145
-rw-r--r--mysys/default_modify.c63
-rw-r--r--mysys/errors.c19
-rw-r--r--mysys/hash.c204
-rw-r--r--mysys/list.c6
-rwxr-xr-xmysys/make-ccc2
-rw-r--r--mysys/mf_cache.c2
-rw-r--r--mysys/mf_dirname.c33
-rw-r--r--mysys/mf_fn_ext.c11
-rw-r--r--mysys/mf_format.c48
-rw-r--r--mysys/mf_getdate.c10
-rw-r--r--mysys/mf_iocache.c273
-rw-r--r--mysys/mf_iocache2.c206
-rw-r--r--mysys/mf_keycache.c90
-rw-r--r--mysys/mf_keycaches.c44
-rw-r--r--mysys/mf_loadpath.c21
-rw-r--r--mysys/mf_pack.c225
-rw-r--r--mysys/mf_path.c16
-rw-r--r--mysys/mf_radix.c4
-rw-r--r--mysys/mf_same.c5
-rw-r--r--mysys/mf_sort.c8
-rw-r--r--mysys/mf_soundex.c4
-rw-r--r--mysys/mf_strip.c45
-rw-r--r--mysys/mf_tempdir.c39
-rw-r--r--mysys/mf_tempfile.c1
-rw-r--r--mysys/mf_unixpath.c2
-rw-r--r--mysys/mf_wfile.c20
-rw-r--r--mysys/mulalloc.c6
-rw-r--r--mysys/my_access.c106
-rw-r--r--mysys/my_alloc.c88
-rw-r--r--mysys/my_append.c18
-rw-r--r--mysys/my_bit.c74
-rw-r--r--mysys/my_bitmap.c732
-rw-r--r--mysys/my_chsize.c8
-rw-r--r--mysys/my_clock.c5
-rw-r--r--mysys/my_compare.c9
-rw-r--r--mysys/my_compress.c205
-rw-r--r--mysys/my_conio.c17
-rw-r--r--mysys/my_copy.c38
-rw-r--r--mysys/my_create.c26
-rw-r--r--mysys/my_delete.c14
-rw-r--r--mysys/my_div.c2
-rw-r--r--mysys/my_dup.c3
-rw-r--r--mysys/my_error.c47
-rw-r--r--mysys/my_file.c38
-rw-r--r--mysys/my_fopen.c142
-rw-r--r--mysys/my_fstream.c96
-rw-r--r--mysys/my_gethwaddr.c39
-rw-r--r--mysys/my_getncpus.c42
-rw-r--r--mysys/my_getopt.c388
-rw-r--r--mysys/my_getsystime.c207
-rw-r--r--mysys/my_getwd.c100
-rw-r--r--mysys/my_handler_errors.h83
-rw-r--r--mysys/my_init.c235
-rw-r--r--mysys/my_largepage.c29
-rw-r--r--mysys/my_lib.c139
-rw-r--r--mysys/my_lock.c10
-rw-r--r--mysys/my_lockmem.c18
-rw-r--r--mysys/my_lread.c54
-rw-r--r--mysys/my_lwrite.c47
-rw-r--r--mysys/my_malloc.c52
-rw-r--r--mysys/my_memmem.c3
-rw-r--r--mysys/my_mkdir.c2
-rw-r--r--mysys/my_mmap.c5
-rw-r--r--mysys/my_net.c17
-rw-r--r--mysys/my_new.cc6
-rw-r--r--mysys/my_once.c28
-rw-r--r--mysys/my_open.c97
-rw-r--r--mysys/my_pread.c112
-rw-r--r--mysys/my_pthread.c11
-rw-r--r--mysys/my_quick.c18
-rw-r--r--mysys/my_read.c25
-rw-r--r--mysys/my_realloc.c21
-rw-r--r--mysys/my_redel.c36
-rw-r--r--mysys/my_rename.c18
-rw-r--r--mysys/my_seek.c21
-rw-r--r--mysys/my_sleep.c2
-rw-r--r--mysys/my_static.c35
-rw-r--r--mysys/my_static.h6
-rw-r--r--mysys/my_symlink.c29
-rw-r--r--mysys/my_symlink2.c4
-rw-r--r--mysys/my_sync.c108
-rw-r--r--mysys/my_thr_init.c72
-rw-r--r--mysys/my_vle.c109
-rw-r--r--mysys/my_wincond.c9
-rw-r--r--mysys/my_windac.c8
-rw-r--r--mysys/my_winthread.c39
-rw-r--r--mysys/my_write.c32
-rw-r--r--mysys/mysys_priv.h4
-rw-r--r--mysys/ptr_cmp.c28
-rw-r--r--mysys/queues.c507
-rw-r--r--mysys/raid.cc798
-rw-r--r--mysys/safemalloc.c170
-rw-r--r--mysys/stacktrace.c977
-rw-r--r--mysys/string.c54
-rw-r--r--mysys/test_charset.c2
-rw-r--r--mysys/test_dir.c1
-rw-r--r--mysys/testhash.c8
-rw-r--r--mysys/thr_alarm.c256
-rw-r--r--mysys/thr_lock.c332
-rw-r--r--mysys/thr_mutex.c119
-rw-r--r--mysys/tree.c8
-rw-r--r--mysys/trie.c236
-rw-r--r--mysys/typelib.c93
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)&copy))
- 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*) &copy))
+ 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