diff options
Diffstat (limited to 'mysql-test/lib/mtr_unique.pm')
-rw-r--r-- | mysql-test/lib/mtr_unique.pm | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/mysql-test/lib/mtr_unique.pm b/mysql-test/lib/mtr_unique.pm new file mode 100644 index 00000000000..b4093ab1dce --- /dev/null +++ b/mysql-test/lib/mtr_unique.pm @@ -0,0 +1,185 @@ +# -*- 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)) { + print "Removing slot $id used by missing process $pid\n"; + 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; + |