note 64150 deleted from function.flock by danbrown
| From: | danbrown@php.net | Date: | Mon, 18 May 2009 00:38:34 +0000 |
| Subject: | note 64150 deleted from function.flock by danbrown | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-155399@lists.php.net to get a copy of this message | ||
Note Submitter: wildcat at brightNOSPAMpages dot net
----
I wrote the following function to make a script wait in a queue of instances accessing the same
shared resource and then lock it, as a part of a lock-access-release advisory mechanism based on
locking directories.
It works on my web site (also passes the loop test proposed by dranger below). Might show
unpredicted behaviors on other systems, under conditions I didn't think at or produce,
expecially when mkdir atomicity is not guaranteed.
The whole script is too long for posting, but everyone interested in looking for eventual bugs,
testing, torturing and using it, can download code and documentation from http://brightpages.net/doc > QLCK.
Hope it is useful.
<?php
function qLock($lockSuffix, $tmpDir, $maxWait, $padLength) {
if ($tmpDir == '' or !is_dir($tmpDir)) $tmpDir = '.';
$maxWait = (int) $maxWait; if ($maxWait <= 0) $maxWait = 60;
$padLength = (int) $padLength; if ($padLength <= 0) $padLength = 6;
if ($lockSuffix == '') {
return false;
} else {
$currentdir = getcwd();
chdir($tmpDir); // relative to the current directory
$n = 0;
$lockdirs = glob('*-*.'.$lockSuffix, GLOB_ONLYDIR) or array();
foreach($lockdirs as $lockdir) {
list($m, ) = explode('-', $lockdir);
$m = intval($m);
if ($m > $n) $n = $m + 1;
}
$npad = str_pad((string) $n, $padLength, '0', STR_PAD_LEFT);
while (glob($npad.'-*.'.$lockSuffix, GLOB_ONLYDIR)) {
$n++;
$npad = str_pad((string) $n, $padLength, '0', STR_PAD_LEFT);
}
$lockname = $npad.'-'.md5(uniqid(rand(), true)).'.'.$lockSuffix;
if (@mkdir($lockname)) {
$nlockdirs = glob($npad.'-*.'.$lockSuffix, GLOB_ONLYDIR) or array();
if (count($nlockdirs) != 1) {
@rmdir($lockname);
return false;
} else {
$prelockdirs = array();
$lockdirs = glob('*-*.'.$lockSuffix, GLOB_ONLYDIR) or array();
foreach($lockdirs as $lockdir) {
list($m, ) = explode('-', $lockdir);
$m = intval($m);
if ($m < $n) $prelockdirs[] = $lockdir;
}
$t0 = time(); $t = 0;
while (count($prelockdirs) != 0 and $t < $maxWait) {
$prelockdirs = array();
$lockdirs = glob('*-*.'.$lockSuffix, GLOB_ONLYDIR) or array();
foreach($lockdirs as $lockdir) {
list($m, ) = explode('-', $lockdir);
$m = intval($m);
if ($m < $n) $prelockdirs[] = $lockdir;
}
$t = time() - $t0;
}
if (count($prelockdirs) != 0) {
@rmdir($lockname);
return false;
} else {
return $lockname;
}
}
} else {
@rmdir($lockname);
return false;
}
chdir($currentdir);
}
}
?>