note 69306 added to function.flock

From: 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

« previous php.notes (#116527) next »