1
by brian
clean slate |
1 |
# -*- cperl -*-
|
2 |
# Copyright (C) 2006 MySQL AB
|
|
3 |
#
|
|
4 |
# This program is free software; you can redistribute it and/or modify
|
|
5 |
# it under the terms of the GNU General Public License as published by
|
|
6 |
# the Free Software Foundation; version 2 of the License.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
16 |
||
17 |
#
|
|
18 |
# This file is used from mysql-test-run.pl when choosing
|
|
19 |
# port numbers and directories to use for running mysqld.
|
|
20 |
#
|
|
21 |
||
22 |
use strict; |
|
23 |
use Fcntl ':flock'; |
|
24 |
||
25 |
#
|
|
26 |
# Requested IDs are stored in a hash and released upon END.
|
|
27 |
#
|
|
28 |
my %mtr_unique_assigned_ids = (); |
|
29 |
my $mtr_unique_pid; |
|
30 |
BEGIN { |
|
31 |
$mtr_unique_pid = $$ unless defined $mtr_unique_pid; |
|
32 |
}
|
|
33 |
END { |
|
34 |
if($mtr_unique_pid == $$) { |
|
35 |
while(my ($id,$file) = each(%mtr_unique_assigned_ids)) { |
|
36 |
print "Autoreleasing $file:$id\n"; |
|
37 |
mtr_release_unique_id($file, $id); |
|
38 |
}
|
|
39 |
}
|
|
40 |
}
|
|
41 |
||
42 |
#
|
|
43 |
# Require a unique, numerical ID, given a file name (where all
|
|
44 |
# requested IDs are stored), a minimum and a maximum value.
|
|
45 |
#
|
|
46 |
# We use flock to implement locking for the ID file and ignore
|
|
47 |
# possible problems arising from lack of support for it on
|
|
48 |
# some platforms (it should work on most, and the possible
|
|
49 |
# race condition would occur rarely). The proper solution for
|
|
50 |
# this is a daemon that manages IDs, of course.
|
|
51 |
#
|
|
52 |
# If no unique ID within the specified parameters can be
|
|
53 |
# obtained, return undef.
|
|
54 |
#
|
|
55 |
sub mtr_require_unique_id($$$) { |
|
56 |
my $file = shift; |
|
57 |
my $min = shift; |
|
58 |
my $max = shift; |
|
59 |
my $ret = undef; |
|
60 |
my $changed = 0; |
|
61 |
||
62 |
my $can_use_ps = `ps -e | grep '^[ ]*$$ '`; |
|
63 |
||
64 |
if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { |
|
65 |
die 'lock file is a symbolic link'; |
|
66 |
}
|
|
67 |
||
68 |
chmod 0777, "$file.sem"; |
|
69 |
open SEM, ">", "$file.sem" or die "can't write to $file.sem"; |
|
70 |
flock SEM, LOCK_EX or die "can't lock $file.sem"; |
|
71 |
if(! -e $file) { |
|
72 |
open FILE, ">", $file or die "can't create $file"; |
|
73 |
close FILE; |
|
74 |
}
|
|
75 |
||
76 |
if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { |
|
77 |
die 'lock file is a symbolic link'; |
|
78 |
}
|
|
79 |
||
80 |
chmod 0777, $file; |
|
81 |
open FILE, "+<", $file or die "can't open $file"; |
|
82 |
select undef,undef,undef,0.2; |
|
83 |
seek FILE, 0, 0; |
|
84 |
my %taken = (); |
|
85 |
while(<FILE>) { |
|
86 |
chomp; |
|
87 |
my ($id, $pid) = split / /; |
|
88 |
$taken{$id} = $pid; |
|
89 |
if($can_use_ps) { |
|
90 |
my $res = `ps -e | grep '^[ ]*$pid '`; |
|
91 |
if(!$res) { |
|
92 |
print "Ignoring slot $id used by missing process $pid.\n"; |
|
93 |
delete $taken{$id}; |
|
94 |
++$changed; |
|
95 |
}
|
|
96 |
}
|
|
97 |
}
|
|
98 |
for(my $i=$min; $i<=$max; ++$i) { |
|
99 |
if(! exists $taken{$i}) { |
|
100 |
$ret = $i; |
|
101 |
$taken{$i} = $$; |
|
102 |
++$changed; |
|
103 |
last; |
|
104 |
}
|
|
105 |
}
|
|
106 |
if($changed) { |
|
107 |
seek FILE, 0, 0; |
|
108 |
truncate FILE, 0 or die "can't truncate $file"; |
|
109 |
for my $k (keys %taken) { |
|
110 |
print FILE $k . ' ' . $taken{$k} . "\n"; |
|
111 |
}
|
|
112 |
}
|
|
113 |
close FILE; |
|
114 |
flock SEM, LOCK_UN or warn "can't unlock $file.sem"; |
|
115 |
close SEM; |
|
116 |
$mtr_unique_assigned_ids{$ret} = $file if defined $ret; |
|
117 |
return $ret; |
|
118 |
}
|
|
119 |
||
120 |
#
|
|
121 |
# Require a unique ID like above, but sleep if no ID can be
|
|
122 |
# obtained immediately.
|
|
123 |
#
|
|
124 |
sub mtr_require_unique_id_and_wait($$$) { |
|
125 |
my $ret = mtr_require_unique_id($_[0],$_[1],$_[2]); |
|
126 |
while(! defined $ret) { |
|
127 |
sleep 30; |
|
128 |
$ret = mtr_require_unique_id($_[0],$_[1],$_[2]); |
|
129 |
print "Waiting for unique id to become available...\n" unless $ret; |
|
130 |
}
|
|
131 |
return $ret; |
|
132 |
}
|
|
133 |
||
134 |
#
|
|
135 |
# Release a unique ID.
|
|
136 |
#
|
|
137 |
sub mtr_release_unique_id($$) { |
|
138 |
my $file = shift; |
|
139 |
my $myid = shift; |
|
140 |
||
141 |
if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { |
|
142 |
die 'lock file is a symbolic link'; |
|
143 |
}
|
|
144 |
||
145 |
open SEM, ">", "$file.sem" or die "can't write to $file.sem"; |
|
146 |
flock SEM, LOCK_EX or die "can't lock $file.sem"; |
|
147 |
||
148 |
if(eval("readlink '$file'") || eval("readlink '$file.sem'")) { |
|
149 |
die 'lock file is a symbolic link'; |
|
150 |
}
|
|
151 |
||
152 |
if(! -e $file) { |
|
153 |
open FILE, ">", $file or die "can't create $file"; |
|
154 |
close FILE; |
|
155 |
}
|
|
156 |
open FILE, "+<", $file or die "can't open $file"; |
|
157 |
select undef,undef,undef,0.2; |
|
158 |
seek FILE, 0, 0; |
|
159 |
my %taken = (); |
|
160 |
while(<FILE>) { |
|
161 |
chomp; |
|
162 |
my ($id, $pid) = split / /; |
|
163 |
$taken{$id} = $pid; |
|
164 |
}
|
|
165 |
delete $taken{$myid}; |
|
166 |
seek FILE, 0, 0; |
|
167 |
truncate FILE, 0 or die "can't truncate $file"; |
|
168 |
for my $k (keys %taken) { |
|
169 |
print FILE $k . ' ' . $taken{$k} . "\n"; |
|
170 |
}
|
|
171 |
close FILE; |
|
172 |
flock SEM, LOCK_UN or warn "can't unlock $file.sem"; |
|
173 |
close SEM; |
|
174 |
delete $mtr_unique_assigned_ids{$myid}; |
|
175 |
}
|
|
176 |
||
177 |
1; |
|
178 |