Here is some sample code:
- Code: Select all
<?php
$method = 2;
$msgid_filename = '/tmp/readwrite';
$uid = md5(uniqid(rand(), true));
$msgid = 0;
while(1)
{
clearstatcache();
if (file_exists($msgid_filename)) {
$fh = fopen($msgid_filename, 'r+');
while(1)
{
if ($method == 1)
{
flock($fh, LOCK_EX);
}
else
{
nfs_flock($msgid_filename, LOCK_EX);
}
$msgid = chop(fread($fh, filesize($msgid_filename)));
$msgid++;
rewind($fh);
fwrite($fh, $msgid);
fflush($fh);
ftruncate($fh, ftell($fh));
if ($method == 1)
{
flock($fh, LOCK_UN);
}
else
{
nfs_flock($msgid_filename, LOCK_UN);
}
break;
}
}
else {
$fh = fopen($msgid_filename, 'w+');
fwrite($fh, "1");
$msgid="1";
}
fclose($fh);
echo "uid=".$uid." ".trim($msgid)."n";
usleep(rand(0,1000)); // a very small pause
}
function nfs_flock ($filename, $lock)
{
if ($lock == LOCK_EX)
{
Do {
$locked = @mkdir($filename.".lock");
usleep(round(rand(0,10000)));
} while ($locked === false);
return true;
}
else if ($lock == LOCK_UN)
{
rmdir($filename.".lock");
return true;
}
}
?>
If you cannot use flock, please try to run multiple instances on your server and verify that the counter never gets reset or out of sync.
Known Issues:
1) If the application is inadvertently shuts down, the lock may not be cleaned up. That will cause deadlocks when the application is restarted. Perhaps I can enhance include logic to delete the lock if it's more than X seconds old?
2) I'd like this to be a direct replacement for flock. However, I need the filename and path, not the file handle. Does anyone know how to extract the absolute path and name of a file from the file handle?