diff options
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/charset-def.c | 132 | ||||
-rw-r--r-- | mysys/charset.c | 10 | ||||
-rw-r--r-- | mysys/my_addr_resolve.c | 68 | ||||
-rw-r--r-- | mysys/my_default.c | 476 | ||||
-rw-r--r-- | mysys/my_error.c | 4 | ||||
-rw-r--r-- | mysys/my_getopt.c | 109 | ||||
-rw-r--r-- | mysys/my_getsystime.c | 30 | ||||
-rw-r--r-- | mysys/my_init.c | 152 | ||||
-rw-r--r-- | mysys/my_pthread.c | 63 | ||||
-rw-r--r-- | mysys/my_winfile.c | 13 | ||||
-rw-r--r-- | mysys/stacktrace.c | 45 | ||||
-rw-r--r-- | mysys/thr_rwlock.c | 139 | ||||
-rw-r--r-- | mysys/thr_timer.c | 31 | ||||
-rw-r--r-- | mysys/typelib.c | 2 |
14 files changed, 514 insertions, 760 deletions
diff --git a/mysys/charset-def.c b/mysys/charset-def.c index b4317806762..249fb1b5e4d 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -116,37 +116,37 @@ extern struct charset_info_st my_charset_utf16_unicode_520_nopad_ci; #endif /* HAVE_CHARSET_utf16 */ -#ifdef HAVE_CHARSET_utf8 -extern struct charset_info_st my_charset_utf8_german2_uca_ci; -extern struct charset_info_st my_charset_utf8_icelandic_uca_ci; -extern struct charset_info_st my_charset_utf8_latvian_uca_ci; -extern struct charset_info_st my_charset_utf8_romanian_uca_ci; -extern struct charset_info_st my_charset_utf8_slovenian_uca_ci; -extern struct charset_info_st my_charset_utf8_polish_uca_ci; -extern struct charset_info_st my_charset_utf8_estonian_uca_ci; -extern struct charset_info_st my_charset_utf8_spanish_uca_ci; -extern struct charset_info_st my_charset_utf8_swedish_uca_ci; -extern struct charset_info_st my_charset_utf8_turkish_uca_ci; -extern struct charset_info_st my_charset_utf8_czech_uca_ci; -extern struct charset_info_st my_charset_utf8_danish_uca_ci; -extern struct charset_info_st my_charset_utf8_lithuanian_uca_ci; -extern struct charset_info_st my_charset_utf8_slovak_uca_ci; -extern struct charset_info_st my_charset_utf8_spanish2_uca_ci; -extern struct charset_info_st my_charset_utf8_roman_uca_ci; -extern struct charset_info_st my_charset_utf8_persian_uca_ci; -extern struct charset_info_st my_charset_utf8_esperanto_uca_ci; -extern struct charset_info_st my_charset_utf8_hungarian_uca_ci; -extern struct charset_info_st my_charset_utf8_croatian_mysql561_uca_ci; -extern struct charset_info_st my_charset_utf8_sinhala_uca_ci; -extern struct charset_info_st my_charset_utf8_unicode_520_ci; -extern struct charset_info_st my_charset_utf8_vietnamese_ci; -extern struct charset_info_st my_charset_utf8_croatian_uca_ci; -extern struct charset_info_st my_charset_utf8_myanmar_uca_ci; -extern struct charset_info_st my_charset_utf8_thai_520_w2; +#ifdef HAVE_CHARSET_utf8mb3 +extern struct charset_info_st my_charset_utf8mb3_german2_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_icelandic_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_latvian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_romanian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_slovenian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_polish_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_estonian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_spanish_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_swedish_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_turkish_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_czech_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_danish_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_lithuanian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_slovak_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_spanish2_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_roman_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_persian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_esperanto_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_hungarian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_croatian_mysql561_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_sinhala_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_unicode_520_ci; +extern struct charset_info_st my_charset_utf8mb3_vietnamese_ci; +extern struct charset_info_st my_charset_utf8mb3_croatian_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_myanmar_uca_ci; +extern struct charset_info_st my_charset_utf8mb3_thai_520_w2; #ifdef HAVE_UTF8_GENERAL_CS -extern struct charset_info_st my_charset_utf8_general_cs; +extern struct charset_info_st my_charset_utf8mb3_general_cs; #endif -extern struct charset_info_st my_charset_utf8_unicode_520_nopad_ci; +extern struct charset_info_st my_charset_utf8mb3_unicode_520_nopad_ci; #endif #ifdef HAVE_CHARSET_utf8mb4 @@ -304,47 +304,47 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ujis_nopad_bin); #endif -#ifdef HAVE_CHARSET_utf8 - add_compiled_collation(&my_charset_utf8_general_ci); - add_compiled_collation(&my_charset_utf8_general_nopad_ci); - add_compiled_collation(&my_charset_utf8_bin); - add_compiled_collation(&my_charset_utf8_nopad_bin); - add_compiled_collation(&my_charset_utf8_general_mysql500_ci); +#ifdef HAVE_CHARSET_utf8mb3 + add_compiled_collation(&my_charset_utf8mb3_general_ci); + add_compiled_collation(&my_charset_utf8mb3_general_nopad_ci); + add_compiled_collation(&my_charset_utf8mb3_bin); + add_compiled_collation(&my_charset_utf8mb3_nopad_bin); + add_compiled_collation(&my_charset_utf8mb3_general_mysql500_ci); #ifdef HAVE_UTF8_GENERAL_CS - add_compiled_collation(&my_charset_utf8_general_cs); + add_compiled_collation(&my_charset_utf8mb3_general_cs); #endif #ifdef HAVE_UCA_COLLATIONS - add_compiled_collation(&my_charset_utf8_unicode_ci); - add_compiled_collation(&my_charset_utf8_german2_uca_ci); - add_compiled_collation(&my_charset_utf8_icelandic_uca_ci); - add_compiled_collation(&my_charset_utf8_latvian_uca_ci); - add_compiled_collation(&my_charset_utf8_romanian_uca_ci); - add_compiled_collation(&my_charset_utf8_slovenian_uca_ci); - add_compiled_collation(&my_charset_utf8_polish_uca_ci); - add_compiled_collation(&my_charset_utf8_estonian_uca_ci); - add_compiled_collation(&my_charset_utf8_spanish_uca_ci); - add_compiled_collation(&my_charset_utf8_swedish_uca_ci); - add_compiled_collation(&my_charset_utf8_turkish_uca_ci); - add_compiled_collation(&my_charset_utf8_czech_uca_ci); - add_compiled_collation(&my_charset_utf8_danish_uca_ci); - add_compiled_collation(&my_charset_utf8_lithuanian_uca_ci); - add_compiled_collation(&my_charset_utf8_slovak_uca_ci); - add_compiled_collation(&my_charset_utf8_spanish2_uca_ci); - add_compiled_collation(&my_charset_utf8_roman_uca_ci); - add_compiled_collation(&my_charset_utf8_persian_uca_ci); - add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); - add_compiled_collation(&my_charset_utf8_hungarian_uca_ci); - add_compiled_collation(&my_charset_utf8_croatian_mysql561_uca_ci); - add_compiled_collation(&my_charset_utf8_sinhala_uca_ci); - add_compiled_collation(&my_charset_utf8_unicode_520_ci); - add_compiled_collation(&my_charset_utf8_vietnamese_ci); - add_compiled_collation(&my_charset_utf8_croatian_uca_ci); - add_compiled_collation(&my_charset_utf8_myanmar_uca_ci); - add_compiled_collation(&my_charset_utf8_thai_520_w2); - add_compiled_collation(&my_charset_utf8_unicode_nopad_ci); - add_compiled_collation(&my_charset_utf8_unicode_520_nopad_ci); + add_compiled_collation(&my_charset_utf8mb3_unicode_ci); + add_compiled_collation(&my_charset_utf8mb3_german2_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_icelandic_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_latvian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_romanian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_slovenian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_polish_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_estonian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_spanish_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_swedish_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_turkish_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_czech_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_danish_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_lithuanian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_slovak_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_spanish2_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_roman_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_persian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_esperanto_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_hungarian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_croatian_mysql561_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_sinhala_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_unicode_520_ci); + add_compiled_collation(&my_charset_utf8mb3_vietnamese_ci); + add_compiled_collation(&my_charset_utf8mb3_croatian_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_myanmar_uca_ci); + add_compiled_collation(&my_charset_utf8mb3_thai_520_w2); + add_compiled_collation(&my_charset_utf8mb3_unicode_nopad_ci); + add_compiled_collation(&my_charset_utf8mb3_unicode_520_nopad_ci); #endif -#endif /* HAVE_CHARSET_utf8 */ +#endif /* HAVE_CHARSET_utf8mb3 */ #ifdef HAVE_CHARSET_utf8mb4 diff --git a/mysys/charset.c b/mysys/charset.c index f44dc7606c1..7771f5800ef 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -262,7 +262,7 @@ static my_bool simple_cs_is_full(CHARSET_INFO *cs) } -#if defined(HAVE_UCA_COLLATIONS) && (defined(HAVE_CHARSET_ucs2) || defined(HAVE_CHARSET_utf8)) +#if defined(HAVE_UCA_COLLATIONS) && (defined(HAVE_CHARSET_ucs2) || defined(HAVE_CHARSET_utf8mb3)) /** Initialize a loaded collation. @param [OUT] to - The new charset_info_st structure to initialize. @@ -350,12 +350,12 @@ static int add_collation(struct charset_info_st *cs) } else if (!strcmp(cs->csname, "utf8") || !strcmp(cs->csname, "utf8mb3")) { -#if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) +#if defined (HAVE_CHARSET_utf8mb3) && defined(HAVE_UCA_COLLATIONS) copy_uca_collation(newcs, newcs->state & MY_CS_NOPAD ? - &my_charset_utf8_unicode_nopad_ci : - &my_charset_utf8_unicode_ci, + &my_charset_utf8mb3_unicode_nopad_ci : + &my_charset_utf8mb3_unicode_ci, cs); - newcs->ctype= my_charset_utf8_unicode_ci.ctype; + newcs->ctype= my_charset_utf8mb3_unicode_ci.ctype; if (init_state_maps(newcs)) return MY_XML_ERROR; #endif diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 7590d576a7c..ff15558ddd4 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -191,7 +191,9 @@ int start_addr2line_fork(const char *binary_path) return 0; } -int my_addr_resolve(void *ptr, my_addr_loc *loc) +static int first_error= 0; + +static int addr_resolve(void *ptr, my_addr_loc *loc) { char input[32]; size_t len; @@ -206,29 +208,13 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) int filename_start = -1; int line_number_start = -1; - Dl_info info; - void *offset; - - if (!dladdr(ptr, &info)) - return 1; - - if (strcmp(addr2line_binary, info.dli_fname)) - { - /* We use dli_fname in case the path is longer than the length of our static - string. We don't want to allocate anything dynamicaly here as we are in - a "crashed" state. */ - if (start_addr2line_fork(info.dli_fname)) - { - addr2line_binary[0] = '\0'; - return 2; - } - /* Save result for future comparisons. */ - strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); - } - offset = info.dli_fbase; - len= my_snprintf(input, sizeof(input), "%08x\n", (ulonglong)(ptr - offset)); + len= my_snprintf(input, sizeof(input), "%p\n", ptr); if (write(in[1], input, len) <= 0) + { + if (!first_error++) + fputs("Printing to addr2line failed\n", stderr); return 3; + } FD_ZERO(&set); FD_SET(out[0], &set); @@ -278,7 +264,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) loc->line= atoi(output + line_number_start); /* Addr2line was unable to extract any meaningful information. */ - if (strcmp(loc->file, "??") == 0) + if (strcmp(loc->file, "??") == 0 && loc->func[0] == '?') return 6; loc->file= strip_path(loc->file); @@ -286,6 +272,42 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) return 0; } + +int my_addr_resolve(void *ptr, my_addr_loc *loc) +{ + Dl_info info; + int error; + + if (!dladdr(ptr, &info)) + return 1; + + if (strcmp(addr2line_binary, info.dli_fname)) + { + /* + We use dli_fname in case the path is longer than the length of + our static string. We don't want to allocate anything + dynamicaly here as we are in a "crashed" state. + */ + if (start_addr2line_fork(info.dli_fname)) + { + if (!first_error++) + fputs("Can't start addr2line\n", stderr); + addr2line_binary[0] = '\0'; + return 2; + } + /* Save result for future comparisons. */ + strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); + } + if (!(error= addr_resolve(ptr, loc))) + return 0; +#ifdef EXTRA_RESOLVE + if (!(error= addr_resolve((void*) (ptr - info.dli_fbase), loc))) + return 0; +#endif + return error; +} + + const char *my_addr_resolve_init() { return 0; diff --git a/mysys/my_default.c b/mysys/my_default.c index deeb9b4a5b8..8655cccf050 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -43,52 +43,23 @@ #include <winbase.h> #endif -/** - arguments separator - - load_defaults() loads arguments from config file and put them - before the arguments from command line, this separator is used to - separate the arguments loaded from config file and arguments user - provided on command line. - - Options with value loaded from config file are always in the form - '--option=value', while for command line options, the value can be - given as the next argument. Thus we used a separator so that - handle_options() can distinguish them. - - Note: any other places that does not need to distinguish them - should skip the separator. - - The content of arguments separator does not matter, one should only - check the pointer, use "----args-separator----" here to ease debug - if someone misused it. - - The args separator will only be added when - my_getopt_use_args_seprator is set to TRUE before calling - load_defaults(); - - See BUG#25192 +/* + Mark file names in argv[]. File marker is *always* followed by a file name + All options after it come from that file. + Empty file name ("") means command line. */ -static const char *args_separator= "----args-separator----"; -inline static void set_args_separator(char** arg) +static char *file_marker= (char*)"----file-marker----"; +my_bool my_defaults_mark_files= FALSE; +my_bool is_file_marker(const 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); + return arg == file_marker; } + +my_bool my_no_defaults=FALSE, my_print_defaults= FALSE; const char *my_defaults_file=0; const char *my_defaults_group_suffix=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) */ #define MAX_DEFAULT_DIRS 7 @@ -103,15 +74,6 @@ static const char *f_extensions[]= { ".cnf", 0 }; #define NEWLINE "\n" #endif -static int handle_default_option(void *, const char *, const char *); - -/* - This structure defines the context that we pass to callback - function 'handle_default_option' used in search_default_file - to process each option. This context is used if search_default_file - was called from load_defaults. -*/ - struct handle_option_ctx { MEM_ROOT *alloc; @@ -119,12 +81,11 @@ struct handle_option_ctx TYPELIB *group; }; -static int search_default_file(Process_option_func func, void *func_ctx, - const char *dir, const char *config_file); -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 int search_default_file(struct handle_option_ctx *, + const char *, const char *); +static int search_default_file_with_ext(struct handle_option_ctx *, + const char *, const char *, + const char *, int); /** @@ -159,33 +120,6 @@ 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: %p", - filename, 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 @@ -194,8 +128,6 @@ fn_expand(const char *filename, char *result_buf) If this is a path, then only this file is read. argc Pointer to argc of original program argv Pointer to argv of original program - args_used Pointer to variable for storing the number of - arguments used. func Pointer to the function to process options func_ctx It's context. Usually it is the structure to store additional options. @@ -219,53 +151,20 @@ fn_expand(const char *filename, char *result_buf) --defaults_group_suffix */ -int my_search_option_files(const char *conf_file, int *argc, char ***argv, - uint *args_used, Process_option_func func, - void *func_ctx, const char **default_directories) +static int my_search_option_files(const char *conf_file, int *argc, char ***argv, + struct handle_option_ctx *ctx, + const char **default_directories) { - const char **dirs, *forced_default_file, *forced_extra_defaults; + const char **dirs; int error= 0; DBUG_ENTER("my_search_option_files"); - /* Check if we want to force the use a specific default file */ - *args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used, - (char **) &forced_default_file, - (char **) &forced_extra_defaults, - (char **) &my_defaults_group_suffix); - - if (! my_defaults_group_suffix) - my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX"); - - 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 - load_defaults() as otherwise we can't know the type of 'func_ctx' - */ - - if (my_defaults_group_suffix && func == handle_default_option) + if (my_defaults_group_suffix) { /* Handle --defaults-group-suffix= */ uint i; const char **extra_groups; const size_t instance_len= strlen(my_defaults_group_suffix); - struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx; char *ptr; TYPELIB *group= ctx->group; @@ -297,7 +196,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, if (my_defaults_file) { - if ((error= search_default_file_with_ext(func, func_ctx, "", "", + if ((error= search_default_file_with_ext(ctx, "", "", my_defaults_file, 0)) < 0) goto err; if (error > 0) @@ -309,7 +208,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, } else if (dirname_length(conf_file)) { - if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0) + if ((error= search_default_file(ctx, NullS, conf_file)) < 0) goto err; } else @@ -318,12 +217,12 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, { if (**dirs) { - if (search_default_file(func, func_ctx, *dirs, conf_file) < 0) + if (search_default_file(ctx, *dirs, conf_file) < 0) goto err; } else if (my_defaults_extra_file) { - if ((error= search_default_file_with_ext(func, func_ctx, "", "", + if ((error= search_default_file_with_ext(ctx, "", "", my_defaults_extra_file, 0)) < 0) goto err; /* Fatal error */ if (error > 0) @@ -345,47 +244,23 @@ err: /* - The option handler for load_defaults. + adds an option to the array of options SYNOPSIS - handle_deault_option() - in_ctx Handler context. In this case it is a - handle_option_ctx structure. - group_name The name of the group the option belongs to. + add_option() + in_ctx Handler context. option The very option to be processed. It is already - prepared to be used in argv (has -- prefix). If it - is NULL, we are handling a new group (section). - - DESCRIPTION - This handler checks whether a group is one of the listed and adds an option - to the array if yes. Some other handler can record, for instance, all - groups and their options, not knowing in advance the names and amount of - groups. + prepared to be used in argv (has -- prefix). RETURN 0 - ok 1 - error occurred */ -static int handle_default_option(void *in_ctx, const char *group_name, - const char *option) +static int add_option(struct handle_option_ctx *ctx, const char *option) { - char *tmp; - struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx; - - if (!option) - return 0; - - if (find_type((char *)group_name, ctx->group, FIND_TYPE_NO_PREFIX)) - { - if (!(tmp= alloc_root(ctx->alloc, strlen(option) + 1))) - return 1; - if (insert_dynamic(ctx->args, (uchar*) &tmp)) - return 1; - strmov(tmp, option); - } - - return 0; + char *tmp= strdup_root(ctx->alloc, option); + return !tmp || insert_dynamic(ctx->args, (uchar*) &tmp); } @@ -394,50 +269,74 @@ static int handle_default_option(void *in_ctx, const char *group_name, SYNOPSIS get_defaults_options() - argc Pointer to argc of original program argv Pointer to argv of original program - defaults --defaults-file option - extra_defaults --defaults-extra-file option + + DESCRIPTION + Sets my_no_defaults, my_defaults_file, my_defaults_extra_file, + my_defaults_group_suffix, my_print_defaults RETURN # Number of arguments used from *argv - defaults and extra_defaults will be set to option of the appropriate - items of argv array, or to NULL if there are no such options */ -int get_defaults_options(int argc, char **argv, - char **defaults, - char **extra_defaults, - char **group_suffix) +int get_defaults_options(char **argv) { - int org_argc= argc; - *defaults= *extra_defaults= *group_suffix= 0; + static char file_buffer[FN_REFLEN]; + static char extra_file_buffer[FN_REFLEN]; + char **orig_argv= argv; + + argv++; /* Skip program name */ + + my_defaults_file= my_defaults_group_suffix= my_defaults_extra_file= 0; + my_no_defaults= my_print_defaults= FALSE; - while (argc >= 2) + if (*argv && !strcmp(*argv, "--no-defaults")) { - /* Skip program name or previously handled argument */ + my_no_defaults= 1; argv++; - if (!*defaults && is_prefix(*argv,"--defaults-file=")) - { - *defaults= *argv + sizeof("--defaults-file=")-1; - argc--; - continue; - } - if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file=")) - { - *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1; - argc--; - continue; - } - if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix=")) + } + else + for(; *argv; argv++) { - *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1; - argc--; - continue; + if (!my_defaults_file && is_prefix(*argv, "--defaults-file=")) + my_defaults_file= *argv + sizeof("--defaults-file=")-1; + else + if (!my_defaults_extra_file && is_prefix(*argv, "--defaults-extra-file=")) + my_defaults_extra_file= *argv + sizeof("--defaults-extra-file=")-1; + else + if (!my_defaults_group_suffix && is_prefix(*argv, "--defaults-group-suffix=")) + my_defaults_group_suffix= *argv + sizeof("--defaults-group-suffix=")-1; + else + break; } - break; + + if (*argv && !strcmp(*argv, "--print-defaults")) + { + my_print_defaults= 1; + my_defaults_mark_files= FALSE; + argv++; } - return org_argc - argc; + + if (! my_defaults_group_suffix) + my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX"); + + if (my_defaults_extra_file && my_defaults_extra_file != extra_file_buffer) + { + int error= my_realpath(extra_file_buffer, my_defaults_extra_file, MYF(0)); + if (error) + return error; + my_defaults_extra_file= extra_file_buffer; + } + + if (my_defaults_file && my_defaults_file != file_buffer) + { + int error= my_realpath(file_buffer, my_defaults_file, MYF(0)); + if (error) + return error; + my_defaults_file= file_buffer; + } + + return (int)(argv - orig_argv); } /* @@ -504,132 +403,85 @@ int load_defaults(const char *conf_file, const char **groups, */ -int my_load_defaults(const char *conf_file, const char **groups, - int *argc, char ***argv, const char ***default_directories) +int my_load_defaults(const char *conf_file, const char **groups, int *argc, + char ***argv, const char ***default_directories) { DYNAMIC_ARRAY args; - TYPELIB group; - my_bool found_print_defaults= 0; - uint args_used= 0; + int args_used= 0; int error= 0; MEM_ROOT alloc; 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"); + DBUG_ENTER("my_load_defaults"); init_alloc_root(&alloc, "my_load_defaults", 512, 0, MYF(0)); if ((dirs= init_default_directories(&alloc)) == NULL) goto err; - /* - Check if the user doesn't want any default option processing - --no-defaults is always the first option - */ - if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults")) - { - /* remove the --no-defaults argument and return only the other arguments */ - 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 */ - 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) - *default_directories= dirs; - DBUG_RETURN(0); - } - - group.count=0; - group.name= "defaults"; - group.type_names= groups; - for (; *groups ; groups++) - group.count++; + args_used= get_defaults_options(*argv); if (my_init_dynamic_array(&args, sizeof(char*), 128, 64, MYF(0))) goto err; - ctx.alloc= &alloc; - ctx.args= &args; - ctx.group= &group; + insert_dynamic(&args, *argv);/* Name MUST be set, even by embedded library */ - if ((error= my_search_option_files(conf_file, argc, argv, &args_used, - handle_default_option, (void *) &ctx, - dirs))) + *argc-= args_used; + *argv+= args_used; + + if (!my_no_defaults) { - delete_dynamic(&args); - free_root(&alloc,MYF(0)); - DBUG_RETURN(error); + TYPELIB group; // XXX + struct handle_option_ctx ctx; + + group.count=0; + group.name= "defaults"; + group.type_names= groups; + + for (; *groups ; groups++) + group.count++; + + ctx.alloc= &alloc; + ctx.args= &args; + ctx.group= &group; + + if ((error= my_search_option_files(conf_file, argc - args_used, + argv + args_used, &ctx, dirs))) + { + delete_dynamic(&args); + free_root(&alloc,MYF(0)); + DBUG_RETURN(error); + } } - /* - Here error contains <> 0 only if we have a fully specified conf_file - or a forced default file - */ - if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (args.elements + *argc + 1 + args_sep) *sizeof(char*)))) + + if (!(ptr=(char*) alloc_root(&alloc, sizeof(alloc) + + (args.elements + *argc + 3) * sizeof(char*)))) goto err; res= (char**) (ptr+sizeof(alloc)); - /* copy name + found arguments + command line arguments to new array */ - res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */ - memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*)); - /* Skip --defaults-xxx options */ - (*argc)-= args_used; - (*argv)+= args_used; + /* found arguments + command line arguments to new array */ + memcpy(res, args.buffer, args.elements * sizeof(char*)); - /* - Check if we want to see the new argument list - This options must always be the last of the default options - */ - if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults")) + if (my_defaults_mark_files) { - found_print_defaults=1; - --*argc; ++*argv; /* skip argument */ - } - - if (my_getopt_use_args_separator) - { - /* set arguments separator for arguments from config file and - command line */ - set_args_separator(&res[args.elements+1]); + res[args.elements++]= file_marker; + res[args.elements++]= (char*)""; } if (*argc) - memcpy((uchar*) (res+1+args.elements+args_sep), (char*) ((*argv)+1), - (*argc-1)*sizeof(char*)); - res[args.elements+ *argc+args_sep]=0; /* last null */ + memcpy(res + args.elements, *argv, *argc * sizeof(char*)); - (*argc)+=args.elements+args_sep; - *argv= (char**) res; + (*argc)+= args.elements; + *argv= res; + (*argv)[*argc]= 0; *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ delete_dynamic(&args); - if (found_print_defaults) + if (my_print_defaults) { int i; printf("%s would have been started with the following arguments:\n", **argv); for (i=1 ; i < *argc ; i++) - if (!my_getopt_is_args_separator((*argv)[i])) /* skip arguments separator */ - printf("%s ", (*argv)[i]); + printf("%s ", (*argv)[i]); puts(""); DBUG_RETURN(4); } @@ -653,9 +505,7 @@ void free_defaults(char **argv) } -static int search_default_file(Process_option_func opt_handler, - void *handler_ctx, - const char *dir, +static int search_default_file(struct handle_option_ctx *ctx, const char *dir, const char *config_file) { char **ext; @@ -666,9 +516,7 @@ static int search_default_file(Process_option_func opt_handler, for (ext= (char**) exts_to_use; *ext; ext++) { int error; - if ((error= search_default_file_with_ext(opt_handler, handler_ctx, - dir, *ext, - config_file, 0)) < 0) + if ((error= search_default_file_with_ext(ctx, dir, *ext, config_file, 0)) < 0) return error; } return 0; @@ -730,9 +578,7 @@ static char *get_argument(const char *keyword, size_t kwlen, SYNOPSIS search_default_file_with_ext() - opt_handler Option handler function. It is used to process - every separate option. - handler_ctx Pointer to the structure to store actual + ctx Pointer to the structure to store actual parameters of the function. dir directory to read ext Extension for configuration file @@ -747,10 +593,8 @@ static char *get_argument(const char *keyword, size_t kwlen, 1 File not found (Warning) */ -static int search_default_file_with_ext(Process_option_func opt_handler, - void *handler_ctx, - const char *dir, - const char *ext, +static int search_default_file_with_ext(struct handle_option_ctx *ctx, + const char *dir, const char *ext, const char *config_file, int recursion_level) { @@ -761,12 +605,12 @@ static int search_default_file_with_ext(Process_option_func opt_handler, const int max_recursion_level= 10; MYSQL_FILE *fp; uint line=0; - my_bool found_group=0; + enum { NONE, PARSE, SKIP } found_group= NONE; uint i; MY_DIR *search_dir; FILEINFO *search_file; - if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3) + if (safe_strlen(dir) + strlen(config_file) >= FN_REFLEN-3) return 0; /* Ignore wrong paths */ if (dir) { @@ -802,6 +646,11 @@ static int search_default_file_with_ext(Process_option_func opt_handler, if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) return 1; /* Ignore wrong files */ + if (my_defaults_mark_files) + if (insert_dynamic(ctx->args, (uchar*) &file_marker) || + add_option(ctx, name)) + goto err; + while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) { line++; @@ -862,8 +711,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, fn_format(tmp, search_file->name, ptr, "", MY_UNPACK_FILENAME | MY_SAFE_PATH); - search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp, - recursion_level + 1); + search_default_file_with_ext(ctx, "", "", tmp, recursion_level + 1); } } @@ -877,8 +725,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, name, line))) goto err; - search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr, - recursion_level + 1); + search_default_file_with_ext(ctx, "", "", ptr, recursion_level + 1); } continue; @@ -886,7 +733,6 @@ static int search_default_file_with_ext(Process_option_func opt_handler, if (*ptr == '[') /* Group name */ { - found_group=1; if (!(end=(char *) strchr(++ptr,']'))) { fprintf(stderr, @@ -899,32 +745,29 @@ static int search_default_file_with_ext(Process_option_func opt_handler, end[0]=0; strmake(curr_gr, ptr, MY_MIN((size_t) (end-ptr)+1, sizeof(curr_gr)-1)); - - /* signal that a new group is found */ - opt_handler(handler_ctx, curr_gr, NULL); - + found_group= find_type(curr_gr, ctx->group, FIND_TYPE_NO_PREFIX) + ? PARSE : SKIP; continue; } - if (!found_group) + switch (found_group) { + case NONE: fprintf(stderr, "error: Found option without preceding group in config file: %s at line: %d\n", name,line); goto err; + case PARSE: + break; + case SKIP: + continue; } - - + end= remove_end_comment(ptr); if ((value= strchr(ptr, '='))) end= value; for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; - if (!value) - { - strmake(strmov(option,"--"),ptr, (size_t) (end-ptr)); - if (opt_handler(handler_ctx, curr_gr, option)) - goto err; - } - else + ptr= strmake(strmov(option,"--"), ptr, (size_t) (end-ptr)); + if (value) { /* Remove pre- and end space */ char *value_end; @@ -946,9 +789,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, value++; value_end--; } - ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr)); *ptr++= '='; - for ( ; value != value_end; value++) { if (*value == '\\' && value != value_end-1) @@ -988,9 +829,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler, *ptr++= *value; } *ptr=0; - if (opt_handler(handler_ctx, curr_gr, option)) - goto err; } + + if (add_option(ctx, option)) + goto err; } mysql_file_fclose(fp, MYF(0)); return(0); diff --git a/mysys/my_error.c b/mysys/my_error.c index 5f1ca0af55b..cb1fbfe1c04 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -118,7 +118,7 @@ void my_error(uint nr, myf MyFlags, ...) else { va_start(args,MyFlags); - (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + (void) my_vsnprintf_ex(&my_charset_utf8mb3_general_ci, ebuff, sizeof(ebuff), format, args); va_end(args); } @@ -148,7 +148,7 @@ void my_printf_error(uint error, const char *format, myf MyFlags, ...) error, MyFlags, errno, format)); va_start(args,MyFlags); - (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, + (void) my_vsnprintf_ex(&my_charset_utf8mb3_general_ci, ebuff, sizeof(ebuff), format, args); va_end(args); (*error_handler_hook)(error, ebuff, MyFlags); diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 7d539cd44fe..9ebf63bf6ef 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -24,6 +24,7 @@ #include <my_getopt.h> #include <errno.h> +my_bool is_file_marker(const char* arg); typedef void (*init_func_p)(const struct my_option *option, void *variable, longlong value); @@ -31,7 +32,7 @@ static void default_reporter(enum loglevel level, const char *format, ...); my_error_reporter my_getopt_error_reporter= &default_reporter; static int findopt(char *, uint, const struct my_option **, const char **); -my_bool getopt_compare_strings(const char *, const char *, uint); +static my_bool getopt_compare_strings(const char *, const char *, uint); static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *, const struct my_option *, int *); static double getopt_double(char *arg, const struct my_option *optp, int *err); @@ -79,8 +80,9 @@ my_bool my_getopt_skip_unknown= 0; */ my_bool my_getopt_prefix_matching= 1; -static void default_reporter(enum loglevel level, - const char *format, ...) +my_getopt_value my_getopt_get_addr= 0; + +static void default_reporter(enum loglevel level, const char *format, ...) { va_list args; DBUG_ENTER("default_reporter"); @@ -97,13 +99,6 @@ static void default_reporter(enum loglevel level, DBUG_VOID_RETURN; } -static my_getopt_value getopt_get_addr; - -void my_getopt_register_get_addr(my_getopt_value func_addr) -{ - getopt_get_addr= func_addr; -} - union ull_dbl { ulonglong ull; @@ -140,7 +135,7 @@ double getopt_ulonglong2double(ulonglong v) or until the end of argv. Parse options, check that the given option matches with one of the options in struct 'my_option'. Check that option was given an argument if it requires one - Call the optional 'get_one_option()' function once for each option. + Call the 'get_one_option()' function once for each option. Note that handle_options() can be invoked multiple times to parse a command line in several steps. @@ -187,19 +182,18 @@ double getopt_ulonglong2double(ulonglong v) @param [in, out] argc command line options (count) @param [in, out] argv command line options (values) @param [in] longopts descriptor of all valid options - @param [in] get_one_option optional callback function to process each option, - can be NULL. + @param [in] get_one_option callback function to process each option @return error in case of ambiguous or unknown options, 0 on success. */ -int handle_options(int *argc, char ***argv, - const struct my_option *longopts, +int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_get_one_option get_one_option) { uint UNINIT_VAR(opt_found), argvpos= 0, length; my_bool end_of_options= 0, must_be_var, set_maximum_value, option_is_loose, option_is_autoset; char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN]; + char *filename= (char*)""; const char *UNINIT_VAR(prev_found); const struct my_option *optp; void *value; @@ -208,40 +202,35 @@ int handle_options(int *argc, char ***argv, DBUG_ENTER("handle_options"); /* handle_options() assumes arg0 (program name) always exists */ - DBUG_ASSERT(argc && *argc >= 1); - DBUG_ASSERT(argv && *argv); + DBUG_ASSERT(*argc >= 1); + DBUG_ASSERT(*argv); (*argc)--; /* Skip the program name */ (*argv)++; /* --- || ---- */ init_variables(longopts, init_one_value); - /* - Search for args_separator, if found, then the first part of the - arguments are loaded from configs - */ - for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) - { - if (my_getopt_is_args_separator(*pos)) - { - is_cmdline_arg= 0; - break; - } - } + is_cmdline_arg= !is_file_marker(**argv); for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { char **first= pos; char *cur_arg= *pos; opt_found= 0; - if (!is_cmdline_arg && (my_getopt_is_args_separator(cur_arg))) + if (!is_cmdline_arg) { - is_cmdline_arg= 1; - - /* save the separator too if skip unknown options */ - if (my_getopt_skip_unknown) - (*argv)[argvpos++]= cur_arg; - else - (*argc)--; - continue; + if (is_file_marker(cur_arg)) + { + pos++; + filename= *pos; + is_cmdline_arg= *filename == 0; /* empty file name = command line */ + if (my_getopt_skip_unknown) + { + (*argv)[argvpos++]= cur_arg; + (*argv)[argvpos++]= filename; + } + else + (*argc)-= 2; + continue; + } } if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ { @@ -408,9 +397,9 @@ int handle_options(int *argc, char ***argv, DBUG_RETURN(EXIT_OPTION_DISABLED); } error= 0; - value= optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : - optp->value; + value= optp->var_type & GET_ASK_ADDR + ? (*my_getopt_get_addr)(key_name, (uint)strlen(key_name), optp, &error) + : optp->value; if (error) DBUG_RETURN(error); @@ -453,9 +442,9 @@ int handle_options(int *argc, char ***argv, my_progname, optp->name, optend); continue; } - if (get_one_option && get_one_option(optp->id, optp, - *((my_bool*) value) ? - enabled_my_option : disabled_my_option)) + if (get_one_option(optp, *((my_bool*) value) ? + enabled_my_option : disabled_my_option, + filename)) DBUG_RETURN(EXIT_ARGUMENT_INVALID); continue; } @@ -472,12 +461,7 @@ int handle_options(int *argc, char ***argv, DBUG_RETURN(EXIT_NO_ARGUMENT_ALLOWED); } - /* - We support automatic setup only via get_one_option and only for - marked options. - */ - if (!get_one_option || - !(optp->var_type & GET_AUTO)) + if (!(optp->var_type & GET_AUTO)) { my_getopt_error_reporter(option_is_loose ? WARNING_LEVEL : ERROR_LEVEL, @@ -493,10 +477,11 @@ 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'. - */ + /* + Check if there are more arguments after this one, + Note: options loaded from config file that requires value + should always be in the form '--option=value'. + */ if (!is_cmdline_arg || !*++pos) { if (my_getopt_print_errors) @@ -534,7 +519,7 @@ int handle_options(int *argc, char ***argv, optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option && get_one_option(optp->id, optp, argument)) + if (get_one_option(optp, argument, filename)) DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); continue; } @@ -554,7 +539,7 @@ int handle_options(int *argc, char ***argv, { if (optp->var_type == GET_BOOL) *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option && get_one_option(optp->id, optp, argument)) + if (get_one_option(optp, argument, filename)) DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); continue; } @@ -575,7 +560,7 @@ int handle_options(int *argc, char ***argv, if ((error= setval(optp, optp->value, argument, set_maximum_value))) DBUG_RETURN(error); - if (get_one_option && get_one_option(optp->id, optp, argument)) + if (get_one_option(optp, argument, filename)) DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); break; } @@ -622,7 +607,7 @@ int handle_options(int *argc, char ***argv, ((error= setval(optp, value, argument, set_maximum_value))) && !option_is_loose) DBUG_RETURN(error); - if (get_one_option && get_one_option(optp->id, optp, argument)) + if (get_one_option(optp, argument, filename)) DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); (*argc)--; /* option handled (long), decrease argument count */ @@ -1430,8 +1415,8 @@ static void init_variables(const struct my_option *options, */ if (options->u_max_value) func_init_one_value(options, options->u_max_value, options->max_value); - value= (options->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, options, 0) : options->value); + value= options->var_type & GET_ASK_ADDR ? + (*my_getopt_get_addr)("", 0, options, 0) : options->value; if (value) func_init_one_value(options, value, options->def_value); } @@ -1635,8 +1620,8 @@ void my_print_variables(const struct my_option *options) for (optp= options; optp->name; optp++) { - void *value= (optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, optp, 0) : optp->value); + void *value= optp->var_type & GET_ASK_ADDR ? + (*my_getopt_get_addr)("", 0, optp, 0) : optp->value; if (value) { length= print_name(optp); diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index 18218c2e8de..ce8a9ca786f 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -21,10 +21,8 @@ #ifdef _WIN32 #define OFFSET_TO_EPOC 116444736000000000LL static ulonglong query_performance_frequency; -typedef void (WINAPI* get_system_time_as_filetime_t)(LPFILETIME); -static get_system_time_as_filetime_t - my_GetSystemTimePreciseAsFileTime= GetSystemTimeAsFileTime; #endif + #ifdef HAVE_LINUX_UNISTD_H #include <linux/unistd.h> #endif @@ -57,20 +55,12 @@ ulonglong my_interval_timer() #elif defined(HAVE_GETHRTIME) return gethrtime(); #elif defined(_WIN32) + DBUG_ASSERT(query_performance_frequency); LARGE_INTEGER t_cnt; - if (query_performance_frequency) - { - QueryPerformanceCounter(&t_cnt); - return (t_cnt.QuadPart / query_performance_frequency * 1000000000ULL) + + QueryPerformanceCounter(&t_cnt); + return (t_cnt.QuadPart / query_performance_frequency * 1000000000ULL) + ((t_cnt.QuadPart % query_performance_frequency) * 1000000000ULL / query_performance_frequency); - } - else - { - ulonglong newtime; - my_GetSystemTimePreciseAsFileTime((FILETIME*)&newtime); - return newtime*100ULL; - } #else /* TODO: check for other possibilities for hi-res timestamping */ struct timeval tv; @@ -87,7 +77,7 @@ my_hrtime_t my_hrtime() my_hrtime_t hrtime; #if defined(_WIN32) ulonglong newtime; - my_GetSystemTimePreciseAsFileTime((FILETIME*)&newtime); + GetSystemTimePreciseAsFileTime((FILETIME*)&newtime); hrtime.val= (newtime - OFFSET_TO_EPOC)/10; #elif defined(HAVE_CLOCK_GETTIME) struct timespec tp; @@ -129,14 +119,8 @@ void my_time_init() #ifdef _WIN32 compile_time_assert(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency)); - if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) - query_performance_frequency= 0; - - get_system_time_as_filetime_t f= (get_system_time_as_filetime_t) - GetProcAddress(GetModuleHandle("kernel32"), - "GetSystemTimePreciseAsFileTime"); - if (f) - my_GetSystemTimePreciseAsFileTime= f; + QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency); + DBUG_ASSERT(query_performance_frequency); #endif } diff --git a/mysys/my_init.c b/mysys/my_init.c index d8fb2003052..fdde04be084 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -22,14 +22,13 @@ #include <m_ctype.h> #include <signal.h> #include <mysql/psi/mysql_stage.h> -#ifdef __WIN__ +#ifdef _WIN32 #ifdef _MSC_VER #include <locale.h> #include <crtdbg.h> /* WSAStartup needs winsock library*/ #pragma comment(lib, "ws2_32") #endif -my_bool have_tcpip=0; static void my_win_init(void); static my_bool win32_init_tcp_ip(); #else @@ -119,8 +118,9 @@ my_bool my_init(void) my_time_init(); my_win_init(); DBUG_PRINT("exit", ("home: '%s'", home_dir)); -#ifdef __WIN__ - win32_init_tcp_ip(); +#ifdef _WIN32 + if (win32_init_tcp_ip()) + DBUG_RETURN(1); #endif #ifdef CHECK_UNLIKELY init_my_likely(); @@ -218,7 +218,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #endif -#if defined(__WIN__) && defined(_MSC_VER) +#if defined(_MSC_VER) _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); @@ -245,10 +245,9 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", (FILE *) 0); #endif /* defined(SAFE_MUTEX) */ -#ifdef __WIN__ - if (have_tcpip) - WSACleanup(); -#endif /* __WIN__ */ +#ifdef _WIN32 + WSACleanup(); +#endif /* At very last, delete mysys key, it is used everywhere including DBUG */ pthread_key_delete(THR_KEY_mysys); @@ -263,16 +262,14 @@ void my_debug_put_break_here(void) } #endif -#ifdef __WIN__ +#ifdef _WIN32 /* my_parameter_handler Invalid parameter handler we will use instead of the one "baked" - into the CRT for MSC v8. This one just prints out what invalid - parameter was encountered. By providing this routine, routines like - lseek will return -1 when we expect them to instead of crash. + into the CRT. */ void my_parameter_handler(const wchar_t * expression, const wchar_t * function, @@ -311,78 +308,14 @@ int handle_rtc_failure(int err_type, const char *file, int line, #pragma runtime_checks("", restore) #endif -/* - 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) { DBUG_ENTER("my_win_init"); #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 -#if _MSC_VER >= 1400 - /* this is required to make crt functions return -1 appropriately */ _set_invalid_parameter_handler(my_parameter_handler); #endif -#endif #ifdef __MSVC_RUNTIME_CHECKS /* @@ -394,75 +327,22 @@ static void my_win_init(void) _tzset(); - win_init_registry(); - DBUG_VOID_RETURN; } -/*------------------------------------------------------------------ - Name: CheckForTcpip| Desc: checks if tcpip has been installed on system - According to Microsoft Developers documentation the first registry - entry should be enough to check if TCP/IP is installed, but as expected - this doesn't work on all Win32 machines :( -------------------------------------------------------------------*/ - -#define TCPIPKEY "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters" -#define WINSOCK2KEY "SYSTEM\\CurrentControlSet\\Services\\Winsock2\\Parameters" -#define WINSOCKKEY "SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters" - -static my_bool win32_have_tcpip(void) -{ - HKEY hTcpipRegKey; - if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, TCPIPKEY, 0, KEY_READ, - &hTcpipRegKey) != ERROR_SUCCESS) - { - if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, WINSOCK2KEY, 0, KEY_READ, - &hTcpipRegKey) != ERROR_SUCCESS) - { - if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, WINSOCKKEY, 0, KEY_READ, - &hTcpipRegKey) != ERROR_SUCCESS) - if (!getenv("HAVE_TCPIP") || have_tcpip) /* Provide a workaround */ - return (FALSE); - } - } - RegCloseKey ( hTcpipRegKey); - return (TRUE); -} - - static my_bool win32_init_tcp_ip() { - if (win32_have_tcpip()) + WORD wVersionRequested = MAKEWORD( 2, 2 ); + WSADATA wsaData; + if (WSAStartup(wVersionRequested, &wsaData)) { - WORD wVersionRequested = MAKEWORD( 2, 2 ); - WSADATA wsaData; - /* Be a good citizen: maybe another lib has already initialised - sockets, so don't clobber them unless necessary */ - if (WSAStartup( wVersionRequested, &wsaData )) - { - /* Load failed, maybe because of previously loaded - incompatible version; try again */ - WSACleanup( ); - if (!WSAStartup( wVersionRequested, &wsaData )) - have_tcpip=1; - } - else - { - if (wsaData.wVersion != wVersionRequested) - { - /* Version is no good, try again */ - WSACleanup( ); - if (!WSAStartup( wVersionRequested, &wsaData )) - have_tcpip=1; - } - else - have_tcpip=1; - } + fprintf(stderr, "WSAStartup() failed with error: %d\n", WSAGetLastError()); + return 1; } return(0); } -#endif /* __WIN__ */ +#endif /* _WIN32 */ PSI_stage_info stage_waiting_for_table_level_lock= {0, "Waiting for table level lock", 0}; diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index e2795ed7bb9..ac6d3f87de3 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -405,3 +405,66 @@ int pthread_dummy(int ret) { return ret; } + + +/* + pthread_attr_setstacksize() without so much platform-dependency + + Return: The actual stack size if possible. +*/ + +size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + size_t guard_size __attribute__((unused))= 0; + +#if defined(__ia64__) || defined(__ia64) + /* + On IA64, half of the requested stack size is used for "normal stack" + and half for "register stack". The space measured by check_stack_overrun + is the "normal stack", so double the request to make sure we have the + caller-expected amount of normal stack. + + NOTE: there is no guarantee that the register stack can't grow faster + than normal stack, so it's very unclear that we won't dump core due to + stack overrun despite check_stack_overrun's efforts. Experimentation + shows that in the execution_constants test, the register stack grows + less than half as fast as normal stack, but perhaps other scenarios are + less forgiving. If it turns out that more space is needed for the + register stack, that could be forced (rather inefficiently) by using a + multiplier higher than 2 here. + */ + stacksize *= 2; +#endif + + /* + On many machines, the "guard space" is subtracted from the requested + stack size, and that space is quite large on some platforms. So add + it to our request, if we can find out what it is. + */ +#ifdef HAVE_PTHREAD_ATTR_GETGUARDSIZE + if (pthread_attr_getguardsize(attr, &guard_size)) + guard_size = 0; /* if can't find it out, treat as 0 */ +#endif /* HAVE_PTHREAD_ATTR_GETGUARDSIZE */ + + pthread_attr_setstacksize(attr, stacksize + guard_size); + + /* Retrieve actual stack size if possible */ +#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE + { + size_t real_stack_size= 0; + /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */ + if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 && + real_stack_size > guard_size) + { + real_stack_size -= guard_size; + if (real_stack_size < stacksize) + stacksize= real_stack_size; + } + } +#endif /* HAVE_PTHREAD_ATTR_GETSTACKSIZE */ + +#if defined(__ia64__) || defined(__ia64) + stacksize /= 2; +#endif + return stacksize; +} diff --git a/mysys/my_winfile.c b/mysys/my_winfile.c index 0c76eb25560..9c8d747adc9 100644 --- a/mysys/my_winfile.c +++ b/mysys/my_winfile.c @@ -501,13 +501,12 @@ static File my_get_stdfile_descriptor(FILE *stream) } -File my_win_fileno(FILE *file) +File my_win_handle2File(HANDLE hFile) { - HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file)); int retval= -1; uint i; - DBUG_ENTER("my_win_fileno"); + DBUG_ENTER("my_win_handle2File"); for(i= MY_FILE_MIN; i < my_file_limit; i++) { @@ -517,6 +516,14 @@ File my_win_fileno(FILE *file) break; } } + DBUG_RETURN(retval); +} + + +File my_win_fileno(FILE *file) +{ + DBUG_ENTER("my_win_fileno"); + int retval= my_win_handle2File((HANDLE) _get_osfhandle(fileno(file))); if(retval == -1) /* try std stream */ DBUG_RETURN(my_get_stdfile_descriptor(file)); diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 2274c505195..19dcdf11dd5 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -14,12 +14,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ -#include <my_global.h> +#include "mysys_priv.h" #include <my_stacktrace.h> #ifndef __WIN__ #include <signal.h> -#include <my_pthread.h> #include <m_string.h> #ifdef HAVE_STACKTRACE #include <unistd.h> @@ -42,11 +41,49 @@ static char *heap_start; extern char *__bss_start; #endif -void my_init_stacktrace() +/** + Default handler for printing stacktrace +*/ + +static sig_handler default_handle_fatal_signal(int sig) +{ + my_safe_printf_stderr("%s: Got signal %d. Attempting backtrace\n", + my_progname_short, sig); + my_print_stacktrace(0,0,1); +#ifndef __WIN__ + signal(sig, SIG_DFL); + kill(getpid(), sig); +#endif /* __WIN__ */ + return; +} + + +/** + Initialize priting off stacktrace at signal + + @param setup_handlers 0 only initialize variables + 1 setup signal handlers for stacktrace printing +*/ + +void my_init_stacktrace(int setup_handlers) { #if(defined HAVE_BSS_START) && !(defined __linux__) heap_start = (char*) &__bss_start; #endif + if (setup_handlers) + { + struct sigaction sa; + sa.sa_flags = SA_RESETHAND | SA_NODEFER; + sigemptyset(&sa.sa_mask); + sa.sa_handler= default_handle_fatal_signal; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); +#ifdef SIGBUS + sigaction(SIGBUS, &sa, NULL); +#endif + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + } } #ifdef __linux__ @@ -510,7 +547,7 @@ static EXCEPTION_POINTERS *exception_ptrs; #define MODULE64_SIZE_WINXP 576 #define STACKWALK_MAX_FRAMES 64 -void my_init_stacktrace() +void my_init_stacktrace(int setup_handlers __attribute__((unused))) { } diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c index ea8b73bf8f5..a8711d517f9 100644 --- a/mysys/thr_rwlock.c +++ b/mysys/thr_rwlock.c @@ -21,116 +21,66 @@ #ifdef _WIN32 -static BOOL have_srwlock= FALSE; -/* Prototypes and function pointers for windows functions */ -typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock); -typedef BOOLEAN (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) +int my_rw_init(my_rw_lock_t *rwp) { - my_InitializeSRWLock(&rwp->srwlock); + InitializeSRWLock(&rwp->srwlock); rwp->have_exclusive_srwlock = FALSE; return 0; } -static int srw_rdlock(my_rw_lock_t *rwp) +int my_rw_rdlock(my_rw_lock_t *rwp) { - my_AcquireSRWLockShared(&rwp->srwlock); + AcquireSRWLockShared(&rwp->srwlock); return 0; } -static int srw_tryrdlock(my_rw_lock_t *rwp) +int my_rw_tryrdlock(my_rw_lock_t *rwp) { - - if (!my_TryAcquireSRWLockShared(&rwp->srwlock)) + if (!TryAcquireSRWLockShared(&rwp->srwlock)) return EBUSY; return 0; } -static int srw_wrlock(my_rw_lock_t *rwp) +int my_rw_wrlock(my_rw_lock_t *rwp) { - my_AcquireSRWLockExclusive(&rwp->srwlock); + AcquireSRWLockExclusive(&rwp->srwlock); rwp->have_exclusive_srwlock= TRUE; return 0; } - -static int srw_trywrlock(my_rw_lock_t *rwp) +int my_rw_trywrlock(my_rw_lock_t *rwp) { - if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock)) + if (!TryAcquireSRWLockExclusive(&rwp->srwlock)) return EBUSY; rwp->have_exclusive_srwlock= TRUE; return 0; } -static int srw_unlock(my_rw_lock_t *rwp) +int my_rw_unlock(my_rw_lock_t *rwp) { if (rwp->have_exclusive_srwlock) { rwp->have_exclusive_srwlock= FALSE; - my_ReleaseSRWLockExclusive(&rwp->srwlock); + ReleaseSRWLockExclusive(&rwp->srwlock); } else { - my_ReleaseSRWLockShared(&rwp->srwlock); + ReleaseSRWLockShared(&rwp->srwlock); } return 0; } -#endif /*_WIN32 */ +int my_rw_destroy(my_rw_lock_t* rwp) +{ + DBUG_ASSERT(!rwp->have_exclusive_srwlock); + return 0; +} + +#else /* Source base from Sun Microsystems SPILT, simplified for MySQL use @@ -175,22 +125,6 @@ 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 ); @@ -209,10 +143,6 @@ int my_rw_init(my_rw_lock_t *rwp) 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 ); @@ -223,11 +153,6 @@ 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 */ @@ -242,12 +167,6 @@ 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) res= EBUSY; /* Can't get lock */ @@ -263,11 +182,6 @@ 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 */ @@ -289,11 +203,6 @@ 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 */ @@ -312,11 +221,6 @@ 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); @@ -347,7 +251,8 @@ int my_rw_unlock(my_rw_lock_t *rwp) return(0); } -#endif /* defined(NEED_MY_RW_LOCK) */ +#endif /* !defined _WIN32 */ +#endif /* NEED_MY_RW_LOCK*/ int rw_pr_init(rw_pr_lock_t *rwlock) diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c index 1532875d7f3..f87c1f75555 100644 --- a/mysys/thr_timer.c +++ b/mysys/thr_timer.c @@ -85,7 +85,7 @@ my_bool init_thr_timer(uint alloc_timers) /* Create a thread to handle timers */ pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setstacksize(&thr_attr,8196); + pthread_attr_setstacksize(&thr_attr,64*1024); thr_timer_inited= 1; if (mysql_thread_create(key_thread_timer, &timer_thread, &thr_attr, timer_handler, NULL)) @@ -141,6 +141,18 @@ void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), DBUG_VOID_RETURN; } +/* + Make timer periodic + + @param timer_data Timer structure + @param micro_seconds Period +*/ +void thr_timer_set_period(thr_timer_t* timer_data, ulonglong micro_seconds) +{ + DBUG_ENTER("thr_timer_set_period"); + timer_data->period= micro_seconds; + DBUG_VOID_RETURN; +} /* Request timer after X milliseconds @@ -240,18 +252,35 @@ static sig_handler process_timers(struct timespec *now) { void (*function)(void*); void *func_arg; + my_bool is_periodic; timer_data= (thr_timer_t*) queue_top(&timer_queue); function= timer_data->func; func_arg= timer_data->func_arg; + is_periodic= timer_data->period != 0; timer_data->expired= 1; /* Mark expired */ /* We remove timer before calling timer function to allow thread to delete it's timer data any time. + + Deleting timer inside the callback would not work + for periodic timers, they need to be removed from + queue prior to destroying timer_data. */ queue_remove_top(&timer_queue); /* Remove timer */ (*function)(func_arg); /* Inform thread of timeout */ + /* + If timer is periodic, recalculate next expiration time, and + reinsert it into the queue. + */ + if (is_periodic && timer_data->period) + { + set_timespec_nsec(timer_data->expire_time, timer_data->period * 1000); + timer_data->expired= 0; + queue_insert(&timer_queue, (uchar*)timer_data); + } + /* Check if next one has also expired */ timer_data= (thr_timer_t*) queue_top(&timer_queue); if (cmp_timespec(timer_data->expire_time, (*now)) > 0) diff --git a/mysys/typelib.c b/mysys/typelib.c index f0037921a87..715e7ad42ba 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -226,7 +226,7 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) NULL otherwise */ -TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from) +TYPELIB *copy_typelib(MEM_ROOT *root, const TYPELIB *from) { TYPELIB *to; uint i; |