List:Internals« Previous MessageNext Message »
From:Patrick Galbraith Date:November 15 2005 6:17pm
Subject:bk commit into 5.1 tree (patg:1.1957)
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.1957 05/11/15 19:17:09 patg@stripped +7 -0
  WL# 2983
  
  mysqlslap load emulation tool, first version.

  mysql-test/t/mysqlslap.test
    1.1 05/11/15 19:16:49 patg@stripped +6 -0
    WL# 2983 test file for mysqlslap tool

  mysql-test/t/mysqlslap.test
    1.0 05/11/15 19:16:49 patg@stripped +0 -0
    BitKeeper file /Users/patg/mysql-build/mysql-5.1-new/mysql-test/t/mysqlslap.test

  mysql-test/r/mysqlslap.result
    1.1 05/11/15 19:16:48 patg@stripped +1 -0
    WL# 2983 test result file for mysqlslap 

  mysql-test/r/mysqlslap.result
    1.0 05/11/15 19:16:48 patg@stripped +0 -0
    BitKeeper file /Users/patg/mysql-build/mysql-5.1-new/mysql-test/r/mysqlslap.result

  client/mysqlslap.c
    1.1 05/11/15 19:16:46 patg@stripped +944 -0
    WL# 2983 
    
    mysqlslap load emulation tool

  mysql-test/mysql-test-run.sh
    1.279 05/11/15 19:16:46 patg@stripped +11 -0
    WL# 2983 Added mysqlslap to test script

  mysql-test/mysql-test-run.pl
    1.41 05/11/15 19:16:46 patg@stripped +13 -1
    WL# 2983 Added mysqlslap to test script

  client/mysqlslap.c
    1.0 05/11/15 19:16:46 patg@stripped +0 -0
    BitKeeper file /Users/patg/mysql-build/mysql-5.1-new/client/mysqlslap.c

  client/client_priv.h
    1.44 05/11/15 19:16:45 patg@stripped +1 -1
    WL# 2983 - Added OPT_CREATE_SLAP_SCHEMA for mysqlslap tool

  client/Makefile.am
    1.51 05/11/15 19:16:45 patg@stripped +3 -1
    WL# 2983 Added mysqlslap tool 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:	radha.local
# Root:	/Users/patg/mysql-build/mysql-5.1-new

--- 1.50/client/Makefile.am	2005-10-18 15:43:53 +02:00
+++ 1.51/client/Makefile.am	2005-11-15 19:16:45 +01: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.278/mysql-test/mysql-test-run.sh	2005-11-04 21:09:53 +01:00
+++ 1.279/mysql-test/mysql-test-run.sh	2005-11-15 19:16:46 +01: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.40/mysql-test/mysql-test-run.pl	2005-11-04 21:09:53 +01:00
+++ 1.41/mysql-test/mysql-test-run.pl	2005-11-15 19:16:46 +01: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,6 +931,7 @@
     }
     $exe_mysqlcheck=     mtr_exe_exists("$path_client_bindir/mysqlcheck");
     $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
+    $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");
@@ -947,6 +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_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");
@@ -2457,11 +2460,19 @@
     $cmdline_mysqldump .=
       " --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
   }
-  my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " .
+  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= " ;
+  if ( $opt_debug )
+  {
     $cmdline_mysqlimport .=
       " --debug=d:t:A,$opt_vardir/log/mysqlimport.trace";
   }
@@ -2518,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-13 07:44:16 +02:00
+++ 1.44/client/client_priv.h	2005-11-15 19:16:45 +01: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/15 19:16:46
/* 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

#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 set_delimiter(MYSQL *mysql);
static int create_schema(MYSQL *mysql, const char *db,const char *script);
static int run_scheduler(const char *script, int(*task)(const char *));
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;

static int verbose=0, num_int_cols=-1, num_char_cols=-1;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
static unsigned int number_of_rows= 1000, number_of_iterations=1000,
  concurrency= 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;
  double time_difference;
  MY_INIT(argv[0]);
  struct timeval start_time, load_time, run_time;

  DBUG_ENTER("main");
  bzero(&start_time, sizeof(struct timeval));
  bzero(&load_time, sizeof(struct timeval));
  bzero(&run_time, sizeof(struct timeval));
  load_defaults("my",load_default_groups,&argc,&argv);
  get_options(&argc,&argv);

  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;

  /* how might this work ? */
  if (delimiter)
    set_delimiter(&mysql);
  /*
    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");

  create_schema(&mysql, "mysqlslap", create_string);

  if (user_supplied_data)
  {
    gettimeofday(&start_time, NULL);
    DBUG_PRINT("info", ("user_supplied_data %s", user_supplied_data));
    run_scheduler(user_supplied_data, load_data);
    gettimeofday(&load_time, NULL);
    time_difference= timedif(load_time, start_time);
    if (!opt_silent)
      printf("Data load took %f seconds\n",time_difference);
  }
  run_scheduler(user_supplied_query, run_task);
  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[] =
{
  {"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", 'c', "Number of clients to simulate.", (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.", (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_NO_ARG, 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.",
    (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.",
    (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.", (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},
  {"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) {
#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)
{
  int x=0, chr=0, c=0;
  struct timeval timestruct;

  DBUG_ENTER("get_random_string");
  gettimeofday(&timestruct, NULL);
  srandom((unsigned int) timestruct.tv_usec);
  for (x= 126 ; x > 0; x--)
  {
    /*
      why this? 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;
    if (chr >= 32 && chr <= 126)
    {
      buf[c]= chr;
      c++;
    }
  }

  DBUG_RETURN(c);
}

/*
  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 && ! user_supplied_data)
  {
    num_int_cols= 1;
    num_char_cols=1;
  }

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

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

  if (! 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));
  }

  if (!user_supplied_data)
  {
    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));
  }

  if (!user_supplied_query)
  {
    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));
  }

  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 %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);
  }

  DBUG_PRINT("info", ("script %s", script));
  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 %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
set_delimiter(MYSQL *mysql)
{
  char query[HUGE_STRING_LENGTH];

  DBUG_ENTER("set_delimiter");
  snprintf(query, HUGE_STRING_LENGTH, "DELIMITER %s", delimiter);
  if (mysql_query(mysql, query))
  {
    DBUG_PRINT("info", ("delimiter %s query %s", delimiter, query));
    fprintf(stderr,"%s: Cannot set delimiter '%s' ERROR : %s\n",
            my_progname, delimiter, mysql_error(mysql));
    exit(1);
  }

  DBUG_RETURN(0);
}

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

  DBUG_ENTER("run_scheduler");

  for (x= 0; x < concurrency; 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++)
  {
    DBUG_PRINT("info", ("running QUERY %s", script));
    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 (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 (generated_insert_flag)
    {
      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/15 19:16:48
# no results in this file, running in --silent mode

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

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

--exec $MYSQL_SLAP --silent --drop-schema --concurrency=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))"

Thread
bk commit into 5.1 tree (patg:1.1957)Patrick Galbraith15 Nov