List:Commits« Previous MessageNext Message »
From:magnus.blaudd Date:April 27 2012 8:14am
Subject:bzr push into mysql-trunk branch (magnus.blaudd:3749 to 3750)
View as plain text  
 3750 magnus.blaudd@stripped	2012-04-27 [merge]
      Merge trunk-wl5960 -> trunk

    added:
      mysql-test/lib/My/Memcache.pm
    modified:
      mysql-test/lib/My/ConfigFactory.pm
      mysql-test/lib/mtr_cases.pm
      mysql-test/mysql-test-run.pl
 3749 Norvald H. Ryeng	2012-04-27
      Bug#13735712 SELECT W/ SUBQUERY PRODUCES MORE ROWS WHEN USING
      VARIABLES
      
      Outer join queries with ALL may return incorrect results because the
      optimizer incorrectly rewrites them to use inner join. E.g.:
      
      SELECT *
      FROM t2 RIGHT JOIN t3 ON(t3.c = t2.b)
      WHERE t2.b < ALL(SELECT t1.a FROM t1 WHERE t1.a <= 7);
      
      is first rewritten by Item_in_subselect::single_value_transformer()
      into:
      
      SELECT *
      FROM t2 RIGHT JOIN t3 ON(t3.c = t2.b)
      WHERE <not>(t2.b >= (SELECT MIN(t1.a) FROM t1 WHERE t1.a <= 7));
      
      When simplify_joins() checks not_null_tables() on the <not> condition
      to find out if the outer join can be transformed into an inner join,
      Item_func::not_null_tables() returns its arguments'
      not_null_tables(). This means that simplify_joins() is told that the
      condition will be false if t2.b is NULL. But the condition is actually
      true if t1 has no rows where t1.a <= 7. This leads to the optimizer
      incorrectly rewriting the query to use inner join.
      
      Fix: Let Item_func_not_all::not_null_tables() return a zero table map.
     @ mysql-test/include/subquery.inc
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_all.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_all_bka.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_all_bka_nixbnl.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_nomat_nosj.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_nomat_nosj_bka.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_none.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_none_bka.result
        Add test cases for bugs #13735712.
     @ mysql-test/r/subquery_none_bka_nixbnl.result
        Add test cases for bugs #13735712.
     @ sql/item_cmpfunc.h
        Return 0 from Item_func_not_all::not_null_tables().

    modified:
      mysql-test/include/subquery.inc
      mysql-test/r/subquery_all.result
      mysql-test/r/subquery_all_bka.result
      mysql-test/r/subquery_all_bka_nixbnl.result
      mysql-test/r/subquery_nomat_nosj.result
      mysql-test/r/subquery_nomat_nosj_bka.result
      mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result
      mysql-test/r/subquery_none.result
      mysql-test/r/subquery_none_bka.result
      mysql-test/r/subquery_none_bka_nixbnl.result
      sql/item_cmpfunc.h
=== modified file 'mysql-test/lib/My/ConfigFactory.pm'
--- a/mysql-test/lib/My/ConfigFactory.pm	2011-09-07 10:08:09 +0000
+++ b/mysql-test/lib/My/ConfigFactory.pm	2012-04-27 07:50:48 +0000
@@ -309,6 +309,16 @@ my @ndbd_rules=
 
 
 #
+# Rules to run for each memcached in the config
+#  - will be run in order listed here
+#
+my @memcached_rules=
+(
+ { '#host' => \&fix_host },
+ { 'port' => \&fix_port },
+);
+
+#
 # Rules to run for each cluster_config section
 #  - will be run in order listed here
 #
@@ -678,6 +688,10 @@ sub new_config {
 			   'mysqld.',
 			   @mysqld_rules);
 
+  $self->run_section_rules($config,
+			   'memcached.',
+			   @memcached_rules);
+               
   # [mysqlbinlog] need additional settings
   $self->run_rules_for_group($config,
 			     $config->insert('mysqlbinlog'),

=== added file 'mysql-test/lib/My/Memcache.pm'
--- a/mysql-test/lib/My/Memcache.pm	1970-01-01 00:00:00 +0000
+++ b/mysql-test/lib/My/Memcache.pm	2012-04-18 14:41:57 +0000
@@ -0,0 +1,572 @@
+# -*- cperl -*-
+# Copyright (c) 2011, Oracle and/or its affiliates. 
+# 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; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+
+
+########## Memcache Client Library for Perl
+### 
+###  $mc = My::Memcache->new()          create an ascii-protocol client 
+###  $mc = My::Memcache::Binary->new()  create a binary-protocol client
+###
+###  $mc->connect(host, port)           returns 1 on success, 0 on failure
+### 
+###  $mc->{error}                       holds most recent error/status message
+### 
+###  $mc->set(key, value)               returns 1 on success, 0 on failure
+###  $mc->add(key, value)               set if record does not exist
+###  $mc->replace(key, value)           set if record exists
+###  $mc->append(key, value)            append value to existing data
+###  $mc->prepend(key, value)           prepend value to existing data
+###  $mc->get(key)                      returns value or undef
+###  $mc->delete(key)                   returns 1 on success, 0 on failure
+###  $mc->stats(stat_key)               get stats; returns a hash
+###  $mc->incr(key, amount)             returns the new value or undef
+###  $mc->decr(key, amount)             like incr
+###  $mc->flush()                       flush_all
+###
+###  $mc->set_expires(sec)              Set TTL for all store operations
+###  $mc->set_flags(int_flags)          Set numeric flags for store operations
+###
+###  $mc->note_config_version() 
+###    Store the generation number of the running config in the filesystem,
+###    for later use by wait_for_reconf()
+### 
+###  $mc->wait_for_reconf()
+###    Wait for NDB/Memcache to complete online reconfiguration.  
+###    Returns the generation number of the newly running configuration, 
+###    or zero on timeout/error. 
+
+use strict;
+use lib 'lib';
+use IO::Socket::INET;
+use IO::File;
+use Carp;
+use mtr_report;            # for main::mtr_verbose()
+
+require "mtr_process.pl";  # for mtr_ping_port() 
+require "mtr_misc.pl";     # for mtr_milli_sleep()
+
+package My::Memcache;
+
+sub new {
+  my $pkg = shift;
+  bless { "created" => 1 , "error" => "" , "cf_gen" => 0,
+          "exptime" => 0 , "flags" => 0
+        }, $pkg;
+}
+
+sub connect {
+  my $self = shift;
+  my $host = shift;
+  my $port = shift; 
+  
+  # Wait for memcached to be ready, up to ten seconds.
+  my $retries = 100;
+  while($retries && (::mtr_ping_port($port) == 0))
+  {
+     ::mtr_milli_sleep(100);
+     $retries--;
+  }
+
+  my $conn = IO::Socket::INET->new(PeerAddr => "$host:$port", Proto => "tcp");
+  if($conn) {
+    $self->{connection} = $conn;
+    $self->{connected} = 1;
+    $self->{server} = "$host:$port";
+    $self->{bin_req_id} = 0;
+    return 1;
+  }
+  $self->{error} = "CONNECTION_FAILED";
+  return 0;
+}
+
+sub DESTROY {
+  my $self = shift;
+  $self->{connection}->close();
+}
+
+sub note_config_version {
+  my $self = shift;
+
+  my $vardir = $ENV{MYSQLTEST_VARDIR};
+  # Fetch the memcached current config generation number and save it
+  my %stats = $self->stats("reconf");
+  my $F = IO::File->new("$vardir/tmp/memcache_cf_gen", "w") or die;
+  my $ver = $stats{"Running"};
+  print $F "$ver\n";
+  $F->close();
+
+  $self->{cf_gen} = $ver;
+}
+
+sub set_expires {
+  my $self = shift;
+  my $delta = shift;
+  
+  $self->{exptime} = $delta;
+}
+
+sub set_flags {
+  my $self = shift;
+  my $flags = shift;
+  
+  $self->{flags} = $flags;
+}
+
+sub wait_for_reconf {
+  my $self = shift;
+
+  if($self->{cf_gen} == 0) { 
+    my $cfgen = 0;
+    my $vardir = $ENV{MYSQLTEST_VARDIR};
+    my $F = IO::File->new("$vardir/tmp/memcache_cf_gen", "r");
+    if(defined $F) {
+      chomp($cfgen = <$F>);
+      undef $F;
+    }
+    $self->{cf_gen} = $cfgen;
+  }
+  
+  print STDERR "Config generation is : " . $self->{cf_gen} . "\n";
+  my $wait_for = $self->{cf_gen} + 1 ;
+  print STDERR "Waiting for: $wait_for \n";
+  
+  my $new_gen = $self->wait_for_config_generation($wait_for);
+  if($new_gen > 0) {
+    $self->{cf_gen} = $new_gen;
+  }
+  else {
+    print STDERR "Timed out.\n";
+  }
+  
+  return $new_gen;
+}
+  
+
+# wait_for_config_generation($cf_gen)
+# Wait until memcached is running config generation >= to $cf_gen
+# Returns 0 on error/timeout, or the actual running generation number
+#
+sub wait_for_config_generation {
+  my $self = shift;
+  my $cf_gen = shift;
+  my $ready = 0;
+  my $retries = 100;   # 100 retries x 100 ms = 10s
+  
+  while($retries && ! $ready) {
+    ::mtr_milli_sleep(100);     
+    my %stats = $self->stats("reconf");
+    if($stats{"Running"} >= $cf_gen) {
+      $ready = $stats{"Running"};
+    }
+    else {
+      $retries -= 1;
+    }
+  }
+  return $ready;
+}
+
+  
+sub delete {
+  my $self = shift;
+  my $key = shift;
+  my $sock = $self->{connection}; 
+  
+  $sock->print("delete $key\r\n") || Carp::confess "send error";
+  
+  $self->{error} = $sock->getline();
+  return $self->{error} =~ "^DELETED" ? 1 : $self->normalize_error();
+}
+
+
+sub _txt_store {
+  my $self = shift;
+  my $cmd = shift;
+  my $key = shift;
+  my $value = shift;
+  my $sock = $self->{connection};
+  
+  $sock->printf("%s %s %d %d %d\r\n%s\r\n",$cmd, $key, 
+                $self->{flags}, $self->{exptime}, length($value), $value);
+  return $sock->getline();
+}
+
+
+sub set {
+  my ($self, $key, $value) = @_;
+  
+  $self->{error} = $self->_txt_store("set", $key, $value);
+  return $self->{error} =~ "^STORED" ? 1 : $self->normalize_error();
+}
+
+
+sub add {
+  my ($self, $key, $value) = @_;
+  
+  $self->{error} = $self->_txt_store("add", $key, $value);
+  return $self->{error} =~ "^STORED" ? 1 : $self->normalize_error();
+}
+
+
+sub append {
+  my ($self, $key, $value) = @_;
+  
+  $self->{error} = $self->_txt_store("append", $key, $value);
+  return $self->{error} =~ "^STORED" ? 1 : $self->normalize_error();
+}
+
+
+sub prepend {    
+  my ($self, $key, $value) = @_;
+  
+  $self->{error} = $self->_txt_store("prepend", $key, $value);
+  return $self->{error} =~ "^STORED" ? 1 : $self->normalize_error();
+}
+
+
+sub replace {
+  my ($self, $key, $value) = @_;
+  
+  $self->{error} = $self->_txt_store("replace", $key, $value);
+  return $self->{error} =~ "^STORED" ? 1 : $self->normalize_error();
+}
+
+
+sub get {
+  my $self = shift;
+  my $key = shift;
+  my $sock = $self->{connection};
+  
+  $sock->print("get $key\r\n") || Carp::confess "send error";
+  my $response = $sock->getline();
+  my $val;
+  
+  if ($response =~ /^END/) 
+  {
+    $self->{error} = "NOT_FOUND";
+    return undef;
+  }
+  else
+  {
+    $response =~ /^VALUE (.*) (\d+) (\d+)/;
+    $self->{flags} = $2;
+    my $len = $3;
+    $sock->read($val, $len);
+    $sock->getline();  # \r\n after value
+    $sock->getline();  # END\r\n
+    
+    return $val;
+  }
+}
+
+
+sub _txt_math {
+  my ($self, $cmd, $key, $delta) = @_;
+  my $sock = $self->{connection};
+  
+  $sock->print("$cmd $key $delta \r\n") || Carp::confess "send error";
+  my $response = $sock->getline();
+  my $val;
+  
+  if ($response =~ "^NOT_FOUND")
+  {
+    $self->{error} = "NOT_FOUND";
+    return undef;
+  }
+  elsif ($response =~ "ERROR")
+  {
+    $self->{error} = $response;
+    $self->normalize_error();
+    return undef;
+  }
+  
+  $response =~ /(\d+)/;
+  return $1;
+}
+
+
+sub incr {
+  my ($self, $key, $delta) = @_;
+  return $self->_txt_math("incr", $key, $delta);
+}
+
+
+sub decr {
+  my ($self, $key, $delta) = @_;
+  return $self->_txt_math("decr", $key, $delta);
+}
+
+
+sub stats {
+  my $self = shift;
+  my $key = shift;
+  my $sock = $self->{connection};
+
+  $sock->print("stats $key\r\n") || Carp::confess "send error";
+  
+  $self->{error} = "OK";
+  my %response = ();
+  my $line = "";
+  while($line !~ "^END") {
+    if(($line) && ($line =~ /^STAT(\s+)(\S+)(\s+)(\S+)/)) {
+      $response{$2} = $4;
+    }
+    $line = $sock->getline();
+  }
+  
+  return %response;
+}
+
+sub flush {
+  my $self = shift;
+  my $key = shift;
+  my $sock = $self->{connection}; 
+  
+  $sock->print("flush_all\r\n") || Carp::confess "send error";
+  
+  $self->{error} = $sock->getline();
+  return $self->{error} =~ "^OK" ? 1 : $self->normalize_error();
+}
+
+
+# Try to provide consistent error messagees across ascii & binary protocols
+sub normalize_error {
+  my $self = shift;
+  my %error_message = (
+  "STORED\r\n"                         => "OK",
+  "EXISTS\r\n"                         => "KEY_EXISTS",
+  "CLIENT_ERROR value too big\r\n"     => "VALUE_TOO_LARGE",
+  "SERVER_ERROR object too large for cache\r\n"     => "VALUE_TOO_LARGE",
+  "CLIENT_ERROR invalid arguments\r\n" => "INVALID_ARGUMENTS",
+  "SERVER_ERROR not my vbucket\r\n"    => "NOT_MY_VBUCKET",
+  "SERVER_ERROR out of memory\r\n"     => "SERVER_OUT_OF_MEMORY",
+  "SERVER_ERROR not supported\r\n"     => "NOT_SUPPORTED",
+  "SERVER_ERROR internal\r\n"          => "INTERNAL_ERROR"
+  );  
+  my $norm_error = $error_message{$self->{error}};
+  $self->{error} = $norm_error if(defined($norm_error));
+  return 0;
+} 
+
+#  -----------------------------------------------------------------------
+#  ------------------         BINARY PROTOCOL         --------------------
+#  -----------------------------------------------------------------------
+
+package My::Memcache::Binary;
+@My::Memcache::Binary::ISA = "My::Memcache";
+
+use constant BINARY_HEADER_FMT  => "CCnCCnNNNN";
+use constant BINARY_REQUEST     => 0x80;
+use constant BINARY_RESPONSE    => 0x81;
+
+use constant BIN_CMD_GET        => 0x00;
+use constant BIN_CMD_SET        => 0x01;
+use constant BIN_CMD_ADD        => 0x02;
+use constant BIN_CMD_REPLACE    => 0x03;
+use constant BIN_CMD_DELETE     => 0x04;
+use constant BIN_CMD_INCR       => 0x05;
+use constant BIN_CMD_DECR       => 0x06;
+use constant BIN_CMD_QUIT       => 0x07;
+use constant BIN_CMD_FLUSH      => 0x08;
+use constant BIN_CMD_NOOP       => 0x0A;
+use constant BIN_CMD_APPEND     => 0x0E;
+use constant BIN_CMD_PREPEND    => 0x0F;
+use constant BIN_CMD_STAT       => 0x10;
+
+my %error_message = (
+ 0x00 => "OK",
+ 0x01 => "NOT_FOUND",
+ 0x02 => "KEY_EXISTS", 
+ 0x03 => "VALUE_TOO_LARGE",
+ 0x04 => "INVALID_ARGUMENTS",
+ 0x05 => "NOT_STORED",
+ 0x06 => "NON_NUMERIC_VALUE",
+ 0x07 => "NOT_MY_VBUCKET",
+ 0x81 => "UNKNOWN_COMMAND",
+ 0x82 => "SERVER_OUT_OF_MEMORY",
+ 0x83 => "NOT_SUPPORTED",
+ 0x84 => "INTERNAL_ERROR",
+ 0x85 => "SERVER_BUSY",
+ 0x86 => "SERVER_TEMPORARY_ERROR"
+);
+
+
+sub send_binary_request {
+  my $self = shift;
+  my ($cmd, $key, $val, $extra_header) = @_;
+  my $sock = $self->{connection};
+  my $key_len    = length($key);
+  my $val_len    = length($val);
+  my $extra_len  = length($extra_header);
+  my $total_len  = $key_len + $val_len + $extra_len;
+  my $cas_hi     = 0;
+  my $cas_lo     = 0;
+
+  $self->{bin_req_id}++;
+  
+  my $header = pack(BINARY_HEADER_FMT, BINARY_REQUEST, $cmd,
+                    $key_len, $extra_len, 0, 0, $total_len, 
+                    $self->{bin_req_id}, $cas_hi, $cas_lo);
+  my $packet = $header . $extra_header . $key . $val;
+
+  $sock->send($packet) || Carp::confess "send failed";
+}
+
+
+sub get_binary_response {
+  my $self = shift;
+  my $sock = $self->{connection};
+  my $header_len = length(pack(BINARY_HEADER_FMT));
+  my $expected = $self->{bin_req_id};
+  my $header;
+  my $body="";
+
+  $sock->recv($header, $header_len);
+
+  my ($magic, $cmd, $key_len, $extra_len, $datatype, $status, $body_len,
+      $opaque, $cas_hi, $cas_lo) = unpack(BINARY_HEADER_FMT, $header);
+  
+  ($magic == BINARY_RESPONSE) || Carp::confess "Bad magic number in response";
+  ($opaque == $expected) || Carp::confess "Response out of order ($expected/$opaque)";
+  
+  while($body_len - length($body) > 0) {
+    my $buf;
+    $sock->recv($buf, $body_len - length($body));
+    $body .= $buf;
+  }
+  $self->{error} = $error_message{$status};
+
+  # Packet structure is: header .. extras .. key .. value 
+  my $l = $extra_len + $key_len;
+  my $extras = substr $body, 0, $extra_len;
+  my $key    = substr $body, $extra_len, $key_len; 
+  my $value  = substr $body, $l, $body_len - $l;
+
+  return ($status, $value, $key, $extras);
+}  
+
+
+sub bin_math {
+  my $self = shift;
+  my ($cmd, $key, $delta, $initial, $expires) = @_;
+  
+  my $extra_header = pack "NNNNN", 
+  ($delta   / (2 ** 32)),   # delta hi
+  ($delta   % (2 ** 32)),   # delta lo
+  ($initial / (2 ** 32)),   # initial hi
+  ($initial % (2 ** 32)),   # initial lo
+  $expires;
+  $self->send_binary_request($cmd, $key, '', $extra_header);  
+  my ($status, $value) = $self->get_binary_response();
+  return ($status == 0) ? $value : undef;
+}
+
+
+sub bin_store {
+  my $self = shift;
+  my $cmd = shift;
+  my $key = shift;
+  my $value = shift;
+  
+  my $extra_header = pack "NN", $self->{flags}, $self->{exptime};
+  $self->send_binary_request($cmd, $key, $value, $extra_header);
+  
+  my ($status) = $self->get_binary_response();
+  return ($status == 0) ? 1 : 0;
+}
+
+
+sub get {
+  my $self = shift;
+  my $key = shift;
+  
+  $self->send_binary_request(BIN_CMD_GET, $key, '', '');  
+  my ($status, $value) = $self->get_binary_response();
+  return ($status == 0) ? $value : undef;
+}
+
+sub stats {
+  my $self = shift;
+  my $key = shift;
+  my %response, my $status, my $value, my $klen, my $tlen;
+
+  $self->send_binary_request(BIN_CMD_STAT, $key, '', '');
+  do {
+    ($status, $value, $key) = $self->get_binary_response();
+    if($status == 0) {
+      $response{$key} = $value;
+    } 
+  } while($status == 0 && $key);
+
+  return %response;
+}
+
+sub flush {
+  my ($self, $key, $value) = @_;
+  $self->send_binary_request(BIN_CMD_FLUSH, $key, '', ''); 
+  my ($status, $value) = $self->get_binary_response();
+  return ($status == 0) ? 1 : 0;
+}
+  
+sub set {
+  my ($self, $key, $value) = @_;
+  return $self->bin_store(BIN_CMD_SET, $key, $value);
+}
+
+sub add {
+  my ($self, $key, $value) = @_;
+  return $self->bin_store(BIN_CMD_ADD, $key, $value);
+}
+
+sub replace {
+  my ($self, $key, $value) = @_;
+  return $self->bin_store(BIN_CMD_REPLACE, $key, $value);
+}
+
+sub append {
+  my ($self, $key, $value) = @_;
+  $self->send_binary_request(BIN_CMD_APPEND, $key, $value, '');
+  my ($status) = $self->get_binary_response();
+  return ($status == 0) ? 1 : 0;
+}
+
+sub prepend {
+  my ($self, $key, $value) = @_;
+  $self->send_binary_request(BIN_CMD_PREPEND, $key, $value, '');
+  my ($status) = $self->get_binary_response();
+  return ($status == 0) ? 1 : 0;
+}
+
+sub delete { 
+  my ($self, $key) = @_;
+  $self->send_binary_request(BIN_CMD_DELETE, $key, '', '');
+  my ($status, $value) = $self->get_binary_response();
+  return ($status == 0) ? 1 : 0;
+}
+  
+sub incr {
+  my ($self, $key, $delta) = @_;
+  return $self->bin_math(BIN_CMD_INCR, $key, $delta, 0, 0xffffffff);
+}
+
+sub decr {
+  my ($self, $key, $delta) = @_;
+  return $self->bin_math(BIN_CMD_DECR, $key, $delta, 0, 0xffffffff);
+}
+
+
+1;
+

=== modified file 'mysql-test/lib/mtr_cases.pm'
--- a/mysql-test/lib/mtr_cases.pm	2012-03-06 14:29:42 +0000
+++ b/mysql-test/lib/mtr_cases.pm	2012-04-18 14:56:21 +0000
@@ -1090,6 +1090,13 @@ sub collect_one_test_case {
     }
   }
 
+  if ( $tinfo->{'not_windows'} && IS_WINDOWS )
+  {
+    $tinfo->{'skip'}= 1;
+    $tinfo->{'comment'}= "Test not supported on Windows";
+    return $tinfo;
+  }
+
   # ----------------------------------------------------------------------
   # Find config file to use if not already selected in <testname>.opt file
   # ----------------------------------------------------------------------
@@ -1172,6 +1179,7 @@ my @tags=
  ["include/not_embedded.inc", "not_embedded", 1],
  ["include/have_ssl.inc", "need_ssl", 1],
  ["include/have_ssl_communication.inc", "need_ssl", 1],
+ ["include/not_windows.inc", "not_windows", 1],
 );
 
 

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2012-04-23 11:00:29 +0000
+++ b/mysql-test/mysql-test-run.pl	2012-04-27 08:11:57 +0000
@@ -411,7 +411,6 @@ sub main {
     unshift(@$tests, $tinfo);
   }
 
-  print "vardir: $opt_vardir\n";
   initialize_servers();
 
   #######################################################################
@@ -2817,7 +2816,7 @@ sub check_ndbcluster_support ($) {
     mtr_report(" - MySQL Cluster");
     # Enable ndb engine and add more test suites
     $opt_include_ndbcluster = 1;
-    $DEFAULT_SUITES.=",ndb,ndb_binlog,rpl_ndb,ndb_rpl";
+    $DEFAULT_SUITES.=",ndb,ndb_binlog,rpl_ndb,ndb_rpl,ndb_memcache";
   }
 
   if ($opt_include_ndbcluster)
@@ -3082,6 +3081,126 @@ sub ndbd_start {
 }
 
 
+sub memcached_start {
+  my ($cluster, $memcached) = @_;
+
+  my $name = $memcached->name();
+  mtr_verbose("memcached_start '$name'");
+
+  my $found_perl_source = my_find_file($basedir,
+     ["storage/ndb/memcache",        # source
+      "mysql-test/lib",              # install
+      "share/mysql-test/lib"],       # install
+      "memcached_path.pl", NOT_REQUIRED);
+
+  mtr_verbose("Found memcache script: '$found_perl_source'");
+  $found_perl_source ne "" or return;
+
+  my $found_so = my_find_file($bindir,
+    ["storage/ndb/memcache",        # source or build
+     "lib", "lib64"],               # install
+    "ndb_engine.so");
+  mtr_verbose("Found memcache plugin: '$found_so'");
+
+  require "$found_perl_source";
+  if(! memcached_is_available())
+  {
+    mtr_error("Memcached not available.");
+  }
+  my $exe = "";
+  if(memcached_is_bundled())
+  {
+    $exe = my_find_bin($bindir,
+    ["libexec", "sbin", "bin", "storage/ndb/memcache/extra/memcached"],
+    "memcached", NOT_REQUIRED);
+  }
+  else
+  {
+    $exe = get_memcached_exe_path();
+  }
+  $exe ne "" or mtr_error("Failed to find memcached.");
+
+  my $args;
+  mtr_init_args(\$args);
+  # TCP port number to listen on
+  mtr_add_arg($args, "-p %d", $memcached->value('port'));
+  # Max simultaneous connections
+  mtr_add_arg($args, "-c %d", $memcached->value('max_connections'));
+  # Load engine as storage engine, ie. /path/ndb_engine.so
+  mtr_add_arg($args, "-E");
+  mtr_add_arg($args, $found_so);
+  # Config options for loaded storage engine
+  {
+    my @opts;
+    push(@opts, "connectstring=" . $memcached->value('ndb_connectstring'));
+    push(@opts, $memcached->if_exist("options"));
+    mtr_add_arg($args, "-e");
+    mtr_add_arg($args, join(";", @opts));
+  }
+
+  if($opt_gdb)
+  {
+    gdb_arguments(\$args, \$exe, "memcached");
+  }
+
+  my $proc = My::SafeProcess->new
+  ( name     =>  $name,
+    path     =>  $exe,
+    args     => \$args,
+    output   =>  "$opt_vardir/log/$name.out",
+    error    =>  "$opt_vardir/log/$name.out",
+    append   =>  1,
+    verbose  => $opt_verbose,
+  );
+  mtr_verbose("Started $proc");
+
+  $memcached->{proc} = $proc;
+
+  return;
+}
+
+
+sub memcached_load_metadata($) {
+  my $cluster= shift;
+
+  foreach my $mysqld (mysqlds())
+  {
+    if(-d $mysqld->value('datadir') . "/" . "ndbmemcache")
+    {
+      mtr_verbose("skipping memcache metadata (already stored)");
+      return;
+    }
+  }
+
+  my $sql_script= my_find_file($bindir,
+                              ["share/mysql/memcache-api", # RPM install
+                               "share/memcache-api",       # Other installs
+                               "scripts"                   # Build tree
+                              ],
+                              "ndb_memcache_metadata.sql", NOT_REQUIRED);
+  mtr_verbose("memcached_load_metadata: '$sql_script'");
+  if (-f $sql_script )
+  {
+    my $args;
+    mtr_init_args(\$args);
+    mtr_add_arg($args, "--defaults-file=%s", $path_config_file);
+    mtr_add_arg($args, "--defaults-group-suffix=%s", $cluster->suffix());
+    mtr_add_arg($args, "--connect-timeout=20");
+    if ( My::SafeProcess->run(
+           name   => "ndbmemcache config loader",
+           path   => $exe_mysql,
+           args   => \$args,
+           input  => $sql_script,
+           output => "$opt_vardir/log/memcache_config.log",
+           error  => "$opt_vardir/log/memcache_config.log"
+       ) != 0)
+    {
+      mtr_error("Could not load ndb_memcache_metadata.sql file");
+    }
+  }
+}
+
+
 sub ndbcluster_start ($) {
   my $cluster= shift;
 
@@ -4254,7 +4373,7 @@ sub run_testcase ($) {
     }
 
     # Try to dump core for mysqltest and all servers
-    foreach my $proc ($test, started(all_servers())) 
+    foreach my $proc ($test, started(all_servers()))
     {
       mtr_print("Trying to dump core for $proc");
       if ($proc->dump_core())
@@ -5280,8 +5399,8 @@ sub mysqlds { return _like('mysqld.'); }
 sub ndbds   { return _like('cluster_config.ndbd.');}
 sub ndb_mgmds { return _like('cluster_config.ndb_mgmd.'); }
 sub clusters  { return _like('mysql_cluster.'); }
-sub all_servers { return ( mysqlds(), ndb_mgmds(), ndbds() ); }
-
+sub memcacheds { return _like('memcached.'); }
+sub all_servers { return ( mysqlds(), ndb_mgmds(), ndbds(), memcacheds() ); }
 
 #
 # Filter a list of servers and return only those that are part
@@ -5353,7 +5472,7 @@ sub stop_servers($$) {
 
     # cluster processes
     My::SafeProcess::shutdown( $opt_shutdown_timeout,
-			       started(ndbds(), ndb_mgmds()) );
+			       started(ndbds(), ndb_mgmds(), memcacheds()) );
   }
   else
   {
@@ -5548,6 +5667,23 @@ sub start_servers($) {
       return 1;
     }
   }
+
+  # Start memcached(s) for each cluster
+  foreach my $cluster ( clusters() )
+  {
+    next if !in_cluster($cluster, memcacheds());
+
+    # Load the memcache metadata into this cluster
+    memcached_load_metadata($cluster);
+
+    # Start memcached(s)
+    foreach my $memcached ( in_cluster($cluster, memcacheds()))
+    {
+      next if started($memcached);
+      memcached_start($cluster, $memcached);
+    }
+  }
+
   return 0;
 }
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (magnus.blaudd:3749 to 3750) magnus.blaudd27 Apr