List:Commits« Previous MessageNext Message »
From:monty Date:February 21 2007 3:12pm
Subject:bk commit into 5.1 tree (monty:1.2436)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of monty. When monty does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-02-21 16:12:01+02:00, monty@stripped +64 -0
  Move all connection handling and command exectuion main loop from sql_parse.cc to
sql_connection.cc
  Split handle_one_connection() into reusable sub functions.
  Split create_new_thread() into reusable sub functions.
  Added thread_scheduler; Preliminary interface code for future thread_handling code.
  
  Use 'my_thread_id' for internal thread id's
  Make thr_alarm_kill() to depend on thread_id instead of thread
  Make thr_abort_locks_for_thread() depend on thread_id instead of thread
  In store_globals(), set my_thread_var->id to be thd->thread_id.
  Use my_thread_var->id as basis for my_thread_name()
  The above changes makes the connection we have between THD and threads more soft.
  
  Added a lot of DBUG_PRINT() and DBUG_ASSERT() functions
  Fixed compiler warnings
  Fixed core dumps when running with --debug
  Removed setting of signal masks (was never used)
  Made event code call pthread_exit() (portability fix)
  Fixed that event code doesn't call DBUG_xxx functions before my_thread_init() is called.
  Made handling of thread_id and thd->variables.pseudo_thread_id uniform.
  Removed one common 'not freed memory' warning from mysqltest

  BUILD/compile-solaris-sparc@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +12 -5
    Update scripts

  BUILD/compile-solaris-sparc-debug@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +9 -5
    Update scripts

  BUILD/compile-solaris-sparc-forte@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +7 -7
    Update scripts

  BUILD/compile-solaris-sparc-purify@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +5
-5
    Update scripts

  BitKeeper/deleted/.del-SETUP.sh.rej@stripped, 2007-02-20 21:00:25+02:00, monty@stripped +0
-0
    Delete: BUILD/SETUP.sh.rej

  BitKeeper/deleted/.del-configure.in.rej@stripped, 2007-02-20 20:29:12+02:00, monty@stripped
+0 -0
    Delete: configure.in.rej

  BitKeeper/deleted/.del-my_global.h.rej@stripped, 2007-02-20 20:51:59+02:00, monty@stripped
+0 -0
    Delete: include/my_global.h.rej

  BitKeeper/deleted/.del-my_pthread.h.rej@stripped, 2007-02-20 20:54:52+02:00, monty@stripped
+0 -0
    Delete: include/my_pthread.h.rej

  BitKeeper/deleted/.del-mysql_client_test.c.rej@stripped, 2007-02-20 21:01:38+02:00,
monty@stripped +0 -0
    Delete: tests/mysql_client_test.c.rej

  BitKeeper/deleted/.del-mysqld.cc.rej~35c1c438e11ebd89@stripped, 2007-02-21 00:43:18+02:00,
monty@stripped +0 -0
    Delete: sql/mysqld.cc.rej

  BitKeeper/deleted/.del-sql_parse.cc.rej@stripped, 2007-02-21 00:43:24+02:00, monty@stripped
+0 -0
    Delete: sql/sql_parse.cc.rej

  BitKeeper/deleted/.del-table.cc.rej@stripped, 2007-02-21 00:43:42+02:00, monty@stripped +0
-0
    Delete: sql/table.cc.rej

  BitKeeper/deleted/.del-thr_alarm.c.rej@stripped, 2007-02-20 20:45:10+02:00, monty@stripped
+0 -0
    Delete: mysys/thr_alarm.c.rej

  client/mysqltest.c@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +16 -14
    Free warning and query memory no abort.
    (Removes strange warnings on screen if mysql-test-run fails)

  client/sql_string.h@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +0 -2
    Removed compiler warning

  configure.in@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +4 -4
    Added detection of port_create and port.h (for future)

  extra/yassl/src/ssl.cpp@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +4 -0
    Detect wrong parameter (Happens when running test suite on solaris)

  include/config-win.h@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +1 -0
    Added HAVE_WINSOCK2 (for future)

  include/my_pthread.h@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +5 -4
    Added my_thread_id typedef
    Renamed 'my_thread_id() function to my_thead_dbug_id()

  include/thr_alarm.h@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +2 -1
    Make thr_alarm_kill() to depend on thread_id instead of thread

  include/thr_lock.h@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +2 -2
    Make thr_abort_locks_for_thread() depend on thread_id instead of thread

  libmysqld/Makefile.am@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +2 -1
    Added new files

  libmysqld/lib_sql.cc@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +1 -9
    Remove not needed code (store_globals() now takes care of things)

  libmysqld/scheduler.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0
    New BitKeeper file ``libmysqld/scheduler.cc''

  libmysqld/scheduler.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  libmysqld/sql_connect.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0
    New BitKeeper file ``libmysqld/sql_connect.cc''

  libmysqld/sql_connect.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  mysql-test/include/one_thread_per_connection.inc@stripped, 2007-02-21 16:11:57+02:00,
monty@stripped +5 -0
    New BitKeeper file ``mysql-test/include/one_thread_per_connection.inc''

  mysql-test/include/one_thread_per_connection.inc@stripped, 2007-02-21 16:11:57+02:00,
monty@stripped +0 -0

  mysql-test/mysql-test-run.pl@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +1 -1
    Fixed typo that caused mysql-test-run.pl to fail on Solaris

  mysql-test/r/no-threads.result@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +6 -0
    New BitKeeper file ``mysql-test/r/no-threads.result''

  mysql-test/r/no-threads.result@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  mysql-test/r/one_thread_per_connection.require@stripped, 2007-02-21 16:11:57+02:00,
monty@stripped +2 -0
    New BitKeeper file ``mysql-test/r/one_thread_per_connection.require''

  mysql-test/r/one_thread_per_connection.require@stripped, 2007-02-21 16:11:57+02:00,
monty@stripped +0 -0

  mysql-test/t/no-threads-master.opt@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +1 -0
    New BitKeeper file ``mysql-test/t/no-threads-master.opt''

  mysql-test/t/no-threads-master.opt@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  mysql-test/t/no-threads.test@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +5 -0
    New BitKeeper file ``mysql-test/t/no-threads.test''

  mysql-test/t/no-threads.test@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  mysql-test/t/wait_timeout.test@stripped, 2007-02-21 16:11:55+02:00, monty@stripped +1 -0
    Don't run this if we are not using a thread per connection (as other thread_handling
code may not support timeouts)

  mysys/my_getopt.c@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +1 -1
    Fixed compiler warning

  mysys/my_init.c@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +9 -7
    Re-indented long comment

  mysys/my_thr_init.c@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +42 -39
    Always use mysys_var->id to generate thread name (makes things uniform accross
thread implementations and thread usage)
    Always generate my_thread_name() when using DBUG
    Ensure mysys_var->pthread_self is set
    Fixed compiler warnings

  mysys/thr_alarm.c@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +5 -4
    Change thr_alarm_kill() to use mysys_var->id instead of thread id

  mysys/thr_lock.c@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +19 -8
    Change thr_abort_locks_for_thread() to use mysys_var->id instead of thread id
    Add purecov statements around not tested code
    Fixed compiler warnings
    

  mysys/thr_mutex.c@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +2 -2
    my_thread_id() -> my_thread_dbug_id()

  server-tools/instance-manager/guardian.cc@stripped, 2007-02-21 16:11:56+02:00,
monty@stripped +2 -2
    Fixed compiler warning

  sql/Makefile.am@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +6 -4
    Added new files

  sql/event_scheduler.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +17 -18
    Added pthread_exit() calls
    Ensure DBUG_xxx calls are not made before my_thread_init()
    Use common functions to set up thread handling

  sql/handler.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +3 -3
    Avoid warnings on KILL_CONNECTION
    Don't print out null pointer with printf()  (Causes crashes on Solaris)

  sql/item_func.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +3 -13
    Merge embedded and normal code usage
    (GET_LOCK, RELEASE_LOCK now works on my_thread_id instead of pthread_t)

  sql/lock.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +1 -1
    Use (new) parameter to thr_abort_locks_for_thread()

  sql/mysql_priv.h@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +27 -5
    Remove TEST_NO_THREADS (not needed with new scheduler interface)
    Added functions from sql_connect.cc and new functions from sql_parse.cc
    

  sql/mysqld.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +216 -106
    Use thread_scheduler structure to dispatch calls (make code more dynamic)
    Change --one-thread option to use thread_scheduler interface
    Made ONE_THREAD option independent of DBUG_BUILD
    --one-thread is now depricated. One should instead use '--thread-handling=no-threads'
    Remove not used uname() function.
    Split create_new_thread() into reusable sub functions.
    Preliminary interface code for future thread_handling code.
    

  sql/parse_file.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +1 -1
    Don't send zero pointer to fn_format() (Causes crashes when using --debug)

  sql/repl_failsafe.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +4 -8
    Setup pseudo_thread_id same way as other code

  sql/scheduler.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +88 -0
    New BitKeeper file ``sql/scheduler.cc''

  sql/scheduler.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  sql/scheduler.h@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +60 -0
    New BitKeeper file ``sql/scheduler.h''

  sql/scheduler.h@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  sql/set_var.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +12 -0
    Added variables 'thread_handling'
    Prepare for future variable 'thread_pool_size'

  sql/slave.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +1 -8
    Setup pseudo_thread_id same way as other code
    Removed not used signal mask

  sql/sql_base.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +36 -15
    Fixed long comments
    Normalized variable setup
    Don't destroy value of thd->variables.pseduo_thread_id
    More DBUG_PRINT()'s
    More DBUG_ASSERT()'s

  sql/sql_class.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +12 -11
    Remove thd->real_id and thd->dbug_thread_id
    Added DBUG_ASSERT()
    Use thread_scheduler to signal threads to be killed.
    In THD::store_globals(), set my_thread_var->id to be thd->thread_id.

  sql/sql_class.h@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +13 -10
    Use 'my_thread_id' for internal thread id's
    Remove not needed THD elements: block_signals and dbug_thread_id
    Added 'thread_scheduler' scheduling extension element to THD

  sql/sql_connect.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +1108 -0
    New BitKeeper file ``sql/sql_connect.cc''

  sql/sql_connect.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -0

  sql/sql_insert.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +1 -7
    Setup pseudo_thread_id same way as other code
    Removed not used signal mask

  sql/sql_parse.cc@stripped, 2007-02-21 16:11:56+02:00, monty@stripped +5 -994
    Move connection related code to sql_connect.cc
    Remove setting of signal mask (not needed)
    Ensure TABLE_LIST->alias is set for generated TABLE_LIST elements (fixed core dumps
when running with --debug)
    Added previous 'optional' element to reset_mgh()

  sql/sql_show.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +0 -4
    Don't send pthread_kill() to threads to detect if they exists.
    (Not that useful and causes problems with future thread_handling code)

  sql/sql_table.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +4 -9
    Simplify code

  sql/sql_test.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +7 -5
    Remove dbug_thread_id from test output

  sql/sql_view.cc@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +1 -1
    Don't send zero pointer to fn_format()

  storage/myisam/mi_log.c@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +1 -1
    my_thread_id() -> my_thread_debug_id()

  vio/viosslfactories.c@stripped, 2007-02-21 16:11:57+02:00, monty@stripped +8 -0
    Added DBUG_PRINT

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	monty
# Host:	narttu.mysql.fi
# Root:	/home/my/mysql-5.1

--- 1.17/BUILD/compile-solaris-sparc-purify	2006-08-10 03:33:05 +03:00
+++ 1.18/BUILD/compile-solaris-sparc-purify	2007-02-21 16:11:55 +02:00
@@ -31,7 +31,7 @@
   shift
 done
 
-gmake -k clean || true 
+make -k clean || true 
 /bin/rm -f */.deps/*.P config.cache
  
 path=`dirname $0`
@@ -39,7 +39,7 @@
 
 CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts
-Wformat -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused 
-DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type
-Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare
-Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy
-Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti  -DHAVE_purify
-DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler
--with-extra-charsets=complex --enable-thread-safe-client --with-embedded-server
--with-innodb $EXTRA_CONFIG_FLAGS
 
-gmake -j 4
+make -j 4
 
 # ----------------------------------------------------------------------
 
@@ -75,17 +75,17 @@
     fi
 
     if [ -n "$mode" -a $mode = purify ] ; then
-      gmake CCLD="purify   $opts gcc"  CXXLD="purify   $opts g++"  $target
+      make CCLD="purify   $opts gcc"  CXXLD="purify   $opts g++"  $target
       mv $binary $binary-purify
     fi
 
     if [ -n "$mode" -a $mode = quantify ] ; then
-      gmake CCLD="quantify $opts gcc"  CXXLD="quantify $opts g++"  $target
+      make CCLD="quantify $opts gcc"  CXXLD="quantify $opts g++"  $target
       mv $binary $binary-quantify
     fi
 
     if [ -n "$mode" -a $mode = purecov ] ; then
-      gmake CCLD="purecov  $opts gcc"  CXXLD="purecov  $opts g++"  $target
+      make CCLD="purecov  $opts gcc"  CXXLD="purecov  $opts g++"  $target
       mv $binary $binary-purecov
     fi
 

--- 1.11/BUILD/compile-solaris-sparc	2006-09-14 08:01:45 +03:00
+++ 1.12/BUILD/compile-solaris-sparc	2007-02-21 16:11:55 +02:00
@@ -1,7 +1,14 @@
-#!/usr/bin/bash
+#! /bin/sh
+
+make -k clean || true
+/bin/rm -f */.deps/*.P config.cache
+ 
+# gcc is often in /usr/ccs/bin or /usr/local/bin
+PATH=$PATH:/usr/ccs/bin:/usr/local/bin
+
 path=`dirname $0`
-. "$path/SETUP.sh"
-extra_flags=""
-extra_configs="$max_configs"
+. "$path/autorun.sh"
+
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts
-Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused  -O3
-fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit
-Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses
-Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder
-Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti 
-O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure
--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex
--enable-thread-safe-client
 
-. "$path/FINISH.sh"
+make -j 4

--- 1.18/client/sql_string.h	2007-01-22 14:10:36 +02:00
+++ 1.19/client/sql_string.h	2007-02-21 16:11:55 +02:00
@@ -23,8 +23,6 @@
 #define NOT_FIXED_DEC			31
 #endif
 
-#define STRING_WITH_LEN(X)  ((const char*) X), ((uint) (sizeof(X) - 1))
-
 class String;
 int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
 String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);

--- 1.434/configure.in	2007-02-06 16:52:22 +02:00
+++ 1.435/configure.in	2007-02-21 16:11:55 +02:00
@@ -715,7 +715,7 @@
  sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
  unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \
  sys/ioctl.h malloc.h sys/malloc.h sys/ipc.h sys/shm.h linux/config.h \
- sys/resource.h sys/param.h)
+ sys/resource.h sys/param.h port.h)
 
 AC_CHECK_HEADERS([xfs/xfs.h])
 
@@ -1883,9 +1883,9 @@
   pthread_setprio_np pthread_setschedparam pthread_sigmask readlink \
   realpath rename rint rwlock_init setupterm \
   shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \
-  sighold sigset sigthreadmask sleep \
-  snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr strtol \
-  strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr \
+  sighold sigset sigthreadmask port_create sleep \
+  snprintf socket stpcpy strcasecmp strerror strsignal strnlen strpbrk strstr \
+  strtol strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr \
   posix_fallocate)
 
 #

--- 1.94/include/config-win.h	2007-01-18 19:18:56 +02:00
+++ 1.95/include/config-win.h	2007-02-21 16:11:55 +02:00
@@ -350,6 +350,7 @@
 #define HAVE_SETFILEPOINTER
 #define HAVE_VIO_READ_BUFF
 #define HAVE_STRNLEN
+#define HAVE_WINSOCK2
 
 #define strcasecmp stricmp
 #define strncasecmp strnicmp

--- 1.106/include/my_pthread.h	2007-02-06 23:37:18 +02:00
+++ 1.107/include/my_pthread.h	2007-02-21 16:11:55 +02:00
@@ -18,7 +18,6 @@
 #ifndef _my_pthread_h
 #define _my_pthread_h
 
-#include <errno.h>
 #ifndef ETIME
 #define ETIME ETIMEDOUT				/* For FreeBSD */
 #endif
@@ -75,6 +74,7 @@
 
 typedef int pthread_mutexattr_t;
 #define win_pthread_self my_thread_var->pthread_self
+#define pthread_self() win_pthread_self
 #define pthread_handler_t EXTERNC void * __cdecl
 typedef void * (__cdecl *pthread_handler)(void *);
 
@@ -130,7 +130,6 @@
 
 #define ETIMEDOUT 145		    /* Win32 doesn't have this */
 #define getpid() GetCurrentThreadId()
-#define pthread_self() win_pthread_self
 #define HAVE_LOCALTIME_R		1
 #define _REENTRANT			1
 #define HAVE_PTHREAD_ATTR_SETSTACKSIZE	1
@@ -638,12 +637,14 @@
 #define MY_MUTEX_INIT_ERRCHK   NULL
 #endif
 
+typedef ulong my_thread_id;
+
 extern my_bool my_thread_global_init(void);
 extern void my_thread_global_end(void);
 extern my_bool my_thread_init(void);
 extern void my_thread_end(void);
 extern const char *my_thread_name(void);
-extern long my_thread_id(void);
+extern my_thread_id my_thread_dbug_id(void);
 extern int pthread_no_free(void *);
 extern int pthread_dummy(int);
 
@@ -670,7 +671,7 @@
   pthread_mutex_t * volatile current_mutex;
   pthread_cond_t * volatile current_cond;
   pthread_t pthread_self;
-  long id;
+  my_thread_id id;
   int cmp_length;
   int volatile abort;
   my_bool init;

--- 1.22/include/thr_alarm.h	2007-02-06 23:37:18 +02:00
+++ 1.23/include/thr_alarm.h	2007-02-21 16:11:55 +02:00
@@ -86,6 +86,7 @@
   ulong expire_time;
   thr_alarm_entry alarmed;		/* set when alarm is due */
   pthread_t thread;
+  my_thread_id thread_id;
   my_bool malloced;
 } ALARM;
 
@@ -94,7 +95,7 @@
 void init_thr_alarm(uint max_alarm);
 void resize_thr_alarm(uint max_alarms);
 my_bool thr_alarm(thr_alarm_t *alarmed, uint sec, ALARM *buff);
-void thr_alarm_kill(pthread_t thread_id);
+void thr_alarm_kill(my_thread_id thread_id);
 void thr_end_alarm(thr_alarm_t *alarmed);
 void end_thr_alarm(my_bool free_structures);
 sig_handler process_alarm(int);

--- 1.20/include/thr_lock.h	2006-12-30 02:36:01 +02:00
+++ 1.21/include/thr_lock.h	2007-02-21 16:11:55 +02:00
@@ -78,7 +78,7 @@
 typedef struct st_thr_lock_info
 {
   pthread_t thread;
-  ulong thread_id;
+  my_thread_id thread_id;
   ulong n_cursors;
 } THR_LOCK_INFO;
 
@@ -144,7 +144,7 @@
                                          uint count, THR_LOCK_OWNER *owner);
 void thr_multi_unlock(THR_LOCK_DATA **data,uint count);
 void thr_abort_locks(THR_LOCK *lock, bool upgrade_lock);
-my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread);
+my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread);
 void thr_print_locks(void);		/* For debugging */
 my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data);
 void    thr_downgrade_write_lock(THR_LOCK_DATA *data,

--- 1.14/storage/myisam/mi_log.c	2006-12-31 02:06:40 +02:00
+++ 1.15/storage/myisam/mi_log.c	2007-02-21 16:11:57 +02:00
@@ -31,7 +31,7 @@
 
 #undef GETPID					/* For HPUX */
 #ifdef THREAD
-#define GETPID() (log_type == 1 ? (long) myisam_pid : (long) my_thread_id());
+#define GETPID() (log_type == 1 ? (long) myisam_pid : (long) my_thread_dbug_id())
 #else
 #define GETPID() myisam_pid
 #endif

--- 1.55/mysys/my_init.c	2007-02-20 18:09:57 +02:00
+++ 1.56/mysys/my_init.c	2007-02-21 16:11:56 +02:00
@@ -250,14 +250,16 @@
 }
 
 /*
-  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.
+  my_parameter_handler
+  
+  Invalid parameter 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, 
+
+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",

--- 1.44/mysys/my_thr_init.c	2007-02-06 23:37:18 +02:00
+++ 1.45/mysys/my_thr_init.c	2007-02-21 16:11:56 +02:00
@@ -46,23 +46,23 @@
 pthread_mutexattr_t my_errorcheck_mutexattr;
 #endif
 
-#ifdef NPTL_PTHREAD_EXIT_BUG /* see my_pthread.h */
+#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.
+  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)
+static pthread_handler_t
+nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
 {
   /* Do nothing! */
   pthread_exit(0);
   return 0;
 }
-
 #endif
 
+
 /*
   initialize thread environment
 
@@ -83,25 +83,28 @@
   }
   
 #ifdef NPTL_PTHREAD_EXIT_BUG
+  /*
+    BUG#24507: Race conditions inside current NPTL pthread_exit() 
+    implementation.
 
-/*
-  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. 
+    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 a full 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);
+    TODO: Remove this code when fixed versions of glibc6 are in common
+    use.
+  */
+  {
+    pthread_t       dummy_thread;
+    pthread_attr_t  dummy_thread_attr;
 
- 
pthread_create(&dummy_thread,&dummy_thread_attr,nptl_pthread_exit_hack_handler,NULL);
+    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
@@ -206,7 +209,7 @@
 #endif
 }
 
-static long thread_id=0;
+static my_thread_id thread_id= 0;
 
 /*
   Allocate thread specific memory for the thread, used by mysys and dbug
@@ -234,15 +237,16 @@
   my_bool error=0;
 
 #ifdef EXTRA_DEBUG_THREADS
-  fprintf(stderr,"my_thread_init(): thread_id=%ld\n",pthread_self());
+  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
+          (ulong) pthread_self());
 #endif  
 
 #if !defined(__WIN__) || defined(USE_TLS)
   if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
   {
 #ifdef EXTRA_DEBUG_THREADS
-    fprintf(stderr,"my_thread_init() called more than once in thread %ld\n",
-	        pthread_self());
+    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
+            (long) pthread_self());
 #endif    
     goto end;
   }
@@ -262,7 +266,9 @@
   tmp= &THR_KEY_mysys;
 #endif
 #if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
-  tmp->thread_self= (pthread_t)getpid();
+  tmp->pthread_self= (pthread_t) getpid();
+#else
+  tmp->pthread_self= pthread_self();
 #endif
   pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
   pthread_cond_init(&tmp->suspend, NULL);
@@ -272,6 +278,11 @@
   tmp->id= ++thread_id;
   ++THR_thread_count;
   pthread_mutex_unlock(&THR_LOCK_threads);
+#ifndef DBUG_OFF
+  /* Generate unique name for thread */
+  (void) my_thread_name();
+#endif
+
 end:
   return error;
 }
@@ -295,8 +306,8 @@
   tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
 
 #ifdef EXTRA_DEBUG_THREADS
-  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  thread_id=%ld\n",
-	  (long) tmp, pthread_self());
+  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
+	  (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
 #endif  
   if (tmp && tmp->init)
   {
@@ -357,17 +368,9 @@
   Get name of current thread.
 ****************************************************************************/
 
-#define UNKNOWN_THREAD -1
-
-long my_thread_id()
+my_thread_id my_thread_dbug_id()
 {
-#if defined(HAVE_PTHREAD_GETSEQUENCE_NP)
-  return pthread_getsequence_np(pthread_self());
-#elif (defined(__sun) || defined(__sgi) || defined(__linux__))
-  return pthread_self();
-#else
   return my_thread_var->id;
-#endif
 }
 
 #ifdef DBUG_OFF
@@ -384,8 +387,8 @@
   struct st_my_thread_var *tmp=my_thread_var;
   if (!tmp->name[0])
   {
-    long id=my_thread_id();
-    sprintf(name_buff,"T@%ld", id);
+    my_thread_id id= my_thread_dbug_id();
+    sprintf(name_buff,"T@%lu", (ulong) id);
     strmake(tmp->name,name_buff,THREAD_NAME_SIZE);
   }
   return tmp->name;

--- 1.55/mysys/thr_alarm.c	2007-02-06 23:37:18 +02:00
+++ 1.56/mysys/thr_alarm.c	2007-02-21 16:11:56 +02:00
@@ -146,6 +146,7 @@
   ulong now;
   sigset_t old_mask;
   my_bool reschedule;
+  struct st_my_thread_var *current_my_thread_var= my_thread_var;
   DBUG_ENTER("thr_alarm");
   DBUG_PRINT("enter",("thread: %s  sec: %d",my_thread_name(),sec));
 
@@ -195,7 +196,8 @@
     alarm_data->malloced=0;
   alarm_data->expire_time=now+sec;
   alarm_data->alarmed=0;
-  alarm_data->thread=pthread_self();
+  alarm_data->thread=    current_my_thread_var->pthread_self;
+  alarm_data->thread_id= current_my_thread_var->id;
   queue_insert(&alarm_queue,(byte*) alarm_data);
 
   /* Reschedule alarm if the current one has more than sec left */
@@ -444,7 +446,7 @@
   Remove another thread from the alarm
 */
 
-void thr_alarm_kill(pthread_t thread_id)
+void thr_alarm_kill(my_thread_id thread_id)
 {
   uint i;
   if (alarm_aborted)
@@ -452,8 +454,7 @@
   pthread_mutex_lock(&LOCK_alarm);
   for (i=0 ; i < alarm_queue.elements ; i++)
   {
-    if (pthread_equal(((ALARM*) queue_element(&alarm_queue,i))->thread,
-		      thread_id))
+    if (((ALARM*) queue_element(&alarm_queue,i))->thread_id == thread_id)
     {
       ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i);
       tmp->expire_time=0;

--- 1.57/mysys/thr_lock.c	2006-12-30 02:36:01 +02:00
+++ 1.58/mysys/thr_lock.c	2007-02-21 16:11:56 +02:00
@@ -343,8 +343,9 @@
 
 void thr_lock_info_init(THR_LOCK_INFO *info)
 {
-  info->thread= pthread_self();
-  info->thread_id= my_thread_id();              /* for debugging */
+  struct st_my_thread_var *tmp= my_thread_var;
+  info->thread=    tmp->pthread_self;
+  info->thread_id= tmp->id;
   info->n_cursors= 0;
 }
 
@@ -622,8 +623,10 @@
 	statistic_increment(locks_immediate,&THR_LOCK_lock);
 	goto end;
       }
+      /* purecov: begin inspected */
       DBUG_PRINT("lock",("write locked by thread: 0x%lx",
 			 lock->write.data->owner->info->thread_id));
+      /* purecov: end */
     }
     else
     {
@@ -658,7 +661,7 @@
 	  goto end;
 	}
       }
-      DBUG_PRINT("lock",("write locked by thread: 0x%lx, type: %d",
+      DBUG_PRINT("lock",("write locked by thread: 0x%lx  type: %d",
 			 lock->read.data->owner->info->thread_id, data->type));
     }
     wait_queue= &lock->write_wait;
@@ -720,8 +723,10 @@
       }
       lock->read_no_write_count++;
     }      
+    /* purecov: begin inspected */
     DBUG_PRINT("lock",("giving read lock to thread: 0x%lx",
 		       data->owner->info->thread_id));
+    /* purecov: end */
     data->cond=0;				/* Mark thread free */
     VOID(pthread_cond_signal(cond));
   } while ((data=data->next));
@@ -806,8 +811,10 @@
 	  if (data->type == TL_WRITE_CONCURRENT_INSERT &&
 	      (*lock->check_status)(data->status_param))
 	    data->type=TL_WRITE;			/* Upgrade lock */
+          /* purecov: begin inspected */
 	  DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx",
 			     data->type, data->owner->info->thread_id));
+          /* purecov: end */
 	  {
 	    pthread_cond_t *cond=data->cond;
 	    data->cond=0;				/* Mark thread free */
@@ -1006,7 +1013,7 @@
       thr_unlock(*pos);
     else
     {
-      DBUG_PRINT("lock",("Free lock: data: 0x%lx  thread: %ld  lock: 0x%lx",
+      DBUG_PRINT("lock",("Free lock: data: 0x%lx  thread: 0x%lx  lock: 0x%lx",
                          (long) *pos, (*pos)->owner->info->thread_id,
                          (long) (*pos)->lock));
     }
@@ -1054,7 +1061,7 @@
   This is used to abort all locks for a specific thread
 */
 
-my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread)
+my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id)
 {
   THR_LOCK_DATA *data;
   my_bool found= FALSE;
@@ -1063,7 +1070,7 @@
   pthread_mutex_lock(&lock->mutex);
   for (data= lock->read_wait.data; data ; data= data->next)
   {
-    if (pthread_equal(thread, data->owner->info->thread))
+    if (data->owner->info->thread_id == thread_id)    /* purecov: tested */
     {
       DBUG_PRINT("info",("Aborting read-wait lock"));
       data->type= TL_UNLOCK;			/* Mark killed */
@@ -1080,7 +1087,7 @@
   }
   for (data= lock->write_wait.data; data ; data= data->next)
   {
-    if (pthread_equal(thread, data->owner->info->thread))
+    if (data->owner->info->thread_id == thread_id) /* purecov: tested */
     {
       DBUG_PRINT("info",("Aborting write-wait lock"));
       data->type= TL_UNLOCK;
@@ -1528,6 +1535,10 @@
 {
 }
 
+static void test_update_status(void* param __attribute__((unused)))
+{
+}
+
 static void test_copy_status(void* to __attribute__((unused)) ,
 			     void *from __attribute__((unused)))
 {
@@ -1620,7 +1631,7 @@
   {
     thr_lock_init(locks+i);
     locks[i].check_status= test_check_status;
-    locks[i].update_status=test_get_status;
+    locks[i].update_status=test_update_status;
     locks[i].copy_status=  test_copy_status;
     locks[i].get_status=   test_get_status;
   }

--- 1.30/mysys/thr_mutex.c	2006-12-23 21:19:47 +02:00
+++ 1.31/mysys/thr_mutex.c	2007-02-21 16:11:56 +02:00
@@ -212,7 +212,7 @@
   {
     fprintf(stderr,
 	    "safe_mutex:  Count was %d in thread 0x%lx when locking mutex at %s, line %d\n",
-	    mp->count-1, my_thread_id(), file, line);
+	    mp->count-1, my_thread_dbug_id(), file, line);
     fflush(stderr);
     abort();
   }
@@ -250,7 +250,7 @@
   {
     fprintf(stderr,
 	    "safe_mutex:  Count was %d in thread 0x%lx when locking mutex at %s, line %d (error:
%d (%d))\n",
-	    mp->count-1, my_thread_id(), file, line, error, error);
+	    mp->count-1, my_thread_dbug_id(), file, line, error, error);
     fflush(stderr);
     abort();
   }

--- 1.173/sql/Makefile.am	2007-02-07 16:11:17 +02:00
+++ 1.174/sql/Makefile.am	2007-02-21 16:11:56 +02:00
@@ -64,10 +64,11 @@
 			tztime.h my_decimal.h\
 			sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
 			parse_file.h sql_view.h	sql_trigger.h \
-			sql_array.h sql_cursor.h events.h \
+			sql_array.h sql_cursor.h events.h scheduler.h \
                         event_db_repository.h event_queue.h \
-			sql_plugin.h authors.h sql_partition.h event_data_objects.h \
-			partition_info.h partition_element.h event_scheduler.h \
+			sql_plugin.h authors.h \
+			event_data_objects.h event_scheduler.h \
+			sql_partition.h partition_info.h partition_element.h \
 			contributors.h sql_servers.h
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -79,7 +80,8 @@
 			lock.cc my_lock.c \
 			sql_string.cc sql_manager.cc sql_map.cc \
 			mysqld.cc password.c hash_filo.cc hostname.cc \
-			set_var.cc sql_parse.cc sql_yacc.yy \
+			sql_connect.cc scheduler.cc sql_parse.cc \
+			set_var.cc sql_yacc.yy \
 			sql_base.cc table.cc sql_select.cc sql_insert.cc \
 			sql_prepare.cc sql_error.cc sql_locale.cc \
 			sql_update.cc sql_delete.cc uniques.cc sql_do.cc \

--- 1.295/sql/handler.cc	2007-02-05 13:29:22 +02:00
+++ 1.296/sql/handler.cc	2007-02-21 16:11:56 +02:00
@@ -845,7 +845,7 @@
     message in the error log, so we don't send it.
   */
   if (is_real_trans && (thd->options & OPTION_STATUS_NO_TRANS_UPDATE)
&&
-      !thd->slave_thread)
+      !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                  ER_WARNING_NOT_COMPLETE_ROLLBACK,
                  ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
@@ -2855,8 +2855,8 @@
 {
   int error= 0;
   DBUG_ENTER("ha_find_files");
-  DBUG_PRINT("enter", ("db: %s, path: %s, wild: %s, dir: %d", 
-		       db, path, wild, dir));
+  DBUG_PRINT("enter", ("db: '%s'  path: '%s'  wild: '%s'  dir: %d", 
+		       db, path, wild ? wild : "NULL", dir));
   st_find_files_args args= {db, path, wild, dir, files};
 
   plugin_foreach(thd, find_files_handlerton,

--- 1.353/sql/item_func.cc	2007-02-13 10:30:00 +02:00
+++ 1.354/sql/item_func.cc	2007-02-21 16:11:56 +02:00
@@ -3085,14 +3085,8 @@
   int count;
   bool locked;
   pthread_cond_t cond;
-#ifndef EMBEDDED_LIBRARY
-  pthread_t thread;
-  void set_thread(THD *thd) { thread= thd->real_id; }
-#else
-  THD       *thread;
-  void set_thread(THD *thd) { thread= thd; }
-#endif /*EMBEDDED_LIBRARY*/
-  ulong thread_id;
+  my_thread_id thread_id;
+  void set_thread(THD *thd) { thread_id= thd->thread_id; }
 
   User_level_lock(const char *key_arg,uint length, ulong id) 
     :key_length(length),count(1),locked(1), thread_id(id)
@@ -3409,11 +3403,7 @@
   }
   else
   {
-#ifdef EMBEDDED_LIBRARY
-    if (ull->locked && (current_thd == ull->thread))
-#else
-    if (ull->locked && pthread_equal(pthread_self(),ull->thread))
-#endif
+    if (ull->locked && current_thd->thread_id == ull->thread_id)
     {
       result=1;					// Release is ok
       item_user_lock_release(ull);

--- 1.102/sql/lock.cc	2007-01-24 23:39:46 +02:00
+++ 1.103/sql/lock.cc	2007-02-21 16:11:56 +02:00
@@ -485,7 +485,7 @@
     for (uint i=0; i < locked->lock_count; i++)
     {
       if (thr_abort_locks_for_thread(locked->locks[i]->lock,
-                                     table->in_use->real_id))
+                                     table->in_use->thread_id))
         result= TRUE;
     }
     my_free((gptr) locked,MYF(0));

--- 1.481/sql/mysql_priv.h	2007-02-14 17:48:25 +02:00
+++ 1.482/sql/mysql_priv.h	2007-02-21 16:11:56 +02:00
@@ -38,6 +38,7 @@
 #include <queues.h>
 #include "sql_bitmap.h"
 #include "sql_array.h"
+#include "scheduler.h"
 
 /* TODO convert all these three maps to Bitmap classes */
 typedef ulonglong table_map;          /* Used for table bits in join */
@@ -282,7 +283,6 @@
 #define TEST_MIT_THREAD		4
 #define TEST_BLOCKING		8
 #define TEST_KEEP_TMP_TABLES	16
-#define TEST_NO_THREADS		32	/* For debugging under Linux */
 #define TEST_READCHECK		64	/* Force use of readcheck */
 #define TEST_NO_EXTRA		128
 #define TEST_CORE_ON_SIGNAL	256	/* Give core if signal */
@@ -787,6 +787,23 @@
 void write_bin_log(THD *thd, bool clear_error,
                    char const *query, ulong query_length);
 
+/* sql_connect.cc */
+int check_user(THD *thd, enum enum_server_command command, 
+	       const char *passwd, uint passwd_len, const char *db,
+	       bool check_count);
+pthread_handler_t handle_one_connection(void *arg);
+bool init_new_connection_handler_thread();
+void reset_mqh(LEX_USER *lu, bool get_them);
+bool check_mqh(THD *thd, uint check_command);
+void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
+int check_for_max_user_connections(THD *thd, USER_CONN *uc);
+void decrease_user_connections(USER_CONN *uc);
+void thd_init_client_charset(THD *thd, uint cs_number);
+bool setup_connection_thread_globals(THD *thd);
+bool login_connection(THD *thd);
+void prepare_new_connection_state(THD* thd);
+void end_connection(THD *thd);
+
 bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
 bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
 bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
@@ -822,10 +839,7 @@
 void init_max_user_conn(void);
 void init_update_queries(void);
 void free_max_user_conn(void);
-pthread_handler_t handle_one_connection(void *arg);
 pthread_handler_t handle_bootstrap(void *arg);
-void end_thread(THD *thd,bool put_in_cache);
-void flush_thread_cache();
 bool mysql_execute_command(THD *thd);
 bool do_command(THD *thd);
 bool dispatch_command(enum enum_server_command command, THD *thd,
@@ -1495,6 +1509,11 @@
 extern void MYSQLerror(const char*);
 void refresh_status(THD *thd);
 my_bool mysql_rm_tmp_tables(void);
+void handle_connection_in_main_thread(THD *thd);
+void create_thread_to_handle_connection(THD *thd);
+void unlink_thd(THD *thd);
+bool one_thread_per_connection_end(THD *thd, bool put_in_cache);
+void flush_thread_cache();
 
 /* item_func.cc */
 extern bool check_reserved_words(LEX_STRING *name);
@@ -1578,7 +1597,7 @@
 extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
 extern ulong max_binlog_size, max_relay_log_size;
 extern ulong opt_binlog_rows_event_max_size;
-extern ulong rpl_recovery_rank, thread_cache_size;
+extern ulong rpl_recovery_rank, thread_cache_size, thread_pool_size;
 extern ulong back_log;
 extern ulong specialflag, current_pid;
 extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
@@ -1663,6 +1682,9 @@
 extern const char* any_db;
 extern struct my_option my_long_options[];
 extern const LEX_STRING view_type;
+extern scheduler_functions thread_scheduler;
+extern TYPELIB thread_handling_typelib;
+extern uint8 uc_update_queries[SQLCOM_END+1];
 extern uint sql_command_flags[];
 extern TYPELIB log_output_typelib;
 

--- 1.618/sql/mysqld.cc	2007-02-09 01:02:51 +02:00
+++ 1.619/sql/mysqld.cc	2007-02-21 16:11:56 +02:00
@@ -59,10 +59,6 @@
 
 #define mysqld_charset &my_charset_latin1
 
-#ifndef DBUG_OFF
-#define ONE_THREAD
-#endif
-
 #ifdef HAVE_purify
 #define IF_PURIFY(A,B) (A)
 #else
@@ -282,6 +278,16 @@
   array_elements(tc_heuristic_recover_names)-1,"",
   tc_heuristic_recover_names, NULL
 };
+
+static const char *thread_handling_names[]=
+{ "one-thread-per-connection", "no-threads", "pool-of-threads", NullS};
+
+TYPELIB thread_handling_typelib=
+{
+  array_elements(thread_handling_names) - 1, "",
+  thread_handling_names, NULL
+};
+
 const char *first_keyword= "first", *binary_keyword= "BINARY";
 const char *my_localhost= "localhost", *delayed_user= "DELAYED";
 #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
@@ -467,7 +473,8 @@
 ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
 ulong open_files_limit, max_binlog_size, max_relay_log_size;
 ulong slave_net_timeout, slave_trans_retries;
-ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
+ulong thread_cache_size=0, thread_pool_size= 0;
+ulong binlog_cache_size=0, max_binlog_cache_size=0;
 ulong query_cache_size=0;
 ulong refresh_version, flush_version;	/* Increments on each reload */
 query_id_t global_query_id;
@@ -681,6 +688,8 @@
 HANDLE smem_event_connect_request= 0;
 #endif
 
+scheduler_functions thread_scheduler;
+
 #define SSL_VARS_NOT_STATIC
 #include "sslopt-vars.h"
 #ifdef HAVE_OPENSSL
@@ -861,6 +870,7 @@
       continue;
 
     tmp->killed= THD::KILL_CONNECTION;
+    thread_scheduler.post_kill_notification(tmp);
     if (tmp->mysys_var)
     {
       tmp->mysys_var->abort=1;
@@ -1254,6 +1264,7 @@
   if (!opt_bootstrap)
     (void) my_delete(pidfile_name,MYF(0));	// This may not always exist
 #endif
+  thread_scheduler.end();
   finish_client_errs();
   my_free((gptr) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST),
           MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
@@ -1513,6 +1524,9 @@
   DBUG_ENTER("network_init");
   LINT_INIT(ret);
 
+  if (thread_scheduler.init())
+    unireg_abort(1);			/* purecov: inspected */
+
   set_ports();
 
   if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
@@ -1731,21 +1745,55 @@
   if (thd && ! thd->bootstrap)
   {
     statistic_increment(killed_threads, &LOCK_status);
-    end_thread(thd,0);
+    thread_scheduler.end_thread(thd,0);		/* purecov: inspected */
   }
   DBUG_VOID_RETURN;				/* purecov: deadcode */
 }
 
 
-void end_thread(THD *thd, bool put_in_cache)
+/*
+  Unlink thd from global list of available connections and free thd
+
+  SYNOPSIS
+    unlink_thd()
+    thd		 Thread handler
+
+  NOTES
+    LOCK_thread_count is locked and left locked
+*/
+
+void unlink_thd(THD *thd)
 {
-  DBUG_ENTER("end_thread");
+  DBUG_ENTER("unlink_thd");
+  DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
   thd->cleanup();
   (void) pthread_mutex_lock(&LOCK_thread_count);
   thread_count--;
   delete thd;
+  DBUG_VOID_RETURN;
+}
+
 
-  if (put_in_cache && cached_thread_count < thread_cache_size &&
+/*
+  Store thread in cache for reuse by new connections
+
+  SYNOPSIS
+    cache_thread()
+
+  NOTES
+    LOCK_thread_count has to be locked
+
+  RETURN
+    0  Thread was not put in cache
+    1  Thread is to be reused by new connection.
+       (ie, caller should return, not abort with pthread_exit())
+*/
+
+
+static bool cache_thread()
+{
+  safe_mutex_assert_owner(&LOCK_thread_count);
+  if (cached_thread_count < thread_cache_size &&
       ! abort_loop && !kill_cached_threads)
   {
     /* Don't kill the thread, just put it in cache for reuse */
@@ -1758,31 +1806,55 @@
       pthread_cond_signal(&COND_flush_thread_cache);
     if (wake_thread)
     {
+      THD *thd;
       wake_thread--;
-      thd=thread_cache.get();
-      thd->real_id=pthread_self();
+      thd= thread_cache.get();
       thd->thread_stack= (char*) &thd;          // For store_globals
       (void) thd->store_globals();
       thd->thr_create_time= time(NULL);
       threads.append(thd);
-      pthread_mutex_unlock(&LOCK_thread_count);
-      DBUG_VOID_RETURN;
+      return(1);
     }
   }
+  return(0);
+}
+
+
+/*
+  End thread for the current connection
+
+  SYNOPSIS
+    one_thread_per_connection_end()
+    thd		  Thread handler
+    put_in_cache  Store thread in cache, if there is room in it
+                  Normally this is true in all cases except when we got
+                  out of resources initializing the current thread
+
+  NOTES
+    If thread is cached, we will wait until thread is scheduled to be
+    reused and then we will return.
+    If thread is not cached, we end the thread.
+
+  RETURN
+    0    Signal to handle_one_connection to reuse connection
+*/
+
+bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
+{
+  DBUG_ENTER("one_thread_per_connection_end");
+  unlink_thd(thd);
+  if (put_in_cache)
+    put_in_cache= cache_thread();
+  pthread_mutex_unlock(&LOCK_thread_count);
+  if (put_in_cache)
+    DBUG_RETURN(0);                             // Thread is reused
 
-  /* Tell main we are ready */
-  (void) pthread_mutex_unlock(&LOCK_thread_count);
   /* It's safe to broadcast outside a lock (COND... is not deleted here) */
   DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
   (void) pthread_cond_broadcast(&COND_thread_count);
-#ifdef ONE_THREAD
-  if (!(test_flags & TEST_NO_THREADS))	// For debugging under Linux
-#endif
-  {
-    my_thread_end();
-    pthread_exit(0);
-  }
-  DBUG_VOID_RETURN;
+
+  my_thread_end();
+  pthread_exit(0);
 }
 
 
@@ -2123,14 +2195,15 @@
           (ulong) dflt_key_cache->key_cache_mem_size);
   fprintf(stderr, "read_buffer_size=%ld\n", (long)
global_system_variables.read_buff_size);
   fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
-  fprintf(stderr, "max_connections=%lu\n", max_connections);
+  fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads);
   fprintf(stderr, "threads_connected=%u\n", thread_count);
   fprintf(stderr, "It is possible that mysqld could use up to \n\
-key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %lu K\n\
+key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = %lu K\n\
 bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
 		     (global_system_variables.read_buff_size +
 		      global_system_variables.sortbuff_size) *
-		     max_connections)/ 1024);
+		     thread_scheduler.max_threads +
+                     max_connections * sizeof(THD)) / 1024);
   fprintf(stderr, "Hope that's ok; if not, decrease some variables in the
equation.\n\n");
 
 #if defined(HAVE_LINUXTHREADS)
@@ -2331,7 +2404,7 @@
     This should actually be '+ max_number_of_slaves' instead of +10,
     but the +10 should be quite safe.
   */
-  init_thr_alarm(max_connections +
+  init_thr_alarm(thread_scheduler.max_threads +
 		 global_system_variables.max_insert_delayed_threads + 10);
 #if SIGINT != THR_KILL_SIGNAL
   if (test_flags & TEST_SIGINT)
@@ -2535,18 +2608,6 @@
 
 #ifdef __WIN__
 
-struct utsname
-{
-  char nodename[FN_REFLEN];
-};
-
-
-int uname(struct utsname *a)
-{
-  return -1;
-}
-
-
 pthread_handler_t handle_shutdown(void *arg)
 {
   MSG msg;
@@ -4009,7 +4070,7 @@
   my_net_init(&thd->net,(st_vio*) 0);
   thd->max_client_packet_length= thd->net.max_packet;
   thd->security_ctx->master_access= ~(ulong)0;
-  thd->thread_id=thread_id++;
+  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
   thread_count++;
 
   bootstrap_file=file;
@@ -4052,6 +4113,74 @@
 
 
 #ifndef EMBEDDED_LIBRARY
+
+/*
+   Simple scheduler that use the main thread to handle the request
+
+   NOTES
+     This is only used for debugging, when starting mysqld with
+     --thread-handling=no-threads or --one-thread
+
+     When we enter this function, LOCK_thread_count is hold!
+*/
+   
+void handle_connection_in_main_thread(THD *thd)
+{
+  safe_mutex_assert_owner(&LOCK_thread_count);
+  thread_cache_size=0;			// Safety
+  threads.append(thd);
+  (void) pthread_mutex_unlock(&LOCK_thread_count);
+  handle_one_connection((void*) thd);
+}
+
+
+/*
+  Scheduler that uses one thread per connection
+*/
+
+void create_thread_to_handle_connection(THD *thd)
+{
+  if (cached_thread_count > wake_thread)
+  {
+    /* Get thread from cache */
+    thread_cache.append(thd);
+    wake_thread++;
+    pthread_cond_signal(&COND_thread_cache);
+  }
+  else
+  {
+    /* Create new thread to handle connection */
+    int error;
+    thread_created++;
+    threads.append(thd);
+    DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
+    thd->connect_time = time(NULL);
+    if ((error=pthread_create(&thd->real_id,&connection_attrib,
+                              handle_one_connection,
+                              (void*) thd)))
+    {
+      /* purify: begin inspected */
+      DBUG_PRINT("error",
+                 ("Can't create thread to handle request (error %d)",
+                  error));
+      thread_count--;
+      thd->killed= THD::KILL_CONNECTION;			// Safety
+      (void) pthread_mutex_unlock(&LOCK_thread_count);
+      statistic_increment(aborted_connects,&LOCK_status);
+      net_printf_error(thd, ER_CANT_CREATE_THREAD, error);
+      (void) pthread_mutex_lock(&LOCK_thread_count);
+      close_connection(thd,0,0);
+      delete thd;
+      (void) pthread_mutex_unlock(&LOCK_thread_count);
+      return;
+      /* purecov: end */
+    }
+  }
+  (void) pthread_mutex_unlock(&LOCK_thread_count);
+  DBUG_PRINT("info",("Thread created"));
+}
+
+
 /*
   Create new thread to handle incoming connection.
 
@@ -4088,64 +4217,15 @@
     DBUG_VOID_RETURN;
   }
   pthread_mutex_lock(&LOCK_thread_count);
-  thd->thread_id=thread_id++;
-
-  thd->real_id=pthread_self();			// Keep purify happy
+  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
 
   /* Start a new thread to handle connection */
   thread_count++;
 
-#ifdef ONE_THREAD
-  if (test_flags & TEST_NO_THREADS)		// For debugging under Linux
-  {
-    thread_cache_size=0;			// Safety
-    threads.append(thd);
-    thd->real_id=pthread_self();
-    (void) pthread_mutex_unlock(&LOCK_thread_count);
-    handle_one_connection((void*) thd);
-  }
-  else
-#endif
-  {
-    if (thread_count-delayed_insert_threads > max_used_connections)
-      max_used_connections=thread_count-delayed_insert_threads;
+  if (thread_count - delayed_insert_threads > max_used_connections)
+    max_used_connections= thread_count - delayed_insert_threads;
 
-    if (cached_thread_count > wake_thread)
-    {
-      thread_cache.append(thd);
-      wake_thread++;
-      pthread_cond_signal(&COND_thread_cache);
-    }
-    else
-    {
-      int error;
-      thread_created++;
-      threads.append(thd);
-      DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
-      thd->connect_time = time(NULL);
-      if ((error=pthread_create(&thd->real_id,&connection_attrib,
-				handle_one_connection,
-				(void*) thd)))
-      {
-	DBUG_PRINT("error",
-		   ("Can't create thread to handle request (error %d)",
-		    error));
-	thread_count--;
-	thd->killed= THD::KILL_CONNECTION;			// Safety
-	(void) pthread_mutex_unlock(&LOCK_thread_count);
-	statistic_increment(aborted_connects,&LOCK_status);
-	net_printf_error(thd, ER_CANT_CREATE_THREAD, error);
-	(void) pthread_mutex_lock(&LOCK_thread_count);
-	close_connection(thd,0,0);
-	delete thd;
-	(void) pthread_mutex_unlock(&LOCK_thread_count);
-	DBUG_VOID_RETURN;
-      }
-    }
-    (void) pthread_mutex_unlock(&LOCK_thread_count);
-
-  }
-  DBUG_PRINT("info",("Thread created"));
+  thread_scheduler.add_connection(thd);
   DBUG_VOID_RETURN;
 }
 #endif /* EMBEDDED_LIBRARY */
@@ -4895,6 +4975,7 @@
   OPT_GENERAL_LOG,
   OPT_SLOW_LOG,
   OPT_MERGE,
+  OPT_THREAD_HANDLING,
   OPT_INNODB_ROLLBACK_ON_TIMEOUT
 };
 
@@ -5502,11 +5583,9 @@
    (gptr*) &global_system_variables.old_passwords,
    (gptr*) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG,
    0, 0, 0, 0, 0, 0},
-#ifdef ONE_THREAD
   {"one-thread", OPT_ONE_THREAD,
-   "Only use one thread (for debugging under Linux).", 0, 0, 0, GET_NO_ARG,
-   NO_ARG, 0, 0, 0, 0, 0, 0},
-#endif
+   "(deprecated): Only use one thread (for debugging under Linux). Use
thread-handling=no-threads instead",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
   {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS,
    "Enable old-style user limits (before 5.0.3 user resources were counted per each
user+host vs. per account)",
    (gptr*) &opt_old_style_user_limits, (gptr*) &opt_old_style_user_limits,
@@ -5985,7 +6064,7 @@
   // children, to avoid "too many connections" error in a common setup
   {"max_connections", OPT_MAX_CONNECTIONS,
    "The number of simultaneous clients allowed.", (gptr*) &max_connections,
-   (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 16384, 0, 1,
+   (gptr*) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1,
    0},
   {"max_delayed_threads", OPT_MAX_DELAYED_THREADS,
    "Don't start more than this number of threads to handle INSERT DELAYED statements. If
set to zero, which means INSERT DELAYED is not used.",
@@ -6276,6 +6355,12 @@
    "Permits the application to give the threads system a hint for the desired number of
threads that should be run at the same time.",
    (gptr*) &concurrency, (gptr*) &concurrency, 0, GET_ULONG, REQUIRED_ARG,
    DEFAULT_CONCURRENCY, 1, 512, 0, 1, 0},
+#if HAVE_POOL_OF_THREADS == 1
+  {"thread_pool_size", OPT_THREAD_CACHE_SIZE,
+   "How many threads we should create to handle query requests in case of
'thread_handling=pool-of-threads'",
+   (gptr*) &thread_pool_size, (gptr*) &thread_pool_size, 0, GET_ULONG,
+   REQUIRED_ARG, 20, 1, 16384, 0, 1, 0},
+#endif
   {"thread_stack", OPT_THREAD_STACK,
    "The stack size for each thread.", (gptr*) &thread_stack,
    (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
@@ -6300,6 +6385,10 @@
    (gptr*) &global_system_variables.trans_prealloc_size,
    (gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
    REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
+  {"thread_handling", OPT_THREAD_HANDLING,
+   "Define threads usage for handling queries:  "
+   "one-thread-per-connection or no-threads", 0, 0,
+   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
   {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT,
    "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a
key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO =
Prohibit update of a VIEW, which does not contain a key of the underlying table and the
query uses a LIMIT clause (usually get from GUI tools).",
    (gptr*) &global_system_variables.updatable_views_with_limit,
@@ -7241,7 +7330,6 @@
     break;
   case 'T':
     test_flags= argument ? (uint) atoi(argument) : 0;
-    test_flags&= ~TEST_NO_THREADS;
     opt_endinfo=1;
     break;
   case (int) OPT_BIG_TABLES:
@@ -7473,11 +7561,6 @@
     opt_skip_show_db=1;
     opt_specialflag|=SPECIAL_SKIP_SHOW_DB;
     break;
-#ifdef ONE_THREAD
-  case (int) OPT_ONE_THREAD:
-    test_flags |= TEST_NO_THREADS;
-#endif
-    break;
   case (int) OPT_WANT_CORE:
     test_flags |= TEST_CORE_ON_SIGNAL;
     break;
@@ -7723,6 +7806,23 @@
 						   sql_mode);
     break;
   }
+  case OPT_ONE_THREAD:
+    global_system_variables.thread_handling= 2;
+    break;
+  case OPT_THREAD_HANDLING:
+  {
+    if ((global_system_variables.thread_handling=
+         find_type(argument, &thread_handling_typelib, 2)) <= 0 ||
+        (global_system_variables.thread_handling == SCHEDULER_POOL_OF_THREADS
+         && !HAVE_POOL_OF_THREADS))
+    {
+      /* purecov: begin tested */
+      fprintf(stderr,"Unknown/unsupported thread-handling: %s\n",argument);
+      exit(1);
+      /* purecov: end */
+    }
+    break;
+  }
   case OPT_FT_BOOLEAN_SYNTAX:
     if (ft_boolean_check_syntax_string((byte*) argument))
     {
@@ -7843,6 +7943,7 @@
   if (mysqld_chroot)
     set_root(mysqld_chroot);
 #else
+  global_system_variables.thread_handling = SCHEDULER_NO_THREADS;
   max_allowed_packet= global_system_variables.max_allowed_packet;
   net_buffer_length= global_system_variables.net_buffer_length;
 #endif
@@ -7873,6 +7974,17 @@
 				  &global_system_variables.datetime_format))
     exit(1);
 
+#ifdef EMBEDDED_LIBRARY
+  one_thread_scheduler(&thread_scheduler);
+#else
+  if (global_system_variables.thread_handling <=
+      SCHEDULER_ONE_THREAD_PER_CONNECTION)
+    one_thread_per_connection_scheduler(&thread_scheduler);
+  else if (global_system_variables.thread_handling == SCHEDULER_NO_THREADS)
+    one_thread_scheduler(&thread_scheduler);
+  else
+    pool_of_threads_scheduler(&thread_scheduler);  /* purecov: tested */
+#endif
 }
 
 
@@ -8213,5 +8325,3 @@
 template class I_List<Statement>;
 template class I_List_iterator<Statement>;
 #endif
-
-

--- 1.306/sql/slave.cc	2007-02-09 01:02:52 +02:00
+++ 1.307/sql/slave.cc	2007-02-21 16:11:56 +02:00
@@ -1425,9 +1425,8 @@
   thd->slave_thread = 1;
   set_slave_thread_options(thd);
   thd->client_capabilities = CLIENT_LOCAL_FILES;
-  thd->real_id=pthread_self();
   pthread_mutex_lock(&LOCK_thread_count);
-  thd->thread_id = thread_id++;
+  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
   pthread_mutex_unlock(&LOCK_thread_count);
 
   if (init_thr_lock() || thd->store_globals())
@@ -1436,12 +1435,6 @@
     delete thd;
     DBUG_RETURN(-1);
   }
-
-#if !defined(__WIN__) && !defined(__NETWARE__)
-  sigset_t set;
-  VOID(sigemptyset(&set));                      // Get mask in use
-  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
 
   if (thd_type == SLAVE_THD_SQL)
     thd->proc_info= "Waiting for the next event in relay log";

--- 1.374/sql/sql_base.cc	2007-02-02 08:19:32 +02:00
+++ 1.375/sql/sql_base.cc	2007-02-21 16:11:56 +02:00
@@ -1078,7 +1078,6 @@
   if (!thd->active_transaction())
     thd->transaction.xid_state.xid.null();
 
-  /* VOID(pthread_sigmask(SIG_SETMASK,&thd->block_signals,NULL)); */
   if (!lock_in_use)
     VOID(pthread_mutex_lock(&LOCK_open));
 
@@ -1208,11 +1207,12 @@
   const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ";
   uint stub_len= sizeof(stub) - 1;
   char buf[256];
-  memcpy(buf, stub, stub_len);
   String s_query= String(buf, sizeof(buf), system_charset_info);
-  bool found_user_tables= false;
+  bool found_user_tables= FALSE;
   LINT_INIT(next);
 
+  memcpy(buf, stub, stub_len);
+
   /*
      insertion sort of temp tables by pseudo_thread_id to build ordered list
      of sublists of equal pseudo_thread_id
@@ -1263,10 +1263,13 @@
   {
     if (is_user_table(table))
     {
+      my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id;
       /* Set pseudo_thread_id to be that of the processed table */
       thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
-      /* Loop forward through all tables within the sublist of
-         common pseudo_thread_id to create single DROP query */
+      /*
+        Loop forward through all tables within the sublist of
+        common pseudo_thread_id to create single DROP query.
+      */
       for (s_query.length(stub_len);
            table && is_user_table(table) &&
              tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
@@ -1292,16 +1295,18 @@
                             0, FALSE);
       thd->variables.character_set_client= cs_save;
       /*
-        Imagine the thread had created a temp table, then was doing a SELECT, and
-        the SELECT was killed. Then it's not clever to mark the statement above as
-        "killed", because it's not really a statement updating data, and there
-        are 99.99% chances it will succeed on slave.
-        If a real update (one updating a persistent table) was killed on the
-        master, then this real update will be logged with error_code=killed,
-        rightfully causing the slave to stop.
+        Imagine the thread had created a temp table, then was doing a
+        SELECT, and the SELECT was killed. Then it's not clever to
+        mark the statement above as "killed", because it's not really
+        a statement updating data, and there are 99.99% chances it
+        will succeed on slave.  If a real update (one updating a
+        persistent table) was killed on the master, then this real
+        update will be logged with error_code=killed, rightfully
+        causing the slave to stop.
       */
       qinfo.error_code= 0;
       mysql_bin_log.write(&qinfo);
+      thd->variables.pseudo_thread_id= save_pseudo_thread_id;
     }
     else
     {
@@ -1519,9 +1524,15 @@
   {
     if (table->s->table_cache_key.length == key_length &&
 	!memcmp(table->s->table_cache_key.str, key, key_length))
+    {
+      DBUG_PRINT("info",
+                 ("Found table. server_id: %u  pseudo_thread_id: %lu",
+                  (uint) thd->server_id,
+                  (ulong) thd->variables.pseudo_thread_id));
       DBUG_RETURN(table);
+    }
   }
-  DBUG_RETURN(0);					// Not a temporary table
+  DBUG_RETURN(0);                               // Not a temporary table
 }
 
 
@@ -1857,6 +1868,10 @@
 	if (table->query_id == thd->query_id ||
             thd->prelocked_mode && table->query_id)
 	{
+          DBUG_PRINT("error",
+                     ("query_id: %lu  server_id: %u  pseudo_thread_id: %lu",
+                      (ulong) table->query_id, (uint) thd->server_id,
+                      (ulong) thd->variables.pseudo_thread_id));
 	  my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias);
 	  DBUG_RETURN(0);
 	}
@@ -3507,8 +3522,11 @@
   uint key_length;
   TABLE_LIST table_list;
   DBUG_ENTER("open_temporary_table");
-  DBUG_PRINT("enter", ("table: '%s'.'%s'  path: '%s'",
-                       db, table_name, path));
+  DBUG_PRINT("enter",
+             ("table: '%s'.'%s'  path: '%s'  server_id: %u  "
+              "pseudo_thread_id: %lu",
+              db, table_name, path,
+              (uint) thd->server_id, (ulong) thd->variables.pseudo_thread_id));
 
   table_list.db=         (char*) db;
   table_list.table_name= (char*) table_name;
@@ -3978,6 +3996,9 @@
 {
   Field *fld;
   DBUG_ENTER("find_field_in_table_ref");
+  DBUG_ASSERT(table_list->alias);
+  DBUG_ASSERT(name);
+  DBUG_ASSERT(item_name);
   DBUG_PRINT("enter",
              ("table: '%s'  field name: '%s'  item name: '%s'  ref 0x%lx",
               table_list->alias, name, item_name, (ulong) ref));

--- 1.312/sql/sql_class.cc	2007-02-03 00:22:14 +02:00
+++ 1.313/sql/sql_class.cc	2007-02-21 16:11:56 +02:00
@@ -243,7 +243,7 @@
   time_after_lock=(time_t) 0;
   current_linfo =  0;
   slave_thread = 0;
-  variables.pseudo_thread_id= 0;
+  thread_id= variables.pseudo_thread_id= 0;
   one_shot_set= 0;
   file_id = 0;
   query_id= 0;
@@ -267,9 +267,6 @@
   cleanup_done= abort_on_warning= no_warnings_for_error= 0;
   peer_port= 0;					// For SHOW PROCESSLIST
   transaction.m_pending_rows_event= 0;
-#ifdef	__WIN__
-  real_id = 0;
-#endif
 #ifdef SIGNAL_WITH_VIO_CLOSE
   active_vio = 0;
 #endif
@@ -401,6 +398,8 @@
 void THD::cleanup(void)
 {
   DBUG_ENTER("THD::cleanup");
+  DBUG_ASSERT(cleanup_done == 0);
+
 #ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
   if (transaction.xid_state.xa_state == XA_PREPARED)
   {
@@ -436,7 +435,6 @@
     pthread_mutex_lock(&LOCK_user_locks);
     item_user_lock_release(ull);
     pthread_mutex_unlock(&LOCK_user_locks);
-    ull= 0;
   }
 
   cleanup_done=1;
@@ -550,7 +548,9 @@
   killed= state_to_set;
   if (state_to_set != THD::KILL_QUERY)
   {
-    thr_alarm_kill(real_id);
+    thr_alarm_kill(thread_id);
+    if (!slave_thread)
+      thread_scheduler.post_kill_notification(this);
 #ifdef SIGNAL_WITH_VIO_CLOSE
     close_active_vio();
 #endif    
@@ -601,18 +601,19 @@
     Assert that thread_stack is initialized: it's necessary to be able
     to track stack overrun.
   */
-  DBUG_ASSERT(this->thread_stack);
+  DBUG_ASSERT(thread_stack);
 
   if (my_pthread_setspecific_ptr(THR_THD,  this) ||
       my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
     return 1;
   mysys_var=my_thread_var;
-  dbug_thread_id=my_thread_id();
   /*
-    By default 'slave_proxy_id' is 'thread_id'. They may later become different
-    if this is the slave SQL thread.
+    Let mysqld define the thread id (not mysys)
+    This allows us to move THD to different threads if needed.
   */
-  variables.pseudo_thread_id= thread_id;
+  mysys_var->id= thread_id;
+  real_id= pthread_self();                      // For debugging
+
   /*
     We have to call thr_lock_info_init() again here as THD may have been
     created in another thread

--- 1.339/sql/sql_class.h	2007-01-29 01:51:39 +02:00
+++ 1.340/sql/sql_class.h	2007-02-21 16:11:56 +02:00
@@ -214,7 +214,7 @@
   ulong read_rnd_buff_size;
   ulong div_precincrement;
   ulong sortbuff_size;
-  handlerton *table_type;
+  ulong thread_handling;
   ulong tx_isolation;
   ulong completion_type;
   /* Determines which non-standard SQL behaviour should be enabled */
@@ -231,11 +231,15 @@
   ulong trans_prealloc_size;
   ulong log_warnings;
   ulong group_concat_max_len;
+  ulong ndb_autoincrement_prefetch_sz;
+  ulong ndb_index_stat_cache_entries;
+  ulong ndb_index_stat_update_freq;
+  ulong binlog_format; // binlog format for this thd (see enum_binlog_format)
   /*
     In slave thread we need to know in behalf of which
     thread the query is being run to replicate temp tables properly
   */
-  ulong pseudo_thread_id;
+  my_thread_id pseudo_thread_id;
 
   my_bool low_priority_updates;
   my_bool new_mode;
@@ -248,14 +252,12 @@
   my_bool ndb_use_exact_count;
   my_bool ndb_use_transactions;
   my_bool ndb_index_stat_enable;
-  ulong ndb_autoincrement_prefetch_sz;
-  ulong ndb_index_stat_cache_entries;
-  ulong ndb_index_stat_update_freq;
-  ulong binlog_format; // binlog format for this thd (see enum_binlog_format)
 
   my_bool old_alter_table;
   my_bool old_passwords;
 
+  handlerton *table_type;
+
   /* Only charset part of these variables is sensible */
   CHARSET_INFO  *character_set_filesystem;
   CHARSET_INFO  *character_set_client;
@@ -1064,7 +1066,7 @@
   } transaction;
   Field      *dup_field;
 #ifndef __WIN__
-  sigset_t signals,block_signals;
+  sigset_t signals;
 #endif
 #ifdef SIGNAL_WITH_VIO_CLOSE
   Vio* active_vio;
@@ -1255,7 +1257,7 @@
     update auto-updatable fields (like auto_increment and timestamp).
   */
   query_id_t query_id, warn_id;
-  ulong      thread_id, col_access;
+  ulong      col_access;
 
 #ifdef ERROR_INJECT_SUPPORT
   ulong      error_inject_value;
@@ -1264,8 +1266,8 @@
   ulong      statement_id_counter;
   ulong	     rand_saved_seed1, rand_saved_seed2;
   ulong      row_count;  // Row counter, mainly for errors and warnings
-  long	     dbug_thread_id;
-  pthread_t  real_id;
+  pthread_t  real_id;                           /* For debugging */
+  my_thread_id  thread_id;
   uint	     tmp_table, global_read_lock;
   uint	     server_status,open_options;
   enum enum_thread_type system_thread;
@@ -1629,6 +1631,7 @@
     *p_db_length= db_length;
     return FALSE;
   }
+  thd_scheduler scheduler;
 };
 
 

--- 1.246/sql/sql_insert.cc	2007-02-13 23:15:19 +02:00
+++ 1.247/sql/sql_insert.cc	2007-02-21 16:11:56 +02:00
@@ -1897,7 +1897,7 @@
   pthread_detach_this_thread();
   /* Add thread to THD list so that's it's visible in 'show processlist' */
   pthread_mutex_lock(&LOCK_thread_count);
-  thd->thread_id=thread_id++;
+  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
   thd->end_time();
   threads.append(thd);
   thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED;
@@ -1928,14 +1928,8 @@
     strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
     goto err;
   }
-#if !defined(__WIN__) && !defined(__NETWARE__)
-  sigset_t set;
-  VOID(sigemptyset(&set));			// Get mask in use
-  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
 
   /* open table */
-
   if (!(di->table=open_ltable(thd,&di->table_list,TL_WRITE_DELAYED)))
   {
     thd->fatal_error();				// Abort waiting inserts

--- 1.626/sql/sql_parse.cc	2007-02-06 16:52:27 +02:00
+++ 1.627/sql/sql_parse.cc	2007-02-21 16:11:56 +02:00
@@ -28,24 +28,6 @@
 #include "events.h"
 #include "event_data_objects.h"
 
-#ifdef HAVE_OPENSSL
-/*
-  Without SSL the handshake consists of one packet. This packet
-  has both client capabilites and scrambled password.
-  With SSL the handshake might consist of two packets. If the first
-  packet (client capabilities) has CLIENT_SSL flag set, we have to
-  switch to SSL and read the second packet. The scrambled password
-  is in the second packet and client_capabilites field will be ignored.
-  Maybe it is better to accept flags other than CLIENT_SSL from the
-  second packet?
-*/
-#define SSL_HANDSHAKE_SIZE      2
-#define NORMAL_HANDSHAKE_SIZE   6
-#define MIN_HANDSHAKE_SIZE      2
-#else
-#define MIN_HANDSHAKE_SIZE      6
-#endif /* HAVE_OPENSSL */
-
 /* Used in error handling only */
 #define SP_TYPE_STRING(LP) \
   ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE")
@@ -56,11 +38,6 @@
    (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
    "FUNCTION" : "PROCEDURE")
 
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-static void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
-static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
-static void decrease_user_connections(USER_CONN *uc);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
 static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
 
 const char *any_db="*any*";	// Special symbol for check_access
@@ -103,20 +80,6 @@
   "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
 };
 
-#ifdef __WIN__
-static void  test_signal(int sig_ptr)
-{
-#if !defined( DBUG_OFF)
-  MessageBox(NULL,"Test signal","DBUG",MB_OK);
-#endif
-}
-static void init_signals(void)
-{
-  int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;
-  for (int i=0 ; i < 7 ; i++)
-    signal( signals[i], test_signal) ;
-}
-#endif
 
 static void unlock_locked_tables(THD *thd)
 {
@@ -160,6 +123,7 @@
   DBUG_RETURN(error);
 }
 
+
 bool begin_trans(THD *thd)
 {
   int error=0;
@@ -211,413 +175,6 @@
   return 0;
 }
 
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-static HASH hash_user_connections;
-
-static int get_or_create_user_conn(THD *thd, const char *user,
-				   const char *host,
-				   USER_RESOURCES *mqh)
-{
-  int return_val= 0;
-  uint temp_len, user_len;
-  char temp_user[USER_HOST_BUFF_SIZE];
-  struct  user_conn *uc;
-
-  DBUG_ASSERT(user != 0);
-  DBUG_ASSERT(host != 0);
-
-  user_len= strlen(user);
-  temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
-  (void) pthread_mutex_lock(&LOCK_user_conn);
-  if (!(uc = (struct  user_conn *) hash_search(&hash_user_connections,
-					       (byte*) temp_user, temp_len)))
-  {
-    /* First connection for user; Create a user connection object */
-    if (!(uc= ((struct user_conn*)
-	       my_malloc(sizeof(struct user_conn) + temp_len+1,
-			 MYF(MY_WME)))))
-    {
-      net_send_error(thd, 0, NullS);		// Out of memory
-      return_val= 1;
-      goto end;
-    }
-    uc->user=(char*) (uc+1);
-    memcpy(uc->user,temp_user,temp_len+1);
-    uc->host= uc->user + user_len +  1;
-    uc->len= temp_len;
-    uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
-    uc->user_resources= *mqh;
-    uc->intime= thd->thr_create_time;
-    if (my_hash_insert(&hash_user_connections, (byte*) uc))
-    {
-      my_free((char*) uc,0);
-      net_send_error(thd, 0, NullS);		// Out of memory
-      return_val= 1;
-      goto end;
-    }
-  }
-  thd->user_connect=uc;
-  uc->connections++;
-end:
-  (void) pthread_mutex_unlock(&LOCK_user_conn);
-  return return_val;
-
-}
-#endif /* !NO_EMBEDDED_ACCESS_CHECKS */
-
-
-/*
-  Check if user exist and password supplied is correct. 
-
-  SYNOPSIS
-    check_user()
-    thd          thread handle, thd->security_ctx->{host,user,ip} are used
-    command      originator of the check: now check_user is called
-                 during connect and change user procedures; used for 
-                 logging.
-    passwd       scrambled password received from client
-    passwd_len   length of scrambled password
-    db           database name to connect to, may be NULL
-    check_count  dont know exactly
-
-    Note, that host, user and passwd may point to communication buffer.
-    Current implementation does not depend on that, but future changes
-    should be done with this in mind; 'thd' is INOUT, all other params
-    are 'IN'.
-
-  RETURN VALUE
-    0  OK; thd->security_ctx->user/master_access/priv_user/db_access and
-       thd->db are updated; OK is sent to client;
-   -1  access denied or handshake error; error is sent to client;
-   >0  error, not sent to client
-*/
-
-int check_user(THD *thd, enum enum_server_command command, 
-	       const char *passwd, uint passwd_len, const char *db,
-	       bool check_count)
-{
-  DBUG_ENTER("check_user");
-  
-#ifdef NO_EMBEDDED_ACCESS_CHECKS
-  thd->main_security_ctx.master_access= GLOBAL_ACLS;       // Full rights
-  /* Change database if necessary */
-  if (db && db[0])
-  {
-    /*
-      thd->db is saved in caller and needs to be freed by caller if this
-      function returns 0
-    */
-    thd->reset_db(NULL, 0);
-    if (mysql_change_db(thd, db, FALSE))
-    {
-      /* Send the error to the client */
-      net_send_error(thd);
-      DBUG_RETURN(-1);
-    }
-  }
-  send_ok(thd);
-  DBUG_RETURN(0);
-#else
-
-  my_bool opt_secure_auth_local;
-  pthread_mutex_lock(&LOCK_global_system_variables);
-  opt_secure_auth_local= opt_secure_auth;
-  pthread_mutex_unlock(&LOCK_global_system_variables);
-  
-  /*
-    If the server is running in secure auth mode, short scrambles are 
-    forbidden.
-  */
-  if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
-  {
-    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
-    general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
-    DBUG_RETURN(-1);
-  }
-  if (passwd_len != 0 &&
-      passwd_len != SCRAMBLE_LENGTH &&
-      passwd_len != SCRAMBLE_LENGTH_323)
-    DBUG_RETURN(ER_HANDSHAKE_ERROR);
-
-  /*
-    Clear thd->db as it points to something, that will be freed when 
-    connection is closed. We don't want to accidentally free a wrong pointer
-    if connect failed. Also in case of 'CHANGE USER' failure, current
-    database will be switched to 'no database selected'.
-  */
-  thd->reset_db(NULL, 0);
-
-  USER_RESOURCES ur;
-  int res= acl_getroot(thd, &ur, passwd, passwd_len);
-#ifndef EMBEDDED_LIBRARY
-  if (res == -1)
-  {
-    /*
-      This happens when client (new) sends password scrambled with
-      scramble(), but database holds old value (scrambled with
-      scramble_323()). Here we please client to send scrambled_password
-      in old format.
-    */
-    NET *net= &thd->net;
-    if (opt_secure_auth_local)
-    {
-      net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
-                       thd->main_security_ctx.user,
-                       thd->main_security_ctx.host_or_ip);
-      general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
-                        thd->main_security_ctx.user,
-                        thd->main_security_ctx.host_or_ip);
-      DBUG_RETURN(-1);
-    }
-    /* We have to read very specific packet size */
-    if (send_old_password_request(thd) ||
-        my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
-    {
-      inc_host_errors(&thd->remote.sin_addr);
-      DBUG_RETURN(ER_HANDSHAKE_ERROR);
-    }
-    /* Final attempt to check the user based on reply */
-    /* So as passwd is short, errcode is always >= 0 */
-    res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
-  }
-#endif /*EMBEDDED_LIBRARY*/
-  /* here res is always >= 0 */
-  if (res == 0)
-  {
-    if (!(thd->main_security_ctx.master_access &
-          NO_ACCESS)) // authentication is OK
-    {
-      DBUG_PRINT("info",
-                 ("Capabilities: %lu  packet_length: %ld  Host: '%s'  "
-                  "Login user: '%s' Priv_user: '%s'  Using password: %s "
-                  "Access: %lu  db: '%s'",
-                  thd->client_capabilities,
-                  thd->max_client_packet_length,
-                  thd->main_security_ctx.host_or_ip,
-                  thd->main_security_ctx.user,
-                  thd->main_security_ctx.priv_user,
-                  passwd_len ? "yes": "no",
-                  thd->main_security_ctx.master_access,
-                  (thd->db ? thd->db : "*none*")));
-
-      if (check_count)
-      {
-        VOID(pthread_mutex_lock(&LOCK_thread_count));
-        bool count_ok= thread_count <= max_connections + delayed_insert_threads
-                       || (thd->main_security_ctx.master_access & SUPER_ACL);
-        VOID(pthread_mutex_unlock(&LOCK_thread_count));
-        if (!count_ok)
-        {                                         // too many connections
-          net_send_error(thd, ER_CON_COUNT_ERROR);
-          DBUG_RETURN(-1);
-        }
-      }
-
-      /*
-        Log the command before authentication checks, so that the user can
-        check the log for the tried login tried and also to detect
-        break-in attempts.
-      */
-      general_log_print(thd, command,
-                        (thd->main_security_ctx.priv_user ==
-                         thd->main_security_ctx.user ?
-                         (char*) "%s@%s on %s" :
-                         (char*) "%s@%s as anonymous on %s"),
-                        thd->main_security_ctx.user,
-                        thd->main_security_ctx.host_or_ip,
-                        db ? db : (char*) "");
-
-      /*
-        This is the default access rights for the current database.  It's
-        set to 0 here because we don't have an active database yet (and we
-        may not have an active database to set.
-      */
-      thd->main_security_ctx.db_access=0;
-
-      /* Don't allow user to connect if he has done too many queries */
-      if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
-	   max_user_connections) &&
-	  get_or_create_user_conn(thd,
-            (opt_old_style_user_limits ? thd->main_security_ctx.user :
-             thd->main_security_ctx.priv_user),
-            (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
-             thd->main_security_ctx.priv_host),
-            &ur))
-	DBUG_RETURN(-1);
-      if (thd->user_connect &&
-	  (thd->user_connect->user_resources.conn_per_hour ||
-	   thd->user_connect->user_resources.user_conn ||
-	   max_user_connections) &&
-	  check_for_max_user_connections(thd, thd->user_connect))
-	DBUG_RETURN(-1);
-
-      /* Change database if necessary */
-      if (db && db[0])
-      {
-        if (mysql_change_db(thd, db, FALSE))
-        {
-          /* Send error to the client */
-          net_send_error(thd);
-          if (thd->user_connect)
-            decrease_user_connections(thd->user_connect);
-          DBUG_RETURN(-1);
-        }
-      }
-      send_ok(thd);
-      thd->password= test(passwd_len);          // remember for error messages 
-      /* Ready to handle queries */
-      DBUG_RETURN(0);
-    }
-  }
-  else if (res == 2) // client gave short hash, server has long hash
-  {
-    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
-    general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
-    DBUG_RETURN(-1);
-  }
-  net_printf_error(thd, ER_ACCESS_DENIED_ERROR,
-                   thd->main_security_ctx.user,
-                   thd->main_security_ctx.host_or_ip,
-                   passwd_len ? ER(ER_YES) : ER(ER_NO));
-  general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
-                    thd->main_security_ctx.user,
-                    thd->main_security_ctx.host_or_ip,
-                    passwd_len ? ER(ER_YES) : ER(ER_NO));
-  DBUG_RETURN(-1);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-}
-
-/*
-  Check for maximum allowable user connections, if the mysqld server is
-  started with corresponding variable that is greater then 0.
-*/
-
-extern "C" byte *get_key_conn(user_conn *buff, uint *length,
-			      my_bool not_used __attribute__((unused)))
-{
-  *length=buff->len;
-  return (byte*) buff->user;
-}
-
-extern "C" void free_user(struct user_conn *uc)
-{
-  my_free((char*) uc,MYF(0));
-}
-
-void init_max_user_conn(void)
-{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-  (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
-		   0,0,
-		   (hash_get_key) get_key_conn, (hash_free_key) free_user,
-		   0);
-#endif
-}
-
-
-/*
-  check if user has already too many connections
-  
-  SYNOPSIS
-  check_for_max_user_connections()
-  thd			Thread handle
-  uc			User connect object
-
-  NOTES
-    If check fails, we decrease user connection count, which means one
-    shouldn't call decrease_user_connections() after this function.
-
-  RETURN
-    0	ok
-    1	error
-*/
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-
-static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
-{
-  int error=0;
-  DBUG_ENTER("check_for_max_user_connections");
-
-  (void) pthread_mutex_lock(&LOCK_user_conn);
-  if (max_user_connections && !uc->user_resources.user_conn &&
-      max_user_connections < (uint) uc->connections)
-  {
-    net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
-    error=1;
-    goto end;
-  }
-  time_out_user_resource_limits(thd, uc);
-  if (uc->user_resources.user_conn &&
-      uc->user_resources.user_conn < uc->connections)
-  {
-    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
-                     "max_user_connections",
-                     (long) uc->user_resources.user_conn);
-    error= 1;
-    goto end;
-  }
-  if (uc->user_resources.conn_per_hour &&
-      uc->user_resources.conn_per_hour <= uc->conn_per_hour)
-  {
-    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
-                     "max_connections_per_hour",
-                     (long) uc->user_resources.conn_per_hour);
-    error=1;
-    goto end;
-  }
-  uc->conn_per_hour++;
-
-  end:
-  if (error)
-    uc->connections--; // no need for decrease_user_connections() here
-  (void) pthread_mutex_unlock(&LOCK_user_conn);
-  DBUG_RETURN(error);
-}
-
-/*
-  Decrease user connection count
-
-  SYNOPSIS
-    decrease_user_connections()
-    uc			User connection object
-
-  NOTES
-    If there is a n user connection object for a connection
-    (which only happens if 'max_user_connections' is defined or
-    if someone has created a resource grant for a user), then
-    the connection count is always incremented on connect.
-
-    The user connect object is not freed if some users has
-    'max connections per hour' defined as we need to be able to hold
-    count over the lifetime of the connection.
-*/
-
-static void decrease_user_connections(USER_CONN *uc)
-{
-  DBUG_ENTER("decrease_user_connections");
-  (void) pthread_mutex_lock(&LOCK_user_conn);
-  DBUG_ASSERT(uc->connections);
-  if (!--uc->connections && !mqh_used)
-  {
-    /* Last connection for user; Delete it */
-    (void) hash_delete(&hash_user_connections,(byte*) uc);
-  }
-  (void) pthread_mutex_unlock(&LOCK_user_conn);
-  DBUG_VOID_RETURN;
-}
-
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-
-
-void free_max_user_conn(void)
-{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-  hash_free(&hash_user_connections);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-}
-
-
 
 /*
   Mark all commands that somehow changes a table
@@ -701,402 +258,6 @@
   return (sql_command_flags[command] & CF_CHANGES_DATA) != 0;
 }
 
-/*
-  Reset per-hour user resource limits when it has been more than
-  an hour since they were last checked
-
-  SYNOPSIS:
-    time_out_user_resource_limits()
-    thd			Thread handler
-    uc			User connection details
-
-  NOTE:
-    This assumes that the LOCK_user_conn mutex has been acquired, so it is
-    safe to test and modify members of the USER_CONN structure.
-*/
-
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-
-static void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
-{
-  time_t check_time = thd->start_time ?  thd->start_time : time(NULL);
-  DBUG_ENTER("time_out_user_resource_limits");
-
-  /* If more than a hour since last check, reset resource checking */
-  if (check_time  - uc->intime >= 3600)
-  {
-    uc->questions=1;
-    uc->updates=0;
-    uc->conn_per_hour=0;
-    uc->intime=check_time;
-  }
-
-  DBUG_VOID_RETURN;
-}
-
-/*
-  Check if maximum queries per hour limit has been reached
-  returns 0 if OK.
-*/
-
-static bool check_mqh(THD *thd, uint check_command)
-{
-  bool error= 0;
-  USER_CONN *uc=thd->user_connect;
-  DBUG_ENTER("check_mqh");
-  DBUG_ASSERT(uc != 0);
-
-  (void) pthread_mutex_lock(&LOCK_user_conn);
-
-  time_out_user_resource_limits(thd, uc);
-
-  /* Check that we have not done too many questions / hour */
-  if (uc->user_resources.questions &&
-      uc->questions++ >= uc->user_resources.questions)
-  {
-    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
-                     (long) uc->user_resources.questions);
-    error=1;
-    goto end;
-  }
-  if (check_command < (uint) SQLCOM_END)
-  {
-    /* Check that we have not done too many updates / hour */
-    if (uc->user_resources.updates &&
-        (sql_command_flags[check_command] & CF_CHANGES_DATA) &&
-	uc->updates++ >= uc->user_resources.updates)
-    {
-      net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
-                       (long) uc->user_resources.updates);
-      error=1;
-      goto end;
-    }
-  }
-end:
-  (void) pthread_mutex_unlock(&LOCK_user_conn);
-  DBUG_RETURN(error);
-}
-
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-
-
-static void reset_mqh(LEX_USER *lu, bool get_them= 0)
-{
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
-  (void) pthread_mutex_lock(&LOCK_user_conn);
-  if (lu)  // for GRANT
-  {
-    USER_CONN *uc;
-    uint temp_len=lu->user.length+lu->host.length+2;
-    char temp_user[USER_HOST_BUFF_SIZE];
-
-    memcpy(temp_user,lu->user.str,lu->user.length);
-    memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
-    temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
-    if ((uc = (struct  user_conn *) hash_search(&hash_user_connections,
-						(byte*) temp_user, temp_len)))
-    {
-      uc->questions=0;
-      get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
-      uc->updates=0;
-      uc->conn_per_hour=0;
-    }
-  }
-  else
-  {
-    /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
-    for (uint idx=0;idx < hash_user_connections.records; idx++)
-    {
-      USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
-						      idx);
-      if (get_them)
-	get_mqh(uc->user,uc->host,uc);
-      uc->questions=0;
-      uc->updates=0;
-      uc->conn_per_hour=0;
-    }
-  }
-  (void) pthread_mutex_unlock(&LOCK_user_conn);
-#endif /* NO_EMBEDDED_ACCESS_CHECKS */
-}
-
-void thd_init_client_charset(THD *thd, uint cs_number)
-{
-  /*
-   Use server character set and collation if
-   - opt_character_set_client_handshake is not set
-   - client has not specified a character set
-   - client character set is the same as the servers
-   - client character set doesn't exists in server
-  */
-  if (!opt_character_set_client_handshake ||
-      !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
-      !my_strcasecmp(&my_charset_latin1,
-                     global_system_variables.character_set_client->name,
-                     thd->variables.character_set_client->name))
-  {
-    thd->variables.character_set_client=
-      global_system_variables.character_set_client;
-    thd->variables.collation_connection=
-      global_system_variables.collation_connection;
-    thd->variables.character_set_results=
-      global_system_variables.character_set_results;
-  }
-  else
-  {
-    thd->variables.character_set_results=
-      thd->variables.collation_connection= 
-      thd->variables.character_set_client;
-  }
-}
-
-
-/*
-    Perform handshake, authorize client and update thd ACL variables.
-  SYNOPSIS
-    check_connection()
-    thd  thread handle
-
-  RETURN
-     0  success, OK is sent to user, thd is updated.
-    -1  error, which is sent to user
-   > 0  error code (not sent to user)
-*/
-
-#ifndef EMBEDDED_LIBRARY
-static int check_connection(THD *thd)
-{
-  uint connect_errors= 0;
-  NET *net= &thd->net;
-  ulong pkt_len= 0;
-  char *end;
-
-  DBUG_PRINT("info",
-             ("New connection received on %s", vio_description(net->vio)));
-#ifdef SIGNAL_WITH_VIO_CLOSE
-  thd->set_active_vio(net->vio);
-#endif
-
-  if (!thd->main_security_ctx.host)         // If TCP/IP connection
-  {
-    char ip[30];
-
-    if (vio_peer_addr(net->vio, ip, &thd->peer_port))
-      return (ER_BAD_HOST_ERROR);
-    if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0))))
-      return (ER_OUT_OF_RESOURCES);
-    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
-    vio_in_addr(net->vio,&thd->remote.sin_addr);
-    if (!(specialflag & SPECIAL_NO_RESOLVE))
-    {
-      vio_in_addr(net->vio,&thd->remote.sin_addr);
-      thd->main_security_ctx.host=
-        ip_to_hostname(&thd->remote.sin_addr, &connect_errors);
-      /* Cut very long hostnames to avoid possible overflows */
-      if (thd->main_security_ctx.host)
-      {
-        if (thd->main_security_ctx.host != my_localhost)
-          thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host),
-                                          HOSTNAME_LENGTH)]= 0;
-        thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
-      }
-      if (connect_errors > max_connect_errors)
-        return(ER_HOST_IS_BLOCKED);
-    }
-    DBUG_PRINT("info",("Host: %s  ip: %s",
-		       (thd->main_security_ctx.host ?
-                        thd->main_security_ctx.host : "unknown host"),
-		       (thd->main_security_ctx.ip ?
-                        thd->main_security_ctx.ip : "unknown ip")));
-    if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
-      return(ER_HOST_NOT_PRIVILEGED);
-  }
-  else /* Hostname given means that the connection was on a socket */
-  {
-    DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host));
-    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
-    thd->main_security_ctx.ip= 0;
-    /* Reset sin_addr */
-    bzero((char*) &thd->remote, sizeof(thd->remote));
-  }
-  vio_keepalive(net->vio, TRUE);
-  {
-    /* buff[] needs to big enough to hold the server_version variable */
-    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
-    ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
-			  CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
-
-    if (opt_using_transactions)
-      client_flags|=CLIENT_TRANSACTIONS;
-#ifdef HAVE_COMPRESS
-    client_flags |= CLIENT_COMPRESS;
-#endif /* HAVE_COMPRESS */
-#ifdef HAVE_OPENSSL
-    if (ssl_acceptor_fd)
-      client_flags |= CLIENT_SSL;       /* Wow, SSL is available! */
-#endif /* HAVE_OPENSSL */
-
-    end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
-    int4store((uchar*) end, thd->thread_id);
-    end+= 4;
-    /*
-      So as check_connection is the only entry point to authorization
-      procedure, scramble is set here. This gives us new scramble for
-      each handshake.
-    */
-    create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
-    /*
-      Old clients does not understand long scrambles, but can ignore packet
-      tail: that's why first part of the scramble is placed here, and second
-      part at the end of packet.
-    */
-    end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
-   
-    int2store(end, client_flags);
-    /* write server characteristics: up to 16 bytes allowed */
-    end[2]=(char) default_charset_info->number;
-    int2store(end+3, thd->server_status);
-    bzero(end+5, 13);
-    end+= 18;
-    /* write scramble tail */
-    end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
-                 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
-
-    /* At this point we write connection message and read reply */
-    if (net_write_command(net, (uchar) protocol_version, "", 0, buff,
-			  (uint) (end-buff)) ||
-	(pkt_len= my_net_read(net)) == packet_error ||
-	pkt_len < MIN_HANDSHAKE_SIZE)
-    {
-      inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
-    }
-  }
-#ifdef _CUSTOMCONFIG_
-#include "_cust_sql_parse.h"
-#endif
-  if (connect_errors)
-    reset_host_errors(&thd->remote.sin_addr);
-  if (thd->packet.alloc(thd->variables.net_buffer_length))
-    return(ER_OUT_OF_RESOURCES);
-
-  thd->client_capabilities=uint2korr(net->read_pos);
-  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
-  {
-    thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
-    thd->max_client_packet_length= uint4korr(net->read_pos+4);
-    DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
-    thd_init_client_charset(thd, (uint) net->read_pos[8]);
-    thd->update_charset();
-    end= (char*) net->read_pos+32;
-  }
-  else
-  {
-    thd->max_client_packet_length= uint3korr(net->read_pos+2);
-    end= (char*) net->read_pos+5;
-  }
-
-  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
-    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
-#ifdef HAVE_OPENSSL
-  DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
-  if (thd->client_capabilities & CLIENT_SSL)
-  {
-    /* Do the SSL layering. */
-    if (!ssl_acceptor_fd)
-    {
-      inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
-    }
-    DBUG_PRINT("info", ("IO layer change in progress..."));
-    if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
-    {
-      DBUG_PRINT("error", ("Failed to accept new SSL connection"));
-      inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
-    }
-    DBUG_PRINT("info", ("Reading user information over SSL layer"));
-    if ((pkt_len= my_net_read(net)) == packet_error ||
-	pkt_len < NORMAL_HANDSHAKE_SIZE)
-    {
-      DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
-			   pkt_len));
-      inc_host_errors(&thd->remote.sin_addr);
-      return(ER_HANDSHAKE_ERROR);
-    }
-  }
-#endif
-
-  if (end >= (char*) net->read_pos+ pkt_len +2)
-  {
-    inc_host_errors(&thd->remote.sin_addr);
-    return(ER_HANDSHAKE_ERROR);
-  }
-
-  if (thd->client_capabilities & CLIENT_INTERACTIVE)
-    thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
-  if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
-      opt_using_transactions)
-    net->return_status= &thd->server_status;
-
-  char *user= end;
-  char *passwd= strend(user)+1;
-  uint user_len= passwd - user - 1;
-  char *db= passwd;
-  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
-  char user_buff[USERNAME_LENGTH + 1];	// buffer to store user in utf8
-  uint dummy_errors;
-
-  /*
-    Old clients send null-terminated string as password; new clients send
-    the size (1 byte) + string (not null-terminated). Hence in case of empty
-    password both send '\0'.
-
-    This strlen() can't be easily deleted without changing protocol.
-  */
-  uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
-    *passwd++ : strlen(passwd);
-  db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
-    db + passwd_len + 1 : 0;
-  /* strlen() can't be easily deleted without changing protocol */
-  uint db_len= db ? strlen(db) : 0;
-
-  if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
-  {
-    inc_host_errors(&thd->remote.sin_addr);
-    return ER_HANDSHAKE_ERROR;
-  }
-
-  /* Since 4.1 all database names are stored in utf8 */
-  if (db)
-  {
-    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
-                             system_charset_info,
-                             db, db_len,
-                             thd->charset(), &dummy_errors)]= 0;
-    db= db_buff;
-  }
-
-  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
-                                       system_charset_info, user, user_len,
-                                       thd->charset(), &dummy_errors)]= '\0';
-  user= user_buff;
-
-  /* If username starts and ends in "'", chop them off */
-  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
-  {
-    user[user_len-1]= 0;
-    user++;
-    user_len-= 2;
-  }
-
-  if (thd->main_security_ctx.user)
-    x_free(thd->main_security_ctx.user);
-  if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
-    return (ER_OUT_OF_RESOURCES);
-  return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
-}
-
 
 void execute_init_command(THD *thd, sys_var_str *init_command_var,
 			  rw_lock_t *var_mutex)
@@ -1129,153 +290,6 @@
 }
 
 
-pthread_handler_t handle_one_connection(void *arg)
-{
-  THD *thd=(THD*) arg;
-  uint launch_time  =
-    (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time);
-  if (launch_time >= slow_launch_time)
-    statistic_increment(slow_launch_threads,&LOCK_status );
-
-  pthread_detach_this_thread();
-
-#if !defined( __WIN__) // Win32 calls this in pthread_create
-  /* The following calls needs to be done before we call DBUG_ macros */
-  if (!(test_flags & TEST_NO_THREADS) & my_thread_init())
-  {
-    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
-    statistic_increment(aborted_connects,&LOCK_status);
-    end_thread(thd,0);
-    return 0;
-  }
-#endif
-
-  /*
-    handle_one_connection() is the only way a thread would start
-    and would always be on top of the stack, therefore, the thread
-    stack always starts at the address of the first local variable
-    of handle_one_connection, which is thd. We need to know the
-    start of the stack so that we could check for stack overruns.
-  */
-  DBUG_PRINT("info", ("handle_one_connection called by thread %lu\n",
-		      thd->thread_id));
-  /* now that we've called my_thread_init(), it is safe to call DBUG_* */
-
-#if defined(__WIN__)
-  init_signals();
-#elif !defined(__NETWARE__)
-  sigset_t set;
-  VOID(sigemptyset(&set));			// Get mask in use
-  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
-  thd->thread_stack= (char*) &thd;
-  if (thd->store_globals())
-  {
-    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
-    statistic_increment(aborted_connects,&LOCK_status);
-    end_thread(thd,0);
-    return 0;
-  }
-
-  do
-  {
-    int error;
-    NET *net= &thd->net;
-    Security_context *sctx= thd->security_ctx;
-    net->no_send_error= 0;
-
-    /* Use "connect_timeout" value during connection phase */
-    net_set_read_timeout(net, connect_timeout);
-    net_set_write_timeout(net, connect_timeout);
-
-    if ((error=check_connection(thd)))
-    {						// Wrong permissions
-      if (error > 0)
-	net_printf_error(thd, error, sctx->host_or_ip);
-#ifdef __NT__
-      if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
-	my_sleep(1000);				/* must wait after eof() */
-#endif
-      statistic_increment(aborted_connects,&LOCK_status);
-      goto end_thread;
-    }
-#ifdef __NETWARE__
-    netware_reg_user(sctx->ip, sctx->user, "MySQL");
-#endif
-    if (thd->variables.max_join_size == HA_POS_ERROR)
-      thd->options |= OPTION_BIG_SELECTS;
-    if (thd->client_capabilities & CLIENT_COMPRESS)
-      net->compress=1;				// Use compression
-
-    thd->version= refresh_version;
-    thd->proc_info= 0;
-    thd->command= COM_SLEEP;
-    thd->set_time();
-    thd->init_for_queries();
-
-    if (sys_init_connect.value_length && !(sctx->master_access &
SUPER_ACL))
-    {
-      execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
-      if (thd->query_error)
-      {
-	thd->killed= THD::KILL_CONNECTION;
-        sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
-                          thd->thread_id,(thd->db ? thd->db : "unconnected"),
-                          sctx->user ? sctx->user : "unauthenticated",
-                          sctx->host_or_ip, "init_connect command failed");
-        sql_print_warning("%s", net->last_error);
-      }
-      thd->proc_info=0;
-      thd->set_time();
-      thd->init_for_queries();
-    }
-
-    /* Connect completed, set read/write timeouts back to tdefault */
-    net_set_read_timeout(net, thd->variables.net_read_timeout);
-    net_set_write_timeout(net, thd->variables.net_write_timeout);
-
-    while (!net->error && net->vio != 0 &&
-           !(thd->killed == THD::KILL_CONNECTION))
-    {
-      net->no_send_error= 0;
-      if (do_command(thd))
-	break;
-    }
-    if (thd->user_connect)
-      decrease_user_connections(thd->user_connect);
-    if (net->error && net->vio != 0 && net->report_error)
-    {
-      if (!thd->killed && thd->variables.log_warnings > 1)
-	sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
-                          thd->thread_id,(thd->db ? thd->db : "unconnected"),
-                          sctx->user ? sctx->user : "unauthenticated",
-                          sctx->host_or_ip,
-                          (net->last_errno ? ER(net->last_errno) :
-                           ER(ER_UNKNOWN_ERROR)));
-      net_send_error(thd, net->last_errno, NullS);
-      statistic_increment(aborted_threads,&LOCK_status);
-    }
-    else if (thd->killed)
-    {
-      statistic_increment(aborted_threads,&LOCK_status);
-    }
-    
-end_thread:
-    close_connection(thd, 0, 1);
-    end_thread(thd,1);
-    /*
-      If end_thread returns, we are either running with --one-thread
-      or this thread has been schedule to handle the next query
-    */
-    thd= current_thd;
-    thd->thread_stack= (char*) &thd;
-  } while (!(test_flags & TEST_NO_THREADS));
-  /* The following is only executed if we are not using --one-thread */
-  return(0);					/* purecov: deadcode */
-}
-
-#endif /* EMBEDDED_LIBRARY */
-
 /*
   Execute commands from bootstrap_file.
   Used when creating the initial grant tables
@@ -1302,11 +316,6 @@
 #ifndef EMBEDDED_LIBRARY
   pthread_detach_this_thread();
   thd->thread_stack= (char*) &thd;
-#if !defined(__WIN__) && !defined(__NETWARE__)
-  sigset_t set;
-  VOID(sigemptyset(&set));			// Get mask in use
-  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
 #endif /* EMBEDDED_LIBRARY */
 
   if (thd->variables.max_join_size == HA_POS_ERROR)
@@ -4230,7 +3239,7 @@
           {
             if (!(user= get_current_user(thd, tmp_user)))
               goto error;
-	    reset_mqh(user);
+	    reset_mqh(user, 0);
           }
 	}
       }
@@ -6580,6 +5589,7 @@
   join_list->push_front(ptr);
   ptr->embedding= embedding;
   ptr->join_list= join_list;
+  ptr->alias= (char*) "(nested_join)";
   embedding= ptr;
   join_list= &nested_join->join_list;
   join_list->empty();
@@ -6664,6 +5674,7 @@
 
   ptr->embedding= embedding;
   ptr->join_list= join_list;
+  ptr->alias= (char*) "(nest_last_join)";
   embedded_list= &nested_join->join_list;
   embedded_list->empty();
 
@@ -7158,7 +6169,7 @@
  }
 #endif
  if (options & REFRESH_USER_RESOURCES)
-   reset_mqh((LEX_USER *) NULL);
+   reset_mqh((LEX_USER *) NULL, 0);		/* purecov: inspected */
  *write_to_binlog= tmp_write_to_binlog;
  return result;
 }

--- 1.391/sql/sql_show.cc	2007-02-13 10:30:01 +02:00
+++ 1.392/sql/sql_show.cc	2007-02-21 16:11:57 +02:00
@@ -1687,10 +1687,6 @@
         if (mysys_var)
           pthread_mutex_unlock(&mysys_var->mutex);
 
-#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
-        if (pthread_kill(tmp->real_id,0))
-          tmp->proc_info="*** DEAD ***";        // This shouldn't happen
-#endif
 #ifdef EXTRA_DEBUG
         thd_info->start_time= tmp->time_after_lock;
 #else

--- 1.388/sql/sql_table.cc	2007-01-29 01:51:40 +02:00
+++ 1.389/sql/sql_table.cc	2007-02-21 16:11:57 +02:00
@@ -3416,16 +3416,11 @@
   {
  #ifdef FN_DEVCHAR
     /* check if the table name contains FN_DEVCHAR when defined */
-    const char *start= alias;
-    while (*start != '\0')
+    if (strchr(alias, FN_DEVCHAR))
     {
-      if (*start == FN_DEVCHAR)
-      {
-        my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
-        DBUG_RETURN(TRUE);
-      }
-      start++;
-    }	  
+      my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
+      DBUG_RETURN(TRUE);
+    }
 #endif
     path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
                                       internal_tmp_table ? FN_IS_TMP : 0);

--- 1.50/sql/sql_test.cc	2006-12-31 02:06:37 +02:00
+++ 1.51/sql/sql_test.cc	2007-02-21 16:11:57 +02:00
@@ -73,17 +73,18 @@
   uint idx,count,unused;
   TABLE *start_link,*lnk;
 
+  /* purecov: begin tested */
   VOID(pthread_mutex_lock(&LOCK_open));
-  puts("DB             Table                            Version  Thread  L.thread  Open 
Lock");
+  puts("DB             Table                            Version  Thread  Open  Lock");
 
   for (idx=unused=0 ; idx < open_cache.records ; idx++)
   {
     TABLE *entry=(TABLE*) hash_element(&open_cache,idx);
-    printf("%-14.14s %-32s%6ld%8ld%10ld%6d  %s\n",
-	   entry->s->db.str, entry->s->table_name.str, entry->s->version,
+    printf("%-14.14s %-32s%6ld%8ld%6d  %s\n",
+           entry->s->db.str, entry->s->table_name.str,
entry->s->version,
 	   entry->in_use ? entry->in_use->thread_id : 0L,
-	   entry->in_use ? entry->in_use->dbug_thread_id : 0L,
-	   entry->db_stat ? 1 : 0, entry->in_use ?
lock_descriptions[(int)entry->reginfo.lock_type] : "Not in use");
+	   entry->db_stat ? 1 : 0,
+           entry->in_use ? lock_descriptions[(int)entry->reginfo.lock_type] : "Not
in use");
     if (!entry->in_use)
       unused++;
   }
@@ -110,6 +111,7 @@
     printf("Error: File hash table is corrupted\n");
   fflush(stdout);
   VOID(pthread_mutex_unlock(&LOCK_open));
+  /* purecov: end */
   return;
 }
 

--- 1.31/sql/event_scheduler.cc	2006-12-23 21:33:28 +02:00
+++ 1.32/sql/event_scheduler.cc	2007-02-21 16:11:56 +02:00
@@ -104,25 +104,22 @@
   SYNOPSIS
     post_init_event_thread()
       thd  Thread
+
+  NOTES
+    Before this is called, one should not do any DBUG_XXX() calls.
+
 */
 
 bool
 post_init_event_thread(THD *thd)
 {
-  my_thread_init();
-  pthread_detach_this_thread();
-  thd->real_id= pthread_self();
+  (void) init_new_connection_handler_thread();
   if (init_thr_lock() || thd->store_globals())
   {
     thd->cleanup();
     return TRUE;
   }
 
-#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
-  sigset_t set;
-    VOID(sigemptyset(&set));                    // Get mask in use
-  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
   pthread_mutex_lock(&LOCK_thread_count);
   threads.append(thd);
   thread_count++;
@@ -187,7 +184,7 @@
   thd->options|= OPTION_AUTO_IS_NULL;
   thd->client_capabilities|= CLIENT_MULTI_RESULTS;
   pthread_mutex_lock(&LOCK_thread_count);
-  thd->thread_id= thread_id++;
+  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
   pthread_mutex_unlock(&LOCK_thread_count);
 
   /*
@@ -218,20 +215,20 @@
 event_scheduler_thread(void *arg)
 {
   /* needs to be first for thread_stack */
-  THD *thd= (THD *)((struct scheduler_param *) arg)->thd;
+  THD *thd= (THD *) ((struct scheduler_param *) arg)->thd;
   Event_scheduler *scheduler= ((struct scheduler_param *) arg)->scheduler;
+  bool res;
 
-  my_free((char*)arg, MYF(0));
-
-  thd->thread_stack= (char *)&thd;              // remember where our stack is
+  thd->thread_stack= (char*) &thd;              // remember where our stack is
+  res= post_init_event_thread(thd);
 
   DBUG_ENTER("event_scheduler_thread");
-
-  if (!post_init_event_thread(thd))
+  my_free((char*)arg, MYF(0));
+  if (!res)
     scheduler->run(thd);
 
   deinit_event_thread(thd);
-
+  pthread_exit(0);
   DBUG_RETURN(0);                               // Against gcc warnings
 }
 
@@ -255,13 +252,14 @@
   THD *thd; 
   Event_job_data *event= (Event_job_data *)arg;
   int ret;
+  bool res;
 
   thd= event->thd;
-
   thd->thread_stack= (char *) &thd;             // remember where our stack is
+  res= post_init_event_thread(thd);
   DBUG_ENTER("event_worker_thread");
 
-  if (!post_init_event_thread(thd))
+  if (!res)
   {
     DBUG_PRINT("info", ("Baikonur, time is %ld, BURAN reporting and operational."
                         "THD: 0x%lx",
@@ -295,6 +293,7 @@
 
   deinit_event_thread(thd);
 
+  pthread_exit(0);
   DBUG_RETURN(0);                               // Can't return anything here
 }
 

--- 1.26/sql/parse_file.cc	2006-12-23 21:19:51 +02:00
+++ 1.27/sql/parse_file.cc	2007-02-21 16:11:56 +02:00
@@ -228,7 +228,7 @@
 
   if (dir)
   {
-    fn_format(path, file_name->str, dir->str, 0, MY_UNPACK_FILENAME);
+    fn_format(path, file_name->str, dir->str, "", MY_UNPACK_FILENAME);
     path_end= strlen(path);
   }
   else

--- 1.121/sql/sql_view.cc	2007-02-13 10:30:02 +02:00
+++ 1.122/sql/sql_view.cc	2007-02-21 16:11:57 +02:00
@@ -713,7 +713,7 @@
     File_parser *parser;
 
     path.str= path_buff;
-    fn_format(path_buff, file.str, dir.str, 0, MY_UNPACK_FILENAME);
+    fn_format(path_buff, file.str, dir.str, "", MY_UNPACK_FILENAME);
     path.length= strlen(path_buff);
 
     if (!access(path.str, F_OK))

--- 1.64/mysys/my_getopt.c	2007-02-14 02:09:32 +02:00
+++ 1.65/mysys/my_getopt.c	2007-02-21 16:11:56 +02:00
@@ -960,7 +960,7 @@
 	printf("%d\n", *((uint*) value));
 	break;
       case GET_LONG:
-	printf("%lu\n", *((long*) value));
+	printf("%ld\n", *((long*) value));
 	break;
       case GET_ULONG:
 	printf("%lu\n", *((ulong*) value));

--- 1.12/mysql-test/t/wait_timeout.test	2007-01-24 19:56:57 +02:00
+++ 1.13/mysql-test/t/wait_timeout.test	2007-02-21 16:11:55 +02:00
@@ -1,5 +1,6 @@
 # This tests not performed with embedded server
 -- source include/not_embedded.inc
+-- source include/one_thread_per_connection.inc
 
 #
 # Bug #8731: wait_timeout does not work on Mac OS X

--- 1.270/mysql-test/mysql-test-run.pl	2007-02-06 17:38:53 +02:00
+++ 1.271/mysql-test/mysql-test-run.pl	2007-02-21 16:11:55 +02:00
@@ -1718,7 +1718,7 @@
   }
 
   $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths,
-				$ENV{'LD_LIBRARY_PATHS'} ?
+				$ENV{'LD_LIBRARY_PATH'} ?
 				split(':', $ENV{'LD_LIBRARY_PATH'}) : ());
   mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}");
 

--- 1.5/BUILD/compile-solaris-sparc-debug	2006-09-14 08:01:56 +03:00
+++ 1.6/BUILD/compile-solaris-sparc-debug	2007-02-21 16:11:55 +02:00
@@ -1,7 +1,11 @@
-#!/usr/bin/bash
+#!/bin/sh
+
+make -k clean || true
+/bin/rm -f */.deps/*.P config.cache
+ 
 path=`dirname $0`
-. "$path/SETUP.sh"
-extra_flags="$debug_cflags"
-extra_configs="$debug_configs $max_configs"
+. "$path/autorun.sh"
+ 
+CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts
-Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused  -O3
-fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit
-Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat
-Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder
-Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti 
-O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure
--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex
--enable-thread-safe-client --with-debug
 
-. "$path/FINISH.sh"
+make -j 4

--- 1.5/BUILD/compile-solaris-sparc-forte	2005-05-18 23:26:19 +03:00
+++ 1.6/BUILD/compile-solaris-sparc-forte	2007-02-21 16:11:55 +02:00
@@ -1,16 +1,16 @@
 #! /bin/sh
 
-gmake -k clean || true
+# Assume Forte is installed in /opt/SUNWSpro and ld is installed in
+# /usr/ccs/bin
+
+PATH=/opt/SUNWspro/bin/:/usr/ccs/bin:$PATH
+
+make -k clean || true
 /bin/rm -f */.deps/*.P config.cache
  
 path=`dirname $0`
 . "$path/autorun.sh"
 
-
-# Assume Forte is installed in /opt/SUNWSpro
-
-PATH=/opt/SUNWspro/bin/:$PATH
-
 # For "optimal" code for this computer add -fast to EXTRA
 # To compile 64 bit, add -xarch=v9 to EXTRA_64_BIT
 
@@ -27,7 +27,7 @@
 CXX=CC CXXFLAGS="-noex $STD" \
 ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex
--enable-thread-safe-client
 
-gmake -j 4
+make -j 4
 if [ $? = 0 ]
 then
   make test

--- 1.215/sql/set_var.cc	2007-02-06 16:52:25 +02:00
+++ 1.216/sql/set_var.cc	2007-02-21 16:11:56 +02:00
@@ -396,6 +396,10 @@
 sys_var_thd_ulong	sys_trans_prealloc_size("transaction_prealloc_size",
 						&SV::trans_prealloc_size,
 						0, fix_trans_mem_root);
+sys_var_thd_enum        sys_thread_handling("thread_handling",
+                                            &SV::thread_handling,
+                                            &thread_handling_typelib,
+                                            NULL);
 
 #ifdef HAVE_QUERY_CACHE
 sys_var_long_ptr	sys_query_cache_limit("query_cache_limit",
@@ -464,6 +468,10 @@
                                                     &table_lock_wait_timeout);
 sys_var_long_ptr	sys_thread_cache_size("thread_cache_size",
 					      &thread_cache_size);
+#if HAVE_POOL_OF_THREADS == 1
+sys_var_long_ptr	sys_thread_pool_size("thread_pool_size",
+					      &thread_pool_size);
+#endif
 sys_var_thd_enum	sys_tx_isolation("tx_isolation",
 					 &SV::tx_isolation,
 					 &tx_isolation_typelib,
@@ -1006,6 +1014,10 @@
   {sys_thread_cache_size.name,(char*) &sys_thread_cache_size,       SHOW_SYS},
 #ifdef HAVE_THR_SETCONCURRENCY
   {"thread_concurrency",      (char*) &concurrency,                 SHOW_LONG},
+#endif
+  {sys_thread_handling.name,  (char*) &sys_thread_handling,         SHOW_SYS},
+#if HAVE_POOL_OF_THREADS == 1
+  {sys_thread_pool_size.name, (char*) &sys_thread_pool_size,        SHOW_SYS},
 #endif
   {"thread_stack",            (char*) &thread_stack,                SHOW_LONG},
   {sys_time_format.name,      (char*) &sys_time_format,		    SHOW_SYS},
--- New file ---
+++ libmysqld/scheduler.cc	07/02/21 16:11:57
SYMLINK -> ../sql/scheduler.cc

--- New file ---
+++ libmysqld/sql_connect.cc	07/02/21 16:11:57
SYMLINK -> ../sql/sql_connect.cc

--- New file ---
+++ mysql-test/include/one_thread_per_connection.inc	07/02/21 16:11:57
-- require r/one_thread_per_connection.require
disable_query_log;
select @@thread_handling;
enable_query_log;


--- New file ---
+++ mysql-test/r/no-threads.result	07/02/21 16:11:57
select 1+1;
1+1
2
select 1+2;
1+2
3

--- New file ---
+++ mysql-test/r/one_thread_per_connection.require	07/02/21 16:11:57
@@thread_handling
one-thread-per-connection

--- New file ---
+++ mysql-test/t/no-threads-master.opt	07/02/21 16:11:57
--one-thread --thread-handling=no-threads

--- New file ---
+++ mysql-test/t/no-threads.test	07/02/21 16:11:57
#
# Test the --thread-handler=no-threads option
#
select 1+1;
select 1+2;

--- New file ---
+++ sql/scheduler.cc	07/02/21 16:11:57
/* Copyright (C) 2007 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 */

/*
  Implementation for the thread scheduler
*/

#ifdef USE_PRAGMA_INTERFACE
#pragma implementation
#endif

#include <mysql_priv.h>

/*
  'Dummy' functions to be used when we don't need any handling for a scheduler
  event
 */

static bool init_dummy(void) {return 0;}
static void post_kill_dummy(THD* thd) {}  
static void end_dummy(void) {}
static bool end_thread_dummy(THD *thd, bool cache_thread) { return 0; }

/*
  Initialize default scheduler with dummy functions so that setup functions
  only need to declare those that are relvant for their usage
*/

scheduler_functions::scheduler_functions()
  :init(init_dummy),
   init_new_connection_thread(init_new_connection_handler_thread),
   add_connection(0),                           // Must be defined
   post_kill_notification(post_kill_dummy),
   end_thread(end_thread_dummy), end(end_dummy)
{}


/*
  End connection, in case when we are using 'no-threads'
*/

static bool no_threads_end(THD *thd, bool put_in_cache)
{
  unlink_thd(thd);
  pthread_mutex_unlock(&LOCK_thread_count);
  return 1;                                     // Abort handle_one_connection
}


/*
  Initailize scheduler for --thread-handling=no-threads
*/

void one_thread_scheduler(scheduler_functions* func)
{
  func->max_threads= 1;
#ifndef EMBEDDED_LIBRARY
  func->add_connection= handle_connection_in_main_thread;
#endif
  func->init_new_connection_thread= init_dummy;
  func->end_thread= no_threads_end;
}


/*
  Initialize scheduler for --thread-handling=one-thread-per-connection
*/

#ifndef EMBEDDED_LIBRARY
void one_thread_per_connection_scheduler(scheduler_functions* func)
{
  func->max_threads= max_connections;
  func->add_connection= create_thread_to_handle_connection;
  func->end_thread= one_thread_per_connection_end;
}
#endif /* EMBEDDED_LIBRARY */

--- New file ---
+++ sql/scheduler.h	07/02/21 16:11:57
/* Copyright (C) 2007 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 */

/*
  Classes for the thread scheduler
*/

#ifdef USE_PRAGMA_INTERFACE
#pragma interface
#endif

class THD;

/* Functions used when manipulating threads */

class scheduler_functions
{
public:
  uint max_threads;
  bool (*init)(void);
  bool (*init_new_connection_thread)(void);
  void (*add_connection)(THD *thd);
  void (*post_kill_notification)(THD *thd);
  bool (*end_thread)(THD *thd, bool cache_thread);
  void (*end)(void);
  scheduler_functions();
};

enum scheduler_types
{
  SCHEDULER_ONE_THREAD_PER_CONNECTION=1,
  SCHEDULER_NO_THREADS,
  SCHEDULER_POOL_OF_THREADS
};

void one_thread_per_connection_scheduler(scheduler_functions* func);
void one_thread_scheduler(scheduler_functions* func);

enum pool_command_op
{
  NOT_IN_USE_OP= 0, NORMAL_OP= 1, CONNECT_OP, KILL_OP, DIE_OP
};

#define HAVE_POOL_OF_THREADS 0                  /* For easyer tests */
#define pool_of_threads_scheduler(A) one_thread_per_connection_scheduler(A)

class thd_scheduler
{};

--- New file ---
+++ sql/sql_connect.cc	07/02/21 16:11:57
/* Copyright (C) 2007 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 */


/*
  Functions to autenticate and handle reqests for a connection
*/

#include "mysql_priv.h"

#ifdef HAVE_OPENSSL
/*
  Without SSL the handshake consists of one packet. This packet
  has both client capabilites and scrambled password.
  With SSL the handshake might consist of two packets. If the first
  packet (client capabilities) has CLIENT_SSL flag set, we have to
  switch to SSL and read the second packet. The scrambled password
  is in the second packet and client_capabilites field will be ignored.
  Maybe it is better to accept flags other than CLIENT_SSL from the
  second packet?
*/
#define SSL_HANDSHAKE_SIZE      2
#define NORMAL_HANDSHAKE_SIZE   6
#define MIN_HANDSHAKE_SIZE      2
#else
#define MIN_HANDSHAKE_SIZE      6
#endif /* HAVE_OPENSSL */

#ifdef __WIN__
static void  test_signal(int sig_ptr)
{
#if !defined( DBUG_OFF)
  MessageBox(NULL,"Test signal","DBUG",MB_OK);
#endif
#if defined(OS2)
  fprintf(stderr, "Test signal %d\n", sig_ptr);
  fflush(stderr);
#endif
}
static void init_signals(void)
{
  int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;
  for (int i=0 ; i < 7 ; i++)
    signal( signals[i], test_signal) ;
}
#endif

/*
  Get structure for logging connection data for the current user
*/

#ifndef NO_EMBEDDED_ACCESS_CHECKS
static HASH hash_user_connections;

static int get_or_create_user_conn(THD *thd, const char *user,
				   const char *host,
				   USER_RESOURCES *mqh)
{
  int return_val= 0;
  uint temp_len, user_len;
  char temp_user[USER_HOST_BUFF_SIZE];
  struct  user_conn *uc;

  DBUG_ASSERT(user != 0);
  DBUG_ASSERT(host != 0);

  user_len= strlen(user);
  temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
  (void) pthread_mutex_lock(&LOCK_user_conn);
  if (!(uc = (struct  user_conn *) hash_search(&hash_user_connections,
					       (byte*) temp_user, temp_len)))
  {
    /* First connection for user; Create a user connection object */
    if (!(uc= ((struct user_conn*)
	       my_malloc(sizeof(struct user_conn) + temp_len+1,
			 MYF(MY_WME)))))
    {
      net_send_error(thd, 0, NullS);		// Out of memory
      return_val= 1;
      goto end;
    }
    uc->user=(char*) (uc+1);
    memcpy(uc->user,temp_user,temp_len+1);
    uc->host= uc->user + user_len +  1;
    uc->len= temp_len;
    uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
    uc->user_resources= *mqh;
    uc->intime= thd->thr_create_time;
    if (my_hash_insert(&hash_user_connections, (byte*) uc))
    {
      my_free((char*) uc,0);
      net_send_error(thd, 0, NullS);		// Out of memory
      return_val= 1;
      goto end;
    }
  }
  thd->user_connect=uc;
  uc->connections++;
end:
  (void) pthread_mutex_unlock(&LOCK_user_conn);
  return return_val;

}


/*
  check if user has already too many connections
  
  SYNOPSIS
  check_for_max_user_connections()
  thd			Thread handle
  uc			User connect object

  NOTES
    If check fails, we decrease user connection count, which means one
    shouldn't call decrease_user_connections() after this function.

  RETURN
    0	ok
    1	error
*/

int check_for_max_user_connections(THD *thd, USER_CONN *uc)
{
  int error=0;
  DBUG_ENTER("check_for_max_user_connections");

  (void) pthread_mutex_lock(&LOCK_user_conn);
  if (max_user_connections && !uc->user_resources.user_conn &&
      max_user_connections < (uint) uc->connections)
  {
    net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
    error=1;
    goto end;
  }
  time_out_user_resource_limits(thd, uc);
  if (uc->user_resources.user_conn &&
      uc->user_resources.user_conn < uc->connections)
  {
    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
                     "max_user_connections",
                     (long) uc->user_resources.user_conn);
    error= 1;
    goto end;
  }
  if (uc->user_resources.conn_per_hour &&
      uc->user_resources.conn_per_hour <= uc->conn_per_hour)
  {
    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
                     "max_connections_per_hour",
                     (long) uc->user_resources.conn_per_hour);
    error=1;
    goto end;
  }
  uc->conn_per_hour++;

  end:
  if (error)
    uc->connections--; // no need for decrease_user_connections() here
  (void) pthread_mutex_unlock(&LOCK_user_conn);
  DBUG_RETURN(error);
}


/*
  Decrease user connection count

  SYNOPSIS
    decrease_user_connections()
    uc			User connection object

  NOTES
    If there is a n user connection object for a connection
    (which only happens if 'max_user_connections' is defined or
    if someone has created a resource grant for a user), then
    the connection count is always incremented on connect.

    The user connect object is not freed if some users has
    'max connections per hour' defined as we need to be able to hold
    count over the lifetime of the connection.
*/

void decrease_user_connections(USER_CONN *uc)
{
  DBUG_ENTER("decrease_user_connections");
  (void) pthread_mutex_lock(&LOCK_user_conn);
  DBUG_ASSERT(uc->connections);
  if (!--uc->connections && !mqh_used)
  {
    /* Last connection for user; Delete it */
    (void) hash_delete(&hash_user_connections,(byte*) uc);
  }
  (void) pthread_mutex_unlock(&LOCK_user_conn);
  DBUG_VOID_RETURN;
}


/*
  Reset per-hour user resource limits when it has been more than
  an hour since they were last checked

  SYNOPSIS:
    time_out_user_resource_limits()
    thd			Thread handler
    uc			User connection details

  NOTE:
    This assumes that the LOCK_user_conn mutex has been acquired, so it is
    safe to test and modify members of the USER_CONN structure.
*/

void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
{
  time_t check_time = thd->start_time ?  thd->start_time : time(NULL);
  DBUG_ENTER("time_out_user_resource_limits");

  /* If more than a hour since last check, reset resource checking */
  if (check_time  - uc->intime >= 3600)
  {
    uc->questions=1;
    uc->updates=0;
    uc->conn_per_hour=0;
    uc->intime=check_time;
  }

  DBUG_VOID_RETURN;
}

/*
  Check if maximum queries per hour limit has been reached
  returns 0 if OK.
*/

bool check_mqh(THD *thd, uint check_command)
{
  bool error= 0;
  USER_CONN *uc=thd->user_connect;
  DBUG_ENTER("check_mqh");
  DBUG_ASSERT(uc != 0);

  (void) pthread_mutex_lock(&LOCK_user_conn);

  time_out_user_resource_limits(thd, uc);

  /* Check that we have not done too many questions / hour */
  if (uc->user_resources.questions &&
      uc->questions++ >= uc->user_resources.questions)
  {
    net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
                     (long) uc->user_resources.questions);
    error=1;
    goto end;
  }
  if (check_command < (uint) SQLCOM_END)
  {
    /* Check that we have not done too many updates / hour */
    if (uc->user_resources.updates &&
        (sql_command_flags[check_command] & CF_CHANGES_DATA) &&
	uc->updates++ >= uc->user_resources.updates)
    {
      net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
                       (long) uc->user_resources.updates);
      error=1;
      goto end;
    }
  }
end:
  (void) pthread_mutex_unlock(&LOCK_user_conn);
  DBUG_RETURN(error);
}

#endif /* NO_EMBEDDED_ACCESS_CHECKS */


/*
  Check if user exist and password supplied is correct. 

  SYNOPSIS
    check_user()
    thd          thread handle, thd->security_ctx->{host,user,ip} are used
    command      originator of the check: now check_user is called
                 during connect and change user procedures; used for 
                 logging.
    passwd       scrambled password received from client
    passwd_len   length of scrambled password
    db           database name to connect to, may be NULL
    check_count  dont know exactly

    Note, that host, user and passwd may point to communication buffer.
    Current implementation does not depend on that, but future changes
    should be done with this in mind; 'thd' is INOUT, all other params
    are 'IN'.

  RETURN VALUE
    0  OK; thd->security_ctx->user/master_access/priv_user/db_access and
       thd->db are updated; OK is sent to client;
   -1  access denied or handshake error; error is sent to client;
   >0  error, not sent to client
*/

int check_user(THD *thd, enum enum_server_command command, 
	       const char *passwd, uint passwd_len, const char *db,
	       bool check_count)
{
  DBUG_ENTER("check_user");
  
#ifdef NO_EMBEDDED_ACCESS_CHECKS
  thd->main_security_ctx.master_access= GLOBAL_ACLS;       // Full rights
  /* Change database if necessary */
  if (db && db[0])
  {
    /*
      thd->db is saved in caller and needs to be freed by caller if this
      function returns 0
    */
    thd->reset_db(NULL, 0);
    if (mysql_change_db(thd, db, FALSE))
    {
      /* Send the error to the client */
      net_send_error(thd);
      DBUG_RETURN(-1);
    }
  }
  send_ok(thd);
  DBUG_RETURN(0);
#else

  my_bool opt_secure_auth_local;
  pthread_mutex_lock(&LOCK_global_system_variables);
  opt_secure_auth_local= opt_secure_auth;
  pthread_mutex_unlock(&LOCK_global_system_variables);
  
  /*
    If the server is running in secure auth mode, short scrambles are 
    forbidden.
  */
  if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
  {
    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
    general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
    DBUG_RETURN(-1);
  }
  if (passwd_len != 0 &&
      passwd_len != SCRAMBLE_LENGTH &&
      passwd_len != SCRAMBLE_LENGTH_323)
    DBUG_RETURN(ER_HANDSHAKE_ERROR);

  /*
    Clear thd->db as it points to something, that will be freed when 
    connection is closed. We don't want to accidentally free a wrong pointer
    if connect failed. Also in case of 'CHANGE USER' failure, current
    database will be switched to 'no database selected'.
  */
  thd->reset_db(NULL, 0);

  USER_RESOURCES ur;
  int res= acl_getroot(thd, &ur, passwd, passwd_len);
#ifndef EMBEDDED_LIBRARY
  if (res == -1)
  {
    /*
      This happens when client (new) sends password scrambled with
      scramble(), but database holds old value (scrambled with
      scramble_323()). Here we please client to send scrambled_password
      in old format.
    */
    NET *net= &thd->net;
    if (opt_secure_auth_local)
    {
      net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
                       thd->main_security_ctx.user,
                       thd->main_security_ctx.host_or_ip);
      general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
                        thd->main_security_ctx.user,
                        thd->main_security_ctx.host_or_ip);
      DBUG_RETURN(-1);
    }
    /* We have to read very specific packet size */
    if (send_old_password_request(thd) ||
        my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
    {
      inc_host_errors(&thd->remote.sin_addr);
      DBUG_RETURN(ER_HANDSHAKE_ERROR);
    }
    /* Final attempt to check the user based on reply */
    /* So as passwd is short, errcode is always >= 0 */
    res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
  }
#endif /*EMBEDDED_LIBRARY*/
  /* here res is always >= 0 */
  if (res == 0)
  {
    if (!(thd->main_security_ctx.master_access &
          NO_ACCESS)) // authentication is OK
    {
      DBUG_PRINT("info",
                 ("Capabilities: %lu  packet_length: %ld  Host: '%s'  "
                  "Login user: '%s' Priv_user: '%s'  Using password: %s "
                  "Access: %lu  db: '%s'",
                  thd->client_capabilities,
                  thd->max_client_packet_length,
                  thd->main_security_ctx.host_or_ip,
                  thd->main_security_ctx.user,
                  thd->main_security_ctx.priv_user,
                  passwd_len ? "yes": "no",
                  thd->main_security_ctx.master_access,
                  (thd->db ? thd->db : "*none*")));

      if (check_count)
      {
        VOID(pthread_mutex_lock(&LOCK_thread_count));
        bool count_ok= thread_count <= max_connections + delayed_insert_threads
                       || (thd->main_security_ctx.master_access & SUPER_ACL);
        VOID(pthread_mutex_unlock(&LOCK_thread_count));
        if (!count_ok)
        {                                         // too many connections
          net_send_error(thd, ER_CON_COUNT_ERROR);
          DBUG_RETURN(-1);
        }
      }

      /*
        Log the command before authentication checks, so that the user can
        check the log for the tried login tried and also to detect
        break-in attempts.
      */
      general_log_print(thd, command,
                        (thd->main_security_ctx.priv_user ==
                         thd->main_security_ctx.user ?
                         (char*) "%s@%s on %s" :
                         (char*) "%s@%s as anonymous on %s"),
                        thd->main_security_ctx.user,
                        thd->main_security_ctx.host_or_ip,
                        db ? db : (char*) "");

      /*
        This is the default access rights for the current database.  It's
        set to 0 here because we don't have an active database yet (and we
        may not have an active database to set.
      */
      thd->main_security_ctx.db_access=0;

      /* Don't allow user to connect if he has done too many queries */
      if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
	   max_user_connections) &&
	  get_or_create_user_conn(thd,
            (opt_old_style_user_limits ? thd->main_security_ctx.user :
             thd->main_security_ctx.priv_user),
            (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
             thd->main_security_ctx.priv_host),
            &ur))
	DBUG_RETURN(-1);
      if (thd->user_connect &&
	  (thd->user_connect->user_resources.conn_per_hour ||
	   thd->user_connect->user_resources.user_conn ||
	   max_user_connections) &&
	  check_for_max_user_connections(thd, thd->user_connect))
	DBUG_RETURN(-1);

      /* Change database if necessary */
      if (db && db[0])
      {
        if (mysql_change_db(thd, db, FALSE))
        {
          /* Send error to the client */
          net_send_error(thd);
          if (thd->user_connect)
            decrease_user_connections(thd->user_connect);
          DBUG_RETURN(-1);
        }
      }
      send_ok(thd);
      thd->password= test(passwd_len);          // remember for error messages 
      /* Ready to handle queries */
      DBUG_RETURN(0);
    }
  }
  else if (res == 2) // client gave short hash, server has long hash
  {
    net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
    general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
    DBUG_RETURN(-1);
  }
  net_printf_error(thd, ER_ACCESS_DENIED_ERROR,
                   thd->main_security_ctx.user,
                   thd->main_security_ctx.host_or_ip,
                   passwd_len ? ER(ER_YES) : ER(ER_NO));
  general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
                    thd->main_security_ctx.user,
                    thd->main_security_ctx.host_or_ip,
                    passwd_len ? ER(ER_YES) : ER(ER_NO));
  DBUG_RETURN(-1);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}


/*
  Check for maximum allowable user connections, if the mysqld server is
  started with corresponding variable that is greater then 0.
*/

extern "C" byte *get_key_conn(user_conn *buff, uint *length,
			      my_bool not_used __attribute__((unused)))
{
  *length=buff->len;
  return (byte*) buff->user;
}


extern "C" void free_user(struct user_conn *uc)
{
  my_free((char*) uc,MYF(0));
}


void init_max_user_conn(void)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  (void) hash_init(&hash_user_connections,system_charset_info,max_connections,
		   0,0,
		   (hash_get_key) get_key_conn, (hash_free_key) free_user,
		   0);
#endif
}


void free_max_user_conn(void)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  hash_free(&hash_user_connections);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}


void reset_mqh(LEX_USER *lu, bool get_them= 0)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
  (void) pthread_mutex_lock(&LOCK_user_conn);
  if (lu)  // for GRANT
  {
    USER_CONN *uc;
    uint temp_len=lu->user.length+lu->host.length+2;
    char temp_user[USER_HOST_BUFF_SIZE];

    memcpy(temp_user,lu->user.str,lu->user.length);
    memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
    temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
    if ((uc = (struct  user_conn *) hash_search(&hash_user_connections,
						(byte*) temp_user, temp_len)))
    {
      uc->questions=0;
      get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
      uc->updates=0;
      uc->conn_per_hour=0;
    }
  }
  else
  {
    /* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
    for (uint idx=0;idx < hash_user_connections.records; idx++)
    {
      USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
						      idx);
      if (get_them)
	get_mqh(uc->user,uc->host,uc);
      uc->questions=0;
      uc->updates=0;
      uc->conn_per_hour=0;
    }
  }
  (void) pthread_mutex_unlock(&LOCK_user_conn);
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}


void thd_init_client_charset(THD *thd, uint cs_number)
{
  /*
   Use server character set and collation if
   - opt_character_set_client_handshake is not set
   - client has not specified a character set
   - client character set is the same as the servers
   - client character set doesn't exists in server
  */
  if (!opt_character_set_client_handshake ||
      !(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
      !my_strcasecmp(&my_charset_latin1,
                     global_system_variables.character_set_client->name,
                     thd->variables.character_set_client->name))
  {
    thd->variables.character_set_client=
      global_system_variables.character_set_client;
    thd->variables.collation_connection=
      global_system_variables.collation_connection;
    thd->variables.character_set_results=
      global_system_variables.character_set_results;
  }
  else
  {
    thd->variables.character_set_results=
      thd->variables.collation_connection= 
      thd->variables.character_set_client;
  }
}


/*
  Initialize connection threads
*/

bool init_new_connection_handler_thread()
{
  pthread_detach_this_thread();
#if defined(__WIN__)
  init_signals();
#else
  /* Win32 calls this in pthread_create */
  if (my_thread_init())
    return 1;
#endif /* __WIN__ */
  return 0;
}

/*
  Perform handshake, authorize client and update thd ACL variables.

  SYNOPSIS
    check_connection()
    thd  thread handle

  RETURN
     0  success, OK is sent to user, thd is updated.
    -1  error, which is sent to user
   > 0  error code (not sent to user)
*/

#ifndef EMBEDDED_LIBRARY
static int check_connection(THD *thd)
{
  uint connect_errors= 0;
  NET *net= &thd->net;
  ulong pkt_len= 0;
  char *end;

  DBUG_PRINT("info",
             ("New connection received on %s", vio_description(net->vio)));
#ifdef SIGNAL_WITH_VIO_CLOSE
  thd->set_active_vio(net->vio);
#endif

  if (!thd->main_security_ctx.host)         // If TCP/IP connection
  {
    char ip[30];

    if (vio_peer_addr(net->vio, ip, &thd->peer_port))
      return (ER_BAD_HOST_ERROR);
    if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0))))
      return (ER_OUT_OF_RESOURCES);
    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
    vio_in_addr(net->vio,&thd->remote.sin_addr);
    if (!(specialflag & SPECIAL_NO_RESOLVE))
    {
      vio_in_addr(net->vio,&thd->remote.sin_addr);
      thd->main_security_ctx.host=
        ip_to_hostname(&thd->remote.sin_addr, &connect_errors);
      /* Cut very long hostnames to avoid possible overflows */
      if (thd->main_security_ctx.host)
      {
        if (thd->main_security_ctx.host != my_localhost)
          thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host),
                                          HOSTNAME_LENGTH)]= 0;
        thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
      }
      if (connect_errors > max_connect_errors)
        return(ER_HOST_IS_BLOCKED);
    }
    DBUG_PRINT("info",("Host: %s  ip: %s",
		       (thd->main_security_ctx.host ?
                        thd->main_security_ctx.host : "unknown host"),
		       (thd->main_security_ctx.ip ?
                        thd->main_security_ctx.ip : "unknown ip")));
    if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
      return(ER_HOST_NOT_PRIVILEGED);
  }
  else /* Hostname given means that the connection was on a socket */
  {
    DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host));
    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
    thd->main_security_ctx.ip= 0;
    /* Reset sin_addr */
    bzero((char*) &thd->remote, sizeof(thd->remote));
  }
  vio_keepalive(net->vio, TRUE);
  {
    /* buff[] needs to big enough to hold the server_version variable */
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
    ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
			  CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);

    if (opt_using_transactions)
      client_flags|=CLIENT_TRANSACTIONS;
#ifdef HAVE_COMPRESS
    client_flags |= CLIENT_COMPRESS;
#endif /* HAVE_COMPRESS */
#ifdef HAVE_OPENSSL
    if (ssl_acceptor_fd)
      client_flags |= CLIENT_SSL;       /* Wow, SSL is available! */
#endif /* HAVE_OPENSSL */

    end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
    int4store((uchar*) end, thd->thread_id);
    end+= 4;
    /*
      So as check_connection is the only entry point to authorization
      procedure, scramble is set here. This gives us new scramble for
      each handshake.
    */
    create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
    /*
      Old clients does not understand long scrambles, but can ignore packet
      tail: that's why first part of the scramble is placed here, and second
      part at the end of packet.
    */
    end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
   
    int2store(end, client_flags);
    /* write server characteristics: up to 16 bytes allowed */
    end[2]=(char) default_charset_info->number;
    int2store(end+3, thd->server_status);
    bzero(end+5, 13);
    end+= 18;
    /* write scramble tail */
    end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
                 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;

    /* At this point we write connection message and read reply */
    if (net_write_command(net, (uchar) protocol_version, "", 0, buff,
			  (uint) (end-buff)) ||
	(pkt_len= my_net_read(net)) == packet_error ||
	pkt_len < MIN_HANDSHAKE_SIZE)
    {
      inc_host_errors(&thd->remote.sin_addr);
      return(ER_HANDSHAKE_ERROR);
    }
  }
#ifdef _CUSTOMCONFIG_
#include "_cust_sql_parse.h"
#endif
  if (connect_errors)
    reset_host_errors(&thd->remote.sin_addr);
  if (thd->packet.alloc(thd->variables.net_buffer_length))
    return(ER_OUT_OF_RESOURCES);

  thd->client_capabilities=uint2korr(net->read_pos);
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
  {
    thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
    thd->max_client_packet_length= uint4korr(net->read_pos+4);
    DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
    thd_init_client_charset(thd, (uint) net->read_pos[8]);
    thd->update_charset();
    end= (char*) net->read_pos+32;
  }
  else
  {
    thd->max_client_packet_length= uint3korr(net->read_pos+2);
    end= (char*) net->read_pos+5;
  }

  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
#ifdef HAVE_OPENSSL
  DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
  if (thd->client_capabilities & CLIENT_SSL)
  {
    /* Do the SSL layering. */
    if (!ssl_acceptor_fd)
    {
      inc_host_errors(&thd->remote.sin_addr);
      return(ER_HANDSHAKE_ERROR);
    }
    DBUG_PRINT("info", ("IO layer change in progress..."));
    if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
    {
      DBUG_PRINT("error", ("Failed to accept new SSL connection"));
      inc_host_errors(&thd->remote.sin_addr);
      return(ER_HANDSHAKE_ERROR);
    }
    DBUG_PRINT("info", ("Reading user information over SSL layer"));
    if ((pkt_len= my_net_read(net)) == packet_error ||
	pkt_len < NORMAL_HANDSHAKE_SIZE)
    {
      DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
			   pkt_len));
      inc_host_errors(&thd->remote.sin_addr);
      return(ER_HANDSHAKE_ERROR);
    }
  }
#endif /* HAVE_OPENSSL */

  if (end >= (char*) net->read_pos+ pkt_len +2)
  {
    inc_host_errors(&thd->remote.sin_addr);
    return(ER_HANDSHAKE_ERROR);
  }

  if (thd->client_capabilities & CLIENT_INTERACTIVE)
    thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
  if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
      opt_using_transactions)
    net->return_status= &thd->server_status;

  char *user= end;
  char *passwd= strend(user)+1;
  uint user_len= passwd - user - 1;
  char *db= passwd;
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
  char user_buff[USERNAME_LENGTH + 1];	// buffer to store user in utf8
  uint dummy_errors;

  /*
    Old clients send null-terminated string as password; new clients send
    the size (1 byte) + string (not null-terminated). Hence in case of empty
    password both send '\0'.

    This strlen() can't be easily deleted without changing protocol.
  */
  uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
    *passwd++ : strlen(passwd);
  db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
    db + passwd_len + 1 : 0;
  /* strlen() can't be easily deleted without changing protocol */
  uint db_len= db ? strlen(db) : 0;

  if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
  {
    inc_host_errors(&thd->remote.sin_addr);
    return ER_HANDSHAKE_ERROR;
  }

  /* Since 4.1 all database names are stored in utf8 */
  if (db)
  {
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
                             system_charset_info,
                             db, db_len,
                             thd->charset(), &dummy_errors)]= 0;
    db= db_buff;
  }

  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
                                       system_charset_info, user, user_len,
                                       thd->charset(), &dummy_errors)]= '\0';
  user= user_buff;

  /* If username starts and ends in "'", chop them off */
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
  {
    user[user_len-1]= 0;
    user++;
    user_len-= 2;
  }

  if (thd->main_security_ctx.user)
    x_free(thd->main_security_ctx.user);
  if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0))))
    return (ER_OUT_OF_RESOURCES);
  return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
}


/*
  Setup thread to be used with the current thread

  SYNOPSIS
    bool setup_connection_thread_globals()
    thd    Thread/connection handler

  RETURN
    0   ok
    1   Error (out of memory)
        In this case we will close the connection and increment status
*/

bool setup_connection_thread_globals(THD *thd)
{
  if (thd->store_globals())
  {
    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
    statistic_increment(aborted_connects,&LOCK_status);
    thread_scheduler.end_thread(thd, 0);
    return 1;                                   // Error
  }
  return 0;
}


/*
  Autenticate user, with error reporting

  SYNOPSIS
   login_connection()
   thd        Thread handler

  NOTES
    Connection is not closed in case of errors

  RETURN
    0    ok
    1    error
*/


bool login_connection(THD *thd)
{
  int error;
  NET *net= &thd->net;
  Security_context *sctx= thd->security_ctx;
  DBUG_ENTER("login_connection");
  DBUG_PRINT("info", ("handle_one_connection called by thread %lu",
                      thd->thread_id));

  net->no_send_error= 0;
  if ((error=check_connection(thd)))
  {						// Wrong permissions
    if (error > 0)
      net_printf_error(thd, error, sctx->host_or_ip);
#ifdef __NT__
    if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
      my_sleep(1000);				/* must wait after eof() */
#endif
    statistic_increment(aborted_connects,&LOCK_status);
    DBUG_RETURN(1);
  }
  DBUG_RETURN(0);
}


/*
  Close an established connection

  NOTES
    This mainly updates status variables
*/

void end_connection(THD *thd)
{
  NET *net= &thd->net;
  if (thd->user_connect)
    decrease_user_connections(thd->user_connect);
  if (net->error && net->vio != 0 && net->report_error)
  {
    Security_context *sctx= thd->security_ctx;
    if (!thd->killed && thd->variables.log_warnings > 1)
      sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
                        thd->thread_id,(thd->db ? thd->db : "unconnected"),
                        sctx->user ? sctx->user : "unauthenticated",
                        sctx->host_or_ip,
                        (net->last_errno ? ER(net->last_errno) :
                         ER(ER_UNKNOWN_ERROR)));
    net_send_error(thd, net->last_errno, NullS);
    statistic_increment(aborted_threads,&LOCK_status);
  }
  else if (thd->killed)
    statistic_increment(aborted_threads,&LOCK_status);
}


/*
  Initialize THD to handle queries
*/

void prepare_new_connection_state(THD* thd)
{
  Security_context *sctx= thd->security_ctx;

#ifdef __NETWARE__
  netware_reg_user(sctx->ip, sctx->user, "MySQL");
#endif

  if (thd->variables.max_join_size == HA_POS_ERROR)
    thd->options |= OPTION_BIG_SELECTS;
  if (thd->client_capabilities & CLIENT_COMPRESS)
    thd->net.compress=1;				// Use compression

  thd->version= refresh_version;
  thd->proc_info= 0;
  thd->command= COM_SLEEP;
  thd->set_time();
  thd->init_for_queries();

  if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL))
  {
    execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
    if (thd->query_error)
    {
      thd->killed= THD::KILL_CONNECTION;
      sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
                        thd->thread_id,(thd->db ? thd->db : "unconnected"),
                        sctx->user ? sctx->user : "unauthenticated",
                        sctx->host_or_ip, "init_connect command failed");
      sql_print_warning("%s", thd->net.last_error);
    }
    thd->proc_info=0;
    thd->set_time();
    thd->init_for_queries();
  }
}


/*
  Thread handler for a connection

  SYNOPSIS
    handle_one_connection()
    arg		Connection object (THD)

  IMPLEMENTATION
    This function (normally) does the following:
    - Initialize thread
    - Initialize THD to be used with this thread
    - Authenticate user
    - Execute all queries sent on the connection
    - Take connection down
    - End thread  / Handle next connection using thread from thread cache
*/

pthread_handler_t handle_one_connection(void *arg)
{
  THD *thd= (THD*) arg;
  uint launch_time  =
    (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time);

  if (thread_scheduler.init_new_connection_thread())
  {
    close_connection(thd, ER_OUT_OF_RESOURCES, 1);
    statistic_increment(aborted_connects,&LOCK_status);
    thread_scheduler.end_thread(thd,0);
    return 0;
  }
  if (launch_time >= slow_launch_time)
    statistic_increment(slow_launch_threads,&LOCK_status);

  /*
    handle_one_connection() is normally the only way a thread would
    start and would always be on the very high end of the stack ,
    therefore, the thread stack always starts at the address of the
    first local variable of handle_one_connection, which is thd. We
    need to know the start of the stack so that we could check for
    stack overruns.
  */
  thd->thread_stack= (char*) &thd;
  if (setup_connection_thread_globals(thd))
    return 0;

  for (;;)
  {
    NET *net= &thd->net;

    /* Use "connect_timeout" value during connection phase */
    net_set_read_timeout(net, connect_timeout);
    net_set_write_timeout(net, connect_timeout);

    if (login_connection(thd))
      goto end_thread;

    prepare_new_connection_state(thd);

    /* Connect completed, set read/write timeouts back to default */
    net_set_read_timeout(net, thd->variables.net_read_timeout);
    net_set_write_timeout(net, thd->variables.net_write_timeout);

    while (!net->error && net->vio != 0 &&
           !(thd->killed == THD::KILL_CONNECTION))
    {
      net->no_send_error= 0;
      if (do_command(thd))
	break;
    }
    end_connection(thd);
   
end_thread:
    close_connection(thd, 0, 1);
    if (thread_scheduler.end_thread(thd,1))
      return 0;                                 // Probably no-threads

    /*
      If end_thread() returns, we are either running with
      thread-handler=no-threads or this thread has been schedule to
      handle the next connection.
    */
    thd= current_thd;
    thd->thread_stack= (char*) &thd;
  }
}
#endif /* EMBEDDED_LIBRARY */


--- 1.108/libmysqld/Makefile.am	2007-01-12 17:11:45 +02:00
+++ 1.109/libmysqld/Makefile.am	2007-02-21 16:11:55 +02:00
@@ -59,7 +59,8 @@
 	sql_load.cc discover.cc sql_locale.cc \
 	sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
 	sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
-	sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc sql_parse.cc \
+	sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc \
+	scheduler.cc sql_connect.cc sql_parse.cc \
 	sql_prepare.cc sql_derived.cc sql_rename.cc \
 	sql_select.cc sql_do.cc sql_show.cc set_var.cc \
 	sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \

--- 1.130/libmysqld/lib_sql.cc	2007-02-13 01:00:20 +02:00
+++ 1.131/libmysqld/lib_sql.cc	2007-02-21 16:11:55 +02:00
@@ -34,11 +34,6 @@
 #include "../sql/mysqld.cc"
 #endif
 
-int check_user(THD *thd, enum enum_server_command command, 
-	       const char *passwd, uint passwd_len, const char *db,
-	       bool check_count);
-void thd_init_client_charset(THD *thd, uint cs_number);
-
 C_MODE_START
 
 #include <mysql.h>
@@ -585,10 +580,7 @@
     goto err;
   }
 
-  thd->mysys_var= my_thread_var;
-  thd->dbug_thread_id= my_thread_id();
-
-/* TODO - add init_connect command execution */
+  /* TODO - add init_connect command execution */
 
   if (thd->variables.max_join_size == HA_POS_ERROR)
     thd->options |= OPTION_BIG_SELECTS;

--- 1.267/client/mysqltest.c	2007-01-29 01:47:29 +02:00
+++ 1.268/client/mysqltest.c	2007-02-21 16:11:55 +02:00
@@ -407,7 +407,8 @@
 TYPELIB command_typelib= {array_elements(command_names),"",
 			  command_names, 0};
 
-DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
+static DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
+static DYNAMIC_STRING global_ds_warnings, global_eval_query;
 
 void die(const char *fmt, ...)
   ATTRIBUTE_FORMAT(printf, 1, 2);
@@ -781,6 +782,9 @@
   dynstr_free(&ds_res);
   dynstr_free(&ds_progress);
   dynstr_free(&ds_warning_messages);
+  dynstr_free(&global_ds_warnings);
+  dynstr_free(&global_eval_query);
+
   free_all_replace();
   my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
   free_defaults(default_argv);
@@ -1865,7 +1869,7 @@
     die("You must write a 4 digit octal number for mode");
 
   DBUG_PRINT("info", ("chmod %o %s", (uint)mode, ds_file.str));
-  handle_command_error(command, chmod(ds_file.str, mode));
+  handle_command_error(command, chmod(ds_file.str, (mode_t) mode));
   dynstr_free(&ds_mode);
   dynstr_free(&ds_file);
   DBUG_VOID_RETURN;
@@ -5191,8 +5195,6 @@
   MYSQL *mysql= &cn->mysql;
   DYNAMIC_STRING *ds;
   DYNAMIC_STRING ds_result;
-  DYNAMIC_STRING ds_warnings;
-  DYNAMIC_STRING eval_query;
   char *query;
   int query_len;
   my_bool view_created= 0, sp_created= 0;
@@ -5200,7 +5202,7 @@
                            (flags & QUERY_REAP_FLAG));
   DBUG_ENTER("run_query");
 
-  init_dynamic_string(&ds_warnings, NULL, 0, 256);
+  init_dynamic_string(&global_ds_warnings, NULL, 0, 256);
 
   /* Scan for warning before sendign to server */
   scan_command_for_warnings(command);
@@ -5210,10 +5212,10 @@
   */
   if (command->type == Q_EVAL)
   {
-    init_dynamic_string(&eval_query, "", command->query_len+256, 1024);
-    do_eval(&eval_query, command->query, command->end, FALSE);
-    query = eval_query.str;
-    query_len = eval_query.length;
+    init_dynamic_string(&global_eval_query, "", command->query_len+256, 1024);
+    do_eval(&global_eval_query, command->query, command->end, FALSE);
+    query = global_eval_query.str;
+    query_len = global_eval_query.length;
   }
   else
   {
@@ -5285,7 +5287,7 @@
         Collect warnings from create of the view that should otherwise
         have been produced when the SELECT was executed
       */
-      append_warnings(&ds_warnings, cur_con->util_mysql);
+      append_warnings(&global_ds_warnings, cur_con->util_mysql);
     }
 
     dynstr_free(&query_str);
@@ -5344,10 +5346,10 @@
   if (ps_protocol_enabled &&
       complete_query &&
       match_re(&ps_re, query))
-    run_query_stmt(mysql, command, query, query_len, ds, &ds_warnings);
+    run_query_stmt(mysql, command, query, query_len, ds, &global_ds_warnings);
   else
     run_query_normal(cn, command, flags, query, query_len,
-		     ds, &ds_warnings);
+		     ds, &global_ds_warnings);
 
   if (sp_created)
   {
@@ -5371,11 +5373,11 @@
     check_require(ds, command->require_file);
   }
 
-  dynstr_free(&ds_warnings);
+  dynstr_free(&global_ds_warnings);
   if (ds == &ds_result)
     dynstr_free(&ds_result);
   if (command->type == Q_EVAL)
-    dynstr_free(&eval_query);
+    dynstr_free(&global_eval_query);
   DBUG_VOID_RETURN;
 }
 

--- 1.41/server-tools/instance-manager/guardian.cc	2007-01-27 03:46:39 +02:00
+++ 1.42/server-tools/instance-manager/guardian.cc	2007-02-21 16:11:56 +02:00
@@ -212,8 +212,8 @@
       return;
 
     case Instance::CRASHED:    /* just regular restarts */
-      if (current_time - instance->last_checked <=
-          Options::Main::monitoring_interval)
+      if ((ulong) (current_time - instance->last_checked) <=
+          (ulong) Options::Main::monitoring_interval)
         return;
 
       if (instance->restart_counter < restart_retry)

--- 1.72/sql/repl_failsafe.cc	2007-02-06 16:12:12 +02:00
+++ 1.73/sql/repl_failsafe.cc	2007-02-21 16:11:56 +02:00
@@ -73,22 +73,18 @@
   thd->net.read_timeout = slave_net_timeout;
   thd->max_client_packet_length=thd->net.max_packet;
   pthread_mutex_lock(&LOCK_thread_count);
-  thd->thread_id = thread_id++;
+  thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
   pthread_mutex_unlock(&LOCK_thread_count);
 
   if (init_thr_lock() || thd->store_globals())
   {
+    /* purecov: begin inspected */
     close_connection(thd, ER_OUT_OF_RESOURCES, 1); // is this needed?
     statistic_increment(aborted_connects,&LOCK_status);
-    end_thread(thd,0);
+    one_thread_per_connection_end(thd,0);
     DBUG_RETURN(-1);
+    /* purecov: end */
   }
-
-#if !defined(__WIN__) && !defined(__NETWARE__)
-  sigset_t set;
-  VOID(sigemptyset(&set));			// Get mask in use
-  VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
-#endif
 
   thd->mem_root->free= thd->mem_root->used= 0;
   if (thd->variables.max_join_size == HA_POS_ERROR)

--- 1.28/extra/yassl/src/ssl.cpp	2007-01-29 18:54:36 +02:00
+++ 1.29/extra/yassl/src/ssl.cpp	2007-02-21 16:11:55 +02:00
@@ -39,6 +39,7 @@
 #include "coding.hpp"           // HexDecoder
 #include "helpers.hpp"          // for placement new hack
 #include <stdio.h>
+#include <assert.h>
 
 #ifdef _WIN32
     #include <windows.h>    // FindFirstFile etc..
@@ -57,6 +58,9 @@
 {
     if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
         return SSL_BAD_FILETYPE;
+
+    if (file == NULL || !file[0])
+      return SSL_BAD_FILE;
 
     FILE* input = fopen(file, "rb");
     if (!input)

--- 1.37/vio/viosslfactories.c	2007-02-06 21:26:03 +02:00
+++ 1.38/vio/viosslfactories.c	2007-02-21 16:11:57 +02:00
@@ -234,6 +234,14 @@
   DH *dh;
   struct st_VioSSLFd *ssl_fd;
   DBUG_ENTER("new_VioSSLFd");
+  DBUG_PRINT("enter",
+             ("key_file: '%s'  cert_file: '%s'  ca_file: '%s'  ca_path: '%s'  "
+              "cipher: '%s'",
+              key_file ? key_file : "NULL",
+              cert_file ? cert_file : "NULL",
+              ca_file ? ca_file : "NULL",
+              ca_path ? ca_path : "NULL",
+              cipher ? cipher : "NULL"));
 
   check_ssl_init();
 
Thread
bk commit into 5.1 tree (monty:1.2436)monty21 Feb