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.blaudd | 27 Apr |