Commit bdb1441a authored by msvensson@neptunus.(none)'s avatar msvensson@neptunus.(none)

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into neptunus.(none):/home/msvensson/mysql/mysql-4.1
parents 49818d6f 1df11005
...@@ -1005,7 +1005,7 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ ...@@ -1005,7 +1005,7 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [
if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then
echo "Could not find an installation of OpenSSL" echo "Could not find an installation of OpenSSL"
if test -n "$OPENSSL_LIB" ; then if test -n "$OPENSSL_LIB" ; then
if test "$IS_LINUX" = "true"; then if test "$TARGET_LINUX" = "true"; then
echo "Looks like you've forgotten to install OpenSSL development RPM" echo "Looks like you've forgotten to install OpenSSL development RPM"
fi fi
fi fi
......
...@@ -410,15 +410,16 @@ AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os") ...@@ -410,15 +410,16 @@ AC_MSG_CHECKING("if we should use 'skip-locking' as default for $target_os")
if expr "$target_os" : "[[Ll]]inux.*" > /dev/null if expr "$target_os" : "[[Ll]]inux.*" > /dev/null
then then
MYSQLD_DEFAULT_SWITCHES="--skip-locking" MYSQLD_DEFAULT_SWITCHES="--skip-locking"
IS_LINUX="true" TARGET_LINUX="true"
AC_MSG_RESULT("yes"); AC_MSG_RESULT("yes")
AC_DEFINE([TARGET_OS_LINUX], [1], [Whether we build for Linux])
else else
MYSQLD_DEFAULT_SWITCHES="" MYSQLD_DEFAULT_SWITCHES=""
IS_LINUX="false" TARGET_LINUX="false"
AC_MSG_RESULT("no"); AC_MSG_RESULT("no")
fi fi
AC_SUBST(MYSQLD_DEFAULT_SWITCHES) AC_SUBST(MYSQLD_DEFAULT_SWITCHES)
AC_SUBST(IS_LINUX) AC_SUBST(TARGET_LINUX)
dnl Find paths to some shell programs dnl Find paths to some shell programs
AC_PATH_PROG(LN, ln, ln) AC_PATH_PROG(LN, ln, ln)
...@@ -607,7 +608,7 @@ AC_SUBST(NOINST_LDFLAGS) ...@@ -607,7 +608,7 @@ AC_SUBST(NOINST_LDFLAGS)
# (this is true on the MySQL build machines to avoid NSS problems) # (this is true on the MySQL build machines to avoid NSS problems)
# #
if test "$IS_LINUX" = "true" -a "$static_nss" = "" if test "$TARGET_LINUX" = "true" -a "$static_nss" = ""
then then
tmp=`nm /usr/lib/libc.a | grep _nss_files_getaliasent_r` tmp=`nm /usr/lib/libc.a | grep _nss_files_getaliasent_r`
if test -n "$tmp" if test -n "$tmp"
...@@ -841,7 +842,7 @@ struct request_info *req; ...@@ -841,7 +842,7 @@ struct request_info *req;
]) ])
AC_SUBST(WRAPLIBS) AC_SUBST(WRAPLIBS)
if test "$IS_LINUX" = "true"; then if test "$TARGET_LINUX" = "true"; then
AC_MSG_CHECKING([for atomic operations]) AC_MSG_CHECKING([for atomic operations])
atom_ops= atom_ops=
...@@ -885,7 +886,7 @@ int main() ...@@ -885,7 +886,7 @@ int main()
[ USE_PSTACK=no ]) [ USE_PSTACK=no ])
pstack_libs= pstack_libs=
pstack_dirs= pstack_dirs=
if test "$USE_PSTACK" = yes -a "$IS_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no" if test "$USE_PSTACK" = yes -a "$TARGET_LINUX" = "true" -a "$BASE_MACHINE_TYPE" = "i386" -a "$with_mit_threads" = "no"
then then
have_libiberty= have_libbfd= have_libiberty= have_libbfd=
my_save_LIBS="$LIBS" my_save_LIBS="$LIBS"
...@@ -1266,11 +1267,36 @@ esac ...@@ -1266,11 +1267,36 @@ esac
# We have to check libc last because else it fails on Solaris 2.6 # We have to check libc last because else it fails on Solaris 2.6
with_posix_threads="no" with_posix_threads="no"
# Hack for DEC-UNIX (OSF1) # Search thread lib on Linux
if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no" if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
then then
AC_MSG_CHECKING("Linux threads")
if test "$TARGET_LINUX" = "true"
then
AC_MSG_RESULT("starting")
# use getconf to check glibc contents
AC_MSG_CHECKING("getconf GNU_LIBPTHREAD_VERSION")
case `getconf GNU_LIBPTHREAD_VERSION | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` in
NPTL* )
AC_MSG_RESULT("NPTL")
AC_DEFINE([HAVE_NPTL], [1], [NPTL threads implementation])
with_named_thread="-lpthread"
;;
LINUXTHREADS* )
AC_MSG_RESULT("Linuxthreads")
AC_DEFINE([HAVE_LINUXTHREADS], [1],
[Whether we are using Xavier Leroy's LinuxThreads])
with_named_thread="-lpthread"
;;
* )
AC_MSG_RESULT("unknown")
;;
esac
if test "$with_named_thread" = "no"
then
# old method, check headers
# Look for LinuxThreads. # Look for LinuxThreads.
AC_MSG_CHECKING("LinuxThreads") AC_MSG_CHECKING("LinuxThreads in header file comment")
res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l` res=`grep Linuxthreads /usr/include/pthread.h 2>/dev/null | wc -l`
if test "$res" -gt 0 if test "$res" -gt 0
then then
...@@ -1286,41 +1312,48 @@ then ...@@ -1286,41 +1312,48 @@ then
else else
AC_MSG_RESULT("Not found") AC_MSG_RESULT("Not found")
# If this is a linux machine we should barf # If this is a linux machine we should barf
if test "$IS_LINUX" = "true" AC_MSG_ERROR([This is a Linux system without a working getconf,
then and Linuxthreads was not found. Please install it (or a new glibc) and try again.
AC_MSG_ERROR([This is a linux system and Linuxthreads was not See the Installation chapter in the Reference Manual for more information.])
found. On linux Linuxthreads should be used. Please install Linuxthreads fi
(or a new glibc) and try again. See the Installation chapter in the else
Reference Manual for more information.]) AC_MSG_RESULT("no need to check headers")
fi
AC_MSG_CHECKING("for pthread_create in -lpthread");
ac_save_LIBS="$LIBS"
LIBS="$LIBS -lpthread"
AC_TRY_LINK( [#include <pthread.h>],
[ (void) pthread_create((pthread_t*) 0,(pthread_attr_t*) 0, 0, 0); ],
AC_MSG_RESULT("yes"),
[ AC_MSG_RESULT("no")
AC_MSG_ERROR([
This is a Linux system claiming to support threads, either Linuxthreads or NPTL, but linking a test program failed.
Please install one of these (or a new glibc) and try again.
See the Installation chapter in the Reference Manual for more information.]) ]
)
LIBS="$ac_save_LIBS"
else else
AC_MSG_CHECKING("DEC threads") AC_MSG_RESULT("no")
fi # "$TARGET_LINUX"
fi # "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
# Hack for DEC-UNIX (OSF1 -> Tru64)
if test "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
then
AC_MSG_CHECKING("DEC threads post OSF/1 3.2")
if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a if test -f /usr/shlib/libpthread.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a
then then
with_named_thread="-lpthread -lmach -lexc" with_named_thread="-lpthread -lmach -lexc"
CFLAGS="$CFLAGS -D_REENTRANT" CFLAGS="$CFLAGS -D_REENTRANT"
CXXFLAGS="$CXXFLAGS -D_REENTRANT" CXXFLAGS="$CXXFLAGS -D_REENTRANT"
AC_DEFINE(HAVE_DEC_THREADS, [1], AC_DEFINE(HAVE_DEC_THREADS, [1], [Whether we are using DEC threads])
[Whether we are using DEC threads])
AC_MSG_RESULT("yes") AC_MSG_RESULT("yes")
else else
AC_MSG_RESULT("no") AC_MSG_RESULT("no")
AC_MSG_CHECKING("DEC 3.2 threads") fi # DEC threads
if test -f /usr/shlib/libpthreads.so -a -f /usr/lib/libmach.a -a -f /usr/ccs/lib/cmplrs/cc/libexc.a fi # "$with_named_thread" = "no" -a "$with_mit_threads" = "no"
then
with_named_thread="-lpthreads -lmach -lc_r"
AC_DEFINE(HAVE_DEC_THREADS, [1])
AC_DEFINE([HAVE_DEC_3_2_THREADS], [1],
[Whether we are using OSF1 DEC threads on 3.2])
with_osf32_threads="yes"
MYSQLD_DEFAULT_SWITCHES="--skip-thread-priority"
AC_MSG_RESULT("yes")
else
AC_MSG_RESULT("no")
fi
fi
fi
fi
fi
dnl This is needed because -lsocket has to come after the thread dnl This is needed because -lsocket has to come after the thread
...@@ -1738,7 +1771,7 @@ fi ...@@ -1738,7 +1771,7 @@ fi
AC_SUBST(COMPILATION_COMMENT) AC_SUBST(COMPILATION_COMMENT)
AC_MSG_CHECKING("need of special linking flags") AC_MSG_CHECKING("need of special linking flags")
if test "$IS_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes" if test "$TARGET_LINUX" = "true" -a "$ac_cv_prog_gcc" = "yes" -a "$all_is_static" != "yes"
then then
LDFLAGS="$LDFLAGS -rdynamic" LDFLAGS="$LDFLAGS -rdynamic"
AC_MSG_RESULT("-rdynamic") AC_MSG_RESULT("-rdynamic")
...@@ -1957,7 +1990,7 @@ CFLAGS="$ORG_CFLAGS" ...@@ -1957,7 +1990,7 @@ CFLAGS="$ORG_CFLAGS"
# Sanity check: We chould not have any fseeko symbol unless # Sanity check: We chould not have any fseeko symbol unless
# large_file_support=yes # large_file_support=yes
AC_CHECK_FUNC(fseeko, AC_CHECK_FUNC(fseeko,
[if test "$large_file_support" = no -a "$IS_LINUX" = "true"; [if test "$large_file_support" = no -a "$TARGET_LINUX" = "true";
then then
AC_MSG_ERROR("Found fseeko symbol but large_file_support is not enabled!"); AC_MSG_ERROR("Found fseeko symbol but large_file_support is not enabled!");
fi] fi]
......
...@@ -97,7 +97,7 @@ ...@@ -97,7 +97,7 @@
/* Fix problem with S_ISLNK() on Linux */ /* Fix problem with S_ISLNK() on Linux */
#if defined(HAVE_LINUXTHREADS) #if defined(TARGET_OS_LINUX)
#undef _GNU_SOURCE #undef _GNU_SOURCE
#define _GNU_SOURCE 1 #define _GNU_SOURCE 1
#endif #endif
...@@ -107,6 +107,7 @@ ...@@ -107,6 +107,7 @@
#undef THREAD #undef THREAD
#undef HAVE_mit_thread #undef HAVE_mit_thread
#undef HAVE_LINUXTHREADS #undef HAVE_LINUXTHREADS
#undef HAVE_NPTL
#undef HAVE_UNIXWARE7_THREADS #undef HAVE_UNIXWARE7_THREADS
#endif #endif
...@@ -214,13 +215,13 @@ C_MODE_START int __cxa_pure_virtual() {\ ...@@ -214,13 +215,13 @@ C_MODE_START int __cxa_pure_virtual() {\
#endif #endif
/* In Linux-alpha we have atomic.h if we are using gcc */ /* In Linux-alpha we have atomic.h if we are using gcc */
#if defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD) #if defined(TARGET_OS_LINUX) && defined(__GNUC__) && defined(__alpha__) && (__GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 95)) && !defined(HAVE_ATOMIC_ADD)
#define HAVE_ATOMIC_ADD #define HAVE_ATOMIC_ADD
#define HAVE_ATOMIC_SUB #define HAVE_ATOMIC_SUB
#endif #endif
/* In Linux-ia64 including atomic.h will give us an error */ /* In Linux-ia64 including atomic.h will give us an error */
#if (defined(HAVE_LINUXTHREADS) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD) #if (defined(TARGET_OS_LINUX) && defined(__GNUC__) && (defined(__ia64__)||defined(__powerpc64__))) || !defined(THREAD)
#undef HAVE_ATOMIC_ADD #undef HAVE_ATOMIC_ADD
#undef HAVE_ATOMIC_SUB #undef HAVE_ATOMIC_SUB
#endif #endif
...@@ -755,7 +756,7 @@ typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */ ...@@ -755,7 +756,7 @@ typedef unsigned long uint32; /* Short for unsigned integer >= 32 bits */
error "Neither int or long is of 4 bytes width" error "Neither int or long is of 4 bytes width"
#endif #endif
#if !defined(HAVE_ULONG) && !defined(HAVE_LINUXTHREADS) && !defined(__USE_MISC) #if !defined(HAVE_ULONG) && !defined(TARGET_OS_LINUX) && !defined(__USE_MISC)
typedef unsigned long ulong; /* Short for unsigned long */ typedef unsigned long ulong; /* Short for unsigned long */
#endif #endif
#ifndef longlong_defined #ifndef longlong_defined
......
...@@ -88,7 +88,7 @@ SUFFIXES = .sh ...@@ -88,7 +88,7 @@ SUFFIXES = .sh
-e 's!@''FIND_PROC''@!@FIND_PROC@!' \ -e 's!@''FIND_PROC''@!@FIND_PROC@!' \
-e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \
-e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \
-e 's!@''IS_LINUX''@!@IS_LINUX@!' \ -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \
-e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \
-e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
-e 's!@''sysconfdir''@!@sysconfdir@!' \ -e 's!@''sysconfdir''@!@sysconfdir@!' \
......
drop table if exists t1;
select floor(5.5),floor(-5.5); select floor(5.5),floor(-5.5);
floor(5.5) floor(-5.5) floor(5.5) floor(-5.5)
5 -6 5 -6
...@@ -126,3 +127,13 @@ Warnings: ...@@ -126,3 +127,13 @@ Warnings:
Note 1003 select degrees(pi()) AS `degrees(pi())`,radians(360) AS `radians(360)` Note 1003 select degrees(pi()) AS `degrees(pi())`,radians(360) AS `radians(360)`
select rand(rand); select rand(rand);
ERROR 42S22: Unknown column 'rand' in 'field list' ERROR 42S22: Unknown column 'rand' in 'field list'
create table t1 select round(1, 6);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`round(1, 6)` double(7,6) NOT NULL default '0.000000'
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1;
round(1, 6)
1.000000
drop table t1;
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
# Test of math functions # Test of math functions
# #
--disable_warnings
drop table if exists t1;
--enable_warnings
select floor(5.5),floor(-5.5); select floor(5.5),floor(-5.5);
explain extended select floor(5.5),floor(-5.5); explain extended select floor(5.5),floor(-5.5);
select ceiling(5.5),ceiling(-5.5); select ceiling(5.5),ceiling(-5.5);
...@@ -58,3 +62,12 @@ explain extended select degrees(pi()),radians(360); ...@@ -58,3 +62,12 @@ explain extended select degrees(pi()),radians(360);
--error 1054 --error 1054
select rand(rand); select rand(rand);
#
# Bug #9837: problem with round()
#
create table t1 select round(1, 6);
show create table t1;
select * from t1;
drop table t1;
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/* This makes a wrapper for mutex handling to make it easier to debug mutex */ /* This makes a wrapper for mutex handling to make it easier to debug mutex */
#include <my_global.h> #include <my_global.h>
#if defined(HAVE_LINUXTHREADS) && !defined (__USE_UNIX98) #if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98)
#define __USE_UNIX98 /* To get rw locks under Linux */ #define __USE_UNIX98 /* To get rw locks under Linux */
#endif #endif
#if defined(THREAD) && defined(SAFE_MUTEX) #if defined(THREAD) && defined(SAFE_MUTEX)
......
...@@ -135,7 +135,7 @@ SUFFIXES = .sh ...@@ -135,7 +135,7 @@ SUFFIXES = .sh
-e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \
-e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \
-e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \
-e 's!@''IS_LINUX''@!@IS_LINUX@!' \ -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \
-e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \
-e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
-e 's!@''STATIC_NSS_FLAGS''@!@STATIC_NSS_FLAGS@!' \ -e 's!@''STATIC_NSS_FLAGS''@!@STATIC_NSS_FLAGS@!' \
......
...@@ -324,7 +324,7 @@ do ...@@ -324,7 +324,7 @@ do
break break
fi fi
if @IS_LINUX@ && test $KILL_MYSQLD -eq 1 if @TARGET_LINUX@ && test $KILL_MYSQLD -eq 1
then then
# Test if one process was hanging. # Test if one process was hanging.
# This is only a fix for Linux (running as base 3 mysqld processes) # This is only a fix for Linux (running as base 3 mysqld processes)
......
...@@ -1072,6 +1072,8 @@ void Item_func_round::fix_length_and_dec() ...@@ -1072,6 +1072,8 @@ void Item_func_round::fix_length_and_dec()
decimals=0; decimals=0;
else else
decimals=min(tmp,NOT_FIXED_DEC); decimals=min(tmp,NOT_FIXED_DEC);
if ((tmp= decimals - args[0]->decimals) > 0)
max_length+= tmp;
} }
} }
......
...@@ -82,7 +82,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count); ...@@ -82,7 +82,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count);
static void print_lock_error(int error); static void print_lock_error(int error);
MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count,
bool ignore_global_read_lock)
{ {
MYSQL_LOCK *sql_lock; MYSQL_LOCK *sql_lock;
TABLE *write_lock_used; TABLE *write_lock_used;
...@@ -93,7 +94,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) ...@@ -93,7 +94,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count)
if (!(sql_lock = get_lock_data(thd,tables,count, 0,&write_lock_used))) if (!(sql_lock = get_lock_data(thd,tables,count, 0,&write_lock_used)))
break; break;
if (global_read_lock && write_lock_used) if (global_read_lock && write_lock_used && ! ignore_global_read_lock)
{ {
/* /*
Someone has issued LOCK ALL TABLES FOR READ and we want a write lock Someone has issued LOCK ALL TABLES FOR READ and we want a write lock
...@@ -911,3 +912,49 @@ void make_global_read_lock_block_commit(THD *thd) ...@@ -911,3 +912,49 @@ void make_global_read_lock_block_commit(THD *thd)
pthread_mutex_unlock(&LOCK_open); pthread_mutex_unlock(&LOCK_open);
thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT; thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
} }
/*
Set protection against global read lock.
SYNOPSIS
set_protect_against_global_read_lock()
void
RETURN
FALSE OK, no global read lock exists.
TRUE Error, global read lock exists already.
*/
my_bool set_protect_against_global_read_lock(void)
{
my_bool global_read_lock_exists;
pthread_mutex_lock(&LOCK_open);
if (! (global_read_lock_exists= test(global_read_lock)))
protect_against_global_read_lock++;
pthread_mutex_unlock(&LOCK_open);
return global_read_lock_exists;
}
/*
Unset protection against global read lock.
SYNOPSIS
unset_protect_against_global_read_lock()
void
RETURN
void
*/
void unset_protect_against_global_read_lock(void)
{
pthread_mutex_lock(&LOCK_open);
protect_against_global_read_lock--;
pthread_mutex_unlock(&LOCK_open);
pthread_cond_broadcast(&COND_refresh);
}
...@@ -975,7 +975,8 @@ extern pthread_t signal_thread; ...@@ -975,7 +975,8 @@ extern pthread_t signal_thread;
extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd; extern struct st_VioSSLAcceptorFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **table,uint count); MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **table, uint count,
bool ignore_global_read_lock= FALSE);
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock); void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock);
void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count);
...@@ -988,6 +989,8 @@ void unlock_global_read_lock(THD *thd); ...@@ -988,6 +989,8 @@ void unlock_global_read_lock(THD *thd);
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit); bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit);
void start_waiting_global_read_lock(THD *thd); void start_waiting_global_read_lock(THD *thd);
void make_global_read_lock_block_commit(THD *thd); void make_global_read_lock_block_commit(THD *thd);
my_bool set_protect_against_global_read_lock(void);
void unset_protect_against_global_read_lock(void);
/* Lock based on name */ /* Lock based on name */
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list); int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
......
...@@ -851,27 +851,42 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -851,27 +851,42 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
{ {
int error; int error;
delayed_insert *tmp; delayed_insert *tmp;
TABLE *table;
DBUG_ENTER("delayed_get_table"); DBUG_ENTER("delayed_get_table");
if (!table_list->db) if (!table_list->db)
table_list->db=thd->db; table_list->db=thd->db;
/* no match; create a new thread to handle the table */ /* Find the thread which handles this table. */
if (!(tmp=find_handler(thd,table_list))) if (!(tmp=find_handler(thd,table_list)))
{ {
/* Don't create more than max_insert_delayed_threads */ /*
No match. Create a new thread to handle the table, but
no more than max_insert_delayed_threads.
*/
if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads)
DBUG_RETURN(0); DBUG_RETURN(0);
thd->proc_info="Creating delayed handler"; thd->proc_info="Creating delayed handler";
pthread_mutex_lock(&LOCK_delayed_create); pthread_mutex_lock(&LOCK_delayed_create);
if (!(tmp=find_handler(thd,table_list))) // Was just created /*
The first search above was done without LOCK_delayed_create.
Another thread might have created the handler in between. Search again.
*/
if (! (tmp= find_handler(thd, table_list)))
{ {
/*
Avoid that a global read lock steps in while we are creating the
new thread. It would block trying to open the table. Hence, the
DI thread and this thread would wait until after the global
readlock is gone. If the read lock exists already, we leave with
no table and then switch to non-delayed insert.
*/
if (set_protect_against_global_read_lock())
goto err;
if (!(tmp=new delayed_insert())) if (!(tmp=new delayed_insert()))
{ {
thd->fatal_error();
my_error(ER_OUTOFMEMORY,MYF(0),sizeof(delayed_insert)); my_error(ER_OUTOFMEMORY,MYF(0),sizeof(delayed_insert));
pthread_mutex_unlock(&LOCK_delayed_create); goto err1;
DBUG_RETURN(0);
} }
pthread_mutex_lock(&LOCK_thread_count); pthread_mutex_lock(&LOCK_thread_count);
thread_count++; thread_count++;
...@@ -880,10 +895,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -880,10 +895,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
!(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME)))) !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_WME))))
{ {
delete tmp; delete tmp;
thd->fatal_error();
my_error(ER_OUT_OF_RESOURCES,MYF(0)); my_error(ER_OUT_OF_RESOURCES,MYF(0));
pthread_mutex_unlock(&LOCK_delayed_create); goto err1;
DBUG_RETURN(0);
} }
tmp->table_list= *table_list; // Needed to open table tmp->table_list= *table_list; // Needed to open table
tmp->table_list.db= tmp->thd.db; tmp->table_list.db= tmp->thd.db;
...@@ -899,10 +912,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -899,10 +912,8 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
pthread_mutex_unlock(&tmp->mutex); pthread_mutex_unlock(&tmp->mutex);
tmp->unlock(); tmp->unlock();
delete tmp; delete tmp;
thd->fatal_error();
pthread_mutex_unlock(&LOCK_delayed_create);
net_printf(thd,ER_CANT_CREATE_THREAD,error); net_printf(thd,ER_CANT_CREATE_THREAD,error);
DBUG_RETURN(0); goto err1;
} }
/* Wait until table is open */ /* Wait until table is open */
...@@ -912,6 +923,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -912,6 +923,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
pthread_cond_wait(&tmp->cond_client,&tmp->mutex); pthread_cond_wait(&tmp->cond_client,&tmp->mutex);
} }
pthread_mutex_unlock(&tmp->mutex); pthread_mutex_unlock(&tmp->mutex);
unset_protect_against_global_read_lock();
thd->proc_info="got old table"; thd->proc_info="got old table";
if (tmp->thd.killed) if (tmp->thd.killed)
{ {
...@@ -923,28 +935,34 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list) ...@@ -923,28 +935,34 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
thd->net.last_errno=tmp->thd.net.last_errno; thd->net.last_errno=tmp->thd.net.last_errno;
} }
tmp->unlock(); tmp->unlock();
pthread_mutex_unlock(&LOCK_delayed_create); goto err;
DBUG_RETURN(0); // Continue with normal insert
} }
if (thd->killed) if (thd->killed)
{ {
tmp->unlock(); tmp->unlock();
pthread_mutex_unlock(&LOCK_delayed_create); goto err;
DBUG_RETURN(0);
} }
} }
pthread_mutex_unlock(&LOCK_delayed_create); pthread_mutex_unlock(&LOCK_delayed_create);
} }
pthread_mutex_lock(&tmp->mutex); pthread_mutex_lock(&tmp->mutex);
TABLE *table=tmp->get_local_table(thd); table=tmp->get_local_table(thd);
pthread_mutex_unlock(&tmp->mutex); pthread_mutex_unlock(&tmp->mutex);
tmp->unlock();
if (table) if (table)
thd->di=tmp; thd->di=tmp;
else if (tmp->thd.is_fatal_error) else if (tmp->thd.is_fatal_error)
thd->fatal_error(); thd->fatal_error();
/* Unlock the delayed insert object after its last access. */
tmp->unlock();
DBUG_RETURN((table_list->table=table)); DBUG_RETURN((table_list->table=table));
err1:
thd->fatal_error();
unset_protect_against_global_read_lock();
err:
pthread_mutex_unlock(&LOCK_delayed_create);
DBUG_RETURN(0); // Continue with normal insert
} }
...@@ -1165,6 +1183,14 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) ...@@ -1165,6 +1183,14 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
thd->killed=abort_loop; thd->killed=abort_loop;
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
/*
Wait until the client runs into pthread_cond_wait(),
where we free it after the table is opened and di linked in the list.
If we did not wait here, the client might detect the opened table
before it is linked to the list. It would release LOCK_delayed_create
and allow another thread to create another handler for the same table,
since it does not find one in the list.
*/
pthread_mutex_lock(&di->mutex); pthread_mutex_lock(&di->mutex);
#if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */ #if !defined( __WIN__) && !defined(OS2) /* Win32 calls this in pthread_create */
if (my_thread_init()) if (my_thread_init())
...@@ -1279,8 +1305,17 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg) ...@@ -1279,8 +1305,17 @@ extern "C" pthread_handler_decl(handle_delayed_insert,arg)
if (di->tables_in_use && ! thd->lock) if (di->tables_in_use && ! thd->lock)
{ {
/* request for new delayed insert */ /*
if (!(thd->lock=mysql_lock_tables(thd,&di->table,1))) Request for new delayed insert.
Lock the table, but avoid to be blocked by a global read lock.
If we got here while a global read lock exists, then one or more
inserts started before the lock was requested. These are allowed
to complete their work before the server returns control to the
client which requested the global read lock. The delayed insert
handler will close the table and finish when the outstanding
inserts are done.
*/
if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, TRUE)))
{ {
di->dead= 1; // Some fatal error di->dead= 1; // Some fatal error
thd->killed= 1; thd->killed= 1;
......
...@@ -43,7 +43,7 @@ void safe_print_str(const char* name, const char* val, int max_len) ...@@ -43,7 +43,7 @@ void safe_print_str(const char* name, const char* val, int max_len)
fputc('\n', stderr); fputc('\n', stderr);
} }
#ifdef HAVE_LINUXTHREADS #ifdef TARGET_OS_LINUX
#define SIGRETURN_FRAME_COUNT 2 #define SIGRETURN_FRAME_COUNT 2
#if defined(__alpha__) && defined(__GNUC__) #if defined(__alpha__) && defined(__GNUC__)
...@@ -201,7 +201,7 @@ end: ...@@ -201,7 +201,7 @@ end:
stack trace is much more helpful in diagnosing the problem, so please do \n\ stack trace is much more helpful in diagnosing the problem, so please do \n\
resolve it\n"); resolve it\n");
} }
#endif /* HAVE_LINUXTHREADS */ #endif /* TARGET_OS_LINUX */
#endif /* HAVE_STACKTRACE */ #endif /* HAVE_STACKTRACE */
/* Produce a core for the thread */ /* Produce a core for the thread */
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
extern "C" { extern "C" {
#endif #endif
#ifdef HAVE_LINUXTHREADS #ifdef TARGET_OS_LINUX
#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__)))
#undef HAVE_STACKTRACE #undef HAVE_STACKTRACE
#define HAVE_STACKTRACE #define HAVE_STACKTRACE
...@@ -30,7 +30,7 @@ extern char* heap_start; ...@@ -30,7 +30,7 @@ extern char* heap_start;
void print_stacktrace(gptr stack_bottom, ulong thread_stack); void print_stacktrace(gptr stack_bottom, ulong thread_stack);
void safe_print_str(const char* name, const char* val, int max_len); void safe_print_str(const char* name, const char* val, int max_len);
#endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */
#endif /* HAVE_LINUXTHREADS */ #endif /* TARGET_OS_LINUX */
/* Define empty prototypes for functions that are not implemented */ /* Define empty prototypes for functions that are not implemented */
#ifndef HAVE_STACKTRACE #ifndef HAVE_STACKTRACE
......
...@@ -90,7 +90,7 @@ SUFFIXES = .sh ...@@ -90,7 +90,7 @@ SUFFIXES = .sh
-e 's!@''FIND_PROC''@!@FIND_PROC@!' \ -e 's!@''FIND_PROC''@!@FIND_PROC@!' \
-e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \ -e 's!@''MYSQLD_DEFAULT_SWITCHES''@!@MYSQLD_DEFAULT_SWITCHES@!' \
-e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \ -e 's!@''MYSQL_UNIX_ADDR''@!@MYSQL_UNIX_ADDR@!' \
-e 's!@''IS_LINUX''@!@IS_LINUX@!' \ -e 's!@''TARGET_LINUX''@!@TARGET_LINUX@!' \
-e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \ -e "s!@""CONF_COMMAND""@!@CONF_COMMAND@!" \
-e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \ -e 's!@''MYSQLD_USER''@!@MYSQLD_USER@!' \
-e 's!@''sysconfdir''@!@sysconfdir@!' \ -e 's!@''sysconfdir''@!@sysconfdir@!' \
......
...@@ -101,7 +101,7 @@ static CHARSET_INFO *cs= &my_charset_latin1; ...@@ -101,7 +101,7 @@ static CHARSET_INFO *cs= &my_charset_latin1;
set by the user set by the user
*/ */
#if defined(__i386__) && defined(HAVE_LINUXTHREADS) #if defined(__i386__) && defined(TARGET_OS_LINUX)
#define DO_STACKTRACE 1 #define DO_STACKTRACE 1
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment