diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-09-18 12:00:23 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-09-18 12:00:23 +0200 |
commit | 909775a7623505bea1b42327c7ce592b649dcdab (patch) | |
tree | 13dc2799539d83d0d02b0f4e2d9593489eb0bf27 /mysys | |
parent | 39f82b4e6ebed949ba17fe4884d96471574c1da1 (diff) | |
parent | 6d06ccbe5384874877485ddc470a89217d90c88d (diff) | |
download | mariadb-git-909775a7623505bea1b42327c7ce592b649dcdab.tar.gz |
mariadb-5.5.33 merge
Diffstat (limited to 'mysys')
-rw-r--r-- | mysys/CMakeLists.txt | 9 | ||||
-rw-r--r-- | mysys/file_logger.c | 223 | ||||
-rw-r--r-- | mysys/ma_dyncol.c | 36 | ||||
-rw-r--r-- | mysys/mf_tempdir.c | 2 | ||||
-rw-r--r-- | mysys/mf_tempfile.c | 2 | ||||
-rw-r--r-- | mysys/my_getopt.c | 55 | ||||
-rw-r--r-- | mysys/my_getsystime.c | 2 | ||||
-rw-r--r-- | mysys/my_static.c | 1 | ||||
-rw-r--r-- | mysys/waiting_threads.c | 1 |
9 files changed, 308 insertions, 23 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 832cd01e263..f90ad0e7aaf 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2006, 2011, Oracle and/or its affiliates +# Copyright (c) 2006, 2013, Oracle and/or its affiliates # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -37,7 +37,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c safemalloc.c my_new.cc my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c - my_rdtsc.c my_context.c) + my_rdtsc.c my_context.c file_logger.c) IF (WIN32) SET (MYSYS_SOURCES ${MYSYS_SOURCES} my_winthread.c my_wincond.c my_winerr.c my_winfile.c my_windac.c my_conio.c) @@ -78,6 +78,11 @@ IF (WIN32) TARGET_LINK_LIBRARIES(mysys IPHLPAPI) ENDIF(WIN32) +# Need explicit pthread for gcc -fsanitize=address +IF(CMAKE_USE_PTHREADS_INIT AND CMAKE_C_FLAGS MATCHES "-fsanitize=") + TARGET_LINK_LIBRARIES(mysys pthread) +ENDIF() + ADD_EXECUTABLE(thr_lock thr_lock.c) TARGET_LINK_LIBRARIES(thr_lock mysys) SET_TARGET_PROPERTIES(thr_lock PROPERTIES COMPILE_FLAGS "-DMAIN") diff --git a/mysys/file_logger.c b/mysys/file_logger.c new file mode 100644 index 00000000000..4c07b8c7854 --- /dev/null +++ b/mysys/file_logger.c @@ -0,0 +1,223 @@ +/* Copyright (C) 2012 Monty Program 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 "my_global.h" +#include <my_sys.h> +#include <mysql/service_logger.h> +#include <my_pthread.h> + +#ifdef HAVE_PSI_INTERFACE +/* These belong to the service initialization */ +static PSI_mutex_key key_LOCK_logger_service; +static PSI_mutex_info mutex_list[]= +{{ &key_LOCK_logger_service, "logger_service_file_st::lock", PSI_FLAG_GLOBAL}}; +#endif + +typedef struct logger_handle_st { + File file; + char path[FN_REFLEN]; + unsigned long long size_limit; + unsigned int rotations; + size_t path_len; + mysql_mutex_t lock; +} LSFS; + + +#define LOG_FLAGS (O_APPEND | O_CREAT | O_WRONLY) + +static unsigned int n_dig(unsigned int i) +{ + return (i == 0) ? 0 : ((i < 10) ? 1 : ((i < 100) ? 2 : 3)); +} + + +LOGGER_HANDLE *logger_open(const char *path, + unsigned long long size_limit, + unsigned int rotations) +{ + LOGGER_HANDLE new_log, *l_perm; + /* + I don't think we ever need more rotations, + but if it's so, the rotation procedure should be adapted to it. + */ + if (rotations > 999) + return 0; + + new_log.rotations= rotations; + new_log.size_limit= size_limit; + new_log.path_len= strlen(fn_format(new_log.path, path, + mysql_data_home, "", MY_UNPACK_FILENAME)); + + if (new_log.path_len+n_dig(rotations)+1 > FN_REFLEN) + { + errno= ENAMETOOLONG; + /* File path too long */ + return 0; + } + if ((new_log.file= my_open(new_log.path, LOG_FLAGS, MYF(0))) < 0) + { + errno= my_errno; + /* Check errno for the cause */ + return 0; + } + + if (!(l_perm= (LOGGER_HANDLE *) my_malloc(sizeof(LOGGER_HANDLE), MYF(0)))) + { + my_close(new_log.file, MYF(0)); + new_log.file= -1; + return 0; /* End of memory */ + } + *l_perm= new_log; + mysql_mutex_init(key_LOCK_logger_service, &l_perm->lock, MY_MUTEX_INIT_FAST); + return l_perm; +} + +int logger_close(LOGGER_HANDLE *log) +{ + int result; + File file= log->file; + mysql_mutex_destroy(&log->lock); + my_free(log); + if ((result= my_close(file, MYF(0)))) + errno= my_errno; + return result; +} + + +static char *logname(LOGGER_HANDLE *log, char *buf, unsigned int n_log) +{ + sprintf(buf+log->path_len, ".%0*u", n_dig(log->rotations), n_log); + return buf; +} + + +static int do_rotate(LOGGER_HANDLE *log) +{ + char namebuf[FN_REFLEN]; + int result; + unsigned int i; + char *buf_old, *buf_new, *tmp; + + if (log->rotations == 0) + return 0; + + memcpy(namebuf, log->path, log->path_len); + + buf_new= logname(log, namebuf, log->rotations); + buf_old= log->path; + for (i=log->rotations-1; i>0; i--) + { + logname(log, buf_old, i); + if (!access(buf_old, F_OK) && + (result= my_rename(buf_old, buf_new, MYF(0)))) + goto exit; + tmp= buf_old; + buf_old= buf_new; + buf_new= tmp; + } + if ((result= my_close(log->file, MYF(0)))) + goto exit; + namebuf[log->path_len]= 0; + result= my_rename(namebuf, logname(log, log->path, 1), MYF(0)); + log->file= my_open(namebuf, LOG_FLAGS, MYF(0)); +exit: + errno= my_errno; + return log->file < 0 || result; +} + + +int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap) +{ + int result; + my_off_t filesize; + char cvtbuf[1024]; + size_t n_bytes; + + mysql_mutex_lock(&log->lock); + if (log->rotations > 0) + if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 || + ((unsigned long long)filesize >= log->size_limit && + do_rotate(log))) + { + result= -1; + errno= my_errno; + goto exit; /* Log rotation needed but failed */ + } + + n_bytes= my_vsnprintf(cvtbuf, sizeof(cvtbuf), fmt, ap); + if (n_bytes >= sizeof(cvtbuf)) + n_bytes= sizeof(cvtbuf) - 1; + + result= my_write(log->file, (uchar *) cvtbuf, n_bytes, MYF(0)); + +exit: + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size) +{ + int result; + my_off_t filesize; + + mysql_mutex_lock(&log->lock); + if (log->rotations > 0) + if ((filesize= my_tell(log->file, MYF(0))) == (my_off_t) -1 || + ((unsigned long long)filesize >= log->size_limit && + do_rotate(log))) + { + result= -1; + errno= my_errno; + goto exit; /* Log rotation needed but failed */ + } + + result= my_write(log->file, (uchar *) buffer, size, MYF(0)); + +exit: + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_rotate(LOGGER_HANDLE *log) +{ + int result; + mysql_mutex_lock(&log->lock); + result= do_rotate(log); + mysql_mutex_unlock(&log->lock); + return result; +} + + +int logger_printf(LOGGER_HANDLE *log, const char *fmt, ...) +{ + int result; + va_list args; + va_start(args,fmt); + result= logger_vprintf(log, fmt, args); + va_end(args); + return result; +} + +void logger_init_mutexes() +{ +#ifdef HAVE_PSI_INTERFACE + if (PSI_server) + PSI_server->register_mutex("sql_logger", mutex_list, 1); +#endif +} + diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index c717f69c3e5..62227ab6834 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -1227,13 +1227,14 @@ dynamic_column_create(DYNAMIC_COLUMN *str, uint column_nr, @param header_end Pointer to the header end @param offset_size Size of offset field in bytes @param last_offset Size of the data segment + @param error Set in case of error @return number of bytes */ static size_t get_length_interval(uchar *entry, uchar *entry_next, uchar *header_end, size_t offset_size, - size_t last_offset) + size_t last_offset, my_bool *error) { size_t offset, offset_next; DYNAMIC_COLUMN_TYPE type, type_next; @@ -1241,8 +1242,12 @@ static size_t get_length_interval(uchar *entry, uchar *entry_next, type_and_offset_read(&type, &offset, entry, offset_size); if (entry_next >= header_end) + { + *error= 0; return (last_offset - offset); + } type_and_offset_read(&type_next, &offset_next, entry_next, offset_size); + *error= (offset_next > last_offset); return (offset_next - offset); } @@ -1254,17 +1259,18 @@ static size_t get_length_interval(uchar *entry, uchar *entry_next, @param header_end Pointer to the header end @param offset_size Size of offset field in bytes @param last_offset Size of the data segment + @param error Set in case of error @return number of bytes */ static size_t get_length(uchar *entry, uchar *header_end, size_t offset_size, - size_t last_offset) + size_t last_offset, my_bool *error) { return get_length_interval(entry, entry + offset_size + COLUMN_NUMBER_SIZE, - header_end, offset_size, last_offset); + header_end, offset_size, last_offset, error); } @@ -1303,6 +1309,7 @@ find_column(DYNAMIC_COLUMN_TYPE *type, uchar **data, size_t *length, uchar *entry; size_t offset, total_data, header_size, entry_size; uchar key[2+4]; + my_bool error; if (!entry_pos) entry_pos= &entry; @@ -1328,12 +1335,12 @@ find_column(DYNAMIC_COLUMN_TYPE *type, uchar **data, size_t *length, return 1; *data= header + header_size + offset; *length= get_length(entry, header + header_size, offset_size, - total_data); + total_data, &error); /* Check that the found data is withing the ranges. This can happen if we get data with wrong offsets. */ - if ((long) *length < 0 || offset + *length > total_data) + if (error || (long) *length < 0 || offset + *length > total_data) return 1; *entry_pos= entry; @@ -1378,7 +1385,8 @@ static inline my_bool read_fixed_header(DYNAMIC_COLUMN *str, @return ER_DYNCOL_* return code */ -int dynamic_column_get(DYNAMIC_COLUMN *str, uint column_nr, +enum enum_dyncol_func_result +dynamic_column_get(DYNAMIC_COLUMN *str, uint column_nr, DYNAMIC_COLUMN_VALUE *store_it_here) { uchar *data; @@ -1450,7 +1458,8 @@ err: @return ER_DYNCOL_* return code */ -int dynamic_column_delete(DYNAMIC_COLUMN *str, uint column_nr) +enum enum_dyncol_func_result +dynamic_column_delete(DYNAMIC_COLUMN *str, uint column_nr) { uchar *data, *header_entry, *read, *write; size_t offset_size, new_offset_size, length, entry_size, new_entry_size, @@ -1835,12 +1844,13 @@ dynamic_column_update_many(DYNAMIC_COLUMN *str, entry_size, column_count, &entry)) { size_t entry_data_size; + my_bool error; /* Data existed; We have to replace or delete it */ entry_data_size= get_length(entry, header_end, - offset_size, max_offset); - if ((long) entry_data_size < 0) + offset_size, max_offset, &error); + if (error || (long) entry_data_size < 0) { rc= ER_DYNCOL_FORMAT; goto end; @@ -2036,12 +2046,13 @@ dynamic_column_update_many(DYNAMIC_COLUMN *str, /* copy first the data that was not replaced in original packed data */ if (start < end) { + my_bool error; /* Add old data last in 'tmp' */ size_t data_size= get_length_interval(header_base + start * entry_size, header_base + end * entry_size, - header_end, offset_size, max_offset); - if ((long) data_size < 0 || + header_end, offset_size, max_offset, &error); + if (error || (long) data_size < 0 || data_size > max_offset - first_offset) { dynamic_column_column_free(&tmp); @@ -2102,7 +2113,8 @@ create_new_string: */ -int dynamic_column_update(DYNAMIC_COLUMN *str, uint column_nr, +enum enum_dyncol_func_result +dynamic_column_update(DYNAMIC_COLUMN *str, uint column_nr, DYNAMIC_COLUMN_VALUE *value) { return dynamic_column_update_many(str, 1, &column_nr, value); diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c index eceb90bb619..e6b56f7d1d0 100644 --- a/mysys/mf_tempdir.c +++ b/mysys/mf_tempdir.c @@ -43,7 +43,7 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) pathlist=getenv("TMP"); #endif if (!pathlist || !pathlist[0]) - pathlist=(char*) P_tmpdir; + pathlist=(char*) DEFAULT_TMPDIR; } do { diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index 15482075c39..5ff139bc92a 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -111,7 +111,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, sizeof(prefix_buff)-7),"XXXXXX") - prefix_buff); if (!dir && ! (dir =getenv("TMPDIR"))) - dir=P_tmpdir; + dir=DEFAULT_TMPDIR; if (strlen(dir)+ pfx_len > FN_REFLEN-2) { errno=my_errno= ENAMETOOLONG; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 0645e413672..67e074e7e59 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1,5 +1,6 @@ /* - Copyright (c) 2002, 2011, Oracle and/or its affiliates + Copyright (c) 2002, 2013, Oracle and/or its affiliates + Copyright (c) 2009, 2013, Monty Program 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 @@ -94,6 +95,35 @@ void my_getopt_register_get_addr(my_getopt_value func_addr) getopt_get_addr= func_addr; } +union ull_dbl +{ + ulonglong ull; + double dbl; +}; + +/** + Returns an ulonglong value containing a raw + representation of the given double value. +*/ +ulonglong getopt_double2ulonglong(double v) +{ + union ull_dbl u; + u.dbl= v; + compile_time_assert(sizeof(ulonglong) >= sizeof(double)); + return u.ull; +} + +/** + Returns the double value which corresponds to + the given raw representation. +*/ +double getopt_ulonglong2double(ulonglong v) +{ + union ull_dbl u; + u.ull= v; + return u.dbl; +} + /** Handle command line options. Sort options. @@ -810,6 +840,7 @@ static int findopt(char *optpat, uint length, { uint count; const struct my_option *opt= *opt_res; + my_bool is_prefix= FALSE; DBUG_ENTER("findopt"); for (count= 0; opt->name; opt++) @@ -819,11 +850,14 @@ static int findopt(char *optpat, uint length, (*opt_res)= opt; if (!opt->name[length]) /* Exact match */ DBUG_RETURN(1); + if (!count) { /* We only need to know one prev */ count= 1; *ffname= opt->name; + if (opt->name[length]) + is_prefix= TRUE; } else if (strcmp(*ffname, opt->name)) { @@ -835,6 +869,12 @@ static int findopt(char *optpat, uint length, } } } + if (is_prefix && count == 1) + my_getopt_error_reporter(WARNING_LEVEL, + "Using unique option prefix %.*s instead of %s " + "is deprecated and will be removed in a future " + "release. Please use the full name instead.", + length, optpat, *ffname); DBUG_RETURN(count); } @@ -1061,16 +1101,19 @@ double getopt_double_limit_value(double num, const struct my_option *optp, { my_bool adjusted= FALSE; double old= num; + double min, max; DBUG_ENTER("getopt_double_limit_value"); - if (optp->max_value && num > (double) optp->max_value) + max= getopt_ulonglong2double(optp->max_value); + min= getopt_ulonglong2double(optp->min_value); + if (max && num > max) { - num= (double) optp->max_value; + num= max; adjusted= TRUE; } - if (num < (double) optp->min_value) + if (num < min) { - num= (double) optp->min_value; + num= min; adjusted= TRUE; } if (fix) @@ -1153,7 +1196,7 @@ static void init_one_value(const struct my_option *option, void *variable, *((ulonglong*) variable)= (ulonglong) value; break; case GET_DOUBLE: - *((double*) variable)= ulonglong2double(value); + *((double*) variable)= getopt_ulonglong2double(value); break; case GET_STR: /* diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c index 74289556262..1cedeb21d6e 100644 --- a/mysys/my_getsystime.c +++ b/mysys/my_getsystime.c @@ -113,7 +113,7 @@ void my_time_init() /* - Return cpu time in milliseconds * 10 + Return cpu time in 1/10th on a microsecond (1e-7 s) */ ulonglong my_getcputime() diff --git a/mysys/my_static.c b/mysys/my_static.c index bc2d8beac83..fdc01b1248b 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -28,6 +28,7 @@ my_bool timed_mutexes= 0; /* from my_init */ char * home_dir=0; +char *mysql_data_home= (char*) "."; const char *my_progname= NULL, *my_progname_short= NULL; char curr_dir[FN_REFLEN]= {0}, home_dir_buff[FN_REFLEN]= {0}; diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c index 0a9474e68b4..c861dcc738c 100644 --- a/mysys/waiting_threads.c +++ b/mysys/waiting_threads.c @@ -475,6 +475,7 @@ void wt_end() my_atomic_rwlock_destroy(&cycle_stats_lock); my_atomic_rwlock_destroy(&success_stats_lock); my_atomic_rwlock_destroy(&wait_stats_lock); + reshash.alloc.constructor= NULL; wt_init_done= 0; DBUG_VOID_RETURN; } |