#!/usr/bin/perl
use DBI;
use Benchmark;
use POSIX qw( floor );
use Getopt::Long;

$opt_loop_count=100000;         # number of loops(rows)
$random_loop_count=$opt_loop_count;

$opt_db_host="localhost";
$opt_db_socket="/tmp/mysql.sock";
$opt_db_name="test";
$opt_db_engine="Falcon";

$opt_rows=50000;
$opt_insert_duplicates=$opt_update_big=$opt_update_with_key=$opt_update_with_key_prefix="";

GetOptions("update_big","update_with_key","insert_duplicates",
           "update_with_key_prefix","db-socket=s","db-engine=s");
           
           
if ($opt_insert_duplicates eq '' && 
    $opt_update_big eq '' &&
    $opt_update_with_key eq '' &&
    $opt_update_with_key_prefix eq '')
{
  print <<EOF;
Please specify at least one of the tests in the command line: 
   --update_big, --update_with_key, --insert_duplicates, --update_with_key_prefix
EOF
exit;
}

$dbh = DBI->connect("dbi:mysql:$opt_db_name;host=$opt_db_host;mysql_socket=$opt_db_socket",
                    "root","", { PrintError => 0}) or die $DBI::errstr;

$sth = $dbh->prepare("select VERSION()") or die $DBI::errstr;
$version="MySQL ?";
if ($sth->execute && (@row = $sth->fetchrow_array))
{
  $row[0] =~ s/-/ /g;
  $version="MySQL $row[0]";
}
$sth->finish;

print "$version, ENGINE: $opt_db_engine \n";


####
#### Generating random keys
####

print "Generating random keys\n";
$random[$random_loop_count]=0;
for ($i=0 ; $i < $random_loop_count ; $i++)
{
  $random[$i]=$i;
}

my $tmpvar=1;
for ($i=0 ; $i < $random_loop_count ; $i++)
{
  $tmpvar^= ((($tmpvar + 63) + $i)*3 % $random_loop_count);
  $swap=$tmpvar % $random_loop_count;
  $tmp=$random[$i]; $random[$i]=$random[$swap]; $random[$swap]=$tmp;
}

sub random {
  my $i = shift;
  $i += $opt_loop_count;
  return $random[$i % $random_loop_count]
           + floor($i/$random_loop_count)*$random_loop_count;
}


####
#### Create needed table
####

print "Creating table bench1\n";
$dbh->do("drop table if exists bench1 ") or die $DBI::errstr;
$dbh->do("create table bench1 (id int NOT NULL, 
                               id2 int NOT NULL,
                               id3 int NOT NULL,
                               dummy1 char(30),
                               primary key (id,id2),
                               index ix_id3 (id3)) engine=$opt_db_engine") or die $DBI::errstr;

$query="insert into bench1 (id,id2,id3,dummy1) values ";

$total_rows=$opt_loop_count*3;

print "Inserting $opt_loop_count rows in order\n";

$loop_time=new Benchmark;
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
  $sth = $dbh->do($query . "($i,$i,$i,'ABCDEFGHIJ')") or die $DBI::errstr;
}
  
$end_time=new Benchmark;
print "Time for insert_in_order (" . ($opt_loop_count) . "): " .
 timestr(timediff($end_time, $loop_time),"all") . "\n";

  $loop_time=new Benchmark;

  print "Inserting $opt_loop_count rows in reverse order\n";
  for ($i=0 ; $i < $opt_loop_count ; $i++)
  {
    $sth = $dbh->do($query . "(" . ($total_rows-1-$i) . "," .
                    ($total_rows-1-$i) . "," .
                    ($total_rows-1-$i) . ",'BCDEFGHIJK')")
      or die $DBI::errstr;
  }

  $end_time=new Benchmark;
  print "Time for insert_reverse_order (" . ($opt_loop_count) . "): " .
  timestr(timediff($end_time, $loop_time),"all") . "\n";

  $loop_time=new Benchmark;
  print "Inserting $opt_loop_count rows in random order\n";

  for ($i=0 ; $i < $opt_loop_count ; $i++)
  {
    $sth = $dbh->do($query . "(". random($i) . ","
                            . random($i) . ","
                            . random($i)
                            . ",'CDEFGHIJKL')") or die $DBI::errstr;
  }
  $end_time=new Benchmark;
  print "Time for insert_random_order (" . ($opt_loop_count) . "): " .
  timestr(timediff($end_time, $loop_time),"all") . "\n\n";

if ($opt_insert_duplicates)
{

  print "Testing insert of duplicates\n";
  $loop_time=new Benchmark;

  for ($i=0 ; $i < $opt_loop_count ; $i++)
  {
    $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
    $tmp=$tmpvar % ($total_rows);
    $tmpquery = "$query ($tmp,$tmp,2,'D')";
    if ($dbh->do($tmpquery))
    {
      die "Didn't get an error when inserting duplicate record $tmp\n";
    }
  }
  $end_time=new Benchmark;
  print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
  timestr(timediff($end_time, $loop_time),"all") . "\n\n";
}

print_stat if ($db_stat);

#
# Testing some simple updates
#
if ($opt_update_with_key)
{
  print "Testing update with key\n";
  $loop_time=new Benchmark;
  for ($i=0 ; $i < $opt_loop_count*3 ; $i++)
  {
    $sth = $dbh->do("update bench1 set dummy1='updated' where id=$i and id2=$i") or die $DBI::errstr;
  }

  $end_time=new Benchmark;
  print "Time for update_with_key (" . ($opt_loop_count*3) . "):  " .
    timestr(timediff($end_time, $loop_time),"all") . "\n";
}

if ($opt_update_with_key_prefix)
{

$loop_time=new Benchmark;
$count=0;
for ($i=1 ; $i < $opt_loop_count*3 ; $i+=3)
{
  $sth = $dbh->do("update bench1 set dummy1='updated' where id=$i") or die $DBI::errstr;
  $end_time=new Benchmark;
}
 print "Time";
 print " for update_with_key_prefix (" . ($opt_loop_count) . "):  " .
  timestr(timediff($end_time, $loop_time),"all") . "\n";
}

if ($opt_update_big)
{
  print "\nTesting update of all rows\n";

  $small_loop_count=10;
  $loop_time=new Benchmark;
  for ($i=0 ; $i < $small_loop_count ; $i++)
  {
    $sth = $dbh->do("update bench1 set dummy1='updated $i'") or die $DBI::errstr;
  }
  $end_time=new Benchmark;
  print "Time for update_big ($small_loop_count):  " .
    timestr(timediff($end_time, $loop_time),"all") . "\n";
}

print_stat if ($db_stat);

$dbh->disconnect();

sub print_stat
{
  $sth=$dbh->prepare("show status like 'handler%'");
  $sth->execute();
  while ((@arr=$sth->fetchrow_array))
  {
    print join(",",@arr),"\n";
  }
 $sth->finish;
}