diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 7fc7cc4edf1..f99a2c655d2 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -16,7 +16,7 @@
 
 /* Create a MyISAM table */
 
-#include "fulltext.h"
+#include "ftdefs.h"
 #include "sp_defs.h"
 
 #if defined(MSDOS) || defined(__WIN__)
@@ -41,7 +41,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
   File dfile,file;
   int errpos,save_errno;
   myf create_flag;
-  uint fields,length,max_key_length,packed,pointer,
+  uint fields,length,max_key_length,packed,pointer,real_length_diff,
        key_length,info_length,key_segs,options,min_key_length_skip,
        base_pos,varchar_count,long_varchar_count,varchar_length,
        max_key_block_length,unique_key_parts,fulltext_keys,offset;
@@ -238,7 +238,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
   {
 
     share.state.key_root[i]= HA_OFFSET_ERROR;
-    min_key_length_skip=length=0;
+    min_key_length_skip=length=real_length_diff=0;
     key_length=pointer;
     if (keydef->flag & HA_SPATIAL)
     {
@@ -297,6 +297,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
       key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
       length++;                              /* At least one length byte */
       min_key_length_skip+=HA_FT_MAXBYTELEN;
+      real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
     }
     else
     {
@@ -397,7 +398,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
 	key_segs)
       share.state.rec_per_key_part[key_segs-1]=1L;
     length+=key_length;
-    keydef->block_length= MI_BLOCK_SIZE(length,pointer,MI_MAX_KEYPTR_SIZE);
+    keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
+                                        pointer,MI_MAX_KEYPTR_SIZE);
     if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
         length >= MI_MAX_KEY_BUFF)
     {
diff --git a/mysql-test/mysql_test_run.c b/mysql-test/mysql_test_run.c
deleted file mode 100644
index 6f388fc4a45..00000000000
--- a/mysql-test/mysql_test_run.c
+++ /dev/null
@@ -1,1728 +0,0 @@
-/*
-  Copyright (c) 2002, 2003 Novell, Inc. All Rights Reserved. 
-
-  This program is free software; you can redistribute it and/or modify 
-  it under the terms of the GNU General Public License as published by 
-  the Free Software Foundation; either version 2 of the License, or 
-  (at your option) any later version. 
-
-  This program is distributed in the hope that it will be useful, 
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-  GNU General Public License for more details. 
-
-  You should have received a copy of the GNU General Public License 
-  along with this program; if not, write to the Free Software 
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/ 
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#ifndef __WIN__
-#include <dirent.h>
-#endif 
-#include <string.h>
-#ifdef __NETWARE__
-#include <screen.h>
-#include <nks/vm.h>
-#endif
-#include <ctype.h>
-#include <sys/stat.h>
-#ifndef __WIN__
-#include <unistd.h>
-#endif
-#include <fcntl.h>
-#ifdef __NETWARE__
-#include <sys/mode.h>
-#endif
-#ifdef __WIN__
-#include <Shlwapi.h>
-#include <direct.h>
-#endif
-
-#include "my_manage.h"
-
-/******************************************************************************
-
-  macros
-  
-******************************************************************************/
-
-#define HEADER  "TEST                                           RESULT  \n"
-#define DASH    "-------------------------------------------------------\n"
-
-#define NW_TEST_SUFFIX    ".nw-test"
-#define NW_RESULT_SUFFIX  ".nw-result"
-#define TEST_SUFFIX		    ".test"
-#define RESULT_SUFFIX	    ".result"
-#define REJECT_SUFFIX	    ".reject"
-#define OUT_SUFFIX		    ".out"
-#define ERR_SUFFIX		    ".err"
-
-const char *TEST_PASS = "[ pass ]";
-const char *TEST_SKIP	= "[ skip ]";
-const char *TEST_FAIL = "[ fail ]";
-const char *TEST_BAD = "[ bad  ]";
-const char *TEST_IGNORE = "[ignore]";
-
-/******************************************************************************
-
-  global variables
-  
-******************************************************************************/
-#ifdef __NETWARE__
-static char base_dir[PATH_MAX]   = "sys:/mysql";
-#else
-static char base_dir[PATH_MAX]   = "..";
-#endif
-static char db[PATH_MAX]         = "test";
-static char user[PATH_MAX]       = "root";
-static char password[PATH_MAX]   = "";
-
-int master_port           = 9306;
-int slave_port            = 9307;
-
-#if !defined(__NETWARE__) && !defined(__WIN__)
-static char master_socket[PATH_MAX] = "./var/tmp/master.sock";
-static char slave_socket[PATH_MAX] = "./var/tmp/slave.sock";
-#endif
-
-// comma delimited list of tests to skip or empty string
-#ifndef __WIN__
-static char skip_test[PATH_MAX]  = " lowercase_table3 , system_mysql_db_fix ";
-#else
-/*
-  The most ignore testes contain the calls of system command
-*/
-#define MAX_COUNT_TESTES 1024
-/*
-  lowercase_table3 is disabled by Gerg
-  system_mysql_db_fix  is disabled by Gerg
-  sp contains a command system
-  rpl_EE_error contains a command system
-  rpl_loaddatalocal contains a command system
-  ndb_autodiscover contains a command system
-  rpl_rotate_logs contains a command system
-  repair contains a command system
-  rpl_trunc_binlog contains a command system
-  mysqldump contains a command system
-  rpl000001 makes non-exit loop...temporary skiped
-*/
-static char skip_test[PATH_MAX]  = " lowercase_table3 , system_mysql_db_fix , sp , rpl_EE_error , rpl_loaddatalocal , ndb_autodiscover , rpl_rotate_logs , repair , rpl_trunc_binlog , mysqldump , rpl000001 ";
-#endif
-static char ignore_test[PATH_MAX]  = "";
-
-static char bin_dir[PATH_MAX];
-static char mysql_test_dir[PATH_MAX];
-static char test_dir[PATH_MAX];
-static char mysql_tmp_dir[PATH_MAX];
-static char result_dir[PATH_MAX];
-static char master_dir[PATH_MAX];
-static char slave_dir[PATH_MAX];
-static char lang_dir[PATH_MAX];
-static char char_dir[PATH_MAX];
-
-static char mysqladmin_file[PATH_MAX];
-static char mysqld_file[PATH_MAX];
-static char mysqltest_file[PATH_MAX];
-#ifndef __WIN__
-static char master_pid[PATH_MAX];
-static char slave_pid[PATH_MAX];
-static char sh_file[PATH_MAX] = "/bin/sh";
-#else
-static HANDLE master_pid;
-static HANDLE slave_pid;
-#endif
-
-static char master_opt[PATH_MAX] = "";
-static char slave_opt[PATH_MAX]  = "";
-
-static char slave_master_info[PATH_MAX]  = "";
-
-static char master_init_script[PATH_MAX]  = "";
-static char slave_init_script[PATH_MAX]  = "";
-
-// OpenSSL
-static char ca_cert[PATH_MAX];
-static char server_cert[PATH_MAX];
-static char server_key[PATH_MAX];
-static char client_cert[PATH_MAX];
-static char client_key[PATH_MAX];
-
-int total_skip    = 0;
-int total_pass    = 0;
-int total_fail    = 0;
-int total_test    = 0;
-
-int total_ignore  = 0;
-
-int use_openssl     = FALSE;
-int master_running  = FALSE;
-int slave_running   = FALSE;
-int skip_slave      = TRUE;
-int single_test     = TRUE;
-
-int restarts  = 0;
-
-FILE *log_fd  = NULL;
-
-/******************************************************************************
-
-  functions
-  
-******************************************************************************/
-
-/******************************************************************************
-
-  prototypes
-  
-******************************************************************************/
-
-void report_stats();
-void install_db(char *);
-void mysql_install_db();
-void start_master();
-void start_slave();
-void mysql_start();
-void stop_slave();
-void stop_master();
-void mysql_stop();
-void mysql_restart();
-int read_option(char *, char *);
-void run_test(char *);
-void setup(char *);
-void vlog(const char *, va_list);
-void mlog(const char *, ...);
-void log_info(const char *, ...);
-void log_error(const char *, ...);
-void log_errno(const char *, ...);
-void die(const char *);
-char *str_tok(char *string, const char *delim);
-#ifndef __WIN__
-void run_init_script(const char *script_name);
-#endif
-/******************************************************************************
-
-  report_stats()
-  
-  Report the gathered statistics.
-
-******************************************************************************/
-void report_stats()
-{
-  if (total_fail == 0)
-  {
-    mlog("\nAll %d test(s) were successful.\n", total_test);
-  }
-  else
-  {
-    double percent = ((double)total_pass / total_test) * 100;
-    
-    mlog("\nFailed %u/%u test(s), %.02f%% successful.\n",
-      total_fail, total_test, percent);
-	mlog("\nThe .out and .err files in %s may give you some\n", result_dir);
-	mlog("hint of what when wrong.\n");
-	mlog("\nIf you want to report this error, please first read the documentation\n");
-	mlog("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n");
-  }
-}
-
-/******************************************************************************
-
-  install_db()
-  
-  Install the a database.
-
-******************************************************************************/
-void install_db(char *datadir)
-{
-  arg_list_t al;
-  int err;
-  char input[PATH_MAX];
-  char output[PATH_MAX];
-  char error[PATH_MAX];
-
-  // input file
-#ifdef __NETWARE__  
-  snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir);
-#else
-  snprintf(input, PATH_MAX, "%s/mysql-test/init_db.sql", base_dir);
-#endif  
-  snprintf(output, PATH_MAX, "%s/install.out", datadir);
-  snprintf(error, PATH_MAX, "%s/install.err", datadir);
-  
-  // args
-  init_args(&al);
-  add_arg(&al, mysqld_file);
-  add_arg(&al, "--no-defaults");
-  add_arg(&al, "--bootstrap");
-  add_arg(&al, "--skip-grant-tables");
-  add_arg(&al, "--basedir=%s", base_dir);
-  add_arg(&al, "--datadir=%s", datadir);
-  add_arg(&al, "--skip-innodb");
-  add_arg(&al, "--skip-bdb");
-#ifndef __NETWARE__
-  add_arg(&al, "--character-sets-dir=%s", char_dir);
-  add_arg(&al, "--language=%s", lang_dir);
-#endif  
-
-  // spawn
-  if ((err = spawn(mysqld_file, &al, TRUE, input, output, error, NULL)) != 0)
-  {
-    die("Unable to create database.");
-  }
-  
-  // free args
-  free_args(&al);
-}
-
-/******************************************************************************
-
-  mysql_install_db()
-  
-  Install the test databases.
-
-******************************************************************************/
-void mysql_install_db()
-{
-  char temp[PATH_MAX];
-  
-  // var directory
-  snprintf(temp, PATH_MAX, "%s/var", mysql_test_dir);
-  
-  // clean up old direcotry
-  del_tree(temp);
-  
-  // create var directory
-#ifndef __WIN__
-  mkdir(temp, S_IRWXU);
-  // create subdirectories
-  mlog("Creating test-suite folders...\n");
-  snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-  snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir);
-  mkdir(temp, S_IRWXU);
-#else
-  mkdir(temp);
-  // create subdirectories
-  mlog("Creating test-suite folders...\n");
-  snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir);
-  mkdir(temp);
-  snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir);
-  mkdir(temp);
-#endif
-
-  // install databases
-  mlog("Creating test databases for master... \n");
-  install_db(master_dir);
-  mlog("Creating test databases for slave... \n");
-  install_db(slave_dir);
-}
-
-/******************************************************************************
-
-  start_master()
-  
-  Start the master server.
-
-******************************************************************************/
-void start_master()
-{
-  arg_list_t al;
-  int err;
-  char master_out[PATH_MAX];
-  char master_err[PATH_MAX];
-//  char temp[PATH_MAX];
-  char temp2[PATH_MAX];
-
-  // remove old berkeley db log files that can confuse the server
-  removef("%s/log.*", master_dir);
-
-  // remove stale binary logs
-  removef("%s/var/log/*-bin.*", mysql_test_dir);
-
-  // remove stale binary logs
-  removef("%s/var/log/*.index", mysql_test_dir);
-
-  // remove master.info file
-  removef("%s/master.info", master_dir);
-
-  // remove relay files
-  removef("%s/var/log/*relay*", mysql_test_dir);
-
-  // remove relay-log.info file
-  removef("%s/relay-log.info", master_dir);
-
-  // init script
-  if (master_init_script[0] != 0)
-  {
-#ifdef __NETWARE__
-    // TODO: use the scripts
-    if (strinstr(master_init_script, "repair_part2-master.sh") != 0)
-    {
-      FILE *fp;
-
-      // create an empty index file
-      snprintf(temp, PATH_MAX, "%s/test/t1.MYI", master_dir);
-      fp = fopen(temp, "wb+");
-
-      fputs("1", fp);
-
-      fclose(fp);
-    }
-#elif !defined(__WIN__)
-    run_init_script(master_init_script);
-#endif	
-  }
-
-  // redirection files
-  snprintf(master_out, PATH_MAX, "%s/var/run/master%u.out",
-           mysql_test_dir, restarts);
-  snprintf(master_err, PATH_MAX, "%s/var/run/master%u.err",
-           mysql_test_dir, restarts);
-#ifndef __WIN__
-  snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir);
-  mkdir(temp2,S_IRWXU);
-  snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir);
-  mkdir(temp2,S_IRWXU);
-#else
-  snprintf(temp2,PATH_MAX,"%s/var",mysql_test_dir);
-  mkdir(temp2);
-  snprintf(temp2,PATH_MAX,"%s/var/log",mysql_test_dir);
-  mkdir(temp2);
-#endif
-  // args
-  init_args(&al);
-  add_arg(&al, "%s", mysqld_file);
-  add_arg(&al, "--no-defaults");
-  add_arg(&al, "--log-bin=%s/var/log/master-bin",mysql_test_dir);
-  add_arg(&al, "--server-id=1");
-  add_arg(&al, "--basedir=%s", base_dir);
-  add_arg(&al, "--port=%u", master_port);
-#if !defined(__NETWARE__) && !defined(__WIN__)
-  add_arg(&al, "--socket=%s",master_socket);
-#endif  
-  add_arg(&al, "--local-infile");
-  add_arg(&al, "--core");
-  add_arg(&al, "--datadir=%s", master_dir);
-#ifndef __WIN__
-  add_arg(&al, "--pid-file=%s", master_pid);
-#endif
-  add_arg(&al, "--character-sets-dir=%s", char_dir);
-  add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
-  add_arg(&al, "--language=%s", lang_dir);
-#ifdef DEBUG	//only for debug builds
-  add_arg(&al, "--debug");
-#endif
-
-  if (use_openssl)
-  {
-    add_arg(&al, "--ssl-ca=%s", ca_cert);
-    add_arg(&al, "--ssl-cert=%s", server_cert);
-    add_arg(&al, "--ssl-key=%s", server_key);
-  }
-
-  // $MASTER_40_ARGS
-  add_arg(&al, "--rpl-recovery-rank=1");
-  add_arg(&al, "--init-rpl-role=master");
-
-  // $SMALL_SERVER
-  add_arg(&al, "-O");
-  add_arg(&al, "key_buffer_size=1M");
-  add_arg(&al, "-O");
-  add_arg(&al, "sort_buffer=256K");
-  add_arg(&al, "-O");
-  add_arg(&al, "max_heap_table_size=1M");
-
-  // $EXTRA_MASTER_OPT
-  if (master_opt[0] != 0)
-  {
-    char *p;
-
-    p = (char *)str_tok(master_opt, " \t");
-    if (!strstr(master_opt, "timezone"))
-    {
-      while (p)
-      {
-        add_arg(&al, "%s", p);
-        p = (char *)str_tok(NULL, " \t");
-      }
-    }
-  }
-
-  // remove the pid file if it exists
-#ifndef __WIN__
-  remove(master_pid);
-#endif
-
-  // spawn
-#ifdef __WIN__
-  if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err, &master_pid)) == 0)
-#else
-  if ((err= spawn(mysqld_file, &al, FALSE, NULL, master_out, master_err, master_pid)) == 0)
-#endif  
-  {
-    sleep_until_file_exists(master_pid);
-
-	if ((err = wait_for_server_start(bin_dir, mysqladmin_file, user, password, master_port,
-                                         mysql_tmp_dir)) == 0)
-    {
-      master_running = TRUE;
-    }
-    else
-    {
-	  log_error("The master server went down early.");
-    }
-  }
-  else
-  {
-    log_error("Unable to start master server.");
-  }
-
-  // free_args
-  free_args(&al);
-}
-
-/******************************************************************************
-
-  start_slave()
-  
-  Start the slave server.
-
-******************************************************************************/
-void start_slave()
-{
-  arg_list_t al;
-  int err;
-  char slave_out[PATH_MAX];
-  char slave_err[PATH_MAX];
-
-  // skip?
-  if (skip_slave) return;
-
-  // remove stale binary logs
-  removef("%s/*-bin.*", slave_dir);
-
-  // remove stale binary logs
-  removef("%s/*.index", slave_dir);
-
-  // remove master.info file
-  removef("%s/master.info", slave_dir);
-
-  // remove relay files
-  removef("%s/var/log/*relay*", mysql_test_dir);
-
-  // remove relay-log.info file
-  removef("%s/relay-log.info", slave_dir);
-
-  // init script
-  if (slave_init_script[0] != 0)
-  {
-#ifdef __NETWARE__
-    // TODO: use the scripts
-    if (strinstr(slave_init_script, "rpl000016-slave.sh") != 0)
-    {
-      // create empty master.info file
-      snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
-      close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO));
-    }
-    else if (strinstr(slave_init_script, "rpl000017-slave.sh") != 0)
-    {
-      FILE *fp;
-      
-      // create a master.info file
-      snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
-      fp = fopen(temp, "wb+");
-      
-      fputs("master-bin.000001\n", fp);
-      fputs("4\n", fp);
-      fputs("127.0.0.1\n", fp);
-      fputs("replicate\n", fp);
-      fputs("aaaaaaaaaaaaaaab\n", fp);
-      fputs("9306\n", fp);
-      fputs("1\n", fp);
-      fputs("0\n", fp);
-
-      fclose(fp);
-    }
-    else if (strinstr(slave_init_script, "rpl_rotate_logs-slave.sh") != 0)
-    {
-      // create empty master.info file
-      snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
-      close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO));
-    }
-#elif !defined(__WIN__)    
-    run_init_script(slave_init_script);
-#endif	
-  }
-
-  // redirection files
-  snprintf(slave_out, PATH_MAX, "%s/var/run/slave%u.out",
-           mysql_test_dir, restarts);
-  snprintf(slave_err, PATH_MAX, "%s/var/run/slave%u.err",
-           mysql_test_dir, restarts);
-  
-  // args
-  init_args(&al);
-  add_arg(&al, "%s", mysqld_file);
-  add_arg(&al, "--no-defaults");
-  add_arg(&al, "--log-bin=slave-bin");
-  add_arg(&al, "--relay_log=slave-relay-bin");
-  add_arg(&al, "--basedir=%s", base_dir);
-  add_arg(&al, "--port=%u", slave_port);
-#if !defined(__NETWARE__) && !defined(__WIN__)
-  add_arg(&al, "--socket=%s",slave_socket);
-#endif  
-  add_arg(&al, "--datadir=%s", slave_dir);
-#ifndef __WIN__
-  add_arg(&al, "--pid-file=%s", slave_pid);
-#endif
-  add_arg(&al, "--character-sets-dir=%s", char_dir);
-  add_arg(&al, "--core");
-  add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
-  add_arg(&al, "--language=%s", lang_dir);
-
-  add_arg(&al, "--exit-info=256");
-  add_arg(&al, "--log-slave-updates");
-  add_arg(&al, "--init-rpl-role=slave");
-  add_arg(&al, "--skip-innodb");
-  add_arg(&al, "--skip-slave-start");
-  add_arg(&al, "--slave-load-tmpdir=../../var/tmp");
-  
-  add_arg(&al, "--report-user=%s", user);
-  add_arg(&al, "--report-host=127.0.0.1");
-  add_arg(&al, "--report-port=%u", slave_port);
-
-  add_arg(&al, "--master-retry-count=10");
-  add_arg(&al, "-O");
-  add_arg(&al, "slave_net_timeout=10");
-#ifdef DEBUG	//only for debug builds
-  add_arg(&al, "--debug");
-#endif
-
-  if (use_openssl)
-  {
-    add_arg(&al, "--ssl-ca=%s", ca_cert);
-    add_arg(&al, "--ssl-cert=%s", server_cert);
-    add_arg(&al, "--ssl-key=%s", server_key);
-  }
-
-  // slave master info
-  if (slave_master_info[0] != 0)
-  {
-    char *p;
-
-    p = (char *)str_tok(slave_master_info, " \t");
-
-    while(p)
-    {
-      add_arg(&al, "%s", p);
-      
-      p = (char *)str_tok(NULL, " \t");
-    }
-  }
-  else
-  {
-    add_arg(&al, "--master-user=%s", user);
-    add_arg(&al, "--master-password=%s", password);
-    add_arg(&al, "--master-host=127.0.0.1");
-    add_arg(&al, "--master-port=%u", master_port);
-    add_arg(&al, "--master-connect-retry=1");
-    add_arg(&al, "--server-id=2");
-    add_arg(&al, "--rpl-recovery-rank=2");
-  }
-  
-  // small server
-  add_arg(&al, "-O");
-  add_arg(&al, "key_buffer_size=1M");
-  add_arg(&al, "-O");
-  add_arg(&al, "sort_buffer=256K");
-  add_arg(&al, "-O");
-  add_arg(&al, "max_heap_table_size=1M");
-
-
-  // opt args
-  if (slave_opt[0] != 0)
-  {
-    char *p;
-
-    p = (char *)str_tok(slave_opt, " \t");
-
-    while(p)
-    {
-      add_arg(&al, "%s", p);
-      
-      p = (char *)str_tok(NULL, " \t");
-    }
-  }
-  
-  // remove the pid file if it exists
-#ifndef __WIN__
-  remove(slave_pid);
-#endif
-  // spawn
-#ifdef __WIN__  
-  if ((err = spawn(mysqld_file, &al, FALSE, NULL, slave_out, slave_err, &slave_pid)) == 0)
-#else
-  if ((err = spawn(mysqld_file, &al, FALSE, NULL, slave_out, slave_err, slave_pid)) == 0)
-#endif  
-  {
-    sleep_until_file_exists(slave_pid);
-    
-    if ((err = wait_for_server_start(bin_dir, mysqladmin_file, user, password, slave_port,
-                                     mysql_tmp_dir)) == 0)
-    {
-      slave_running = TRUE;
-    }
-    else
-    {
-      log_error("The slave server went down early.");
-    }
-  }
-  else
-  {
-    log_error("Unable to start slave server.");
-  }
-  
-  // free args
-  free_args(&al);
-}
-
-/******************************************************************************
-
-  mysql_start()
-  
-  Start the mysql servers.
-
-******************************************************************************/
-void mysql_start()
-{
-//  log_info("Starting the MySQL server(s): %u", ++restarts);
-  start_master();
-
-  start_slave();
-
-  // activate the test screen
-#ifdef __NETWARE__  
-  ActivateScreen(getscreenhandle());
-#endif  
-}
-
-/******************************************************************************
-
-  stop_slave()
-
-  Stop the slave server.
-
-******************************************************************************/
-void stop_slave()
-{
-  int err;
-
-  // running?
-  if (!slave_running) return;
-
-  // stop
-  if ((err = stop_server(bin_dir, mysqladmin_file, user, password, slave_port, slave_pid,
-                         mysql_tmp_dir)) == 0)
-  {
-    slave_running = FALSE;
-  }
-  else
-  {
-    log_error("Unable to stop slave server.");
-  }
-}
-
-/******************************************************************************
-
-  stop_master()
-
-  Stop the master server.
-
-******************************************************************************/
-void stop_master()
-{
-  int err;
-
-  // running?
-  if (!master_running) return;
-
-  if ((err = stop_server(bin_dir, mysqladmin_file, user, password, master_port, master_pid,
-                         mysql_tmp_dir)) == 0)
-  {
-    master_running = FALSE;
-  }
-  else
-  {
-    log_error("Unable to stop master server.");
-  }
-}
-
-/******************************************************************************
-
-  mysql_stop()
-
-  Stop the mysql servers.
-
-******************************************************************************/
-void mysql_stop()
-{
-
-  stop_master();
-
-  stop_slave();
-
-  // activate the test screen
-#ifdef __NETWARE__  
-  ActivateScreen(getscreenhandle());
-#endif  
-}
-
-/******************************************************************************
-
-  mysql_restart()
-
-  Restart the mysql servers.
-
-******************************************************************************/
-void mysql_restart()
-{
-//  log_info("Restarting the MySQL server(s): %u", ++restarts);
-
-  mysql_stop();
-
-  mlog(DASH);
-
-  mysql_start();
-}
-
-/******************************************************************************
-
-  read_option()
-
-  Read the option file.
-
-******************************************************************************/
-int read_option(char *opt_file, char *opt)
-{
-  int fd, err;
-  char *p;
-  char buf[PATH_MAX];
-
-  // copy current option
-  strncpy(buf, opt, PATH_MAX);
-
-  // open options file
-  fd = open(opt_file, O_RDONLY);
-  
-  err = read(fd, opt, PATH_MAX);
-  
-  close(fd);
-  
-  if (err > 0)
-  {
-    // terminate string
-    if ((p = strchr(opt, '\n')) != NULL)
-    {
-      *p = 0;
-      
-      // check for a '\r'
-      if ((p = strchr(opt, '\r')) != NULL)
-      {
-        *p = 0;
-      }
-    }
-    else
-    {
-      opt[err] = 0;
-    }
-
-    // check for $MYSQL_TEST_DIR
-    if ((p = strstr(opt, "$MYSQL_TEST_DIR")) != NULL)
-    {
-      char temp[PATH_MAX];
-      
-      *p = 0;
-      
-      strcpy(temp, p + strlen("$MYSQL_TEST_DIR"));
-      
-      strcat(opt, mysql_test_dir);
-      
-      strcat(opt, temp);
-    }
-    // Check for double backslash and replace it with single bakslash
-    if ((p = strstr(opt, "\\\\")) != NULL)
-    {
-      /* bmove is guranteed to work byte by byte */
-      bmove(p, p+1, strlen(p+1));
-    }
-  }
-  else
-  {
-    // clear option
-    *opt = 0;
-  }
-  
-  // compare current option with previous
-  return strcmp(opt, buf);
-}
-
-/******************************************************************************
-
-  run_test()
-  
-  Run the given test case.
-
-******************************************************************************/
-void run_test(char *test)
-{
-  char temp[PATH_MAX];
-  const char *rstr;
-  int skip = FALSE, ignore=FALSE;
-  int restart = FALSE;
-  int flag = FALSE;
-  struct stat info;
-  
-  // skip tests in the skip list
-  snprintf(temp, PATH_MAX, " %s ", test);
-  skip = (strinstr(skip_test, temp) != 0);
-  if (skip == FALSE)
-    ignore = (strinstr(ignore_test, temp) != 0);
-
-  snprintf(master_init_script, PATH_MAX, "%s/%s-master.sh", test_dir, test);
-  snprintf(slave_init_script, PATH_MAX, "%s/%s-slave.sh", test_dir, test);
-#ifdef __WIN__    
-  if (! stat(master_init_script, &info))
-      skip = TRUE;
-  if (!stat(slave_init_script, &info))
-      skip = TRUE;
-#endif
-  if (ignore)
-  {
-    // show test
-    mlog("%-46s ", test);
-         
-    // ignore
-    rstr = TEST_IGNORE;
-    ++total_ignore;
-  }  
-  else if (!skip)     // skip test?
-  {
-    char test_file[PATH_MAX];
-    char master_opt_file[PATH_MAX];
-    char slave_opt_file[PATH_MAX];
-    char slave_master_info_file[PATH_MAX];
-    char result_file[PATH_MAX];
-    char reject_file[PATH_MAX];
-    char out_file[PATH_MAX];
-    char err_file[PATH_MAX];
-    int err;
-    arg_list_t al;
-#ifdef __WIN__
-    /*
-      Clean test database
-    */
-    removef("%s/test/*.*", master_dir);
-    removef("%s/test/*.*", slave_dir);
-    removef("%s/mysqltest/*.*", master_dir);
-    removef("%s/mysqltest/*.*", slave_dir);
-
-#endif
-    // skip slave?
-    flag = skip_slave;
-    skip_slave = (strncmp(test, "rpl", 3) != 0);
-    if (flag != skip_slave) restart = TRUE;
-    
-    // create files
-    snprintf(master_opt_file, PATH_MAX, "%s/%s-master.opt", test_dir, test);
-    snprintf(slave_opt_file, PATH_MAX, "%s/%s-slave.opt", test_dir, test);
-    snprintf(slave_master_info_file, PATH_MAX, "%s/%s.slave-mi", test_dir, test);
-    snprintf(reject_file, PATH_MAX, "%s/%s%s", result_dir, test, REJECT_SUFFIX);
-    snprintf(out_file, PATH_MAX, "%s/%s%s", result_dir, test, OUT_SUFFIX);
-    snprintf(err_file, PATH_MAX, "%s/%s%s", result_dir, test, ERR_SUFFIX);
-    
-    // netware specific files
-    snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX);
-    if (stat(test_file, &info))
-    {
-      snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, TEST_SUFFIX);
-      if (access(test_file,0))
-      {
-        printf("Invalid test name %s, %s file not found\n",test,test_file);
-        return;
-      }
-    }
-
-    snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, NW_RESULT_SUFFIX);
-    if (stat(result_file, &info))
-    {
-      snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, RESULT_SUFFIX);
-    }
-
-    // init scripts
-    if (stat(master_init_script, &info))
-      master_init_script[0] = 0;
-    else
-      restart = TRUE;
-    
-    if (stat(slave_init_script, &info))
-      slave_init_script[0] = 0;
-    else
-      restart = TRUE;
-
-    // read options
-    if (read_option(master_opt_file, master_opt)) restart = TRUE;
-    if (read_option(slave_opt_file, slave_opt)) restart = TRUE;
-    if (read_option(slave_master_info_file, slave_master_info)) restart = TRUE;
-    
-    // cleanup previous run
-    remove(reject_file);
-    remove(out_file);
-    remove(err_file);
-    
-    // start or restart?
-    if (!master_running) mysql_start();
-      else if (restart) mysql_restart();
-    
-    // let the system stabalize
-    sleep(1);
-
-    // show test
-    mlog("%-46s ", test);
-    
-	
-    // args
-    init_args(&al);
-    add_arg(&al, "%s", mysqltest_file);
-    add_arg(&al, "--no-defaults");
-    add_arg(&al, "--port=%u", master_port);
-#if !defined(__NETWARE__) && !defined(__WIN__)
-    add_arg(&al, "--socket=%s", master_socket);
-    add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
-#endif	
-    add_arg(&al, "--database=%s", db);
-    add_arg(&al, "--user=%s", user);
-    add_arg(&al, "--password=%s", password);
-    add_arg(&al, "--silent");
-    add_arg(&al, "--basedir=%s/", mysql_test_dir);
-    add_arg(&al, "--host=127.0.0.1");
-    add_arg(&al, "-v");
-    add_arg(&al, "-R");
-    add_arg(&al, "%s", result_file);
-
-    if (use_openssl)
-    {
-      add_arg(&al, "--ssl-ca=%s", ca_cert);
-      add_arg(&al, "--ssl-cert=%s", client_cert);
-      add_arg(&al, "--ssl-key=%s", client_key);
-    }
-
-    // spawn
-    err = spawn(mysqltest_file, &al, TRUE, test_file, out_file, err_file, NULL);
-    
-    // free args
-    free_args(&al);
-
-    remove_empty_file(out_file);  
-    remove_empty_file(err_file);  
-    
-    if (err == 0)
-    {
-      // pass
-      rstr = TEST_PASS;
-      ++total_pass;
-      
-      // increment total
-      ++total_test;
-    }
-    else if (err == 2)
-    {
-      // skip
-      rstr = TEST_SKIP;
-      ++total_skip;
-    }
-    else if (err == 1)
-    {
-      // fail
-      rstr = TEST_FAIL;
-      ++total_fail;
-
-      // increment total
-      ++total_test;
-    }
-    else
-    {
-      rstr = TEST_BAD;
-    }
-  }
-  else // early skips
-  {
-    // show test
-    mlog("%-46s ", test);
-    
-    // skip
-    rstr = TEST_SKIP;
-    ++total_skip;
-  }
-
-  // result
-  mlog("%-14s\n", rstr);
-}
-
-/******************************************************************************
-
-  vlog()
-  
-  Log the message.
-
-******************************************************************************/
-void vlog(const char *format, va_list ap)
-{
-  vfprintf(stdout, format, ap);
-  fflush(stdout);
-  
-  if (log_fd)
-  {
-    vfprintf(log_fd, format, ap);
-    fflush(log_fd);
-  }
-}
-
-/******************************************************************************
-
-  log()
-  
-  Log the message.
-
-******************************************************************************/
-void mlog(const char *format, ...)
-{
-  va_list ap;
-
-  va_start(ap, format);
-
-  vlog(format, ap);
-  
-  va_end(ap);
-}
-
-/******************************************************************************
-
-  log_info()
-  
-  Log the given information.
-
-******************************************************************************/
-void log_info(const char *format, ...)
-{
-  va_list ap;
-  
-  va_start(ap, format);
-
-  mlog("-- INFO : ");
-  vlog(format, ap);
-  mlog("\n");
-
-  va_end(ap);
-}
-
-/******************************************************************************
-
-  log_error()
-  
-  Log the given error.
-
-******************************************************************************/
-void log_error(const char *format, ...)
-{
-  va_list ap;
-  
-  va_start(ap, format);
-
-  mlog("-- ERROR: ");
-  vlog(format, ap);
-  mlog("\n");
-
-  va_end(ap);
-}
-
-/******************************************************************************
-
-  log_errno()
-  
-  Log the given error and errno.
-
-******************************************************************************/
-void log_errno(const char *format, ...)
-{
-  va_list ap;
-  
-  va_start(ap, format);
-
-  mlog("-- ERROR: (%003u) ", errno);
-  vlog(format, ap);
-  mlog("\n");
-
-  va_end(ap);
-}
-
-/******************************************************************************
-
-  die()
-  
-  Exit the application.
-
-******************************************************************************/
-void die(const char *msg)
-{
-  log_error(msg);
-#ifdef __NETWARE__
-  pressanykey();
-#endif
-  exit(-1);
-}
-
-/******************************************************************************
-
-  setup()
-  
-  Setup the mysql test enviornment.
-
-******************************************************************************/
-void setup(char *file)
-{
-  char temp[PATH_MAX];
-  char file_path[PATH_MAX*2];
-  char *p;
-  int position;
-
-  // set the timezone for the timestamp test
-#ifdef __WIN__
-  _putenv( "TZ=GMT-3" );
-#else
-  setenv("TZ", "GMT-3", TRUE);
-#endif
-  // find base dir
-#ifdef __NETWARE__  
-  strcpy(temp, strlwr(file));
-  while((p = strchr(temp, '\\')) != NULL) *p = '/';
-#else  
-  getcwd(temp, PATH_MAX);
-  position = strlen(temp);
-  temp[position] = '/';
-  temp[position+1] = 0;
-#ifdef __WIN__
-  while((p = strchr(temp, '\\')) != NULL) *p = '/';
-#endif
-#endif  
-
-  if ((position = strinstr(temp, "/mysql-test/")) != 0)
-  {
-    p = temp + position - 1;
-    *p = 0;
-    strcpy(base_dir, temp);
-  } 
-
-  log_info("Currect directory: %s",base_dir);
-
-#ifdef __NETWARE__
-  // setup paths
-  snprintf(bin_dir, PATH_MAX, "%s/bin", base_dir);
-  snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir);
-  snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir);
-  snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir);
-  snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir);
-  snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir);
-  snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
-  snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir);
-  snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir);
-
-#ifdef HAVE_OPENSSL
-  use_openssl = TRUE;
-#endif // HAVE_OPENSSL
-
-  // OpenSSL paths
-  snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir);
-  snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir);
-  snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir);
-  snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir);
-  snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir);
-
-  // setup files
-  snprintf(mysqld_file, PATH_MAX, "%s/mysqld", bin_dir);
-  snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir);
-  snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir);
-  snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir);
-  snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir);
-#elif __WIN__
-  // setup paths
-#ifdef _DEBUG
-  snprintf(bin_dir, PATH_MAX, "%s/client_debug", base_dir);
-#else
-  snprintf(bin_dir, PATH_MAX, "%s/client_release", base_dir);
-#endif
-  snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir);
-  snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir);
-  snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir);
-  snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir);
-  snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir);
-  snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
-  snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir);
-  snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir);
-
-#ifdef HAVE_OPENSSL
-  use_openssl = TRUE;
-#endif // HAVE_OPENSSL
-
-  // OpenSSL paths
-  snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir);
-  snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir);
-  snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir);
-  snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir);
-  snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir);
-
-  // setup files
-  snprintf(mysqld_file, PATH_MAX, "%s/mysqld.exe", bin_dir);
-  snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest.exe", bin_dir);
-  snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin.exe", bin_dir);
-#else  
-  // setup paths
-  snprintf(bin_dir, PATH_MAX, "%s/client", base_dir);
-  snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir);
-  snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir);
-  snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir);
-  snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir);
-  snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir);
-  snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
-  snprintf(lang_dir, PATH_MAX, "%s/sql/share/english", base_dir);
-  snprintf(char_dir, PATH_MAX, "%s/sql/share/charsets", base_dir);
-
-#ifdef HAVE_OPENSSL
-  use_openssl = TRUE;
-#endif // HAVE_OPENSSL
-
-  // OpenSSL paths
-  snprintf(ca_cert, PATH_MAX, "%s/SSL/cacert.pem", base_dir);
-  snprintf(server_cert, PATH_MAX, "%s/SSL/server-cert.pem", base_dir);
-  snprintf(server_key, PATH_MAX, "%s/SSL/server-key.pem", base_dir);
-  snprintf(client_cert, PATH_MAX, "%s/SSL/client-cert.pem", base_dir);
-  snprintf(client_key, PATH_MAX, "%s/SSL/client-key.pem", base_dir);
-
-  // setup files
-  snprintf(mysqld_file, PATH_MAX, "%s/sql/mysqld", base_dir);
-  snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir);
-  snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir);
-  snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir);
-  snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir);
-  
-  snprintf(master_socket,PATH_MAX, "%s/var/tmp/master.sock", mysql_test_dir);
-  snprintf(slave_socket,PATH_MAX, "%s/var/tmp/slave.sock", mysql_test_dir);
-
-#endif
-  // create log file
-  snprintf(temp, PATH_MAX, "%s/mysql-test-run.log", mysql_test_dir);
-  if ((log_fd = fopen(temp, "w+")) == NULL)
-  {
-    log_errno("Unable to create log file.");
-  }
-
-  // prepare skip test list
-  while((p = strchr(skip_test, ',')) != NULL) *p = ' ';
-  strcpy(temp, strlwr(skip_test));
-  snprintf(skip_test, PATH_MAX, " %s ", temp);
-
-  // environment
-#ifdef __NETWARE__  
-  setenv("MYSQL_TEST_DIR", mysql_test_dir, 1);
-  snprintf(file_path, PATH_MAX*2, "%s/client/mysqldump --no-defaults -u root --port=%u", bin_dir, master_port);
-  setenv("MYSQL_DUMP", file_path, 1);
-  snprintf(file_path, PATH_MAX*2, "%s/client/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir);
-  setenv("MYSQL_BINLOG", file_path, 1);
-#elif __WIN__
-  snprintf(file_path,MAX_PATH,"MYSQL_TEST_DIR=%s",mysql_test_dir);
-  _putenv(file_path);
-  snprintf(file_path, PATH_MAX*2, "MYSQL_DUMP=%s/mysqldump.exe --no-defaults -u root --port=%u", bin_dir, master_port);
-  _putenv(file_path);
-  snprintf(file_path, PATH_MAX*2, "MYSQL_BINLOG=%s/mysqlbinlog.exe --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir);
-  _putenv(file_path);
-#else
-  setenv("MYSQL_TEST_DIR", mysql_test_dir, 1);
-  snprintf(file_path, PATH_MAX*2, "%s/mysqldump --no-defaults -u root --port=%u --socket=%s", bin_dir, master_port, master_socket);
-  setenv("MYSQL_DUMP", file_path, 1);
-  snprintf(file_path, PATH_MAX*2, "%s/mysqlbinlog --no-defaults --local-load=%s", bin_dir, mysql_tmp_dir);
-  setenv("MYSQL_BINLOG", file_path, 1);
-#endif  
-
-#ifndef __WIN__
-  setenv("MASTER_MYPORT", "9306", 1);
-  setenv("SLAVE_MYPORT", "9307", 1);
-  setenv("MYSQL_TCP_PORT", "3306", 1);
-#else
-  _putenv("MASTER_MYPORT=9306");
-  _putenv("SLAVE_MYPORT=9307");
-  _putenv("MYSQL_TCP_PORT=3306");
-#endif
-
-}
-
-/******************************************************************************
-
-  main()
-  
-******************************************************************************/
-int main(int argc, char **argv)
-{
-  int is_ignore_list = 0;
-  // setup
-  setup(argv[0]);
-  
-  /* The --ignore option is comma saperated list of test cases to skip and
-     should be very first command line option to the test suite. 
-
-     The usage is now:
-     mysql_test_run --ignore=test1,test2 test3 test4
-     where test1 and test2 are test cases to ignore
-     and test3 and test4 are test cases to run.
-  */
-  if (argc >= 2 && !strnicmp(argv[1], "--ignore=", sizeof("--ignore=")-1))
-  {
-    char *temp, *token;
-    temp= strdup(strchr(argv[1],'=') + 1);
-    for (token=str_tok(temp, ","); token != NULL; token=str_tok(NULL, ","))
-    {
-      if (strlen(ignore_test) + strlen(token) + 2 <= PATH_MAX-1)
-        sprintf(ignore_test+strlen(ignore_test), " %s ", token);
-      else
-      {
-        free(temp);
-        die("ignore list too long.");
-      }
-    }
-    free(temp);
-    is_ignore_list = 1;
-  }
-  // header
-#ifndef __WIN__
-  mlog("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
-#else
-  mlog("MySQL Server ---, for %s (%s)\n\n", SYSTEM_TYPE, MACHINE_TYPE);
-#endif
-  
-  mlog("Initializing Tests...\n");
-  
-  // install test databases
-  mysql_install_db();
-  
-  mlog("Starting Tests...\n");
-  
-  mlog("\n");
-  mlog(HEADER);
-  mlog(DASH);
-
-  if ( argc > 1 + is_ignore_list )
-  {
-    int i;
-
-    // single test
-    single_test = TRUE;
-
-    for (i = 1 + is_ignore_list; i < argc; i++)
-    {
-      // run given test
-      run_test(argv[i]);
-    }
-  }
-  else
-  {
-    // run all tests
-#ifndef __WIN__
-    struct dirent **namelist;
-    int i,n;
-    char test[NAME_MAX];
-    char *p;
-    int position;
-					 
-    n = scandir(test_dir, &namelist, 0, alphasort);
-    if (n < 0)
-      die("Unable to open tests directory.");
-    else 
-    {
-      for (i = 0; i < n; i++) 
-      {
-        strcpy(test, strlwr(namelist[i]->d_name));      
-        // find the test suffix
-        if ((position = strinstr(test, TEST_SUFFIX)) != 0)
-        {
-          p = test + position - 1;
-          // null terminate at the suffix
-          *p = 0;
-          // run test
-          run_test(test);
-        }
-        free(namelist[n]);
-      }	
-      free(namelist);
-    }																																					   	
-#else
-    struct _finddata_t dir;
-    intptr_t handle;
-    char test[NAME_MAX];
-    char mask[PATH_MAX];
-    char *p;
-    int position;
-    char **names = 0;
-    char **testes = 0;
-    int name_index;
-    int index;
-    
-    // single test
-    single_test = FALSE;    
-
-    snprintf(mask,MAX_PATH,"%s/*.test",test_dir);
-    
-    if ((handle=_findfirst(mask,&dir)) == -1L)
-    {
-      die("Unable to open tests directory.");
-    }
-
-    names = malloc(MAX_COUNT_TESTES*4); 
-    testes = names;
-    name_index = 0;
-
-    do
-    {
-      if (!(dir.attrib & _A_SUBDIR)) 
-      {
-        strcpy(test, strlwr(dir.name));
-        
-        // find the test suffix
-        if ((position = strinstr(test, TEST_SUFFIX)) != 0)
-        {
-          p = test + position - 1;
-          // null terminate at the suffix
-          *p = 0;
-
-          // insert test
-          *names = malloc(PATH_MAX);
-          strcpy(*names,test);
-          names++;
-          name_index++;
-        }
-      } 
-    }while (_findnext(handle,&dir) == 0);
-
-    _findclose(handle);
-
-    qsort( (void *)testes, name_index, sizeof( char * ), compare );
-
-    for (index = 0; index <= name_index; index++)
-    {
-      run_test(testes[index]);
-      free(testes[index]);
-    }
-
-    free(testes);
-#endif
-  }
-
-  // stop server
-  mysql_stop();
-
-  mlog(DASH);
-  mlog("\n");
-
-  mlog("Ending Tests...\n");
-
-  // report stats
-  report_stats();
-
-  // close log
-  if (log_fd) fclose(log_fd);
-
-  // keep results up
-#ifdef __NETWARE__  
-  pressanykey();
-#endif
-  return 0;
-}
-
-
-/*
- Synopsis:
-  This function breaks the string into a sequence of tokens. The difference
-  between this function and strtok is that it respects the quoted string i.e.
-  it skips  any delimiter character within the quoted part of the string. 
-  It return tokens by eliminating quote character. It modifies the input string
-  passed. It will work with whitespace delimeter but may not work properly with
-  other delimeter. If the delimeter will contain any quote character, then
-  function will not tokenize and will return null string.
-  e.g. if input string is 
-     --init-slave="set global max_connections=500" --skip-external-locking
-  then the output will two string i.e.
-     --init-slave=set global max_connections=500
-     --skip-external-locking
-
-Arguments:
-  string:  input string
-  delim:   set of delimiter character
-Output:
-  return the null terminated token of NULL.
-*/
-
-
-char *str_tok(char *string, const char *delim)
-{
-  char *token;            /* current token received from strtok */
-  char *qt_token;         /* token delimeted by the matching pair of quote */
-  /*
-    if there are any quote chars found in the token then this variable
-    will hold the concatenated string to return to the caller
-  */
-  char *ptr_token=NULL;
-  /* pointer to the quote character in the token from strtok */
-  char *ptr_quote=NULL;
-  
-  /* See if the delimeter contains any quote character */
-  if (strchr(delim,'\'') || strchr(delim,'\"'))
-    return NULL;
-
-  /* repeate till we are getting some token from strtok */
-  while ((token = (char*)strtok(string, delim) ) != NULL)
-  {
-    /*
-      make the input string NULL so that next time onward strtok can
-      be called with NULL input string.
-    */
-    string = NULL;
-    /*
-      We don't need to remove any quote character for Windows version
-    */
-#ifndef __WIN__
-    /* check if the current token contain double quote character*/
-    if ((ptr_quote = (char*)strchr(token,'\"')) != NULL)
-    {
-      /*
-        get the matching the matching double quote in the remaining
-        input string
-      */
-      qt_token = (char*)strtok(NULL,"\"");
-    }
-    /* check if the current token contain single quote character*/
-    else if ((ptr_quote = (char*)strchr(token,'\'')) != NULL)
-    {
-      /*
-        get the matching the matching single quote in the remaining
-        input string
-      */
-      qt_token = (char*)strtok(NULL,"\'");
-    }
-#endif
-    /*
-      if the current token does not contains any quote character then
-      return to the caller.
-    */
-    if (ptr_quote == NULL)
-    {
-      /*
-        if there is any earlier token i.e. ptr_token then append the
-        current token in it and return it else return the current
-        token directly
-      */
-      return ptr_token ? strcat(ptr_token,token) : token;
-    }
-
-    /*
-      remove the quote character i.e. make NULL so that the token will
-      be devided in two part and later both part can be concatenated
-      and hence quote will be removed
-    */
-    *ptr_quote= 0;
-    
-    /* check if ptr_token has been initialized or not */
-    if (ptr_token == NULL)
-    {
-      /* initialize the ptr_token with current token */
-      ptr_token= token;
-      /* copy entire string between matching pair of quote*/
-      sprintf(ptr_token+strlen(ptr_token),"%s %s", ptr_quote+1, qt_token);
-    }
-    else
-    {
-      /*
-        copy the current token and entire string between matching pair
-        of quote
-      */
-	  if (qt_token == NULL)
-	  {
-    	sprintf(ptr_token+strlen(ptr_token),"%s%s", token, ptr_quote+1);
-	  }
-	  else
-	  {
-    	sprintf(ptr_token+strlen(ptr_token),"%s%s %s", token, ptr_quote+1,
-      	        qt_token );
-	  }
-    }
-  }
-  
-  /* return the concatenated token */
-  return ptr_token;
-}
-
-#ifndef __WIN__
-
-/*
- Synopsis:
-  This function run scripts files on Linux and Netware
-
-Arguments:
-  script_name:  name of script file
-
-Output:
-  nothing
-*/
-void run_init_script(const char *script_name)
-{
-  arg_list_t al;
-  int err;
-  
-  // args
-  init_args(&al);
-  add_arg(&al, sh_file);
-  add_arg(&al, script_name);
-  
-  // spawn
-  if ((err = spawn(sh_file, &al, TRUE, NULL, NULL, NULL, NULL)) != 0)
-  {
-    die("Unable to run script.");
-  }
-  
-  // free args
-  free_args(&al);
-}
-#endif
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index 7af5d27b922..256199dced7 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbConnection.hpp
@@ -607,8 +607,8 @@ private:
   NdbOperation*	theLastExecOpInList;	    // Last executing operation in list.
 
 
-  NdbOperation*	theCompletedFirstOp;	    // First operation in completed 
-                                            // operation list.
+  NdbOperation*	theCompletedFirstOp;	    // First & last operation in completed 
+  NdbOperation*	theCompletedLastOp;         // operation list.
 
   Uint32	theNoOfOpSent;				// How many operations have been sent	    
   Uint32	theNoOfOpCompleted;			// How many operations have completed
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index 4f6468eb4ae..719c5bef49e 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -55,6 +55,7 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
   theFirstExecOpInList(NULL),
   theLastExecOpInList(NULL),
   theCompletedFirstOp(NULL),
+  theCompletedLastOp(NULL),
   theNoOfOpSent(0),
   theNoOfOpCompleted(0),
   theNoOfOpFetched(0),
@@ -124,6 +125,7 @@ NdbConnection::init()
   theLastExecOpInList	  = NULL;
 
   theCompletedFirstOp	  = NULL;
+  theCompletedLastOp	  = NULL;
 
   theGlobalCheckpointId   = 0;
   theCommitStatus         = Started;
@@ -256,6 +258,8 @@ NdbConnection::handleExecuteCompletion()
   if (tLastExecOp != NULL) {
     tLastExecOp->next(theCompletedFirstOp);
     theCompletedFirstOp = tFirstExecOp;
+    if (theCompletedLastOp == NULL)
+      theCompletedLastOp = tLastExecOp;
     theFirstExecOpInList = NULL;
     theLastExecOpInList = NULL;
   }//if
@@ -292,6 +296,8 @@ NdbConnection::execute(ExecType aTypeOfExec,
 
   ExecType tExecType;
   NdbOperation* tPrepOp;
+  NdbOperation* tCompletedFirstOp = NULL;
+  NdbOperation* tCompletedLastOp = NULL;
 
   int ret = 0;
   do {
@@ -314,6 +320,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
       }
       tPrepOp = tPrepOp->next();
     }
+
     // save rest of prepared ops if batch
     NdbOperation* tRestOp= 0;
     NdbOperation* tLastOp= 0;
@@ -323,6 +330,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
       tLastOp = theLastOpInList;
       theLastOpInList = tPrepOp;
     }
+
     if (tExecType == Commit) {
       NdbOperation* tOp = theCompletedFirstOp;
       while (tOp != NULL) {
@@ -338,6 +346,19 @@ NdbConnection::execute(ExecType aTypeOfExec,
       }
     }
 
+    // completed ops are in unspecified order
+    if (theCompletedFirstOp != NULL) {
+      if (tCompletedFirstOp == NULL) {
+        tCompletedFirstOp = theCompletedFirstOp;
+        tCompletedLastOp = theCompletedLastOp;
+      } else {
+        tCompletedLastOp->next(theCompletedFirstOp);
+        tCompletedLastOp = theCompletedLastOp;
+      }
+      theCompletedFirstOp = NULL;
+      theCompletedLastOp = NULL;
+    }
+
     if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
         ret = -1;
 #ifndef VM_TRACE
@@ -362,6 +383,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
         tOp = tOp->next();
       }
     }
+
     // add saved prepared ops if batch
     if (tPrepOp != NULL && tRestOp != NULL) {
       if (theFirstOpInList == NULL)
@@ -373,6 +395,18 @@ NdbConnection::execute(ExecType aTypeOfExec,
     assert(theFirstOpInList == NULL || tExecType == NoCommit);
   } while (theFirstOpInList != NULL || tExecType != aTypeOfExec);
 
+  if (tCompletedFirstOp != NULL) {
+    tCompletedLastOp->next(theCompletedFirstOp);
+    theCompletedFirstOp = tCompletedFirstOp;
+    if (theCompletedLastOp == NULL)
+      theCompletedLastOp = tCompletedLastOp;
+  }
+#if ndb_api_count_completed_ops_after_blob_execute
+  { NdbOperation* tOp; unsigned n = 0;
+    for (tOp = theCompletedFirstOp; tOp != NULL; tOp = tOp->next()) n++;
+    ndbout << "completed ops: " << n << endl;
+  }
+#endif
   DBUG_RETURN(ret);
 }
 
@@ -894,6 +928,7 @@ NdbConnection::releaseOperations()
   releaseOps(theFirstExecOpInList);
 
   theCompletedFirstOp = NULL;
+  theCompletedLastOp = NULL;
   theFirstOpInList = NULL;
   theFirstExecOpInList = NULL;
   theLastOpInList = NULL;
@@ -909,6 +944,7 @@ NdbConnection::releaseCompletedOperations()
 {
   releaseOps(theCompletedFirstOp);
   theCompletedFirstOp = NULL;
+  theCompletedLastOp = NULL;
 }//NdbConnection::releaseOperations()
 
 /******************************************************************************
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index efa0811aa39..4b532856709 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -22,6 +22,7 @@
 #include <NdbMain.h>
 #include <NdbOut.hpp>
 #include <NdbTest.hpp>
+#include <NdbTick.h>
 
 struct Bcol {
   bool m_nullable;
@@ -59,6 +60,9 @@ struct Opt {
   bool m_oneblob;
   Bcol m_blob1;
   Bcol m_blob2;
+  // perf
+  const char* m_tnameperf;
+  unsigned m_rowsperf;
   // bugs
   int m_bug;
   int (*m_bugtest)();
@@ -84,6 +88,9 @@ struct Opt {
     m_oneblob(false),
     m_blob1(false, 7, 1137, 10),
     m_blob2(true, 99, 55, 1),
+    // perf
+    m_tnameperf("TBLOB2"),
+    m_rowsperf(10000),
     // bugs
     m_bug(0),
     m_bugtest(0) {
@@ -107,6 +114,7 @@ printusage()
     << "  -loop N     loop N times 0=forever [" << d.m_loop << "]" << endl
     << "  -parts N    max parts in blob value [" << d.m_parts << "]" << endl
     << "  -rows N     number of rows [" << d.m_rows << "]" << endl
+    << "  -rowsperf N rows for performace test [" << d.m_rowsperf << "]" << endl
     << "  -seed N     random seed 0=loop number [" << d.m_seed << "]" << endl
     << "  -skip xxx   skip given tests (see list) [no tests]" << endl
     << "  -test xxx   only given tests (see list) [all tests]" << endl
@@ -118,6 +126,7 @@ printusage()
     << "  i           hash index ops" << endl
     << "  s           table scans" << endl
     << "  r           ordered index scans" << endl
+    << "  p           performance test" << endl
     << "additional flags for test/skip" << endl
     << "  u           update existing blob value" << endl
     << "  n           normal insert and update" << endl
@@ -1381,6 +1390,292 @@ testmain()
   return 0;
 }
 
+// separate performance test
+
+struct Tmr {    // stolen from testOIBasic
+  Tmr() {
+    clr();
+  }
+  void clr() {
+    m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0;
+  }
+  void on() {
+    assert(m_on == 0);
+    m_on = NdbTick_CurrentMillisecond();
+  }
+  void off(unsigned cnt = 0) {
+    NDB_TICKS off = NdbTick_CurrentMillisecond();
+    assert(m_on != 0 && off >= m_on);
+    m_ms += off - m_on;
+    m_cnt += cnt;
+    m_on = 0;
+  }
+  const char* time() {
+    if (m_cnt == 0)
+      sprintf(m_time, "%u ms", m_ms);
+    else
+      sprintf(m_time, "%u ms per %u ( %u ms per 1000 )", m_ms, m_cnt, (1000 * m_ms) / m_cnt);
+    return m_time;
+  }
+  const char* pct (const Tmr& t1) {
+    if (0 < t1.m_ms)
+      sprintf(m_text, "%u pct", (100 * m_ms) / t1.m_ms);
+    else
+      sprintf(m_text, "[cannot measure]");
+    return m_text;
+  }
+  const char* over(const Tmr& t1) {
+    if (0 < t1.m_ms) {
+      if (t1.m_ms <= m_ms)
+        sprintf(m_text, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms);
+      else
+        sprintf(m_text, "-%u pct", (100 * (t1.m_ms - m_ms)) / t1.m_ms);
+    } else
+      sprintf(m_text, "[cannot measure]");
+    return m_text;
+  }
+  NDB_TICKS m_on;
+  unsigned m_ms;
+  unsigned m_cnt;
+  char m_time[100];
+  char m_text[100];
+};
+
+static int
+testperf()
+{
+  if (! testcase('p'))
+    return 0;
+  DBG("=== perf test ===");
+  g_ndb = new Ndb("TEST_DB");
+  CHK(g_ndb->init() == 0);
+  CHK(g_ndb->waitUntilReady() == 0);
+  g_dic = g_ndb->getDictionary();
+  NdbDictionary::Table tab(g_opt.m_tnameperf);
+  if (g_dic->getTable(tab.getName()) != 0)
+    CHK(g_dic->dropTable(tab) == 0);
+  // col A - pk
+  { NdbDictionary::Column col("A");
+    col.setType(NdbDictionary::Column::Unsigned);
+    col.setPrimaryKey(true);
+    tab.addColumn(col);
+  }
+  // col B - char 20
+  { NdbDictionary::Column col("B");
+    col.setType(NdbDictionary::Column::Char);
+    col.setLength(20);
+    col.setNullable(true);
+    tab.addColumn(col);
+  }
+  // col C - text
+  { NdbDictionary::Column col("C");
+    col.setType(NdbDictionary::Column::Text);
+    col.setInlineSize(20);
+    col.setPartSize(512);
+    col.setStripeSize(1);
+    col.setNullable(true);
+    tab.addColumn(col);
+  }
+  // create
+  CHK(g_dic->createTable(tab) == 0);
+  Uint32 cA = 0, cB = 1, cC = 2;
+  // timers
+  Tmr t1;
+  Tmr t2;
+  // insert char (one trans)
+  {
+    DBG("--- insert char ---");
+    t1.on();
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+      CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+      CHK(g_opr->insertTuple() == 0);
+      CHK(g_opr->equal(cA, (char*)&k) == 0);
+      CHK(g_opr->setValue(cB, "b") == 0);
+      CHK(g_con->execute(NoCommit) == 0);
+    }
+    t1.off(g_opt.m_rowsperf);
+    CHK(g_con->execute(Rollback) == 0);
+    DBG(t1.time());
+    g_opr = 0;
+    g_con = 0;
+  }
+  // insert text (one trans)
+  {
+    DBG("--- insert text ---");
+    t2.on();
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+      CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+      CHK(g_opr->insertTuple() == 0);
+      CHK(g_opr->equal(cA, (char*)&k) == 0);
+      CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0);
+      CHK((g_bh1->setValue("c", 1) == 0));
+      CHK(g_con->execute(NoCommit) == 0);
+    }
+    t2.off(g_opt.m_rowsperf);
+    CHK(g_con->execute(Rollback) == 0);
+    DBG(t2.time());
+    g_bh1 = 0;
+    g_opr = 0;
+    g_con = 0;
+  }
+  // insert overhead
+  DBG("insert overhead: " << t2.over(t1));
+  t1.clr();
+  t2.clr();
+  // insert
+  {
+    DBG("--- insert for read test ---");
+    unsigned n = 0;
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+      CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+      CHK(g_opr->insertTuple() == 0);
+      CHK(g_opr->equal(cA, (char*)&k) == 0);
+      CHK(g_opr->setValue(cB, "b") == 0);
+      CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0);
+      CHK((g_bh1->setValue("c", 1) == 0));
+      if (++n == g_opt.m_batch) {
+        CHK(g_con->execute(Commit) == 0);
+        g_ndb->closeTransaction(g_con);
+        CHK((g_con = g_ndb->startTransaction()) != 0);
+        n = 0;
+      }
+    }
+    if (n != 0) {
+      CHK(g_con->execute(Commit) == 0);
+      n = 0;
+    }
+    g_bh1 = 0;
+    g_opr = 0;
+    g_con = 0;
+  }
+  // pk read char (one trans)
+  {
+    DBG("--- pk read char ---");
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    Uint32 a;
+    char b[20];
+    t1.on();
+    for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+      CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+      CHK(g_opr->readTuple() == 0);
+      CHK(g_opr->equal(cA, (char*)&k) == 0);
+      CHK(g_opr->getValue(cA, (char*)&a) != 0);
+      CHK(g_opr->getValue(cB, b) != 0);
+      a = (Uint32)-1;
+      b[0] = 0;
+      CHK(g_con->execute(NoCommit) == 0);
+      CHK(a == k && strcmp(b, "b") == 0);
+    }
+    CHK(g_con->execute(Commit) == 0);
+    t1.off(g_opt.m_rowsperf);
+    DBG(t1.time());
+    g_opr = 0;
+    g_con = 0;
+  }
+  // pk read text (one trans)
+  {
+    DBG("--- pk read text ---");
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    Uint32 a;
+    char c[20];
+    t2.on();
+    for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+      CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+      CHK(g_opr->readTuple() == 0);
+      CHK(g_opr->equal(cA, (char*)&k) == 0);
+      CHK(g_opr->getValue(cA, (char*)&a) != 0);
+      CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0);
+      a = (Uint32)-1;
+      c[0] = 0;
+      CHK(g_con->execute(NoCommit) == 0);
+      Uint32 m = 20;
+      CHK(g_bh1->readData(c, m) == 0);
+      CHK(a == k && m == 1 && strcmp(c, "c") == 0);
+    }
+    CHK(g_con->execute(Commit) == 0);
+    t2.off(g_opt.m_rowsperf);
+    DBG(t2.time());
+    g_opr = 0;
+    g_con = 0;
+  }
+  // pk read overhead
+  DBG("pk read overhead: " << t2.over(t1));
+  t1.clr();
+  t2.clr();
+  // scan read char
+  {
+    DBG("--- scan read char ---");
+    NdbResultSet* rs;
+    Uint32 a;
+    char b[20];
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
+    CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+    CHK(g_ops->getValue(cA, (char*)&a) != 0);
+    CHK(g_ops->getValue(cB, b) != 0);
+    CHK(g_con->execute(NoCommit) == 0);
+    unsigned n = 0;
+    t1.on();
+    while (1) {
+      a = (Uint32)-1;
+      b[0] = 0;
+      int ret;
+      CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+      if (ret == 1)
+        break;
+      CHK(a < g_opt.m_rowsperf && strcmp(b, "b") == 0);
+      n++;
+    }
+    CHK(n == g_opt.m_rowsperf);
+    t1.off(g_opt.m_rowsperf);
+    DBG(t1.time());
+    g_ops = 0;
+    g_con = 0;
+  }
+  // scan read text
+  {
+    DBG("--- read text ---");
+    NdbResultSet* rs;
+    Uint32 a;
+    char c[20];
+    CHK((g_con = g_ndb->startTransaction()) != 0);
+    CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
+    CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+    CHK(g_ops->getValue(cA, (char*)&a) != 0);
+    CHK((g_bh1 = g_ops->getBlobHandle(cC)) != 0);
+    CHK(g_con->execute(NoCommit) == 0);
+    unsigned n = 0;
+    t2.on();
+    while (1) {
+      a = (Uint32)-1;
+      c[0] = 0;
+      int ret;
+      CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+      if (ret == 1)
+        break;
+      Uint32 m = 20;
+      CHK(g_bh1->readData(c, m) == 0);
+      CHK(a < g_opt.m_rowsperf && m == 1 && strcmp(c, "c") == 0);
+      n++;
+    }
+    CHK(n == g_opt.m_rowsperf);
+    t2.off(g_opt.m_rowsperf);
+    DBG(t2.time());
+    g_bh1 = 0;
+    g_ops = 0;
+    g_con = 0;
+  }
+  // scan read overhead
+  DBG("scan read overhead: " << t2.over(t1));
+  t1.clr();
+  t2.clr();
+  delete g_ndb;
+  return 0;
+}
+
 // bug tests
 
 static int
@@ -1498,6 +1793,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
 	continue;
       }
     }
+    if (strcmp(arg, "-rowsperf") == 0) {
+      if (++argv, --argc > 0) {
+	g_opt.m_rowsperf = atoi(argv[0]);
+	continue;
+      }
+    }
     if (strcmp(arg, "-seed") == 0) {
       if (++argv, --argc > 0) {
 	g_opt.m_seed = atoi(argv[0]);
@@ -1558,7 +1859,7 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
     strcat(b, "r");
     g_opt.m_skip = strdup(b);
   }
-  if (testmain() == -1) {
+  if (testmain() == -1 || testperf() == -1) {
     ndbout << "line " << __LINE__ << " FAIL loop=" << g_loop << endl;
     return NDBT_ProgramExit(NDBT_FAILED);
   }
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 51e12ff23f9..2778bdedee6 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -468,6 +468,7 @@ Query_cache query_cache;
 #ifdef HAVE_SMEM
 char *shared_memory_base_name= default_shared_memory_base_name;
 bool opt_enable_shared_memory;
+HANDLE smem_event_connect_request= 0;
 #endif
 
 #include "sslopt-vars.h"
@@ -743,6 +744,15 @@ void kill_mysql(void)
       CloseHandle(hEvent);
     */
   }
+#ifdef HAVE_SMEM
+    /*
+     Send event to smem_event_connect_request for aborting
+    */
+    if (!SetEvent(smem_event_connect_request))
+    {
+      DBUG_PRINT("error",("Got error: %ld from SetEvent of smem_event_connect_request",GetLastError()));
+    }
+#endif  
 #endif
 #elif defined(OS2)
   pthread_cond_signal( &eventShutdown);		// post semaphore
@@ -3709,7 +3719,6 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
   /* file-mapping object, use for create shared memory */
   HANDLE handle_connect_file_map= 0;
   char  *handle_connect_map= 0;  		// pointer on shared memory
-  HANDLE event_connect_request= 0;		// for start connection actions
   HANDLE event_connect_answer= 0;
   ulong smem_buffer_length= shared_memory_buffer_length + 4;
   ulong connect_number= 1;
@@ -3730,7 +3739,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
   */
   suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
   strmov(suffix_pos, "CONNECT_REQUEST");
-  if ((event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+  if ((smem_event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
   {
     errmsg= "Could not create request event";
     goto error;
@@ -3761,7 +3770,13 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
   while (!abort_loop)
   {
     /* Wait a request from client */
-    WaitForSingleObject(event_connect_request,INFINITE);
+    WaitForSingleObject(smem_event_connect_request,INFINITE);
+
+    /*
+       it can be after shutdown command
+    */
+    if (abort_loop) 
+      goto error;
 
     HANDLE handle_client_file_map= 0;
     char  *handle_client_map= 0;
@@ -3886,7 +3901,7 @@ error:
   if (handle_connect_map)	UnmapViewOfFile(handle_connect_map);
   if (handle_connect_file_map)	CloseHandle(handle_connect_file_map);
   if (event_connect_answer)	CloseHandle(event_connect_answer);
-  if (event_connect_request)	CloseHandle(event_connect_request);
+  if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
 
   decrement_handler_count();
   DBUG_RETURN(0);