~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysql-test/lib/mtr_unique.pl

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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