1# -*- cperl -*- 2# Copyright (c) 2006, 2008 MySQL AB, 2009 Sun Microsystems, Inc. 3# Use is subject to license terms. 4# 5# This program is free software; you can redistribute it and/or modify 6# it under the terms of the GNU General Public License, version 2.0, 7# as published by the Free Software Foundation. 8# 9# This program is also distributed with certain software (including 10# but not limited to OpenSSL) that is licensed under separate terms, 11# as designated in a particular file or component or in included license 12# documentation. The authors of MySQL hereby grant you an additional 13# permission to link the program and your derivative works with the 14# separately licensed software that they have included with MySQL. 15# 16# This program is distributed in the hope that it will be useful, 17# but WITHOUT ANY WARRANTY; without even the implied warranty of 18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19# GNU General Public License, version 2.0, for more details. 20# 21# You should have received a copy of the GNU General Public License 22# along with this program; if not, write to the Free Software 23# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 25package mtr_unique; 26 27use strict; 28use Fcntl ':flock'; 29 30use base qw(Exporter); 31our @EXPORT= qw(mtr_get_unique_id mtr_release_unique_id); 32 33use My::Platform; 34 35sub msg { 36 # print "### unique($$) - ", join(" ", @_), "\n"; 37} 38 39my $dir; 40 41if(!IS_WINDOWS) 42{ 43 $dir= "/tmp/mysql-unique-ids"; 44} 45else 46{ 47 # Try to use machine-wide directory location for unique IDs, 48 # $ALLUSERSPROFILE . IF it is not available, fallback to $TEMP 49 # which is typically a per-user temporary directory 50 if (exists $ENV{'ALLUSERSPROFILE'} && -w $ENV{'ALLUSERSPROFILE'}) 51 { 52 $dir= $ENV{'ALLUSERSPROFILE'}."/mysql-unique-ids"; 53 } 54 else 55 { 56 $dir= $ENV{'TEMP'}."/mysql-unique-ids"; 57 } 58} 59 60my $mtr_unique_fh = undef; 61 62END 63{ 64 mtr_release_unique_id(); 65} 66 67# 68# Get a unique, numerical ID in a specified range. 69# 70# If no unique ID within the specified parameters can be 71# obtained, return undef. 72# 73sub mtr_get_unique_id($$) { 74 my ($min, $max)= @_;; 75 76 msg("get $min-$max, $$"); 77 78 die "Can only get one unique id per process!" if defined $mtr_unique_fh; 79 80 81 # Make sure our ID directory exists 82 if (! -d $dir) 83 { 84 # If there is a file with the reserved 85 # directory name, just delete the file. 86 if (-e $dir) 87 { 88 unlink($dir); 89 } 90 91 mkdir $dir; 92 chmod 0777, $dir; 93 94 if(! -d $dir) 95 { 96 die "can't make directory $dir"; 97 } 98 } 99 100 101 my $fh; 102 for(my $id = $min; $id <= $max; $id++) 103 { 104 open( $fh, ">$dir/$id"); 105 chmod 0666, "$dir/$id"; 106 # Try to lock the file exclusively. If lock succeeds, we're done. 107 if (flock($fh, LOCK_EX|LOCK_NB)) 108 { 109 # Store file handle - we would need it to release the ID (==unlock the file) 110 $mtr_unique_fh = $fh; 111 return $id; 112 } 113 else 114 { 115 close $fh; 116 } 117 } 118 return undef; 119} 120 121 122# 123# Release a unique ID. 124# 125sub mtr_release_unique_id() 126{ 127 msg("release $$"); 128 if (defined $mtr_unique_fh) 129 { 130 close $mtr_unique_fh; 131 $mtr_unique_fh = undef; 132 } 133} 134 135 1361; 137 138