summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rwxr-xr-xmysys/CMakeLists.txt2
-rw-r--r--mysys/Makefile.am2
-rw-r--r--mysys/default.c176
-rw-r--r--mysys/mf_arr_appstr.c61
-rw-r--r--mysys/mf_keycache.c2
-rw-r--r--mysys/mf_qsort.c4
-rw-r--r--mysys/mf_sort.c4
-rw-r--r--mysys/my_delete.c10
-rw-r--r--mysys/my_getopt.c159
-rw-r--r--mysys/my_lib.c4
-rw-r--r--mysys/my_write.c4
-rw-r--r--mysys/queues.c38
-rw-r--r--mysys/thr_lock.c33
13 files changed, 361 insertions, 138 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
index 6b24165686a..60e75c96b75 100755
--- a/mysys/CMakeLists.txt
+++ b/mysys/CMakeLists.txt
@@ -29,7 +29,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c
mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c
mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c
- mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_tempdir.c
+ mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_arr_appstr.c mf_tempdir.c
mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c
my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c
my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index fca13ab52b8..f06d81da849 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -35,7 +35,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
my_error.c errors.c my_div.c my_messnc.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
- mf_pack.c mf_unixpath.c mf_strip.c \
+ mf_pack.c mf_unixpath.c mf_strip.c mf_arr_appstr.c \
mf_wcomp.c mf_wfile.c my_gethwaddr.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c my_getncpus.c \
diff --git a/mysys/default.c b/mysys/default.c
index 3cc5b08e77c..2758029ec12 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -47,7 +47,7 @@ char *my_defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
-#define MAX_DEFAULT_DIRS 7
+#define MAX_DEFAULT_DIRS 6
const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
@@ -83,7 +83,22 @@ static int search_default_file_with_ext(Process_option_func func,
void *func_ctx,
const char *dir, const char *ext,
const char *config_file, int recursion_level);
-static void init_default_directories();
+
+
+
+/**
+ Create the list of default directories.
+
+ @details
+ On all systems, if a directory is already in the list, it will be moved
+ to the end of the list. This avoids reading defaults files multiple times,
+ while ensuring the correct precedence.
+
+ @return void
+*/
+
+static void (*init_default_directories)();
+
static char *remove_end_comment(char *ptr);
@@ -922,6 +937,34 @@ void print_defaults(const char *conf_file, const char **groups)
#include <help_end.h>
+/*
+ This extra complexity is to avoid declaring 'rc' if it won't be
+ used.
+*/
+#define ADD_DIRECTORY_INTERNAL(DIR) \
+ array_append_string_unique((DIR), default_directories, \
+ array_elements(default_directories))
+#ifdef DBUG_OFF
+# define ADD_DIRECTORY(DIR) (void) ADD_DIRECTORY_INTERNAL(DIR)
+#else
+#define ADD_DIRECTORY(DIR) \
+ do { \
+ my_bool rc= ADD_DIRECTORY_INTERNAL(DIR); \
+ DBUG_ASSERT(rc == FALSE); /* Success */ \
+ } while (0)
+#endif
+
+
+#define ADD_COMMON_DIRECTORIES() \
+ do { \
+ char *env; \
+ if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
+ ADD_DIRECTORY(env); \
+ /* Placeholder for --defaults-extra-file=<path> */ \
+ ADD_DIRECTORY(""); \
+ } while (0)
+
+
#ifdef __WIN__
/*
This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
@@ -956,71 +999,33 @@ static size_t my_get_system_windows_directory(char *buffer, size_t size)
}
return count;
}
-#endif
-/*
- Create the list of default directories.
+/**
+ Initialize default directories for Microsoft Windows
- On Microsoft Windows, this is:
- 1. C:/
+ @details
+ 1. GetSystemWindowsDirectory()
2. GetWindowsDirectory()
- 3. GetSystemWindowsDirectory()
- 4. getenv(DEFAULT_HOME_ENV)
- 5. Directory above where the executable is located
- 6. ""
- 7. --sysconfdir=<path>
-
- On Novell NetWare, this is:
- 1. sys:/etc/
- 2. getenv(DEFAULT_HOME_ENV)
- 3. ""
- 4. --sysconfdir=<path>
-
- On OS/2, this is:
- 1. getenv(ETC)
- 2. /etc/
- 3. getenv(DEFAULT_HOME_ENV)
- 4. ""
- 5. "~/"
- 6. --sysconfdir=<path>
-
- Everywhere else, this is:
- 1. /etc/
- 2. /etc/mysql/
- 3. getenv(DEFAULT_HOME_ENV)
- 4. ""
- 5. "~/"
- 6. --sysconfdir=<path>
-
- */
+ 3. C:/
+ 4. Directory above where the executable is located
+ 5. getenv(DEFAULT_HOME_ENV)
+ 6. --defaults-extra-file=<path> (run-time option)
+*/
-static void init_default_directories()
+static void init_default_directories_win()
{
- const char *env, **ptr= default_directories;
+ bzero((char *) default_directories, sizeof(default_directories));
-#ifdef __WIN__
- *ptr++= "C:/";
+ if (my_get_system_windows_directory(shared_system_dir,
+ sizeof(shared_system_dir)))
+ ADD_DIRECTORY(shared_system_dir);
if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
- *ptr++= (char*)&system_dir;
- if (my_get_system_windows_directory(shared_system_dir,
- sizeof(shared_system_dir)) &&
- strcmp(system_dir, shared_system_dir))
- *ptr++= (char *)&shared_system_dir;
+ ADD_DIRECTORY(system_dir);
+
+ ADD_DIRECTORY("C:/");
-#elif defined(__NETWARE__)
- *ptr++= "sys:/etc/";
-#else
- *ptr++= "/etc/";
- *ptr++= "/etc/mysql/";
-#endif
- if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
- *ptr++= env;
- *ptr++= ""; /* Place for defaults_extra_file */
-#if !defined(__WIN__) && !defined(__NETWARE__)
- *ptr++= "~/";;
-#elif defined(__WIN__)
if (GetModuleFileName(NULL, config_dir, sizeof(config_dir)))
{
char *last= NULL, *end= strend(config_dir);
@@ -1050,12 +1055,61 @@ static void init_default_directories()
last= end;
}
}
- *ptr++= (char *)&config_dir;
+ ADD_DIRECTORY(config_dir);
}
-#endif
+
+ ADD_COMMON_DIRECTORIES();
+}
+
+static void (*init_default_directories)()= init_default_directories_win;
+
+#elif defined(__NETWARE__)
+
+/**
+ Initialize default directories for Novell Netware
+
+ @details
+ 1. sys:/etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. --defaults-extra-file=<path> (run-time option)
+*/
+
+static void init_default_directories_netware()
+{
+ bzero((char *) default_directories, sizeof(default_directories));
+ ADD_DIRECTORY("sys:/etc/");
+ ADD_COMMON_DIRECTORIES();
+}
+
+static void (*init_default_directories)()= init_default_directories_netware;
+
+#else
+
+/**
+ Initialize default directories for Unix
+
+ @details
+ 1. /etc/
+ 2. /etc/mysql/
+ 3. --sysconfdir=<path> (compile-time option)
+ 4. getenv(DEFAULT_HOME_ENV)
+ 5. --defaults-extra-file=<path> (run-time option)
+ 6. "~/"
+*/
+
+static void init_default_directories_unix()
+{
+ bzero((char *) default_directories, sizeof(default_directories));
+ ADD_DIRECTORY("/etc/");
+ ADD_DIRECTORY("/etc/mysql/");
#ifdef DEFAULT_SYSCONFDIR
if (DEFAULT_SYSCONFDIR != "")
- *ptr++= DEFAULT_SYSCONFDIR;
+ ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
#endif
- *ptr= 0; /* end marker */
+ ADD_COMMON_DIRECTORIES();
+ ADD_DIRECTORY("~/");
}
+
+static void (*init_default_directories)()= init_default_directories_unix;
+
+#endif
diff --git a/mysys/mf_arr_appstr.c b/mysys/mf_arr_appstr.c
new file mode 100644
index 00000000000..1edbea9df4a
--- /dev/null
+++ b/mysys/mf_arr_appstr.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+#include <m_string.h> /* strcmp() */
+
+
+/**
+ Append str to array, or move to the end if it already exists
+
+ @param str String to be appended
+ @param array The array, terminated by a NULL element, all unused elements
+ pre-initialized to NULL
+ @param size Size of the array; array must be terminated by a NULL
+ pointer, so can hold size - 1 elements
+
+ @retval FALSE Success
+ @retval TRUE Failure, array is full
+*/
+
+my_bool array_append_string_unique(const char *str,
+ const char **array, size_t size)
+{
+ const char **p;
+ /* end points at the terminating NULL element */
+ const char **end= array + size - 1;
+ DBUG_ASSERT(*end == NULL);
+
+ for (p= array; *p; ++p)
+ {
+ if (strcmp(*p, str) == 0)
+ break;
+ }
+ if (p >= end)
+ return TRUE; /* Array is full */
+
+ DBUG_ASSERT(*p == NULL || strcmp(*p, str) == 0);
+
+ while (*(p + 1))
+ {
+ *p= *(p + 1);
+ ++p;
+ }
+
+ DBUG_ASSERT(p < end);
+ *p= str;
+
+ return FALSE; /* Success */
+}
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index c81da9a469a..a03d71f32d8 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -3429,7 +3429,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
we are guarunteed no thread will change them
*/
- qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
+ my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
keycache_pthread_mutex_lock(&keycache->cache_lock);
/*
diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c
index 3d52d56c952..4b3ecb603a6 100644
--- a/mysys/mf_qsort.c
+++ b/mysys/mf_qsort.c
@@ -91,10 +91,10 @@ typedef struct st_stack
*****************************************************************************/
#ifdef QSORT_EXTRA_CMP_ARGUMENT
-qsort_t qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp,
+qsort_t my_qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp,
void *cmp_argument)
#else
-qsort_t qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp)
+qsort_t my_qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp)
#endif
{
char *low, *high, *pivot;
diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c
index 741c8f42327..686ebbc1d14 100644
--- a/mysys/mf_sort.c
+++ b/mysys/mf_sort.c
@@ -34,8 +34,8 @@ void my_string_ptr_sort(uchar *base, uint items, size_t size)
{
if (size && items)
{
- qsort2(base,items, sizeof(uchar*), get_ptr_compare(size),
- (void*) &size);
+ my_qsort2(base,items, sizeof(uchar*), get_ptr_compare(size),
+ (void*) &size);
}
}
}
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index bac3e2513e1..cff00bf7e08 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -56,16 +56,20 @@ int nt_share_delete(const char *name, myf MyFlags)
ulong cnt;
DBUG_ENTER("nt_share_delete");
DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags));
-
+
for (cnt= GetTickCount(); cnt; cnt--)
{
sprintf(buf, "%s.%08X.deleted", name, cnt);
if (MoveFile(name, buf))
break;
-
+
if ((errno= GetLastError()) == ERROR_ALREADY_EXISTS)
continue;
-
+
+ /* This happened during tests with MERGE tables. */
+ if (errno == ERROR_ACCESS_DENIED)
+ continue;
+
DBUG_PRINT("warning", ("Failed to rename %s to %s, errno: %d",
name, buf, errno));
break;
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 3aad6152dfd..5132ac820b8 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -86,6 +86,7 @@ static void default_reporter(enum loglevel level,
fprintf(stderr, "%s", "Info: ");
vfprintf(stderr, format, args);
va_end(args);
+ fputc('\n', stderr);
fflush(stderr);
}
@@ -153,7 +154,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Option '-O' requires an argument\n",
+ "%s: Option '-O' requires an argument",
my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
@@ -171,7 +172,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Option '--set-variable' requires an argument\n",
+ "%s: Option '--set-variable' requires an argument",
my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
@@ -185,7 +186,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Option '--set-variable' requires an argument\n",
+ "%s: Option '--set-variable' requires an argument",
my_progname);
return EXIT_ARGUMENT_REQUIRED;
}
@@ -247,7 +248,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: ambiguous option '--%s-%s' (--%s-%s)\n",
+ "%s: ambiguous option '--%s-%s' (--%s-%s)",
my_progname, special_opt_prefix[i],
cur_arg, special_opt_prefix[i],
prev_found);
@@ -298,7 +299,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
my_getopt_error_reporter(option_is_loose ?
WARNING_LEVEL : ERROR_LEVEL,
- "%s: unknown variable '%s'\n",
+ "%s: unknown variable '%s'",
my_progname, cur_arg);
if (!option_is_loose)
return EXIT_UNKNOWN_VARIABLE;
@@ -308,7 +309,7 @@ int handle_options(int *argc, char ***argv,
if (my_getopt_print_errors)
my_getopt_error_reporter(option_is_loose ?
WARNING_LEVEL : ERROR_LEVEL,
- "%s: unknown option '--%s'\n",
+ "%s: unknown option '--%s'",
my_progname, cur_arg);
if (!option_is_loose)
return EXIT_UNKNOWN_OPTION;
@@ -326,7 +327,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: variable prefix '%s' is not unique\n",
+ "%s: variable prefix '%s' is not unique",
my_progname, opt_str);
return EXIT_VAR_PREFIX_NOT_UNIQUE;
}
@@ -334,7 +335,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: ambiguous option '--%s' (%s, %s)\n",
+ "%s: ambiguous option '--%s' (%s, %s)",
my_progname, opt_str, prev_found,
optp->name);
return EXIT_AMBIGUOUS_OPTION;
@@ -357,7 +358,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '%s' cannot take an argument\n",
+ "%s: option '%s' cannot take an argument",
my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED;
}
@@ -370,7 +371,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '--%s' cannot take an argument\n",
+ "%s: option '--%s' cannot take an argument",
my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED;
}
@@ -392,7 +393,7 @@ int handle_options(int *argc, char ***argv,
{
my_getopt_error_reporter(WARNING_LEVEL,
"%s: ignoring option '--%s' due to \
-invalid value '%s'\n",
+invalid value '%s'",
my_progname, optp->name, optend);
continue;
}
@@ -423,7 +424,7 @@ invalid value '%s'\n",
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '--%s' requires an argument\n",
+ "%s: option '--%s' requires an argument",
my_progname, optp->name);
return EXIT_ARGUMENT_REQUIRED;
}
@@ -483,7 +484,7 @@ invalid value '%s'\n",
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '-%c' requires an argument\n",
+ "%s: option '-%c' requires an argument",
my_progname, optp->id);
return EXIT_ARGUMENT_REQUIRED;
}
@@ -496,7 +497,7 @@ invalid value '%s'\n",
set_maximum_value)))
{
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Error while setting value '%s' to '%s'\n",
+ "%s: Error while setting value '%s' to '%s'",
my_progname, argument, optp->name);
return error;
}
@@ -508,7 +509,7 @@ invalid value '%s'\n",
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: unknown option '-%c'\n",
+ "%s: unknown option '-%c'",
my_progname, *optend);
return EXIT_UNKNOWN_OPTION;
}
@@ -519,7 +520,7 @@ invalid value '%s'\n",
if ((error= setval(optp, value, argument, set_maximum_value)))
{
my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Error while setting value '%s' to '%s'\n",
+ "%s: Error while setting value '%s' to '%s'",
my_progname, argument, optp->name);
return error;
}
@@ -608,13 +609,17 @@ static int setval(const struct my_option *opts, uchar* *value, char *argument,
*((my_bool*) result_pos)= (my_bool) atoi(argument) != 0;
break;
case GET_INT:
- case GET_UINT: /* fall through */
*((int*) result_pos)= (int) getopt_ll(argument, opts, &err);
break;
+ case GET_UINT:
+ *((uint*) result_pos)= (uint) getopt_ull(argument, opts, &err);
+ break;
case GET_LONG:
- case GET_ULONG: /* fall through */
*((long*) result_pos)= (long) getopt_ll(argument, opts, &err);
break;
+ case GET_ULONG:
+ *((long*) result_pos)= (long) getopt_ull(argument, opts, &err);
+ break;
case GET_LL:
*((longlong*) result_pos)= getopt_ll(argument, opts, &err);
break;
@@ -778,23 +783,70 @@ static longlong eval_num_suffix(char *argument, int *error, char *option_name)
static longlong getopt_ll(char *arg, const struct my_option *optp, int *err)
{
- longlong num;
+ longlong num=eval_num_suffix(arg, err, (char*) optp->name);
+ return getopt_ll_limit_value(num, optp, NULL);
+}
+
+/*
+ function: getopt_ll_limit_value
+
+ Applies min/max/block_size to a numeric value of an option.
+ Returns "fixed" value.
+*/
+
+longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
+ bool *fix)
+{
+ longlong old= num;
+ bool adjusted= FALSE;
+ char buf1[255], buf2[255];
ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L);
-
- num= eval_num_suffix(arg, err, (char*) optp->name);
- if (num > 0 && (ulonglong) num > (ulonglong) optp->max_value &&
+
+ if (num > 0 && ((ulonglong) num > (ulonglong) optp->max_value) &&
optp->max_value) /* if max value is not set -> no upper limit */
{
- char buf[22];
- my_getopt_error_reporter(WARNING_LEVEL,
- "Truncated incorrect %s value: '%s'",
- optp->name, llstr(num, buf));
-
num= (ulonglong) optp->max_value;
+ adjusted= TRUE;
}
+
+ switch ((optp->var_type & GET_TYPE_MASK)) {
+ case GET_INT:
+ if (num > (longlong) INT_MAX)
+ {
+ num= ((longlong) INT_MAX);
+ adjusted= TRUE;
+ }
+ break;
+ case GET_LONG:
+#if SIZEOF_LONG < SIZEOF_LONG_LONG
+ if (num > (longlong) LONG_MAX)
+ {
+ num= ((longlong) LONG_MAX);
+ adjusted= TRUE;
+ }
+#endif
+ break;
+ default:
+ DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_LL);
+ break;
+ }
+
num= ((num - optp->sub_size) / block_size);
num= (longlong) (num * block_size);
- return max(num, optp->min_value);
+
+ if (num < optp->min_value)
+ {
+ num= optp->min_value;
+ adjusted= TRUE;
+ }
+
+ if (fix)
+ *fix= adjusted;
+ else if (adjusted)
+ my_getopt_error_reporter(WARNING_LEVEL,
+ "option '%s': signed value %s adjusted to %s",
+ optp->name, llstr(old, buf1), llstr(num, buf2));
+ return num;
}
/*
@@ -806,25 +858,66 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err)
static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err)
{
- ulonglong num;
-
- num= eval_num_suffix(arg, err, (char*) optp->name);
- return getopt_ull_limit_value(num, optp);
+ ulonglong num= eval_num_suffix(arg, err, (char*) optp->name);
+ return getopt_ull_limit_value(num, optp, NULL);
}
-ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp)
+ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
+ bool *fix)
{
+ bool adjusted= FALSE;
+ ulonglong old= num;
+ char buf1[255], buf2[255];
+
if ((ulonglong) num > (ulonglong) optp->max_value &&
optp->max_value) /* if max value is not set -> no upper limit */
+ {
num= (ulonglong) optp->max_value;
+ adjusted= TRUE;
+ }
+
+ switch ((optp->var_type & GET_TYPE_MASK)) {
+ case GET_UINT:
+ if (num > (ulonglong) UINT_MAX)
+ {
+ num= ((ulonglong) UINT_MAX);
+ adjusted= TRUE;
+ }
+ break;
+ case GET_ULONG:
+#if SIZEOF_LONG < SIZEOF_LONG_LONG
+ if (num > (ulonglong) ULONG_MAX)
+ {
+ num= ((ulonglong) ULONG_MAX);
+ adjusted= TRUE;
+ }
+#endif
+ break;
+ default:
+ DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_ULL);
+ break;
+ }
+
if (optp->block_size > 1)
{
num/= (ulonglong) optp->block_size;
num*= (ulonglong) optp->block_size;
}
+
if (num < (ulonglong) optp->min_value)
+ {
num= (ulonglong) optp->min_value;
+ adjusted= TRUE;
+ }
+
+ if (fix)
+ *fix= adjusted;
+ else if (adjusted)
+ my_getopt_error_reporter(WARNING_LEVEL,
+ "option '%s': unsigned value %s adjusted to %s",
+ optp->name, ullstr(old, buf1), ullstr(num, buf2));
+
return num;
}
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index c10b2e391b4..c18d14fb549 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -180,7 +180,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
result->number_off_files= dir_entries_storage->elements;
if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) result->dir_entry, result->number_off_files,
+ my_qsort((void *) result->dir_entry, result->number_off_files,
sizeof(FILEINFO), (qsort_cmp) comp_names);
DBUG_RETURN(result);
@@ -491,7 +491,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
result->number_off_files= dir_entries_storage->elements;
if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) result->dir_entry, result->number_off_files,
+ my_qsort((void *) result->dir_entry, result->number_off_files,
sizeof(FILEINFO), (qsort_cmp) comp_names);
DBUG_PRINT("exit", ("found %d files", result->number_off_files));
DBUG_RETURN(result);
diff --git a/mysys/my_write.c b/mysys/my_write.c
index 056a84f1794..c67b1d8f3f2 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -29,6 +29,10 @@ size_t my_write(int Filedes, const uchar *Buffer, size_t Count, myf MyFlags)
Filedes, (long) Buffer, (ulong) Count, MyFlags));
errors=0; written=0;
+ /* The behavior of write(fd, buf, 0) is not portable */
+ if (unlikely(!Count))
+ DBUG_RETURN(0);
+
for (;;)
{
if ((writenbytes= write(Filedes, Buffer, Count)) == Count)
diff --git a/mysys/queues.c b/mysys/queues.c
index d8a7ca19bee..94f49ab8f9c 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -61,7 +61,7 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
queue->first_cmp_arg=first_cmp_arg;
queue->max_elements=max_elements;
queue->offset_to_key=offset_to_key;
- queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
+ queue_set_max_at_top(queue, max_at_top);
DBUG_RETURN(0);
}
@@ -137,7 +137,7 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
queue->compare=compare;
queue->first_cmp_arg=first_cmp_arg;
queue->offset_to_key=offset_to_key;
- queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
+ queue_set_max_at_top(queue, max_at_top);
resize_queue(queue, max_elements);
DBUG_RETURN(0);
}
@@ -208,16 +208,14 @@ void delete_queue(QUEUE *queue)
void queue_insert(register QUEUE *queue, uchar *element)
{
reg2 uint idx, next;
- int cmp;
DBUG_ASSERT(queue->elements < queue->max_elements);
queue->root[0]= element;
idx= ++queue->elements;
/* max_at_top swaps the comparison if we want to order by desc */
- while ((cmp= queue->compare(queue->first_cmp_arg,
- element + queue->offset_to_key,
- queue->root[(next= idx >> 1)] +
- queue->offset_to_key)) &&
- (cmp ^ queue->max_at_top) < 0)
+ while ((queue->compare(queue->first_cmp_arg,
+ element + queue->offset_to_key,
+ queue->root[(next= idx >> 1)] +
+ queue->offset_to_key) * queue->max_at_top) < 0)
{
queue->root[idx]= queue->root[next];
idx= next;
@@ -287,19 +285,17 @@ void _downheap(register QUEUE *queue, uint idx)
while (idx <= half_queue)
{
- int cmp;
next_index=idx+idx;
if (next_index < elements &&
(queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
- queue->root[next_index+1]+offset_to_key) ^
+ queue->root[next_index+1]+offset_to_key) *
queue->max_at_top) > 0)
next_index++;
if (first &&
- (((cmp=queue->compare(queue->first_cmp_arg,
- queue->root[next_index]+offset_to_key,
- element+offset_to_key)) == 0) ||
- ((cmp ^ queue->max_at_top) > 0)))
+ (((queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ element+offset_to_key) * queue->max_at_top) >= 0)))
{
queue->root[idx]= element;
return;
@@ -314,7 +310,7 @@ void _downheap(register QUEUE *queue, uint idx)
{
if ((queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
- element+offset_to_key) ^
+ element+offset_to_key) *
queue->max_at_top) < 0)
break;
queue->root[idx]=queue->root[next_index];
@@ -334,7 +330,6 @@ void _downheap(register QUEUE *queue, uint idx)
{
uchar *element;
uint elements,half_queue,next_index,offset_to_key;
- int cmp;
offset_to_key=queue->offset_to_key;
element=queue->root[idx];
@@ -346,13 +341,12 @@ void _downheap(register QUEUE *queue, uint idx)
if (next_index < elements &&
(queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
- queue->root[next_index+1]+offset_to_key) ^
+ queue->root[next_index+1]+offset_to_key) *
queue->max_at_top) > 0)
next_index++;
- if ((cmp=queue->compare(queue->first_cmp_arg,
- queue->root[next_index]+offset_to_key,
- element+offset_to_key)) == 0 ||
- (cmp ^ queue->max_at_top) > 0)
+ if ((queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ element+offset_to_key) * queue->max_at_top) >= 0)
break;
queue->root[idx]=queue->root[next_index];
idx=next_index;
@@ -382,7 +376,7 @@ void queue_fix(QUEUE *queue)
make test_priority_queue
./test_priority_queue
- Written by Mikael Ronström, 2005
+ Written by Mikael Ronström, 2005
*/
static uint num_array[1025];
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index a81ed925562..7f7be4835a5 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -396,6 +396,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
struct timespec wait_timeout;
enum enum_thr_lock_result result= THR_LOCK_ABORTED;
my_bool can_deadlock= test(data->owner->info->n_cursors);
+ DBUG_ENTER("wait_for_lock");
if (!in_wait_list)
{
@@ -431,13 +432,21 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
if the predicate is true.
*/
if (data->cond == 0)
+ {
+ DBUG_PRINT("thr_lock", ("lock granted/aborted"));
break;
+ }
if (rc == ETIMEDOUT || rc == ETIME)
{
+ /* purecov: begin inspected */
+ DBUG_PRINT("thr_lock", ("lock timed out"));
result= THR_LOCK_WAIT_TIMEOUT;
break;
+ /* purecov: end */
}
}
+ DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d",
+ thread_var->abort, in_wait_list));
if (data->cond || data->type == TL_UNLOCK)
{
@@ -453,6 +462,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
}
else
{
+ DBUG_PRINT("thr_lock", ("lock aborted"));
check_locks(data->lock, "aborted wait_for_lock", 0);
}
}
@@ -471,7 +481,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
thread_var->current_mutex= 0;
thread_var->current_cond= 0;
pthread_mutex_unlock(&thread_var->mutex);
- return result;
+ DBUG_RETURN(result);
}
@@ -509,7 +519,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
and the read lock is not TL_READ_NO_INSERT
*/
- DBUG_PRINT("lock",("write locked by thread: 0x%lx",
+ DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx",
lock->write.data->owner->info->thread_id));
if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
(lock->write.data->type <= TL_WRITE_DELAYED &&
@@ -598,10 +608,14 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
{
if (lock->write.data->type == TL_WRITE_ONLY)
{
- /* We are not allowed to get a lock in this case */
- data->type=TL_UNLOCK;
- result= THR_LOCK_ABORTED; /* Can't wait for this one */
- goto end;
+ /* Allow lock owner to bypass TL_WRITE_ONLY. */
+ if (!thr_lock_owner_equal(data->owner, lock->write.data->owner))
+ {
+ /* We are not allowed to get a lock in this case */
+ data->type=TL_UNLOCK;
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
+ goto end;
+ }
}
/*
@@ -631,10 +645,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
- /* purecov: begin inspected */
- DBUG_PRINT("lock",("write locked by thread: 0x%lx",
+ DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx",
lock->write.data->owner->info->thread_id));
- /* purecov: end */
}
else
{
@@ -669,7 +681,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
goto end;
}
}
- DBUG_PRINT("lock",("write locked by thread: 0x%lx type: %d",
+ DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d",
lock->read.data->owner->info->thread_id, data->type));
}
wait_queue= &lock->write_wait;
@@ -683,6 +695,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
lock_owner= lock->read.data ? lock->read.data : lock->write.data;
if (lock_owner && lock_owner->owner->info == owner->info)
{
+ DBUG_PRINT("lock",("deadlock"));
result= THR_LOCK_DEADLOCK;
goto end;
}