summaryrefslogtreecommitdiff
path: root/mysql-test/lib/mtr_unique.pm
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/lib/mtr_unique.pm')
-rw-r--r--mysql-test/lib/mtr_unique.pm185
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;
+