diff options
author | unknown <tnurnberg@mysql.com/white.intern.koehntopp.de> | 2007-11-30 06:32:04 +0100 |
---|---|---|
committer | unknown <tnurnberg@mysql.com/white.intern.koehntopp.de> | 2007-11-30 06:32:04 +0100 |
commit | 89a208850a714d5653207cffa2d654e86063a7e7 (patch) | |
tree | d9c1641496d14878b7f46428eea3f65b3a7aeb9b /mysys/my_getopt.c | |
parent | 9e6bb07d3845566ffa7274bb14df544c8147f594 (diff) | |
download | mariadb-git-89a208850a714d5653207cffa2d654e86063a7e7.tar.gz |
Bug#31177: Server variables can't be set to their current values
Default values of variables were not subject to upper/lower bounds
and step, while setting variables was. Bounds and step are also
applied to defaults now; defaults are corrected quietly, values
given by the user are corrected, and a correction-warning is thrown
as needed. Lastly, very large values could wrap around, starting
from 0 again. They are bounded at the maximum value for the
respective data-type now if no lower maximum is specified in the
variable's definition.
client/mysql.cc:
correct maxima in options array
client/mysqltest.c:
adjust minimum for "sleep" option so default value is no longer
out of bounds.
include/m_string.h:
ullstr() - the unsigned brother of llstr()
include/my_getopt.h:
Flag if we bounded the value (that is, correct anything aside from
making value a multiple of block-size)
mysql-test/r/delayed.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/index_merge.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/innodb.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/innodb_mysql.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/key_cache.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/packet.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/ps.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/subselect.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/type_bit.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/type_bit_innodb.result:
We throw a warning now when we adjust out of range parameters.
mysql-test/r/variables.result:
correct results: bounds and step apply to variables' default values, too
mysql-test/t/variables.test:
correct results: bounds and step apply to variables' default values, too
mysys/my_getopt.c:
- apply bounds/step to default values of variables (based on work by serg)
- print complaints about incorrect values for variables (truncation etc.,
by requestion of consulting)
- if no lower maximum is specified in variable definition, bound unsigned
values at their maximum to prevent wrap-around
- some calls to error_reporter had a \n, some didn't. remove \n from calls,
let reporter-function handle it, so the default reporter behaves like that
in mysqld
sql/mysql_priv.h:
correct RANGE_ALLOC_BLOCK_SIZE (cleared with monty)
sql/mysqld.cc:
correct maxima to correct data-type.
correct minima where higher than default.
correct range-alloc-block-size.
correct inno variables so GET_* corresponds to actual variable's type.
sql/set_var.cc:
When the new value for a variable is out of bounds, we'll send the
client a warning (but not if the value was simply not a multiple of
'blocksize'). sys_var_thd_ulong had this, sys_var_long_ptr_global
didn't; broken out and streamlined to avoid duplication of code.
strings/llstr.c:
ullstr() - the unsigned brother of llstr()
Diffstat (limited to 'mysys/my_getopt.c')
-rw-r--r-- | mysys/my_getopt.c | 175 |
1 files changed, 127 insertions, 48 deletions
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 71630e1b4c2..f41e8166876 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -31,6 +31,7 @@ my_bool getopt_compare_strings(const char *s, const char *t, uint length); static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); +static longlong getopt_ll_limit_value(longlong, const struct my_option *); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); static void init_variables(const struct my_option *options); @@ -70,6 +71,7 @@ static void default_reporter(enum loglevel level, fprintf(stderr, "%s", "Info: "); vfprintf(stderr, format, args); va_end(args); + fputc('\n', stderr); fflush(stderr); } @@ -133,7 +135,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; } @@ -151,7 +153,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; } @@ -165,7 +167,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; } @@ -228,7 +230,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); @@ -265,7 +267,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; @@ -273,9 +275,9 @@ int handle_options(int *argc, char ***argv, else { if (my_getopt_print_errors) - my_getopt_error_reporter(option_is_loose ? + my_getopt_error_reporter(option_is_loose ? WARNING_LEVEL : ERROR_LEVEL, - "%s: unknown option '--%s'\n", + "%s: unknown option '--%s'", my_progname, cur_arg); if (!option_is_loose) return EXIT_UNKNOWN_OPTION; @@ -293,7 +295,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; } @@ -301,7 +303,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; @@ -324,7 +326,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; } @@ -337,7 +339,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; } @@ -359,7 +361,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; } @@ -390,7 +392,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; } @@ -450,7 +452,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; } @@ -463,7 +465,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; } @@ -475,7 +477,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; } @@ -486,13 +488,13 @@ 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; } get_one_option(optp->id, optp, argument); - (*argc)--; /* option handled (short or long), decrease argument count */ + (*argc)--; /* option handled (short or long), decrease argument count */ } else /* non-option found */ (*argv)[argvpos++]= cur_arg; @@ -575,13 +577,17 @@ static int setval(const struct my_option *opts, gptr *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; @@ -733,23 +739,46 @@ 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); +} + +/* + function: getopt_ll_limit_value + + Applies min/max/block_size to a numeric value of an option. + Returns "fixed" value. +*/ + +static longlong getopt_ll_limit_value(longlong num, + const struct my_option *optp) +{ + longlong old= num; + bool trunc= 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; + trunc= TRUE; } + 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; + trunc= TRUE; + } + + if (trunc) + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': signed value %s adjusted to %s", + optp->name, llstr(old, buf1), llstr(num, buf2)); + return num; } /* @@ -761,25 +790,67 @@ 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, mod; + 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 (adjusted) + my_getopt_error_reporter(WARNING_LEVEL, + "option '%s': unsigned value %s adjusted to %s", + optp->name, ullstr(old, buf1), ullstr(num, buf2)); + + if (fix) + *fix= adjusted; + return num; } @@ -789,38 +860,43 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp) SYNOPSIS init_one_value() - option Option to initialize - value Pointer to variable + optp Option to initialize + value Pointer to variable */ -static void init_one_value(const struct my_option *option, gptr *variable, +static void init_one_value(const struct my_option *optp, gptr *variable, longlong value) { - switch ((option->var_type & GET_TYPE_MASK)) { + DBUG_ENTER("init_one_value"); + + switch ((optp->var_type & GET_TYPE_MASK)) { case GET_BOOL: *((my_bool*) variable)= (my_bool) value; break; case GET_INT: - *((int*) variable)= (int) value; + *((int*) variable)= (int) getopt_ll_limit_value(value, optp); break; case GET_UINT: - *((uint*) variable)= (uint) value; + *((uint*) variable)= (uint) getopt_ull_limit_value(value, optp, NULL); break; case GET_LONG: - *((long*) variable)= (long) value; + *((long*) variable)= (long) getopt_ll_limit_value(value, optp); break; case GET_ULONG: - *((ulong*) variable)= (ulong) value; + *((ulong*) variable)= (ulong) getopt_ull_limit_value(value, optp, NULL); break; case GET_LL: - *((longlong*) variable)= (longlong) value; + *((longlong*) variable)= (longlong) getopt_ll_limit_value(value, optp); break; case GET_ULL: - *((ulonglong*) variable)= (ulonglong) value; + *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value(value, optp, + NULL); break; default: /* dummy default to avoid compiler warnings */ break; } + + DBUG_VOID_RETURN; } @@ -839,9 +915,11 @@ static void init_one_value(const struct my_option *option, gptr *variable, static void init_variables(const struct my_option *options) { + DBUG_ENTER("init_variables"); for (; options->name; options++) { gptr *variable; + DBUG_PRINT("options", ("name: '%s'", options->name)); /* We must set u_max_value first as for some variables options->u_max_value == options->value and in this case we want to @@ -855,6 +933,7 @@ static void init_variables(const struct my_option *options) (variable= (*getopt_get_addr)("", 0, options))) init_one_value(options, variable, options->def_value); } + DBUG_VOID_RETURN; } @@ -957,8 +1036,8 @@ void my_print_variables(const struct my_option *options) (*getopt_get_addr)("", 0, optp) : optp->value); if (value) { - printf("%s", optp->name); - length= (uint) strlen(optp->name); + printf("%s ", optp->name); + length= (uint) strlen(optp->name)+1; for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { @@ -977,7 +1056,7 @@ void my_print_variables(const struct my_option *options) printf("%d\n", *((uint*) value)); break; case GET_LONG: - printf("%lu\n", *((long*) value)); + printf("%ld\n", *((long*) value)); break; case GET_ULONG: printf("%lu\n", *((ulong*) value)); |