note 69306 added to function.flock
| From: | chozo at juno dot com | Date: | Thu, 31 Aug 2006 02:06:04 +0000 |
| Subject: | note 69306 added to function.flock | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-116527@lists.php.net to get a copy of this message | ||
Recently I had to put together a form of file locking method for my message boards I'd been
writing. However, being that I run windows 98 (FAT32) FLOCK will as per the documentation will
always return false and not work. So... I had to make one up on my own since I rely on flatfile
databases for my scripts rather than SQL.
I had to modify drangers stress test to fit in with the locking method I use. My method uses a
two-step lock. We will make the target file read-only AND apply a lock-file. Two steps are used due
to the read-only being unset when the target is being written to and the lockfile as a precaution
while the target is now writable but marked as still locked by the lockfile.
I had ran 4 instances of this script looping at once and there was no instance of a data mismatch on
any of them. However, it will give out a notice if the lock was beaten to through a race condition -
which will cause it to reattempt to aquire a lock rather than continue.
Test platform was:
Windows 98 Second Edition
Abyss Web Server X1 (v 2.3.2)
PHP v4.4.3RC2-dev
Simulatanious test loops ran: 04
As for the code...
NOTE: the chmod is set for a win9x system not NT/*nix/Etc.
You'll have to adjust the chmod settings accordingly if used on other systems.
Also, there are some lines that are optional which can be safely removed but will increase the
chance of a lock retry when removed. Full comments provided as well.
<?php
//Windows 9x FLOCK Alternative - Chozo4
//Passes multiple instance stress testing
//http://mechresource.myvnc.com/board
function aquirelock($wp)
{
//Keep looping until both our lock doesn't exist and our target is writable
//Additionally - use a random start point to help break up racing conditions
for($x=rand(1,23);(file_exists("$wp.l") || !is_writable($wp));)
if(!(++$x%25)) clearstatcache(); //Clear the stat cache and recheck both
//create the lock - hide warnings and pass empty if already created from racing
return @fopen("$wp.l",'x');
}
function dblock($wp)
{
//Check for lockfile handle - if empty , another process raced the lock so retry
while (!$ftw=aquirelock($wp)) echo 'Locked by Other... retrying<br>';
chmod($wp,0444); //set the target file to read-only
fwrite($ftw,'lock'); //write the lockfile with 4bytes
chmod("$wp.l",0444); //set the lockfile to read only (OPTIONAL)
fclose($ftw); //close our lockfile
clearstatcache(); //Clear the stat cache
}
function dbexport_unlock($wp,$data,$meth)
{
chmod($wp,0666); //Set the target file to read+write
//Write the passed string to the target file then close
fwrite($ftw=fopen($wp,$meth),$data);fclose($ftw);
//Validate the written data ujsing a string comparison
$check=file_get_contents($wp);
if($check != $data) echo "Data Mismatch - Locking FAILED!<br>";
chmod("$wp.l",0666); //Set the lockfile to read+write (OPTIONAL)
unlink ("$wp.l"); //Release the lockfile by removing it
}
while(1) //our stress-test loop (must run multiple instances to verify)
{
dblock('test'); //aquire our file lock on file 'test' (must exist)
//getmypid() turns up blank on this system
//use a random number instead for this test
$pid=rand(0,500000);
//Our contents to be written to the file
$string="Important Information! From $pid";
//Unset our locks incrementally in steps while writing
//Done using the next function call...
dbexport_unlock('test',$string,'w');
}
?>
----
Server IP: 66.163.161.117
Probable Submitter: 71.3.189.225
----
X-Spam-Status: No, hits=3.3 required=5.0 tests=DATE_MISSING,FROM_NO_LOWER,
HTML_MESSAGE autolearn=no version=2.64
----
Manual Page -- http://www.php.net/manual/en/function.flock.php
Edit -- https://master.php.net/note/edit/69306
Del: integrated -- https://master.php.net/note/delete/69306/integrated
Del: useless -- https://master.php.net/note/delete/69306/useless
Del: bad code -- https://master.php.net/note/delete/69306/bad+code
Del: spam -- https://master.php.net/note/delete/69306/spam
Del: non-english -- https://master.php.net/note/delete/69306/non-english
Del: in docs -- https://master.php.net/note/delete/69306/in+docs
Del: other reasons-- https://master.php.net/note/delete/69306
Reject -- https://master.php.net/note/reject/69306
Search -- https://master.php.net/manage/user-notes.php