summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/CMakeLists.txt9
-rw-r--r--mysys/Makefile.am170
-rw-r--r--mysys/charset.c20
-rw-r--r--mysys/default.c130
-rw-r--r--mysys/errors.c4
-rw-r--r--mysys/lf_alloc-pin.c48
-rw-r--r--mysys/mf_brkhant.c72
-rw-r--r--mysys/mf_format.c2
-rw-r--r--mysys/mf_iocache.c87
-rw-r--r--mysys/mf_iocache2.c5
-rw-r--r--mysys/mf_keycache.c99
-rw-r--r--mysys/mf_pack.c5
-rw-r--r--mysys/my_bitmap.c20
-rw-r--r--mysys/my_compare.c (renamed from mysys/my_handler.c)73
-rw-r--r--mysys/my_fopen.c136
-rw-r--r--mysys/my_fstream.c3
-rw-r--r--mysys/my_gethostbyname.c114
-rw-r--r--mysys/my_gethwaddr.c32
-rw-r--r--mysys/my_getopt.c58
-rw-r--r--mysys/my_handler_errors.h5
-rw-r--r--mysys/my_init.c271
-rw-r--r--mysys/my_lib.c15
-rw-r--r--mysys/my_open.c6
-rw-r--r--mysys/my_port.c40
-rw-r--r--mysys/my_pread.c8
-rw-r--r--mysys/my_pthread.c2
-rw-r--r--mysys/my_rdtsc.c10
-rw-r--r--mysys/my_read.c4
-rw-r--r--mysys/my_seek.c3
-rw-r--r--mysys/my_static.c4
-rw-r--r--mysys/my_symlink.c20
-rw-r--r--mysys/my_sync.c44
-rw-r--r--mysys/my_thr_init.c103
-rw-r--r--mysys/my_wincond.c232
-rw-r--r--mysys/my_winfile.c21
-rw-r--r--mysys/my_winthread.c15
-rw-r--r--mysys/my_write.c3
-rw-r--r--mysys/mysys_priv.h12
-rw-r--r--mysys/ptr_cmp.c19
-rw-r--r--mysys/stacktrace.c114
-rw-r--r--mysys/thr_alarm.c15
-rw-r--r--mysys/thr_lock.c13
-rw-r--r--mysys/thr_mutex.c7
-rw-r--r--mysys/thr_rwlock.c299
-rw-r--r--mysys/typelib.c49
45 files changed, 1267 insertions, 1154 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index c3c4d6b5246..e32a722ff05 100644
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -23,8 +23,8 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c
mf_tempfile.c mf_unixpath.c mf_wcomp.c mulalloc.c my_access.c
my_aes.c my_alloc.c my_bit.c my_bitmap.c my_chsize.c
my_compress.c my_copy.c my_create.c my_delete.c
- my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_gethostbyname.c
- my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_handler.c my_init.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_malloc.c my_mess.c
my_mkdir.c my_mmap.c my_once.c my_open.c my_pread.c my_pthread.c
my_quick.c my_read.c my_redel.c my_rename.c my_seek.c my_sleep.c
@@ -65,11 +65,6 @@ IF(HAVE_MLOCK)
SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_lockmem.c)
ENDIF()
-IF(UNIX)
- # some workarounds
- SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_port.c)
-ENDIF()
-
ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES})
TARGET_LINK_LIBRARIES(mysys dbug strings ${ZLIB_LIBRARY}
${LIBNSL} ${LIBM} ${LIBRT})
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
deleted file mode 100644
index da5a2fa0b3b..00000000000
--- a/mysys/Makefile.am
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright (C) 2000-2006 MySQL AB, 2009 Sun Microsystems, Inc.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# 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
-
-MYSQLDATAdir = $(localstatedir)
-MYSQLSHAREdir = $(pkgdatadir)
-MYSQLBASEdir= $(prefix)
-INCLUDES = @ZLIB_INCLUDES@ @RDTSC_SPARC_ASSEMBLY@ \
- -I$(top_builddir)/include \
- -I$(top_srcdir)/include -I$(srcdir)
-pkglib_LIBRARIES = libmysys.a
-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 \
- my_safehash.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_seek.c my_read.c \
- my_pread.c my_write.c my_getpagesize.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_once.c mulalloc.c \
- my_alloc.c my_new.cc my_atomic.c lf_hash.c \
- lf_dynarray.c lf_alloc-pin.c \
- my_fopen.c my_fstream.c my_getsystime.c \
- my_error.c errors.c my_div.c my_mess.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_arr_appstr.c \
- mf_wcomp.c my_gethwaddr.c \
- mf_qsort.c mf_qsort2.c mf_sort.c \
- ptr_cmp.c mf_radix.c queues.c my_getncpus.c \
- tree.c list.c hash.c array.c string.c typelib.c \
- my_copy.c my_lib.c \
- my_delete.c my_rename.c my_redel.c \
- my_chsize.c my_quick.c my_lockmem.c my_static.c \
- my_sync.c my_getopt.c my_mkdir.c \
- default.c my_compress.c checksum.c \
- my_port.c my_sleep.c \
- charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
- my_safehash.c my_rnd.c my_uuid.c my_chmod.c wqueue.c \
- my_gethostbyname.c rijndael.c my_aes.c sha1.c \
- my_handler.c my_largepage.c \
- my_memmem.c stacktrace.c \
- my_windac.c my_access.c base64.c my_libwrap.c \
- my_rdtsc.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 mf_keycaches.c
-endif
-
-EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
- thr_mutex.c thr_rwlock.c waiting_threads.c \
- CMakeLists.txt mf_soundex.c \
- my_conio.c my_wincond.c my_winthread.c my_winerr.c \
- my_winfile.c \
- my_timer_cycles.il
-libmysys_a_LIBADD = @THREAD_LOBJECTS@
-# test_dir_DEPENDENCIES= $(LIBRARIES)
-# testhash_DEPENDENCIES= $(LIBRARIES)
-# test_charset_DEPENDENCIES= $(LIBRARIES)
-# charset2html_DEPENDENCIES= $(LIBRARIES)
-DEFS = -DDEFAULT_BASEDIR='"$(prefix)"' \
- -DMYSQL_DATADIR='"$(MYSQLDATAdir)"' \
- -DDEFAULT_CHARSET_HOME='"$(MYSQLBASEdir)"' \
- -DSHAREDIR'="$(MYSQLSHAREdir)"' \
- -DDEFAULT_HOME_ENV=MYSQL_HOME \
- -DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
- -DDEFAULT_SYSCONFDIR='"$(sysconfdir)"' \
- @DEFS@
-
-libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
-
-# I hope this always does the right thing. Otherwise this is only test programs
-FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@
-
-#CLEANFILES = test_bitmap$(EXEEXT) test_priority_queue$(EXEEXT) \
-# test_thr_alarm$(EXEEXT) test_thr_lock$(EXEEXT) \
-# test_vsnprintf$(EXEEXT) test_io_cache$(EXEEXT) \
-# test_dir$(EXEEXT) test_charset$(EXEEXT) \
-# testhash$(EXEEXT) test_gethwaddr$(EXEEXT) \
-# test_base64$(EXEEXT) test_thr_mutex$(EXEEXT)
-
-#
-# The CP .. RM stuff is to avoid problems with some compilers (like alpha ccc)
-# 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)
- $(RM) -f ./test_thr_alarm.c
-
-test_thr_lock$(EXEEXT): thr_lock.c $(LIBRARIES)
- $(CP) $(srcdir)/thr_lock.c test_thr_lock.c
- $(LINK) $(FLAGS) -DMAIN ./test_thr_lock.c $(LDADD) $(LIBS)
- $(RM) -f ./test_thr_lock.c
-
-test_vsnprintf$(EXEEXT): my_vsnprintf.c $(LIBRARIES)
- $(CP) $(srcdir)/my_vsnprintf.c test_vsnprintf.c
- $(LINK) $(FLAGS) -DMAIN ./test_vsnprintf.c $(LDADD) $(LIBS)
- $(RM) -f test_vsnprintf.c
-
-test_io_cache$(EXEEXT): mf_iocache.c $(LIBRARIES)
- $(CP) $(srcdir)/mf_iocache.c test_io_cache.c
- $(LINK) $(FLAGS) -DMAIN ./test_io_cache.c $(LDADD) $(LIBS)
- $(RM) -f test_io_cache.c
-
-test_dir$(EXEEXT): test_dir.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_dir.c $(LDADD) $(LIBS)
-
-test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
-
-testhash$(EXEEXT): testhash.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
-
-test_gethwaddr$(EXEEXT): my_gethwaddr.c $(LIBRARIES)
- $(CP) $(srcdir)/my_gethwaddr.c ./test_gethwaddr.c
- $(LINK) $(FLAGS) -DMAIN ./test_gethwaddr.c $(LDADD) $(LIBS)
- $(RM) -f ./test_gethwaddr.c
-
-test_base64$(EXEEXT): base64.c $(LIBRARIES)
- $(CP) $(srcdir)/base64.c ./test_base64.c
- $(LINK) $(FLAGS) -DMAIN ./test_base64.c $(LDADD) $(LIBS)
- $(RM) -f ./test_base64.c
-
-test_thr_mutex$(EXEEXT): test_thr_mutex.c $(LIBRARIES)
- $(LINK) $(FLAGS) $(srcdir)/test_thr_mutex.c $(LDADD) $(LIBS)
-
-if HAVE_DTRACE_DASH_G
-libmysys_a_LIBADD += probes_mysql.o
-libmysys_a_DEPENDENCIES += probes_mysql.o dtrace_files dtrace_providers
-CLEANFILES = probes_mysql.o dtrace_files dtrace_providers
-DTRACEFILES = mf_keycache.o
-DTRACEPROVIDER = probes_mysql.d
-CLEANFILES += $(DTRACEPROVIDER) dtrace_sources
-
-dtrace_files:
- echo $(DTRACEFILES) > $@
-dtrace_providers: probes_mysql.d
- echo $(DTRACEPROVIDER) > $@
-probes_mysql.d:
- -$(RM) -f probes_mysql.d
- $(CP) $(top_srcdir)/include/probes_mysql.d.base probes_mysql.d
- echo timestamp > dtrace_sources
-
-probes_mysql.o: $(DTRACEPROVIDER) $(DTRACEFILES)
- $(DTRACE) $(DTRACEFLAGS) -G -s $(DTRACEPROVIDER) $(DTRACEFILES) -o $@
-endif
diff --git a/mysys/charset.c b/mysys/charset.c
index 7f414fbad97..f859ceae394 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -415,6 +415,7 @@ CHARSET_INFO *default_charset_info = &my_charset_latin1;
void add_compiled_collation(struct charset_info_st *cs)
{
+ DBUG_ASSERT(cs->number < array_elements(all_charsets));
all_charsets[cs->number]= cs;
cs->state|= MY_CS_AVAILABLE;
}
@@ -526,14 +527,17 @@ uint get_charset_number(const char *charset_name, uint cs_flags)
const char *get_charset_name(uint charset_number)
{
- CHARSET_INFO *cs;
my_pthread_once(&charsets_initialized, init_available_charsets);
- cs=all_charsets[charset_number];
- if (cs && (cs->number == charset_number) && cs->name )
- return (char*) cs->name;
+ if (charset_number < array_elements(all_charsets))
+ {
+ CHARSET_INFO *cs= all_charsets[charset_number];
+
+ if (cs && (cs->number == charset_number) && cs->name)
+ return (char*) cs->name;
+ }
- return (char*) "?"; /* this mimics find_type() */
+ return "?"; /* this mimics find_type() */
}
@@ -542,6 +546,8 @@ static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags)
char buf[FN_REFLEN];
struct charset_info_st *cs;
+ DBUG_ASSERT(cs_number < array_elements(all_charsets));
+
if ((cs= (struct charset_info_st*) all_charsets[cs_number]))
{
if (cs->state & MY_CS_READY) /* if CS is already initialized */
@@ -586,8 +592,8 @@ CHARSET_INFO *get_charset(uint cs_number, myf flags)
return default_charset_info;
my_pthread_once(&charsets_initialized, init_available_charsets);
-
- if (!cs_number || cs_number > array_elements(all_charsets))
+
+ if (cs_number >= array_elements(all_charsets))
return NULL;
cs=get_internal_charset(cs_number, flags);
diff --git a/mysys/default.c b/mysys/default.c
index 0e0883e1fcf..fe070f42748 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* 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
@@ -61,12 +61,31 @@
check the pointer, use "----args-separator----" here to ease debug
if someone misused it.
+ The args seprator will only be added when
+ my_getopt_use_args_seprator is set to TRUE before calling
+ load_defaults();
+
See BUG#25192
*/
-const char *args_separator= "----args-separator----";
+static const char *args_separator= "----args-separator----";
+inline static void set_args_separator(char** arg)
+{
+ DBUG_ASSERT(my_getopt_use_args_separator);
+ *arg= (char*)args_separator;
+}
+my_bool my_getopt_use_args_separator= FALSE;
+my_bool my_getopt_is_args_separator(const char* arg)
+{
+ return (arg == args_separator);
+}
const char *my_defaults_file=0;
const char *my_defaults_group_suffix=0;
-char *my_defaults_extra_file=0;
+const char *my_defaults_extra_file=0;
+
+static char my_defaults_file_buffer[FN_REFLEN];
+static char my_defaults_extra_file_buffer[FN_REFLEN];
+
+static my_bool defaults_already_read= FALSE;
/* Which directories are searched for options (and in which order) */
@@ -121,7 +140,7 @@ static int search_default_file_with_ext(Process_option_func func,
- Unix: /etc/
- Unix: /etc/mysql/
- Unix: --sysconfdir=<path> (compile-time option)
- - ALL: getenv(DEFAULT_HOME_ENV)
+ - ALL: getenv("MYSQL_HOME")
- ALL: --defaults-extra-file=<path> (run-time option)
- Unix: ~/
@@ -140,6 +159,33 @@ static char *remove_end_comment(char *ptr);
/*
+ Expand a file name so that the current working directory is added if
+ the name is relative.
+
+ RETURNS
+ 0 All OK
+ 2 Out of memory or path to long
+ 3 Not able to get working directory
+ */
+
+static int
+fn_expand(const char *filename, char *result_buf)
+{
+ char dir[FN_REFLEN];
+ const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH;
+ DBUG_ENTER("fn_expand");
+ DBUG_PRINT("enter", ("filename: %s, result_buf: 0x%lx",
+ filename, (unsigned long) result_buf));
+ if (my_getwd(dir, sizeof(dir), MYF(0)))
+ DBUG_RETURN(3);
+ DBUG_PRINT("debug", ("dir: %s", dir));
+ if (fn_format(result_buf, filename, dir, "", flags) == NULL)
+ DBUG_RETURN(2);
+ DBUG_PRINT("return", ("result: %s", result_buf));
+ DBUG_RETURN(0);
+}
+
+/*
Process config files in default directories.
SYNOPSIS
@@ -167,6 +213,7 @@ static char *remove_end_comment(char *ptr);
0 ok
1 given cinf_file doesn't exist
2 out of memory
+ 3 Can't get current working directory
The global variable 'my_defaults_group_suffix' is updated with value for
--defaults_group_suffix
@@ -189,11 +236,23 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
if (! my_defaults_group_suffix)
my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
- if (forced_extra_defaults)
- my_defaults_extra_file= (char *) forced_extra_defaults;
-
- if (forced_default_file)
- my_defaults_file= forced_default_file;
+ if (forced_extra_defaults && !defaults_already_read)
+ {
+ int error= fn_expand(forced_extra_defaults, my_defaults_extra_file_buffer);
+ if (error)
+ DBUG_RETURN(error);
+ my_defaults_extra_file= my_defaults_extra_file_buffer;
+ }
+
+ if (forced_default_file && !defaults_already_read)
+ {
+ int error= fn_expand(forced_default_file, my_defaults_file_buffer);
+ if (error)
+ DBUG_RETURN(error);
+ my_defaults_file= my_defaults_file_buffer;
+ }
+
+ defaults_already_read= TRUE;
/*
We can only handle 'defaults-group-suffix' if we are called from
@@ -236,15 +295,15 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
group->type_names[group->count]= 0;
}
- if (forced_default_file)
+ if (my_defaults_file)
{
if ((error= search_default_file_with_ext(func, func_ctx, "", "",
- forced_default_file, 0)) < 0)
+ my_defaults_file, 0)) < 0)
goto err;
if (error > 0)
{
fprintf(stderr, "Could not open required defaults file: %s\n",
- forced_default_file);
+ my_defaults_file);
goto err;
}
}
@@ -317,7 +376,7 @@ static int handle_default_option(void *in_ctx, const char *group_name,
if (!option)
return 0;
- if (find_type((char *)group_name, ctx->group, 3))
+ if (find_type((char *)group_name, ctx->group, FIND_TYPE_NO_PREFIX))
{
if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1)))
return 1;
@@ -458,6 +517,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
char *ptr,**res;
struct handle_option_ctx ctx;
const char **dirs;
+ uint args_sep= my_getopt_use_args_separator ? 1 : 0;
DBUG_ENTER("load_defaults");
init_alloc_root(&alloc,512,0);
@@ -470,17 +530,28 @@ int my_load_defaults(const char *conf_file, const char **groups,
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
{
/* remove the --no-defaults argument and return only the other arguments */
- uint i;
+ uint i, j;
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
(*argc + 1)*sizeof(char*))))
goto err;
res= (char**) (ptr+sizeof(alloc));
res[0]= **argv; /* Copy program name */
- /* set arguments separator */
- res[1]= (char *)args_separator;
- for (i=2 ; i < (uint) *argc ; i++)
- res[i]=argv[0][i];
- res[i]=0; /* End pointer */
+ j= 1; /* Start from 1 for the reset result args */
+ if (my_getopt_use_args_separator)
+ {
+ /* set arguments separator */
+ set_args_separator(&res[1]);
+ j++;
+ }
+ for (i=2 ; i < (uint) *argc ; i++, j++)
+ res[j]=argv[0][i];
+ res[j]=0; /* End pointer */
+ /*
+ Update the argc, if have not added args separator, then we have
+ to decrease argc because we have removed the "--no-defaults".
+ */
+ if (!my_getopt_use_args_separator)
+ (*argc)--;
*argv=res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
if (default_directories)
@@ -514,7 +585,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
or a forced default file
*/
if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+
- (args.elements + *argc + 1 + 1) *sizeof(char*))))
+ (args.elements + *argc + 1 + args_sep) *sizeof(char*))))
goto err;
res= (char**) (ptr+sizeof(alloc));
@@ -535,16 +606,19 @@ int my_load_defaults(const char *conf_file, const char **groups,
--*argc; ++*argv; /* skip argument */
}
- /* set arguments separator for arguments from config file and
- command line */
- res[args.elements+1]= (char *)args_separator;
+ if (my_getopt_use_args_separator)
+ {
+ /* set arguments separator for arguments from config file and
+ command line */
+ set_args_separator(&res[args.elements+1]);
+ }
if (*argc)
- memcpy((uchar*) (res+1+args.elements+1), (char*) ((*argv)+1),
+ memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1),
(*argc-1)*sizeof(char*));
- res[args.elements+ *argc+1]=0; /* last null */
+ res[args.elements+ *argc+args_sep]=0; /* last null */
- (*argc)+=args.elements+1;
+ (*argc)+=args.elements+args_sep;
*argv= (char**) res;
*(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */
delete_dynamic(&args);
@@ -554,7 +628,7 @@ int my_load_defaults(const char *conf_file, const char **groups,
printf("%s would have been started with the following arguments:\n",
**argv);
for (i=1 ; i < *argc ; i++)
- if ((*argv)[i] != args_separator) /* skip arguments separator */
+ if (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */
printf("%s ", (*argv)[i]);
puts("");
exit(0);
@@ -1158,7 +1232,7 @@ static const char **init_default_directories(MEM_ROOT *alloc)
#endif
- if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ if ((env= getenv("MYSQL_HOME")))
errors += add_directory(alloc, env, dirs);
/* Placeholder for --defaults-extra-file=<path> */
diff --git a/mysys/errors.c b/mysys/errors.c
index 5c8afff6395..2a9b3e770d2 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -52,8 +52,8 @@ const char *globerrs[GLOBERRS]=
"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)"
"Can't change mode for file '%s' to 0x%lx (Error: %d)",
- "Can't do seek on file '%s' (Errcode: %d)",
"Warning: Can't copy ownership for file '%s' (Error: %d)"
};
@@ -97,8 +97,8 @@ void init_glob_errs()
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)";
EE(EE_CANT_CHMOD) = "Can't change mode for file '%s' to 0x%lx (Error: %d)";
- EE(EE_CANT_SEEK) = "Can't do seek on file '%s' (Errcode: %d)";
EE(EE_CANT_COPY_OWNERSHIP)= "Warning: Can't copy ownership for file '%s' (Error: %d)";
}
#endif
diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c
index 3eec91236c5..ab88828d2f6 100644
--- a/mysys/lf_alloc-pin.c
+++ b/mysys/lf_alloc-pin.c
@@ -146,6 +146,7 @@ void lf_pinbox_destroy(LF_PINBOX *pinbox)
*/
LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox)
{
+ struct st_my_thread_var *var;
uint32 pins, next, top_ver;
LF_PINS *el;
/*
@@ -188,7 +189,12 @@ LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox)
el->link= pins;
el->purgatory_count= 0;
el->pinbox= pinbox;
- el->stack_ends_here= & my_thread_var->stack_ends_here;
+ var= my_thread_var;
+ /*
+ Threads that do not call my_thread_init() should still be
+ able to use the LF_HASH.
+ */
+ el->stack_ends_here= (var ? & var->stack_ends_here : NULL);
return el;
}
@@ -327,34 +333,36 @@ static int match_pins(LF_PINS *el, void *addr)
*/
static void _lf_pinbox_real_free(LF_PINS *pins)
{
- int npins, alloca_size;
- void *list, **addr;
+ int npins;
+ void *list;
+ void **addr= NULL;
void *first= NULL, *last= NULL;
LF_PINBOX *pinbox= pins->pinbox;
npins= pinbox->pins_in_array+1;
#ifdef HAVE_ALLOCA
- alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins;
- /* create a sorted list of pinned addresses, to speed up searches */
- if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size)
+ if (pins->stack_ends_here != NULL)
{
- struct st_harvester hv;
- addr= (void **) alloca(alloca_size);
- hv.granary= addr;
- hv.npins= npins;
- /* scan the dynarray and accumulate all pinned addresses */
- _lf_dynarray_iterate(&pinbox->pinarray,
- (lf_dynarray_func)harvest_pins, &hv);
-
- npins= hv.granary-addr;
- /* and sort them */
- if (npins)
- qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp);
+ int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins;
+ /* create a sorted list of pinned addresses, to speed up searches */
+ if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size)
+ {
+ struct st_harvester hv;
+ addr= (void **) alloca(alloca_size);
+ hv.granary= addr;
+ hv.npins= npins;
+ /* scan the dynarray and accumulate all pinned addresses */
+ _lf_dynarray_iterate(&pinbox->pinarray,
+ (lf_dynarray_func)harvest_pins, &hv);
+
+ npins= hv.granary-addr;
+ /* and sort them */
+ if (npins)
+ qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp);
+ }
}
- else
#endif
- addr= 0;
list= pins->purgatory;
pins->purgatory= 0;
diff --git a/mysys/mf_brkhant.c b/mysys/mf_brkhant.c
deleted file mode 100644
index 3573b9973b2..00000000000
--- a/mysys/mf_brkhant.c
+++ /dev/null
@@ -1,72 +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 */
-
-/* Dont let the user break when you are doing something important */
-/* Remembers if it got 'SIGINT' and executes it on allow_break */
-/* A static buffer is used; don't call dont_break() twice in a row */
-
-#include "mysys_priv.h"
-#include "my_static.h"
-
- /* Set variable that we can't break */
-
-#if !defined(THREAD)
-void dont_break(void)
-{
- my_dont_interrupt=1;
- return;
-} /* dont_break */
-
-void allow_break(void)
-{
- {
- reg1 int index;
-
- my_dont_interrupt=0;
- if (_my_signals)
- {
- if (_my_signals > MAX_SIGNALS)
- _my_signals=MAX_SIGNALS;
- for (index=0 ; index < _my_signals ; index++)
- {
- if (_my_sig_remember[index].func) /* Safequard */
- {
- (*_my_sig_remember[index].func)(_my_sig_remember[index].number);
- _my_sig_remember[index].func=0;
- }
- }
- _my_signals=0;
- }
- }
-} /* dont_break */
-#endif
-
- /* Set old status */
-
-#if !defined(THREAD)
-void my_remember_signal(int signal_number, sig_handler (*func) (int))
-{
-#ifndef __WIN__
- reg1 int index;
-
- index=_my_signals++; /* Nobody can break a ++ ? */
- if (index < MAX_SIGNALS)
- {
- _my_sig_remember[index].number=signal_number;
- _my_sig_remember[index].func=func;
- }
-#endif /* __WIN__ */
-} /* my_remember_signal */
-#endif /* THREAD */
diff --git a/mysys/mf_format.c b/mysys/mf_format.c
index 6afa2938fa3..74f114a966f 100644
--- a/mysys/mf_format.c
+++ b/mysys/mf_format.c
@@ -31,6 +31,8 @@ char * fn_format(char * to, const char *name, const char *dir,
reg1 size_t length;
size_t dev_length;
DBUG_ENTER("fn_format");
+ DBUG_ASSERT(name != NULL);
+ DBUG_ASSERT(extension != NULL);
DBUG_PRINT("enter",("name: %s dir: %s extension: %s flag: %d",
name,dir,extension,flag));
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index aa7e4be03eb..4a548fe330f 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -55,15 +55,10 @@ static void my_aiowait(my_aio_result *result);
#endif
#include <errno.h>
-#ifdef THREAD
#define lock_append_buffer(info) \
mysql_mutex_lock(&(info)->append_buffer_lock)
#define unlock_append_buffer(info) \
mysql_mutex_unlock(&(info)->append_buffer_lock)
-#else
-#define lock_append_buffer(info)
-#define unlock_append_buffer(info)
-#endif
#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1))
#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1))
@@ -116,11 +111,7 @@ init_functions(IO_CACHE* info)
info->write_function = 0; /* Force a core if used */
break;
default:
- info->read_function =
-#ifdef THREAD
- info->share ? _my_b_read_r :
-#endif
- _my_b_read;
+ info->read_function = info->share ? _my_b_read_r : _my_b_read;
info->write_function = _my_b_write;
}
@@ -173,7 +164,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
if (file >= 0)
{
- pos= my_tell(file, MYF(0));
+ pos= mysql_file_tell(file, MYF(0));
if ((pos == (my_off_t) -1) && (my_errno == ESPIPE))
{
/*
@@ -193,9 +184,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
}
info->disk_writes= 0;
-#ifdef THREAD
info->share=0;
-#endif
if (!cachesize && !(cachesize= my_default_record_cache_size))
DBUG_RETURN(1); /* No cache requested */
@@ -205,7 +194,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
{
/* Calculate end of file to avoid allocating oversized buffers */
- end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
+ end_of_file= mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0));
/* Need to reset seek_not_done now that we just did a seek. */
info->seek_not_done= end_of_file == seek_offset ? 0 : 1;
if (end_of_file < seek_offset)
@@ -263,12 +252,10 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize,
{
info->append_read_pos = info->write_pos = info->write_buffer;
info->write_end = info->write_buffer + info->buffer_length;
-#ifdef THREAD
mysql_mutex_init(key_IO_CACHE_append_buffer_lock,
&info->append_buffer_lock, MY_MUTEX_INIT_FAST);
-#endif
}
-#if defined(SAFE_MUTEX) && defined(THREAD)
+#if defined(SAFE_MUTEX)
else
{
/* Clear mutex so that safe_mutex will notice that it's not initialized */
@@ -485,7 +472,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
*/
if (info->seek_not_done)
{
- if ((my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
+ if ((mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0))
!= MY_FILEPOS_ERROR))
{
/* No error, reset seek_not_done flag. */
@@ -529,7 +516,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
end aligned with a block.
*/
length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
- if ((read_length= my_read(info->file,Buffer, length, info->myflags))
+ if ((read_length= mysql_file_read(info->file,Buffer, length, info->myflags))
!= length)
{
/*
@@ -572,7 +559,7 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
length=0; /* Didn't read any chars */
}
- else if ((length= my_read(info->file,info->buffer, max_length,
+ else if ((length= mysql_file_read(info->file,info->buffer, max_length,
info->myflags)) < Count ||
length == (size_t) -1)
{
@@ -601,7 +588,6 @@ int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
-#ifdef THREAD
/*
Prepare IO_CACHE for shared use.
@@ -1056,7 +1042,7 @@ int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count)
*/
if (cache->seek_not_done)
{
- if (my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0))
+ if (mysql_file_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0))
== MY_FILEPOS_ERROR)
{
cache->error= -1;
@@ -1064,7 +1050,7 @@ int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count)
DBUG_RETURN(1);
}
}
- len= my_read(cache->file, cache->buffer, length, cache->myflags);
+ len= mysql_file_read(cache->file, cache->buffer, length, cache->myflags);
}
DBUG_PRINT("io_cache_share", ("read %lu bytes", (ulong) len));
@@ -1162,7 +1148,6 @@ static void copy_to_read_buffer(IO_CACHE *write_cache,
write_length-= copy_length;
}
}
-#endif /*THREAD*/
/*
@@ -1203,7 +1188,7 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
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 (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)
{
info->error= -1;
unlock_append_buffer(info);
@@ -1220,8 +1205,8 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
size_t read_length;
length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
- if ((read_length= my_read(info->file,Buffer, length,
- info->myflags)) == (size_t) -1)
+ if ((read_length= mysql_file_read(info->file,Buffer, length,
+ info->myflags)) == (size_t) -1)
{
info->error= -1;
unlock_append_buffer(info);
@@ -1254,7 +1239,7 @@ int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
else
{
- length= my_read(info->file,info->buffer, max_length, info->myflags);
+ length= mysql_file_read(info->file,info->buffer, max_length, info->myflags);
if (length == (size_t) -1)
{
info->error= -1;
@@ -1431,7 +1416,7 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
return 1;
}
- if (my_seek(info->file,next_pos_in_file,MY_SEEK_SET,MYF(0))
+ if (mysql_file_seek(info->file, next_pos_in_file, MY_SEEK_SET, MYF(0))
== MY_FILEPOS_ERROR)
{
info->error= -1;
@@ -1441,8 +1426,8 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
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)) == (size_t) -1)
+ if ((read_length=mysql_file_read(info->file,info->request_pos,
+ 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);
@@ -1462,7 +1447,7 @@ int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count)
}
else
{ /* Big block, don't cache it */
- if ((read_length= my_read(info->file,Buffer, Count,info->myflags))
+ if ((read_length= mysql_file_read(info->file, Buffer, Count,info->myflags))
!= Count)
{
info->error= read_length == (size_t) -1 ? -1 : read_length+left_length;
@@ -1569,17 +1554,16 @@ int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count)
"seek_not_done" to indicate this to other functions operating
on the IO_CACHE.
*/
- if (my_seek(info->file,info->pos_in_file,MY_SEEK_SET,MYF(0)))
+ if (mysql_file_seek(info->file, info->pos_in_file, MY_SEEK_SET, MYF(0)))
{
info->error= -1;
return (1);
}
info->seek_not_done=0;
}
- if (my_write(info->file, Buffer, length, info->myflags | MY_NABP))
+ if (mysql_file_write(info->file, Buffer, length, info->myflags | MY_NABP))
return info->error= -1;
-#ifdef THREAD
/*
In case of a shared I/O cache with a writer we normally do direct
write cache to read cache copy. Simulate this here by direct
@@ -1593,7 +1577,6 @@ int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count)
*/
if (info->share)
copy_to_read_buffer(info, Buffer, length);
-#endif
Count-=length;
Buffer+=length;
@@ -1615,13 +1598,11 @@ int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count)
{
size_t rest_length,length;
-#ifdef THREAD
/*
Assert that we cannot come here with a shared cache. If we do one
day, we might need to add a call to copy_to_read_buffer().
*/
DBUG_ASSERT(!info->share);
-#endif
lock_append_buffer(info);
rest_length= (size_t) (info->write_end - info->write_pos);
@@ -1639,7 +1620,7 @@ int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count)
if (Count >= IO_SIZE)
{ /* Fill first intern buffer */
length=Count & (size_t) ~(IO_SIZE-1);
- if (my_write(info->file,Buffer, length, info->myflags | MY_NABP))
+ if (mysql_file_write(info->file,Buffer, length, info->myflags | MY_NABP))
{
unlock_append_buffer(info);
return info->error= -1;
@@ -1683,23 +1664,21 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count,
size_t length;
int error=0;
-#ifdef THREAD
/*
Assert that we cannot come here with a shared cache. If we do one
day, we might need to add a call to copy_to_read_buffer().
*/
DBUG_ASSERT(!info->share);
-#endif
if (pos < info->pos_in_file)
{
/* Of no overlap, write everything without buffering */
if (pos + Count <= info->pos_in_file)
- return (int) my_pwrite(info->file, Buffer, Count, pos,
- info->myflags | MY_NABP);
+ return (int)mysql_file_pwrite(info->file, Buffer, Count, pos,
+ info->myflags | MY_NABP);
/* 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))
+ if (mysql_file_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP))
info->error= error= -1;
Buffer+=length;
pos+= length;
@@ -1735,16 +1714,10 @@ int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count,
/* Flush write cache */
-#ifdef THREAD
#define LOCK_APPEND_BUFFER if (need_append_buffer_lock) \
lock_append_buffer(info);
#define UNLOCK_APPEND_BUFFER if (need_append_buffer_lock) \
unlock_append_buffer(info);
-#else
-#define LOCK_APPEND_BUFFER
-#define UNLOCK_APPEND_BUFFER
-#endif
-
int my_b_flush_io_cache(IO_CACHE *info,
int need_append_buffer_lock __attribute__((unused)))
@@ -1755,10 +1728,8 @@ int my_b_flush_io_cache(IO_CACHE *info,
DBUG_ENTER("my_b_flush_io_cache");
DBUG_PRINT("enter", ("cache: 0x%lx", (long) info));
-#ifdef THREAD
if (!append_cache)
need_append_buffer_lock= 0;
-#endif
if (info->type == WRITE_CACHE || append_cache)
{
@@ -1771,7 +1742,6 @@ int my_b_flush_io_cache(IO_CACHE *info,
if ((length=(size_t) (info->write_pos - info->write_buffer)))
{
-#ifdef THREAD
/*
In case of a shared I/O cache with a writer we do direct write
cache to read cache copy. Do it before the write here so that
@@ -1780,7 +1750,6 @@ int my_b_flush_io_cache(IO_CACHE *info,
*/
if (info->share)
copy_to_read_buffer(info, info->write_buffer, length);
-#endif
pos_in_file=info->pos_in_file;
/*
@@ -1789,7 +1758,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
*/
if (!append_cache && info->seek_not_done)
{ /* File touched, do seek */
- if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) ==
+ if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) ==
MY_FILEPOS_ERROR)
{
UNLOCK_APPEND_BUFFER;
@@ -1803,7 +1772,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
info->write_end= (info->write_buffer+info->buffer_length-
((pos_in_file+length) & (IO_SIZE-1)));
- if (my_write(info->file,info->write_buffer,length,
+ if (mysql_file_write(info->file,info->write_buffer,length,
info->myflags | MY_NABP))
info->error= -1;
else
@@ -1815,7 +1784,7 @@ int my_b_flush_io_cache(IO_CACHE *info,
else
{
info->end_of_file+=(info->write_pos-info->append_read_pos);
- DBUG_ASSERT(info->end_of_file == my_tell(info->file,MYF(0)));
+ DBUG_ASSERT(info->end_of_file == mysql_file_tell(info->file, MYF(0)));
}
info->append_read_pos=info->write_pos=info->write_buffer;
@@ -1859,13 +1828,11 @@ int end_io_cache(IO_CACHE *info)
DBUG_ENTER("end_io_cache");
DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info));
-#ifdef THREAD
/*
Every thread must call remove_io_thread(). The last one destroys
the share elements.
*/
DBUG_ASSERT(!info->share || !info->share->total_threads);
-#endif
if ((pre_close=info->pre_close))
{
@@ -1884,9 +1851,7 @@ int end_io_cache(IO_CACHE *info)
{
/* Destroy allocated mutex */
info->type= TYPE_NOT_SET;
-#ifdef THREAD
mysql_mutex_destroy(&info->append_buffer_lock);
-#endif
}
#ifdef THREAD
info->share= 0;
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index c74504e4fa8..85631e9741b 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -90,9 +90,8 @@ my_off_t my_b_append_tell(IO_CACHE* info)
from messing with the variables that we need in order to provide the
answer to the question.
*/
-#ifdef THREAD
mysql_mutex_lock(&info->append_buffer_lock);
-#endif
+
#ifndef DBUG_OFF
/*
Make sure EOF is where we think it is. Note that we cannot just use
@@ -112,9 +111,7 @@ my_off_t my_b_append_tell(IO_CACHE* info)
}
#endif
res = info->end_of_file + (info->write_pos-info->append_read_pos);
-#ifdef THREAD
mysql_mutex_unlock(&info->append_buffer_lock);
-#endif
return res;
}
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 41b93517655..80111b3245d 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -318,16 +318,11 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cache_var;
static int flush_all_key_blocks(SIMPLE_KEY_CACHE_CB *keycache);
static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup);
-#ifdef THREAD
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
mysql_mutex_t *mutex);
static void release_whole_queue(KEYCACHE_WQUEUE *wqueue);
-#else
-#define wait_on_queue(wqueue, mutex) do {} while (0)
-#define release_whole_queue(wqueue) do {} while (0)
-#endif
static void free_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block);
-#if !defined(DBUG_OFF)
+#ifndef DBUG_OFF
static void test_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
const char *where, my_bool lock);
#endif
@@ -379,7 +374,6 @@ static void keycache_debug_print(const char *fmt,...);
#endif /* defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG) */
#if defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF)
-#ifdef THREAD
static long keycache_thread_id;
#define KEYCACHE_THREAD_TRACE(l) \
KEYCACHE_DBUG_PRINT(l,("|thread %ld",keycache_thread_id))
@@ -391,11 +385,6 @@ static long keycache_thread_id;
#define KEYCACHE_THREAD_TRACE_END(l) \
KEYCACHE_DBUG_PRINT(l,("]thread %ld",keycache_thread_id))
-#else /* THREAD */
-#define KEYCACHE_THREAD_TRACE(l) KEYCACHE_DBUG_PRINT(l,(""))
-#define KEYCACHE_THREAD_TRACE_BEGIN(l) KEYCACHE_DBUG_PRINT(l,(""))
-#define KEYCACHE_THREAD_TRACE_END(l) KEYCACHE_DBUG_PRINT(l,(""))
-#endif /* THREAD */
#else
#define KEYCACHE_THREAD_TRACE_BEGIN(l)
#define KEYCACHE_THREAD_TRACE_END(l)
@@ -685,7 +674,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
keycache_pthread_mutex_lock(&keycache->cache_lock);
-#ifdef THREAD
/*
We may need to wait for another thread which is doing a resize
already. This cannot happen in the MySQL server though. It allows
@@ -698,7 +686,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
/* purecov: end */
}
-#endif
/*
Mark the operation in progress. This blocks other threads from doing
@@ -727,7 +714,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
keycache->resize_in_flush= 0;
}
-#ifdef THREAD
/*
Some direct read/write operations (bypassing the cache) may still be
unfinished. Wait until they are done. If the key cache can be used,
@@ -741,9 +727,6 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
*/
while (keycache->cnt_for_resize_op)
wait_on_queue(&keycache->waiting_for_resize_cnt, &keycache->cache_lock);
-#else
- KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0);
-#endif
end_simple_key_cache(keycache, 0);
@@ -1022,8 +1005,6 @@ void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup)
} /* end_key_cache */
-#ifdef THREAD
-
/*
Link a thread into double-linked queue of waiting threads.
@@ -1203,8 +1184,6 @@ static void release_whole_queue(KEYCACHE_WQUEUE *wqueue)
wqueue->last_thread= NULL;
}
-#endif /* THREAD */
-
/*
Unlink a block from the chain of dirty/clean blocks
@@ -1376,7 +1355,6 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block,
DBUG_ASSERT(block->prev_changed && *block->prev_changed == block);
DBUG_ASSERT(!block->next_used);
DBUG_ASSERT(!block->prev_used);
-#ifdef THREAD
if (!hot && keycache->waiting_for_block.last_thread)
{
/* Signal that in the LRU warm sub-chain an available block has appeared */
@@ -1436,10 +1414,6 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block,
#endif
return;
}
-#else /* THREAD */
- KEYCACHE_DBUG_ASSERT(! (!hot && keycache->waiting_for_block.last_thread));
- /* Condition not transformed using DeMorgan, to keep the text identical */
-#endif /* THREAD */
pins= hot ? &keycache->used_ins : &keycache->used_last;
ins= *pins;
if (ins)
@@ -1662,12 +1636,8 @@ static void remove_reader(BLOCK_LINK *block)
DBUG_ASSERT(!block->next_used);
DBUG_ASSERT(!block->prev_used);
DBUG_ASSERT(block->hash_link->requests);
-#ifdef THREAD
if (! --block->hash_link->requests && block->condvar)
keycache_pthread_cond_signal(block->condvar);
-#else
- --block->hash_link->requests;
-#endif
}
@@ -1679,7 +1649,6 @@ static void remove_reader(BLOCK_LINK *block)
static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache,
BLOCK_LINK *block)
{
-#ifdef THREAD
struct st_my_thread_var *thread= my_thread_var;
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
DBUG_ASSERT(!(block->status & (BLOCK_IN_FLUSH | BLOCK_CHANGED)));
@@ -1701,9 +1670,6 @@ static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache,
keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock);
block->condvar= NULL;
}
-#else
- KEYCACHE_DBUG_ASSERT(block->hash_link->requests == 0);
-#endif
}
@@ -1733,7 +1699,6 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
if ((*hash_link->prev= hash_link->next))
hash_link->next->prev= hash_link->prev;
hash_link->block= NULL;
-#ifdef THREAD
if (keycache->waiting_for_hash_link.last_thread)
{
/* Signal that a free hash link has appeared */
@@ -1769,9 +1734,6 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link)
hash_link);
return;
}
-#else /* THREAD */
- KEYCACHE_DBUG_ASSERT(! (keycache->waiting_for_hash_link.last_thread));
-#endif /* THREAD */
hash_link->next= keycache->free_hash_list;
keycache->free_hash_list= hash_link;
}
@@ -1836,7 +1798,6 @@ restart:
}
else
{
-#ifdef THREAD
/* Wait for a free hash link */
struct st_my_thread_var *thread= my_thread_var;
KEYCACHE_PAGE page;
@@ -1850,9 +1811,6 @@ restart:
keycache_pthread_cond_wait(&thread->suspend,
&keycache->cache_lock);
thread->opt_info= NULL;
-#else
- KEYCACHE_DBUG_ASSERT(0);
-#endif
goto restart;
}
hash_link->file= file;
@@ -1972,7 +1930,6 @@ restart:
- block assigned but not yet read from file (invalid data).
*/
-#ifdef THREAD
if (keycache->in_resize)
{
/* This is a request during a resize operation */
@@ -2214,9 +2171,6 @@ restart:
}
DBUG_RETURN(0);
}
-#else /* THREAD */
- DBUG_ASSERT(!keycache->in_resize);
-#endif
if (page_status == PAGE_READ &&
(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
@@ -2346,7 +2300,6 @@ restart:
from the LRU ring.
*/
-#ifdef THREAD
if (! keycache->used_last)
{
/*
@@ -2379,9 +2332,6 @@ restart:
DBUG_ASSERT(!hash_link->block->next_used);
DBUG_ASSERT(!hash_link->block->prev_used);
}
-#else
- KEYCACHE_DBUG_ASSERT(keycache->used_last);
-#endif
/*
If we waited above, hash_link->block has been assigned by
link_block(). Otherwise it is still NULL. In the latter case
@@ -2868,11 +2818,6 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
set_if_smaller(read_length, keycache->key_cache_block_size-offset);
KEYCACHE_DBUG_ASSERT(read_length > 0);
-#ifndef THREAD
- if (block_length > keycache->key_cache_block_size || offset)
- return_buffer=0;
-#endif
-
/* Request the cache block that matches file/pos. */
keycache->global_cache_r_requests++;
@@ -2931,9 +2876,6 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
/* block status may have added BLOCK_ERROR in the above 'if'. */
if (!(block->status & BLOCK_ERROR))
{
-#ifndef THREAD
- if (! return_buffer)
-#endif
{
DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE));
#if !defined(SERIALIZED_READ_FROM_CACHE)
@@ -2972,20 +2914,6 @@ uchar *simple_key_cache_read(SIMPLE_KEY_CACHE_CB *keycache,
break;
}
-#ifndef THREAD
- /* This is only true if we where able to read everything in one block */
- if (return_buffer)
- {
- if (MYSQL_KEYCACHE_READ_DONE_ENABLED())
- {
- MYSQL_KEYCACHE_READ_DONE((ulong) (keycache->blocks_used *
- keycache->key_cache_block_size),
- (ulong) (keycache->blocks_unused *
- keycache->key_cache_block_size));
- }
- DBUG_RETURN(block->buffer);
- }
-#endif
next_block:
buff+= read_length;
filepos+= read_length+offset;
@@ -4262,17 +4190,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;
-
- LINT_INIT(next_hash_link);
- LINT_INIT(next_diskpos);
- LINT_INIT(next_file);
- LINT_INIT(next_status);
- LINT_INIT(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++;
@@ -5488,10 +5410,6 @@ uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache,
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
-#ifndef THREAD
- if (block_length > keycache->key_cache_block_size || offset)
- return_buffer=0;
-#endif
/* Read data in key_cache_block_size increments */
do
@@ -5507,11 +5425,6 @@ uchar *partitioned_key_cache_read(PARTITIONED_KEY_CACHE_CB *keycache,
block_length, return_buffer);
if (ret_buff == 0)
DBUG_RETURN(0);
-#ifndef THREAD
- /* This is only true if we were able to read everything in one block */
- if (return_buffer)
- DBUG_RETURN(ret_buff);
-#endif
filepos+= r_length;
buff+= r_length;
offset= 0;
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index c6e6a3a429e..790936461a4 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -1,4 +1,4 @@
-/* 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
@@ -192,7 +192,8 @@ size_t cleanup_dirname(register char *to, const char *from)
end_parentdir=pos;
while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */
pos--;
- if (pos[1] == FN_HOMELIB || memcmp(pos,parent,length) == 0)
+ if (pos[1] == FN_HOMELIB ||
+ (pos >= start && memcmp(pos, parent, length) == 0))
{ /* Don't remove ~user/ */
pos=strmov(end_parentdir+1,parent);
*pos=FN_LIBCHAR;
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index 22199758112..be39ac50731 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -21,17 +21,13 @@
* 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
+ 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
+ was made by Mikael Ronstrom 2005, with assistance of Tomas Ulin and Mats
Kindahl.
*/
@@ -100,18 +96,14 @@ void create_last_word_mask(MY_BITMAP *map)
static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused)))
{
-#ifdef THREAD
if (map->mutex)
mysql_mutex_lock(map->mutex);
-#endif
}
static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
{
-#ifdef THREAD
if (map->mutex)
mysql_mutex_unlock(map->mutex);
-#endif
}
@@ -123,30 +115,24 @@ my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
{
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(mysql_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= (mysql_mutex_t *) ((char*) buf + size_in_bytes);
mysql_mutex_init(key_BITMAP_mutex, map->mutex, MY_MUTEX_INIT_FAST);
}
-#endif
}
-#ifdef THREAD
else
{
DBUG_ASSERT(thread_safe == 0);
}
-#endif
map->bitmap= buf;
map->n_bits= n_bits;
@@ -161,10 +147,8 @@ void bitmap_free(MY_BITMAP *map)
DBUG_ENTER("bitmap_free");
if (map->bitmap)
{
-#ifdef THREAD
if (map->mutex)
mysql_mutex_destroy(map->mutex);
-#endif
my_free(map->bitmap);
map->bitmap=0;
}
diff --git a/mysys/my_handler.c b/mysys/my_compare.c
index 2cbe65bebba..4629a3bae18 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_compare.c
@@ -1,26 +1,23 @@
-/* Copyright (C) 2002-2006 MySQL AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; version 2
- of the License.
-
- This library 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
- Library General Public License for more details.
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ 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 <my_global.h>
#include <m_ctype.h>
#include <my_base.h>
-#include <my_handler.h>
+#include <my_compare.h>
#include <my_sys.h>
-#include "my_handler_errors.h"
int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, uint a_length,
const uchar *b, uint b_length, my_bool part_key,
@@ -28,8 +25,7 @@ int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, uint a_length,
{
if (!part_key)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
- b, b_length,
- (my_bool)!skip_end_space);
+ b, b_length, (my_bool)!skip_end_space);
return charset_info->coll->strnncoll(charset_info, a, a_length,
b, b_length, part_key);
}
@@ -121,8 +117,8 @@ static int compare_bin(const uchar *a, uint a_length,
#define FCMP(A,B) ((int) (A) - (int) (B))
-int ha_key_cmp(register HA_KEYSEG *keyseg, register const uchar *a,
- register const uchar *b, uint key_length, uint32 nextflag,
+int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a,
+ const uchar *b, uint key_length, uint32 nextflag,
uint *diff_pos)
{
int flag;
@@ -555,7 +551,6 @@ found:
return 0;
} /* ha_key_cmp */
-
/*
Find the first NULL value in index-suffix values tuple
@@ -645,37 +640,3 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a)
return keyseg;
}
-
-/*
- Register handler error messages for usage with my_error()
-
- NOTES
- This is safe to call multiple times as my_error_register()
- will ignore calls to register already registered error numbers.
-*/
-
-static const char **get_handler_error_messages()
-{
- return handler_error_messages;
-}
-
-void my_handler_error_register(void)
-{
- /*
- If you got compilation error here about compile_time_assert array, check
- that every HA_ERR_xxx constant has a corresponding error message in
- handler_error_messages[] list (check mysys/ma_handler_errors.h and
- include/my_base.h).
- */
- compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) ==
- HA_ERR_LAST + 1);
- my_error_register(get_handler_error_messages, HA_ERR_FIRST,
- HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
-}
-
-
-void my_handler_error_unregister(void)
-{
- my_error_unregister(HA_ERR_FIRST,
- HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
-}
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index ebe5c7ddf80..9bc740c80fd 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* 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,6 +18,10 @@
#include <errno.h>
#include "mysys_err.h"
+#if defined(__FreeBSD__)
+extern int getosreldate(void);
+#endif
+
static void make_ftype(char * to,int flag);
/*
@@ -89,7 +93,135 @@ 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)
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index 0c7e4ef7aa3..83cb0d261c0 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -124,10 +124,9 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags)
}
#endif
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
-#ifdef THREAD
if (my_thread_var->abort)
MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
-#endif
+
if ((errno == ENOSPC || errno == EDQUOT) &&
(MyFlags & MY_WAIT_IF_FULL))
{
diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c
deleted file mode 100644
index 3962de21fc0..00000000000
--- a/mysys/my_gethostbyname.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Copyright (C) 2002, 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; version 2
- of the License.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/* Thread safe version of gethostbyname_r() */
-
-#include "mysys_priv.h"
-#if !defined(__WIN__)
-#include <netdb.h>
-#endif
-#include <my_net.h>
-
-/* This file is not needed if my_gethostbyname_r is a macro */
-#if !defined(my_gethostbyname_r)
-
-/*
- Emulate SOLARIS style calls, not because it's better, but just to make the
- usage of getbostbyname_r simpler.
-*/
-
-#if defined(HAVE_GETHOSTBYNAME_R)
-
-#if defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE)
-
-struct hostent *my_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- int buflen, int *h_errnop)
-{
- struct hostent *hp;
- DBUG_ASSERT((size_t) buflen >= sizeof(*result));
- if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop))
- return 0;
- return hp;
-}
-
-#elif defined(HAVE_GETHOSTBYNAME_R_RETURN_INT)
-
-struct hostent *my_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- int buflen, int *h_errnop)
-{
- if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1)
- {
- *h_errnop= errno;
- return 0;
- }
- return result;
-}
-
-#else
-
-/* gethostbyname_r with similar interface as gethostbyname() */
-
-struct hostent *my_gethostbyname_r(const char *name,
- struct hostent *result, char *buffer,
- int buflen, int *h_errnop)
-{
- struct hostent *hp;
- DBUG_ASSERT(buflen >= sizeof(struct hostent_data));
- hp= gethostbyname_r(name,result,(struct hostent_data *) buffer);
- *h_errnop= errno;
- return hp;
-}
-#endif /* GLIBC2_STYLE_GETHOSTBYNAME_R */
-
-#else /* !HAVE_GETHOSTBYNAME_R */
-
-#ifdef THREAD
-extern mysql_mutex_t LOCK_gethostbyname_r;
-#endif
-
-/*
- No gethostbyname_r() function exists.
- In this case we have to keep a mutex over the call to ensure that no
- other thread is going to reuse the internal memory.
-
- The user is responsible to call my_gethostbyname_r_free() when he
- is finished with the structure.
-*/
-
-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;
- mysql_mutex_lock(&LOCK_gethostbyname_r);
- hp= gethostbyname(name);
- *h_errnop= h_errno;
- return hp;
-}
-
-void my_gethostbyname_r_free()
-{
- mysql_mutex_unlock(&LOCK_gethostbyname_r);
-}
-
-#endif /* !HAVE_GETHOSTBYNAME_R */
-#endif /* !my_gethostbyname_r */
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index d14087d061e..ab44bac43d3 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -21,18 +21,6 @@
#ifndef MAIN
-#if defined(__FreeBSD__) || defined(__linux__)
-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;
-}
-#endif /* FreeBSD || linux */
-
#ifdef __FreeBSD__
#include <net/ethernet.h>
@@ -44,10 +32,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 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;
@@ -63,9 +52,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=(uchar *)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;
}
}
@@ -81,8 +70,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)
@@ -91,9 +81,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);
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 74c0d6b5ba3..fff8fda581c 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2002, 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
@@ -176,7 +176,7 @@ int handle_options(int *argc, char ***argv,
*/
for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
{
- if (*pos == args_separator)
+ if (my_getopt_is_args_separator(*pos))
{
is_cmdline_arg= 0;
break;
@@ -188,7 +188,7 @@ int handle_options(int *argc, char ***argv,
char **first= pos;
char *cur_arg= *pos;
opt_found= 0;
- if (!is_cmdline_arg && (cur_arg == args_separator))
+ if (!is_cmdline_arg && (my_getopt_is_args_separator(cur_arg)))
{
is_cmdline_arg= 1;
@@ -360,14 +360,6 @@ int handle_options(int *argc, char ***argv,
}
return EXIT_OPTION_DISABLED;
}
- if (must_be_var && optp->arg_type == NO_ARG)
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '%s' cannot take an argument",
- 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, &error) :
@@ -377,6 +369,11 @@ int handle_options(int *argc, char ***argv,
if (optp->arg_type == NO_ARG)
{
+ /*
+ Due to historical reasons GET_BOOL var_types still accepts arguments
+ despite the NO_ARG arg_type attribute. This can seems a bit unintuitive
+ and care should be taken when refactoring this code.
+ */
if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
{
if (my_getopt_print_errors)
@@ -391,7 +388,7 @@ int handle_options(int *argc, char ***argv,
Set bool to 1 if no argument or if the user has used
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
- */
+ */
(*argc)--;
if (!optend || *optend == '1' ||
!my_strcasecmp(&my_charset_latin1, optend, "true"))
@@ -418,10 +415,9 @@ int handle_options(int *argc, char ***argv,
else if (optp->arg_type == REQUIRED_ARG && !optend)
{
/* Check if there are more arguments after this one,
-
- Note: options loaded from config file that requires value
- should always be in the form '--option=value'.
- */
+ Note: options loaded from config file that requires value
+ should always be in the form '--option=value'.
+ */
if (!is_cmdline_arg || !*++pos)
{
if (my_getopt_print_errors)
@@ -607,6 +603,32 @@ static char *check_struct_option(char *cur_arg, char *key_name)
}
}
+/**
+ Parse a boolean command line argument
+
+ "ON", "TRUE" and "1" will return true,
+ other values will return false.
+
+ @param[in] argument The value argument
+ @return boolean value
+*/
+static my_bool get_bool_argument(const struct my_option *opts,
+ const char *argument)
+{
+ if (!my_strcasecmp(&my_charset_latin1, argument, "true") ||
+ !my_strcasecmp(&my_charset_latin1, argument, "on") ||
+ !my_strcasecmp(&my_charset_latin1, argument, "1"))
+ return 1;
+ else if (!my_strcasecmp(&my_charset_latin1, argument, "false") ||
+ !my_strcasecmp(&my_charset_latin1, argument, "off") ||
+ !my_strcasecmp(&my_charset_latin1, argument, "0"))
+ return 0;
+ my_getopt_error_reporter(WARNING_LEVEL,
+ "option '%s': boolean value '%s' wasn't recognized. Set to OFF.",
+ opts->name, argument);
+ return 0;
+}
+
/*
function: setval
@@ -634,7 +656,7 @@ static int setval(const struct my_option *opts, void *value, char *argument,
switch ((opts->var_type & GET_TYPE_MASK)) {
case GET_BOOL: /* If argument differs from 0, enable option, else disable */
- *((my_bool*) value)= (my_bool) atoi(argument) != 0;
+ *((my_bool*) value)= get_bool_argument(opts, argument);
break;
case GET_INT:
*((int*) value)= (int) getopt_ll(argument, opts, &err);
@@ -674,7 +696,7 @@ static int setval(const struct my_option *opts, void *value, char *argument,
break;
case GET_ENUM:
{
- int type= find_type(argument, opts->typelib, 2);
+ int type= find_type(argument, opts->typelib, FIND_TYPE_BASIC);
if (type == 0)
{
/*
diff --git a/mysys/my_handler_errors.h b/mysys/my_handler_errors.h
index e5cb06fba63..97282503967 100644
--- a/mysys/my_handler_errors.h
+++ b/mysys/my_handler_errors.h
@@ -66,7 +66,12 @@ static const char *handler_error_messages[]=
"File too short; Expected more data in file",
"Read page with wrong checksum",
"Too many active concurrent transactions",
+ "Index column length exceeds limit"
"Row is not visible by the current transaction"
};
+extern void my_handler_error_register(void);
+extern void my_handler_error_unregister(void);
+
+
#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */
diff --git a/mysys/my_init.c b/mysys/my_init.c
index ae4aa5bb5b7..8cf1af2f8ee 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* 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
@@ -37,8 +37,6 @@ static my_bool win32_init_tcp_ip();
#define SCALE_USEC 10000
my_bool my_init_done= 0;
-/** True if @c my_basic_init() has been called. */
-my_bool my_basic_init_done= 0;
uint mysys_usage_id= 0; /* Incremented for each my_init() */
ulong my_thread_stack_size= (sizeof(void*) <= 4)? 65536: ((256-16)*1024);
@@ -57,23 +55,22 @@ static ulong atoi_octal(const char *str)
MYSQL_FILE *mysql_stdin= NULL;
static MYSQL_FILE instrumented_stdin;
+
/**
- Perform a limited initialisation of mysys.
- This initialisation is sufficient to:
- - allocate memory,
- - read configuration files,
- - parse command lines arguments.
- To complete the mysys initialisation,
- call my_init().
- @return 0 on success
+ Initialize my_sys functions, resources and variables
+
+ @return Initialization result
+ @retval 0 Success
+ @retval 1 Error. Couldn't initialize environment
*/
-my_bool my_basic_init(void)
+my_bool my_init(void)
{
- char * str;
+ char *str;
- if (my_basic_init_done)
+ if (my_init_done)
return 0;
- my_basic_init_done= 1;
+
+ my_init_done= 1;
mysys_usage_id++;
my_umask= 0660; /* Default umask for new files */
@@ -96,52 +93,20 @@ my_bool my_basic_init(void)
if (my_progname)
my_progname_short= my_progname + dirname_length(my_progname);
-#if defined(THREAD)
/* Initalize our mutex handling */
my_mutex_init();
if (my_thread_global_init())
return 1;
+
#if defined(HAVE_PTHREAD_INIT)
pthread_init(); /* Must be called before DBUG_ENTER */
#endif
- if (my_thread_basic_global_init())
- return 1;
-#endif
/* $HOME is needed early to parse configuration files located in ~/ */
if ((home_dir= getenv("HOME")) != 0)
home_dir= intern_filename(home_dir_buff, home_dir);
- return 0;
-}
-
-
-/*
- Init my_sys functions and my_sys variabels
-
- SYNOPSIS
- my_init()
-
- RETURN
- 0 ok
- 1 Couldn't initialize environment
-*/
-
-my_bool my_init(void)
-{
- if (my_init_done)
- return 0;
-
- my_init_done= 1;
-
- if (my_basic_init())
- return 1;
-
-#ifdef THREAD
- if (my_thread_global_init())
- return 1;
-#endif /* THREAD */
{
DBUG_ENTER("my_init");
DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown"));
@@ -240,7 +205,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
{
DBUG_END(); /* Must be done before my_thread_end */
}
-#ifdef THREAD
+
my_thread_end();
my_thread_global_end();
my_mutex_end();
@@ -252,7 +217,6 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
safe_mutex_end((infoflag & (MY_GIVE_INFO | MY_CHECK_ERROR)) ? stderr :
(FILE *) 0);
#endif /* defined(SAFE_MUTEX) */
-#endif /* THREAD */
#ifdef __WIN__
if (have_tcpip)
@@ -260,7 +224,6 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
#endif /* __WIN__ */
my_init_done=0;
- my_basic_init_done= 0;
} /* my_end */
#ifndef DBUG_OFF
@@ -319,6 +282,89 @@ int handle_rtc_failure(int err_type, const char *file, int line,
#pragma runtime_checks("", restore)
#endif
+#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10)
+#define MS 10000000
+
+static void win_init_time(void)
+{
+ /* The following is used by time functions */
+ 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);
+ }
+}
+
+
+/*
+ Open HKEY_LOCAL_MACHINE\SOFTWARE\MySQL and set any strings found
+ there as environment variables
+*/
+static void win_init_registry(void)
+{
+ 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;
+ }
+
+ RegCloseKey(key_handle);
+ }
+}
+
static void my_win_init(void)
{
@@ -326,17 +372,18 @@ static void my_win_init(void)
#if defined(_MSC_VER)
#if _MSC_VER < 1300
- /*
+ /*
Clear the OS system variable TZ and avoid the 100% CPU usage
Only for old versions of Visual C++
*/
- _putenv( "TZ=" );
-#endif
+ _putenv("TZ=");
+#endif
#if _MSC_VER >= 1400
/* this is required to make crt functions return -1 appropriately */
_set_invalid_parameter_handler(my_parameter_handler);
#endif
-#endif
+#endif
+
#ifdef __MSVC_RUNTIME_CHECKS
/*
Install handler to send RTC (Runtime Error Check) warnings
@@ -347,106 +394,10 @@ static void my_win_init(void)
_tzset();
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /* The following is used by time functions */
-#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10)
-#define MS 10000000
- {
- 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);
- }
- }
-
- {
- /*
- 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];
+ win_init_time();
+ win_init_registry();
- 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;
- }
-
- RegCloseKey(key_handle) ;
- }
- }
- DBUG_VOID_RETURN ;
+ DBUG_VOID_RETURN;
}
@@ -524,29 +475,22 @@ PSI_mutex_key key_my_file_info_mutex;
PSI_mutex_key key_LOCK_localtime_r;
#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */
-#ifndef HAVE_GETHOSTBYNAME_R
-PSI_mutex_key key_LOCK_gethostbyname_r;
-#endif /* HAVE_GETHOSTBYNAME_R */
-
PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm,
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc,
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
- key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time,
+ key_THR_LOCK_open, key_THR_LOCK_threads,
key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap;
static PSI_mutex_info all_mysys_mutexes[]=
{
-#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32)
+#if !defined(HAVE_PREAD) && !defined(_WIN32)
{ &key_my_file_info_mutex, "st_my_file_info:mutex", 0},
#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
{ &key_LOCK_localtime_r, "LOCK_localtime_r", PSI_FLAG_GLOBAL},
#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */
-#ifndef HAVE_GETHOSTBYNAME_R
- { &key_LOCK_gethostbyname_r, "LOCK_gethostbyname_r", PSI_FLAG_GLOBAL},
-#endif /* HAVE_GETHOSTBYNAME_R */
{ &key_BITMAP_mutex, "BITMAP::mutex", 0},
{ &key_IO_CACHE_append_buffer_lock, "IO_CACHE::append_buffer_lock", 0},
{ &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0},
@@ -563,7 +507,6 @@ static PSI_mutex_info all_mysys_mutexes[]=
{ &key_THR_LOCK_net, "THR_LOCK_net", PSI_FLAG_GLOBAL},
{ &key_THR_LOCK_open, "THR_LOCK_open", PSI_FLAG_GLOBAL},
{ &key_THR_LOCK_threads, "THR_LOCK_threads", PSI_FLAG_GLOBAL},
- { &key_THR_LOCK_time, "THR_LOCK_time", PSI_FLAG_GLOBAL},
{ &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL},
{ &key_THR_LOCK_myisam_mmap, "THR_LOCK_myisam_mmap", PSI_FLAG_GLOBAL}
};
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 890ff0b5dd1..06f9521a664 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -41,7 +41,7 @@
# endif
#endif
-#if defined(THREAD) && defined(HAVE_READDIR_R)
+#if defined(HAVE_READDIR_R)
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
#else
#define READDIR(A,B,C) (!(C=readdir(A)))
@@ -97,13 +97,12 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
DIR *dirp;
struct dirent *dp;
char tmp_path[FN_REFLEN+1],*tmp_file;
-#ifdef THREAD
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
-#endif
+
DBUG_ENTER("my_dir");
DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
-#if defined(THREAD) && !defined(HAVE_READDIR_R)
+#if !defined(HAVE_READDIR_R)
mysql_mutex_lock(&THR_LOCK_open);
#endif
@@ -135,11 +134,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
tmp_file=strend(tmp_path);
-#ifdef THREAD
dp= (struct dirent*) dirent_tmp;
-#else
- dp=0;
-#endif
while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
{
@@ -166,7 +161,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
}
(void) closedir(dirp);
-#if defined(THREAD) && !defined(HAVE_READDIR_R)
+#if !defined(HAVE_READDIR_R)
mysql_mutex_unlock(&THR_LOCK_open);
#endif
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
@@ -178,7 +173,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
DBUG_RETURN(result);
error:
-#if defined(THREAD) && !defined(HAVE_READDIR_R)
+#if !defined(HAVE_READDIR_R)
mysql_mutex_unlock(&THR_LOCK_open);
#endif
my_errno=errno;
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 8f34ce1c6dc..2aef97b3e34 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -89,7 +89,7 @@ int my_close(File fd, myf MyFlags)
if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN)
{
my_free(my_file_info[fd].name);
-#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32)
+#if !defined(HAVE_PREAD) && !defined(_WIN32)
mysql_mutex_destroy(&my_file_info[fd].mutex);
#endif
my_file_info[fd].type = UNOPEN;
@@ -125,7 +125,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type
{
if ((uint) fd >= my_file_limit)
{
-#if defined(THREAD) && !defined(HAVE_PREAD)
+#if !defined(HAVE_PREAD)
my_errno= EMFILE;
#else
thread_safe_increment(my_file_opened,&THR_LOCK_open);
@@ -140,7 +140,7 @@ File my_register_filename(File fd, const char *FileName, enum file_type
my_file_opened++;
my_file_total_opened++;
my_file_info[fd].type = type_of_file;
-#if defined(THREAD) && !defined(HAVE_PREAD) && !defined(_WIN32)
+#if !defined(HAVE_PREAD) && !defined(_WIN32)
mysql_mutex_init(key_my_file_info_mutex, &my_file_info[fd].mutex,
MY_MUTEX_INIT_FAST);
#endif
diff --git a/mysys/my_port.c b/mysys/my_port.c
deleted file mode 100644
index 9ad333421ca..00000000000
--- a/mysys/my_port.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright (C) 2002 MySQL AB
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; version 2
- of the License.
-
- This library 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
-
-/*
- Small functions to make code portable
-*/
-
-#include "mysys_priv.h"
-
-#ifdef _AIX
-
-/*
- On AIX, at least with gcc 3.1, the expression
- '(double) (ulonglong) var' doesn't always work for big unsigned
- integers like '18446744073709551615'. The end result is that the
- high bit is simply dropped. (probably bug in gcc optimizations)
- Handling the conversion in a sub function seems to work.
-*/
-
-
-
-double my_ulonglong2double(unsigned long long nr)
-{
- return (double) nr;
-}
-#endif /* _AIX */
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index d0a0ddaec66..e006360c11b 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -85,14 +85,14 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
(int) readbytes, (uint) Count,Filedes,my_errno));
-#ifdef THREAD
+
if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR)
{
DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d",
(int) readbytes));
continue; /* Interrupted */
}
-#endif
+
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
if (readbytes == (size_t) -1)
@@ -173,10 +173,10 @@ size_t my_pwrite(File Filedes, const uchar *Buffer, size_t Count,
}
DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes));
#ifndef NO_BACKGROUND
-#ifdef THREAD
+
if (my_thread_var->abort)
MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
-#endif
+
if ((my_errno == ENOSPC || my_errno == EDQUOT) &&
(MyFlags & MY_WAIT_IF_FULL))
{
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index a13cd9b3545..f0b3b1e8aef 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -18,7 +18,6 @@
#define DONT_REMAP_PTHREAD_FUNCTIONS
#include "mysys_priv.h"
-#ifdef THREAD
#include <signal.h>
#include <m_string.h>
#include <thr_alarm.h>
@@ -470,4 +469,3 @@ int pthread_dummy(int ret)
{
return ret;
}
-#endif /* THREAD */
diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c
index c8ef38efbdc..2afe3ec31dd 100644
--- a/mysys/my_rdtsc.c
+++ b/mysys/my_rdtsc.c
@@ -868,14 +868,8 @@ void my_timer_init(MY_TIMER_INFO *mti)
clock() -- We don't use because it would overflow frequently.
- clock_gettime() -- Often we don't use this even when it exists.
- In configure.in, we use AC_CHECK_FUNCS(clock_gettime). Not
- AC_CHECK_LIB(rc,clock_gettime)
- AC_CHECK_FUNCS(clock_gettime)
- If we had the above lines in configure.in, we'd have to use
- /usr/lib/librt.so or /usr/lib64/librt.so when linking, and
- the size of librt.so is 40KB. In tests, clock_gettime often
- had resolution = 1000.
+ clock_gettime() -- In tests, clock_gettime often had
+ resolution = 1000.
ftime() -- A "man ftime" says: "This function is obsolete.
Don't use it." On every platform that we tested, if ftime()
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 75f9dd64f1d..dbe9006a1d3 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -59,14 +59,14 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
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 %ld",
(long) readbytes));
continue; /* Interrupted */
}
-#endif
+
if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
{
if (readbytes == (size_t) -1)
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index 63337c636a4..ca12a2e95d1 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -65,7 +65,7 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags)
my_errno= errno;
if (MyFlags & MY_WME)
my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno);
- DBUG_PRINT("error",("lseek: %llu errno: %d", (ulonglong) newpos,errno));
+ DBUG_PRINT("error", ("lseek: %llu errno: %d", (ulonglong) newpos, errno));
DBUG_RETURN(MY_FILEPOS_ERROR);
}
if ((my_off_t) newpos != pos)
@@ -95,6 +95,7 @@ my_off_t my_tell(File fd, myf MyFlags)
my_errno= errno;
if (MyFlags & MY_WME)
my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno);
+ DBUG_PRINT("error", ("tell: %llu errno: %d", (ulonglong) pos, my_errno));
}
DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos));
DBUG_RETURN((my_off_t) pos);
diff --git a/mysys/my_static.c b/mysys/my_static.c
index c6bf3c0ef0f..ac0ad2467f7 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -32,9 +32,7 @@ char curr_dir[FN_REFLEN]= {0},
ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0;
ulong my_file_total_opened= 0;
int my_umask=0664, my_umask_dir=0777;
-#ifndef THREAD
-int my_errno=0;
-#endif
+
struct st_my_file_info my_file_info_default[MY_NFILE];
uint my_file_limit= MY_NFILE;
struct st_my_file_info *my_file_info= my_file_info_default;
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index 33f45a882e1..9657ea6bf58 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -113,7 +113,6 @@ int my_is_symlink(const char *filename __attribute__((unused)))
#endif
}
-
/*
Resolve all symbolic links in path
'to' may be equal to 'filename'
@@ -122,8 +121,7 @@ int my_is_symlink(const char *filename __attribute__((unused)))
(including the end \0)
*/
-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_BROKEN_REALPATH)
int result=0;
@@ -150,7 +148,23 @@ int my_realpath(char *to, const char *filename,
}
DBUG_RETURN(result);
#else
+#ifdef _WIN32
+ int ret= GetFullPathName(filename,FN_REFLEN,
+ to,
+ NULL);
+ if (ret == 0 || ret > FN_REFLEN)
+ {
+ if (ret > FN_REFLEN)
+ my_errno= ENAMETOOLONG;
+ else
+ my_errno= EACCES;
+ if (MyFlags & MY_WME)
+ my_error(EE_REALPATH, MYF(0), filename, my_errno);
+ return -1;
+ }
+#else
my_load_path(to, filename, NullS);
+#endif
return 0;
#endif
}
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index 7dfd365326c..f39b10253dd 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -17,8 +17,19 @@
#include "mysys_err.h"
#include <errno.h>
+
ulong my_sync_count; /* Count number of sync calls */
+static void (*before_sync_wait)(void)= 0;
+static void (*after_sync_wait)(void)= 0;
+
+void thr_set_sync_wait_callback(void (*before_wait)(void),
+ void (*after_wait)(void))
+{
+ before_sync_wait= before_wait;
+ after_sync_wait= after_wait;
+}
+
/*
Sync data in file to disk
@@ -46,12 +57,19 @@ int my_sync(File fd, myf my_flags)
{
int res;
DBUG_ENTER("my_sync");
+
DBUG_PRINT("my",("fd: %d my_flags: %d", fd, my_flags));
if (my_disable_sync)
DBUG_RETURN(0);
statistic_increment(my_sync_count,&THR_LOCK_open);
+
+ DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags));
+
+ if (before_sync_wait)
+ (*before_sync_wait)();
+
do
{
#if defined(F_FULLFSYNC)
@@ -64,7 +82,7 @@ int my_sync(File fd, myf my_flags)
/* 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)
+#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC
res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
res= fsync(fd);
@@ -83,6 +101,8 @@ int my_sync(File fd, myf my_flags)
int er= errno;
if (!(my_errno= er))
my_errno= -1; /* Unknown error */
+ if (after_sync_wait)
+ (*after_sync_wait)();
if ((my_flags & MY_IGNORE_BADFD) &&
(er == EBADF || er == EINVAL || er == EROFS))
{
@@ -92,11 +112,18 @@ int my_sync(File fd, myf my_flags)
else if (my_flags & MY_WME)
my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno);
}
+ else
+ {
+ if (after_sync_wait)
+ (*after_sync_wait)();
+ }
DBUG_RETURN(res);
} /* my_sync */
static const char cur_dir_name[]= {FN_CURLIB, 0};
+
+
/*
Force directory information to disk.
@@ -108,7 +135,9 @@ static const char cur_dir_name[]= {FN_CURLIB, 0};
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;
@@ -133,12 +162,15 @@ int my_sync_dir(const char *dir_name, myf my_flags)
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)))
+ myf my_flags __attribute__((unused)))
{
return 0;
}
+
#endif /* NEED_EXPLICIT_SYNC_DIR */
@@ -153,7 +185,9 @@ int my_sync_dir(const char *dir_name __attribute__((unused)),
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];
@@ -161,10 +195,14 @@ int my_sync_dir_by_file(const char *file_name, myf my_flags)
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)))
+ 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 a2d89c79b4e..146a223a9e3 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* 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
@@ -22,11 +22,10 @@
#include <m_string.h>
#include <signal.h>
-#ifdef THREAD
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open,
THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_myisam, THR_LOCK_heap,
- THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time,
+ THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads,
THR_LOCK_myisam_mmap;
mysql_cond_t THR_COND_threads;
@@ -35,9 +34,6 @@ uint my_thread_end_wait_time= 5;
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
mysql_mutex_t LOCK_localtime_r;
#endif
-#ifndef HAVE_GETHOSTBYNAME_R
-mysql_mutex_t LOCK_gethostbyname_r;
-#endif
#ifdef _MSC_VER
static void install_sigabrt_handler();
#endif
@@ -61,62 +57,40 @@ nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
static uint get_thread_lib(void);
-/** True if @c my_thread_basic_global_init() has been called. */
-static my_bool my_thread_basic_global_init_done= 0;
-
-/**
- Perform a minimal initialisation of mysys, when compiled with threads.
- The initialisation performed is sufficient to:
- - allocate memory
- - perform file operations
- - use charsets
- - use my_errno
- @sa my_basic_init
- @sa my_thread_basic_global_reinit
-*/
-my_bool my_thread_basic_global_init(void)
-{
- int pth_ret;
-
- if (my_thread_basic_global_init_done)
- return 0;
- my_thread_basic_global_init_done= 1;
-
- mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST);
- mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST);
- mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST);
- mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST);
-
- if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
- {
- fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret);
- return 1;
- }
-
- if (my_thread_init())
- return 1;
+/** True if @c my_thread_global_init() has been called. */
+static my_bool my_thread_global_init_done= 0;
- return 0;
-}
/**
- Re-initialize components initialized early with @c my_thread_basic_global_init.
+ Re-initialize components initialized early with @c my_thread_global_init.
Some mutexes were initialized before the instrumentation.
Destroy + create them again, now that the instrumentation
is in place.
This is safe, since this function() is called before creating new threads,
so the mutexes are not in use.
*/
-void my_thread_basic_global_reinit(void)
+void my_thread_global_reinit(void)
{
struct st_my_thread_var *tmp;
- DBUG_ASSERT(my_thread_basic_global_init_done);
+ DBUG_ASSERT(my_thread_global_init_done);
#ifdef HAVE_PSI_INTERFACE
my_init_mysys_psi_keys();
#endif
+ mysql_mutex_destroy(&THR_LOCK_isam);
+ mysql_mutex_init(key_THR_LOCK_isam, &THR_LOCK_isam, MY_MUTEX_INIT_SLOW);
+
+ mysql_mutex_destroy(&THR_LOCK_heap);
+ mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST);
+
+ mysql_mutex_destroy(&THR_LOCK_net);
+ mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST);
+
+ mysql_mutex_destroy(&THR_LOCK_myisam);
+ mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW);
+
mysql_mutex_destroy(&THR_LOCK_malloc);
mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST);
@@ -129,6 +103,9 @@ void my_thread_basic_global_reinit(void)
mysql_mutex_destroy(&THR_LOCK_threads);
mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST);
+ mysql_cond_destroy(&THR_COND_threads);
+ mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL);
+
tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys);
DBUG_ASSERT(tmp);
@@ -152,7 +129,24 @@ void my_thread_basic_global_reinit(void)
my_bool my_thread_global_init(void)
{
- if (my_thread_basic_global_init())
+ int pth_ret;
+
+ if (my_thread_global_init_done)
+ return 0;
+ my_thread_global_init_done= 1;
+
+ if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
+ {
+ fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret);
+ return 1;
+ }
+
+ mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST);
+ mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST);
+
+ if (my_thread_init())
return 1;
thd_lib_detected= get_thread_lib();
@@ -190,26 +184,16 @@ my_bool my_thread_global_init(void)
mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST);
mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST);
- mysql_mutex_init(key_THR_LOCK_time, &THR_LOCK_time, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL);
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
mysql_mutex_init(key_LOCK_localtime_r, &LOCK_localtime_r, MY_MUTEX_INIT_SLOW);
#endif
-#ifndef HAVE_GETHOSTBYNAME_R
- mysql_mutex_init(key_LOCK_gethostbyname_r,
- &LOCK_gethostbyname_r, MY_MUTEX_INIT_SLOW);
-#endif
#ifdef _MSC_VER
install_sigabrt_handler();
#endif
- if (my_thread_init())
- {
- my_thread_global_end(); /* Clean up */
- return 1;
- }
return 0;
}
@@ -253,7 +237,6 @@ void my_thread_global_end(void)
mysql_mutex_destroy(&THR_LOCK_myisam_mmap);
mysql_mutex_destroy(&THR_LOCK_heap);
mysql_mutex_destroy(&THR_LOCK_net);
- mysql_mutex_destroy(&THR_LOCK_time);
mysql_mutex_destroy(&THR_LOCK_charset);
if (all_threads_killed)
{
@@ -263,11 +246,8 @@ void my_thread_global_end(void)
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
mysql_mutex_destroy(&LOCK_localtime_r);
#endif
-#ifndef HAVE_GETHOSTBYNAME_R
- mysql_mutex_destroy(&LOCK_gethostbyname_r);
-#endif
- my_thread_basic_global_init_done= 0;
+ my_thread_global_init_done= 0;
}
static my_thread_id thread_id= 0;
@@ -498,4 +478,3 @@ static void install_sigabrt_handler(void)
}
#endif
-#endif /* THREAD */
diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c
index ad1636011db..58c09e332d6 100644
--- a/mysys/my_wincond.c
+++ b/mysys/my_wincond.c
@@ -24,7 +24,108 @@
#include <process.h>
#include <sys/timeb.h>
-int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
+
+/*
+ Windows native condition variables. We use runtime loading / function
+ pointers, because they are not available on XP
+*/
+
+/* Prototypes and function pointers for condition variable functions */
+typedef VOID (WINAPI * InitializeConditionVariableProc)
+ (PCONDITION_VARIABLE ConditionVariable);
+
+typedef BOOL (WINAPI * SleepConditionVariableCSProc)
+ (PCONDITION_VARIABLE ConditionVariable,
+ PCRITICAL_SECTION CriticalSection,
+ DWORD dwMilliseconds);
+
+typedef VOID (WINAPI * WakeAllConditionVariableProc)
+ (PCONDITION_VARIABLE ConditionVariable);
+
+typedef VOID (WINAPI * WakeConditionVariableProc)
+ (PCONDITION_VARIABLE ConditionVariable);
+
+static InitializeConditionVariableProc my_InitializeConditionVariable;
+static SleepConditionVariableCSProc my_SleepConditionVariableCS;
+static WakeAllConditionVariableProc my_WakeAllConditionVariable;
+static WakeConditionVariableProc my_WakeConditionVariable;
+
+
+/**
+ Indicates if we have native condition variables,
+ initialized first time pthread_cond_init is called.
+*/
+
+static BOOL have_native_conditions= FALSE;
+
+
+/**
+ Check if native conditions can be used, load function pointers
+*/
+
+static void check_native_cond_availability(void)
+{
+ HMODULE module= GetModuleHandle("kernel32");
+
+ my_InitializeConditionVariable= (InitializeConditionVariableProc)
+ GetProcAddress(module, "InitializeConditionVariable");
+ my_SleepConditionVariableCS= (SleepConditionVariableCSProc)
+ GetProcAddress(module, "SleepConditionVariableCS");
+ my_WakeAllConditionVariable= (WakeAllConditionVariableProc)
+ GetProcAddress(module, "WakeAllConditionVariable");
+ my_WakeConditionVariable= (WakeConditionVariableProc)
+ GetProcAddress(module, "WakeConditionVariable");
+
+ if (my_InitializeConditionVariable)
+ have_native_conditions= TRUE;
+}
+
+
+
+/**
+ Convert abstime to milliseconds
+*/
+
+static DWORD get_milliseconds(const struct timespec *abstime)
+{
+ long long millis;
+ union ft64 now;
+
+ if (abstime == NULL)
+ return INFINITE;
+
+ GetSystemTimeAsFileTime(&now.ft);
+
+ /*
+ Calculate time left to abstime
+ - subtract start time from current time(values are in 100ns units)
+ - convert to millisec by dividing with 10000
+ */
+ millis= (abstime->tv.i64 - now.i64) / 10000;
+
+ /* Don't allow the timeout to be negative */
+ if (millis < 0)
+ return 0;
+
+ /*
+ Make sure the calculated timeout does not exceed original timeout
+ value which could cause "wait for ever" if system time changes
+ */
+ if (millis > abstime->max_timeout_msec)
+ millis= abstime->max_timeout_msec;
+
+ if (millis > UINT_MAX)
+ millis= UINT_MAX;
+
+ return (DWORD)millis;
+}
+
+
+/*
+ Old (pre-vista) implementation using events
+*/
+
+static int legacy_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
cond->waiting= 0;
InitializeCriticalSection(&cond->lock_waiting);
@@ -53,7 +154,8 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
return 0;
}
-int pthread_cond_destroy(pthread_cond_t *cond)
+
+static int legacy_cond_destroy(pthread_cond_t *cond)
{
DeleteCriticalSection(&cond->lock_waiting);
@@ -65,48 +167,13 @@ int pthread_cond_destroy(pthread_cond_t *cond)
}
-int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
-{
- return pthread_cond_timedwait(cond,mutex,NULL);
-}
-
-
-int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec *abstime)
{
int result;
- long timeout;
- union ft64 now;
-
- if( abstime != NULL )
- {
- GetSystemTimeAsFileTime(&now.ft);
-
- /*
- Calculate time left to abstime
- - subtract start time from current time(values are in 100ns units)
- - convert to millisec by dividing with 10000
- */
- timeout= (long)((abstime->tv.i64 - now.i64) / 10000);
-
- /* Don't allow the timeout to be negative */
- if (timeout < 0)
- timeout= 0L;
-
- /*
- Make sure the calucated timeout does not exceed original timeout
- value which could cause "wait for ever" if system time changes
- */
- if (timeout > abstime->max_timeout_msec)
- timeout= abstime->max_timeout_msec;
-
- }
- else
- {
- /* No time specified; don't expire */
- timeout= INFINITE;
- }
+ DWORD timeout;
+ timeout= get_milliseconds(abstime);
/*
Block access if previous broadcast hasn't finished.
This is just for safety and should normally not
@@ -142,7 +209,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
}
-int pthread_cond_signal(pthread_cond_t *cond)
+static int legacy_cond_signal(pthread_cond_t *cond)
{
EnterCriticalSection(&cond->lock_waiting);
@@ -155,7 +222,7 @@ int pthread_cond_signal(pthread_cond_t *cond)
}
-int pthread_cond_broadcast(pthread_cond_t *cond)
+static int legacy_cond_broadcast(pthread_cond_t *cond)
{
EnterCriticalSection(&cond->lock_waiting);
/*
@@ -177,6 +244,87 @@ int pthread_cond_broadcast(pthread_cond_t *cond)
}
+/*
+ Posix API functions. Just choose between native and legacy implementation.
+*/
+
+int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
+{
+ /*
+ Once initialization is used here rather than in my_init(), to
+ 1) avoid my_init() pitfalls- undefined order in which initialization should
+ run
+ 2) be potentially useful C++ (in static constructors that run before main())
+ 3) just to simplify the API.
+ Also, the overhead of my_pthread_once is very small.
+ */
+ static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT;
+ my_pthread_once(&once_control, check_native_cond_availability);
+
+ if (have_native_conditions)
+ {
+ my_InitializeConditionVariable(&cond->native_cond);
+ return 0;
+ }
+ else
+ return legacy_cond_init(cond, attr);
+}
+
+
+int pthread_cond_destroy(pthread_cond_t *cond)
+{
+ if (have_native_conditions)
+ return 0; /* no destroy function */
+ else
+ return legacy_cond_destroy(cond);
+}
+
+
+int pthread_cond_broadcast(pthread_cond_t *cond)
+{
+ if (have_native_conditions)
+ {
+ my_WakeAllConditionVariable(&cond->native_cond);
+ return 0;
+ }
+ else
+ return legacy_cond_broadcast(cond);
+}
+
+
+int pthread_cond_signal(pthread_cond_t *cond)
+{
+ if (have_native_conditions)
+ {
+ my_WakeConditionVariable(&cond->native_cond);
+ return 0;
+ }
+ else
+ return legacy_cond_signal(cond);
+}
+
+
+int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ struct timespec *abstime)
+{
+ if (have_native_conditions)
+ {
+ DWORD timeout= get_milliseconds(abstime);
+ if (!my_SleepConditionVariableCS(&cond->native_cond, mutex, timeout))
+ return ETIMEDOUT;
+ return 0;
+ }
+ else
+ return legacy_cond_timedwait(cond, mutex, abstime);
+}
+
+
+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+ return pthread_cond_timedwait(cond, mutex, NULL);
+}
+
+
int pthread_attr_init(pthread_attr_t *connect_att)
{
connect_att->dwStackSize = 0;
diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c
index 6c0b191ca2c..4d80d774dad 100644
--- a/mysys/my_winfile.c
+++ b/mysys/my_winfile.c
@@ -97,7 +97,7 @@ HANDLE my_get_osfhandle(File fd)
static int my_get_open_flags(File fd)
{
- DBUG_ENTER("my_get_osfhandle");
+ DBUG_ENTER("my_get_open_flags");
DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit);
DBUG_RETURN(my_file_info[fd].oflag);
}
@@ -321,7 +321,7 @@ size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset)
if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
DBUG_RETURN(0); /*return 0 at EOF*/
my_osmaperr(lastError);
- DBUG_RETURN(-1);
+ DBUG_RETURN((size_t)-1);
}
DBUG_RETURN(nBytesRead);
}
@@ -352,7 +352,7 @@ size_t my_win_read(File Filedes, uchar *Buffer, size_t Count)
if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE)
DBUG_RETURN(0); /*return 0 at EOF*/
my_osmaperr(lastError);
- DBUG_RETURN(-1);
+ DBUG_RETURN((size_t)-1);
}
DBUG_RETURN(nBytesRead);
}
@@ -386,7 +386,7 @@ size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count,
if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov))
{
my_osmaperr(GetLastError());
- DBUG_RETURN(-1);
+ DBUG_RETURN((size_t)-1);
}
else
DBUG_RETURN(nBytesWritten);
@@ -427,6 +427,15 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count)
DBUG_ENTER("my_win_write");
DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer,
(ulonglong)Count));
+
+ if(!Count)
+ DBUG_RETURN(0);
+
+#ifdef _WIN64
+ if(Count > UINT_MAX)
+ Count= UINT_MAX;
+#endif
+
if(my_get_open_flags(fd) & _O_APPEND)
{
/*
@@ -442,10 +451,10 @@ size_t my_win_write(File fd, const uchar *Buffer, size_t Count)
hFile= my_get_osfhandle(fd);
if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov))
{
- nWritten= (size_t)-1;
my_osmaperr(GetLastError());
+ DBUG_RETURN((size_t)-1);
}
- DBUG_RETURN((size_t)nWritten);
+ DBUG_RETURN(nWritten);
}
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index 19d4a707062..54b8463fe0b 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -156,8 +156,19 @@ int pthread_cancel(pthread_t thread)
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);
+ LONG state;
+
+ /*
+ Do "dirty" read to find out if initialization is already done, to
+ save an interlocked operation in common case. Memory barriers are ensured by
+ Visual C++ volatile implementation.
+ */
+ if (*once_control == MY_PTHREAD_ONCE_DONE)
+ return 0;
+
+ state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS,
+ MY_PTHREAD_ONCE_INIT);
+
switch(state)
{
case MY_PTHREAD_ONCE_INIT:
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 3eac1364f46..64f7546620f 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -52,10 +52,9 @@ size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
DBUG_PRINT("error",("Write only %ld bytes, error: %d",
(long) writtenbytes, my_errno));
#ifndef NO_BACKGROUND
-#ifdef THREAD
if (my_thread_var->abort)
MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */
-#endif
+
if ((my_errno == ENOSPC || my_errno == EDQUOT) &&
(MyFlags & MY_WAIT_IF_FULL))
{
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 772e0346016..af7939376a6 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -24,7 +24,6 @@
#include <sys/resource.h>
#endif
-#ifdef THREAD
#include <my_pthread.h>
#ifdef HAVE_PSI_INTERFACE
@@ -37,16 +36,12 @@ extern PSI_mutex_key key_my_file_info_mutex;
extern PSI_mutex_key key_LOCK_localtime_r;
#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */
-#ifndef HAVE_GETHOSTBYNAME_R
-extern PSI_mutex_key key_LOCK_gethostbyname_r;
-#endif /* HAVE_GETHOSTBYNAME_R */
-
extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock,
key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm,
key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap,
key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc,
key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net,
- key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time,
+ key_THR_LOCK_open, key_THR_LOCK_threads,
key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap;
extern PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond,
@@ -61,10 +56,7 @@ extern PSI_thread_key key_thread_alarm;
extern mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache;
extern mysql_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net;
-extern mysql_mutex_t THR_LOCK_charset, THR_LOCK_time;
-#else /* THREAD */
-#include <my_no_pthread.h>
-#endif /* THREAD */
+extern mysql_mutex_t THR_LOCK_charset;
#include <mysql/psi/mysql_file.h>
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 2005e3eb2b7..dcafe13291d 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -22,7 +22,7 @@
#include "mysys_priv.h"
#include <myisampack.h>
-#ifdef TARGET_OS_SOLARIS
+#ifdef __sun
/*
* On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N
* functions, as memcmp() is usually a platform-specific implementation
@@ -39,22 +39,25 @@ static int native_compare(size_t *length, unsigned char **a, unsigned char **b)
return memcmp(*a, *b, *length);
}
-#else /* TARGET_OS_SOLARIS */
+#else /* __sun */
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);
-#endif /* TARGET_OS_SOLARIS */
+#endif /* __sun */
/* Get a pointer to a optimal byte-compare function for a given size */
-qsort2_cmp get_ptr_compare (size_t size)
+#ifdef __sun
+qsort2_cmp get_ptr_compare (size_t size __attribute__((unused)))
{
-#ifdef TARGET_OS_SOLARIS
return (qsort2_cmp) native_compare;
+}
#else
+qsort2_cmp get_ptr_compare (size_t size)
+{
if (size < 4)
return (qsort2_cmp) ptr_compare;
switch (size & 3) {
@@ -64,8 +67,8 @@ qsort2_cmp get_ptr_compare (size_t size)
case 3: return (qsort2_cmp) ptr_compare_3;
}
return 0; /* Impossible */
-#endif /* TARGET_OS_SOLARIS */
}
+#endif /* __sun */
/*
@@ -75,6 +78,8 @@ qsort2_cmp get_ptr_compare (size_t size)
#define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N]
+#ifndef __sun
+
static int ptr_compare(size_t *compare_length, uchar **a, uchar **b)
{
reg3 int length= *compare_length;
@@ -177,6 +182,8 @@ static int ptr_compare_3(size_t *compare_length,uchar **a, uchar **b)
return (0);
}
+#endif /* !__sun */
+
void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos)
{
switch (pack_length) {
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index ba62062ebc0..e4999dbbe81 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -24,6 +24,11 @@
#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
@@ -43,10 +48,99 @@ void my_init_stacktrace()
#endif
}
-void my_safe_print_str(const char* name, const char* val, int max_len)
+#ifdef __linux__
+
+static void print_buffer(char *buffer, size_t count)
+{
+ for (; count && *buffer; --count)
+ {
+ int c= (int) *buffer++;
+ fputc(isprint(c) ? c : ' ', stderr);
+ }
+}
+
+/**
+ 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)
{
- char *heap_end= (char*) sbrk(0);
- fprintf(stderr, "%s at %p ", name, val);
+ 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)
+ fputc('\n', stderr);
+
+ if (nbytes == -1)
+ fprintf(stderr, "Can't read from address %p: %m.\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))
{
@@ -54,7 +148,6 @@ void my_safe_print_str(const char* name, const char* val, int max_len)
return;
}
- fprintf(stderr, "= ");
for (; max_len && PTR_SANE(val) && *val; --max_len)
fputc(*val++, stderr);
fputc('\n', stderr);
@@ -315,6 +408,9 @@ end:
/* 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
/*
@@ -322,7 +418,6 @@ void my_write_core(int sig)
information from this process, causing gcov output to be incomplete.
So we force the writing of coverage information here before terminating.
*/
- extern void __gcov_flush(void);
__gcov_flush();
#endif
pthread_kill(pthread_self(), sig);
@@ -605,16 +700,15 @@ void my_write_core(int unused)
}
-void my_safe_print_str(const char *name, const char *val, int len)
+void my_safe_print_str(const char *val, int len)
{
- fprintf(stderr,"%s at %p", name, val);
- __try
+ __try
{
- fprintf(stderr,"=%.*s\n", len, val);
+ fprintf(stderr, "%.*s\n", len, val);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
- fprintf(stderr,"is an invalid string pointer\n");
+ fprintf(stderr, "is an invalid string pointer\n");
}
}
#endif /*__WIN__*/
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 9742861db08..725b32fa4a6 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -18,7 +18,7 @@
#include "mysys_priv.h"
#include <my_global.h>
-#if defined(THREAD) && !defined(DONT_USE_THR_ALARM)
+#if !defined(DONT_USE_THR_ALARM)
#include <errno.h>
#include <my_pthread.h>
#include <signal.h>
@@ -674,15 +674,14 @@ void resize_thr_alarm(uint max_alarms)
#endif /* __WIN__ */
-#endif /* THREAD */
-
+#endif
/****************************************************************************
Handling of test case (when compiled with -DMAIN)
***************************************************************************/
#ifdef MAIN
-#if defined(THREAD) && !defined(DONT_USE_THR_ALARM)
+#if !defined(DONT_USE_THR_ALARM)
static mysql_cond_t COND_thread_count;
static mysql_mutex_t LOCK_thread_count;
@@ -936,17 +935,13 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
return 0;
}
-#else /* THREAD */
+#else /* !defined(DONT_USE_ALARM_THREAD) */
int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
{
-#ifndef THREAD
- printf("thr_alarm disabled because we are not using threads\n");
-#else
printf("thr_alarm disabled with DONT_USE_THR_ALARM\n");
-#endif
exit(1);
}
-#endif /* THREAD */
+#endif /* !defined(DONT_USE_ALARM_THREAD) */
#endif /* MAIN */
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index b22823ae33e..8034e6d30a8 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -85,7 +85,6 @@ be any number of TL_WRITE_CONCURRENT_INSERT locks aktive at the same time.
#include "mysys_priv.h"
-#ifdef THREAD
#include "thr_lock.h"
#include <m_string.h>
#include <errno.h>
@@ -1515,7 +1514,6 @@ void thr_print_locks(void)
mysql_mutex_unlock(&THR_LOCK_lock);
}
-#endif /* THREAD */
/*****************************************************************************
** Test of thread locks
@@ -1523,8 +1521,6 @@ void thr_print_locks(void)
#ifdef MAIN
-#ifdef THREAD
-
struct st_test {
uint lock_nr;
enum thr_lock_type lock_type;
@@ -1754,13 +1750,4 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
return 0;
}
-#else /* THREAD */
-
-int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
-{
- printf("thr_lock disabled because we are not using threads\n");
- exit(1);
-}
-
-#endif /* THREAD */
#endif /* MAIN */
diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c
index b5548662679..fdc25b67049 100644
--- a/mysys/thr_mutex.c
+++ b/mysys/thr_mutex.c
@@ -19,12 +19,12 @@
#if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98)
#define __USE_UNIX98 /* To get rw locks under Linux */
#endif
+
#ifdef SAFE_MUTEX
#define SAFE_MUTEX_DEFINED
+#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
#endif
-#if defined(THREAD)
-#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
#include "mysys_priv.h"
#include "my_static.h"
#include <m_string.h>
@@ -525,7 +525,7 @@ 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 struct timespec *abstime,
const char *file, uint line)
{
int error;
@@ -929,4 +929,3 @@ void fastmutex_global_init(void)
}
#endif /* defined(MY_PTHREAD_FASTMUTEX) */
-#endif /* THREAD */
diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c
index ecd12849822..bad80b43eef 100644
--- a/mysys/thr_rwlock.c
+++ b/mysys/thr_rwlock.c
@@ -16,10 +16,122 @@
/* Synchronization - readers / writer thread locks */
#include "mysys_priv.h"
-#if defined(THREAD)
#if defined(NEED_MY_RW_LOCK)
#include <errno.h>
+#ifdef _WIN32
+
+static BOOL have_srwlock= FALSE;
+/* Prototypes and function pointers for windows functions */
+typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock);
+typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock);
+
+static srw_func my_InitializeSRWLock;
+static srw_func my_AcquireSRWLockExclusive;
+static srw_func my_ReleaseSRWLockExclusive;
+static srw_func my_AcquireSRWLockShared;
+static srw_func my_ReleaseSRWLockShared;
+
+static srw_bool_func my_TryAcquireSRWLockExclusive;
+static srw_bool_func my_TryAcquireSRWLockShared;
+
+/**
+ Check for presence of Windows slim reader writer lock function.
+ Load function pointers.
+*/
+
+static void check_srwlock_availability(void)
+{
+ HMODULE module= GetModuleHandle("kernel32");
+
+ my_InitializeSRWLock= (srw_func) GetProcAddress(module,
+ "InitializeSRWLock");
+ my_AcquireSRWLockExclusive= (srw_func) GetProcAddress(module,
+ "AcquireSRWLockExclusive");
+ my_AcquireSRWLockShared= (srw_func) GetProcAddress(module,
+ "AcquireSRWLockShared");
+ my_ReleaseSRWLockExclusive= (srw_func) GetProcAddress(module,
+ "ReleaseSRWLockExclusive");
+ my_ReleaseSRWLockShared= (srw_func) GetProcAddress(module,
+ "ReleaseSRWLockShared");
+ my_TryAcquireSRWLockExclusive= (srw_bool_func) GetProcAddress(module,
+ "TryAcquireSRWLockExclusive");
+ my_TryAcquireSRWLockShared= (srw_bool_func) GetProcAddress(module,
+ "TryAcquireSRWLockShared");
+
+ /*
+ We currently require TryAcquireSRWLockExclusive. This API is missing on
+ Vista, this means SRWLock are only used starting with Win7.
+
+ If "trylock" usage for rwlocks is eliminated from server codebase (it is used
+ in a single place currently, in query cache), then SRWLock can be enabled on
+ Vista too. In this case condition below needs to be changed to e.g check
+ for my_InitializeSRWLock.
+ */
+
+ if (my_TryAcquireSRWLockExclusive)
+ have_srwlock= TRUE;
+
+}
+
+
+static int srw_init(my_rw_lock_t *rwp)
+{
+ my_InitializeSRWLock(&rwp->srwlock);
+ rwp->have_exclusive_srwlock = FALSE;
+ return 0;
+}
+
+
+static int srw_rdlock(my_rw_lock_t *rwp)
+{
+ my_AcquireSRWLockShared(&rwp->srwlock);
+ return 0;
+}
+
+
+static int srw_tryrdlock(my_rw_lock_t *rwp)
+{
+
+ if (!my_TryAcquireSRWLockShared(&rwp->srwlock))
+ return EBUSY;
+ return 0;
+}
+
+
+static int srw_wrlock(my_rw_lock_t *rwp)
+{
+ my_AcquireSRWLockExclusive(&rwp->srwlock);
+ rwp->have_exclusive_srwlock= TRUE;
+ return 0;
+}
+
+
+static int srw_trywrlock(my_rw_lock_t *rwp)
+{
+ if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock))
+ return EBUSY;
+ rwp->have_exclusive_srwlock= TRUE;
+ return 0;
+}
+
+
+static int srw_unlock(my_rw_lock_t *rwp)
+{
+ if (rwp->have_exclusive_srwlock)
+ {
+ rwp->have_exclusive_srwlock= FALSE;
+ my_ReleaseSRWLockExclusive(&rwp->srwlock);
+ }
+ else
+ {
+ my_ReleaseSRWLockShared(&rwp->srwlock);
+ }
+ return 0;
+}
+
+#endif /*_WIN32 */
+
/*
Source base from Sun Microsystems SPILT, simplified for MySQL use
-- Joshua Chamas
@@ -59,10 +171,26 @@
* Mountain View, California 94043
*/
-int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
+int my_rw_init(my_rw_lock_t *rwp)
{
pthread_condattr_t cond_attr;
+#ifdef _WIN32
+ /*
+ Once initialization is used here rather than in my_init(), in order to
+ - avoid my_init() pitfalls- (undefined order in which initialization should
+ run)
+ - be potentially useful C++ (static constructors)
+ - just to simplify the API.
+ Also, the overhead is of my_pthread_once is very small.
+ */
+ static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT;
+ my_pthread_once(&once_control, check_srwlock_availability);
+
+ if (have_srwlock)
+ return srw_init(rwp);
+#endif
+
pthread_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST);
pthread_condattr_init( &cond_attr );
pthread_cond_init( &rwp->readers, &cond_attr );
@@ -74,8 +202,6 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
#ifdef SAFE_MUTEX
rwp->write_thread = 0;
#endif
- /* If attribute argument is NULL use default value - prefer writers. */
- rwp->prefer_readers= prefer_readers_attr ? *prefer_readers_attr : FALSE;
return(0);
}
@@ -83,6 +209,10 @@ int my_rw_init(my_rw_lock_t *rwp, my_bool *prefer_readers_attr)
int my_rw_destroy(my_rw_lock_t *rwp)
{
+#ifdef _WIN32
+ if (have_srwlock)
+ return 0; /* no destroy function */
+#endif
DBUG_ASSERT(rwp->state == 0);
pthread_mutex_destroy( &rwp->lock );
pthread_cond_destroy( &rwp->readers );
@@ -93,11 +223,15 @@ int my_rw_destroy(my_rw_lock_t *rwp)
int my_rw_rdlock(my_rw_lock_t *rwp)
{
+#ifdef _WIN32
+ if (have_srwlock)
+ return srw_rdlock(rwp);
+#endif
+
pthread_mutex_lock(&rwp->lock);
/* active or queued writers */
- while (( rwp->state < 0 ) ||
- (rwp->waiters && ! rwp->prefer_readers))
+ while (( rwp->state < 0 ) || rwp->waiters)
pthread_cond_wait( &rwp->readers, &rwp->lock);
rwp->state++;
@@ -108,9 +242,14 @@ int my_rw_rdlock(my_rw_lock_t *rwp)
int my_rw_tryrdlock(my_rw_lock_t *rwp)
{
int res;
+
+#ifdef _WIN32
+ if (have_srwlock)
+ return srw_tryrdlock(rwp);
+#endif
+
pthread_mutex_lock(&rwp->lock);
- if ((rwp->state < 0 ) ||
- (rwp->waiters && ! rwp->prefer_readers))
+ if ((rwp->state < 0 ) || rwp->waiters)
res= EBUSY; /* Can't get lock */
else
{
@@ -124,6 +263,11 @@ int my_rw_tryrdlock(my_rw_lock_t *rwp)
int my_rw_wrlock(my_rw_lock_t *rwp)
{
+#ifdef _WIN32
+ if (have_srwlock)
+ return srw_wrlock(rwp);
+#endif
+
pthread_mutex_lock(&rwp->lock);
rwp->waiters++; /* another writer queued */
@@ -144,6 +288,12 @@ int my_rw_wrlock(my_rw_lock_t *rwp)
int my_rw_trywrlock(my_rw_lock_t *rwp)
{
int res;
+
+#ifdef _WIN32
+ if (have_srwlock)
+ return srw_trywrlock(rwp);
+#endif
+
pthread_mutex_lock(&rwp->lock);
if (rwp->state)
res= EBUSY; /* Can't get lock */
@@ -162,6 +312,11 @@ int my_rw_trywrlock(my_rw_lock_t *rwp)
int my_rw_unlock(my_rw_lock_t *rwp)
{
+#ifdef _WIN32
+ if (have_srwlock)
+ return srw_unlock(rwp);
+#endif
+
DBUG_PRINT("rw_unlock",
("state: %d waiters: %d", rwp->state, rwp->waiters));
pthread_mutex_lock(&rwp->lock);
@@ -192,30 +347,126 @@ int my_rw_unlock(my_rw_lock_t *rwp)
return(0);
}
+#endif /* defined(NEED_MY_RW_LOCK) */
+
-int rw_pr_init(struct st_my_rw_lock_t *rwlock)
+int rw_pr_init(rw_pr_lock_t *rwlock)
{
- my_bool prefer_readers_attr= TRUE;
- return my_rw_init(rwlock, &prefer_readers_attr);
+ pthread_mutex_init(&rwlock->lock, NULL);
+ pthread_cond_init(&rwlock->no_active_readers, NULL);
+ rwlock->active_readers= 0;
+ rwlock->writers_waiting_readers= 0;
+ rwlock->active_writer= FALSE;
+#ifdef SAFE_MUTEX
+ rwlock->writer_thread= 0;
+#endif
+ return 0;
}
-#else
-/*
- We are on system which has native read/write locks which support
- preferring of readers.
-*/
+int rw_pr_destroy(rw_pr_lock_t *rwlock)
+{
+ pthread_cond_destroy(&rwlock->no_active_readers);
+ pthread_mutex_destroy(&rwlock->lock);
+ return 0;
+}
-int rw_pr_init(rw_pr_lock_t *rwlock)
+
+int rw_pr_rdlock(rw_pr_lock_t *rwlock)
+{
+ pthread_mutex_lock(&rwlock->lock);
+ /*
+ The fact that we were able to acquire 'lock' mutex means
+ that there are no active writers and we can acquire rd-lock.
+ Increment active readers counter to prevent requests for
+ wr-lock from succeeding and unlock mutex.
+ */
+ rwlock->active_readers++;
+ pthread_mutex_unlock(&rwlock->lock);
+ return 0;
+}
+
+
+int rw_pr_wrlock(rw_pr_lock_t *rwlock)
{
- pthread_rwlockattr_t rwlock_attr;
+ pthread_mutex_lock(&rwlock->lock);
+
+ if (rwlock->active_readers != 0)
+ {
+ /* There are active readers. We have to wait until they are gone. */
+ rwlock->writers_waiting_readers++;
+
+ while (rwlock->active_readers != 0)
+ pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock);
- pthread_rwlockattr_init(&rwlock_attr);
- pthread_rwlockattr_setkind_np(&rwlock_attr, PTHREAD_RWLOCK_PREFER_READER_NP);
- pthread_rwlock_init(rwlock, NULL);
- pthread_rwlockattr_destroy(&rwlock_attr);
+ rwlock->writers_waiting_readers--;
+ }
+
+ /*
+ We own 'lock' mutex so there is no active writers.
+ Also there are no active readers.
+ This means that we can grant wr-lock.
+ Not releasing 'lock' mutex until unlock will block
+ both requests for rd and wr-locks.
+ Set 'active_writer' flag to simplify unlock.
+
+ Thanks to the fact wr-lock/unlock in the absence of
+ contention from readers is essentially mutex lock/unlock
+ with a few simple checks make this rwlock implementation
+ wr-lock optimized.
+ */
+ rwlock->active_writer= TRUE;
+#ifdef SAFE_MUTEX
+ rwlock->writer_thread= pthread_self();
+#endif
return 0;
}
-#endif /* defined(NEED_MY_RW_LOCK) */
-#endif /* defined(THREAD) */
+
+int rw_pr_unlock(rw_pr_lock_t *rwlock)
+{
+ if (rwlock->active_writer)
+ {
+ /* We are unlocking wr-lock. */
+#ifdef SAFE_MUTEX
+ rwlock->writer_thread= 0;
+#endif
+ rwlock->active_writer= FALSE;
+ if (rwlock->writers_waiting_readers)
+ {
+ /*
+ Avoid expensive cond signal in case when there is no contention
+ or it is wr-only.
+
+ Note that from view point of performance it would be better to
+ signal on the condition variable after unlocking mutex (as it
+ reduces number of contex switches).
+
+ Unfortunately this would mean that such rwlock can't be safely
+ used by MDL subsystem, which relies on the fact that it is OK
+ to destroy rwlock once it is in unlocked state.
+ */
+ pthread_cond_signal(&rwlock->no_active_readers);
+ }
+ pthread_mutex_unlock(&rwlock->lock);
+ }
+ else
+ {
+ /* We are unlocking rd-lock. */
+ pthread_mutex_lock(&rwlock->lock);
+ rwlock->active_readers--;
+ if (rwlock->active_readers == 0 &&
+ rwlock->writers_waiting_readers)
+ {
+ /*
+ If we are last reader and there are waiting
+ writers wake them up.
+ */
+ pthread_cond_signal(&rwlock->no_active_readers);
+ }
+ pthread_mutex_unlock(&rwlock->lock);
+ }
+ return 0;
+}
+
+
diff --git a/mysys/typelib.c b/mysys/typelib.c
index aec203becc0..463d3ba53a5 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.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
@@ -27,7 +27,7 @@ int find_type_with_warning(const char *x, TYPELIB *typelib, const char *option)
int res;
const char **ptr;
- if ((res= find_type((char *) x, typelib, 2)) <= 0)
+ if ((res= find_type((char *) x, typelib, FIND_TYPE_BASIC)) <= 0)
{
ptr= typelib->type_names;
if (!*x)
@@ -56,16 +56,13 @@ uint find_type_or_exit(const char *x, TYPELIB *typelib, const char *option)
Search after a string in a list of strings. Endspace in x is not compared.
@param x String to find
- @param lib TYPELIB (struct of pointer to values + count)
- @param full_name bitmap of what to do
- 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
-
- @note
- If part, uniq field is found and full_name == 0 then x is expanded
- to full field.
+ @param typelib TYPELIB (struct of pointer to values + count)
+ @param flags flags to tune behaviour: a combination of
+ FIND_TYPE_NO_PREFIX
+ FIND_TYPE_ALLOW_NUMBER
+ FIND_TYPE_COMMA_TERM.
+ FIND_TYPE_NO_OVERWRITE can be passed but is
+ superfluous (is always implicitely on).
@retval
-1 Too many matching values
@@ -76,15 +73,17 @@ uint find_type_or_exit(const char *x, TYPELIB *typelib, const char *option)
*/
-int find_type(char *x, const TYPELIB *typelib, uint full_name)
+int find_type(const char *x, const TYPELIB *typelib, uint flags)
{
int find,pos;
int UNINIT_VAR(findpos); /* guarded by find */
- reg1 char * i;
- reg2 const char *j;
+ const char *i;
+ const char *j;
DBUG_ENTER("find_type");
DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib));
+ DBUG_ASSERT(!(flags & ~(FIND_TYPE_NO_PREFIX | FIND_TYPE_ALLOW_NUMBER |
+ FIND_TYPE_NO_OVERWRITE | FIND_TYPE_COMMA_TERM)));
if (!typelib->count)
{
DBUG_PRINT("exit",("no count"));
@@ -94,24 +93,26 @@ int find_type(char *x, const TYPELIB *typelib, uint full_name)
for (pos=0 ; (j=typelib->type_names[pos]) ; pos++)
{
for (i=x ;
- *i && (!(full_name & 8) || !is_field_separator(*i)) &&
+ *i && (!(flags & FIND_TYPE_COMMA_TERM) || !is_field_separator(*i)) &&
my_toupper(&my_charset_latin1,*i) ==
my_toupper(&my_charset_latin1,*j) ; i++, j++) ;
if (! *j)
{
while (*i == ' ')
i++; /* skip_end_space */
- if (! *i || ((full_name & 8) && is_field_separator(*i)))
+ if (! *i || ((flags & FIND_TYPE_COMMA_TERM) && is_field_separator(*i)))
DBUG_RETURN(pos+1);
}
- if ((!*i && (!(full_name & 8) || !is_field_separator(*i))) &&
- (!*j || !(full_name & 1)))
+ if ((!*i &&
+ (!(flags & FIND_TYPE_COMMA_TERM) || !is_field_separator(*i))) &&
+ (!*j || !(flags & FIND_TYPE_NO_PREFIX)))
{
find++;
findpos=pos;
}
}
- if (find == 0 && (full_name & 4) && x[0] == '#' && strend(x)[-1] == '#' &&
+ if (find == 0 && (flags & FIND_TYPE_ALLOW_NUMBER) && x[0] == '#' &&
+ strend(x)[-1] == '#' &&
(findpos=atoi(x+1)-1) >= 0 && (uint) findpos < typelib->count)
find=1;
else if (find == 0 || ! x[0])
@@ -119,13 +120,11 @@ int find_type(char *x, const TYPELIB *typelib, uint full_name)
DBUG_PRINT("exit",("Couldn't find type"));
DBUG_RETURN(0);
}
- else if (find != 1 || (full_name & 1))
+ else if (find != 1 || (flags & FIND_TYPE_NO_PREFIX))
{
DBUG_PRINT("exit",("Too many possybilities"));
DBUG_RETURN(-1);
}
- if (!(full_name & 2))
- (void) strmov(x,typelib->type_names[findpos]);
DBUG_RETURN(findpos+1);
} /* find_type */
@@ -200,7 +199,7 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err)
x++;
if (x[0] && x[1]) /* skip separator if found */
x++;
- if ((find= find_type(i, lib, 2 | 8) - 1) < 0)
+ if ((find= find_type(i, lib, FIND_TYPE_COMMA_TERM) - 1) < 0)
DBUG_RETURN(0);
result|= (ULL(1) << find);
}
@@ -284,7 +283,7 @@ static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1,
static uint parse_name(const TYPELIB *lib, const char **strpos, const char *end)
{
const char *pos= *strpos;
- uint find= find_type((char*)pos, lib, 8);
+ uint find= find_type(pos, lib, FIND_TYPE_COMMA_TERM);
for (; pos != end && *pos != '=' && *pos !=',' ; pos++);
*strpos= pos;
return find;