summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rwxr-xr-xmysys/CMakeLists.txt47
-rw-r--r--mysys/Makefile.am36
-rw-r--r--mysys/array.c7
-rw-r--r--mysys/base64.c278
-rw-r--r--mysys/charset-def.c16
-rw-r--r--mysys/charset.c186
-rw-r--r--mysys/charset2html.c177
-rw-r--r--mysys/checksum.c3
-rw-r--r--mysys/default.c663
-rw-r--r--mysys/default_modify.c227
-rw-r--r--mysys/errors.c13
-rw-r--r--mysys/hash.c21
-rw-r--r--mysys/list.c5
-rw-r--r--mysys/make-conf.c3
-rw-r--r--mysys/md5.c3
-rw-r--r--mysys/mf_brkhant.c3
-rw-r--r--mysys/mf_cache.c3
-rw-r--r--mysys/mf_dirname.c9
-rw-r--r--mysys/mf_fn_ext.c9
-rw-r--r--mysys/mf_format.c17
-rw-r--r--mysys/mf_getdate.c45
-rw-r--r--mysys/mf_iocache.c86
-rw-r--r--mysys/mf_iocache2.c138
-rw-r--r--mysys/mf_keycache.c146
-rw-r--r--mysys/mf_keycaches.c7
-rw-r--r--mysys/mf_loadpath.c3
-rw-r--r--mysys/mf_pack.c3
-rw-r--r--mysys/mf_path.c3
-rw-r--r--mysys/mf_qsort.c3
-rw-r--r--mysys/mf_qsort2.c3
-rw-r--r--mysys/mf_radix.c3
-rw-r--r--mysys/mf_same.c3
-rw-r--r--mysys/mf_sort.c3
-rw-r--r--mysys/mf_soundex.c3
-rw-r--r--mysys/mf_strip.c3
-rw-r--r--mysys/mf_tempdir.c16
-rw-r--r--mysys/mf_tempfile.c3
-rw-r--r--mysys/mf_unixpath.c3
-rw-r--r--mysys/mf_util.c3
-rw-r--r--mysys/mf_wcomp.c3
-rw-r--r--mysys/mf_wfile.c3
-rw-r--r--mysys/mulalloc.c3
-rw-r--r--mysys/my_access.c5
-rw-r--r--mysys/my_aes.c5
-rw-r--r--mysys/my_alarm.c3
-rw-r--r--mysys/my_alloc.c109
-rw-r--r--mysys/my_append.c3
-rw-r--r--mysys/my_bit.c8
-rw-r--r--mysys/my_bitmap.c152
-rw-r--r--mysys/my_chsize.c17
-rw-r--r--mysys/my_clock.c3
-rw-r--r--mysys/my_compress.c3
-rw-r--r--mysys/my_conio.c3
-rw-r--r--mysys/my_copy.c20
-rw-r--r--mysys/my_crc32.c3
-rw-r--r--mysys/my_create.c8
-rw-r--r--mysys/my_delete.c54
-rw-r--r--mysys/my_div.c3
-rw-r--r--mysys/my_dup.c5
-rw-r--r--mysys/my_error.c272
-rw-r--r--mysys/my_file.c3
-rw-r--r--mysys/my_fopen.c9
-rw-r--r--mysys/my_fstream.c11
-rw-r--r--mysys/my_gethostbyname.c6
-rw-r--r--mysys/my_gethwaddr.c5
-rw-r--r--mysys/my_getopt.c80
-rw-r--r--mysys/my_getpagesize.c40
-rw-r--r--mysys/my_getsystime.c5
-rw-r--r--mysys/my_getwd.c5
-rw-r--r--mysys/my_handler.c42
-rw-r--r--mysys/my_init.c37
-rw-r--r--mysys/my_largepage.c166
-rw-r--r--mysys/my_lib.c124
-rw-r--r--mysys/my_libwrap.c41
-rw-r--r--mysys/my_lock.c3
-rw-r--r--mysys/my_lockmem.c3
-rw-r--r--mysys/my_lread.c7
-rw-r--r--mysys/my_lwrite.c7
-rw-r--r--mysys/my_malloc.c9
-rw-r--r--mysys/my_memmem.c66
-rw-r--r--mysys/my_messnc.c3
-rw-r--r--mysys/my_mkdir.c3
-rw-r--r--mysys/my_mmap.c83
-rw-r--r--mysys/my_net.c3
-rw-r--r--mysys/my_netware.c3
-rw-r--r--mysys/my_new.cc12
-rw-r--r--mysys/my_once.c5
-rw-r--r--mysys/my_open.c201
-rw-r--r--mysys/my_os2cond.c151
-rw-r--r--mysys/my_os2dirsrch.c4
-rw-r--r--mysys/my_os2dirsrch.h4
-rw-r--r--mysys/my_os2dlfcn.c4
-rw-r--r--mysys/my_os2dlfcn.h04
-rw-r--r--mysys/my_os2file64.c4
-rw-r--r--mysys/my_os2thread.c6
-rw-r--r--mysys/my_os2tls.c4
-rw-r--r--mysys/my_port.c6
-rw-r--r--mysys/my_pread.c11
-rw-r--r--mysys/my_pthread.c5
-rw-r--r--mysys/my_quick.c3
-rw-r--r--mysys/my_read.c9
-rw-r--r--mysys/my_realloc.c9
-rw-r--r--mysys/my_redel.c5
-rw-r--r--mysys/my_rename.c3
-rw-r--r--mysys/my_seek.c13
-rw-r--r--mysys/my_sleep.c3
-rw-r--r--mysys/my_static.c14
-rw-r--r--mysys/my_static.h3
-rw-r--r--mysys/my_symlink.c3
-rw-r--r--mysys/my_symlink2.c3
-rw-r--r--mysys/my_sync.c35
-rw-r--r--mysys/my_tempnam.c173
-rw-r--r--mysys/my_thr_init.c152
-rw-r--r--mysys/my_wincond.c149
-rw-r--r--mysys/my_windac.c3
-rw-r--r--mysys/my_winthread.c5
-rw-r--r--mysys/my_write.c5
-rw-r--r--mysys/mysys_priv.h3
-rw-r--r--mysys/ptr_cmp.c42
-rw-r--r--mysys/queues.c3
-rw-r--r--mysys/raid.cc17
-rw-r--r--mysys/raid2.c4
-rw-r--r--mysys/rijndael.c5
-rw-r--r--mysys/safemalloc.c15
-rw-r--r--mysys/sha1.c17
-rw-r--r--mysys/string.c55
-rw-r--r--mysys/test_charset.c3
-rw-r--r--mysys/test_dir.c3
-rw-r--r--mysys/test_fn.c3
-rw-r--r--mysys/test_xml.c3
-rw-r--r--mysys/testhash.c3
-rw-r--r--mysys/thr_alarm.c14
-rw-r--r--mysys/thr_lock.c248
-rw-r--r--mysys/thr_mutex.c14
-rw-r--r--mysys/thr_rwlock.c3
-rw-r--r--mysys/tree.c19
-rw-r--r--mysys/typelib.c56
137 files changed, 3687 insertions, 1506 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt
new file mode 100755
index 00000000000..608d7cb1ce9
--- /dev/null
+++ b/mysys/CMakeLists.txt
@@ -0,0 +1,47 @@
+# Copyright (C) 2006 MySQL AB
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
+
+# Need to set USE_TLS, since mysys is linked into libmysql.dll and
+# libmysqld.dll, and __declspec(thread) approach to thread local storage does
+# not work properly in DLLs.
+# Currently, USE_TLS crashes in Debug builds, so until that is fixed Debug
+# .dlls cannot be loaded at runtime.
+SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DUSE_TLS")
+SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DUSE_TLS")
+SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DUSE_TLS")
+SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DUSE_TLS")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys )
+ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_modify.c
+ errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c
+ mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c
+ mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c
+ mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_tempdir.c
+ mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c
+ my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c
+ my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c
+ my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_gethostbyname.c
+ my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_handler.c my_init.c
+ my_lib.c my_lock.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c
+ my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c
+ my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c
+ my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c
+ my_windac.c my_winthread.c my_write.c ptr_cmp.c queues.c
+ rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c
+ thr_rwlock.c tree.c typelib.c base64.c my_memmem.c
+ my_getpagesize.c)
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 90a28a9ce4b..a835492e670 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -1,9 +1,8 @@
-# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+# Copyright (C) 2000-2006 MySQL AB
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
+# 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
@@ -17,8 +16,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-INCLUDES = @MT_INCLUDES@ \
- @ZLIB_INCLUDES@ -I$(top_builddir)/include \
+INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \
-I$(top_srcdir)/include -I$(srcdir)
pkglib_LIBRARIES = libmysys.a
LDADD = libmysys.a ../dbug/libdbug.a \
@@ -27,10 +25,10 @@ noinst_HEADERS = mysys_priv.h my_static.h \
my_os2cond.c my_os2dirsrch.c my_os2dirsrch.h \
my_os2dlfcn.c my_os2file64.c my_os2mutex.c \
my_os2thread.c my_os2tls.c
-libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
+libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_path.c mf_loadpath.c my_file.c \
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
- my_pread.c my_write.c \
+ my_pread.c my_write.c my_getpagesize.c \
mf_keycache.c mf_keycaches.c my_crc32.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
@@ -46,19 +44,22 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
ptr_cmp.c mf_radix.c queues.c \
tree.c list.c hash.c array.c string.c typelib.c \
my_copy.c my_append.c my_lib.c \
- my_delete.c my_rename.c my_redel.c my_tempnam.c \
+ my_delete.c my_rename.c my_redel.c \
my_chsize.c my_lread.c my_lwrite.c my_clock.c \
my_quick.c my_lockmem.c my_static.c \
my_sync.c my_getopt.c my_mkdir.c \
- default.c my_compress.c checksum.c raid.cc \
+ default_modify.c default.c \
+ my_compress.c checksum.c raid.cc \
my_net.c my_port.c my_sleep.c \
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
- my_handler.c my_netware.c my_windac.c my_access.c
+ my_handler.c my_netware.c my_largepage.c \
+ my_memmem.c \
+ my_windac.c my_access.c base64.c my_libwrap.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
- thr_mutex.c thr_rwlock.c
+ thr_mutex.c thr_rwlock.c mf_soundex.c my_conio.c \
+ my_wincond.c my_winthread.c CMakeLists.txt
libmysys_a_LIBADD = @THREAD_LOBJECTS@
-noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
@@ -68,6 +69,9 @@ DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+ -DDEFAULT_HOME_ENV=MYSQL_HOME \
+ -DDEFAULT_GROUP_SUFFIX_ENV=MYSQL_GROUP_SUFFIX \
+ -DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
@DEFS@
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
@@ -106,9 +110,6 @@ test_dir$(EXEEXT): test_dir.c $(LIBRARIES)
test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
-charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS)
-
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
@@ -117,5 +118,10 @@ test_gethwaddr$(EXEEXT): my_gethwaddr.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN ./test_gethwaddr.c $(LDADD) $(LIBS)
$(RM) -f ./test_gethwaddr.c
+test_base64$(EXEEXT): base64.c $(LIBRARIES)
+ $(CP) $(srcdir)/base64.c ./test_base64.c
+ $(LINK) $(FLAGS) -DMAIN ./test_base64.c $(LDADD) $(LIBS)
+ $(RM) -f ./test_base64.c
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/mysys/array.c b/mysys/array.c
index 6d00585f24d..4ea1946d837 100644
--- a/mysys/array.c
+++ b/mysys/array.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -16,10 +15,6 @@
/* Handling of arrays that can grow dynamicly. */
-#if defined(WIN32) || defined(__WIN__)
-#undef SAFEMALLOC /* Problems with threads */
-#endif
-
#include "mysys_priv.h"
#include "m_string.h"
diff --git a/mysys/base64.c b/mysys/base64.c
new file mode 100644
index 00000000000..47b93942784
--- /dev/null
+++ b/mysys/base64.c
@@ -0,0 +1,278 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <base64.h>
+#include <m_string.h> /* strchr() */
+
+#ifndef MAIN
+
+static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+
+int
+base64_needed_encoded_length(int length_of_data)
+{
+ int nb_base64_chars;
+ nb_base64_chars= (length_of_data + 2) / 3 * 4;
+
+ return
+ nb_base64_chars + /* base64 char incl padding */
+ (nb_base64_chars - 1)/ 76 + /* newlines */
+ 1; /* NUL termination of string */
+}
+
+
+int
+base64_needed_decoded_length(int length_of_encoded_data)
+{
+ return (int) ceil(length_of_encoded_data * 3 / 4);
+}
+
+
+/*
+ Encode a data as base64.
+
+ Note: We require that dst is pre-allocated to correct size.
+ See base64_needed_encoded_length().
+*/
+
+int
+base64_encode(const void *src, size_t src_len, char *dst)
+{
+ const unsigned char *s= (const unsigned char*)src;
+ size_t i= 0;
+ size_t len= 0;
+
+ for (; i < src_len; len += 4)
+ {
+ unsigned c;
+
+ if (len == 76)
+ {
+ len= 0;
+ *dst++= '\n';
+ }
+
+ c= s[i++];
+ c <<= 8;
+
+ if (i < src_len)
+ c += s[i];
+ c <<= 8;
+ i++;
+
+ if (i < src_len)
+ c += s[i];
+ i++;
+
+ *dst++= base64_table[(c >> 18) & 0x3f];
+ *dst++= base64_table[(c >> 12) & 0x3f];
+
+ if (i > (src_len + 1))
+ *dst++= '=';
+ else
+ *dst++= base64_table[(c >> 6) & 0x3f];
+
+ if (i > src_len)
+ *dst++= '=';
+ else
+ *dst++= base64_table[(c >> 0) & 0x3f];
+ }
+ *dst= '\0';
+
+ return 0;
+}
+
+
+static inline uint
+pos(unsigned char c)
+{
+ return (uint) (strchr(base64_table, c) - base64_table);
+}
+
+
+#define SKIP_SPACE(src, i, size) \
+{ \
+ while (i < size && my_isspace(&my_charset_latin1, * src)) \
+ { \
+ i++; \
+ src++; \
+ } \
+ if (i == size) \
+ { \
+ i= size + 1; \
+ break; \
+ } \
+}
+
+
+/*
+ Decode a base64 string
+
+ Note: We require that dst is pre-allocated to correct size.
+ See base64_needed_decoded_length().
+
+ RETURN Number of bytes produced in dst or -1 in case of failure
+*/
+int
+base64_decode(const char *src, size_t size, void *dst)
+{
+ char b[3];
+ size_t i= 0;
+ char *dst_base= (char *)dst;
+ char *d= dst_base;
+ size_t j;
+
+ while (i < size)
+ {
+ unsigned c= 0;
+ size_t mark= 0;
+
+ SKIP_SPACE(src, i, size);
+
+ c += pos(*src++);
+ c <<= 6;
+ i++;
+
+ SKIP_SPACE(src, i, size);
+
+ c += pos(*src++);
+ c <<= 6;
+ i++;
+
+ SKIP_SPACE(src, i, size);
+
+ if (* src != '=')
+ c += pos(*src++);
+ else
+ {
+ i= size;
+ mark= 2;
+ c <<= 6;
+ goto end;
+ }
+ c <<= 6;
+ i++;
+
+ SKIP_SPACE(src, i, size);
+
+ if (*src != '=')
+ c += pos(*src++);
+ else
+ {
+ i= size;
+ mark= 1;
+ goto end;
+ }
+ i++;
+
+ end:
+ b[0]= (c >> 16) & 0xff;
+ b[1]= (c >> 8) & 0xff;
+ b[2]= (c >> 0) & 0xff;
+
+ for (j=0; j<3-mark; j++)
+ *d++= b[j];
+ }
+
+ if (i != size)
+ {
+ return -1;
+ }
+ return d - dst_base;
+}
+
+
+#else /* MAIN */
+
+#define require(b) { \
+ if (!(b)) { \
+ printf("Require failed at %s:%d\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+}
+
+
+int
+main(void)
+{
+ int i;
+ size_t j;
+ size_t k, l;
+ size_t dst_len;
+ size_t needed_length;
+
+ for (i= 0; i < 500; i++)
+ {
+ /* Create source data */
+ const size_t src_len= rand() % 1000 + 1;
+
+ char * src= (char *) malloc(src_len);
+ char * s= src;
+ char * str;
+ char * dst;
+
+ for (j= 0; j<src_len; j++)
+ {
+ char c= rand();
+ *s++= c;
+ }
+
+ /* Encode */
+ needed_length= base64_needed_encoded_length(src_len);
+ str= (char *) malloc(needed_length);
+ for (k= 0; k < needed_length; k++)
+ str[k]= 0xff; /* Fill memory to check correct NUL termination */
+ require(base64_encode(src, src_len, str) == 0);
+ require(needed_length == strlen(str) + 1);
+
+ /* Decode */
+ dst= (char *) malloc(base64_needed_decoded_length(strlen(str)));
+ dst_len= base64_decode(str, strlen(str), dst);
+ require(dst_len == src_len);
+
+ if (memcmp(src, dst, src_len) != 0)
+ {
+ printf(" --------- src --------- --------- dst ---------\n");
+ for (k= 0; k<src_len; k+=8)
+ {
+ printf("%.4x ", (uint) k);
+ for (l=0; l<8 && k+l<src_len; l++)
+ {
+ unsigned char c= src[k+l];
+ printf("%.2x ", (unsigned)c);
+ }
+
+ printf(" ");
+
+ for (l=0; l<8 && k+l<dst_len; l++)
+ {
+ unsigned char c= dst[k+l];
+ printf("%.2x ", (unsigned)c);
+ }
+ printf("\n");
+ }
+ printf("src length: %.8x, dst length: %.8x\n",
+ (uint) src_len, (uint) dst_len);
+ require(0);
+ }
+ }
+ printf("Test succeeded.\n");
+ return 0;
+}
+
+#endif
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index 1fa87b715a8..394fe6de1f3 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -42,6 +41,8 @@ extern CHARSET_INFO my_charset_ucs2_slovak_uca_ci;
extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci;
extern CHARSET_INFO my_charset_ucs2_roman_uca_ci;
extern CHARSET_INFO my_charset_ucs2_persian_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci;
+extern CHARSET_INFO my_charset_ucs2_hungarian_uca_ci;
#endif
#ifdef HAVE_CHARSET_utf8
@@ -62,6 +63,8 @@ extern CHARSET_INFO my_charset_utf8_slovak_uca_ci;
extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci;
extern CHARSET_INFO my_charset_utf8_roman_uca_ci;
extern CHARSET_INFO my_charset_utf8_persian_uca_ci;
+extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci;
+extern CHARSET_INFO my_charset_utf8_hungarian_uca_ci;
#ifdef HAVE_UTF8_GENERAL_CS
extern CHARSET_INFO my_charset_utf8_general_cs;
#endif
@@ -97,6 +100,11 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_latin2_czech_ci);
#endif
+#ifdef HAVE_CHARSET_eucjpms
+ add_compiled_collation(&my_charset_eucjpms_japanese_ci);
+ add_compiled_collation(&my_charset_eucjpms_bin);
+#endif
+
#ifdef HAVE_CHARSET_euckr
add_compiled_collation(&my_charset_euckr_korean_ci);
add_compiled_collation(&my_charset_euckr_bin);
@@ -143,6 +151,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
add_compiled_collation(&my_charset_ucs2_spanish2_uca_ci);
add_compiled_collation(&my_charset_ucs2_roman_uca_ci);
add_compiled_collation(&my_charset_ucs2_persian_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci);
+ add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci);
#endif
#endif
@@ -175,6 +185,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
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);
#endif
#endif
diff --git a/mysys/charset.c b/mysys/charset.c
index 6f2d4d3c347..9fb02f1a39f 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -113,7 +112,7 @@ static my_bool init_state_maps(CHARSET_INFO *cs)
/* Special handling of hex and binary strings */
state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX;
- state_map[(uchar)'b']= state_map[(uchar)'b']= (uchar) MY_LEX_IDENT_OR_BIN;
+ state_map[(uchar)'b']= state_map[(uchar)'B']= (uchar) MY_LEX_IDENT_OR_BIN;
state_map[(uchar)'n']= state_map[(uchar)'N']= (uchar) MY_LEX_IDENT_OR_NCHAR;
return 0;
}
@@ -559,10 +558,10 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_PRINT("enter",("name: '%s'", cs_name));
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
+
cs_number= get_charset_number(cs_name, cs_flags);
cs= cs_number ? get_internal_charset(cs_number, flags) : NULL;
-
+
if (!cs && (flags & MY_WME))
{
char index_file[FN_REFLEN];
@@ -574,21 +573,54 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
}
-ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+/*
+ Escape string with backslashes (\)
+
+ SYNOPSIS
+ escape_string_for_mysql()
+ charset_info Charset of the strings
+ to Buffer for escaped string
+ to_length Length of destination buffer, or 0
+ from The string to escape
+ length The length of the string to escape
+
+ DESCRIPTION
+ This escapes the contents of a string by adding backslashes before special
+ characters, and turning others into specific escape sequences, such as
+ turning newlines into \n and null bytes into \0.
+
+ NOTE
+ To maintain compatibility with the old C API, to_length may be 0 to mean
+ "big enough"
+
+ RETURN VALUES
+ ~0 The escaped string did not fit in the to buffer
+ >=0 The length of the escaped string
+*/
+
+ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length)
{
const char *to_start= to;
- const char *end;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow= FALSE;
#ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info);
#endif
- for (end= from + length; from != end; from++)
+ for (end= from + length; from < end; from++)
{
+ char escape= 0;
#ifdef USE_MB
- int l;
- if (use_mb_flag && (l= my_ismbchar(charset_info, from, end)))
+ int tmp_length;
+ if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
{
- while (l--)
+ if (to + tmp_length > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ while (tmp_length--)
*to++= *from++;
from--;
continue;
@@ -604,48 +636,55 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
multi-byte character into a valid one. For example, 0xbf27 is not
a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \)
*/
- if (use_mb_flag && (l= my_mbcharlen(charset_info, *from)) > 1)
- {
- *to++= '\\';
- *to++= *from;
- continue;
- }
+ if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1)
+ escape= *from;
+ else
#endif
switch (*from) {
case 0: /* Must be escaped for 'mysql' */
- *to++= '\\';
- *to++= '0';
+ escape= '0';
break;
case '\n': /* Must be escaped for logs */
- *to++= '\\';
- *to++= 'n';
+ escape= 'n';
break;
case '\r':
- *to++= '\\';
- *to++= 'r';
+ escape= 'r';
break;
case '\\':
- *to++= '\\';
- *to++= '\\';
+ escape= '\\';
break;
case '\'':
- *to++= '\\';
- *to++= '\'';
+ escape= '\'';
break;
case '"': /* Better safe than sorry */
- *to++= '\\';
- *to++= '"';
+ escape= '"';
break;
case '\032': /* This gives problems on Win32 */
- *to++= '\\';
- *to++= 'Z';
+ escape= 'Z';
break;
- default:
+ }
+ if (escape)
+ {
+ if (to + 2 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ *to++= '\\';
+ *to++= escape;
+ }
+ else
+ {
+ if (to + 1 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
*to++= *from;
}
}
*to= 0;
- return (ulong) (to - to_start);
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
}
@@ -673,3 +712,84 @@ CHARSET_INFO *fs_character_set()
return fs_cset_cache;
}
#endif
+
+/*
+ Escape apostrophes by doubling them up
+
+ SYNOPSIS
+ escape_quotes_for_mysql()
+ charset_info Charset of the strings
+ to Buffer for escaped string
+ to_length Length of destination buffer, or 0
+ from The string to escape
+ length The length of the string to escape
+
+ DESCRIPTION
+ This escapes the contents of a string by doubling up any apostrophes that
+ it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in
+ effect on the server.
+
+ NOTE
+ To be consistent with escape_string_for_mysql(), to_length may be 0 to
+ mean "big enough"
+
+ RETURN VALUES
+ ~0 The escaped string did not fit in the to buffer
+ >=0 The length of the escaped string
+*/
+
+ulong escape_quotes_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
+ const char *from, ulong length)
+{
+ const char *to_start= to;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow= FALSE;
+#ifdef USE_MB
+ my_bool use_mb_flag= use_mb(charset_info);
+#endif
+ for (end= from + length; from < end; from++)
+ {
+#ifdef USE_MB
+ int tmp_length;
+ if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
+ {
+ if (to + tmp_length > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ while (tmp_length--)
+ *to++= *from++;
+ from--;
+ continue;
+ }
+ /*
+ We don't have the same issue here with a non-multi-byte character being
+ turned into a multi-byte character by the addition of an escaping
+ character, because we are only escaping the ' character with itself.
+ */
+#endif
+ if (*from == '\'')
+ {
+ if (to + 2 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ *to++= '\'';
+ *to++= '\'';
+ }
+ else
+ {
+ if (to + 1 > to_end)
+ {
+ overflow= TRUE;
+ break;
+ }
+ *to++= *from;
+ }
+ }
+ *to= 0;
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
+}
diff --git a/mysys/charset2html.c b/mysys/charset2html.c
deleted file mode 100644
index 96862ff16a1..00000000000
--- a/mysys/charset2html.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/* Copyright (C) 2000 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- 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
- */
-
-/*
- Written by Alexander Barkov to check what
- a charset is in your favorite web browser
-*/
-
-#include <my_global.h>
-#include <m_ctype.h>
-#include <my_sys.h>
-#include <mysql_version.h>
-
-#include <stdio.h>
-
-typedef struct char_info_st
-{
- int cod;
- int srt;
- int uni;
- int low;
- int upp;
- int ctp;
-} MY_CH;
-
-static int chcmp(const void *vf, const void *vs)
-{
- const MY_CH *f=vf;
- const MY_CH *s=vs;
-
- return f->srt-s->srt ? f->srt-s->srt : f->uni-s->uni;
-}
-
-static void print_cs(CHARSET_INFO *cs)
-{
- uint i;
- int srt;
- int clr=0;
- MY_CH ch[256];
-
- printf("<HTML>\n");
- printf("<HEAD>\n");
- printf("</HEAD>\n");
- printf("<BODY><PRE>\n");
- printf("Charset %s\n",cs->name);
-
- printf("<TABLE>\n");
- printf("<TR><TH>Code<TH>Uni<TH>Sort<TH>Ctype<TH>Ch<TH>Lo<TH>Up</TR>");
-
- for (i=0; i<256; i++)
- {
- ch[i].cod=i;
- ch[i].srt=cs->sort_order ? cs->sort_order[i] : i;
- ch[i].uni=cs->tab_to_uni[i];
- ch[i].low=cs->tab_to_uni[cs->to_lower[i]];
- ch[i].upp=cs->tab_to_uni[cs->to_upper[i]];
- ch[i].ctp=cs->ctype[i+1];
- }
-
- qsort(ch,256,sizeof(MY_CH),&chcmp);
- srt=ch[0].srt;
-
- for (i=0; i<256; i++)
- {
- clr = (srt!=ch[i].srt) ? !clr : clr;
-
- printf("<TR bgcolor=#%s>",clr ? "DDDDDD" : "EEEE99");
- printf("<TD>%02X",ch[i].cod);
- printf("<TD>%04X",ch[i].uni);
- printf("<TD>%02X",ch[i].srt);
-
- printf("<TD>%s%s%s%s%s%s%s%s",
- ch[i].ctp & _MY_U ? "U" : "",
- ch[i].ctp & _MY_L ? "L" : "",
- ch[i].ctp & _MY_NMR ? "N" : "",
- ch[i].ctp & _MY_SPC ? "S" : "",
- ch[i].ctp & _MY_PNT ? "P" : "",
- ch[i].ctp & _MY_CTR ? "C" : "",
- ch[i].ctp & _MY_B ? "B" : "",
- ch[i].ctp & _MY_X ? "X" : "");
-
- if ((ch[i].uni >= 0x80) && (ch[i].uni <= 0x9F))
- {
- /*
- Control characters 0x0080..0x009F are dysplayed by some
- browers as if they were letters. Don't print them to
- avoid confusion.
- */
- printf("<TD>ctrl<TD>ctrl<TD>ctrl");
- }
- else
- {
- printf("<TD>&#%d;",ch[i].uni);
- printf("<TD>&#%d;",ch[i].low);
- printf("<TD>&#%d;",ch[i].upp);
- }
- printf("</TR>\n");
- srt=ch[i].srt;
- }
- printf("</TABLE>\n");
- printf("</PRE></BODY>\n");
- printf("</HTML>\n");
-}
-
-static void print_index()
-{
- CHARSET_INFO **cs;
- int clr=0;
-
- get_charset_by_name("",MYF(0)); /* To execute init_available_charsets */
-
- printf("All charsets\n");
- printf("<table border=1>\n");
- printf("<tr bgcolor=EEEE99><th>ID<th>Charset<th>Collation<th>Def<th>Bin<th>Com<th>Comment\n");
- for (cs=all_charsets ; cs < all_charsets+256; cs++)
- {
- if (!cs[0])
- continue;
- printf("<tr bgcolor=#%s><td><a href=\"?%s\">%d</a><td>%s<td>%s<td>%s<td>%s<td>%s<td>%s\n",
- (clr= !clr) ? "DDDDDD" : "EEEE99",
- cs[0]->name,cs[0]->number,cs[0]->csname,
- cs[0]->name,
- (cs[0]->state & MY_CS_PRIMARY) ? "def " : "&nbsp;",
- (cs[0]->state & MY_CS_BINSORT) ? "bin " : "&nbsp;",
- (cs[0]->state & MY_CS_COMPILED) ? "com " : "&nbsp;",
- cs[0]->comment);
- }
- printf("</table>\n");
-}
-
-int main(int argc, char **argv) {
- const char *the_set = NULL;
- int argcnt = 1;
- CHARSET_INFO *cs;
-
- if (getenv("SCRIPT_NAME"))
- {
- printf("Content-Type: text/html\r\n\r\n");
- }
- my_init();
-
- if (argc > argcnt && argv[argcnt][0] == '-' && argv[argcnt][1] == '#')
- DBUG_PUSH(argv[argcnt++]+2);
-
- if (argc > argcnt)
- the_set = argv[argcnt++];
-
- if (argc > argcnt)
- charsets_dir = argv[argcnt++];
-
- if (!the_set)
- {
- print_index();
- return 0;
- }
-
- if (!(cs= get_charset_by_name(the_set, MYF(MY_WME))))
- return 1;
-
- print_cs(cs);
-
- return 0;
-}
diff --git a/mysys/checksum.c b/mysys/checksum.c
index 92ec3d550f1..09e9c5b3730 100644
--- a/mysys/checksum.c
+++ b/mysys/checksum.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/default.c b/mysys/default.c
index fadf6efbc5b..dc1c5a698b8 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -30,81 +29,301 @@
--no-defaults ; no options are read.
--defaults-file=full-path-to-default-file ; Only this file will be read.
--defaults-extra-file=full-path-to-default-file ; Read this file before ~/
- --print-defaults ; Print the modified command line and exit
+ --defaults-group-suffix ; Also read groups with concat(group, suffix)
+ --print-defaults ; Print the modified command line and exit
****************************************************************************/
#include "mysys_priv.h"
#include "m_string.h"
#include "m_ctype.h"
#include <my_dir.h>
+#ifdef __WIN__
+#include <winbase.h>
+#endif
-char *defaults_extra_file=0;
+const char *my_defaults_file=0;
+const char *my_defaults_group_suffix=0;
+char *my_defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
-const char *default_directories[]= {
-#ifdef __WIN__
-"C:/",
-#elif defined(__NETWARE__)
-"sys:/etc/",
-#else
-"/etc/",
-#endif
-#ifdef DATADIR
-DATADIR,
-#endif
-"", /* Place for defaults_extra_dir */
-#if !defined(__WIN__) && !defined(__NETWARE__)
-"~/",
-#endif
-NullS,
-};
+#define MAX_DEFAULT_DIRS 7
+const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
+#define NEWLINE "\r\n"
+static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN],
+ config_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
+#define NEWLINE "\n"
#endif
-static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
- const char *dir, const char *config_file,
- TYPELIB *group);
+static int handle_default_option(void *in_ctx, const char *group_name,
+ const char *option);
+
+/*
+ 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;
+ DYNAMIC_ARRAY *args;
+ TYPELIB *group;
+};
-static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+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,
- TYPELIB *group, int recursion_level);
+ const char *config_file, int recursion_level);
+static void init_default_directories();
static char *remove_end_comment(char *ptr);
/*
- Gets --defaults-file and --defaults-extra-file options from command line.
+ Process config files in default directories.
+
+ SYNOPSIS
+ my_search_option_files()
+ conf_file Basename for configuration file to search for.
+ 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.
+ DESCRIPTION
+ Process the default options from argc & argv
+ Read through each found config file looks and calls 'func' to process
+ each option.
+
+ NOTES
+ --defaults-group-suffix is only processed if we are called from
+ load_defaults().
+
+
+ RETURN
+ 0 ok
+ 1 given cinf_file doesn't exist
+
+ The global variable 'my_defaults_group_suffix' is updated with value for
+ --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 **dirs, *forced_default_file, *forced_extra_defaults;
+ 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(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV));
+
+ if (forced_extra_defaults)
+ my_defaults_extra_file= (char *) forced_extra_defaults;
+
+ if (forced_default_file)
+ my_defaults_file= forced_default_file;
+
+ /*
+ 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)
+ {
+ /* Handle --defaults-group-suffix= */
+ uint i;
+ const char **extra_groups;
+ const uint instance_len= strlen(my_defaults_group_suffix);
+ struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx;
+ char *ptr;
+ TYPELIB *group= ctx->group;
+
+ if (!(extra_groups=
+ (const char**)alloc_root(ctx->alloc,
+ (2*group->count+1)*sizeof(char*))))
+ goto err;
+
+ for (i= 0; i < group->count; i++)
+ {
+ uint len;
+ extra_groups[i]= group->type_names[i]; /** copy group */
+
+ len= strlen(extra_groups[i]);
+ if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1)))
+ goto err;
+
+ extra_groups[i+group->count]= ptr;
+
+ /** Construct new group */
+ memcpy(ptr, extra_groups[i], len);
+ memcpy(ptr+len, my_defaults_group_suffix, instance_len+1);
+ }
+
+ group->count*= 2;
+ group->type_names= extra_groups;
+ group->type_names[group->count]= 0;
+ }
+
+ if (forced_default_file)
+ {
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ forced_default_file, 0)) < 0)
+ goto err;
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ forced_default_file);
+ goto err;
+ }
+ }
+ else if (dirname_length(conf_file))
+ {
+ if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
+ goto err;
+ }
+ else
+ {
+ for (dirs= default_directories ; *dirs; dirs++)
+ {
+ if (**dirs)
+ {
+ if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
+ goto err;
+ }
+ else if (my_defaults_extra_file)
+ {
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ my_defaults_extra_file, 0)) < 0)
+ goto err; /* Fatal error */
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ my_defaults_extra_file);
+ goto err;
+ }
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+
+err:
+ fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
+ exit(1);
+ return 0; /* Keep compiler happy */
+}
+
+
+/*
+ The option handler for load_defaults.
SYNOPSIS
- get_defaults_files()
+ 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.
+ option The very option to be processed. It is already
+ prepared to be used in argv (has -- prefix)
+
+ 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.
+
+ RETURN
+ 0 - ok
+ 1 - error occured
+*/
+
+static int handle_default_option(void *in_ctx, const char *group_name,
+ const char *option)
+{
+ char *tmp;
+ struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
+
+ if (find_type((char *)group_name, ctx->group, 3))
+ {
+ if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
+ return 1;
+ if (insert_dynamic(ctx->args, (gptr) &tmp))
+ return 1;
+ strmov(tmp, option);
+ }
+
+ return 0;
+}
+
+
+/*
+ Gets options from the command line
+
+ 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
RETURN
- defaults and extra_defaults will be set to appropriate items
- of argv array, or to NULL if there are no such options
+ # 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
*/
-void get_defaults_files(int argc, char **argv,
- char **defaults, char **extra_defaults)
+int get_defaults_options(int argc, char **argv,
+ char **defaults,
+ char **extra_defaults,
+ char **group_suffix)
{
- *defaults=0;
- *extra_defaults=0;
- if (argc >= 2)
+ int org_argc= argc, prev_argc= 0;
+ *defaults= *extra_defaults= *group_suffix= 0;
+
+ while (argc >= 2 && argc != prev_argc)
{
- if (is_prefix(argv[1],"--defaults-file="))
- *defaults= argv[1];
- else if (is_prefix(argv[1],"--defaults-extra-file="))
- *extra_defaults= argv[1];
+ /* Skip program name or previously handled argument */
+ argv++;
+ prev_argc= argc; /* To check if we found */
+ 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="))
+ {
+ *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1;
+ argc--;
+ continue;
+ }
}
+ return org_argc - argc;
}
@@ -136,7 +355,6 @@ void get_defaults_files(int argc, char **argv,
RETURN
0 ok
1 The given conf_file didn't exists
- 2 The given conf_file was not a normal readable file
*/
@@ -144,17 +362,21 @@ int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
- const char **dirs, *forced_default_file, *forced_extra_defaults;
TYPELIB group;
- my_bool found_print_defaults=0;
- uint args_used=0;
+ my_bool found_print_defaults= 0;
+ uint args_used= 0;
int error= 0;
MEM_ROOT alloc;
- char *ptr, **res;
-
+ char *ptr,**res;
+ struct handle_option_ctx ctx;
DBUG_ENTER("load_defaults");
+ init_default_directories();
init_alloc_root(&alloc,512,0);
+ /*
+ 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 */
@@ -173,76 +395,22 @@ int load_defaults(const char *conf_file, const char **groups,
DBUG_RETURN(0);
}
- get_defaults_files(*argc, *argv,
- (char **)&forced_default_file,
- (char **)&forced_extra_defaults);
- if (forced_default_file)
- forced_default_file= strchr(forced_default_file,'=')+1;
- if (forced_extra_defaults)
- defaults_extra_file= strchr(forced_extra_defaults,'=')+1;
-
- args_used+= (forced_default_file ? 1 : 0) + (forced_extra_defaults ? 1 : 0);
-
group.count=0;
group.name= "defaults";
group.type_names= groups;
+
for (; *groups ; groups++)
group.count++;
if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32))
goto err;
- if (forced_default_file)
- {
- if ((error= search_default_file_with_ext(&args, &alloc, "", "",
- forced_default_file,
- &group, 0)) < 0)
- goto err;
- if (error > 0)
- {
- fprintf(stderr, "Could not open required defaults file: %s\n",
- forced_default_file);
- goto err;
- }
- }
- else if (dirname_length(conf_file))
- {
- if ((error= search_default_file(&args, &alloc, NullS, conf_file,
- &group)) < 0)
- goto err;
- }
- else
- {
-#ifdef __WIN__
- char system_dir[FN_REFLEN];
- GetWindowsDirectory(system_dir,sizeof(system_dir));
- if ((search_default_file(&args, &alloc, system_dir, conf_file, &group)))
- goto err;
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
- if ((etc= getenv("ETC")) &&
- (search_default_file(&args, &alloc, etc, conf_file,
- &group)) < 0)
- goto err;
- }
-#endif
- for (dirs=default_directories ; *dirs; dirs++)
- {
- if (**dirs)
- {
- if (search_default_file(&args, &alloc, *dirs, conf_file,
- &group) < 0)
- goto err;
- }
- else if (defaults_extra_file)
- {
- if (search_default_file(&args, &alloc, NullS, defaults_extra_file,
- &group) < 0)
- goto err; /* Fatal error */
- }
- }
- }
+
+ ctx.alloc= &alloc;
+ ctx.args= &args;
+ ctx.group= &group;
+
+ error= my_search_option_files(conf_file, argc, argv, &args_used,
+ handle_default_option, (void *) &ctx);
/*
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file
@@ -255,11 +423,14 @@ int load_defaults(const char *conf_file, const char **groups,
/* copy name + found arguments + command line arguments to new array */
res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */
memcpy((gptr) (res+1), args.buffer, args.elements*sizeof(char*));
- /* Skip --defaults-file and --defaults-extra-file */
+ /* Skip --defaults-xxx options */
(*argc)-= args_used;
(*argv)+= args_used;
- /* Check if we wan't to see the new argument list */
+ /*
+ Check if we wan't 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"))
{
found_print_defaults=1;
@@ -302,17 +473,22 @@ void free_defaults(char **argv)
}
-static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+static int search_default_file(Process_option_func opt_handler,
+ void *handler_ctx,
const char *dir,
- const char *config_file, TYPELIB *group)
+ const char *config_file)
{
char **ext;
+ const char *empty_list[]= { "", 0 };
+ my_bool have_ext= fn_ext(config_file)[0] != 0;
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
- for (ext= (char**) f_extensions; *ext; ext++)
+ for (ext= (char**) exts_to_use; *ext; ext++)
{
int error;
- if ((error= search_default_file_with_ext(args, alloc, dir, *ext,
- config_file, group, 0)) < 0)
+ if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
+ dir, *ext,
+ config_file, 0)) < 0)
return error;
}
return 0;
@@ -374,8 +550,10 @@ static char *get_argument(const char *keyword, uint kwlen,
SYNOPSIS
search_default_file_with_ext()
- args Store pointer to found options here
- alloc Allocate strings in this object
+ opt_handler Option handler function. It is used to process
+ every separate option.
+ handler_ctx Pointer to the structure to store actual
+ parameters of the function.
dir directory to read
ext Extension for configuration file
config_file Name of configuration file
@@ -387,21 +565,23 @@ static char *get_argument(const char *keyword, uint kwlen,
0 Success
-1 Fatal error, abort
1 File not found (Warning)
- 2 File is not a regular file (Warning)
*/
-static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
- const char *dir, const char *ext,
- const char *config_file,
- TYPELIB *group, int recursion_level)
+static int search_default_file_with_ext(Process_option_func opt_handler,
+ void *handler_ctx,
+ const char *dir,
+ const char *ext,
+ const char *config_file,
+ int recursion_level)
{
- char name[FN_REFLEN + 10], buff[4096], *ptr, *end, *value, *tmp, **tmp_ext;
+ char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
+ char *value, option[4096], tmp[FN_REFLEN];
static const char includedir_keyword[]= "includedir";
static const char include_keyword[]= "include";
const int max_recursion_level= 10;
FILE *fp;
- uint line= 0;
- my_bool read_values= 0, found_group= 0;
+ uint line=0;
+ my_bool found_group=0;
uint i;
MY_DIR *search_dir;
FILEINFO *search_file;
@@ -433,14 +613,14 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
if ((stat_info.st_mode & S_IWOTH) &&
(stat_info.st_mode & S_IFMT) == S_IFREG)
{
- fprintf(stderr, "warning: World-writable config file %s is ignored\n",
+ fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
name);
return 0;
}
}
#endif
- if (!(fp= my_fopen(fn_format(name, name, "", "", 4), O_RDONLY, MYF(0))))
- return 0; /* Ignore wrong files */
+ if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
+ return 1; /* Ignore wrong files */
while (fgets(buff, sizeof(buff) - 1, fp))
{
@@ -491,7 +671,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
ext= fn_ext(search_file->name);
/* check extension */
- for (tmp_ext= (char**) f_extensions; *tmp_ext; *tmp_ext++)
+ for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++)
{
if (!strcmp(ext, *tmp_ext))
break;
@@ -499,14 +679,10 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
if (*tmp_ext)
{
- if (!(tmp= alloc_root(alloc, 2 + strlen(search_file->name)
- + strlen(ptr))))
- goto err;
-
fn_format(tmp, search_file->name, ptr, "",
MY_UNPACK_FILENAME | MY_SAFE_PATH);
- search_default_file_with_ext(args, alloc, "", "", tmp, group,
+ search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
recursion_level + 1);
}
}
@@ -521,7 +697,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name, line)))
goto err;
- search_default_file_with_ext(args, alloc, "", "", ptr, group,
+ search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
recursion_level + 1);
}
@@ -540,7 +716,8 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */
end[0]=0;
- read_values=find_type(ptr,group,3) > 0;
+
+ strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
continue;
}
if (!found_group)
@@ -550,19 +727,17 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name,line);
goto err;
}
- if (!read_values)
- continue;
+
+
end= remove_end_comment(ptr);
if ((value= strchr(ptr, '=')))
end= value; /* Option without argument */
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;
if (!value)
{
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
- goto err;
- strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr));
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
+ strmake(strmov(option,"--"),ptr,(uint) (end-ptr));
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
else
{
@@ -586,12 +761,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
value++;
value_end--;
}
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
- (uint) (value_end-value)+1)))
- goto err;
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
- ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr));
+ ptr=strnmov(strmov(option,"--"),ptr,(uint) (end-ptr));
*ptr++= '=';
for ( ; value != value_end; value++)
@@ -633,6 +803,8 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
*ptr++= *value;
}
*ptr=0;
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
}
my_fclose(fp,MYF(0));
@@ -671,51 +843,31 @@ static char *remove_end_comment(char *ptr)
#include <help_start.h>
-void print_defaults(const char *conf_file, const char **groups)
+void my_print_default_files(const char *conf_file)
{
-#ifdef __WIN__
+ const char *empty_list[]= { "", 0 };
my_bool have_ext= fn_ext(conf_file)[0] != 0;
-#endif
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
char name[FN_REFLEN], **ext;
const char **dirs;
+ init_default_directories();
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
fputs(conf_file,stdout);
else
{
-#ifdef __WIN__
- GetWindowsDirectory(name,sizeof(name));
- if (!have_ext)
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", name, conf_file, *ext);
- }
- else
- printf("%s\\%s ", name, conf_file);
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
-
- if ((etc= getenv("ETC")))
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", etc, conf_file, *ext);
- }
- }
-#endif
for (dirs=default_directories ; *dirs; dirs++)
{
- for (ext= (char**) f_extensions; *ext; ext++)
+ for (ext= (char**) exts_to_use; *ext; ext++)
{
const char *pos;
char *end;
if (**dirs)
pos= *dirs;
- else if (defaults_extra_file)
- pos= defaults_extra_file;
+ else if (my_defaults_extra_file)
+ pos= my_defaults_extra_file;
else
continue;
end= convert_dirname(name, pos, NullS);
@@ -727,12 +879,30 @@ void print_defaults(const char *conf_file, const char **groups)
}
puts("");
}
+}
+
+void print_defaults(const char *conf_file, const char **groups)
+{
+ const char **groups_save= groups;
+ my_print_default_files(conf_file);
+
fputs("The following groups are read:",stdout);
for ( ; *groups ; groups++)
{
fputc(' ',stdout);
fputs(*groups,stdout);
}
+
+ if (my_defaults_group_suffix)
+ {
+ groups= groups_save;
+ for ( ; *groups ; groups++)
+ {
+ fputc(' ',stdout);
+ fputs(*groups,stdout);
+ fputs(my_defaults_group_suffix,stdout);
+ }
+ }
puts("\nThe following options may be given as the first argument:\n\
--print-defaults Print the program argument list and exit\n\
--no-defaults Don't read default options from any options file\n\
@@ -741,3 +911,144 @@ void print_defaults(const char *conf_file, const char **groups)
}
#include <help_end.h>
+
+
+#ifdef __WIN__
+/*
+ This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
+ function if it is available, emulate it on NT4 Terminal Server by stripping
+ the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just
+ return GetSystemDirectory().
+ */
+
+typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT);
+
+static uint my_get_system_windows_directory(char *buffer, uint size)
+{
+ uint count;
+ GET_SYSTEM_WINDOWS_DIRECTORY
+ func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY)
+ GetProcAddress(GetModuleHandle("kernel32.dll"),
+ "GetSystemWindowsDirectoryA");
+
+ if (func_ptr)
+ return func_ptr(buffer, size);
+
+ /*
+ Windows NT 4.0 Terminal Server Edition:
+ To retrieve the shared Windows directory, call GetSystemDirectory and
+ trim the "System32" element from the end of the returned path.
+ */
+ count= GetSystemDirectory(buffer, size);
+ if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0)
+ {
+ count-= 8;
+ buffer[count] = '\0';
+ }
+ return count;
+}
+#endif
+
+
+/*
+ Create the list of default directories.
+
+ On Microsoft Windows, this is:
+ 1. C:/
+ 2. GetWindowsDirectory()
+ 3. GetSystemWindowsDirectory()
+ 4. getenv(DEFAULT_HOME_ENV)
+ 5. Directory above where the executable is located
+ 6. ""
+ 7. --sysconfdir=<path>
+
+ On Novell NetWare, this is:
+ 1. sys:/etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+ 4. --sysconfdir=<path>
+
+ On OS/2, this is:
+ 1. getenv(ETC)
+ 2. /etc/
+ 3. getenv(DEFAULT_HOME_ENV)
+ 4. ""
+ 5. "~/"
+ 6. --sysconfdir=<path>
+
+ Everywhere else, this is:
+ 1. /etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+ 4. "~/"
+ 5. --sysconfdir=<path>
+
+ */
+
+static void init_default_directories()
+{
+ const char *env, **ptr= default_directories;
+
+#ifdef __WIN__
+ *ptr++= "C:/";
+
+ if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
+ *ptr++= (char*)&system_dir;
+ if (my_get_system_windows_directory(shared_system_dir,
+ sizeof(shared_system_dir)) &&
+ strcmp(system_dir, shared_system_dir))
+ *ptr++= (char *)&shared_system_dir;
+
+#elif defined(__NETWARE__)
+ *ptr++= "sys:/etc/";
+#else
+#if defined(__EMX__) || defined(OS2)
+ if ((env= getenv("ETC")))
+ *ptr++= env;
+#endif
+ *ptr++= "/etc/";
+#endif
+ if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ *ptr++= env;
+ *ptr++= ""; /* Place for defaults_extra_file */
+#if !defined(__WIN__) && !defined(__NETWARE__)
+ *ptr++= "~/";;
+#elif defined(__WIN__)
+ if (GetModuleFileName(NULL, config_dir, sizeof(config_dir)))
+ {
+ char *last= NULL, *end= strend(config_dir);
+ /*
+ Look for the second-to-last \ in the filename, but hang on
+ to a pointer after the last \ in case we're in the root of
+ a drive.
+ */
+ for ( ; end > config_dir; end--)
+ {
+ if (*end == FN_LIBCHAR)
+ {
+ if (last)
+ {
+ if (end != config_dir)
+ {
+ /* Keep the last '\' as this works both with D:\ and a directory */
+ end[1]= 0;
+ }
+ else
+ {
+ /* No parent directory (strange). Use current dir + '\' */
+ last[1]= 0;
+ }
+ break;
+ }
+ last= end;
+ }
+ }
+ *ptr++= (char *)&config_dir;
+ }
+#endif
+#ifdef DEFAULT_SYSCONFDIR
+ if (DEFAULT_SYSCONFDIR != "")
+ *ptr++= DEFAULT_SYSCONFDIR;
+#endif
+ *ptr= 0; /* end marker */
+}
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
new file mode 100644
index 00000000000..be40d3b3660
--- /dev/null
+++ b/mysys/default_modify.c
@@ -0,0 +1,227 @@
+/* Copyright (C) 2005 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "my_global.h"
+#include "mysys_priv.h"
+#include "m_string.h"
+#include <my_dir.h>
+
+#define BUFF_SIZE 1024
+#define RESERVE 1024 /* Extend buffer with this extent */
+
+#ifdef __WIN__
+#define NEWLINE "\r\n"
+#define NEWLINE_LEN 2
+#else
+#define NEWLINE "\n"
+#define NEWLINE_LEN 1
+#endif
+
+static char *add_option(char *dst, const char *option_value,
+ const char *option, int remove_option);
+
+
+/*
+ Add/remove option to the option file section.
+
+ SYNOPSYS
+ modify_defaults_file()
+ file_location The location of configuration file to edit
+ option option to look for
+ option value The value of the option we would like to set
+ section_name the name of the section
+ remove_option This is true if we want to remove the option.
+ False otherwise.
+ IMPLEMENTATION
+ We open the option file first, then read the file line-by-line,
+ looking for the section we need. At the same time we put these lines
+ into a buffer. Then we look for the option within this section and
+ change/remove it. In the end we get a buffer with modified version of the
+ file. Then we write it to the file, truncate it if needed and close it.
+ Note that there is a small time gap, when the file is incomplete,
+ and this theoretically might introduce a problem.
+
+ RETURN
+ 0 - ok
+ 1 - some error has occured. Probably due to the lack of resourses
+ 2 - cannot open the file
+*/
+
+int modify_defaults_file(const char *file_location, const char *option,
+ const char *option_value,
+ const char *section_name, int remove_option)
+{
+ FILE *cnf_file;
+ MY_STAT file_stat;
+ char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer;
+ uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size;
+ my_bool in_section= FALSE, opt_applied= 0;
+ uint reserve_extended;
+ uint new_opt_len;
+ int reserve_occupied= 0;
+ DBUG_ENTER("modify_defaults_file");
+
+ if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0))))
+ DBUG_RETURN(2);
+
+ /* my_fstat doesn't use the flag parameter */
+ if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
+ goto malloc_err;
+
+ opt_len= (uint) strlen(option);
+ optval_len= (uint) strlen(option_value);
+
+ new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN;
+
+ /* calculate the size of the buffer we need */
+ reserve_extended= (opt_len +
+ 1 + /* For '=' char */
+ optval_len + /* Option value len */
+ NEWLINE_LEN + /* Space for newline */
+ RESERVE); /* Some additional space */
+
+ buffer_size= (file_stat.st_size +
+ 1); /* The ending zero */
+
+ /*
+ Reserve space to read the contents of the file and some more
+ for the option we want to add.
+ */
+ if (!(file_buffer= (char*) my_malloc(buffer_size + reserve_extended,
+ MYF(MY_WME))))
+ goto malloc_err;
+
+ sect_len= (uint) strlen(section_name);
+
+ for (dst_ptr= file_buffer; fgets(linebuff, BUFF_SIZE, cnf_file); )
+ {
+ /* Skip over whitespaces */
+ for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr);
+ src_ptr++)
+ {}
+
+ if (!*src_ptr) /* Empty line */
+ {
+ nr_newlines++;
+ continue;
+ }
+
+ /* correct the option */
+ if (in_section && !strncmp(src_ptr, option, opt_len) &&
+ (*(src_ptr + opt_len) == '=' ||
+ my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) ||
+ *(src_ptr + opt_len) == '\0'))
+ {
+ char *old_src_ptr= src_ptr;
+ src_ptr= strend(src_ptr+ opt_len); /* Find the end of the line */
+
+ /* could be negative */
+ reserve_occupied+= (int) new_opt_len - (int) (src_ptr - old_src_ptr);
+ if (reserve_occupied >= (int) reserve_extended)
+ {
+ reserve_extended= (uint) reserve_occupied + RESERVE;
+ if (!(file_buffer= (char*) my_realloc(file_buffer, buffer_size +
+ reserve_extended,
+ MYF(MY_WME|MY_FREE_ON_ERROR))))
+ goto malloc_err;
+ }
+ opt_applied= 1;
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ }
+ else
+ {
+ /* If going to new group and we have option to apply, do it now */
+ if (in_section && !opt_applied && *src_ptr == '[')
+ {
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ opt_applied= 1; /* set the flag to do write() later */
+ reserve_occupied= new_opt_len+ opt_len + 1 + NEWLINE_LEN;
+ }
+
+ for (; nr_newlines; nr_newlines--)
+ dst_ptr= strmov(dst_ptr, NEWLINE);
+ dst_ptr= strmov(dst_ptr, linebuff);
+ }
+ /* Look for a section */
+ if (*src_ptr == '[')
+ {
+ /* Copy the line to the buffer */
+ if (!strncmp(++src_ptr, section_name, sect_len))
+ {
+ src_ptr+= sect_len;
+ /* Skip over whitespaces. They are allowed after section name */
+ for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++)
+ {}
+
+ if (*src_ptr != ']')
+ continue; /* Missing closing parenthesis. Assume this was no group */
+ in_section= TRUE;
+ }
+ else
+ in_section= FALSE; /* mark that this section is of no interest to us */
+ }
+ }
+ /* File ended. */
+ if (!opt_applied && !remove_option && in_section)
+ {
+ /* New option still remains to apply at the end */
+ if (*(dst_ptr - 1) != '\n')
+ dst_ptr= strmov(dst_ptr, NEWLINE);
+ dst_ptr= add_option(dst_ptr, option_value, option, remove_option);
+ opt_applied= 1;
+ }
+ for (; nr_newlines; nr_newlines--)
+ dst_ptr= strmov(dst_ptr, NEWLINE);
+
+ if (opt_applied)
+ {
+ /* Don't write the file if there are no changes to be made */
+ if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
+ MYF(MY_WME)) ||
+ my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
+ my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer),
+ MYF(MY_NABP)))
+ goto err;
+ }
+ if (my_fclose(cnf_file, MYF(MY_WME)))
+ DBUG_RETURN(1);
+
+ my_free(file_buffer, MYF(0));
+ DBUG_RETURN(0);
+
+err:
+ my_free(file_buffer, MYF(0));
+malloc_err:
+ my_fclose(cnf_file, MYF(0));
+ DBUG_RETURN(1); /* out of resources */
+}
+
+
+static char *add_option(char *dst, const char *option_value,
+ const char *option, int remove_option)
+{
+ if (!remove_option)
+ {
+ dst= strmov(dst, option);
+ if (*option_value)
+ {
+ *dst++= '=';
+ dst= strmov(dst, option_value);
+ }
+ /* add a newline */
+ dst= strmov(dst, NEWLINE);
+ }
+ return dst;
+}
diff --git a/mysys/errors.c b/mysys/errors.c
index 05436c9a212..857de1325d4 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -21,7 +20,6 @@
const char * NEAR globerrs[GLOBERRS]=
{
- "File '%s' not found (Errcode: %d)",
"Can't create/write to file '%s' (Errcode: %d)",
"Error reading file '%s' (Errcode: %d)",
"Error writing file '%s' (Errcode: %d)",
@@ -50,20 +48,18 @@ const char * NEAR globerrs[GLOBERRS]=
"Error on realpath() on '%s' (Error %d)",
"Can't sync file '%s' to disk (Errcode: %d)",
"Collation '%s' is not a compiled collation and is not specified in the '%s' file",
+ "File '%s' not found (Errcode: %d)",
};
void init_glob_errs(void)
{
- my_errmsg[GLOB] = & globerrs[0];
-} /* init_glob_errs */
+ /* This is now done statically. */
+}
#else
void init_glob_errs()
{
- my_errmsg[GLOB] = & globerrs[0];
-
- EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
EE(EE_CANTCREATEFILE) = "Can't create/write to file '%s' (Errcode: %d)";
EE(EE_READ) = "Error reading file '%s' (Errcode: %d)";
EE(EE_WRITE) = "Error writing file '%s' (Errcode: %d)";
@@ -91,5 +87,6 @@ void init_glob_errs()
EE(EE_REALPATH)= "Error on realpath() on '%s' (Error %d)";
EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)";
EE(EE_UNKNOWN_COLLATION)= "Collation '%s' is not a compiled collation and is not specified in the %s file";
+ EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
}
#endif
diff --git a/mysys/hash.c b/mysys/hash.c
index 75135a470c9..0c949b3a0d8 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -53,7 +52,7 @@ _hash_init(HASH *hash,CHARSET_INFO *charset,
void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
{
DBUG_ENTER("hash_init");
- DBUG_PRINT("enter",("hash: 0x%lx size: %d",hash,size));
+ DBUG_PRINT("enter",("hash: 0x%lx size: %d", (long) hash, size));
hash->records=0;
if (my_init_dynamic_array_ci(&hash->array,sizeof(HASH_LINK),size,0))
@@ -103,13 +102,13 @@ static inline void hash_free_elements(HASH *hash)
hash_free()
hash the hash to delete elements of
- NOTES: Hash can't be reused wuthing calling hash_init again.
+ NOTES: Hash can't be reused without calling hash_init again.
*/
void hash_free(HASH *hash)
{
DBUG_ENTER("hash_free");
- DBUG_PRINT("enter",("hash: 0x%lxd",hash));
+ DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash));
hash_free_elements(hash);
hash->free= 0;
@@ -129,7 +128,7 @@ void hash_free(HASH *hash)
void my_hash_reset(HASH *hash)
{
DBUG_ENTER("my_hash_reset");
- DBUG_PRINT("enter",("hash: 0x%lxd",hash));
+ DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash));
hash_free_elements(hash);
reset_dynamic(&hash->array);
@@ -289,9 +288,8 @@ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink)
record being compared against.
RETURN
- < 0 key of record < key
= 0 key of record == key
- > 0 key of record > key
+ != 0 key of record != key
*/
static int hashcmp(const HASH *hash, HASH_LINK *pos, const byte *key,
@@ -645,7 +643,8 @@ my_bool hash_check(HASH *hash)
if ((rec_link=hash_rec_mask(hash,hash_info,blength,records)) != i)
{
DBUG_PRINT("error",
- ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d", idx,i,hash_info->data,rec_link));
+ ("Record in wrong link at %d: Start %d Record: 0x%lx Record-link %d",
+ idx, i, (long) hash_info->data, rec_link));
error=1;
}
else
@@ -656,12 +655,12 @@ my_bool hash_check(HASH *hash)
}
if (found != records)
{
- DBUG_PRINT("error",("Found %ld of %ld records"));
+ DBUG_PRINT("error",("Found %u of %u records", found, records));
error=1;
}
if (records)
DBUG_PRINT("info",
- ("records: %ld seeks: %d max links: %d hitrate: %.2f",
+ ("records: %u seeks: %d max links: %d hitrate: %.2f",
records,seek,max_links,(float) seek / (float) records));
return error;
}
diff --git a/mysys/list.c b/mysys/list.c
index 480c1080a45..ccc3f495093 100644
--- a/mysys/list.c
+++ b/mysys/list.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -28,7 +27,7 @@
LIST *list_add(LIST *root, LIST *element)
{
DBUG_ENTER("list_add");
- DBUG_PRINT("enter",("root: 0x%lx element: %lx", root, element));
+ DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", (long) root, (long) element));
if (root)
{
if (root->prev) /* If add in mid of list */
diff --git a/mysys/make-conf.c b/mysys/make-conf.c
index 404299e1726..0dacde4dee0 100644
--- a/mysys/make-conf.c
+++ b/mysys/make-conf.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/md5.c b/mysys/md5.c
index 5de95288141..a88fb279a0b 100644
--- a/mysys/md5.c
+++ b/mysys/md5.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_brkhant.c b/mysys/mf_brkhant.c
index 4180bd6df66..3573b9973b2 100644
--- a/mysys/mf_brkhant.c
+++ b/mysys/mf_brkhant.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_cache.c b/mysys/mf_cache.c
index 2c5d8658625..a3abb3bc974 100644
--- a/mysys/mf_cache.c
+++ b/mysys/mf_cache.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c
index 45bf4d56c31..d1672e55b65 100644
--- a/mysys/mf_dirname.c
+++ b/mysys/mf_dirname.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -72,7 +71,9 @@ uint dirname_part(my_string to, const char *name)
SYNPOSIS
convert_dirname()
- to Store result here
+ to Store result here. Must be at least of size
+ min(FN_REFLEN, strlen(from) + 1) to make room
+ for adding FN_LIBCHAR at the end.
from Original filename
from_end Pointer at end of filename (normally end \0)
@@ -108,7 +109,7 @@ char *convert_dirname(char *to, const char *from, const char *from_end)
#if FN_LIBCHAR != '/' || defined(FN_C_BEFORE_DIR_2)
{
- for (; *from && from != from_end; from++)
+ for (; from != from_end && *from ; from++)
{
if (*from == '/')
*to++= FN_LIBCHAR;
diff --git a/mysys/mf_fn_ext.c b/mysys/mf_fn_ext.c
index 9c86a8072ef..20e835fe641 100644
--- a/mysys/mf_fn_ext.c
+++ b/mysys/mf_fn_ext.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -40,14 +39,14 @@ my_string fn_ext(const char *name)
DBUG_ENTER("fn_ext");
DBUG_PRINT("mfunkt",("name: '%s'",name));
-#if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR)
+#if defined(FN_DEVCHAR) || defined(FN_C_AFTER_DIR) || defined(BASKSLASH_MBTAIL)
{
char buff[FN_REFLEN];
gpos=(my_string) name+dirname_part(buff,(char*) name);
}
#else
- if (!(gpos=strrchr(name,FNLIBCHAR)))
- gpos=name;
+ if (!(gpos= strrchr(name, FN_LIBCHAR)))
+ gpos= (my_string) name;
#endif
pos=strchr(gpos,FN_EXTCHAR);
DBUG_RETURN (pos ? pos : strend(gpos));
diff --git a/mysys/mf_format.c b/mysys/mf_format.c
index d1ca1108d02..7a861c9f1e6 100644
--- a/mysys/mf_format.c
+++ b/mysys/mf_format.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -17,13 +16,12 @@
#include "mysys_priv.h"
#include <m_string.h>
- /*
- Formats a filename with possible replace of directory of extension
- Function can handle the case where 'to' == 'name'
- For a description of the flag values, consult my_sys.h
- The arguments should be in unix format.
- */
-
+/*
+ Formats a filename with possible replace of directory of extension
+ Function can handle the case where 'to' == 'name'
+ For a description of the flag values, consult my_sys.h
+ The arguments should be in unix format.
+*/
my_string fn_format(my_string to, const char *name, const char *dir,
const char *extension, uint flag)
@@ -54,6 +52,7 @@ my_string fn_format(my_string to, const char *name, const char *dir,
pack_dirname(dev,dev); /* Put in ./.. and ~/.. */
if (flag & MY_UNPACK_FILENAME)
(void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */
+
if ((pos= (char*) strchr(name,FN_EXTCHAR)) != NullS)
{
if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */
diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c
index 189d43e782a..1ced312848e 100644
--- a/mysys/mf_getdate.c
+++ b/mysys/mf_getdate.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -19,11 +18,20 @@
#include "mysys_priv.h"
#include <m_string.h>
- /*
- If flag & 1 Return date and time
- If flag & 2 Return short date format YYMMDD
- if flag & 4 Return time in HHMMDD format.
- */
+/*
+ get date as string
+
+ SYNOPSIS
+ get_date()
+ to - string where date will be written
+ flag - format of date:
+ If flag & GETDATE_TIME Return date and time
+ If flag & GETDATE_SHORT_DATE Return short date format YYMMDD
+ If flag & GETDATE_HHMMSSTIME Return time in HHMMDD format.
+ If flag & GETDATE_GMT Date/time in GMT
+ If flag & GETDATE_FIXEDLENGTH Return fixed length date/time
+ date - for conversion
+*/
void get_date(register my_string to, int flag, time_t date)
@@ -36,27 +44,36 @@ void get_date(register my_string to, int flag, time_t date)
skr=date ? (time_t) date : time((time_t*) 0);
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
- localtime_r(&skr,&tm_tmp);
+ if (flag & GETDATE_GMT)
+ localtime_r(&skr,&tm_tmp);
+ else
+ gmtime_r(&skr,&tm_tmp);
start_time= &tm_tmp;
#else
- start_time=localtime(&skr);
+ if (flag & GETDATE_GMT)
+ start_time= localtime(&skr);
+ else
+ start_time= gmtime(&skr);
#endif
- if (flag & 2)
+ if (flag & GETDATE_SHORT_DATE)
sprintf(to,"%02d%02d%02d",
start_time->tm_year % 100,
start_time->tm_mon+1,
start_time->tm_mday);
else
- sprintf(to,"%d-%02d-%02d",
+ sprintf(to, ((flag & GETDATE_FIXEDLENGTH) ?
+ "%4d-%02d-%02d" : "%d-%02d-%02d"),
start_time->tm_year+1900,
start_time->tm_mon+1,
start_time->tm_mday);
- if (flag & 1)
- sprintf(strend(to)," %2d:%02d:%02d",
+ if (flag & GETDATE_DATE_TIME)
+ sprintf(strend(to),
+ ((flag & GETDATE_FIXEDLENGTH) ?
+ " %02d:%02d:%02d" : " %2d:%02d:%02d"),
start_time->tm_hour,
start_time->tm_min,
start_time->tm_sec);
- else if (flag & 4)
+ else if (flag & GETDATE_HHMMSSTIME)
sprintf(strend(to),"%02d%02d%02d",
start_time->tm_hour,
start_time->tm_min,
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index a91002d3b4c..d2ace12da4d 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -27,7 +26,7 @@
also info->read_pos is set to info->read_end.
If called through open_cached_file(), then the temporary file will
only be created if a write exeeds the file buffer or if one calls
- flush_io_cache().
+ my_b_flush_io_cache().
If one uses SEQ_READ_APPEND, then two buffers are allocated, one for
reading and another for writing. Reads are first done from disk and
@@ -43,7 +42,7 @@ TODO:
each time the write buffer gets full and it's written to disk, we will
always do a disk read to read a part of the buffer from disk to the
read buffer.
- This should be fixed so that when we do a flush_io_cache() and
+ This should be fixed so that when we do a my_b_flush_io_cache() and
we have been reading the write buffer, we should transfer the rest of the
write buffer to the read buffer before we start to reuse it.
*/
@@ -158,19 +157,42 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
pbool use_async_io, myf cache_myflags)
{
uint min_cache;
+ my_off_t pos;
my_off_t end_of_file= ~(my_off_t) 0;
DBUG_ENTER("init_io_cache");
DBUG_PRINT("enter",("cache: 0x%lx type: %d pos: %ld",
(ulong) info, (int) type, (ulong) seek_offset));
info->file= file;
- info->type= 0; /* Don't set it until mutex are created */
+ info->type= TYPE_NOT_SET; /* Don't set it until mutex are created */
info->pos_in_file= seek_offset;
info->pre_close = info->pre_read = info->post_read = 0;
info->arg = 0;
info->alloced_buffer = 0;
info->buffer=0;
- info->seek_not_done= test(file >= 0);
+ info->seek_not_done= 0;
+
+ if (file >= 0)
+ {
+ pos= my_tell(file, MYF(0));
+ if ((pos == (my_off_t) -1) && (my_errno == ESPIPE))
+ {
+ /*
+ This kind of object doesn't support seek() or tell(). Don't set a
+ flag that will make us again try to seek() later and fail.
+ */
+ info->seek_not_done= 0;
+ /*
+ Additionally, if we're supposed to start somewhere other than the
+ the beginning of whatever this file is, then somebody made a bad
+ assumption.
+ */
+ DBUG_ASSERT(seek_offset == 0);
+ }
+ else
+ info->seek_not_done= test(seek_offset != pos);
+ }
+
info->disk_writes= 0;
#ifdef THREAD
info->share=0;
@@ -183,8 +205,10 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
{ /* Assume file isn't growing */
if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
{
- /* Calculate end of file to not allocate to big buffers */
+ /* Calculate end of file to avoid allocating oversized buffers */
end_of_file=my_seek(file,0L,MY_SEEK_END,MYF(0));
+ /* Need to reset seek_not_done now that we just did a seek. */
+ info->seek_not_done= end_of_file == seek_offset ? 0 : 1;
if (end_of_file < seek_offset)
end_of_file=seek_offset;
/* Trim cache size if the file is very small */
@@ -331,7 +355,11 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
{
info->read_end=info->write_pos;
info->end_of_file=my_b_tell(info);
- info->seek_not_done=1;
+ /*
+ Trigger a new seek only if we have a valid
+ file handle.
+ */
+ info->seek_not_done= (info->file != -1);
}
else if (type == WRITE_CACHE)
{
@@ -360,7 +388,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
if (info->type == WRITE_CACHE && type == READ_CACHE)
info->end_of_file=my_b_tell(info);
/* flush cache if we want to reuse it */
- if (!clear_cache && flush_io_cache(info))
+ if (!clear_cache && my_b_flush_io_cache(info,1))
DBUG_RETURN(1);
info->pos_in_file=seek_offset;
/* Better to do always do a seek */
@@ -449,13 +477,23 @@ int _my_b_read(register IO_CACHE *info, byte *Buffer, uint Count)
*/
if (info->seek_not_done)
{
- if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
- == MY_FILEPOS_ERROR)
+ if ((my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0))
+ != MY_FILEPOS_ERROR))
{
- info->error= -1;
- DBUG_RETURN(1);
+ /* No error, reset seek_not_done flag. */
+ info->seek_not_done= 0;
+ }
+ else
+ {
+ /*
+ If the seek failed and the error number is ESPIPE, it is because
+ info->file is a pipe or socket or FIFO. We never should have tried
+ to seek on that. See Bugs#25807 and #22828 for more info.
+ */
+ DBUG_ASSERT(my_errno != ESPIPE);
+ info->error= -1;
+ DBUG_RETURN(1);
}
- info->seek_not_done=0;
}
diff_length=(uint) (pos_in_file & (IO_SIZE-1));
@@ -589,7 +627,8 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
DBUG_ENTER("init_io_cache_share");
DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx share: 0x%lx "
"write_cache: 0x%lx threads: %u",
- read_cache, cshare, write_cache, num_threads));
+ (long) read_cache, (long) cshare,
+ (long) write_cache, num_threads));
DBUG_ASSERT(num_threads > 1);
DBUG_ASSERT(read_cache->type == READ_CACHE);
@@ -651,7 +690,7 @@ void remove_io_thread(IO_CACHE *cache)
pthread_mutex_lock(&cshare->mutex);
DBUG_PRINT("io_cache_share", ("%s: 0x%lx",
(cache == cshare->source_cache) ?
- "writer" : "reader", cache));
+ "writer" : "reader", (long) cache));
/* Remove from share. */
total= --cshare->total_threads;
@@ -727,7 +766,7 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos)
cshare->running_threads--;
DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u",
(cache == cshare->source_cache) ?
- "writer" : "reader", cache, (ulong) pos,
+ "writer" : "reader", (long) cache, (ulong) pos,
cshare->running_threads));
if (cshare->source_cache)
@@ -866,7 +905,7 @@ static void unlock_io_cache(IO_CACHE *cache)
DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u",
(cache == cshare->source_cache) ?
"writer" : "reader",
- cache, (ulong) cshare->pos_in_file,
+ (long) cache, (ulong) cshare->pos_in_file,
cshare->total_threads));
cshare->running_threads= cshare->total_threads;
@@ -966,7 +1005,7 @@ int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count)
*/
if (cache->seek_not_done)
{
- if (my_seek(cache->file,pos_in_file,MY_SEEK_SET,MYF(0))
+ if (my_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0))
== MY_FILEPOS_ERROR)
{
cache->error= -1;
@@ -1000,7 +1039,7 @@ int _my_b_read_r(register IO_CACHE *cache, byte *Buffer, uint Count)
cache->read_end= cshare->read_end;
cache->pos_in_file= cshare->pos_in_file;
- len= ((cache->error == -1) ? -1 : cache->read_end - cache->buffer);
+ len= (int) ((cache->error == -1) ? -1 : cache->read_end - cache->buffer);
}
cache->read_pos= cache->buffer;
cache->seek_not_done= 0;
@@ -1465,7 +1504,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
Count-=rest_length;
info->write_pos+=rest_length;
- if (flush_io_cache(info))
+ if (my_b_flush_io_cache(info,1))
return 1;
if (Count >= IO_SIZE)
{ /* Fill first intern buffer */
@@ -1762,6 +1801,7 @@ int end_io_cache(IO_CACHE *info)
int error=0;
IO_CACHE_CALLBACK pre_close;
DBUG_ENTER("end_io_cache");
+ DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info));
#ifdef THREAD
/*
@@ -1780,14 +1820,14 @@ int end_io_cache(IO_CACHE *info)
{
info->alloced_buffer=0;
if (info->file != -1) /* File doesn't exist */
- error=flush_io_cache(info);
+ error= my_b_flush_io_cache(info,1);
my_free((gptr) info->buffer,MYF(MY_WME));
info->buffer=info->read_pos=(byte*) 0;
}
if (info->type == SEQ_READ_APPEND)
{
/* Destroy allocated mutex */
- info->type=0;
+ info->type= TYPE_NOT_SET;
#ifdef THREAD
pthread_mutex_destroy(&info->append_buffer_lock);
#endif
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 3755bcdb53d..30e9f19a189 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -65,6 +64,13 @@ my_off_t my_b_append_tell(IO_CACHE* info)
return res;
}
+my_off_t my_b_safe_tell(IO_CACHE *info)
+{
+ if (unlikely(info->type == SEQ_READ_APPEND))
+ return my_b_append_tell(info);
+ return my_b_tell(info);
+}
+
/*
Make next read happen at the given position
For write cache, make next write happen at the given position
@@ -72,7 +78,7 @@ my_off_t my_b_append_tell(IO_CACHE* info)
void my_b_seek(IO_CACHE *info,my_off_t pos)
{
- my_off_t offset;
+ my_off_t offset;
DBUG_ENTER("my_b_seek");
DBUG_PRINT("enter",("pos: %lu", (ulong) pos));
@@ -84,10 +90,10 @@ void my_b_seek(IO_CACHE *info,my_off_t pos)
b) see if there is a better way to make it work
*/
if (info->type == SEQ_READ_APPEND)
- flush_io_cache(info);
-
+ VOID(flush_io_cache(info));
+
offset=(pos - info->pos_in_file);
-
+
if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND)
{
/* TODO: explain why this works if pos < info->pos_in_file */
@@ -112,7 +118,7 @@ void my_b_seek(IO_CACHE *info,my_off_t pos)
info->write_pos = info->write_buffer + offset;
DBUG_VOID_RETURN;
}
- flush_io_cache(info);
+ VOID(flush_io_cache(info));
/* Correct buffer end so that we write in increments of IO_SIZE */
info->write_end=(info->write_buffer+info->buffer_length-
(pos & (IO_SIZE-1)));
@@ -245,74 +251,126 @@ uint my_b_printf(IO_CACHE *info, const char* fmt, ...)
uint my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args)
{
uint out_length=0;
+ uint minimum_width; /* as yet unimplemented */
+ uint minimum_width_sign;
+ uint precision; /* as yet unimplemented for anything but %b */
+
+ /*
+ Store the location of the beginning of a format directive, for the
+ case where we learn we shouldn't have been parsing a format string
+ at all, and we don't want to lose the flag/precision/width/size
+ information.
+ */
+ const char* backtrack;
- for (; *fmt ; fmt++)
+ for (; *fmt != '\0'; fmt++)
{
- if (*fmt++ != '%')
+ /* Copy everything until '%' or end of string */
+ const char *start=fmt;
+ uint length;
+
+ for (; (*fmt != '\0') && (*fmt != '%'); fmt++) ;
+
+ length= (uint) (fmt - start);
+ out_length+=length;
+ if (my_b_write(info, start, length))
+ goto err;
+
+ if (*fmt == '\0') /* End of format */
{
- /* Copy everything until '%' or end of string */
- const char *start=fmt-1;
- uint length;
- for (; *fmt && *fmt != '%' ; fmt++ ) ;
- length= (uint) (fmt - start);
- out_length+=length;
- if (my_b_write(info, start, length))
- goto err;
- if (!*fmt) /* End of format */
- {
- return out_length;
- }
- fmt++;
- /* Found one '%' */
+ return out_length;
}
+
+ /*
+ By this point, *fmt must be a percent; Keep track of this location and
+ skip over the percent character.
+ */
+ DBUG_ASSERT(*fmt == '%');
+ backtrack= fmt;
+ fmt++;
+
+ minimum_width= 0;
+ precision= 0;
+ minimum_width_sign= 1;
/* Skip if max size is used (to be compatible with printf) */
- while (my_isdigit(&my_charset_latin1, *fmt) || *fmt == '.' || *fmt == '-')
+ while (*fmt == '-') { fmt++; minimum_width_sign= -1; }
+ if (*fmt == '*') {
+ precision= (int) va_arg(args, int);
+ fmt++;
+ } else {
+ while (my_isdigit(&my_charset_latin1, *fmt)) {
+ minimum_width=(minimum_width * 10) + (*fmt - '0');
+ fmt++;
+ }
+ }
+ minimum_width*= minimum_width_sign;
+
+ if (*fmt == '.') {
fmt++;
+ if (*fmt == '*') {
+ precision= (int) va_arg(args, int);
+ fmt++;
+ } else {
+ while (my_isdigit(&my_charset_latin1, *fmt)) {
+ precision=(precision * 10) + (*fmt - '0');
+ fmt++;
+ }
+ }
+ }
+
if (*fmt == 's') /* String parameter */
{
reg2 char *par = va_arg(args, char *);
- uint length = (uint) strlen(par);
- out_length+=length;
- if (my_b_write(info, par, length))
+ uint length2 = (uint) strlen(par);
+ /* TODO: implement minimum width and precision */
+ out_length+= length2;
+ if (my_b_write(info, par, length2))
goto err;
}
+ else if (*fmt == 'b') /* Sized buffer parameter, only precision makes sense */
+ {
+ char *par = va_arg(args, char *);
+ out_length+= precision;
+ if (my_b_write(info, par, precision))
+ goto err;
+ }
else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */
{
register int iarg;
- uint length;
+ uint length2;
char buff[17];
iarg = va_arg(args, int);
if (*fmt == 'd')
- length= (uint) (int10_to_str((long) iarg,buff, -10) - buff);
+ length2= (uint) (int10_to_str((long) iarg,buff, -10) - buff);
else
- length= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff);
- out_length+=length;
- if (my_b_write(info, buff, length))
+ length2= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff);
+ out_length+= length2;
+ if (my_b_write(info, buff, length2))
goto err;
}
else if ((*fmt == 'l' && fmt[1] == 'd') || fmt[1] == 'u')
/* long parameter */
{
register long iarg;
- uint length;
+ uint length2;
char buff[17];
iarg = va_arg(args, long);
if (*++fmt == 'd')
- length= (uint) (int10_to_str(iarg,buff, -10) - buff);
+ length2= (uint) (int10_to_str(iarg,buff, -10) - buff);
else
- length= (uint) (int10_to_str(iarg,buff,10)- buff);
- out_length+=length;
- if (my_b_write(info, buff, length))
+ length2= (uint) (int10_to_str(iarg,buff,10)- buff);
+ out_length+= length2;
+ if (my_b_write(info, buff, length2))
goto err;
}
else
{
/* %% or unknown code */
- if (my_b_write(info, "%", 1))
- goto err;
- out_length++;
+ if (my_b_write(info, backtrack, fmt-backtrack))
+ goto err;
+ out_length+= fmt-backtrack;
}
}
return out_length;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 88b5051c52b..87f136dbf81 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -161,13 +160,17 @@ KEY_CACHE *dflt_key_cache= &dflt_key_cache_var;
#define FLUSH_CACHE 2000 /* sort this many blocks at once */
static int flush_all_key_blocks(KEY_CACHE *keycache);
+#ifdef THREAD
static void link_into_queue(KEYCACHE_WQUEUE *wqueue,
struct st_my_thread_var *thread);
static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
struct st_my_thread_var *thread);
+#endif
static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block);
+#ifndef DBUG_OFF
static void test_key_cache(KEY_CACHE *keycache,
const char *where, my_bool lock);
+#endif
#define KEYCACHE_HASH(f, pos) \
(((ulong) ((pos) >> keycache->key_cache_shift)+ \
@@ -215,6 +218,7 @@ static void keycache_debug_print _VARARGS((const char *fmt,...));
#endif /* defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG) */
#if defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF)
+#ifdef THREAD
static long keycache_thread_id;
#define KEYCACHE_THREAD_TRACE(l) \
KEYCACHE_DBUG_PRINT(l,("|thread %ld",keycache_thread_id))
@@ -226,6 +230,11 @@ static long keycache_thread_id;
#define KEYCACHE_THREAD_TRACE_END(l) \
KEYCACHE_DBUG_PRINT(l,("]thread %ld",keycache_thread_id))
+#else /* THREAD */
+#define KEYCACHE_THREAD_TRACE(l) KEYCACHE_DBUG_PRINT(l,(""))
+#define KEYCACHE_THREAD_TRACE_BEGIN(l) KEYCACHE_DBUG_PRINT(l,(""))
+#define KEYCACHE_THREAD_TRACE_END(l) KEYCACHE_DBUG_PRINT(l,(""))
+#endif /* THREAD */
#else
#define KEYCACHE_THREAD_TRACE_BEGIN(l)
#define KEYCACHE_THREAD_TRACE_END(l)
@@ -347,8 +356,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
blocks--;
/* Allocate memory for cache page buffers */
if ((keycache->block_mem=
- my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
- MYF(0))))
+ my_large_malloc((ulong) blocks * keycache->key_cache_block_size,
+ MYF(MY_WME))))
{
/*
Allocate memory for blocks, hash_links and hash entries;
@@ -357,7 +366,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length,
MYF(0))))
break;
- my_free_lock(keycache->block_mem, MYF(0));
+ my_large_free(keycache->block_mem, MYF(0));
keycache->block_mem= 0;
}
if (blocks < 8)
@@ -410,9 +419,9 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
DBUG_PRINT("exit",
("disk_blocks: %d block_root: 0x%lx hash_entries: %d\
hash_root: 0x%lx hash_links: %d hash_link_root: 0x%lx",
- keycache->disk_blocks, keycache->block_root,
- keycache->hash_entries, keycache->hash_root,
- keycache->hash_links, keycache->hash_link_root));
+ keycache->disk_blocks, (long) keycache->block_root,
+ keycache->hash_entries, (long) keycache->hash_root,
+ keycache->hash_links, (long) keycache->hash_link_root));
bzero((gptr) keycache->changed_blocks,
sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
bzero((gptr) keycache->file_blocks,
@@ -428,7 +437,7 @@ err:
keycache->blocks= 0;
if (keycache->block_mem)
{
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_large_free((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
}
if (keycache->block_root)
@@ -492,6 +501,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
keycache_pthread_mutex_lock(&keycache->cache_lock);
+#ifdef THREAD
wqueue= &keycache->resize_queue;
thread= my_thread_var;
link_into_queue(wqueue, thread);
@@ -500,6 +510,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
{
keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock);
}
+#endif
keycache->resize_in_flush= 1;
if (flush_all_key_blocks(keycache))
@@ -512,12 +523,16 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
}
keycache->resize_in_flush= 0;
keycache->can_be_used= 0;
+#ifdef THREAD
while (keycache->cnt_for_resize_op)
{
KEYCACHE_DBUG_PRINT("resize_key_cache: wait",
("suspend thread %ld", thread->id));
keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock);
}
+#else
+ KEYCACHE_DBUG_ASSERT(keycache->cnt_for_resize_op == 0);
+#endif
end_key_cache(keycache, 0); /* Don't free mutex */
/* The following will work even if use_mem is 0 */
@@ -525,6 +540,7 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
division_limit, age_threshold);
finish:
+#ifdef THREAD
unlink_from_queue(wqueue, thread);
/* Signal for the next resize request to proceeed if any */
if (wqueue->last_thread)
@@ -533,6 +549,7 @@ finish:
("thread %ld", wqueue->last_thread->next->id));
keycache_pthread_cond_signal(&wqueue->last_thread->next->suspend);
}
+#endif
keycache_pthread_mutex_unlock(&keycache->cache_lock);
return blocks;
}
@@ -553,6 +570,7 @@ static inline void inc_counter_for_resize_op(KEY_CACHE *keycache)
*/
static inline void dec_counter_for_resize_op(KEY_CACHE *keycache)
{
+#ifdef THREAD
struct st_my_thread_var *last_thread;
if (!--keycache->cnt_for_resize_op &&
(last_thread= keycache->resize_queue.last_thread))
@@ -561,6 +579,9 @@ static inline void dec_counter_for_resize_op(KEY_CACHE *keycache)
("thread %ld", last_thread->next->id));
keycache_pthread_cond_signal(&last_thread->next->suspend);
}
+#else
+ keycache->cnt_for_resize_op--;
+#endif
}
/*
@@ -613,7 +634,7 @@ void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
{
DBUG_ENTER("end_key_cache");
- DBUG_PRINT("enter", ("key_cache: 0x%lx", keycache));
+ DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache));
if (!keycache->key_cache_inited)
DBUG_VOID_RETURN;
@@ -622,7 +643,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
{
if (keycache->block_mem)
{
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_large_free((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
my_free((gptr) keycache->block_root, MYF(0));
keycache->block_root= NULL;
@@ -632,7 +653,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
keycache->blocks_changed= 0;
}
- DBUG_PRINT("status", ("used: %d changed: %d w_requests: %lu "
+ DBUG_PRINT("status", ("used: %lu changed: %lu w_requests: %lu "
"writes: %lu r_requests: %lu reads: %lu",
keycache->blocks_used, keycache->global_blocks_changed,
(ulong) keycache->global_cache_w_requests,
@@ -650,6 +671,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
} /* end_key_cache */
+#ifdef THREAD
/*
Link a thread into double-linked queue of waiting threads.
@@ -786,6 +808,7 @@ static void release_queue(KEYCACHE_WQUEUE *wqueue)
while (thread != last);
wqueue->last_thread= NULL;
}
+#endif
/*
@@ -819,9 +842,10 @@ static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
*/
static void link_to_file_list(KEY_CACHE *keycache,
- BLOCK_LINK *block, int file, my_bool unlink)
+ BLOCK_LINK *block, int file,
+ my_bool unlink_block)
{
- if (unlink)
+ if (unlink_block)
unlink_changed(block);
link_changed(block, &keycache->file_blocks[FILE_HASH(file)]);
if (block->status & BLOCK_CHANGED)
@@ -893,6 +917,7 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
BLOCK_LINK **pins;
KEYCACHE_DBUG_ASSERT(! (block->hash_link && block->hash_link->requests));
+#ifdef THREAD
if (!hot && keycache->waiting_for_block.last_thread)
{
/* Signal that in the LRU warm sub-chain an available block has appeared */
@@ -929,6 +954,10 @@ static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
#endif
return;
}
+#else /* THREAD */
+ KEYCACHE_DBUG_ASSERT(! (!hot && keycache->waiting_for_block.last_thread));
+ /* Condition not transformed using DeMorgan, to keep the text identical */
+#endif /* THREAD */
pins= hot ? &keycache->used_ins : &keycache->used_last;
ins= *pins;
if (ins)
@@ -1058,7 +1087,7 @@ static void unreg_request(KEY_CACHE *keycache,
if (block->temperature == BLOCK_WARM)
keycache->warm_blocks--;
block->temperature= BLOCK_HOT;
- KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks=%u",
+ KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu",
keycache->warm_blocks));
}
link_block(keycache, block, hot, (my_bool)at_end);
@@ -1077,7 +1106,7 @@ static void unreg_request(KEY_CACHE *keycache,
keycache->warm_blocks++;
block->temperature= BLOCK_WARM;
}
- KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks=%u",
+ KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu",
keycache->warm_blocks));
}
}
@@ -1101,6 +1130,7 @@ static inline void remove_reader(BLOCK_LINK *block)
static inline void wait_for_readers(KEY_CACHE *keycache, BLOCK_LINK *block)
{
+#ifdef THREAD
struct st_my_thread_var *thread= my_thread_var;
while (block->hash_link->requests)
{
@@ -1111,6 +1141,9 @@ static inline void wait_for_readers(KEY_CACHE *keycache, BLOCK_LINK *block)
keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock);
block->condvar= NULL;
}
+#else
+ KEYCACHE_DBUG_ASSERT(block->hash_link->requests == 0);
+#endif
}
@@ -1140,6 +1173,7 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
if ((*hash_link->prev= hash_link->next))
hash_link->next->prev= hash_link->prev;
hash_link->block= NULL;
+#ifdef THREAD
if (keycache->waiting_for_hash_link.last_thread)
{
/* Signal that a free hash link has appeared */
@@ -1175,6 +1209,9 @@ static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
hash_link);
return;
}
+#else /* THREAD */
+ KEYCACHE_DBUG_ASSERT(! (keycache->waiting_for_hash_link.last_thread));
+#endif /* THREAD */
hash_link->next= keycache->free_hash_list;
keycache->free_hash_list= hash_link;
}
@@ -1240,6 +1277,7 @@ restart:
}
else
{
+#ifdef THREAD
/* Wait for a free hash link */
struct st_my_thread_var *thread= my_thread_var;
KEYCACHE_DBUG_PRINT("get_hash_link", ("waiting"));
@@ -1252,6 +1290,9 @@ restart:
keycache_pthread_cond_wait(&thread->suspend,
&keycache->cache_lock);
thread->opt_info= NULL;
+#else
+ KEYCACHE_DBUG_ASSERT(0);
+#endif
goto restart;
}
hash_link->file= file;
@@ -1313,11 +1354,11 @@ static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
DBUG_ENTER("find_key_block");
KEYCACHE_THREAD_TRACE("find_key_block:begin");
- DBUG_PRINT("enter", ("fd: %u pos %lu wrmode: %lu",
- (uint) file, (ulong) filepos, (uint) wrmode));
- KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %u pos: %lu wrmode: %lu",
- (uint) file, (ulong) filepos,
- (uint) wrmode));
+ DBUG_PRINT("enter", ("fd: %d pos: %lu wrmode: %d",
+ file, (ulong) filepos, wrmode));
+ KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %d pos: %lu wrmode: %d",
+ file, (ulong) filepos,
+ wrmode));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache2",
test_key_cache(keycache, "start of find_key_block", 0););
@@ -1363,6 +1404,7 @@ restart:
/* Wait intil the page is flushed on disk */
hash_link->requests--;
{
+#ifdef THREAD
struct st_my_thread_var *thread= my_thread_var;
add_to_queue(&block->wqueue[COND_FOR_SAVED], thread);
do
@@ -1373,6 +1415,16 @@ restart:
&keycache->cache_lock);
}
while(thread->next);
+#else
+ KEYCACHE_DBUG_ASSERT(0);
+ /*
+ Given the use of "resize_in_flush", it seems impossible
+ that this whole branch is ever entered in single-threaded case
+ because "(wrmode && keycache->resize_in_flush)" cannot be true.
+ TODO: Check this, and then put the whole branch into the
+ "#ifdef THREAD" guard.
+ */
+#endif
}
/* Invalidate page in the block if it has not been done yet */
if (block->status)
@@ -1401,6 +1453,7 @@ restart:
KEYCACHE_DBUG_PRINT("find_key_block",
("request waiting for old page to be saved"));
{
+#ifdef THREAD
struct st_my_thread_var *thread= my_thread_var;
/* Put the request into the queue of those waiting for the old page */
add_to_queue(&block->wqueue[COND_FOR_SAVED], thread);
@@ -1413,6 +1466,10 @@ restart:
&keycache->cache_lock);
}
while(thread->next);
+#else
+ KEYCACHE_DBUG_ASSERT(0);
+ /* No parallel requests in single-threaded case */
+#endif
}
KEYCACHE_DBUG_PRINT("find_key_block",
("request for old page resubmitted"));
@@ -1471,6 +1528,7 @@ restart:
all of them must get the same block
*/
+#ifdef THREAD
if (! keycache->used_last)
{
struct st_my_thread_var *thread= my_thread_var;
@@ -1486,6 +1544,9 @@ restart:
while (thread->next);
thread->opt_info= NULL;
}
+#else
+ KEYCACHE_DBUG_ASSERT(keycache->used_last);
+#endif
block= hash_link->block;
if (! block)
{
@@ -1587,8 +1648,8 @@ restart:
KEYCACHE_DBUG_ASSERT(page_status != -1);
*page_st=page_status;
KEYCACHE_DBUG_PRINT("find_key_block",
- ("fd: %u pos %lu block->status %u page_status %lu",
- (uint) file, (ulong) filepos, block->status,
+ ("fd: %d pos: %lu block->status: %u page_status: %u",
+ file, (ulong) filepos, block->status,
(uint) page_status));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
@@ -1674,6 +1735,7 @@ static void read_block(KEY_CACHE *keycache,
KEYCACHE_DBUG_PRINT("read_block",
("secondary request waiting for new page to be read"));
{
+#ifdef THREAD
struct st_my_thread_var *thread= my_thread_var;
/* Put the request into a queue and wait until it can be processed */
add_to_queue(&block->wqueue[COND_FOR_REQUESTED], thread);
@@ -1685,6 +1747,10 @@ static void read_block(KEY_CACHE *keycache,
&keycache->cache_lock);
}
while (thread->next);
+#else
+ KEYCACHE_DBUG_ASSERT(0);
+ /* No parallel requests in single-threaded case */
+#endif
}
KEYCACHE_DBUG_PRINT("read_block",
("secondary request: new page in cache"));
@@ -1822,7 +1888,7 @@ byte *key_cache_read(KEY_CACHE *keycache,
#ifndef THREAD
/* This is only true if we where able to read everything in one block */
if (return_buffer)
- return (block->buffer);
+ DBUG_RETURN(block->buffer);
#endif
buff+= read_length;
filepos+= read_length+offset;
@@ -2194,7 +2260,7 @@ static int flush_cached_blocks(KEY_CACHE *keycache,
{
int error;
int last_errno= 0;
- uint count= end-cache;
+ uint count= (uint) (end-cache);
/* Don't lock the cache during the flush */
keycache_pthread_mutex_unlock(&keycache->cache_lock);
@@ -2274,7 +2340,7 @@ static int flush_key_blocks_int(KEY_CACHE *keycache,
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
int last_errno= 0;
DBUG_ENTER("flush_key_blocks_int");
- DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
+ DBUG_PRINT("enter",("file: %d blocks_used: %lu blocks_changed: %lu",
file, keycache->blocks_used, keycache->blocks_changed));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
@@ -2400,6 +2466,7 @@ restart:
#endif
block= first_in_switch;
{
+#ifdef THREAD
struct st_my_thread_var *thread= my_thread_var;
add_to_queue(&block->wqueue[COND_FOR_SAVED], thread);
do
@@ -2410,6 +2477,10 @@ restart:
&keycache->cache_lock);
}
while (thread->next);
+#else
+ KEYCACHE_DBUG_ASSERT(0);
+ /* No parallel requests in single-threaded case */
+#endif
}
#if defined(KEYCACHE_DEBUG)
cnt++;
@@ -2474,7 +2545,7 @@ int flush_key_blocks(KEY_CACHE *keycache,
{
int res;
DBUG_ENTER("flush_key_blocks");
- DBUG_PRINT("enter", ("keycache: 0x%lx", keycache));
+ DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache));
if (keycache->disk_blocks <= 0)
DBUG_RETURN(0);
@@ -2536,7 +2607,8 @@ static int flush_all_key_blocks(KEY_CACHE *keycache)
0 on success (always because it can't fail)
*/
-int reset_key_cache_counters(const char *name, KEY_CACHE *key_cache)
+int reset_key_cache_counters(const char *name __attribute__((unused)),
+ KEY_CACHE *key_cache)
{
DBUG_ENTER("reset_key_cache_counters");
if (!key_cache->key_cache_inited)
@@ -2576,7 +2648,6 @@ static void test_key_cache(KEY_CACHE *keycache __attribute__((unused)),
static void keycache_dump(KEY_CACHE *keycache)
{
FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
- struct st_my_thread_var *thread_var= my_thread_var;
struct st_my_thread_var *last;
struct st_my_thread_var *thread;
BLOCK_LINK *block;
@@ -2684,9 +2755,12 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond,
gettimeofday(&now, &tz);
/* Prepare timeout value */
timeout.tv_sec= now.tv_sec + KEYCACHE_TIMEOUT;
- timeout.tv_nsec= now.tv_usec * 1000; /* timeval uses microseconds. */
- /* timespec uses nanoseconds. */
- /* 1 nanosecond = 1000 micro seconds. */
+ /*
+ timeval uses microseconds.
+ timespec uses nanoseconds.
+ 1 nanosecond = 1000 micro seconds
+ */
+ timeout.tv_nsec= now.tv_usec * 1000;
KEYCACHE_THREAD_TRACE_END("started waiting");
#if defined(KEYCACHE_DEBUG)
cnt++;
@@ -2696,17 +2770,15 @@ static int keycache_pthread_cond_wait(pthread_cond_t *cond,
#endif
rc= pthread_cond_timedwait(cond, mutex, &timeout);
KEYCACHE_THREAD_TRACE_BEGIN("finished waiting");
-#if defined(KEYCACHE_DEBUG)
- if (rc == ETIMEDOUT)
+ if (rc == ETIMEDOUT || rc == ETIME)
{
+#if defined(KEYCACHE_DEBUG)
fprintf(keycache_debug_log,"aborted by keycache timeout\n");
fclose(keycache_debug_log);
abort();
- }
#endif
-
- if (rc == ETIMEDOUT)
keycache_dump();
+ }
#if defined(KEYCACHE_DEBUG)
KEYCACHE_DBUG_ASSERT(rc != ETIMEDOUT);
diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c
index 38fef31fdd4..51ad54159e5 100644
--- a/mysys/mf_keycaches.c
+++ b/mysys/mf_keycaches.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -159,7 +158,7 @@ static byte *safe_hash_search(SAFE_HASH *hash, const byte *key, uint length)
result= hash->default_value;
else
result= ((SAFE_HASH_ENTRY*) result)->data;
- DBUG_PRINT("exit",("data: 0x%lx", result));
+ DBUG_PRINT("exit",("data: 0x%lx", (long) result));
DBUG_RETURN(result);
}
@@ -190,7 +189,7 @@ static my_bool safe_hash_set(SAFE_HASH *hash, const byte *key, uint length,
SAFE_HASH_ENTRY *entry;
my_bool error= 0;
DBUG_ENTER("safe_hash_set");
- DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, data));
+ DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data));
rw_wrlock(&hash->mutex);
entry= (SAFE_HASH_ENTRY*) hash_search(&hash->hash, key, length);
diff --git a/mysys/mf_loadpath.c b/mysys/mf_loadpath.c
index a46b43c34d4..ffa83cb20ec 100644
--- a/mysys/mf_loadpath.c
+++ b/mysys/mf_loadpath.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c
index 049aa59a578..d14c24f35d7 100644
--- a/mysys/mf_pack.c
+++ b/mysys/mf_pack.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_path.c b/mysys/mf_path.c
index 1ecd5fbb2b1..9af6173b417 100644
--- a/mysys/mf_path.c
+++ b/mysys/mf_path.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_qsort.c b/mysys/mf_qsort.c
index 9cc937f6e8b..3d52d56c952 100644
--- a/mysys/mf_qsort.c
+++ b/mysys/mf_qsort.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_qsort2.c b/mysys/mf_qsort2.c
index 160bb6df817..ca2bd1a4952 100644
--- a/mysys/mf_qsort2.c
+++ b/mysys/mf_qsort2.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_radix.c b/mysys/mf_radix.c
index 7ee96b966b9..6b750181558 100644
--- a/mysys/mf_radix.c
+++ b/mysys/mf_radix.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_same.c b/mysys/mf_same.c
index efd6e7b2ca4..e7cdb012c9f 100644
--- a/mysys/mf_same.c
+++ b/mysys/mf_same.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_sort.c b/mysys/mf_sort.c
index 0dc6c78a589..e7fd6873eee 100644
--- a/mysys/mf_sort.c
+++ b/mysys/mf_sort.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_soundex.c b/mysys/mf_soundex.c
index c0c6105a6eb..fa393d1a94a 100644
--- a/mysys/mf_soundex.c
+++ b/mysys/mf_soundex.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_strip.c b/mysys/mf_strip.c
index ef2aab2c0a3..712b0e1d28a 100644
--- a/mysys/mf_strip.c
+++ b/mysys/mf_strip.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c
index 4d244aa7d74..bcd003920f1 100644
--- a/mysys/mf_tempdir.c
+++ b/mysys/mf_tempdir.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -27,9 +26,8 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist)
{
char *end, *copy;
char buff[FN_REFLEN];
- DYNAMIC_ARRAY t_arr;
pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST);
- if (my_init_dynamic_array(&t_arr, sizeof(char*), 1, 5))
+ if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5))
return TRUE;
if (!pathlist || !pathlist[0])
{
@@ -50,14 +48,14 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist)
convert_dirname(buff, pathlist, end);
if (!(copy=my_strdup(buff, MYF(MY_WME))))
return TRUE;
- if (insert_dynamic(&t_arr, (gptr)&copy))
+ if (insert_dynamic(&tmpdir->full_list, (gptr)&copy))
return TRUE;
pathlist=end+1;
}
while (*end);
- freeze_size(&t_arr);
- tmpdir->list=(char **)t_arr.buffer;
- tmpdir->max=t_arr.elements-1;
+ freeze_size(&tmpdir->full_list);
+ tmpdir->list=(char **)tmpdir->full_list.buffer;
+ tmpdir->max=tmpdir->full_list.elements-1;
tmpdir->cur=0;
return FALSE;
}
@@ -77,7 +75,7 @@ void free_tmpdir(MY_TMPDIR *tmpdir)
uint i;
for (i=0; i<=tmpdir->max; i++)
my_free(tmpdir->list[i], MYF(0));
- my_free((gptr)tmpdir->list, MYF(0));
+ delete_dynamic(&tmpdir->full_list);
pthread_mutex_destroy(&tmpdir->mutex);
}
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index a15bda4da6d..431674c5d61 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_unixpath.c b/mysys/mf_unixpath.c
index 9efc3e5d9b8..11292e231ba 100644
--- a/mysys/mf_unixpath.c
+++ b/mysys/mf_unixpath.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_util.c b/mysys/mf_util.c
index 132c83b4623..248b72b8748 100644
--- a/mysys/mf_util.c
+++ b/mysys/mf_util.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_wcomp.c b/mysys/mf_wcomp.c
index 1a01388a3db..4786537d1a5 100644
--- a/mysys/mf_wcomp.c
+++ b/mysys/mf_wcomp.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c
index 7d537eaa06a..b574d158b9e 100644
--- a/mysys/mf_wfile.c
+++ b/mysys/mf_wfile.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c
index e1eb1c00602..bada0a55a6a 100644
--- a/mysys/mulalloc.c
+++ b/mysys/mulalloc.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_access.c b/mysys/my_access.c
index 237312b5c9b..9ee20cc942b 100644
--- a/mysys/my_access.c
+++ b/mysys/my_access.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -44,7 +43,7 @@ int my_access(const char *path, int amode)
result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo);
if (! result ||
- (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & F_OK))
+ (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK))
{
my_errno= errno= EACCES;
return -1;
diff --git a/mysys/my_aes.c b/mysys/my_aes.c
index 16d326d7d1f..575d4702dee 100644
--- a/mysys/my_aes.c
+++ b/mysys/my_aes.c
@@ -1,9 +1,8 @@
-/* Copyright (C) 2002 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_alarm.c b/mysys/my_alarm.c
index 70daf4a9dd0..d6a0da1bd13 100644
--- a/mysys/my_alarm.c
+++ b/mysys/my_alarm.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index d52a8efeed2..cfa2dd6216d 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -39,15 +38,17 @@
DESCRIPTION
This function prepares memory root for further use, sets initial size of
chunk for memory allocation and pre-allocates first block if specified.
- Altough error can happen during execution of this function if pre_alloc_size
- is non-0 it won't be reported. Instead it will be reported as error in first
- alloc_root() on this memory root.
+ Altough error can happen during execution of this function if
+ pre_alloc_size is non-0 it won't be reported. Instead it will be
+ reported as error in first alloc_root() on this memory root.
*/
+
void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
{
DBUG_ENTER("init_alloc_root");
- DBUG_PRINT("enter",("root: 0x%lx", mem_root));
+ DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
+
mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
mem_root->min_malloc= 32;
mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
@@ -71,6 +72,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
DBUG_VOID_RETURN;
}
+
/*
SYNOPSIS
reset_root_defaults()
@@ -86,7 +88,7 @@ void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
reuse one of existing blocks as prealloc block, or malloc new one of
requested size. If no blocks can be reused, all unused blocks are freed
before allocation.
- */
+*/
void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
@@ -144,7 +146,7 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
reg1 USED_MEM *next;
DBUG_ENTER("alloc_root");
- DBUG_PRINT("enter",("root: 0x%lx", mem_root));
+ DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
@@ -158,15 +160,16 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
next->next= mem_root->used;
next->size= Size;
mem_root->used= next;
- DBUG_PRINT("exit",("ptr: 0x%lx", (((char*) next)+
- ALIGN_SIZE(sizeof(USED_MEM)))));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) (((char*) next)+
+ ALIGN_SIZE(sizeof(USED_MEM)))));
DBUG_RETURN((gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
#else
uint get_size, block_size;
gptr point;
reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev;
-
+ DBUG_ENTER("alloc_root");
+ DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
Size= ALIGN_SIZE(Size);
@@ -213,15 +216,63 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
mem_root->used= next;
mem_root->first_block_usage= 0;
}
- return(point);
+ DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point));
+ DBUG_RETURN(point);
#endif
}
-#ifdef SAFEMALLOC
-#define TRASH(X) bfill(((char*)(X) + ((X)->size-(X)->left)), (X)->left, 0xa5)
-#else
-#define TRASH /* no-op */
-#endif
+
+/*
+ Allocate many pointers at the same time.
+
+ DESCRIPTION
+ ptr1, ptr2, etc all point into big allocated memory area.
+
+ SYNOPSIS
+ multi_alloc_root()
+ root Memory root
+ ptr1, length1 Multiple arguments terminated by a NULL pointer
+ ptr2, length2 ...
+ ...
+ NULL
+
+ RETURN VALUE
+ A pointer to the beginning of the allocated memory block
+ in case of success or NULL if out of memory.
+*/
+
+gptr multi_alloc_root(MEM_ROOT *root, ...)
+{
+ va_list args;
+ char **ptr, *start, *res;
+ uint tot_length, length;
+ DBUG_ENTER("multi_alloc_root");
+
+ va_start(args, root);
+ tot_length= 0;
+ while ((ptr= va_arg(args, char **)))
+ {
+ length= va_arg(args, uint);
+ tot_length+= ALIGN_SIZE(length);
+ }
+ va_end(args);
+
+ if (!(start= (char*) alloc_root(root, tot_length)))
+ DBUG_RETURN(0); /* purecov: inspected */
+
+ va_start(args, root);
+ res= start;
+ while ((ptr= va_arg(args, char **)))
+ {
+ *ptr= res;
+ length= va_arg(args, uint);
+ res+= ALIGN_SIZE(length);
+ }
+ va_end(args);
+ DBUG_RETURN((gptr) start);
+}
+
+#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left)
/* Mark all data in blocks free for reusage */
@@ -235,7 +286,7 @@ static inline void mark_blocks_free(MEM_ROOT* root)
for (next= root->free; next; next= *(last= &next->next))
{
next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
- TRASH(next);
+ TRASH_MEM(next);
}
/* Combine the free and the used list */
@@ -245,7 +296,7 @@ static inline void mark_blocks_free(MEM_ROOT* root)
for (; next; next= next->next)
{
next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
- TRASH(next);
+ TRASH_MEM(next);
}
/* Now everything is set; Indicate that nothing is used anymore */
@@ -257,13 +308,27 @@ static inline void mark_blocks_free(MEM_ROOT* root)
/*
Deallocate everything used by alloc_root or just move
used blocks to free list if called with MY_USED_TO_FREE
+
+ SYNOPSIS
+ free_root()
+ root Memory root
+ MyFlags Flags for what should be freed:
+
+ MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free
+ MY_KEEP_PREALLOC If this is not set, then free also the
+ preallocated block
+
+ NOTES
+ One can call this function either with root block initialised with
+ init_alloc_root() or with a bzero()-ed block.
+ It's also safe to call this multiple times with the same mem_root.
*/
void free_root(MEM_ROOT *root, myf MyFlags)
{
reg1 USED_MEM *next,*old;
DBUG_ENTER("free_root");
- DBUG_PRINT("enter",("root: 0x%lx flags: %u", root, (uint) MyFlags));
+ DBUG_PRINT("enter",("root: 0x%lx flags: %u", (long) root, (uint) MyFlags));
if (!root) /* QQ: Should be deleted */
DBUG_VOID_RETURN; /* purecov: inspected */
@@ -292,7 +357,7 @@ void free_root(MEM_ROOT *root, myf MyFlags)
{
root->free=root->pre_alloc;
root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
- TRASH(root->pre_alloc);
+ TRASH_MEM(root->pre_alloc);
root->free->next=0;
}
root->block_num= 4;
@@ -328,7 +393,7 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr)
char *strdup_root(MEM_ROOT *root,const char *str)
{
- return strmake_root(root, str, strlen(str));
+ return strmake_root(root, str, (uint) strlen(str));
}
char *strmake_root(MEM_ROOT *root,const char *str, uint len)
diff --git a/mysys/my_append.c b/mysys/my_append.c
index c3549c670c3..274f2110575 100644
--- a/mysys/my_append.c
+++ b/mysys/my_append.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 55dd72f5f76..81d63246e7a 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -71,3 +70,8 @@ uint my_count_bits(ulonglong v)
#endif
}
+uint my_count_bits_ushort(ushort v)
+{
+ return nbits[v];
+}
+
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index 2af4edbf1a5..beb67bb419b 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -29,6 +28,9 @@
* bitmap_intersect() is an exception :)
(for for Bitmap::intersect(ulonglong map2buff))
+ If THREAD is defined all bitmap operations except bitmap_init/bitmap_free
+ are thread-safe.
+
TODO:
Make assembler THREAD safe versions of these using test-and-set instructions
*/
@@ -37,7 +39,7 @@
#include <my_bitmap.h>
#include <m_string.h>
-static inline void bitmap_lock(MY_BITMAP* map)
+static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused)))
{
#ifdef THREAD
if (map->mutex)
@@ -45,7 +47,7 @@ static inline void bitmap_lock(MY_BITMAP* map)
#endif
}
-static inline void bitmap_unlock(MY_BITMAP* map)
+static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
{
#ifdef THREAD
if (map->mutex)
@@ -66,7 +68,7 @@ my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size,
(thread_safe ?
sizeof(pthread_mutex_t) : 0),
MYF(MY_WME | MY_ZEROFILL))))
- return 1;
+ DBUG_RETURN(1);
map->bitmap_size=bitmap_size;
#ifdef THREAD
if (thread_safe)
@@ -106,6 +108,52 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
}
+/*
+ test if bit already set and set it if it was not (thread unsafe method)
+
+ SYNOPSIS
+ bitmap_fast_test_and_set()
+ MAP bit map struct
+ BIT bit number
+
+ RETURN
+ 0 bit was not set
+ !=0 bit was set
+*/
+
+my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
+{
+ uchar *value= map->bitmap + (bitmap_bit / 8);
+ uchar bit= 1 << ((bitmap_bit) & 7);
+ uchar res= (*value) & bit;
+ *value|= bit;
+ return res;
+}
+
+
+/*
+ test if bit already set and set it if it was not (thread safe method)
+
+ SYNOPSIS
+ bitmap_fast_test_and_set()
+ map bit map struct
+ bitmap_bit bit number
+
+ RETURN
+ 0 bit was not set
+ !=0 bit was set
+*/
+
+my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
+{
+ my_bool res;
+ DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
+ bitmap_lock(map);
+ res= bitmap_fast_test_and_set(map, bitmap_bit);
+ bitmap_unlock(map);
+ return res;
+}
+
uint bitmap_set_next(MY_BITMAP *map)
{
uchar *bitmap=map->bitmap;
@@ -290,6 +338,37 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
}
+/*
+ Set/clear all bits above a bit.
+
+ SYNOPSIS
+ bitmap_set_above()
+ map RETURN The bitmap to change.
+ from_byte The bitmap buffer byte offset to start with.
+ use_bit The bit value (1/0) to use for all upper bits.
+
+ NOTE
+ You can only set/clear full bytes.
+ The function is meant for the situation that you copy a smaller bitmap
+ to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
+ size of a byte). Using 'from_byte' saves multiplication and division
+ by eight during parameter passing.
+
+ RETURN
+ void
+*/
+
+void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit)
+{
+ uchar use_byte= use_bit ? 0xff : 0;
+ uchar *to= map->bitmap + from_byte;
+ uchar *end= map->bitmap + map->bitmap_size;
+
+ while (to < end)
+ *to++= use_byte;
+}
+
+
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
{
uchar *to=map->bitmap, *from=map2->bitmap, *end;
@@ -327,3 +406,66 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
bitmap_unlock(map);
}
+
+/*
+ SYNOPSIS
+ bitmap_bits_set()
+ map
+ RETURN
+ Number of set bits in the bitmap.
+*/
+
+uint bitmap_bits_set(const MY_BITMAP *map)
+{
+ uchar *m= map->bitmap;
+ uchar *end= m + map->bitmap_size;
+ uint res= 0;
+
+ DBUG_ASSERT(map->bitmap);
+ bitmap_lock((MY_BITMAP *)map);
+ while (m < end)
+ {
+ res+= my_count_bits_ushort(*m++);
+ }
+ bitmap_unlock((MY_BITMAP *)map);
+ return res;
+}
+
+
+/*
+ SYNOPSIS
+ bitmap_get_first()
+ map
+ RETURN
+ Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
+*/
+
+uint bitmap_get_first(const MY_BITMAP *map)
+{
+ uchar *bitmap=map->bitmap;
+ uint bit_found = MY_BIT_NONE;
+ uint bitmap_size=map->bitmap_size;
+ uint i;
+
+ DBUG_ASSERT(map->bitmap);
+ bitmap_lock((MY_BITMAP *)map);
+ for (i=0; i < bitmap_size ; i++, bitmap++)
+ {
+ if (*bitmap != 0xff)
+ { /* Found slot with free bit */
+ uint b;
+ for (b=0; ; b++)
+ {
+ if (!(*bitmap & (1 << b)))
+ {
+ bit_found = (i*8)+b;
+ break;
+ }
+ }
+ break; /* Found bit */
+ }
+ }
+ bitmap_unlock((MY_BITMAP *)map);
+ return bit_found;
+}
+
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index 149a5c81e08..a5dd1564692 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -30,7 +29,9 @@
MyFlags Flags
DESCRIPTION
- my_chsize() truncates file if shorter else fill with the filler character
+ my_chsize() truncates file if shorter else fill with the filler character.
+ The function also changes the file pointer. Usually it points to the end
+ of the file after execution.
RETURN VALUE
0 Ok
@@ -50,9 +51,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
if (oldsize > newlength)
+ {
#if defined(HAVE_SETFILEPOINTER)
/* This is for the moment only true on windows */
- {
long is_success;
HANDLE win_file= (HANDLE) _get_osfhandle(fd);
long length_low, length_high;
@@ -65,27 +66,21 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_RETURN(0);
my_errno= GetLastError();
goto err;
- }
#elif defined(HAVE_FTRUNCATE)
- {
if (ftruncate(fd, (off_t) newlength))
{
my_errno= errno;
goto err;
}
DBUG_RETURN(0);
- }
#elif defined(HAVE_CHSIZE)
- {
if (chsize(fd, (off_t) newlength))
{
my_errno=errno;
goto err;
}
DBUG_RETURN(0);
- }
#else
- {
/*
Fill space between requested length and true length with 'filler'
We should never come here on any modern machine
@@ -96,8 +91,8 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
goto err;
}
swap_variables(my_off_t, newlength, oldsize);
- }
#endif
+ }
/* Full file with 'filler' until it's as big as requested */
bfill(buff, IO_SIZE, filler);
diff --git a/mysys/my_clock.c b/mysys/my_clock.c
index a192bde056d..c5fa516a622 100644
--- a/mysys/my_clock.c
+++ b/mysys/my_clock.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_compress.c b/mysys/my_compress.c
index 0e37d2fef9b..c054bf155b1 100644
--- a/mysys/my_compress.c
+++ b/mysys/my_compress.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_conio.c b/mysys/my_conio.c
index e381f9f23ef..23b0c55e7a9 100644
--- a/mysys/my_conio.c
+++ b/mysys/my_conio.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 03f3feb54d3..6143700befc 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -16,7 +15,7 @@
#define USES_TYPES /* sys/types is included */
#include "mysys_priv.h"
-#include <sys/stat.h>
+#include <my_dir.h> /* for stat */
#include <m_string.h>
#if defined(HAVE_UTIME_H)
#include <utime.h>
@@ -53,26 +52,27 @@ struct utimbuf {
int my_copy(const char *from, const char *to, myf MyFlags)
{
uint Count;
- int new_file_stat, create_flag;
+ my_bool new_file_stat= 0; /* 1 if we could stat "to" */
+ int create_flag;
File from_file,to_file;
char buff[IO_SIZE];
- struct stat stat_buff,new_stat_buff;
+ MY_STAT stat_buff,new_stat_buff;
DBUG_ENTER("my_copy");
DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags));
from_file=to_file= -1;
- new_file_stat=0;
+ DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */
if (MyFlags & MY_HOLD_ORIGINAL_MODES) /* Copy stat if possible */
- new_file_stat=stat((char*) to, &new_stat_buff);
+ new_file_stat= test(my_stat((char*) to, &new_stat_buff, MYF(0)));
if ((from_file=my_open(from,O_RDONLY | O_SHARE,MyFlags)) >= 0)
{
- if (stat(from,&stat_buff))
+ if (!my_stat(from, &stat_buff, MyFlags))
{
my_errno=errno;
goto err;
}
- if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
+ if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat)
stat_buff=new_stat_buff;
create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC;
@@ -91,7 +91,7 @@ int my_copy(const char *from, const char *to, myf MyFlags)
/* Copy modes if possible */
- if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat)
+ if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat)
DBUG_RETURN(0); /* File copyed but not stat */
VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */
#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__)
diff --git a/mysys/my_crc32.c b/mysys/my_crc32.c
index db1beb58263..51c553da5ea 100644
--- a/mysys/my_crc32.c
+++ b/mysys/my_crc32.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_create.c b/mysys/my_create.c
index 5fa97a9ca78..d612926c1a5 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -47,13 +46,16 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
#elif defined(VMS)
fd = open((my_string) FileName, access_flags | O_CREAT, 0,
"ctx=stm","ctx=bin");
-#elif defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2)
+#elif defined(MSDOS) || defined(__EMX__) || defined(OS2)
if (access_flags & O_SHARE)
fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY,
SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
else
fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY,
MY_S_IREAD | MY_S_IWRITE);
+#elif defined(__WIN__)
+ fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY,
+ SH_DENYNO, MY_S_IREAD | MY_S_IWRITE);
#else
fd = open(FileName, access_flags);
#endif
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index 5670f03da64..bac3e2513e1 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -32,3 +31,54 @@ int my_delete(const char *name, myf MyFlags)
}
DBUG_RETURN(err);
} /* my_delete */
+
+#if defined(__WIN__) && defined(__NT__)
+/*
+ Delete file which is possibly not closed.
+
+ This function is intended to be used exclusively as a temporal solution
+ for Win NT in case when it is needed to delete a not closed file (note
+ that the file must be opened everywhere with FILE_SHARE_DELETE mode).
+ Deleting not-closed files can not be supported on Win 98|ME (and because
+ of that is considered harmful).
+
+ The function deletes the file with its preliminary renaming. This is
+ because when not-closed share-delete file is deleted it still lives on
+ a disk until it will not be closed everwhere. This may conflict with an
+ attempt to create a new file with the same name. The deleted file is
+ renamed to <name>.<num>.deleted where <name> - the initial name of the
+ file, <num> - a hexadecimal number chosen to make the temporal name to
+ be unique.
+*/
+int nt_share_delete(const char *name, myf MyFlags)
+{
+ char buf[MAX_PATH + 20];
+ ulong cnt;
+ DBUG_ENTER("nt_share_delete");
+ DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags));
+
+ for (cnt= GetTickCount(); cnt; cnt--)
+ {
+ sprintf(buf, "%s.%08X.deleted", name, cnt);
+ if (MoveFile(name, buf))
+ break;
+
+ if ((errno= GetLastError()) == ERROR_ALREADY_EXISTS)
+ continue;
+
+ DBUG_PRINT("warning", ("Failed to rename %s to %s, errno: %d",
+ name, buf, errno));
+ break;
+ }
+
+ if (DeleteFile(buf))
+ DBUG_RETURN(0);
+
+ my_errno= GetLastError();
+ if (MyFlags & (MY_FAE+MY_WME))
+ my_error(EE_DELETE, MYF(ME_BELL + ME_WAITTANG + (MyFlags & ME_NOINPUT)),
+ name, my_errno);
+
+ DBUG_RETURN(-1);
+}
+#endif
diff --git a/mysys/my_div.c b/mysys/my_div.c
index 9141ff4fcc5..656c6cfde91 100644
--- a/mysys/my_div.c
+++ b/mysys/my_div.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_dup.c b/mysys/my_dup.c
index 4b7434e29ea..2c6a42726e4 100644
--- a/mysys/my_dup.c
+++ b/mysys/my_dup.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -30,7 +29,7 @@ File my_dup(File file, myf MyFlags)
File fd;
const char *filename;
DBUG_ENTER("my_dup");
- DBUG_PRINT("my",("file: %d MyFlags: %d", MyFlags));
+ DBUG_PRINT("my",("file: %d MyFlags: %d", file, MyFlags));
fd = dup(file);
filename= (((uint) file < my_file_limit) ?
my_file_info[(int) file].name : "Unknown");
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 8a377f63c7e..836f851322b 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -22,10 +21,40 @@
/* Define some external variables for error handling */
-const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
+/*
+ WARNING!
+ my_error family functions have to be used according following rules:
+ - if message have not parameters use my_message(ER_CODE, ER(ER_CODE), MYF(N))
+ - if message registered use my_error(ER_CODE, MYF(N), ...).
+ - With some special text of errror message use:
+ my_printf_error(ER_CODE, format, MYF(N), ...)
+*/
+
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
/*
+ Message texts are registered into a linked list of 'my_err_head' structs.
+ Each struct contains (1.) an array of pointers to C character strings with
+ '\0' termination, (2.) the error number for the first message in the array
+ (array index 0) and (3.) the error number for the last message in the array
+ (array index (last - first)).
+ The array may contain gaps with NULL pointers and pointers to empty strings.
+ Both kinds of gaps will be translated to "Unknown error %d.", if my_error()
+ is called with a respective error number.
+ The list of header structs is sorted in increasing order of error numbers.
+ Negative error numbers are allowed. Overlap of error numbers is not allowed.
+ Not registered error numbers will be translated to "Unknown error %d.".
+*/
+static struct my_err_head
+{
+ struct my_err_head *meh_next; /* chain link */
+ const char **meh_errmsgs; /* error messages array */
+ int meh_first; /* error number matching array slot 0 */
+ int meh_last; /* error number matching last slot */
+} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST};
+static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs;
+
+/*
Error message to user
SYNOPSIS
@@ -33,115 +62,42 @@ char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
nr Errno
MyFlags Flags
... variable list
- NOTE
- The following subset of printf format is supported:
- "%[0-9.-]*l?[sdu]", where all length flags are parsed but ignored.
- Additionally "%.*s" is supported and "%.*[ud]" is correctly parsed but
- the length value is ignored.
+ RETURN
+ What (*error_handler_hook)() returns:
+ 0 OK
*/
-int my_error(int nr,myf MyFlags, ...)
+int my_error(int nr, myf MyFlags, ...)
{
- va_list ap;
- uint olen, plen;
- reg1 const char *tpos;
- reg2 char *endpos;
- char * par;
- char ebuff[ERRMSGSIZE+20];
- int prec_chars; /* output precision */
- my_bool prec_supplied;
+ const char *format;
+ struct my_err_head *meh_p;
+ va_list args;
+ char ebuff[ERRMSGSIZE + 20];
DBUG_ENTER("my_error");
- LINT_INIT(prec_chars); /* protected by prec_supplied */
- va_start(ap,MyFlags);
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno));
- if (nr / ERRMOD == GLOB && my_errmsg[GLOB] == 0)
- init_glob_errs();
+ /* Search for the error messages array, which could contain the message. */
+ for (meh_p= my_errmsgs_list; meh_p; meh_p= meh_p->meh_next)
+ if (nr <= meh_p->meh_last)
+ break;
- olen=(uint) strlen(tpos=my_errmsg[nr / ERRMOD][nr % ERRMOD]);
- endpos=ebuff;
+#ifdef SHARED_LIBRARY
+ if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0])
+ init_glob_errs();
+#endif
- while (*tpos)
+ /* get the error message string. Default, if NULL or empty string (""). */
+ if (! (format= (meh_p && (nr >= meh_p->meh_first)) ?
+ meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format)
+ (void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr);
+ else
{
- if (tpos[0] != '%')
- {
- *endpos++= *tpos++; /* Copy ordinary char */
- continue;
- }
- if (*++tpos == '%') /* test if %% */
- {
- olen--;
- }
- else
- {
- /*
- Skip size/precision flags to be compatible with printf.
- The only size/precision flag supported is "%.*s".
- If "%.*u" or "%.*d" are encountered, the precision number is read
- from the variable argument list but its value is ignored.
- */
- prec_supplied= 0;
- if (*tpos== '.')
- {
- tpos++;
- olen--;
- if (*tpos == '*')
- {
- tpos++;
- olen--;
- prec_chars= va_arg(ap, int); /* get length parameter */
- prec_supplied= 1;
- }
- }
-
- if (!prec_supplied)
- {
- while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' ||
- *tpos == '-')
- tpos++;
-
- if (*tpos == 'l') /* Skip 'l' argument */
- tpos++;
- }
-
- if (*tpos == 's') /* String parameter */
- {
- par= va_arg(ap, char *);
- plen= (uint) strlen(par);
- if (prec_supplied && prec_chars > 0)
- plen= min((uint)prec_chars, plen);
- if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */
- {
- strmake(endpos, par, plen);
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */
- {
- register int iarg;
- iarg= va_arg(ap, int);
- if (*tpos == 'd')
- plen= (uint) (int10_to_str((long) iarg, endpos, -10) - endpos);
- else
- plen= (uint) (int10_to_str((long) (uint) iarg, endpos, 10) - endpos);
- if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */
- {
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- }
- *endpos++= '%'; /* % used as % or unknown code */
+ va_start(args,MyFlags);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
+ va_end(args);
}
- *endpos= '\0'; /* End of errmessage */
- va_end(ap);
DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}
@@ -160,11 +116,14 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
+ DBUG_ENTER("my_printf_error");
+ DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s",
+ error, MyFlags, errno, format));
va_start(args,MyFlags);
- (void) vsprintf (ebuff,format,args);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
- return (*error_handler_hook)(error, ebuff, MyFlags);
+ DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags));
}
/*
@@ -181,3 +140,112 @@ int my_message(uint error, const char *str, register myf MyFlags)
{
return (*error_handler_hook)(error, str, MyFlags);
}
+
+
+/*
+ Register error messages for use with my_error().
+
+ SYNOPSIS
+ my_error_register()
+ errmsgs array of pointers to error messages
+ first error number of first message in the array
+ last error number of last message in the array
+
+ DESCRIPTION
+ The pointer array is expected to contain addresses to NUL-terminated
+ C character strings. The array contains (last - first + 1) pointers.
+ NULL pointers and empty strings ("") are allowed. These will be mapped to
+ "Unknown error" when my_error() is called with a matching error number.
+ This function registers the error numbers 'first' to 'last'.
+ No overlapping with previously registered error numbers is allowed.
+
+ RETURN
+ 0 OK
+ != 0 Error
+*/
+
+int my_error_register(const char **errmsgs, int first, int last)
+{
+ struct my_err_head *meh_p;
+ struct my_err_head **search_meh_pp;
+
+ /* Allocate a new header structure. */
+ if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head),
+ MYF(MY_WME))))
+ return 1;
+ meh_p->meh_errmsgs= errmsgs;
+ meh_p->meh_first= first;
+ meh_p->meh_last= last;
+
+ /* Search for the right position in the list. */
+ for (search_meh_pp= &my_errmsgs_list;
+ *search_meh_pp;
+ search_meh_pp= &(*search_meh_pp)->meh_next)
+ {
+ if ((*search_meh_pp)->meh_last > first)
+ break;
+ }
+
+ /* Error numbers must be unique. No overlapping is allowed. */
+ if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last))
+ {
+ my_free((gptr)meh_p, MYF(0));
+ return 1;
+ }
+
+ /* Insert header into the chain. */
+ meh_p->meh_next= *search_meh_pp;
+ *search_meh_pp= meh_p;
+ return 0;
+}
+
+
+/*
+ Unregister formerly registered error messages.
+
+ SYNOPSIS
+ my_error_unregister()
+ first error number of first message
+ last error number of last message
+
+ DESCRIPTION
+ This function unregisters the error numbers 'first' to 'last'.
+ These must have been previously registered by my_error_register().
+ 'first' and 'last' must exactly match the registration.
+ If a matching registration is present, the header is removed from the
+ list and the pointer to the error messages pointers array is returned.
+ Otherwise, NULL is returned.
+
+ RETURN
+ non-NULL OK, returns address of error messages pointers array.
+ NULL Error, no such number range registered.
+*/
+
+const char **my_error_unregister(int first, int last)
+{
+ struct my_err_head *meh_p;
+ struct my_err_head **search_meh_pp;
+ const char **errmsgs;
+
+ /* Search for the registration in the list. */
+ for (search_meh_pp= &my_errmsgs_list;
+ *search_meh_pp;
+ search_meh_pp= &(*search_meh_pp)->meh_next)
+ {
+ if (((*search_meh_pp)->meh_first == first) &&
+ ((*search_meh_pp)->meh_last == last))
+ break;
+ }
+ if (! *search_meh_pp)
+ return NULL;
+
+ /* Remove header from the chain. */
+ meh_p= *search_meh_pp;
+ *search_meh_pp= meh_p->meh_next;
+
+ /* Save the return value and free the header. */
+ errmsgs= meh_p->meh_errmsgs;
+ my_free((gptr) meh_p, MYF(0));
+
+ return errmsgs;
+}
diff --git a/mysys/my_file.c b/mysys/my_file.c
index 6a9d39cf944..c97a512f8a1 100644
--- a/mysys/my_file.c
+++ b/mysys/my_file.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index f07beec9f39..b56be263ba4 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -79,7 +78,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags)
my_stream_opened++;
my_file_info[fileno(fd)].type = STREAM_BY_FOPEN;
pthread_mutex_unlock(&THR_LOCK_open);
- DBUG_PRINT("exit",("stream: 0x%lx",fd));
+ DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
DBUG_RETURN(fd);
}
pthread_mutex_unlock(&THR_LOCK_open);
@@ -103,7 +102,7 @@ int my_fclose(FILE *fd, myf MyFlags)
{
int err,file;
DBUG_ENTER("my_fclose");
- DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d",fd, MyFlags));
+ DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
file=fileno(fd);
@@ -163,7 +162,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags)
pthread_mutex_unlock(&THR_LOCK_open);
}
- DBUG_PRINT("exit",("stream: 0x%lx",fd));
+ DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
DBUG_RETURN(fd);
} /* my_fdopen */
diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c
index 5b17e3ff51c..ea30509ca8c 100644
--- a/mysys/my_fstream.c
+++ b/mysys/my_fstream.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -40,7 +39,7 @@ uint my_fread(FILE *stream, byte *Buffer, uint Count, myf MyFlags)
uint readbytes;
DBUG_ENTER("my_fread");
DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d",
- stream, Buffer, Count, MyFlags));
+ (long) stream, (long) Buffer, Count, MyFlags));
if ((readbytes = (uint) fread(Buffer,sizeof(char),(size_t) Count,stream))
!= Count)
@@ -81,7 +80,7 @@ uint my_fwrite(FILE *stream, const byte *Buffer, uint Count, myf MyFlags)
#endif
DBUG_ENTER("my_fwrite");
DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d",
- stream, Buffer, Count, MyFlags));
+ (long) stream, (long) Buffer, Count, MyFlags));
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
errors=0;
@@ -153,7 +152,7 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence,
{
DBUG_ENTER("my_fseek");
DBUG_PRINT("my",("stream: 0x%lx pos: %lu whence: %d MyFlags: %d",
- stream, pos, whence, MyFlags));
+ (long) stream, (long) pos, whence, MyFlags));
DBUG_RETURN(fseek(stream, (off_t) pos, whence) ?
MY_FILEPOS_ERROR : (my_off_t) ftell(stream));
} /* my_seek */
@@ -166,7 +165,7 @@ my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused)))
{
off_t pos;
DBUG_ENTER("my_ftell");
- DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d",stream, MyFlags));
+ DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) stream, MyFlags));
pos=ftell(stream);
DBUG_PRINT("exit",("ftell: %lu",(ulong) pos));
DBUG_RETURN((my_off_t) pos);
diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c
index 27281f3489d..434a00bab11 100644
--- a/mysys/my_gethostbyname.c
+++ b/mysys/my_gethostbyname.c
@@ -1,9 +1,9 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002, 2004 MySQL AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
index 222abe81933..01abc02058b 100644
--- a/mysys/my_gethwaddr.c
+++ b/mysys/my_gethwaddr.c
@@ -1,9 +1,8 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 075956c7af9..623c48b2e55 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -1,9 +1,8 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002-2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -185,7 +184,7 @@ int handle_options(int *argc, char ***argv,
}
opt_str= check_struct_option(cur_arg, key_name);
optend= strcend(opt_str, '=');
- length= optend - opt_str;
+ length= (uint) (optend - opt_str);
if (*optend == '=')
optend++;
else
@@ -195,6 +194,7 @@ int handle_options(int *argc, char ***argv,
Find first the right option. Return error in case of an ambiguous,
or unknown option
*/
+ LINT_INIT(prev_found);
optp= longopts;
if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
{
@@ -210,7 +210,8 @@ int handle_options(int *argc, char ***argv,
{
if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
special_opt_prefix_lengths[i]) &&
- opt_str[special_opt_prefix_lengths[i]] == '-')
+ (opt_str[special_opt_prefix_lengths[i]] == '-' ||
+ opt_str[special_opt_prefix_lengths[i]] == '_'))
{
/*
We were called with a special prefix, we can reuse opt_found
@@ -327,7 +328,7 @@ int handle_options(int *argc, char ***argv,
return EXIT_NO_ARGUMENT_ALLOWED;
}
value= optp->var_type & GET_ASK_ADDR ?
- (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value;
+ (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp) : optp->value;
if (optp->arg_type == NO_ARG)
{
@@ -346,11 +347,24 @@ int handle_options(int *argc, char ***argv,
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
*/
- my_bool tmp= (my_bool) (!optend || *optend == '1');
- *((my_bool*) value)= tmp;
(*argc)--;
+ if (!optend || *optend == '1' ||
+ !my_strcasecmp(&my_charset_latin1, optend, "true"))
+ *((my_bool*) value)= (my_bool) 1;
+ else if (*optend == '0' ||
+ !my_strcasecmp(&my_charset_latin1, optend, "false"))
+ *((my_bool*) value)= (my_bool) 0;
+ else
+ {
+ my_getopt_error_reporter(WARNING_LEVEL,
+ "%s: ignoring option '--%s' due to \
+invalid value '%s'\n",
+ my_progname, optp->name, optend);
+ continue;
+ }
get_one_option(optp->id, optp,
- tmp ? (char*) "1" : disabled_my_option);
+ *((my_bool*) value) ?
+ (char*) "1" : disabled_my_option);
continue;
}
argument= optend;
@@ -523,7 +537,7 @@ static char *check_struct_option(char *cur_arg, char *key_name)
*/
if (end - ptr > 1)
{
- uint len= ptr - cur_arg;
+ uint len= (uint) (ptr - cur_arg);
set_if_smaller(len, FN_REFLEN-1);
strmake(key_name, cur_arg, len);
return ++ptr;
@@ -591,16 +605,27 @@ static int setval(const struct my_option *opts, gptr *value, char *argument,
return 0;
}
-/*
- function: findopt
- Arguments: opt_pattern, length of opt_pattern, opt_struct, first found
- name (ffname)
+/*
+ Find option
- Go through all options in the my_option struct. Return number
- of options found that match the pattern and in the argument
- list the option found, if any. In case of ambiguous option, store
- the name in ffname argument
+ SYNOPSIS
+ findopt()
+ optpat Prefix of option to find (with - or _)
+ length Length of optpat
+ opt_res Options
+ ffname Place for pointer to first found name
+
+ IMPLEMENTATION
+ Go through all options in the my_option struct. Return number
+ of options found that match the pattern and in the argument
+ list the option found, if any. In case of ambiguous option, store
+ the name in ffname argument
+
+ RETURN
+ 0 No matching options
+ # Number of matching options
+ ffname points to first matching option
*/
static int findopt(char *optpat, uint length,
@@ -615,12 +640,21 @@ static int findopt(char *optpat, uint length,
if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */
{
(*opt_res)= opt;
- if (!count)
- *ffname= (char *) opt->name; /* We only need to know one prev */
if (!opt->name[length]) /* Exact match */
return 1;
- if (!count || strcmp(*ffname, opt->name)) /* Don't count synonyms */
+ if (!count)
+ {
+ count= 1;
+ *ffname= (char *) opt->name; /* We only need to know one prev */
+ }
+ else if (strcmp(*ffname, opt->name))
+ {
+ /*
+ The above test is to not count same option twice
+ (see mysql.cc, option "help")
+ */
count++;
+ }
}
}
return count;
@@ -837,7 +871,7 @@ void my_print_help(const struct my_option *options)
if (strlen(optp->name))
{
printf("--%s", optp->name);
- col+= 2 + strlen(optp->name);
+ col+= 2 + (uint) strlen(optp->name);
if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
(optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
{
@@ -908,7 +942,7 @@ void my_print_variables(const struct my_option *options)
if (value)
{
printf("%s", optp->name);
- length= strlen(optp->name);
+ length= (uint) strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
switch ((optp->var_type & GET_TYPE_MASK)) {
diff --git a/mysys/my_getpagesize.c b/mysys/my_getpagesize.c
new file mode 100644
index 00000000000..b0560cede35
--- /dev/null
+++ b/mysys/my_getpagesize.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+
+#ifndef HAVE_GETPAGESIZE
+
+#if defined __WIN__
+
+int my_getpagesize(void)
+{
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+}
+
+#else
+
+/* Default implementation */
+int my_getpagesize(void)
+{
+ return (int)8192;
+}
+
+#endif
+
+#endif
+
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
index 91c977f0b5a..2fd7eed7778 100644
--- a/mysys/my_getsystime.c
+++ b/mysys/my_getsystime.c
@@ -1,9 +1,8 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index 5663ceaa60e..3870a5d61b0 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -45,7 +44,7 @@ int my_getwd(my_string buf, uint size, myf MyFlags)
{
my_string pos;
DBUG_ENTER("my_getwd");
- DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", buf,size,MyFlags));
+ DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", (long) buf,size,MyFlags));
#if ! defined(MSDOS)
if (curr_dir[0]) /* Current pos is saved here */
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 156e7892580..afc44cc2838 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -1,9 +1,9 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002-2006 MySQL AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,11 +22,11 @@ int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
uchar *b, uint b_length, my_bool part_key,
my_bool skip_end_space)
{
- if (skip_end_space)
+ if (!part_key)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
- b, b_length);
+ b, b_length, (my_bool)!skip_end_space);
return charset_info->coll->strnncoll(charset_info, a, a_length,
- b, b_length, part_key);
+ b, b_length, part_key);
}
@@ -197,6 +197,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
}
break;
case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_BIT:
if (keyseg->flag & HA_SPACE_PACK)
{
int a_length,b_length,pack_length;
@@ -225,13 +226,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
b+=length;
}
break;
- case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
{
- int a_length,full_a_length,b_length,full_b_length,pack_length;
+ int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
- full_a_length= a_length;
- full_b_length= b_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
@@ -240,14 +240,17 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
next_key_length <= 0),
(my_bool) ((nextflag & (SEARCH_FIND |
SEARCH_UPDATE)) ==
- SEARCH_FIND))))
+ SEARCH_FIND &&
+ ! (keyseg->flag &
+ HA_END_SPACE_ARE_EQUAL)))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+= full_a_length;
- b+= full_b_length;
+ a+= a_length;
+ b+= b_length;
break;
}
break;
- case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
{
int a_length,b_length,pack_length;
get_key_length(a_length,a);
@@ -502,6 +505,7 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
switch ((enum ha_base_keytype) keyseg->type) {
case HA_KEYTYPE_TEXT:
case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_BIT:
if (keyseg->flag & HA_SPACE_PACK)
{
int a_length;
@@ -512,8 +516,10 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
else
a= end;
break;
- case HA_KEYTYPE_VARTEXT:
- case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
+ case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
{
int a_length;
get_key_length(a_length, a);
@@ -543,6 +549,10 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
case HA_KEYTYPE_DOUBLE:
a= end;
break;
+ case HA_KEYTYPE_END: /* purecov: inspected */
+ /* keep compiler happy */
+ DBUG_ASSERT(0);
+ break;
}
}
return keyseg;
diff --git a/mysys/my_init.c b/mysys/my_init.c
index d68c76bef1b..2bcf5f44c4d 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -96,7 +95,7 @@ my_bool my_init(void)
#endif
{
DBUG_ENTER("my_init");
- DBUG_PROCESS(my_progname ? my_progname : (char*) "unknown");
+ DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown"));
if (!home_dir)
{ /* Don't initialize twice */
my_win_init();
@@ -196,8 +195,12 @@ Voluntary context switches %ld, Involuntary context switches %ld\n",
_CrtDumpMemoryLeaks();
#endif
}
+
+ if (!(infoflag & MY_DONT_FREE_DBUG))
+ {
+ DBUG_END(); /* Must be done before my_thread_end */
+ }
#ifdef THREAD
- DBUG_POP(); /* Must be done before my_thread_end */
my_thread_end();
my_thread_global_end();
#if defined(SAFE_MUTEX)
@@ -243,6 +246,22 @@ void setEnvString(char *ret, const char *name, const char *value)
DBUG_VOID_RETURN ;
}
+/*
+ my_paramter_handler
+ Invalid paramter 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.
+*/
+void my_parameter_handler(const wchar_t * expression, const wchar_t * function,
+ const wchar_t * file, unsigned int line,
+ uintptr_t pReserved)
+{
+ DBUG_PRINT("my",("Expression: %s function: %s file: %s, line: %d",
+ expression, function, file, line));
+}
+
+
static void my_win_init(void)
{
HKEY hSoftMysql ;
@@ -260,12 +279,18 @@ static void my_win_init(void)
setlocale(LC_CTYPE, ""); /* To get right sortorder */
-#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#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
_tzset();
@@ -409,7 +434,7 @@ static void netware_init()
}
/* Parse program name and change to base format */
- name= my_progname;
+ name= (char*) my_progname;
for (; *name; name++)
{
if (*name == '\\')
diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c
new file mode 100644
index 00000000000..9714c582acb
--- /dev/null
+++ b/mysys/my_largepage.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2004 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+
+#ifdef HAVE_LARGE_PAGES
+
+#ifdef HAVE_SYS_IPC_H
+#include <sys/ipc.h>
+#endif
+
+#ifdef HAVE_SYS_SHM_H
+#include <sys/shm.h>
+#endif
+
+static uint my_get_large_page_size_int(void);
+static gptr my_large_malloc_int(uint size, myf my_flags);
+static my_bool my_large_free_int(gptr ptr, myf my_flags);
+
+/* Gets the size of large pages from the OS */
+
+uint my_get_large_page_size(void)
+{
+ uint size;
+ DBUG_ENTER("my_get_large_page_size");
+
+ if (!(size = my_get_large_page_size_int()))
+ fprintf(stderr, "Warning: Failed to determine large page size\n");
+
+ DBUG_RETURN(size);
+}
+
+/*
+ General large pages allocator.
+ Tries to allocate memory from large pages pool and falls back to
+ my_malloc_lock() in case of failure
+*/
+
+gptr my_large_malloc(uint size, myf my_flags)
+{
+ gptr ptr;
+ DBUG_ENTER("my_large_malloc");
+
+ if (my_use_large_pages && my_large_page_size)
+ {
+ if ((ptr = my_large_malloc_int(size, my_flags)) != NULL)
+ DBUG_RETURN(ptr);
+ if (my_flags & MY_WME)
+ fprintf(stderr, "Warning: Using conventional memory pool\n");
+ }
+
+ DBUG_RETURN(my_malloc_lock(size, my_flags));
+}
+
+/*
+ General large pages deallocator.
+ Tries to deallocate memory as if it was from large pages pool and falls back
+ to my_free_lock() in case of failure
+ */
+
+void my_large_free(gptr ptr, myf my_flags __attribute__((unused)))
+{
+ DBUG_ENTER("my_large_free");
+
+ /*
+ my_large_free_int() can only fail if ptr was not allocated with
+ my_large_malloc_int(), i.e. my_malloc_lock() was used so we should free it
+ with my_free_lock()
+ */
+ if (!my_use_large_pages || !my_large_page_size ||
+ !my_large_free_int(ptr, my_flags))
+ my_free_lock(ptr, my_flags);
+
+ DBUG_VOID_RETURN;
+}
+
+#ifdef HUGETLB_USE_PROC_MEMINFO
+/* Linux-specific function to determine the size of large pages */
+
+uint my_get_large_page_size_int(void)
+{
+ FILE *f;
+ uint size = 0;
+ char buf[256];
+ DBUG_ENTER("my_get_large_page_size_int");
+
+ if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME))))
+ goto finish;
+
+ while (fgets(buf, sizeof(buf), f))
+ if (sscanf(buf, "Hugepagesize: %u kB", &size))
+ break;
+
+ my_fclose(f, MYF(MY_WME));
+
+finish:
+ DBUG_RETURN(size * 1024);
+}
+#endif /* HUGETLB_USE_PROC_MEMINFO */
+
+#if HAVE_DECL_SHM_HUGETLB
+/* Linux-specific large pages allocator */
+
+gptr my_large_malloc_int(uint size, myf my_flags)
+{
+ int shmid;
+ gptr ptr;
+ struct shmid_ds buf;
+ DBUG_ENTER("my_large_malloc_int");
+
+ /* Align block size to my_large_page_size */
+ size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size;
+
+ shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
+ if (shmid < 0)
+ {
+ if (my_flags & MY_WME)
+ fprintf(stderr,
+ "Warning: Failed to allocate %d bytes from HugeTLB memory."
+ " errno %d\n", size, errno);
+
+ DBUG_RETURN(NULL);
+ }
+
+ ptr = shmat(shmid, NULL, 0);
+ if (ptr == (void *)-1)
+ {
+ if (my_flags& MY_WME)
+ fprintf(stderr, "Warning: Failed to attach shared memory segment,"
+ " errno %d\n", errno);
+ shmctl(shmid, IPC_RMID, &buf);
+
+ DBUG_RETURN(NULL);
+ }
+
+ /*
+ Remove the shared memory segment so that it will be automatically freed
+ after memory is detached or process exits
+ */
+ shmctl(shmid, IPC_RMID, &buf);
+
+ DBUG_RETURN(ptr);
+}
+
+/* Linux-specific large pages deallocator */
+
+my_bool my_large_free_int(byte *ptr, myf my_flags __attribute__((unused)))
+{
+ DBUG_ENTER("my_large_free_int");
+ DBUG_RETURN(shmdt(ptr) == 0);
+}
+#endif /* HAVE_DECL_SHM_HUGETLB */
+
+#endif /* HAVE_LARGE_PAGES */
diff --git a/mysys/my_lib.c b/mysys/my_lib.c
index 1908c70f407..75e31c4d555 100644
--- a/mysys/my_lib.c
+++ b/mysys/my_lib.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -170,6 +169,8 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
bzero(finfo.mystat, sizeof(MY_STAT));
VOID(strmov(tmp_file,dp->d_name));
VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
+ if (!(finfo.mystat->st_mode & MY_S_IREAD))
+ continue;
}
else
finfo.mystat= NULL;
@@ -382,11 +383,10 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
/* Put LIB-CHAR as last path-character if not there */
-
tmp_file=tmp_path;
if (!*path)
*tmp_file++ ='.'; /* From current dir */
- tmp_file= strmov(tmp_file,path);
+ tmp_file= strnmov(tmp_file, path, FN_REFLEN-5);
if (tmp_file[-1] == FN_DEVCHAR)
*tmp_file++= '.'; /* From current dev-dir */
if (tmp_file[-1] != FN_LIBCHAR)
@@ -396,14 +396,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
tmp_file[2]='*';
tmp_file[3]='\0';
-#ifdef __BORLANDC__
- if ((handle= findfirst(tmp_path,&find,0)) == -1L)
- goto error;
-#else
- if ((handle=_findfirst(tmp_path,&find)) == -1L)
- goto error;
-#endif
-
if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
sizeof(MEM_ROOT), MyFlags)))
@@ -423,72 +415,92 @@ MY_DIR *my_dir(const char *path, myf MyFlags)
/* MY_DIR structure is allocated and completly initialized at this point */
result= (MY_DIR*)buffer;
-
- do
- {
+
#ifdef __BORLANDC__
- attrib= find.ff_attrib;
+ if ((handle= findfirst(tmp_path,&find,0)) == -1L)
#else
- attrib= find.attrib;
+ if ((handle=_findfirst(tmp_path,&find)) == -1L)
+#endif
+ {
+ DBUG_PRINT("info", ("findfirst returned error, errno: %d", errno));
+ if (errno != EINVAL)
+ goto error;
/*
- Do not show hidden and system files which Windows sometimes create.
- Note. Because Borland's findfirst() is called with the third
- argument = 0 hidden/system files are excluded from the search.
+ Could not read the directory, no read access.
+ Probably because by "chmod -r".
+ continue and return zero files in dir
*/
- if (attrib & (_A_HIDDEN | _A_SYSTEM))
- continue;
-#endif
+ }
+ else
+ {
+
+ do
+ {
#ifdef __BORLANDC__
- if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
- goto error;
+ attrib= find.ff_attrib;
#else
- if (!(finfo.name= strdup_root(names_storage, find.name)))
- goto error;
-#endif
- if (MyFlags & MY_WANT_STAT)
- {
- if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
- sizeof(MY_STAT))))
+ attrib= find.attrib;
+ /*
+ Do not show hidden and system files which Windows sometimes create.
+ Note. Because Borland's findfirst() is called with the third
+ argument = 0 hidden/system files are excluded from the search.
+ */
+ if (attrib & (_A_HIDDEN | _A_SYSTEM))
+ continue;
+#endif
+#ifdef __BORLANDC__
+ if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
goto error;
-
- bzero(finfo.mystat, sizeof(MY_STAT));
+#else
+ if (!(finfo.name= strdup_root(names_storage, find.name)))
+ goto error;
+#endif
+ if (MyFlags & MY_WANT_STAT)
+ {
+ if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
+ sizeof(MY_STAT))))
+ goto error;
+
+ bzero(finfo.mystat, sizeof(MY_STAT));
#ifdef __BORLANDC__
- finfo.mystat->st_size=find.ff_fsize;
+ finfo.mystat->st_size=find.ff_fsize;
#else
- finfo.mystat->st_size=find.size;
+ finfo.mystat->st_size=find.size;
#endif
- mode=MY_S_IREAD;
- if (!(attrib & _A_RDONLY))
- mode|=MY_S_IWRITE;
- if (attrib & _A_SUBDIR)
- mode|=MY_S_IFDIR;
- finfo.mystat->st_mode=mode;
+ mode= MY_S_IREAD;
+ if (!(attrib & _A_RDONLY))
+ mode|= MY_S_IWRITE;
+ if (attrib & _A_SUBDIR)
+ mode|= MY_S_IFDIR;
+ finfo.mystat->st_mode= mode;
#ifdef __BORLANDC__
- finfo.mystat->st_mtime=((uint32) find.ff_ftime);
+ finfo.mystat->st_mtime= ((uint32) find.ff_ftime);
#else
- finfo.mystat->st_mtime=((uint32) find.time_write);
+ finfo.mystat->st_mtime= ((uint32) find.time_write);
#endif
- }
- else
- finfo.mystat= NULL;
+ }
+ else
+ finfo.mystat= NULL;
- if (push_dynamic(dir_entries_storage, (gptr)&finfo))
- goto error;
-
+ if (push_dynamic(dir_entries_storage, (gptr)&finfo))
+ goto error;
+ }
#ifdef __BORLANDC__
- } while (findnext(&find) == 0);
+ while (findnext(&find) == 0);
#else
- } while (_findnext(handle,&find) == 0);
-
- _findclose(handle);
+ while (_findnext(handle,&find) == 0);
+
+ _findclose(handle);
#endif
+ }
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
result->number_off_files= dir_entries_storage->elements;
-
+
if (!(MyFlags & MY_DONT_SORT))
qsort((void *) result->dir_entry, result->number_off_files,
sizeof(FILEINFO), (qsort_cmp) comp_names);
+ DBUG_PRINT("exit", ("found %d files", result->number_off_files));
DBUG_RETURN(result);
error:
my_errno=errno;
@@ -625,7 +637,7 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
int m_used;
DBUG_ENTER("my_stat");
DBUG_PRINT("my", ("path: '%s', stat_area: 0x%lx, MyFlags: %d", path,
- (byte *) stat_area, my_flags));
+ (long) stat_area, my_flags));
if ((m_used= (stat_area == NULL)))
if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c
new file mode 100644
index 00000000000..e72334ba806
--- /dev/null
+++ b/mysys/my_libwrap.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ This is needed to be able to compile with original libwrap header
+ files that don't have the prototypes
+*/
+
+#include <my_global.h>
+#include <my_libwrap.h>
+
+#ifdef HAVE_LIBWRAP
+
+void my_fromhost(struct request_info *req)
+{
+ fromhost(req);
+}
+
+int my_hosts_access(struct request_info *req)
+{
+ return hosts_access(req);
+}
+
+char *my_eval_client(struct request_info *req)
+{
+ return eval_client(req);
+}
+
+#endif /* HAVE_LIBWRAP */
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index b8307f366c0..a07f0c072a0 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_lockmem.c b/mysys/my_lockmem.c
index 6712c387a71..a58a5a340b1 100644
--- a/mysys/my_lockmem.c
+++ b/mysys/my_lockmem.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_lread.c b/mysys/my_lread.c
index a96febe4474..1399b197119 100644
--- a/mysys/my_lread.c
+++ b/mysys/my_lread.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -27,8 +26,8 @@ uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags)
{
uint32 readbytes;
DBUG_ENTER("my_lread");
- DBUG_PRINT("my",("Fd: %d Buffer: %ld Count: %ld MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
+ Filedes, (long) Buffer, (ulong) Count, MyFlags));
DBUG_PRINT("error", ("Deprecated my_lread() function should not be used."));
diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c
index 02c56a69ba4..d26825397e3 100644
--- a/mysys/my_lwrite.c
+++ b/mysys/my_lwrite.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -23,8 +22,8 @@ uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags)
{
uint32 writenbytes;
DBUG_ENTER("my_lwrite");
- DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %ld MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d",
+ Filedes, (long) Buffer, (ulong) Count, MyFlags));
DBUG_PRINT("error", ("Deprecated my_lwrite() function should not be used."));
diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c
index 3f601a42dc9..3baf55d4c57 100644
--- a/mysys/my_malloc.c
+++ b/mysys/my_malloc.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -44,7 +43,7 @@ gptr my_malloc(unsigned int size, myf my_flags)
}
else if (my_flags & MY_ZEROFILL)
bzero(point,size);
- DBUG_PRINT("exit",("ptr: 0x%lx",point));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) point));
DBUG_RETURN(point);
} /* my_malloc */
@@ -55,7 +54,7 @@ gptr my_malloc(unsigned int size, myf my_flags)
void my_no_flags_free(gptr ptr)
{
DBUG_ENTER("my_free");
- DBUG_PRINT("my",("ptr: 0x%lx",ptr));
+ DBUG_PRINT("my",("ptr: 0x%lx", (long) ptr));
if (ptr)
free(ptr);
DBUG_VOID_RETURN;
@@ -83,7 +82,7 @@ char *my_strdup(const char *from, myf my_flags)
}
-char *my_strdup_with_length(const byte *from, uint length, myf my_flags)
+char *my_strdup_with_length(const char *from, uint length, myf my_flags)
{
gptr ptr;
if ((ptr=my_malloc(length+1,my_flags)) != 0)
diff --git a/mysys/my_memmem.c b/mysys/my_memmem.c
new file mode 100644
index 00000000000..682a1314f09
--- /dev/null
+++ b/mysys/my_memmem.c
@@ -0,0 +1,66 @@
+#include "my_base.h"
+
+/*
+ my_memmem, port of a GNU extension.
+
+ Returns a pointer to the beginning of the substring, needle, or NULL if the
+ substring is not found in haystack.
+*/
+void *my_memmem(const void *haystack, size_t haystacklen,
+ const void *needle, size_t needlelen)
+{
+ const unsigned char *cursor;
+ const unsigned char *last_possible_needle_location =
+ (unsigned char *)haystack + haystacklen - needlelen;
+
+ /* Easy answers */
+ if (needlelen > haystacklen) return(NULL);
+ if (needle == NULL) return(NULL);
+ if (haystack == NULL) return(NULL);
+ if (needlelen == 0) return(NULL);
+ if (haystacklen == 0) return(NULL);
+
+ for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) {
+ if (memcmp(needle, cursor, needlelen) == 0) {
+ return((void *) cursor);
+ }
+ }
+ return(NULL);
+}
+
+
+
+#ifdef MAIN
+#include <assert.h>
+
+int main(int argc, char *argv[]) {
+ char haystack[10], needle[3];
+
+ memmove(haystack, "0123456789", 10);
+
+ memmove(needle, "no", 2);
+ assert(my_memmem(haystack, 10, needle, 2) == NULL);
+
+ memmove(needle, "345", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+
+ memmove(needle, "789", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+ assert(my_memmem(haystack, 9, needle, 3) == NULL);
+
+ memmove(needle, "012", 3);
+ assert(my_memmem(haystack, 10, needle, 3) != NULL);
+ assert(my_memmem(NULL, 10, needle, 3) == NULL);
+
+ assert(my_memmem(NULL, 10, needle, 3) == NULL);
+ assert(my_memmem(haystack, 0, needle, 3) == NULL);
+ assert(my_memmem(haystack, 10, NULL, 3) == NULL);
+ assert(my_memmem(haystack, 10, needle, 0) == NULL);
+
+ assert(my_memmem(haystack, 1, needle, 3) == NULL);
+
+ printf("success\n");
+ return(0);
+}
+
+#endif
diff --git a/mysys/my_messnc.c b/mysys/my_messnc.c
index 1f9df3c7c2c..e2431959b7a 100644
--- a/mysys/my_messnc.c
+++ b/mysys/my_messnc.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_mkdir.c b/mysys/my_mkdir.c
index ba1f4c1f2d8..25176e4b823 100644
--- a/mysys/my_mkdir.c
+++ b/mysys/my_mkdir.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
new file mode 100644
index 00000000000..147bdfdcbf2
--- /dev/null
+++ b/mysys/my_mmap.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+
+#ifdef HAVE_SYS_MMAN_H
+
+/*
+ system msync() only syncs mmap'ed area to fs cache.
+ fsync() is required to really sync to disc
+*/
+int my_msync(int fd, void *addr, size_t len, int flags)
+{
+ msync(addr, len, flags);
+ return my_sync(fd, MYF(0));
+}
+
+#elif defined(__WIN__)
+
+static SECURITY_ATTRIBUTES mmap_security_attributes=
+ {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
+
+void *my_mmap(void *addr, size_t len, int prot,
+ int flags, int fd, my_off_t offset)
+{
+ DWORD flProtect=0;
+ HANDLE hFileMap;
+ LPVOID ptr;
+ HANDLE hFile= (HANDLE)_get_osfhandle(fd);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return MAP_FAILED;
+
+ flProtect|=SEC_COMMIT;
+
+ hFileMap=CreateFileMapping(hFile, &mmap_security_attributes,
+ PAGE_READWRITE, 0, (DWORD) len, NULL);
+ if (hFileMap == 0)
+ return MAP_FAILED;
+
+ ptr=MapViewOfFile(hFileMap,
+ flags & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ,
+ (DWORD)(offset >> 32), (DWORD)offset, len);
+
+ /*
+ MSDN explicitly states that it's possible to close File Mapping Object
+ even when a view is not unmapped - then the object will be held open
+ implicitly until unmap, as every view stores internally a handler of
+ a corresponding File Mapping Object
+ */
+ CloseHandle(hFileMap);
+
+ if (ptr)
+ return ptr;
+
+ return MAP_FAILED;
+}
+
+int my_munmap(void *addr, size_t len)
+{
+ return UnmapViewOfFile(addr) ? 0 : -1;
+}
+
+int my_msync(int fd, void *addr, size_t len, int flags)
+{
+ return FlushViewOfFile(addr, len) ? 0 : -1;
+}
+
+#else
+#warning "no mmap!"
+#endif
+
diff --git a/mysys/my_net.c b/mysys/my_net.c
index be92adae353..136d987f500 100644
--- a/mysys/my_net.c
+++ b/mysys/my_net.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_netware.c b/mysys/my_netware.c
index 9c604778c2d..5b5c39c0ac0 100644
--- a/mysys/my_netware.c
+++ b/mysys/my_netware.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_new.cc b/mysys/my_new.cc
index 14423c3afd5..babfe04d695 100644
--- a/mysys/my_new.cc
+++ b/mysys/my_new.cc
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -45,5 +44,14 @@ void operator delete[] (void *ptr) throw ()
free(ptr);
}
+C_MODE_START
+
+int __cxa_pure_virtual() {
+ assert("Pure virtual method called." == "Aborted");
+ return 0;
+}
+
+C_MODE_END
+
#endif /* USE_MYSYS_NEW */
diff --git a/mysys/my_once.c b/mysys/my_once.c
index a4201810b03..d83eba95b9d 100644
--- a/mysys/my_once.c
+++ b/mysys/my_once.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -81,7 +80,7 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags)
char *my_once_strdup(const char *src,myf myflags)
{
- uint len=strlen(src)+1;
+ uint len= (uint) strlen(src)+1;
char *dst=my_once_alloc(len, myflags);
if (dst)
memcpy(dst, src, len);
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 7cf40b57403..9e1da1d3f07 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -56,12 +55,18 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
DBUG_RETURN(my_register_filename(-1, FileName, FILE_BY_OPEN,
EE_FILENOTFOUND, MyFlags));
}
+#ifndef __WIN__
if (Flags & O_SHARE)
fd = sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
MY_S_IREAD | MY_S_IWRITE);
else
fd = open((my_string) FileName, Flags | O_BINARY,
MY_S_IREAD | MY_S_IWRITE);
+#else
+ fd= my_sopen((my_string) FileName, (Flags & ~O_SHARE) | O_BINARY, SH_DENYNO,
+ MY_S_IREAD | MY_S_IWRITE);
+#endif
+
#elif !defined(NO_OPEN_3)
fd = open(FileName, Flags, my_umask); /* Normal unix */
#else
@@ -79,7 +84,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
my_close()
fd File sescriptor
myf Special Flags
-
+
*/
int my_close(File fd, myf MyFlags)
@@ -89,7 +94,12 @@ int my_close(File fd, myf MyFlags)
DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
- if ((err = close(fd)))
+ do
+ {
+ err= close(fd);
+ } while (err == -1 && errno == EINTR);
+
+ if (err)
{
DBUG_PRINT("error",("Got error %d on close",err));
my_errno=errno;
@@ -162,3 +172,186 @@ File my_register_filename(File fd, const char *FileName, enum file_type
FileName, my_errno);
return(fd);
}
+
+#ifdef __WIN__
+
+extern void __cdecl _dosmaperr(unsigned long);
+
+/*
+ Open a file with sharing. Similar to _sopen() from libc, but allows managing
+ share delete on win32
+
+ SYNOPSIS
+ my_sopen()
+ path fully qualified file name
+ oflag operation flags
+ shflag share flag
+ pmode permission flags
+
+ RETURN VALUE
+ File descriptor of opened file if success
+ -1 and sets errno if fails.
+*/
+
+File my_sopen(const char *path, int oflag, int shflag, int pmode)
+{
+ int fh; /* handle of opened file */
+ int mask;
+ HANDLE osfh; /* OS handle of opened file */
+ DWORD fileaccess; /* OS file access (requested) */
+ DWORD fileshare; /* OS file sharing mode */
+ DWORD filecreate; /* OS method of opening/creating */
+ DWORD fileattrib; /* OS file attribute flags */
+ SECURITY_ATTRIBUTES SecurityAttributes;
+
+ SecurityAttributes.nLength= sizeof(SecurityAttributes);
+ SecurityAttributes.lpSecurityDescriptor= NULL;
+ SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
+
+ /*
+ * decode the access flags
+ */
+ switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
+ case _O_RDONLY: /* read access */
+ fileaccess= GENERIC_READ;
+ break;
+ case _O_WRONLY: /* write access */
+ fileaccess= GENERIC_WRITE;
+ break;
+ case _O_RDWR: /* read and write access */
+ fileaccess= GENERIC_READ | GENERIC_WRITE;
+ break;
+ default: /* error, bad oflag */
+ errno= EINVAL;
+ _doserrno= 0L; /* not an OS error */
+ return -1;
+ }
+
+ /*
+ * decode sharing flags
+ */
+ switch (shflag) {
+ case _SH_DENYRW: /* exclusive access except delete */
+ fileshare= FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYWR: /* share read and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRD: /* share write and delete access */
+ fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYNO: /* share read, write and delete access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case _SH_DENYRWD: /* exclusive access */
+ fileshare= 0L;
+ break;
+ case _SH_DENYWRD: /* share read access */
+ fileshare= FILE_SHARE_READ;
+ break;
+ case _SH_DENYRDD: /* share write access */
+ fileshare= FILE_SHARE_WRITE;
+ break;
+ case _SH_DENYDEL: /* share read and write access */
+ fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+ default: /* error, bad shflag */
+ errno= EINVAL;
+ _doserrno= 0L; /* not an OS error */
+ return -1;
+ }
+
+ /*
+ * decode open/create method flags
+ */
+ switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
+ case 0:
+ case _O_EXCL: /* ignore EXCL w/o CREAT */
+ filecreate= OPEN_EXISTING;
+ break;
+
+ case _O_CREAT:
+ filecreate= OPEN_ALWAYS;
+ break;
+
+ case _O_CREAT | _O_EXCL:
+ case _O_CREAT | _O_TRUNC | _O_EXCL:
+ filecreate= CREATE_NEW;
+ break;
+
+ case _O_TRUNC:
+ case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
+ filecreate= TRUNCATE_EXISTING;
+ break;
+
+ case _O_CREAT | _O_TRUNC:
+ filecreate= CREATE_ALWAYS;
+ break;
+
+ default:
+ /* this can't happen ... all cases are covered */
+ errno= EINVAL;
+ _doserrno= 0L;
+ return -1;
+ }
+
+ /*
+ * decode file attribute flags if _O_CREAT was specified
+ */
+ fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */
+ if (oflag & _O_CREAT)
+ {
+ _umask((mask= _umask(0)));
+
+ if (!((pmode & ~mask) & _S_IWRITE))
+ fileattrib= FILE_ATTRIBUTE_READONLY;
+ }
+
+ /*
+ * Set temporary file (delete-on-close) attribute if requested.
+ */
+ if (oflag & _O_TEMPORARY)
+ {
+ fileattrib|= FILE_FLAG_DELETE_ON_CLOSE;
+ fileaccess|= DELETE;
+ }
+
+ /*
+ * Set temporary file (delay-flush-to-disk) attribute if requested.
+ */
+ if (oflag & _O_SHORT_LIVED)
+ fileattrib|= FILE_ATTRIBUTE_TEMPORARY;
+
+ /*
+ * Set sequential or random access attribute if requested.
+ */
+ if (oflag & _O_SEQUENTIAL)
+ fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN;
+ else if (oflag & _O_RANDOM)
+ fileattrib|= FILE_FLAG_RANDOM_ACCESS;
+
+ /*
+ * try to open/create the file
+ */
+ if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
+ filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
+ {
+ /*
+ * OS call to open/create file failed! map the error, release
+ * the lock, and return -1. note that it's not necessary to
+ * call _free_osfhnd (it hasn't been used yet).
+ */
+ _dosmaperr(GetLastError()); /* map error */
+ return -1; /* return error to caller */
+ }
+
+ if ((fh= _open_osfhandle((intptr_t)osfh,
+ oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1)
+ {
+ _dosmaperr(GetLastError()); /* map error */
+ CloseHandle(osfh);
+ }
+
+ return fh; /* return handle */
+}
+#endif /* __WIN__ */
diff --git a/mysys/my_os2cond.c b/mysys/my_os2cond.c
index e23afb89e66..f0cf91404d2 100644
--- a/mysys/my_os2cond.c
+++ b/mysys/my_os2cond.c
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -22,7 +22,7 @@
** The following is a simple implementation of posix conditions
*****************************************************************************/
-#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
+#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */
#include "mysys_priv.h"
#if defined(THREAD) && defined(OS2)
#include <m_string.h>
@@ -31,134 +31,109 @@
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
- APIRET rc = 0;
- HEV event;
- cond->waiting=0;
- /* Warp3 FP29 or Warp4 FP4 or better required */
- rc = DosCreateEventSem( NULL, &cond->semaphore, 0x0800, 0);
- if (rc)
- return ENOMEM;
-
+ cond->waiting= 0;
+ /* Warp3 FP29 or Warp4 FP4 or better required */
+ if (DosCreateEventSem(NULL, &cond->semaphore, 0x0800, 0))
+ return ENOMEM;
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond)
{
- APIRET rc;
-
- do {
- rc = DosCloseEventSem(cond->semaphore);
- if (rc == 301) DosPostEventSem(cond->semaphore);
- } while (rc == 301);
- if (rc)
- return EINVAL;
-
- return 0;
+ for (;;)
+ {
+ APIRET rc;
+ if ((rc= DosCloseEventSem(cond->semaphore)) != 301)
+ return rc ? EINVAL : 0;
+ DosPostEventSem(cond->semaphore);
+ }
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
- APIRET rc;
- int rval;
-
- rval = 0;
- cond->waiting++;
-
- if (mutex) pthread_mutex_unlock(mutex);
-
- rc = DosWaitEventSem(cond->semaphore,SEM_INDEFINITE_WAIT);
- if (rc != 0)
- rval = EINVAL;
-
- if (mutex) pthread_mutex_lock(mutex);
-
- cond->waiting--;
-
- return rval;
+ int rval= 0;
+ cond->waiting++;
+ if (mutex)
+ pthread_mutex_unlock(mutex);
+ if (DosWaitEventSem(cond->semaphore, SEM_INDEFINITE_WAIT))
+ rval= EINVAL;
+ if (mutex)
+ pthread_mutex_lock(mutex);
+ cond->waiting--;
+ return rval;
}
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
- struct timespec *abstime)
+ struct timespec *abstime)
{
struct timeb curtime;
int result;
long timeout;
- APIRET rc;
- int rval;
-
- _ftime(&curtime);
- timeout= ((long) (abstime->ts_sec - curtime.time)*1000L +
- (long)((abstime->ts_nsec/1000) - curtime.millitm)/1000L);
- if (timeout < 0) /* Some safety */
- timeout = 0L;
+ int rval= 0;
- rval = 0;
- cond->waiting++;
+ _ftime(&curtime);
+ timeout= ((long) (abstime->ts_sec - curtime.time) * 1000L +
+ (long) ((abstime->ts_nsec / 1000) - curtime.millitm) / 1000L);
+ if (timeout < 0) /* Some safety */
+ timeout= 0L;
- if (mutex) pthread_mutex_unlock(mutex);
+ cond->waiting++;
- rc = DosWaitEventSem(cond->semaphore, timeout);
- if (rc != 0)
- rval = ETIME;
+ if (mutex)
+ pthread_mutex_unlock(mutex);
+ if (DosWaitEventSem(cond->semaphore, timeout) != 0)
+ rval= ETIMEDOUT;
+ if (mutex)
+ pthread_mutex_lock(mutex);
- if (mutex) pthread_mutex_lock(mutex);
+ cond->waiting--;
- cond->waiting--;
-
- return rval;
+ return rval;
}
int pthread_cond_signal(pthread_cond_t *cond)
{
- APIRET rc;
-
- /* Bring the next thread off the condition queue: */
- rc = DosPostEventSem(cond->semaphore);
- return 0;
+ /* Bring the next thread off the condition queue: */
+ DosPostEventSem(cond->semaphore);
+ return 0;
}
int pthread_cond_broadcast(pthread_cond_t *cond)
{
- int i;
- APIRET rc;
-
- /*
- * Enter a loop to bring all threads off the
- * condition queue:
- */
- i = cond->waiting;
- while (i--) rc = DosPostEventSem(cond->semaphore);
-
- return 0 ;
+ int i;
+ /* Enter a loop to bring all threads off the condition queue */
+ for (i= cond->waiting; i--;)
+ DosPostEventSem(cond->semaphore);
+ return 0;
}
int pthread_attr_init(pthread_attr_t *connect_att)
{
- connect_att->dwStackSize = 0;
- connect_att->dwCreatingFlag = 0;
- connect_att->priority = 0;
+ connect_att->dwStackSize= 0;
+ connect_att->dwCreatingFlag= 0;
+ connect_att->priority= 0;
return 0;
}
-int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack)
+int pthread_attr_setstacksize(pthread_attr_t *connect_att, DWORD stack)
{
- connect_att->dwStackSize=stack;
+ connect_att->dwStackSize= stack;
return 0;
}
-int pthread_attr_setprio(pthread_attr_t *connect_att,int priority)
+int pthread_attr_setprio(pthread_attr_t *connect_att, int priority)
{
- connect_att->priority=priority;
+ connect_att->priority= priority;
return 0;
}
int pthread_attr_destroy(pthread_attr_t *connect_att)
{
- bzero((gptr) connect_att,sizeof(*connect_att));
+ bzero((gptr) connect_att, sizeof(*connect_att));
return 0;
}
@@ -166,22 +141,22 @@ int pthread_attr_destroy(pthread_attr_t *connect_att)
** Fix localtime_r() to be a bit safer
****************************************************************************/
-struct tm *localtime_r(const time_t *timep,struct tm *tmp)
+struct tm *localtime_r(const time_t *timep, struct tm *tmp)
{
- if (*timep == (time_t) -1) /* This will crash win32 */
+ if (*timep == (time_t) - 1) /* This will crash win32 */
{
- bzero(tmp,sizeof(*tmp));
+ bzero(tmp, sizeof(*tmp));
}
else
{
- struct tm *res=localtime(timep);
- if (!res) /* Wrong date */
+ struct tm *res= localtime(timep);
+ if (!res) /* Wrong date */
{
- bzero(tmp,sizeof(*tmp)); /* Keep things safe */
+ bzero(tmp, sizeof(*tmp)); /* Keep things safe */
return 0;
}
*tmp= *res;
}
return tmp;
}
-#endif /* __WIN__ */
+#endif /* __WIN__ */
diff --git a/mysys/my_os2dirsrch.c b/mysys/my_os2dirsrch.c
index 8d1f6ddd947..27e774c8e04 100644
--- a/mysys/my_os2dirsrch.c
+++ b/mysys/my_os2dirsrch.c
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_os2dirsrch.h b/mysys/my_os2dirsrch.h
index 3889f628bad..e3af6740769 100644
--- a/mysys/my_os2dirsrch.h
+++ b/mysys/my_os2dirsrch.h
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_os2dlfcn.c b/mysys/my_os2dlfcn.c
index 9c9a6061e8d..74be940d0d4 100644
--- a/mysys/my_os2dlfcn.c
+++ b/mysys/my_os2dlfcn.c
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_os2dlfcn.h0 b/mysys/my_os2dlfcn.h0
index 7f84d430230..ec05eebc47b 100644
--- a/mysys/my_os2dlfcn.h0
+++ b/mysys/my_os2dlfcn.h0
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_os2file64.c b/mysys/my_os2file64.c
index 786e083adc4..52156903b80 100644
--- a/mysys/my_os2file64.c
+++ b/mysys/my_os2file64.c
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_os2thread.c b/mysys/my_os2thread.c
index 0696f480a91..e34fd18d596 100644
--- a/mysys/my_os2thread.c
+++ b/mysys/my_os2thread.c
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -51,7 +51,7 @@ void win_pthread_init(void)
** in the new thread.
*/
-static pthread_handler_decl(pthread_start,param)
+pthread_handler_t pthread_start(void *param)
{
DBUG_ENTER("pthread_start");
pthread_handler func=((struct pthread_map *) param)->func;
diff --git a/mysys/my_os2tls.c b/mysys/my_os2tls.c
index f7cf3b09283..49100c65516 100644
--- a/mysys/my_os2tls.c
+++ b/mysys/my_os2tls.c
@@ -5,8 +5,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_port.c b/mysys/my_port.c
index bf5dbcbace1..9ad333421ca 100644
--- a/mysys/my_port.c
+++ b/mysys/my_port.c
@@ -1,9 +1,9 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002 MySQL AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index f378d548731..2d42a6ebbc4 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -30,7 +29,7 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
int error;
DBUG_ENTER("my_pread");
DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d",
- Filedes, (ulong) offset, Buffer, Count, MyFlags));
+ Filedes, (ulong) offset, (long) Buffer, Count, MyFlags));
for (;;)
{
@@ -49,8 +48,8 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset,
if (error)
{
my_errno=errno;
- DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d",
- readbytes,Count,Filedes,my_errno));
+ DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
+ (int) readbytes, Count,Filedes,my_errno));
#ifdef THREAD
if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
{
@@ -87,7 +86,7 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
ulong written;
DBUG_ENTER("my_pwrite");
DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %d MyFlags: %d",
- Filedes, (ulong) offset,Buffer, Count, MyFlags));
+ Filedes, (ulong) offset, (long) Buffer, Count, MyFlags));
errors=0; written=0L;
for (;;)
diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c
index 14ba6aabf0e..0422e0c6512 100644
--- a/mysys/my_pthread.c
+++ b/mysys/my_pthread.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -30,7 +29,7 @@
#define SCHED_POLICY SCHED_OTHER
#endif
-uint thd_lib_detected;
+uint thd_lib_detected= 0;
#ifndef my_pthread_setprio
void my_pthread_setprio(pthread_t thread_id,int prior)
diff --git a/mysys/my_quick.c b/mysys/my_quick.c
index ffc8160c371..15549dfb751 100644
--- a/mysys/my_quick.c
+++ b/mysys/my_quick.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_read.c b/mysys/my_read.c
index 8b88e483fef..a6c45340b0c 100644
--- a/mysys/my_read.c
+++ b/mysys/my_read.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -39,7 +38,7 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
uint readbytes, save_count;
DBUG_ENTER("my_read");
DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ Filedes, (long) Buffer, Count, MyFlags));
save_count= Count;
for (;;)
@@ -48,8 +47,8 @@ uint my_read(File Filedes, byte *Buffer, uint Count, myf MyFlags)
if ((readbytes= (uint) read(Filedes, Buffer, Count)) != Count)
{
my_errno= errno ? errno : -1;
- DBUG_PRINT("warning",("Read only %ld bytes off %ld from %d, errno: %d",
- readbytes, Count, Filedes, my_errno));
+ DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
+ (int) readbytes, Count, Filedes, my_errno));
#ifdef THREAD
if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR)
{
diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c
index c8edb172890..43fbb0c1eee 100644
--- a/mysys/my_realloc.c
+++ b/mysys/my_realloc.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -27,7 +26,7 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags)
{
gptr point;
DBUG_ENTER("my_realloc");
- DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d",oldpoint, size,
+ DBUG_PRINT("my",("ptr: 0x%lx size: %u my_flags: %d", (long) oldpoint, size,
my_flags));
if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR))
@@ -52,7 +51,7 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags)
if ((point = (char*)realloc(oldpoint,size)) == NULL)
{
if (my_flags & MY_FREE_ON_ERROR)
- my_free(oldpoint,MyFLAGS);
+ my_free(oldpoint, my_flags);
if (my_flags & MY_HOLD_ON_ERROR)
DBUG_RETURN(oldpoint);
my_errno=errno;
@@ -60,6 +59,6 @@ gptr my_realloc(gptr oldpoint, uint size, myf my_flags)
my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size);
}
#endif
- DBUG_PRINT("exit",("ptr: 0x%lx",point));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) point));
DBUG_RETURN(point);
} /* my_realloc */
diff --git a/mysys/my_redel.c b/mysys/my_redel.c
index 9af360424b0..0aec395cf65 100644
--- a/mysys/my_redel.c
+++ b/mysys/my_redel.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -61,7 +60,7 @@ int my_redel(const char *org_name, const char *tmp_name, myf MyFlags)
MyFlags))
goto end;
}
- else if (my_delete(org_name,MyFlags))
+ else if (my_delete_allow_opened(org_name, MyFlags))
goto end;
if (my_rename(tmp_name,org_name,MyFlags))
goto end;
diff --git a/mysys/my_rename.c b/mysys/my_rename.c
index b5d813ad787..c4aeb95b2c0 100644
--- a/mysys/my_rename.c
+++ b/mysys/my_rename.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_seek.c b/mysys/my_seek.c
index a9ae68cd5f0..fd2344e0d36 100644
--- a/mysys/my_seek.c
+++ b/mysys/my_seek.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -51,11 +50,17 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
whence, MyFlags));
DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */
- newpos=lseek(fd, pos, whence);
+ /*
+ Make sure we are using a valid file descriptor!
+ */
+ DBUG_ASSERT(fd != -1);
+
+ newpos= lseek(fd, pos, whence);
+
if (newpos == (os_off_t) -1)
{
my_errno=errno;
- DBUG_PRINT("error",("lseek: %lu, errno: %d",newpos,errno));
+ DBUG_PRINT("error",("lseek: %lu, errno: %d", (ulong) newpos,errno));
DBUG_RETURN(MY_FILEPOS_ERROR);
}
if ((my_off_t) newpos != pos)
diff --git a/mysys/my_sleep.c b/mysys/my_sleep.c
index 31eaf7eeb96..50e6fae17fc 100644
--- a/mysys/my_sleep.c
+++ b/mysys/my_sleep.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 5f034555156..694e5058bb0 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -25,8 +24,11 @@
#include "my_alarm.h"
#endif
+my_bool timed_mutexes= 0;
+
/* from my_init */
-my_string home_dir=0,my_progname=0;
+my_string home_dir=0;
+const char *my_progname=0;
char NEAR curr_dir[FN_REFLEN]= {0},
NEAR home_dir_buff[FN_REFLEN]= {0};
ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0;
@@ -61,6 +63,12 @@ const char *soundex_map= "01230120022455012623010202";
USED_MEM* my_once_root_block=0; /* pointer to first block */
uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */
+ /* from my_largepage.c */
+#ifdef HAVE_LARGE_PAGES
+my_bool my_use_large_pages= 0;
+uint my_large_page_size= 0;
+#endif
+
/* from my_tempnam */
#if !defined(HAVE_TEMPNAM) || defined(HPUX11)
int _my_tempnam_used=0;
diff --git a/mysys/my_static.h b/mysys/my_static.h
index 51f9fbc922f..cbd293a0431 100644
--- a/mysys/my_static.h
+++ b/mysys/my_static.h
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_symlink.c b/mysys/my_symlink.c
index 7be3fcd36f0..810c0c72632 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c
index 603248e186b..2ad08ef67de 100644
--- a/mysys/my_symlink2.c
+++ b/mysys/my_symlink2.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index 317ca039346..64fce3aac21 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -27,7 +26,14 @@
my_flags Flags (now only MY_WME is supported)
NOTE
- If file system supports its, only file data is synced, not inode date
+ If file system supports its, only file data is synced, not inode data.
+
+ MY_IGNORE_BADFD is useful when fd is "volatile" - not protected by a
+ mutex. In this case by the time of fsync(), fd may be already closed by
+ another thread, or even reassigned to a different file. With this flag -
+ MY_IGNORE_BADFD - such a situation will not be considered an error.
+ (which is correct behaviour, if we know that the other thread synced the
+ file before closing)
RETURN
0 ok
@@ -40,21 +46,30 @@ int my_sync(File fd, myf my_flags)
DBUG_ENTER("my_sync");
DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags));
+ do
+ {
#if defined(HAVE_FDATASYNC)
- res= fdatasync(fd);
+ res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
- res=fsync(fd);
+ res= fsync(fd);
#elif defined(__WIN__)
res= _commit(fd);
#else
- res= 0; /* No sync (strange OS) */
+ res= 0; /* No sync (strange OS) */
#endif
+ } while (res == -1 && errno == EINTR);
+
if (res)
{
- if (!(my_errno= errno))
- my_errno= -1; /* Unknown error */
- if (my_flags & MY_WME)
+ int er= errno;
+ if (!(my_errno= er))
+ my_errno= -1; /* Unknown error */
+ if ((my_flags & MY_IGNORE_BADFD) &&
+ (er == EBADF || er == EINVAL || er == EROFS))
+ res= 0;
+ else if (my_flags & MY_WME)
my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno);
}
DBUG_RETURN(res);
-} /* my_read */
+} /* my_sync */
+
diff --git a/mysys/my_tempnam.c b/mysys/my_tempnam.c
deleted file mode 100644
index 9f765298fb6..00000000000
--- a/mysys/my_tempnam.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/* Copyright (C) 2000 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- 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 */
-
-/*
- This function is only used by some old ISAM code.
- When we remove ISAM support from MySQL, we should also delete this file
-
- One should instead use the functions in mf_tempfile.c
-*/
-
-#include "mysys_priv.h"
-#include <m_string.h>
-
-/* HPUX 11.0 doesn't allow us to change the environ pointer */
-#ifdef HPUX11
-#undef HAVE_TEMPNAM
-#endif
-
-#include "my_static.h"
-#include "mysys_err.h"
-
-#define TMP_EXT ".tmp" /* Extension of tempfile */
-#if ! defined(P_tmpdir)
-#define P_tmpdir ""
-#endif
-
-#ifdef HAVE_TEMPNAM
-#if !defined( MSDOS) && !defined(OS2) && !defined(__NETWARE__)
-extern char **environ;
-#endif
-#endif
-
-/* Make a uniq temp file name by using dir and adding something after
- pfx to make name uniq. Name is made by adding a uniq 8 length-string and
- TMP_EXT after pfx.
- Returns pointer to malloced area for filename. Should be freed by
- free().
- The name should be uniq, but it isn't checked if it file allready exists.
- Uses tempnam() if function exist on system.
- This function fixes that if dir is given it's used. For example
- MSDOS tempnam() uses always TMP environment-variable if it exists.
-*/
- /* ARGSUSED */
-
-my_string my_tempnam(const char *dir, const char *pfx,
- myf MyFlags __attribute__((unused)))
-{
-#ifdef _MSC_VER
- char temp[FN_REFLEN],*end,*res,**old_env,*temp_env[1];
- old_env=environ;
- if (dir)
- {
- end=strend(dir)-1;
- if (!dir[0])
- { /* Change empty string to current dir */
- temp[0]= FN_CURLIB;
- temp[1]= 0;
- dir=temp;
- }
- else if (*end == FN_DEVCHAR)
- { /* Get current dir for drive */
- _fullpath(temp,dir,FN_REFLEN);
- dir=temp;
- }
- else if (*end == FN_LIBCHAR && dir < end && end[-1] != FN_DEVCHAR)
- {
- strmake(temp,dir,(uint) (end-dir)); /* Copy and remove last '\' */
- dir=temp;
- }
- environ=temp_env; /* Force use of dir (dir not checked) */
- temp_env[0]=0;
- }
- res=tempnam((char*) dir,(my_string) pfx);
- environ=old_env;
- return res;
-#else
-#ifdef __ZTC__
- if (!dir)
- { /* If empty test first if TMP can be used */
- dir=getenv("TMP");
- }
- return tempnam((char*) dir,(my_string) pfx); /* Use stand. dir with prefix */
-#else
-#ifdef HAVE_TEMPNAM
- char temp[2],*res,**old_env,*temp_env[1];
-
- if (dir && !dir[0])
- { /* Change empty string to current dir */
- temp[0]= FN_CURLIB;
- temp[1]= 0;
- dir=temp;
- }
-#ifdef OS2
- /* changing environ variable doesn't work with VACPP */
- char buffer[256], *end;
- buffer[sizeof[buffer)-1]= 0;
- end= strxnmov(buffer, sizeof(buffer)-1, (char*) "TMP=", dir, NullS);
- /* remove ending backslash */
- if (end[-1] == '\\')
- end[-1]= 0;
- putenv(buffer);
-#elif !defined(__NETWARE__)
- old_env=(char**)environ;
- if (dir)
- { /* Don't use TMPDIR if dir is given */
- /*
- The following strange cast is required because the IBM compiler on AIX
- doesn't allow us to cast the value of environ.
- The cast of environ is needed as some systems doesn't allow us to
- update environ with a char ** pointer. (const mismatch)
- */
- (*(char***) &environ)=(char**) temp_env;
- temp_env[0]=0;
- }
-#endif
- res=tempnam((char*) dir,(my_string) pfx); /* Use stand. dir with prefix */
-#if !defined(OS2) && !defined(__NETWARE__)
- (*(char***) &environ)=(char**) old_env;
-#endif
- if (!res)
- DBUG_PRINT("error",("Got error: %d from tempnam",errno));
- return res;
-#else
- register long uniq;
- register int length;
- my_string pos,end_pos;
- DBUG_ENTER("my_tempnam");
- /* Make a uniq nummber */
- pthread_mutex_lock(&THR_LOCK_open);
- uniq= ((long) getpid() << 20) + (long) _my_tempnam_used++ ;
- pthread_mutex_unlock(&THR_LOCK_open);
- if (!dir && !(dir=getenv("TMPDIR"))) /* Use this if possibly */
- dir=P_tmpdir; /* Use system default */
- length=strlen(dir)+strlen(pfx)+1;
-
- DBUG_PRINT("test",("mallocing %d byte",length+8+sizeof(TMP_EXT)+1));
- if (!(pos=(char*) malloc(length+8+sizeof(TMP_EXT)+1)))
- {
- if (MyFlags & MY_FAE+MY_WME)
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),
- length+8+sizeof(TMP_EXT)+1);
- DBUG_RETURN(NullS);
- }
- end_pos=strmov(pos,dir);
- if (end_pos != pos && end_pos[-1] != FN_LIBCHAR)
- *end_pos++=FN_LIBCHAR;
- end_pos=strmov(end_pos,pfx);
-
- for (length=0 ; length < 8 && uniq ; length++)
- {
- *end_pos++= _dig_vec_upper[(int) (uniq & 31)];
- uniq >>= 5;
- }
- VOID(strmov(end_pos,TMP_EXT));
- DBUG_PRINT("exit",("tempnam: '%s'",pos));
- DBUG_RETURN(pos);
-#endif /* HAVE_TEMPNAM */
-#endif /* __ZTC__ */
-#endif /* _MSC_VER */
-} /* my_tempnam */
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 42f025c39f3..7a5fdbf8ad6 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -31,7 +30,10 @@ pthread_key(struct st_my_thread_var, THR_KEY_mysys);
#endif /* USE_TLS */
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
- THR_LOCK_net, THR_LOCK_charset;
+ THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads;
+pthread_cond_t THR_COND_threads;
+uint THR_thread_count= 0;
+uint my_thread_end_wait_time= 5;
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_t LOCK_localtime_r;
#endif
@@ -45,6 +47,23 @@ pthread_mutexattr_t my_fast_mutexattr;
pthread_mutexattr_t my_errorcheck_mutexattr;
#endif
+#ifdef NPTL_PTHREAD_EXIT_BUG /* see my_pthread.h */
+
+/*
+ Dummy thread spawned in my_thread_global_init() below to avoid
+ race conditions in NPTL pthread_exit code.
+*/
+
+static pthread_handler_t
+nptl_pthread_exit_hack_handler(void *arg __attribute__((unused)))
+{
+ /* Do nothing! */
+ pthread_exit(0);
+ return 0;
+}
+
+#endif
+
static uint get_thread_lib(void);
/*
@@ -67,17 +86,38 @@ my_bool my_thread_global_init(void)
fprintf(stderr,"Can't initialize threads: error %d\n",errno);
return 1;
}
+
+#ifdef NPTL_PTHREAD_EXIT_BUG
+
+/*
+ BUG#24507: Race conditions inside current NPTL pthread_exit() implementation.
+
+ To avoid a possible segmentation fault during concurrent executions of
+ pthread_exit(), a dummy thread is spawned which initializes internal variables
+ of pthread lib. See bug description for thoroughfull explanation.
+
+ TODO: Remove this code when fixed versions of glibc6 are in common use.
+*/
+
+ pthread_t dummy_thread;
+ pthread_attr_t dummy_thread_attr;
+
+ pthread_attr_init(&dummy_thread_attr);
+ pthread_attr_setdetachstate(&dummy_thread_attr,PTHREAD_CREATE_DETACHED);
+
+ pthread_create(&dummy_thread,&dummy_thread_attr,nptl_pthread_exit_hack_handler,NULL);
+
+#endif
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
/*
Set mutex type to "fast" a.k.a "adaptive"
- The mutex kind determines what happens if a thread attempts to lock
- a mutex it already owns with pthread_mutex_lock(3). If the mutex
- is of the ``fast'' kind, pthread_mutex_lock(3) simply suspends
- the calling thread forever. If the mutex is of the ``error checking''
- kind, pthread_mutex_lock(3) returns immediately with the error
- code EDEADLK.
+ In this case the thread may steal the mutex from some other thread
+ that is waiting for the same mutex. This will save us some
+ context switches but may cause a thread to 'starve forever' while
+ waiting for the mutex (not likely if the code within the mutex is
+ short).
*/
pthread_mutexattr_init(&my_fast_mutexattr);
pthread_mutexattr_settype(&my_fast_mutexattr,
@@ -85,7 +125,7 @@ my_bool my_thread_global_init(void)
#endif
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
/*
- Set mutex type to "errorcheck" a.k.a "adaptive"
+ Set mutex type to "errorcheck"
*/
pthread_mutexattr_init(&my_errorcheck_mutexattr);
pthread_mutexattr_settype(&my_errorcheck_mutexattr,
@@ -100,6 +140,8 @@ my_bool my_thread_global_init(void)
pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&THR_COND_threads, NULL);
#if defined( __WIN__) || defined(OS2)
win_pthread_init();
#endif
@@ -120,6 +162,27 @@ my_bool my_thread_global_init(void)
void my_thread_global_end(void)
{
+ struct timespec abstime;
+ my_bool all_threads_killed= 1;
+
+ set_timespec(abstime, my_thread_end_wait_time);
+ pthread_mutex_lock(&THR_LOCK_threads);
+ while (THR_thread_count > 0)
+ {
+ int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
+ &abstime);
+ if (error == ETIMEDOUT || error == ETIME)
+ {
+ if (THR_thread_count)
+ fprintf(stderr,
+ "Error in my_thread_global_end(): %d threads didn't exit\n",
+ THR_thread_count);
+ all_threads_killed= 0;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&THR_LOCK_threads);
+
pthread_key_delete(THR_KEY_mysys);
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
pthread_mutexattr_destroy(&my_fast_mutexattr);
@@ -135,6 +198,11 @@ void my_thread_global_end(void)
pthread_mutex_destroy(&THR_LOCK_heap);
pthread_mutex_destroy(&THR_LOCK_net);
pthread_mutex_destroy(&THR_LOCK_charset);
+ if (all_threads_killed)
+ {
+ pthread_mutex_destroy(&THR_LOCK_threads);
+ pthread_cond_destroy (&THR_COND_threads);
+ }
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
pthread_mutex_destroy(&LOCK_localtime_r);
#endif
@@ -146,10 +214,23 @@ void my_thread_global_end(void)
static long thread_id=0;
/*
- We can't use mutex_locks here if we are using windows as
- we may have compiled the program with SAFE_MUTEX, in which
- case the checking of mutex_locks will not work until
- the pthread_self thread specific variable is initialized.
+ Allocate thread specific memory for the thread, used by mysys and dbug
+
+ SYNOPSIS
+ my_thread_init()
+
+ NOTES
+ We can't use mutex_locks here if we are using windows as
+ we may have compiled the program with SAFE_MUTEX, in which
+ case the checking of mutex_locks will not work until
+ the pthread_self thread specific variable is initialized.
+
+ This function may called multiple times for a thread, for example
+ if one uses my_init() followed by mysql_server_init().
+
+ RETURN
+ 0 ok
+ 1 Fatal error; mysys/dbug functions can't be used
*/
my_bool my_thread_init(void)
@@ -160,9 +241,6 @@ my_bool my_thread_init(void)
#ifdef EXTRA_DEBUG_THREADS
fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self());
#endif
-#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
- pthread_mutex_lock(&THR_LOCK_lock);
-#endif
#if !defined(__WIN__) || defined(USE_TLS)
if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
@@ -180,7 +258,7 @@ my_bool my_thread_init(void)
}
pthread_setspecific(THR_KEY_mysys,tmp);
-#else
+#else /* defined(__WIN__) && !(defined(USE_TLS) */
/*
Skip initialization if the thread specific variable is already initialized
*/
@@ -188,7 +266,6 @@ my_bool my_thread_init(void)
goto end;
tmp= &THR_KEY_mysys;
#endif
- tmp->id= ++thread_id;
#if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
tmp->thread_self= (pthread_t)getpid();
#endif
@@ -196,22 +273,35 @@ my_bool my_thread_init(void)
pthread_cond_init(&tmp->suspend, NULL);
tmp->init= 1;
+ pthread_mutex_lock(&THR_LOCK_threads);
+ tmp->id= ++thread_id;
+ ++THR_thread_count;
+ pthread_mutex_unlock(&THR_LOCK_threads);
end:
-#if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
- pthread_mutex_unlock(&THR_LOCK_lock);
-#endif
return error;
}
+/*
+ Deallocate memory used by the thread for book-keeping
+
+ SYNOPSIS
+ my_thread_end()
+
+ NOTE
+ This may be called multiple times for a thread.
+ This happens for example when one calls 'mysql_server_init()'
+ mysql_server_end() and then ends with a mysql_end().
+*/
+
void my_thread_end(void)
{
struct st_my_thread_var *tmp;
tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
#ifdef EXTRA_DEBUG_THREADS
- fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ld\n",
- tmp,pthread_self());
+ fprintf(stderr,"my_thread_end(): tmp: 0x%lx thread_id=%ld\n",
+ (long) tmp, pthread_self());
#endif
if (tmp && tmp->init)
{
@@ -233,6 +323,18 @@ void my_thread_end(void)
#else
tmp->init= 0;
#endif
+
+ /*
+ Decrement counter for number of running threads. We are using this
+ in my_thread_global_end() to wait until all threads have called
+ my_thread_end and thus freed all memory they have allocated in
+ my_thread_init() and DBUG_xxxx
+ */
+ pthread_mutex_lock(&THR_LOCK_threads);
+ DBUG_ASSERT(THR_thread_count != 0);
+ if (--THR_thread_count == 0)
+ pthread_cond_signal(&THR_COND_threads);
+ pthread_mutex_unlock(&THR_LOCK_threads);
}
/* The following free has to be done, even if my_thread_var() is 0 */
#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
@@ -298,9 +400,9 @@ const char *my_thread_name(void)
static uint get_thread_lib(void)
{
+#ifdef _CS_GNU_LIBPTHREAD_VERSION
char buff[64];
-#ifdef _CS_GNU_LIBPTHREAD_VERSION
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
if (!strncasecmp(buff, "NPTL", 4))
diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c
index 8c497e8f250..353b2fced4e 100644
--- a/mysys/my_wincond.c
+++ b/mysys/my_wincond.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -28,65 +27,155 @@
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
{
- cond->waiting=0;
- cond->semaphore=CreateSemaphore(NULL,0,0x7FFFFFFF,NullS);
- if (!cond->semaphore)
+ cond->waiting= 0;
+ InitializeCriticalSection(&cond->lock_waiting);
+
+ cond->events[SIGNAL]= CreateEvent(NULL, /* no security */
+ FALSE, /* auto-reset event */
+ FALSE, /* non-signaled initially */
+ NULL); /* unnamed */
+
+ /* Create a manual-reset event. */
+ cond->events[BROADCAST]= CreateEvent(NULL, /* no security */
+ TRUE, /* manual-reset */
+ FALSE, /* non-signaled initially */
+ NULL); /* unnamed */
+
+
+ cond->broadcast_block_event= CreateEvent(NULL, /* no security */
+ TRUE, /* manual-reset */
+ TRUE, /* signaled initially */
+ NULL); /* unnamed */
+
+ if( cond->events[SIGNAL] == NULL ||
+ cond->events[BROADCAST] == NULL ||
+ cond->broadcast_block_event == NULL )
return ENOMEM;
return 0;
}
int pthread_cond_destroy(pthread_cond_t *cond)
{
- return CloseHandle(cond->semaphore) ? 0 : EINVAL;
+ DeleteCriticalSection(&cond->lock_waiting);
+
+ if (CloseHandle(cond->events[SIGNAL]) == 0 ||
+ CloseHandle(cond->events[BROADCAST]) == 0 ||
+ CloseHandle(cond->broadcast_block_event) == 0)
+ return EINVAL;
+ return 0;
}
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
{
- InterlockedIncrement(&cond->waiting);
- LeaveCriticalSection(mutex);
- WaitForSingleObject(cond->semaphore,INFINITE);
- InterlockedDecrement(&cond->waiting);
- EnterCriticalSection(mutex);
- return 0 ;
+ return pthread_cond_timedwait(cond,mutex,NULL);
}
+
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
struct timespec *abstime)
{
- struct _timeb curtime;
int result;
- long timeout;
- _ftime(&curtime);
- timeout= ((long) (abstime->tv_sec - curtime.time)*1000L +
- (long)((abstime->tv_nsec/1000) - curtime.millitm)/1000L);
- if (timeout < 0) /* Some safety */
- timeout = 0L;
- InterlockedIncrement(&cond->waiting);
+ long timeout;
+ union ft64 now;
+
+ if( abstime != NULL )
+ {
+ GetSystemTimeAsFileTime(&now.ft);
+
+ /*
+ Calculate time left to abstime
+ - subtract start time from current time(values are in 100ns units)
+ - convert to millisec by dividing with 10000
+ */
+ timeout= (long)((abstime->tv.i64 - now.i64) / 10000);
+
+ /* Don't allow the timeout to be negative */
+ if (timeout < 0)
+ timeout= 0L;
+
+ /*
+ Make sure the calucated timeout does not exceed original timeout
+ value which could cause "wait for ever" if system time changes
+ */
+ if (timeout > abstime->max_timeout_msec)
+ timeout= abstime->max_timeout_msec;
+
+ }
+ else
+ {
+ /* No time specified; don't expire */
+ timeout= INFINITE;
+ }
+
+ /*
+ Block access if previous broadcast hasn't finished.
+ This is just for safety and should normally not
+ affect the total time spent in this function.
+ */
+ WaitForSingleObject(cond->broadcast_block_event, INFINITE);
+
+ EnterCriticalSection(&cond->lock_waiting);
+ cond->waiting++;
+ LeaveCriticalSection(&cond->lock_waiting);
+
LeaveCriticalSection(mutex);
- result=WaitForSingleObject(cond->semaphore,timeout);
- InterlockedDecrement(&cond->waiting);
+
+ result= WaitForMultipleObjects(2, cond->events, FALSE, timeout);
+
+ EnterCriticalSection(&cond->lock_waiting);
+ cond->waiting--;
+
+ if (cond->waiting == 0 && result == (WAIT_OBJECT_0+BROADCAST))
+ {
+ /*
+ We're the last waiter to be notified or to stop waiting, so
+ reset the manual event.
+ */
+ /* Close broadcast gate */
+ ResetEvent(cond->events[BROADCAST]);
+ /* Open block gate */
+ SetEvent(cond->broadcast_block_event);
+ }
+ LeaveCriticalSection(&cond->lock_waiting);
+
EnterCriticalSection(mutex);
return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
}
-
int pthread_cond_signal(pthread_cond_t *cond)
{
- long prev_count;
- if (cond->waiting)
- ReleaseSemaphore(cond->semaphore,1,&prev_count);
+ EnterCriticalSection(&cond->lock_waiting);
+
+ if(cond->waiting > 0)
+ SetEvent(cond->events[SIGNAL]);
+
+ LeaveCriticalSection(&cond->lock_waiting);
+
return 0;
}
int pthread_cond_broadcast(pthread_cond_t *cond)
{
- long prev_count;
- if (cond->waiting)
- ReleaseSemaphore(cond->semaphore,cond->waiting,&prev_count);
- return 0 ;
+ EnterCriticalSection(&cond->lock_waiting);
+ /*
+ The mutex protect us from broadcasting if
+ there isn't any thread waiting to open the
+ block gate after this call has closed it.
+ */
+ if(cond->waiting > 0)
+ {
+ /* Close block gate */
+ ResetEvent(cond->broadcast_block_event);
+ /* Open broadcast gate */
+ SetEvent(cond->events[BROADCAST]);
+ }
+
+ LeaveCriticalSection(&cond->lock_waiting);
+
+ return 0;
}
diff --git a/mysys/my_windac.c b/mysys/my_windac.c
index 2c1027e4aa6..c711093b48f 100644
--- a/mysys/my_windac.c
+++ b/mysys/my_windac.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index eebc07df180..27ccaef4f23 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -51,7 +50,7 @@ void win_pthread_init(void)
** in the new thread.
*/
-static pthread_handler_decl(pthread_start,param)
+pthread_handler_t pthread_start(void *param)
{
pthread_handler func=((struct pthread_map *) param)->func;
void *func_param=((struct pthread_map *) param)->param;
diff --git a/mysys/my_write.c b/mysys/my_write.c
index ae8cb4ab02b..4c3d187e4e8 100644
--- a/mysys/my_write.c
+++ b/mysys/my_write.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -27,7 +26,7 @@ uint my_write(int Filedes, const byte *Buffer, uint Count, myf MyFlags)
ulong written;
DBUG_ENTER("my_write");
DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %d MyFlags: %d",
- Filedes, Buffer, Count, MyFlags));
+ Filedes, (long) Buffer, Count, MyFlags));
errors=0; written=0L;
for (;;)
diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h
index 89a6d8aa2a7..8a636e94626 100644
--- a/mysys/mysys_priv.h
+++ b/mysys/mysys_priv.h
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 5fc7ccab4fa..33c28160a4c 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -21,6 +20,7 @@
*/
#include "mysys_priv.h"
+#include <myisampack.h>
static int ptr_compare(uint *compare_length, uchar **a, uchar **b);
static int ptr_compare_0(uint *compare_length, uchar **a, uchar **b);
@@ -152,3 +152,41 @@ static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b)
}
return (0);
}
+
+void my_store_ptr(byte *buff, uint pack_length, my_off_t pos)
+{
+ switch (pack_length) {
+#if SIZEOF_OFF_T > 4
+ case 8: mi_int8store(buff,pos); break;
+ case 7: mi_int7store(buff,pos); break;
+ case 6: mi_int6store(buff,pos); break;
+ case 5: mi_int5store(buff,pos); break;
+#endif
+ case 4: mi_int4store(buff,pos); break;
+ case 3: mi_int3store(buff,pos); break;
+ case 2: mi_int2store(buff,pos); break;
+ case 1: buff[0]= (uchar) pos; break;
+ default: DBUG_ASSERT(0);
+ }
+ return;
+}
+
+my_off_t my_get_ptr(byte *ptr, uint pack_length)
+{
+ my_off_t pos;
+ switch (pack_length) {
+#if SIZEOF_OFF_T > 4
+ case 8: pos= (my_off_t) mi_uint8korr(ptr); break;
+ case 7: pos= (my_off_t) mi_uint7korr(ptr); break;
+ case 6: pos= (my_off_t) mi_uint6korr(ptr); break;
+ case 5: pos= (my_off_t) mi_uint5korr(ptr); break;
+#endif
+ case 4: pos= (my_off_t) mi_uint4korr(ptr); break;
+ case 3: pos= (my_off_t) mi_uint3korr(ptr); break;
+ case 2: pos= (my_off_t) mi_uint2korr(ptr); break;
+ case 1: pos= (my_off_t) mi_uint2korr(ptr); break;
+ default: DBUG_ASSERT(0); return 0;
+ }
+ return pos;
+}
+
diff --git a/mysys/queues.c b/mysys/queues.c
index 6a285ce7417..7809c97131c 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/raid.cc b/mysys/raid.cc
index 62587c438ca..c70c01fde4b 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -185,7 +184,7 @@ extern "C" {
uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_write");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
+ DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@@ -198,7 +197,7 @@ extern "C" {
uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_read");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
+ DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@@ -212,8 +211,9 @@ extern "C" {
myf MyFlags)
{
DBUG_ENTER("my_raid_pread");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
- Filedes, Buffer, Count, offset, MyFlags));
+ DBUG_PRINT("enter",
+ ("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d",
+ Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
@@ -231,8 +231,9 @@ extern "C" {
my_off_t offset, myf MyFlags)
{
DBUG_ENTER("my_raid_pwrite");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
- Filedes, Buffer, Count, offset, MyFlags));
+ DBUG_PRINT("enter",
+ ("Fd: %d Buffer: 0x %lx Count: %u offset: %u MyFlags: %d",
+ Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
diff --git a/mysys/raid2.c b/mysys/raid2.c
index 94b085b0074..4feace7410f 100644
--- a/mysys/raid2.c
+++ b/mysys/raid2.c
@@ -2,8 +2,8 @@
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
+ License as published by the Free Software Foundation; version 2
+ of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/mysys/rijndael.c b/mysys/rijndael.c
index 43cd14101ca..2b12753c4e5 100644
--- a/mysys/rijndael.c
+++ b/mysys/rijndael.c
@@ -1,9 +1,8 @@
-/* Copyright (C) 2002 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002, 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- at your option) any later version.
+ 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
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 6cdf98c5f5f..f43c860adb0 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -194,7 +193,7 @@ gptr _mymalloc(uint size, const char *filename, uint lineno, myf MyFlags)
if ((MyFlags & MY_ZEROFILL) || !sf_malloc_quick)
bfill(data, size, (char) (MyFlags & MY_ZEROFILL ? 0 : ALLOC_VAL));
/* Return a pointer to the real data */
- DBUG_PRINT("exit",("ptr: 0x%lx", data));
+ DBUG_PRINT("exit",("ptr: 0x%lx", (long) data));
if (sf_min_adress > data)
sf_min_adress= data;
if (sf_max_adress < data)
@@ -259,7 +258,7 @@ void _myfree(gptr ptr, const char *filename, uint lineno, myf myflags)
{
struct st_irem *irem;
DBUG_ENTER("_myfree");
- DBUG_PRINT("enter",("ptr: 0x%lx", ptr));
+ DBUG_PRINT("enter",("ptr: 0x%lx", (long) ptr));
if (!sf_malloc_quick)
(void) _sanity (filename, lineno);
@@ -410,7 +409,7 @@ void TERMINATE(FILE *file)
}
DBUG_PRINT("safe",
("%6u bytes at 0x%09lx, allocated at line %4d in '%s'",
- irem->datasize, data, irem->linenum, irem->filename));
+ irem->datasize, (long) data, irem->linenum, irem->filename));
irem= irem->next;
}
}
@@ -447,7 +446,7 @@ static int _checkchunk(register struct st_irem *irem, const char *filename,
fprintf(stderr, " discovered at %s:%d\n", filename, lineno);
(void) fflush(stderr);
DBUG_PRINT("safe",("Underrun at 0x%lx, allocated at %s:%d",
- data, irem->filename, irem->linenum));
+ (long) data, irem->filename, irem->linenum));
flag=1;
}
@@ -463,7 +462,7 @@ static int _checkchunk(register struct st_irem *irem, const char *filename,
fprintf(stderr, " discovered at '%s:%d'\n", filename, lineno);
(void) fflush(stderr);
DBUG_PRINT("safe",("Overrun at 0x%lx, allocated at %s:%d",
- data,
+ (long) data,
irem->filename,
irem->linenum));
flag=1;
@@ -525,7 +524,7 @@ char *_my_strdup(const char *from, const char *filename, uint lineno,
} /* _my_strdup */
-char *_my_strdup_with_length(const byte *from, uint length,
+char *_my_strdup_with_length(const char *from, uint length,
const char *filename, uint lineno,
myf MyFlags)
{
diff --git a/mysys/sha1.c b/mysys/sha1.c
index 110d24f8bfc..3469e480c26 100644
--- a/mysys/sha1.c
+++ b/mysys/sha1.c
@@ -1,9 +1,8 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2002, 2004, 2006 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -245,7 +244,7 @@ static void SHA1ProcessMessageBlock(SHA1_CONTEXT *context)
uint32 temp; /* Temporary word value */
uint32 W[80]; /* Word sequence */
uint32 A, B, C, D, E; /* Word buffers */
- int index;
+ int idx;
/*
Initialize the first 16 words in the array W
@@ -253,11 +252,11 @@ static void SHA1ProcessMessageBlock(SHA1_CONTEXT *context)
for (t = 0; t < 16; t++)
{
- index=t*4;
- W[t] = context->Message_Block[index] << 24;
- W[t] |= context->Message_Block[index + 1] << 16;
- W[t] |= context->Message_Block[index + 2] << 8;
- W[t] |= context->Message_Block[index + 3];
+ idx=t*4;
+ W[t] = context->Message_Block[idx] << 24;
+ W[t] |= context->Message_Block[idx + 1] << 16;
+ W[t] |= context->Message_Block[idx + 2] << 8;
+ W[t] |= context->Message_Block[idx + 3];
}
diff --git a/mysys/string.c b/mysys/string.c
index ea747bc9847..df78f2b98b5 100644
--- a/mysys/string.c
+++ b/mysys/string.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -91,7 +90,7 @@ my_bool dynstr_realloc(DYNAMIC_STRING *str, ulong additional_size)
my_bool dynstr_append(DYNAMIC_STRING *str, const char *append)
{
- return dynstr_append_mem(str,append,strlen(append));
+ return dynstr_append_mem(str,append,(uint) strlen(append));
}
@@ -116,6 +115,56 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
}
+/** Concatenates any number of strings, escapes any OS quote in the result then
+ * surround the whole affair in another set of quotes which is finally appended
+ * to specified DYNAMIC_STRING. This function is especially useful when
+ * building strings to be executed with the system() function.
+ * @param str Dynamic String which will have addtional strings appended.
+ * @param append String to be appended.
+ * @param ... Optional. Additional string(s) to be appended.
+ *
+ * @note The final argument in the list must be NullS even if no additional
+ * options are passed.
+ *
+ * @return True = Success.
+ */
+my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
+{
+#ifdef __WIN__
+ const char *quote_str= "\"";
+ const uint quote_len= 1;
+#else
+ const char *quote_str= "\'";
+ const uint quote_len= 1;
+#endif /* __WIN__ */
+ my_bool ret= TRUE;
+ va_list dirty_text;
+
+ ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */
+ va_start(dirty_text, append);
+ while (append != NullS)
+ {
+ const char *cur_pos= append;
+ const char *next_pos= cur_pos;
+
+ /* Search for quote in each string and replace with escaped quote */
+ while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0')
+ {
+ ret&= dynstr_append_mem(str, cur_pos, next_pos - cur_pos);
+ ret&= dynstr_append_mem(str ,"\\", 1);
+ ret&= dynstr_append_mem(str, quote_str, quote_len);
+ cur_pos= next_pos + 1;
+ }
+ ret&= dynstr_append_mem(str, cur_pos, next_pos - cur_pos);
+ append= va_arg(dirty_text, char *);
+ }
+ va_end(dirty_text);
+ ret&= dynstr_append_mem(str, quote_str, quote_len); /* Trailing quote */
+
+ return ret;
+}
+
+
void dynstr_free(DYNAMIC_STRING *str)
{
if (str->str)
diff --git a/mysys/test_charset.c b/mysys/test_charset.c
index 419332cb997..08154e67863 100644
--- a/mysys/test_charset.c
+++ b/mysys/test_charset.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/test_dir.c b/mysys/test_dir.c
index f3d220e942f..f1e4987371b 100644
--- a/mysys/test_dir.c
+++ b/mysys/test_dir.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/test_fn.c b/mysys/test_fn.c
index d0fb9f59fd6..249cc878390 100644
--- a/mysys/test_fn.c
+++ b/mysys/test_fn.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/test_xml.c b/mysys/test_xml.c
index 2a679906cbf..0cb10e1c8d9 100644
--- a/mysys/test_xml.c
+++ b/mysys/test_xml.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/testhash.c b/mysys/testhash.c
index d15016113cd..fd2bc73b2ae 100644
--- a/mysys/testhash.c
+++ b/mysys/testhash.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 759544af17b..d11883a4ea4 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -407,7 +406,7 @@ void end_thr_alarm(my_bool free_structures)
{
DBUG_ENTER("end_thr_alarm");
if (alarm_aborted != 1) /* If memory not freed */
- {
+ {
pthread_mutex_lock(&LOCK_alarm);
DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements));
alarm_aborted= -1; /* mark aborted */
@@ -421,13 +420,10 @@ void end_thr_alarm(my_bool free_structures)
if (free_structures)
{
struct timespec abstime;
- /*
- The following test is just for safety, the caller should not
- depend on this
- */
+
DBUG_ASSERT(!alarm_queue.elements);
- /* Wait until alarm thread dies */
+ /* Wait until alarm thread dies */
set_timespec(abstime, 10); /* Wait up to 10 seconds */
while (alarm_thread_running)
{
@@ -438,7 +434,7 @@ void end_thr_alarm(my_bool free_structures)
delete_queue(&alarm_queue);
alarm_aborted= 1;
pthread_mutex_unlock(&LOCK_alarm);
- if (!alarm_thread_running) /* Safety */
+ if (!alarm_thread_running) /* Safety */
{
pthread_mutex_destroy(&LOCK_alarm);
pthread_cond_destroy(&COND_alarm);
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index d6443539216..3d29379a9fc 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -84,6 +83,7 @@ multiple read locks.
my_bool thr_lock_inited=0;
ulong locks_immediate = 0L, locks_waited = 0L;
+ulong table_lock_wait_timeout;
enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE;
/* The following constants are only for debug output */
@@ -109,25 +109,32 @@ my_bool init_thr_lock()
return 0;
}
+static inline my_bool
+thr_lock_owner_equal(THR_LOCK_OWNER *rhs, THR_LOCK_OWNER *lhs)
+{
+ return rhs == lhs;
+}
+
+
#ifdef EXTRA_DEBUG
#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */
static uint found_errors=0;
static int check_lock(struct st_lock_list *list, const char* lock_type,
- const char *where, my_bool same_thread, bool no_cond)
+ const char *where, my_bool same_owner, bool no_cond)
{
THR_LOCK_DATA *data,**prev;
uint count=0;
- pthread_t first_thread;
- LINT_INIT(first_thread);
+ THR_LOCK_OWNER *first_owner;
+ LINT_INIT(first_owner);
prev= &list->data;
if (list->data)
{
enum thr_lock_type last_lock_type=list->data->type;
- if (same_thread && list->data)
- first_thread=list->data->thread;
+ if (same_owner && list->data)
+ first_owner= list->data->owner;
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
{
if (data->type != last_lock_type)
@@ -139,7 +146,8 @@ static int check_lock(struct st_lock_list *list, const char* lock_type,
count, lock_type, where);
return 1;
}
- if (same_thread && ! pthread_equal(data->thread,first_thread) &&
+ if (same_owner &&
+ !thr_lock_owner_equal(data->owner, first_owner) &&
last_lock_type != TL_WRITE_ALLOW_WRITE)
{
fprintf(stderr,
@@ -195,6 +203,8 @@ static void check_locks(THR_LOCK *lock, const char *where,
{
if ((int) data->type == (int) TL_READ_NO_INSERT)
count++;
+ /* Protect against infinite loop. */
+ DBUG_ASSERT(count <= lock->read_no_write_count);
}
if (count != lock->read_no_write_count)
{
@@ -255,8 +265,8 @@ static void check_locks(THR_LOCK *lock, const char *where,
}
if (lock->read.data)
{
- if (!pthread_equal(lock->write.data->thread,
- lock->read.data->thread) &&
+ if (!thr_lock_owner_equal(lock->write.data->owner,
+ lock->read.data->owner) &&
((lock->write.data->type > TL_WRITE_DELAYED &&
lock->write.data->type != TL_WRITE_ONLY) ||
((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT ||
@@ -330,24 +340,32 @@ void thr_lock_delete(THR_LOCK *lock)
DBUG_VOID_RETURN;
}
+
+void thr_lock_info_init(THR_LOCK_INFO *info)
+{
+ info->thread= pthread_self();
+ info->thread_id= my_thread_id(); /* for debugging */
+ info->n_cursors= 0;
+}
+
/* Initialize a lock instance */
void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param)
{
data->lock=lock;
data->type=TL_UNLOCK;
- data->thread=pthread_self();
- data->thread_id=my_thread_id(); /* for debugging */
+ data->owner= 0; /* no owner yet */
data->status_param=param;
data->cond=0;
}
-static inline my_bool have_old_read_lock(THR_LOCK_DATA *data,pthread_t thread)
+static inline my_bool
+have_old_read_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner)
{
for ( ; data ; data=data->next)
{
- if ((pthread_equal(data->thread,thread)))
+ if (thr_lock_owner_equal(data->owner, owner))
return 1; /* Already locked by thread */
}
return 0;
@@ -365,12 +383,15 @@ static inline my_bool have_specific_lock(THR_LOCK_DATA *data,
}
-static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
- my_bool in_wait_list)
+static enum enum_thr_lock_result
+wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
+ my_bool in_wait_list)
{
- pthread_cond_t *cond=get_cond();
- struct st_my_thread_var *thread_var=my_thread_var;
- int result;
+ struct st_my_thread_var *thread_var= my_thread_var;
+ pthread_cond_t *cond= &thread_var->suspend;
+ struct timespec wait_timeout;
+ enum enum_thr_lock_result result= THR_LOCK_ABORTED;
+ my_bool can_deadlock= test(data->owner->info->n_cursors);
if (!in_wait_list)
{
@@ -382,34 +403,56 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
/* Set up control struct to allow others to abort locks */
thread_var->current_mutex= &data->lock->mutex;
thread_var->current_cond= cond;
+ data->cond= cond;
- data->cond=cond;
+ if (can_deadlock)
+ set_timespec(wait_timeout, table_lock_wait_timeout);
while (!thread_var->abort || in_wait_list)
{
- pthread_cond_wait(cond,&data->lock->mutex);
- if (data->cond != cond)
+ int rc= (can_deadlock ?
+ pthread_cond_timedwait(cond, &data->lock->mutex,
+ &wait_timeout) :
+ pthread_cond_wait(cond, &data->lock->mutex));
+ /*
+ We must break the wait if one of the following occurs:
+ - the connection has been aborted (!thread_var->abort), but
+ this is not a delayed insert thread (in_wait_list). For a delayed
+ insert thread the proper action at shutdown is, apparently, to
+ acquire the lock and complete the insert.
+ - the lock has been granted (data->cond is set to NULL by the granter),
+ or the waiting has been aborted (additionally data->type is set to
+ TL_UNLOCK).
+ - the wait has timed out (rc == ETIMEDOUT)
+ Order of checks below is important to not report about timeout
+ if the predicate is true.
+ */
+ if (data->cond == 0)
+ break;
+ if (rc == ETIMEDOUT || rc == ETIME)
+ {
+ result= THR_LOCK_WAIT_TIMEOUT;
break;
+ }
}
if (data->cond || data->type == TL_UNLOCK)
{
- if (data->cond) /* aborted */
+ if (data->cond) /* aborted or timed out */
{
if (((*data->prev)=data->next)) /* remove from wait-list */
data->next->prev= data->prev;
else
wait->last=data->prev;
+ data->type= TL_UNLOCK; /* No lock */
}
- data->type=TL_UNLOCK; /* No lock */
- result=1; /* Didn't get lock */
check_locks(data->lock,"failed wait_for_lock",0);
}
else
{
- result=0;
+ result= THR_LOCK_SUCCESS;
statistic_increment(locks_waited, &THR_LOCK_lock);
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
check_locks(data->lock,"got wait_for_lock",0);
}
pthread_mutex_unlock(&data->lock->mutex);
@@ -423,20 +466,24 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
}
-int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
+enum enum_thr_lock_result
+thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner,
+ enum thr_lock_type lock_type)
{
THR_LOCK *lock=data->lock;
- int result=0;
+ enum enum_thr_lock_result result= THR_LOCK_SUCCESS;
+ struct st_lock_list *wait_queue;
+ THR_LOCK_DATA *lock_owner;
DBUG_ENTER("thr_lock");
data->next=0;
data->cond=0; /* safety */
data->type=lock_type;
- data->thread=pthread_self(); /* Must be reset ! */
- data->thread_id=my_thread_id(); /* Must be reset ! */
+ data->owner= owner; /* Must be reset ! */
VOID(pthread_mutex_lock(&lock->mutex));
DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx type: %d",
- data,data->thread_id,lock,(int) lock_type));
+ (long) data, data->owner->info->thread_id,
+ (long) lock, (int) lock_type));
check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ?
"enter read_lock" : "enter write_lock",0);
if ((int) lock_type <= (int) TL_READ_NO_INSERT)
@@ -454,8 +501,8 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
*/
DBUG_PRINT("lock",("write locked by thread: %ld",
- lock->write.data->thread_id));
- if (pthread_equal(data->thread,lock->write.data->thread) ||
+ lock->write.data->owner->info->thread_id));
+ if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
(lock->write.data->type <= TL_WRITE_DELAYED &&
(((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) ||
(lock->write.data->type != TL_WRITE_CONCURRENT_INSERT &&
@@ -464,11 +511,11 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
(*lock->read.last)=data; /* Add to running FIFO */
data->prev=lock->read.last;
lock->read.last= &data->next;
- if ((int) lock_type == (int) TL_READ_NO_INSERT)
+ if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with old write lock",0);
if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ (*lock->get_status)(data->status_param, 0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
@@ -476,28 +523,32 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
{
/* We are not allowed to get a READ lock in this case */
data->type=TL_UNLOCK;
- result=1; /* Can't wait for this one */
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
}
else if (!lock->write_wait.data ||
lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY ||
lock_type == TL_READ_HIGH_PRIORITY ||
- have_old_read_lock(lock->read.data,data->thread))
+ have_old_read_lock(lock->read.data, data->owner))
{ /* No important write-locks */
(*lock->read.last)=data; /* Add to running FIFO */
data->prev=lock->read.last;
lock->read.last= &data->next;
if (lock->get_status)
- (*lock->get_status)(data->status_param);
- if ((int) lock_type == (int) TL_READ_NO_INSERT)
+ (*lock->get_status)(data->status_param, 0);
+ if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with no write locks",0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
- /* Can't get lock yet; Wait for it */
- DBUG_RETURN(wait_for_lock(&lock->read_wait,data,0));
+ /*
+ We're here if there is an active write lock or no write
+ lock but a high priority write waiting in the write_wait queue.
+ In the latter case we should yield the lock to the writer.
+ */
+ wait_queue= &lock->read_wait;
}
else /* Request for WRITE lock */
{
@@ -506,7 +557,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY)
{
data->type=TL_UNLOCK;
- result=1; /* Can't wait for this one */
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
/*
@@ -523,8 +574,10 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write_wait.last;
lock->write_wait.last= &data->next;
data->cond=get_cond();
- if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ /*
+ We don't have to do get_status here as we will do it when we change
+ the delayed lock to a real write lock
+ */
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
@@ -538,7 +591,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
{
/* We are not allowed to get a lock in this case */
data->type=TL_UNLOCK;
- result=1; /* Can't wait for this one */
+ result= THR_LOCK_ABORTED; /* Can't wait for this one */
goto end;
}
@@ -547,7 +600,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
TL_WRITE_ALLOW_WRITE, TL_WRITE_ALLOW_READ or TL_WRITE_DELAYED in
the same thread, but this will never happen within MySQL.
*/
- if (pthread_equal(data->thread,lock->write.data->thread) ||
+ if (thr_lock_owner_equal(data->owner, lock->write.data->owner) ||
(lock_type == TL_WRITE_ALLOW_WRITE &&
!lock->write_wait.data &&
lock->write.data->type == TL_WRITE_ALLOW_WRITE))
@@ -565,12 +618,12 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
lock->write.last= &data->next;
check_locks(lock,"second write lock",0);
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
DBUG_PRINT("lock",("write locked by thread: %ld",
- lock->write.data->thread_id));
+ lock->write.data->owner->info->thread_id));
}
else
{
@@ -578,9 +631,16 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
(ulong) lock->write_wait.data));
if (!lock->write_wait.data)
{ /* no scheduled write locks */
- if (lock_type == TL_WRITE_CONCURRENT_INSERT &&
- (*lock->check_status)(data->status_param))
- data->type=lock_type= thr_upgraded_concurrent_insert_lock;
+ my_bool concurrent_insert= 0;
+ if (lock_type == TL_WRITE_CONCURRENT_INSERT)
+ {
+ concurrent_insert= 1;
+ if ((*lock->check_status)(data->status_param))
+ {
+ concurrent_insert= 0;
+ data->type=lock_type= thr_upgraded_concurrent_insert_lock;
+ }
+ }
if (!lock->read.data ||
(lock_type <= TL_WRITE_DELAYED &&
@@ -592,17 +652,31 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write.last;
lock->write.last= &data->next;
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, concurrent_insert);
check_locks(lock,"only write lock",0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
}
- DBUG_PRINT("lock",("write locked by thread: %ld, type: %ld",
- lock->read.data->thread_id,data->type));
+ DBUG_PRINT("lock",("write locked by thread: %ld, type: %d",
+ lock->read.data->owner->info->thread_id, data->type));
}
- DBUG_RETURN(wait_for_lock(&lock->write_wait,data,0));
+ wait_queue= &lock->write_wait;
+ }
+ /*
+ Try to detect a trivial deadlock when using cursors: attempt to
+ lock a table that is already locked by an open cursor within the
+ same connection. lock_owner can be zero if we succumbed to a high
+ priority writer in the write_wait queue.
+ */
+ lock_owner= lock->read.data ? lock->read.data : lock->write.data;
+ if (lock_owner && lock_owner->owner->info == owner->info)
+ {
+ result= THR_LOCK_DEADLOCK;
+ goto end;
}
+ /* Can't get lock yet; Wait for it */
+ DBUG_RETURN(wait_for_lock(wait_queue, data, 0));
end:
pthread_mutex_unlock(&lock->mutex);
DBUG_RETURN(result);
@@ -647,7 +721,7 @@ static inline void free_all_read_locks(THR_LOCK *lock,
lock->read_no_write_count++;
}
DBUG_PRINT("lock",("giving read lock to thread: %ld",
- data->thread_id));
+ data->owner->info->thread_id));
data->cond=0; /* Mark thread free */
VOID(pthread_cond_signal(cond));
} while ((data=data->next));
@@ -665,7 +739,7 @@ void thr_unlock(THR_LOCK_DATA *data)
enum thr_lock_type lock_type=data->type;
DBUG_ENTER("thr_unlock");
DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx",
- data,data->thread_id,lock));
+ (long) data, data->owner->info->thread_id, (long) lock));
pthread_mutex_lock(&lock->mutex);
check_locks(lock,"start of release lock",0);
@@ -675,14 +749,24 @@ void thr_unlock(THR_LOCK_DATA *data)
lock->read.last=data->prev;
else if (lock_type == TL_WRITE_DELAYED && data->cond)
{
- /* This only happens in extreme circumstances when a
- write delayed lock that is waiting for a lock */
+ /*
+ This only happens in extreme circumstances when a
+ write delayed lock that is waiting for a lock
+ */
lock->write_wait.last=data->prev; /* Put it on wait queue */
}
else
lock->write.last=data->prev;
- if (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock->update_status)
- (*lock->update_status)(data->status_param);
+ if (lock_type >= TL_WRITE_CONCURRENT_INSERT)
+ {
+ if (lock->update_status)
+ (*lock->update_status)(data->status_param);
+ }
+ else
+ {
+ if (lock->restore_status)
+ (*lock->restore_status)(data->status_param);
+ }
if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count--;
data->type=TL_UNLOCK; /* Mark unlocked */
@@ -723,7 +807,7 @@ void thr_unlock(THR_LOCK_DATA *data)
(*lock->check_status)(data->status_param))
data->type=TL_WRITE; /* Upgrade lock */
DBUG_PRINT("lock",("giving write lock of type %d to thread: %ld",
- data->type,data->thread_id));
+ data->type, data->owner->info->thread_id));
{
pthread_cond_t *cond=data->cond;
data->cond=0; /* Mark thread free */
@@ -831,20 +915,22 @@ static void sort_locks(THR_LOCK_DATA **data,uint count)
}
-int thr_multi_lock(THR_LOCK_DATA **data,uint count)
+enum enum_thr_lock_result
+thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_OWNER *owner)
{
THR_LOCK_DATA **pos,**end;
DBUG_ENTER("thr_multi_lock");
- DBUG_PRINT("lock",("data: 0x%lx count: %d",data,count));
+ DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count));
if (count > 1)
sort_locks(data,count);
/* lock everything */
for (pos=data,end=data+count; pos < end ; pos++)
{
- if (thr_lock(*pos,(*pos)->type))
+ enum enum_thr_lock_result result= thr_lock(*pos, owner, (*pos)->type);
+ if (result != THR_LOCK_SUCCESS)
{ /* Aborted */
thr_multi_unlock(data,(uint) (pos-data));
- DBUG_RETURN(1);
+ DBUG_RETURN(result);
}
#ifdef MAIN
printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(),
@@ -898,7 +984,7 @@ int thr_multi_lock(THR_LOCK_DATA **data,uint count)
} while (pos != data);
}
#endif
- DBUG_RETURN(0);
+ DBUG_RETURN(THR_LOCK_SUCCESS);
}
/* free all locks */
@@ -907,7 +993,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
{
THR_LOCK_DATA **pos,**end;
DBUG_ENTER("thr_multi_unlock");
- DBUG_PRINT("lock",("data: 0x%lx count: %d",data,count));
+ DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count));
for (pos=data,end=data+count; pos < end ; pos++)
{
@@ -921,7 +1007,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
else
{
DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: %ld lock: 0x%lx",
- *pos,(*pos)->thread_id,(*pos)->lock));
+ (long) *pos, (*pos)->owner->info->thread_id,
+ (long) (*pos)->lock));
}
}
DBUG_VOID_RETURN;
@@ -941,6 +1028,7 @@ void thr_abort_locks(THR_LOCK *lock)
for (data=lock->read_wait.data; data ; data=data->next)
{
data->type=TL_UNLOCK; /* Mark killed */
+ /* It's safe to signal the cond first: we're still holding the mutex. */
pthread_cond_signal(data->cond);
data->cond=0; /* Removed from list */
}
@@ -975,10 +1063,11 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
pthread_mutex_lock(&lock->mutex);
for (data= lock->read_wait.data; data ; data= data->next)
{
- if (pthread_equal(thread, data->thread))
+ if (pthread_equal(thread, data->owner->info->thread))
{
DBUG_PRINT("info",("Aborting read-wait lock"));
data->type= TL_UNLOCK; /* Mark killed */
+ /* It's safe to signal the cond first: we're still holding the mutex. */
found= TRUE;
pthread_cond_signal(data->cond);
data->cond= 0; /* Removed from list */
@@ -991,7 +1080,7 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
}
for (data= lock->write_wait.data; data ; data= data->next)
{
- if (pthread_equal(thread, data->thread))
+ if (pthread_equal(thread, data->owner->info->thread))
{
DBUG_PRINT("info",("Aborting write-wait lock"));
data->type= TL_UNLOCK;
@@ -1034,7 +1123,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
if (!lock->read.data) /* No read locks */
{ /* We have the lock */
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
pthread_mutex_unlock(&lock->mutex);
DBUG_RETURN(0);
}
@@ -1109,7 +1198,8 @@ static void thr_print_lock(const char* name,struct st_lock_list *list)
prev= &list->data;
for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next)
{
- printf("0x%lx (%lu:%d); ",(ulong) data,data->thread_id,(int) data->type);
+ printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->info->thread_id,
+ (int) data->type);
if (data->prev != prev)
printf("\nWarning: prev didn't point at previous lock\n");
prev= &data->next;
@@ -1223,7 +1313,8 @@ static ulong sum=0;
/* The following functions is for WRITE_CONCURRENT_INSERT */
-static void test_get_status(void* param __attribute__((unused)))
+static void test_get_status(void* param __attribute__((unused)),
+ int concurrent_insert __attribute__((unused)))
{
}
@@ -1242,11 +1333,16 @@ static void *test_thread(void *arg)
{
int i,j,param=*((int*) arg);
THR_LOCK_DATA data[MAX_LOCK_COUNT];
+ THR_LOCK_OWNER owner;
+ THR_LOCK_INFO lock_info;
THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT];
my_thread_init();
printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout);
+
+ thr_lock_info_init(&lock_info);
+ thr_lock_owner_init(&owner, &lock_info);
for (i=0; i < lock_counts[param] ; i++)
thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL);
for (j=1 ; j < 10 ; j++) /* try locking 10 times */
@@ -1256,7 +1352,7 @@ static void *test_thread(void *arg)
multi_locks[i]= &data[i];
data[i].type= tests[param][i].lock_type;
}
- thr_multi_lock(multi_locks,lock_counts[param]);
+ thr_multi_lock(multi_locks, lock_counts[param], &owner);
pthread_mutex_lock(&LOCK_thread_count);
{
int tmp=rand() & 7; /* Do something from 0-2 sec */
diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c
index 2facb4e18cf..425e5fce459 100644
--- a/mysys/thr_mutex.c
+++ b/mysys/thr_mutex.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -103,7 +102,7 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
fflush(stderr);
abort();
}
-
+
pthread_mutex_lock(&mp->global);
if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread))
{
@@ -121,6 +120,7 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
fflush(stderr);
abort();
}
+ mp->thread= pthread_self();
if (mp->count++)
{
fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, \
@@ -128,7 +128,6 @@ line %d more than 1 time\n", file,line);
fflush(stderr);
abort();
}
- mp->thread=pthread_self();
mp->file= file;
mp->line=line;
pthread_mutex_unlock(&mp->global);
@@ -154,6 +153,7 @@ int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line)
fflush(stderr);
abort();
}
+ mp->thread= 0;
mp->count--;
#ifdef __WIN__
pthread_mutex_unlock(&mp->mutex);
@@ -207,6 +207,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file,
fflush(stderr);
abort();
}
+ mp->thread=pthread_self();
if (mp->count++)
{
fprintf(stderr,
@@ -215,7 +216,6 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file,
fflush(stderr);
abort();
}
- mp->thread=pthread_self();
mp->file= file;
mp->line=line;
pthread_mutex_unlock(&mp->global);
@@ -239,12 +239,13 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
pthread_mutex_unlock(&mp->global);
error=pthread_cond_timedwait(cond,&mp->mutex,abstime);
#ifdef EXTRA_DEBUG
- if (error && (error != EINTR && error != ETIMEDOUT))
+ if (error && (error != EINTR && error != ETIMEDOUT && error != ETIME))
{
fprintf(stderr,"safe_mutex: Got error: %d (%d) when doing a safe_mutex_timedwait at %s, line %d\n", error, errno, file, line);
}
#endif
pthread_mutex_lock(&mp->global);
+ mp->thread=pthread_self();
if (mp->count++)
{
fprintf(stderr,
@@ -253,7 +254,6 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
fflush(stderr);
abort();
}
- mp->thread=pthread_self();
mp->file= file;
mp->line=line;
pthread_mutex_unlock(&mp->global);
diff --git a/mysys/thr_rwlock.c b/mysys/thr_rwlock.c
index 29db2b997a0..0aa4d3fc3c4 100644
--- a/mysys/thr_rwlock.c
+++ b/mysys/thr_rwlock.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
diff --git a/mysys/tree.c b/mysys/tree.c
index bec1ec680f1..2e6868e0777 100644
--- a/mysys/tree.c
+++ b/mysys/tree.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -84,12 +83,12 @@ static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent);
static int test_rb_tree(TREE_ELEMENT *element);
#endif
-void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
+void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit,
int size, qsort_cmp2 compare, my_bool with_delete,
tree_element_free free_element, void *custom_arg)
{
DBUG_ENTER("init_tree");
- DBUG_PRINT("enter",("tree: 0x%lx size: %d",tree,size));
+ DBUG_PRINT("enter",("tree: 0x%lx size: %d", (long) tree, size));
if (default_alloc_size < DEFAULT_ALLOC_SIZE)
default_alloc_size= DEFAULT_ALLOC_SIZE;
@@ -128,7 +127,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
}
if (!(tree->with_delete=with_delete))
{
- init_alloc_root(&tree->mem_root, default_alloc_size,0);
+ init_alloc_root(&tree->mem_root, (uint) default_alloc_size, 0);
tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element);
}
DBUG_VOID_RETURN;
@@ -137,7 +136,7 @@ void init_tree(TREE *tree, uint default_alloc_size, uint memory_limit,
static void free_tree(TREE *tree, myf free_flags)
{
DBUG_ENTER("free_tree");
- DBUG_PRINT("enter",("tree: 0x%lx",tree));
+ DBUG_PRINT("enter",("tree: 0x%lx", (long) tree));
if (tree->root) /* If initialized */
{
@@ -263,12 +262,15 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
if (tree->flag & TREE_NO_DUPS)
return(NULL);
element->count++;
+ /* Avoid a wrap over of the count. */
+ if (! element->count)
+ element->count--;
}
DBUG_EXECUTE("check_tree", test_rb_tree(tree->root););
return element;
}
-int tree_delete(TREE *tree, void *key, void *custom_arg)
+int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg)
{
int cmp,remove_colour;
TREE_ELEMENT *element,***parent, ***org_parent, *nod;
@@ -323,8 +325,7 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent);
if (tree->free)
(*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
- /* This doesn't include key_size, but better than nothing */
- tree->allocated-= sizeof(TREE_ELEMENT)+tree->size_of_element;
+ tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size;
my_free((gptr) element,MYF(0));
tree->elements_in_tree--;
return 0;
diff --git a/mysys/typelib.c b/mysys/typelib.c
index 90a093b0b32..4fab6f20493 100644
--- a/mysys/typelib.c
+++ b/mysys/typelib.c
@@ -2,8 +2,7 @@
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; either version 2 of the License, or
- (at your option) any later version.
+ 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
@@ -49,7 +48,7 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name)
reg1 my_string i;
reg2 const char *j;
DBUG_ENTER("find_type");
- DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib));
+ DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib));
if (!typelib->count)
{
@@ -119,3 +118,54 @@ const char *get_type(TYPELIB *typelib, uint nr)
return(typelib->type_names[nr]);
return "?";
}
+
+
+/*
+ Create a copy of a specified TYPELIB structure.
+
+ SYNOPSIS
+ copy_typelib()
+ root pointer to a MEM_ROOT object for allocations
+ from pointer to a source TYPELIB structure
+
+ RETURN
+ pointer to the new TYPELIB structure on successful copy, or
+ NULL otherwise
+*/
+
+TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from)
+{
+ TYPELIB *to;
+ uint i;
+
+ if (!from)
+ return NULL;
+
+ if (!(to= (TYPELIB*) alloc_root(root, sizeof(TYPELIB))))
+ return NULL;
+
+ if (!(to->type_names= (const char **)
+ alloc_root(root, (sizeof(char *) + sizeof(int)) * (from->count + 1))))
+ return NULL;
+ to->type_lengths= (unsigned int *)(to->type_names + from->count + 1);
+ to->count= from->count;
+ if (from->name)
+ {
+ if (!(to->name= strdup_root(root, from->name)))
+ return NULL;
+ }
+ else
+ to->name= NULL;
+
+ for (i= 0; i < from->count; i++)
+ {
+ if (!(to->type_names[i]= strmake_root(root, from->type_names[i],
+ from->type_lengths[i])))
+ return NULL;
+ to->type_lengths[i]= from->type_lengths[i];
+ }
+ to->type_names[to->count]= NULL;
+ to->type_lengths[to->count]= 0;
+
+ return to;
+}