summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-09-18 12:00:23 +0200
committerSergei Golubchik <sergii@pisem.net>2013-09-18 12:00:23 +0200
commit909775a7623505bea1b42327c7ce592b649dcdab (patch)
tree13dc2799539d83d0d02b0f4e2d9593489eb0bf27 /mysys
parent39f82b4e6ebed949ba17fe4884d96471574c1da1 (diff)
parent6d06ccbe5384874877485ddc470a89217d90c88d (diff)
downloadmariadb-git-909775a7623505bea1b42327c7ce592b649dcdab.tar.gz
mariadb-5.5.33 merge
Diffstat (limited to 'mysys')
-rw-r--r--mysys/CMakeLists.txt9
-rw-r--r--mysys/file_logger.c223
-rw-r--r--mysys/ma_dyncol.c36
-rw-r--r--mysys/mf_tempdir.c2
-rw-r--r--mysys/mf_tempfile.c2
-rw-r--r--mysys/my_getopt.c55
-rw-r--r--mysys/my_getsystime.c2
-rw-r--r--mysys/my_static.c1
-rw-r--r--mysys/waiting_threads.c1
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;
}