List:Internals« Previous MessageNext Message »
From:Patrick Galbraith Date:November 25 2005 8:38pm
Subject:bk commit into 5.1 tree (patg:1.1964)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of patg. When patg 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
  1.1964 05/11/25 11:38:36 patg@stripped +7 -0
  Worklog #2983 Mysqlslap load emulator tool and accompanied test, results
  and modifications to mysql-test-run(.pl/.sh)

  mysql-test/t/mysqlslap.test
    1.1 05/11/25 11:38:19 patg@stripped +9 -0
    Worklog #2983 Added mysqlslap test

  mysql-test/t/mysqlslap.test
    1.0 05/11/25 11:38:19 patg@stripped +0 -0
    BitKeeper file /home/patg/mysql-build/mysql-5.1-slap/mysql-test/t/mysqlslap.test

  mysql-test/r/mysqlslap.result
    1.1 05/11/25 11:38:18 patg@stripped +60 -0
    Worklog #2983 Mysqlslap test results

  client/mysqlslap.c
    1.1 05/11/25 11:38:18 patg@stripped +1109 -0
    Worklog #2983 mysqlslap.c, new utility for running load simulation.

  mysql-test/r/mysqlslap.result
    1.0 05/11/25 11:38:18 patg@stripped +0 -0
    BitKeeper file /home/patg/mysql-build/mysql-5.1-slap/mysql-test/r/mysqlslap.result

  mysql-test/mysql-test-run.sh
    1.280 05/11/25 11:38:18 patg@stripped +11 -0
    Worklog #2983 Added mysqlslap binary def to test script

  mysql-test/mysql-test-run.pl
    1.42 05/11/25 11:38:18 patg@stripped +13 -2
    Worklog #2983 Added mysqlslap test binary to test script

  client/mysqlslap.c
    1.0 05/11/25 11:38:18 patg@stripped +0 -0
    BitKeeper file /home/patg/mysql-build/mysql-5.1-slap/client/mysqlslap.c

  client/client_priv.h
    1.44 05/11/25 11:38:17 patg@stripped +1 -1
    Worklog #2983 Added OPT_CREATE_SLAP_SCHEMA

  client/Makefile.am
    1.53 05/11/25 11:38:17 patg@stripped +3 -1
    Worklog #2983, added mysqlslap to Makefile.am

# 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:	patg
# Host:	krsna.patg.net
# Root:	/home/patg/mysql-build/mysql-5.1-slap

--- 1.52/client/Makefile.am	2005-11-09 01:26:52 -08:00
+++ 1.53/client/Makefile.am	2005-11-25 11:38:17 -08:00
@@ -31,7 +31,8 @@
                                 $(top_builddir)/libmysql/libmysqlclient.la
 bin_PROGRAMS =			mysql mysqladmin mysqlcheck mysqlshow \
 				mysqldump mysqlimport mysqltest mysqlbinlog \
-				mysqltestmanagerc mysqltestmanager-pwgen
+				mysqltestmanagerc mysqltestmanager-pwgen \
+				mysqlslap
 noinst_HEADERS =		sql_string.h completion_hash.h my_readline.h \
 				client_priv.h
 mysql_SOURCES =			mysql.cc readline.cc sql_string.cc completion_hash.cc
@@ -46,6 +47,7 @@
 mysqltestmanagerc_SOURCES=      mysqlmanagerc.c $(yassl_dummy_link_fix)
 mysqlcheck_SOURCES=             mysqlcheck.c $(yassl_dummy_link_fix)
 mysqlshow_SOURCES=              mysqlshow.c $(yassl_dummy_link_fix)
+mysqlslap_SOURCES=              mysqlslap.c $(yassl_dummy_link_fix)
 mysqldump_SOURCES=              mysqldump.c $(yassl_dummy_link_fix)
 mysqlimport_SOURCES=            mysqlimport.c $(yassl_dummy_link_fix)
 sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc

--- 1.279/mysql-test/mysql-test-run.sh	2005-11-18 07:06:32 -08:00
+++ 1.280/mysql-test/mysql-test-run.sh	2005-11-25 11:38:18 -08:00
@@ -243,6 +243,7 @@
 EXTRA_MYSQL_TEST_OPT=""
 EXTRA_MYSQLCHECK_OPT=""
 EXTRA_MYSQLDUMP_OPT=""
+EXTRA_MYSQLSLAP_OPT=""
 EXTRA_MYSQLSHOW_OPT=""
 EXTRA_MYSQLBINLOG_OPT=""
 USE_RUNNING_SERVER=0
@@ -519,6 +520,8 @@
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlcheck.trace"
       EXTRA_MYSQLDUMP_OPT="$EXTRA_MYSQLDUMP_OPT \
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqldump.trace"
+      EXTRA_MYSQLSLAP_OPT="$EXTRA_MYSQLSLAP_OPT \
+       --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlslap.trace"
       EXTRA_MYSQLSHOW_OPT="$EXTRA_MYSQLSHOW_OPT \
        --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlshow.trace"
       EXTRA_MYSQLBINLOG_OPT="$EXTRA_MYSQLBINLOG_OPT \
@@ -629,6 +632,11 @@
  else
    MYSQL_DUMP="$BASEDIR/client/mysqldump"
  fi
+ if [ -f "$BASEDIR/client/.libs/mysqlslap" ] ; then
+   MYSQL_SLAP="$BASEDIR/client/.libs/mysqlslap"
+ else
+   MYSQL_SLAP="$BASEDIR/client/mysqlslap"
+ fi
  if [ -f "$BASEDIR/client/.libs/mysqlimport" ] ; then
    MYSQL_IMPORT="$BASEDIR/client/.libs/mysqlimport"
  else
@@ -709,6 +717,7 @@
  MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
  MYSQL_CHECK="$CLIENT_BINDIR/mysqlcheck"
  MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
+ MYSQL_SLAP="$CLIENT_BINDIR/mysqlslap"
  MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow"
  MYSQL_IMPORT="$CLIENT_BINDIR/mysqlimport"
  MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
@@ -796,6 +805,7 @@
 export MYSQL_DUMP_DIR
 MYSQL_CHECK="$MYSQL_CHECK --no-defaults -uroot --socket=$MASTER_MYSOCK
--password=$DBPASSWD $EXTRA_MYSQLCHECK_OPT"
 MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD
$EXTRA_MYSQLDUMP_OPT"
+MYSQL_SLAP="$MYSQL_SLAP -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD
$EXTRA_MYSQLSLAP_OPT"
 MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD
$EXTRA_MYSQLSHOW_OPT"
 MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR 
--character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
 MYSQL_IMPORT="$MYSQL_IMPORT -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD
$EXTRA_MYSQLDUMP_OPT"
@@ -803,6 +813,7 @@
 MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT
--socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
 export MYSQL MYSQL_CHECK MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES
MYSQL_IMPORT
 export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS
+export MYSQL_SLAP
 export NDB_TOOLS_DIR
 export NDB_MGM
 export NDB_BACKUP_DIR

--- 1.41/mysql-test/mysql-test-run.pl	2005-11-18 07:06:32 -08:00
+++ 1.42/mysql-test/mysql-test-run.pl	2005-11-25 11:38:18 -08:00
@@ -173,6 +173,7 @@
 our $exe_mysqld;
 our $exe_mysqlcheck;             # Called from test case
 our $exe_mysqldump;              # Called from test case
+our $exe_mysqlslap;              # Called from test case
 our $exe_mysqlimport;              # Called from test case
 our $exe_mysqlshow;              # Called from test case
 our $exe_mysql_fix_system_tables;
@@ -930,7 +931,8 @@
     }
     $exe_mysqlcheck=     mtr_exe_exists("$path_client_bindir/mysqlcheck");
     $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
-    $exe_mysqlimport=    mtr_exe_exists("$path_client_bindir/mysqlimport");
+    $exe_mysqlslap=      mtr_exe_exists("$path_client_bindir/mysqlslap");
+    $exe_mysqlimport=      mtr_exe_exists("$path_client_bindir/mysqlimport");
     $exe_mysqlshow=      mtr_exe_exists("$path_client_bindir/mysqlshow");
     $exe_mysqlbinlog=    mtr_exe_exists("$path_client_bindir/mysqlbinlog");
     $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
@@ -947,7 +949,7 @@
     $path_client_bindir= mtr_path_exists("$glob_basedir/bin");
     $exe_mysqlcheck=     mtr_exe_exists("$path_client_bindir/mysqlcheck");
     $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
-    $exe_mysqlimport=    mtr_exe_exists("$path_client_bindir/mysqlimport");
+    $exe_mysqlslap=      mtr_exe_exists("$path_client_bindir/mysqlslap");
     $exe_mysqlshow=      mtr_exe_exists("$path_client_bindir/mysqlshow");
     $exe_mysqlbinlog=    mtr_exe_exists("$path_client_bindir/mysqlbinlog");
     $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
@@ -2458,6 +2460,14 @@
     $cmdline_mysqldump .=
       " --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
   }
+  my $cmdline_mysqlslap= "$exe_mysqlslap -uroot " .
+                         "--port=$master->[0]->{'path_myport'} " .
+                         "--socket=$master->[0]->{'path_mysock'} --password=";
+  if ( $opt_debug )
+  {
+    $cmdline_mysqlslap .=
+      " --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
+  }
   my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " .
                          "--port=$master->[0]->{'path_myport'} " .
                          "--socket=$master->[0]->{'path_mysock'} --password=";
@@ -2519,6 +2529,7 @@
   $ENV{'MYSQL'}=                    $cmdline_mysql;
   $ENV{'MYSQL_CHECK'}=              $cmdline_mysqlcheck;
   $ENV{'MYSQL_DUMP'}=               $cmdline_mysqldump;
+  $ENV{'MYSQL_SLAP'}=               $cmdline_mysqlslap;
   $ENV{'MYSQL_IMPORT'}=             $cmdline_mysqlimport;
   $ENV{'MYSQL_SHOW'}=               $cmdline_mysqlshow;
   $ENV{'MYSQL_BINLOG'}=             $cmdline_mysqlbinlog;

--- 1.43/client/client_priv.h	2005-10-12 22:44:16 -07:00
+++ 1.44/client/client_priv.h	2005-11-25 11:38:17 -08:00
@@ -51,5 +51,5 @@
 #endif
   OPT_TRIGGERS,
   OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
-  OPT_TZ_UTC, OPT_AUTO_CLOSE
+  OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA
 };
--- New file ---
+++ client/mysqlslap.c	05/11/25 11:38:18
/* Copyright (C) 2000 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Show databases, tables or columns */

/*
  MySQL slap run three stages:
  1) Create Schema (single thread)
  2) Insert data (many threads)
  3) Load test (many threads)

Example:
./mysqlslap --create="CREATE TABLE A (a int)" --data="INSERT INTO A (23)" --iterations=200
            --query="SELECT * FROM A" --concurrency=50
*/

#define SHOW_VERSION "0.1"

#define HUGE_STRING_LENGTH 8096
#define ALPHANUMERICS "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
#define RAND_STRING_SIZE 126

#include "client_priv.h"
#include <my_sys.h>
#include <m_string.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <my_dir.h>
#include <signal.h>
#include <stdarg.h>
#include <sslopt-vars.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/wait.h>


static int drop_schema(MYSQL *mysql, const char *db);
unsigned int get_random_number(void);
unsigned int get_random_string(char *buf);
static int build_table_string(void);
static int build_insert_string(void);
static int build_query_string(void);
static int create_schema(MYSQL *mysql, const char *db,const char *script);
static int run_scheduler(const char *script, int(*task)(const char *),
                         unsigned int concur);
int run_task(const char *script);
int load_data(const char *script);

static my_string host=0, opt_password=0, user=0, user_supplied_query= 0,
  user_supplied_data=0, create_string=0, default_engine=0, delimiter=0;

static my_bool opt_compress= 0, opt_count=0, tty_password= 0, opt_drop=0,
    create_string_alloced=0, insert_string_alloced=0, query_string_alloced=0,
    generated_insert_flag=0, opt_silent=0, auto_generate_sql=0,
    opt_skip_create=0, opt_skip_data_load=0, opt_skip_query=0;

static int verbose=0, num_int_cols=-1, num_char_cols=-1, delimiter_length=0;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
static unsigned int number_of_rows= 1000, number_of_iterations=1000,
  concurrency= 1, concurrency_load= 1, children_spawned=1;

const char *default_dbug_option="d:t:o,/tmp/mysqlslap.trace";

static uint opt_protocol=0;

static void get_options(int *argc,char ***argv);
static uint opt_mysql_port=0;

static const char *load_default_groups[]= { "mysqlslap","client",0 };
static my_string opt_mysql_unix_port=0;

/* returns the time in ms between two timevals */

static double timedif(struct timeval end, struct timeval begin)
{
  double seconds;
  DBUG_ENTER("timedif");

  seconds= (double)(end.tv_usec - begin.tv_usec)/1000000;
  DBUG_PRINT("info", ("end.tv_usec %d - begin.tv_usec %d = %d microseconds ( fseconds
%f)",
                      end.tv_usec, begin.tv_usec,
                      (end.tv_usec - begin.tv_usec),
                      seconds));
  seconds += (double)(end.tv_sec - begin.tv_sec);
  DBUG_PRINT("info", ("end.tv_sec %d - begin.tv_sec %d = %d seconds (fseconds %f)",
                      end.tv_sec, begin.tv_sec,
                      (end.tv_sec - begin.tv_sec), seconds));

  DBUG_PRINT("info", ("returning time %f seconds", seconds));
  DBUG_RETURN(seconds);
}


int main(int argc, char **argv)
{
  my_bool first_argument_uses_wildcards=0;
  char *wild;
  MYSQL mysql;
  int client_flag=0;
  double time_difference;
  MY_INIT(argv[0]);
  struct timeval start_time, load_time, run_time;

  DBUG_ENTER("main");

  bzero(&load_time, sizeof(struct timeval));
  bzero(&run_time, sizeof(struct timeval));
  load_defaults("my",load_default_groups,&argc,&argv);
  get_options(&argc,&argv);
  /*
    globals? Yes, so we only have to run strlen once
  */
  if (delimiter)
    delimiter_length=strlen(delimiter);

  wild=0;
  if (argc)
  {
    char *pos= argv[argc-1], *to;
    for (to= pos ; *pos ; pos++, to++)
    {
      switch (*pos) {
      case '*':
        *pos= '%';
        first_argument_uses_wildcards= 1;
        break;
      case '?':
        *pos= '_';
        first_argument_uses_wildcards= 1;
        break;
      case '%':
      case '_':
        first_argument_uses_wildcards= 1;
        break;
      case '\\':
        pos++;
      default: break;
      }
      *to= *pos;
    }
    *to= *pos; /* just to copy a '\0'  if '\\' was used */
  }
  if (first_argument_uses_wildcards)
    wild= argv[--argc];
  else if (argc == 3)			/* We only want one field */
    wild= argv[--argc];

  if (argc > 2)
  {
    fprintf(stderr,"%s: Too many arguments\n",my_progname);
    exit(1);
  }
  mysql_init(&mysql);
  if (opt_compress)
    mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
#ifdef HAVE_OPENSSL
  if (opt_use_ssl)
    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
                  opt_ssl_capath, opt_ssl_cipher);
#endif
  if (opt_protocol)
    mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
#ifdef HAVE_SMEM
  if (shared_memory_base_name)
    mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
#endif
  mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);

  client_flag|= CLIENT_MULTI_RESULTS;
  if (!(mysql_real_connect(&mysql,host,user,opt_password,
                           (first_argument_uses_wildcards) ? "" :
                           argv[0],opt_mysql_port,opt_mysql_unix_port,
                           client_flag)))
  {
    fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
    exit(1);
  }

  mysql.reconnect= 1;

  /*
    we might not want to load any data, if for instance we are calling
    a stored_procedure that doesn't use data, or we know we already have 
    data in the table
  */
  if (opt_drop)
    drop_schema(&mysql, "mysqlslap");

  if (! opt_skip_create)
    create_schema(&mysql, "mysqlslap", create_string);

  if (! opt_skip_data_load)
  {
    gettimeofday(&start_time, NULL);
    DBUG_PRINT("info", ("user_supplied_data %s", user_supplied_data));
    run_scheduler(user_supplied_data, load_data, concurrency_load);
    gettimeofday(&load_time, NULL);
    time_difference= timedif(load_time, start_time);
    if (!opt_silent)
    {
      printf("Data load took %f seconds\n",time_difference);
      printf("Clients spawned %d number of inserts per child %d\n",
             children_spawned, number_of_rows);
    }
  }

  if (! opt_skip_query)
  {
    run_scheduler(user_supplied_query, run_task, concurrency);
    gettimeofday(&run_time, 0);
    time_difference= timedif(run_time, load_time);

    if (!opt_silent)
    {
      printf("Running task took %f seconds\n", time_difference);
      printf("Clients spawned %d number of queries per child %d\n",
             children_spawned, number_of_iterations);
    }
  }
  if (opt_drop)
    drop_schema(&mysql, "mysqlslap");

  mysql_close(&mysql); /* Close & free connection */

  /* now free all the strings we created */
  if (opt_password)
    my_free(opt_password,MYF(0));
  if (create_string_alloced)
    my_free(create_string,MYF(0));
  if (insert_string_alloced)
    my_free(user_supplied_data,MYF(0));
  if (query_string_alloced)
    my_free(user_supplied_query,MYF(0));
#ifdef HAVE_SMEM
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif
  my_end(0);

  DBUG_RETURN(0); /* No compiler warnings */
}

static struct my_option my_long_options[] =
{
  {"auto-generate-sql", 'a', "Generate SQL where not supplied by file or command line.",
    (gptr*) &auto_generate_sql, (gptr*) &auto_generate_sql,
    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"compress", 'C', "Use compression in server/client protocol.",
    (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
    0, 0, 0},
  {"concurrency-load", 'l', "Number of clients to simulate for data load.",
    (gptr*) &concurrency_load, (gptr*) &concurrency_load, 0,
    GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"concurrency", 'c', "Number of clients to simulate for query to run.",
    (gptr*) &concurrency, (gptr*) &concurrency, 0, GET_UINT,
    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"create", OPT_CREATE_SLAP_SCHEMA, "File or string to use for create.",
    (gptr*) &create_string, (gptr*) &create_string, 0, GET_STR, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
  {"data", 'd', 
    "Insert statement or file containing the insert statement to populcate the table
with.",
    (gptr*) &user_supplied_data, (gptr*) &user_supplied_data, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
    (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR,
    OPT_ARG, 0, 0, 0, 0, 0, 0},
  {"delimiter", 'F', "Delimiter to use in SQL statements supplied in file or command
line.", (gptr*) &delimiter,
    (gptr*) &delimiter, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"drop-schema", 'D',
    "Drop schema if it exists prior to running, and after running",
    (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"engine", 'e', "Engine to create the table as.", (gptr*) &default_engine,
    (gptr*) &default_engine, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG,
    0, 0, 0, 0, 0, 0},
  {"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR,
    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"iterations", 'i', "Number of iterations.", (gptr*) &number_of_iterations,
    (gptr*) &number_of_iterations, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"number-char-cols", 'x', "Number of int columns to create table with in
--sql-generate-sql.",
    (gptr*) &num_char_cols, (gptr*) &num_char_cols, 0, GET_UINT, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
  {"number-int-cols", 'y', "Number of varchar columns to create table with in
--sql-generate-sql.",
    (gptr*) &num_int_cols, (gptr*) &num_int_cols, 0, GET_UINT, REQUIRED_ARG,
    0, 0, 0, 0, 0, 0},
  {"number-rows", 'n', "Number of rows to insert in data load.", (gptr*)
&number_of_rows,
    (gptr*) &number_of_rows, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"password", 'p',
    "Password to use when connecting to server. If password is not given it's asked from
the tty.",
    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
  {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
    (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
    0},
#ifdef __WIN__
  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
    NO_ARG, 0, 0, 0, 0, 0, 0},
#endif
  {"protocol", OPT_MYSQL_PROTOCOL,
    "The protocol of connection (tcp,socket,pipe,memory).",
    0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"skip-create-schema", 'A', "Don't create a schema, use existing schema.",
    (gptr*) &opt_skip_create, (gptr*) &opt_skip_create, 0, GET_BOOL,  NO_ARG,
    0, 0, 0, 0, 0, 0},
  {"skip-data-load", 'L', "Don't load any data, use existing data set.",
    (gptr*) &opt_skip_data_load, (gptr*) &opt_skip_data_load, 0,
    GET_BOOL,  NO_ARG, 0, 0, 0, 0, 0, 0},
  {"skip-query", 'Q', "Don't run any queries.",
    (gptr*) &opt_skip_query, (gptr*) &opt_skip_query, 0, GET_BOOL,  NO_ARG,
    0, 0, 0, 0, 0, 0},
  {"silent", 's', "Run program in silent mode - no output.",
    (gptr*) &opt_silent, (gptr*) &opt_silent, 0, GET_BOOL,  NO_ARG,
    0, 0, 0, 0, 0, 0},
#ifdef HAVE_SMEM
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
    "Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*)
&shared_memory_base_name,
    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
  {"query", 'q', "Query to run or file containing query to run.",
    (gptr*) &user_supplied_query, (gptr*) &user_supplied_query,
    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"socket", 'S', "Socket file to use for connection.",
    (gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h>
#ifndef DONT_ALLOW_USER_CHANGE
  {"user", 'u', "User for login if not current user.", (gptr*) &user,
    (gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
  {"verbose", 'v',
    "More verbose output; You can use this multiple times to get even more verbose
output.",
    (gptr*) &verbose, (gptr*) &verbose, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
    NO_ARG, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};


#include <help_start.h>

static void print_version(void)
{
  printf("%s  Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
         MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
}


static void usage(void)
{
  print_version();
  puts("Copyright (C) 2005 MySQL AB");
  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\
       \nand you are welcome to modify and redistribute it under the GPL \
       license\n");
  puts("Run a query multiple times against the server\n");
  printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
  print_defaults("my",load_default_groups);
  my_print_help(my_long_options);
}

#include <help_end.h>

static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
               char *argument)
{
  DBUG_ENTER("get_one_option");
  switch(optid) {
  case 'a':
    auto_generate_sql=TRUE;
    break;
  case 'A':
    opt_skip_create=TRUE;
    break;
  case 'L':
    opt_skip_data_load=TRUE;
    break;
  case 'Q':
    opt_skip_query=TRUE;
    break;
#ifdef __NETWARE__
  case OPT_AUTO_CLOSE:
    setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
    break;
#endif
  case 'v':
    verbose++;
    break;
  case 'p':
    if (argument)
    {
      char *start=argument;
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
      opt_password=my_strdup(argument,MYF(MY_FAE));
      while (*argument) *argument++= 'x';		/* Destroy argument */
      if (*start)
        start[1]=0;				/* Cut length of argument */
      tty_password= 0;
    }
    else
      tty_password=1;
    break;
  case 'W':
#ifdef __WIN__
    opt_protocol= MYSQL_PROTOCOL_PIPE;
#endif
    break;
  case OPT_MYSQL_PROTOCOL:
    {
      if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
      {
        fprintf(stderr, "Unknown option to protocol: %s\n", argument);
        exit(1);
      }
      break;
    }
  case '#':
    DBUG_PUSH(argument ? argument : default_dbug_option);
    break;
#include <sslopt-case.h>
  case 'V':
    print_version();
    exit(0);
    break;
  case '?':
  case 'I':					/* Info */
    usage();
    exit(0);
  }
  DBUG_RETURN(0);
}

/*
  get_random_number()

  returns a random number to be used in building an sql statement
*/
unsigned int
get_random_number(void)
{
  int num;
  char rstate[8];
  struct timeval timestruct;

  DBUG_ENTER("get_random_number");
  gettimeofday(&timestruct, NULL);
  initstate(timestruct.tv_usec, rstate, sizeof(rstate));
  setstate(rstate);
  num= random()%128;
  DBUG_RETURN(num);
}

unsigned int
get_random_string(char *buf)
{
  char *buf_ptr=buf;
  int x=0, chr=0;
  struct timeval timestruct;

  DBUG_ENTER("get_random_string");
  gettimeofday(&timestruct, NULL);
  srandom((unsigned int) timestruct.tv_usec);
  for (x= RAND_STRING_SIZE; x > 0; x--)
  {
    /*
      why this tmp_num? Because for some reason, x's value gets
      munged if I use chr=random() % x;
      Some strange optimisation of gcc????
    */
    int tmp_num= x;
    chr= random()% tmp_num;
    /*
      avoiding problematic chars for insert
    */
    if (chr >= 48 && chr <= 122 && chr != 96 && chr != 92)
      *buf_ptr++= chr;
  }
  *buf_ptr++= '\0';

  /*
    strlen
  */
  DBUG_RETURN(buf_ptr- buf);
}

/*
  build_table_string

  This function builds a create table query if the user opts to not supply
  a file or string containing a create table statement
*/
static int
build_table_string(void)
{
  char       buf[512];
  int        col_count;
  static DYNAMIC_STRING table_string;
  DBUG_ENTER("build_table_string");

  DBUG_PRINT("info", ("num int cols %d num char cols %d",
                      num_int_cols, num_char_cols));

  init_dynamic_string(&table_string, "", 1024, 1024);

  dynstr_append_mem(&table_string, "CREATE TABLE t1 (\n", 18);
  for (col_count= 1; col_count <= num_int_cols; col_count++)
  {
    sprintf(buf, "intcol%d INT(32)", col_count);
    dynstr_append(&table_string, buf);

    if (col_count < num_int_cols || num_char_cols > 0)
      dynstr_append_mem(&table_string, ",", 1);

    dynstr_append_mem(&table_string, "\n", 1);
  }
  for (col_count= 1; col_count <= num_char_cols; col_count++)
  {
    sprintf(buf, "charcol%d VARCHAR(128)", col_count);
    dynstr_append(&table_string, buf);

    if (col_count < num_char_cols)
      dynstr_append_mem(&table_string, ",", 1);

    dynstr_append_mem(&table_string, "\n", 1);
  }
  dynstr_append_mem(&table_string, ")\n", 2);
  create_string= (char *)my_malloc(table_string.length+1, MYF(MY_WME));
  create_string_alloced=1;
  sprintf(create_string, "%s", table_string.str);
  DBUG_PRINT("info", ("create_string %s", create_string));
  dynstr_free(&table_string);
  DBUG_RETURN(0);
}

/*
  build_insert_string()

  This function builds insert statements when the user opts to not supply
  a insert file or string containing insert data
*/
static int
build_insert_string(void)
{
  char       buf[512];
  int        col_count;
  DYNAMIC_STRING insert_string;
  MYSQL      mysql;
  DBUG_ENTER("build_insert_string");
  mysql_init(&mysql);

  init_dynamic_string(&insert_string, "", 1024, 1024);

  dynstr_append_mem(&insert_string, "INSERT INTO t1 VALUES (", 23);
  for (col_count= 1; col_count <= num_int_cols; col_count++)
  {
    sprintf(buf, "%d", get_random_number());
    dynstr_append(&insert_string, buf);

    if (col_count < num_int_cols || num_char_cols > 0)
      dynstr_append_mem(&insert_string, ",", 1);
  }
  for (col_count= 1; col_count <= num_char_cols; col_count++)
  {
    char buf_tmp[200];
    int buf_len;
    buf_len= get_random_string((char *) &buf);
    mysql_real_escape_string(&mysql, (char *) &buf_tmp, (char *) &buf,
buf_len);
    dynstr_append_mem(&insert_string, "'", 1);
    dynstr_append(&insert_string, buf_tmp);
    dynstr_append_mem(&insert_string, "'", 1);

    if (col_count < num_char_cols)
      dynstr_append_mem(&insert_string, ",", 1);

  }
  dynstr_append_mem(&insert_string, ")", 1);

  /*
    since this function can be called if the user wants varying insert
    statement in the for loop where inserts run, free in advance
  */
  if (insert_string_alloced)
    my_free(user_supplied_data,MYF(0));
  user_supplied_data= (char *)my_malloc(insert_string.length+1, MYF(MY_WME));
  insert_string_alloced=1;
  sprintf(user_supplied_data, "%s", insert_string.str);
  DBUG_PRINT("info", ("generated_insert_data %s", user_supplied_data));
  dynstr_free(&insert_string);
  mysql_close(&mysql);
  DBUG_RETURN(insert_string.length+1);
}

/*
  build_query_string()

  This function builds a query if the user opts to not supply a query
  statement or file containing a query statement
*/
static int
build_query_string(void)
{
  char       buf[512];
  int        col_count;
  static DYNAMIC_STRING query_string;
  DBUG_ENTER("build_query_string");

  init_dynamic_string(&query_string, "", 1024, 1024);

  dynstr_append_mem(&query_string, "SELECT ", 7);
  for (col_count= 1; col_count <= num_int_cols; col_count++)
  {
    sprintf(buf, "intcol%d", col_count);
    dynstr_append(&query_string, buf);

    if (col_count < num_int_cols || num_char_cols > 0)
      dynstr_append_mem(&query_string, ",", 1);

  }
  for (col_count= 1; col_count <= num_char_cols; col_count++)
  {
    sprintf(buf, "charcol%d", col_count);
    dynstr_append(&query_string, buf);

    if (col_count < num_char_cols)
      dynstr_append_mem(&query_string, ",", 1);

  }
  dynstr_append_mem(&query_string, " FROM t1", 8);
  user_supplied_query= (char *)my_malloc(query_string.length+1, MYF(MY_WME));
  query_string_alloced=1;
  sprintf(user_supplied_query, "%s", query_string.str);
  DBUG_PRINT("info", ("user_supplied_query %s", user_supplied_query));
  dynstr_free(&query_string);
  DBUG_RETURN(0);
}

static void
get_options(int *argc,char ***argv)
{
  int ho_error;
  MY_STAT sbuf;  /* Stat information for the data file */

  DBUG_ENTER("get_options");
  if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
    exit(ho_error);

  /*
    Default policy - if they don't supply either char or int cols, and
    also no data, then default to 1 of each.
  */
  if (num_int_cols == 0 && num_char_cols == 0 && auto_generate_sql
&&
      !user_supplied_data)
  {
    num_int_cols= 1;
    num_char_cols=1;
  }

  if (!default_engine)
    default_engine= (char *)"MYISAM";

  if (!user)
    user= (char *)"root";

  if(auto_generate_sql && create_string &&
     user_supplied_data && user_supplied_query)
  {
      fprintf(stderr,
              "%s: Auto-generate SQL specified, but user has specified create, insert and
query strings!\n",
              my_progname);
      exit(1);
  }

  if (opt_skip_create && opt_drop)
  {
    fprintf(stderr,"You cannot specify to drop the schema and not re-create it,\nand then
insert data or query the schema that has been dropped!\n");
    exit(1);
  }

  if (opt_skip_create)
  {
    if (create_string)
      fprintf(stderr,"User-specified schema creation string or file, but skipping schema
creation!\n");
  }
  else
  {
    if (auto_generate_sql && !create_string)
      build_table_string();
    else if (create_string && my_stat(create_string, &sbuf, MYF(0)))
    {
      File data_file;
      if (!MY_S_ISREG(sbuf.st_mode))
      {
        fprintf(stderr,"%s: Create file was not a regular file\n",
                my_progname);
        exit(1);
      }
      if ((data_file= my_open(create_string, O_RDWR, MYF(0))) == -1)
      {
        fprintf(stderr,"%s: Could not open create file\n", my_progname);
        exit(1);
      }
      create_string= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
      create_string_alloced=1;
      my_read(data_file, create_string, sbuf.st_size, MYF(0));
      create_string[sbuf.st_size]= '\0';
      my_close(data_file,MYF(0));
    }
    else if (!auto_generate_sql && !create_string)
    {
      fprintf(stderr,"%s: No user defined schema creation or --auto-generate-sql\
              specified!\n", my_progname);
    }
  }

  if (opt_skip_data_load)
  {
    if (user_supplied_data)
      fprintf(stderr,"User-specified data insert data supplied, but skipping data
load!\n");
  }
  else
  {
    if (!user_supplied_data && auto_generate_sql)
    {
      int length;
      generated_insert_flag=1;
      length= build_insert_string();
      DBUG_PRINT("info", ("user_supplied_data is %s", user_supplied_data));
    }
    else if (my_stat(user_supplied_data, &sbuf, MYF(0)))
    {
      File data_file;
      if (!MY_S_ISREG(sbuf.st_mode))
      {
        fprintf(stderr,"%s: User data supplied file was not a regular file\n",
                my_progname);
        exit(1);
      }
      if ((data_file= my_open(user_supplied_data, O_RDWR, MYF(0))) == -1)
      {
        fprintf(stderr,"%s: Could not open data supplied file\n", my_progname);
        exit(1);
      }
      user_supplied_data= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
      insert_string_alloced=1;
      my_read(data_file, user_supplied_data, sbuf.st_size, MYF(0));
      user_supplied_data[sbuf.st_size]= '\0';
      my_close(data_file,MYF(0));
    }
    else if (!user_supplied_query && !auto_generate_sql)
    {
      fprintf(stderr,"%s: No user supplied data to insert or --auto-generate-sql\
              specified!\n", my_progname);
    }
  }

  if (opt_skip_query)
  {
    if (user_supplied_query)
      fprintf(stderr,"User-specified query supplied, but skipping query!\n");
  }
  else 
  {
    if (!user_supplied_query && auto_generate_sql)
    {
      build_query_string();
    }
    else if (my_stat(user_supplied_query, &sbuf, MYF(0)))
    {
      File data_file;
      if (!MY_S_ISREG(sbuf.st_mode))
      {
        fprintf(stderr,"%s: User query supplied file was not a regular file\n",
                my_progname);
        exit(1);
      }
      if ((data_file= my_open(user_supplied_query, O_RDWR, MYF(0))) == -1)
      {
        fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
        exit(1);
      }
      user_supplied_query= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
      query_string_alloced=1;
      my_read(data_file, user_supplied_query, sbuf.st_size, MYF(0));
      user_supplied_query[sbuf.st_size]= '\0';
      my_close(data_file,MYF(0));
    }
    else if (!user_supplied_query && !auto_generate_sql)
    {
      fprintf(stderr,"%s: No user supplied query or --auto-generate-sql\
              specified!\n", my_progname);
    }
  }

  if (tty_password)
    opt_password=get_tty_password(NullS);
  if (opt_count)
  {
    /*
      We need to set verbose to 2 as we need to change the output to include
      the number-of-rows column
    */
    verbose= 2;
  }
  DBUG_VOID_RETURN;
}


static int
create_schema(MYSQL *mysql,const char *db,const char *script)
{
  char query[HUGE_STRING_LENGTH], buffer[HUGE_STRING_LENGTH];

  DBUG_ENTER("create_schema");
  snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS %s", db);
  DBUG_PRINT("info", ("query %s", query)); 
  mysql_query(mysql, query);

  snprintf(query, HUGE_STRING_LENGTH, "CREATE DATABASE %s", db);
  DBUG_PRINT("info", ("query %s", query)); 
  if (mysql_query(mysql, query))
  {
    fprintf(stderr,"%s: Cannot create database %s : %s\n", my_progname, db,
            mysql_error(mysql));
    exit(1);
  }

  if (mysql_select_db(mysql,db))
  {
    fprintf(stderr,"%s: Cannot connect to db %s: %s\n",my_progname, db,
	    mysql_error(mysql));
    exit(1);
  }

  snprintf(buffer, HUGE_STRING_LENGTH, "set storage_engine=%s",
           default_engine);
  if (mysql_query(mysql, buffer))
  {
    fprintf(stderr,"%s: Cannot set default engine: %s\n", my_progname,
            mysql_error(mysql));
    exit(1);
  }

  if (delimiter)
  {
    char *retstr;
    char buf[HUGE_STRING_LENGTH];

    while((retstr= strstr(script, delimiter)))
    {
      strncpy((char*)&buf, script, retstr - script);
      buf[retstr - script]= '\0';
      script+= retstr - script + delimiter_length;
      DBUG_PRINT("info", ("running create QUERY %s", (char *)buf));
      if (mysql_query(mysql, buf))
      {
        fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
                my_progname, (char *)buf, mysql_error(mysql));
        exit(1);
      }
    }
  }
  /*
    remainder, if there was a delimeter, or the whole query if not a 
    delimiter. If less than 3, can't be anything useful
  */
  if ((strlen(script)) < 3)
    DBUG_RETURN(0);
  if (mysql_query(mysql, script))
  {
    fprintf(stderr,"%s: Cannot create tables: %s\n", my_progname,
            mysql_error(mysql));
    exit(1);
  }

  DBUG_RETURN(0);
}

static int
drop_schema(MYSQL *mysql,const char *db)
{
  char query[HUGE_STRING_LENGTH];

  DBUG_ENTER("drop_schema");
  snprintf(query, HUGE_STRING_LENGTH, "DROP DATABASE IF EXISTS %s", db);
  if (mysql_query(mysql, query))
  {
    fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
            my_progname, db, mysql_error(mysql));
    exit(1);
  }

  DBUG_RETURN(0);
}


static int
run_scheduler(const char *script,
              int(*task)(const char *), unsigned int concur)
{
  uint x;

  DBUG_ENTER("run_scheduler");
  /* 
    reset to 0
  */
  children_spawned= 0;

  for (x= 0; x < concur; x++)
  {
    int pid;
    DBUG_PRINT("info", ("x %d concurrency %d", x, concurrency));
    pid= fork();
    switch(pid)
    {
    case 0:
      /* child */
      DBUG_PRINT("info", ("fork returned 0, calling task(\"%s\"), pid %d gid %d",
                          script, pid, getgid()));
      if (verbose >= 2)
        fprintf(stderr,
                "%s: fork returned 0, calling task(\"%s\") pid %d gid %d\n",
                my_progname, script, pid, getgid());
      task(script);
      exit(0);
      break;
    case -1:
      /* error */
      DBUG_PRINT("info",
                 ("fork returned -1, failing pid %d gid %d", pid, getgid()));
      fprintf(stderr,
              "%s: Failed on fork: -1, max procs per parent exceeded.\n",
              my_progname);
      /*exit(1);*/
      goto WAIT;
    default:
      /* parent, forked */
      DBUG_PRINT("info", ("default, break: pid %d gid %d", pid, getgid()));
      if (verbose >= 2)
        fprintf(stderr,"%s: fork returned %d, gid %d\n",
                my_progname, pid, getgid());
      break;
    }
  }

  children_spawned= x;
WAIT:
  while(x--)
  {
    int status, pid;
    pid= wait(&status);
    DBUG_PRINT("info", ("Parent: child %d status %d", pid, status));
  }

  DBUG_RETURN(0);
}

int
run_task(const char *script)
{
  uint counter= 0, x;
  MYSQL mysql;
  MYSQL_RES *result;
  MYSQL_ROW row;

  DBUG_ENTER("run_task");
  DBUG_PRINT("info", ("task script \"%s\"", script));

  mysql_init(&mysql);

  DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user));
  if (!(mysql_real_connect(&mysql, host, user, opt_password,
                           "mysqlslap", opt_mysql_port, opt_mysql_unix_port,
                           0)))
  {
    fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
    exit(1);
  }
  DBUG_PRINT("info", ("connected."));

  for (x= 0; x < number_of_iterations; x++)
  {
    if (delimiter)
    {
      char *retstr;
      char buf[HUGE_STRING_LENGTH];

      while((retstr= strstr(script, delimiter)))
      {
        strncpy((char*)&buf, script, retstr - script);
        buf[retstr - script]= '\0';
        script+= retstr - script + delimiter_length;
        DBUG_PRINT("info", ("running QUERY %s", (char *)buf));
        if (mysql_query(&mysql, (char *)buf))
        {
          fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
                  my_progname, buf, mysql_error(&mysql));
          exit(1);
        }

        result= mysql_store_result(&mysql);
        while ((row = mysql_fetch_row(result)))
        {
          counter++;
        }
        mysql_free_result(result);
        result= 0;
      }
    }
    if ((strlen(script)) < 3)
      DBUG_RETURN(0);
    if (mysql_query(&mysql, script))
    {
      fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
              my_progname, script, mysql_error(&mysql));
      exit(1);
    }

    result= mysql_store_result(&mysql);
    while ((row = mysql_fetch_row(result)))
    {
      counter++;
    }
    mysql_free_result(result);
    result= 0;

  }

  mysql_close(&mysql);

  DBUG_RETURN(0);
}


int
load_data(const char *script)
{
  unsigned int x;
  MYSQL mysql;

  DBUG_ENTER("load_data");
  DBUG_PRINT("info", ("task load_data, pid %d", getpid()));
  mysql_init(&mysql);

  if (!(mysql_real_connect(&mysql, host, user, opt_password,
                           "mysqlslap", opt_mysql_port, opt_mysql_unix_port,
                           0)))
  {
    fprintf(stderr,"%s: Unable to connect to mysqlslap ERROR: %s\n",
            my_progname, mysql_error(&mysql));
    exit(1);
  }

  for (x= 0; x < number_of_rows; x++)
  {
    if (delimiter)
    {
      char *retstr;
      char buf[HUGE_STRING_LENGTH];

      while((retstr= strstr(script, delimiter)))
      {
        strncpy((char*)&buf, script, retstr - script);
        buf[retstr - script]= '\0';
        script+= retstr - script + delimiter_length;
        DBUG_PRINT("info", ("running INSERT %s", (char *)buf));
        if (mysql_query(&mysql, (char *)buf))
        {
          fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
                  my_progname, buf, mysql_error(&mysql));
          exit(1);
        }
      }
    }
    if ((strlen(script)) < 3)
      DBUG_RETURN(0);
    if (mysql_query(&mysql, script))
    {
      DBUG_PRINT("info", ("iteration %d with INSERT statement %s", script));
      fprintf(stderr,"%s: Cannot insert into table using script: %s ERROR: %s\n",
              my_progname, script, mysql_error(&mysql));
      exit(1);
    }
    /* this causes variable data on the insert string */
    if (auto_generate_sql)
    {
      build_insert_string();
      sprintf((char *)script, "%s", (char *)user_supplied_data);
    }
  }

  mysql_close(&mysql);

  DBUG_RETURN(0);
}


--- New file ---
+++ mysql-test/r/mysqlslap.result	05/11/25 11:38:18
/home/patg/mysql-build/mysql-5.1-slap/client/.libs/lt-mysqlslap  Ver 0.1 Distrib
5.1.3-alpha, for suse-linux (i686)
Copyright (C) 2005 MySQL AB
This software comes with ABSOLUTELY NO WARRANTY. This is free software,       
and you are welcome to modify and redistribute it under the GPL        license

Run a query multiple times against the server

Usage: /home/patg/mysql-build/mysql-5.1-slap/client/.libs/lt-mysqlslap [OPTIONS] [database
[table [column]]]

Default options are read from the following files in the given order:
/etc/my.cnf ~/.my.cnf 
The following groups are read: mysqlslap client
The following options may be given as the first argument:
--print-defaults	Print the program argument list and exit
--no-defaults		Don't read default options from any options file
--defaults-file=#	Only read default options from the given file #
--defaults-extra-file=# Read this file after the global files are read
  -a, --auto-generate-sql 
                      Generate SQL where not supplied by file or command line.
  -C, --compress      Use compression in server/client protocol.
  -l, --concurrency-load=# 
                      Number of clients to simulate.
  -c, --concurrency=# Number of clients to simulate.
  --create=name       File or string to use for create.
  -d, --data=name     Insert statement or file containing the insert statement
                      to populcate the table with.
  -#, --debug[=name]  Output debug log. Often this is 'd:t:o,filename'.
  -F, --delimiter=name 
                      Delimiter to use in SQL statements.
  -D, --drop-schema   Drop schema if it exists prior to running, and after
                      running
  -e, --engine=name   Engine to create the table as.
  -?, --help          Display this help and exit.
  -h, --host=name     Connect to host.
  -i, --iterations=#  Number of iterations.
  -x, --number-char-cols=# 
                      Number of int columns to create table with.
  -y, --number-int-cols=# 
                      Number of varchar columns to create table with.
  -n, --number-rows=# Number of rows to insert.
  -p, --password[=name] 
                      Password to use when connecting to server. If password is
                      not given it's asked from the tty.
  -P, --port=#        Port number to use for connection.
  --protocol=name     The protocol of connection (tcp,socket,pipe,memory).
  -s, --silent        Run program in silent mode - no output.
  -q, --query=name    Query to run or file containing query to run.
  -S, --socket=name   Socket file to use for connection.
  --ssl               Enable SSL for connection (automatically enabled with
                      other flags). Disable with --skip-ssl.
  --ssl-key=name      X509 key in PEM format (implies --ssl).
  --ssl-cert=name     X509 cert in PEM format (implies --ssl).
  --ssl-ca=name       CA file in PEM format (check OpenSSL docs, implies
                      --ssl).
  --ssl-capath=name   CA directory (check OpenSSL docs, implies --ssl).
  --ssl-cipher=name   SSL cipher to use (implies --ssl).
  -u, --user=name     User for login if not current user.
  -v, --verbose       More verbose output; You can use this multiple times to
                      get even more verbose output.
  -V, --version       Output version information and exit.

--- New file ---
+++ mysql-test/t/mysqlslap.test	05/11/25 11:38:19
# Can't run test of external client with embedded server
--source include/not_embedded.inc

--exec $MYSQL_SLAP --help
--exec $MYSQL_SLAP --silent --drop-schema --concurrency=5 --concurrency-load=5
--iterations=20 --number-int-cols=2 --number-char-cols=3 --number-rows=12
--auto-generate-sql

--exec $MYSQL_SLAP --silent --drop-schema --concurrency=5 --concurrency-load=5
--iterations=20 --number-rows=10 --query="select * from t1" --data="INSERT INTO t1 VALUES
(1, 'This is a test')" --create="CREATE TABLE t1 (id int, name varchar(64))"

--exec $MYSQL_SLAP --silent --drop-schema --concurrency=5 --concurrency-load=5
--iterations=20 --delimiter=";" --number-rows=10 --query="select * from t1;select * from
t2" --data="INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test',
'test2')" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1
varchar(32), foo2 varchar(32))"

Thread
bk commit into 5.1 tree (patg:1.1964)Patrick Galbraith25 Nov