Commit c431b23b authored by Magnus Svensson's avatar Magnus Svensson
Browse files

Fixup mtr_unique. Remove usage of ps and grep. Make it a module. Move...

Fixup mtr_unique. Remove usage of ps and grep. Make it a module. Move _process_alive to Platform.pm. Rename opt_baseport to baseport, it's not an option
parent 552d514d
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ use strict;
use base qw(Exporter);
our @EXPORT= qw(IS_CYGWIN IS_WINDOWS IS_WIN32PERL
		native_path posix_path mixed_path
                check_socket_path_length);
                check_socket_path_length process_alive);

BEGIN {
  if ($^O eq "cygwin") {
@@ -123,4 +123,16 @@ sub check_socket_path_length {
}


sub process_alive {
  my ($pid)= @_;
  die "usage: process_alive(pid)" unless $pid;

  return kill(0, $pid) unless IS_WINDOWS;

  my @list= split(/,/, `tasklist /FI "PID eq $pid" /NH /FO CSV`);
  my $ret_pid= eval($list[1]);
  return ($ret_pid == $pid);
}


1;
+0 −11
Original line number Diff line number Diff line
@@ -100,17 +100,6 @@ else
}


sub _process_alive {
  my ($pid)= @_;

  return kill(0, $pid) unless IS_WINDOWS;

  my @list= split(/,/, `tasklist /FI "PID eq $pid" /NH /FO CSV`);
  my $ret_pid= eval($list[1]);
  return ($ret_pid == $pid);
}


sub new {
  my $class= shift;

mysql-test/lib/mtr_unique.pl

deleted100644 → 0
+0 −178
Original line number Diff line number Diff line
# -*- cperl -*-
# Copyright (C) 2006 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; 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

#
# This file is used from mysql-test-run.pl when choosing
# port numbers and directories to use for running mysqld.
#

use strict;
use Fcntl ':flock';

#
# Requested IDs are stored in a hash and released upon END.
#
my %mtr_unique_assigned_ids = ();
my $mtr_unique_pid;
BEGIN {
	$mtr_unique_pid = $$ unless defined $mtr_unique_pid;
}
END { 
	if($mtr_unique_pid == $$) {
		while(my ($id,$file) = each(%mtr_unique_assigned_ids)) {
			print "Autoreleasing $file:$id\n";
			mtr_release_unique_id($file, $id);
		}
	}
}

#
# Require a unique, numerical ID, given a file name (where all
# requested IDs are stored), a minimum and a maximum value.
#
# We use flock to implement locking for the ID file and ignore
# possible problems arising from lack of support for it on 
# some platforms (it should work on most, and the possible
# race condition would occur rarely). The proper solution for
# this is a daemon that manages IDs, of course.
#
# If no unique ID within the specified parameters can be 
# obtained, return undef.
#
sub mtr_require_unique_id($$$) {
	my $file = shift;
	my $min = shift;
	my $max = shift;
	my $ret = undef;
	my $changed = 0;

	my $can_use_ps = `ps -e | grep '^[ ]*$$ '`;

	if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
		die 'lock file is a symbolic link';
	}

	chmod 0777, "$file.sem";
	open SEM, ">", "$file.sem" or die "can't write to $file.sem";
	flock SEM, LOCK_EX or die "can't lock $file.sem";
	if(! -e $file) {
		open FILE, ">", $file or die "can't create $file";
		close FILE;
	}

	if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
		die 'lock file is a symbolic link';
	}

	chmod 0777, $file;
	open FILE, "+<", $file or die "can't open $file";
	select undef,undef,undef,0.2;
	seek FILE, 0, 0;
	my %taken = ();
	while(<FILE>) {
		chomp;
		my ($id, $pid) = split / /;
		$taken{$id} = $pid;
		if($can_use_ps) {
			my $res = `ps -e | grep '^[ ]*$pid '`;
			if(!$res) {
				print "Ignoring slot $id used by missing process $pid.\n";
				delete $taken{$id};
				++$changed;
			}
		}
	}
	for(my $i=$min; $i<=$max; ++$i) {
		if(! exists $taken{$i}) {
			$ret = $i;
			$taken{$i} = $$;
			++$changed;
			last;
		}
	}
	if($changed) {
		seek FILE, 0, 0;
		truncate FILE, 0 or die "can't truncate $file";
		for my $k (keys %taken) {
			print FILE $k . ' ' . $taken{$k} . "\n";
		}
	}
	close FILE;
	flock SEM, LOCK_UN or warn "can't unlock $file.sem";
	close SEM;
	$mtr_unique_assigned_ids{$ret} = $file if defined $ret;
	return $ret;
}

#
# Require a unique ID like above, but sleep if no ID can be
# obtained immediately.
#
sub mtr_require_unique_id_and_wait($$$) {
	my $ret = mtr_require_unique_id($_[0],$_[1],$_[2]);
	while(! defined $ret) {
		sleep 30;
		$ret = mtr_require_unique_id($_[0],$_[1],$_[2]);
		print "Waiting for unique id to become available...\n" unless $ret;
	}
	return $ret;
}

#
# Release a unique ID.
#
sub mtr_release_unique_id($$) {
	my $file = shift;
	my $myid = shift;

	if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
		die 'lock file is a symbolic link';
	}

	open SEM, ">", "$file.sem" or die "can't write to $file.sem";
	flock SEM, LOCK_EX or die "can't lock $file.sem";

	if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
		die 'lock file is a symbolic link';
	}

	if(! -e $file) {
		open FILE, ">", $file or die "can't create $file";
		close FILE;
	}
	open FILE, "+<", $file or die "can't open $file";
	select undef,undef,undef,0.2;
	seek FILE, 0, 0;
	my %taken = ();
	while(<FILE>) {
		chomp;
		my ($id, $pid) = split / /;
		$taken{$id} = $pid;
	}
	delete $taken{$myid};
	seek FILE, 0, 0;
	truncate FILE, 0 or die "can't truncate $file";
	for my $k (keys %taken) {
		print FILE $k . ' ' . $taken{$k} . "\n";
	}
	close FILE;
	flock SEM, LOCK_UN or warn "can't unlock $file.sem";
	close SEM;
	delete $mtr_unique_assigned_ids{$myid};
}

1;
+184 −0
Original line number Diff line number Diff line
# -*- cperl -*-
# Copyright (C) 2006 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; 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

package mtr_unique;

use strict;
use Fcntl ':flock';

use base qw(Exporter);
our @EXPORT= qw(mtr_get_unique_id mtr_release_unique_id);

use My::Platform;

sub msg {
 # print "### unique($$) - ", join(" ", @_), "\n";
}

my $file= "/tmp/mysql-test-ports";

my %mtr_unique_ids;

END {
  my $allocated_id= $mtr_unique_ids{$$};
  if (defined $allocated_id)
  {
    mtr_release_unique_id($allocated_id);
  }
  delete $mtr_unique_ids{$$};
}

#
# Get a unique, numerical ID, given a file name (where all
# requested IDs are stored), a minimum and a maximum value.
#
# If no unique ID within the specified parameters can be
# obtained, return undef.
#
sub mtr_get_unique_id($$) {
  my ($min, $max)= @_;;

  msg("get, '$file', $min-$max");

  die "Can only get one unique id per process!" if $mtr_unique_ids{$$};

  my $ret = undef;
  my $changed = 0;

  if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
    die 'lock file is a symbolic link';
  }

  chmod 0777, "$file.sem";
  open SEM, ">", "$file.sem" or die "can't write to $file.sem";
  flock SEM, LOCK_EX or die "can't lock $file.sem";
  if(! -e $file) {
    open FILE, ">", $file or die "can't create $file";
    close FILE;
  }

  msg("HAVE THE LOCK");

  if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
    die 'lock file is a symbolic link';
  }

  chmod 0777, $file;
  open FILE, "+<", $file or die "can't open $file";
  #select undef,undef,undef,0.2;
  seek FILE, 0, 0;
  my %taken = ();
  while(<FILE>) {
    chomp;
    my ($id, $pid) = split / /;
    $taken{$id} = $pid;
    msg("taken: $id, $pid");
    # Check if process with given pid is alive
    if(!process_alive($pid)) {
      msg("Removing slot $id used by missing process $pid");;
      delete $taken{$id};
      $changed++;
    }
  }
  for(my $i=$min; $i<=$max; ++$i) {
    if(! exists $taken{$i}) {
      $ret = $i;
      $taken{$i} = $$;
      $changed++;
      # Remember the id this process got
      $mtr_unique_ids{$$}= $i;
      msg(" got $i"); 
      last;
    }
  }
  if($changed) {
    seek FILE, 0, 0;
    truncate FILE, 0 or die "can't truncate $file";
    for my $k (keys %taken) {
      print FILE $k . ' ' . $taken{$k} . "\n";
    }
  }
  close FILE;

  msg("RELEASING THE LOCK");
  flock SEM, LOCK_UN or warn "can't unlock $file.sem";
  close SEM;

  return $ret;
}


#
# Release a unique ID.
#
sub mtr_release_unique_id($) {
  my ($myid)= @_;

  msg("release, $myid");


  if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
    die 'lock file is a symbolic link';
  }

  open SEM, ">", "$file.sem" or die "can't write to $file.sem";
  flock SEM, LOCK_EX or die "can't lock $file.sem";

  msg("HAVE THE LOCK");

  if(eval("readlink '$file'") || eval("readlink '$file.sem'")) {
    die 'lock file is a symbolic link';
  }

  if(! -e $file) {
    open FILE, ">", $file or die "can't create $file";
    close FILE;
  }
  open FILE, "+<", $file or die "can't open $file";
  #select undef,undef,undef,0.2;
  seek FILE, 0, 0;
  my %taken = ();
  while(<FILE>) {
    chomp;
    my ($id, $pid) = split / /;
    msg(" taken, $id $pid");
    $taken{$id} = $pid;
  }

  if ($taken{$myid} != $$)
  {
    msg(" The unique id for this process does not match pid");
  }


  msg(" removing $myid");
  delete $taken{$myid};
  seek FILE, 0, 0;
  truncate FILE, 0 or die "can't truncate $file";
  for my $k (keys %taken) {
    print FILE $k . ' ' . $taken{$k} . "\n";
  }
  close FILE;

  msg("RELEASE THE LOCK");

  flock SEM, LOCK_UN or warn "can't unlock $file.sem";
  close SEM;
}


1;
+12 −10
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ use My::SysInfo;
use mtr_cases;
use mtr_report;
use mtr_match;
use mtr_unique;
use IO::Socket::INET;
use IO::Select;

@@ -60,7 +61,6 @@ require "lib/mtr_process.pl";
require "lib/mtr_io.pl";
require "lib/mtr_gcov.pl";
require "lib/mtr_misc.pl";
require "lib/mtr_unique.pl";

$SIG{INT}= sub { mtr_error("Got ^C signal"); };

@@ -143,7 +143,7 @@ our $opt_client_debugger;
my $config; # The currently running config
my $current_config_name; # The currently running config file template

my $opt_baseport;
my $baseport;
my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto";

my $opt_record;
@@ -1181,24 +1181,26 @@ sub set_build_thread_ports($) {

  if ( lc($build_thread) eq 'auto' ) {
    mtr_report("Requesting build thread... ");
    $build_thread=
      mtr_require_unique_id_and_wait("/tmp/mysql-test-ports", 200, 299);
    $build_thread= mtr_get_unique_id(200, 299);
    if ( !defined $build_thread ) {
      mtr_error("Could not get a unique build thread id");
    }
    mtr_report(" - got $build_thread");
  }
  $ENV{MTR_BUILD_THREAD}= $build_thread;
  $opt_build_thread= $build_thread;

  # Calculate baseport
  $opt_baseport= $build_thread * 10 + 10000;
  if ( $opt_baseport < 5001 or $opt_baseport + 9 >= 32767 )
  $baseport= $build_thread * 10 + 10000;
  if ( $baseport < 5001 or $baseport + 9 >= 32767 )
  {
    mtr_error("MTR_BUILD_THREAD number results in a port",
              "outside 5001 - 32767",
              "($opt_baseport - $opt_baseport + 9)");
              "($baseport - $baseport + 9)");
  }

  mtr_report("Using MTR_BUILD_THREAD $build_thread,",
	     "with reserved ports $opt_baseport..".($opt_baseport+9));
	     "with reserved ports $baseport..".($baseport+9));

}

@@ -2286,7 +2288,7 @@ sub kill_leftovers ($) {
sub check_ports_free
{
  my @ports_to_check;
  for ($opt_baseport..$opt_baseport+9){
  for ($baseport..$baseport+9){
    push(@ports_to_check, $_);
  }
  mtr_report("Checking ports...");
@@ -2931,7 +2933,7 @@ sub run_testcase ($) {
	   extra_template_path => $tinfo->{extra_template_path},
	   vardir          => $opt_vardir,
	   tmpdir          => $opt_tmpdir,
	   baseport        => $opt_baseport,
	   baseport        => $baseport,
	   #hosts          => [ 'host1', 'host2' ],
	   user            => $opt_user,
	   password        => '',