note 99931 added to function.flock
| From: | mirco dot babin at gmail dot com | Date: | Wed, 15 Sep 2010 17:10:49 +0000 |
| Subject: | note 99931 added to function.flock | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-172585@lists.php.net to get a copy of this message | ||
Because:
1) flock() is not safe if multiple php sessions are simultaneously locking.
2) fopen( , 'a') is not safe if multiple php sessions are simultaneously appending.
3) usleep and sleep are known for having problems.
I wrote the Weblog function, it's purpose is to append a line to logging. This function handles
the concurrency as follows:
- Try to create a lockfile named: $directory . date('Ymd') . $logfile . 1 . lock
- If this fails, try to create lockfile named: $directory . date('Ymd') . $logfile . 2 .
lock
- etc. After 100 tries return false.
- When the lockfile is acquired the file named: $directory.date('Ymd').$logfile.1 (or .2
or .3 or .25) is opened or created.
- If created the a "extended log file" header is written.
- Write out the line.
- Close the flie and if created set the correct access rights. (I had some problems creating files
on a webserver, I did not see them when I opened a FTP session to the webdirectory. The chmod did
the trick for me).
- Remove the lockfile.
There is only one drawback, multiple logfiles are created.
e.g. (executed on 15 september 2010)
Weblog('./' , 'visit', 'Somebody requested the index page');
Could lead to 100 files, depending how many concurrent php sessions are simultaneously trying to
append a logline:
./20100915visit.1
./20100915visit.2
./20100915visit.3
./20100915visit.4
...
./20100915visit.100
This function is donated to the public domain. Maybe you can give me some credit by leaving in the
author comment, but it is not required. You may modify this as you wish.
(This function was inspired by the function m_lock_file presented by Kuzma dot Deretuke at gmail dot
com)
<?php
function Weblog($directory, $logfile, $message)
{
// Created 15 september 2010: Mirco Babin
$curtime = time();
$logfile = date('Ymd',$curtime) . $logfile;
if (!isset($directory) || $directory === false)
$directory = './';
if (substr($directory,-1) !== '/')
$directory = $directory . '/';
$count = 1;
while(1)
{
$logfilename = $directory . $logfile . '.' . $count;
$lockfile = $logfilename . '.lock';
$lockhandle = false;
if (!file_exists($lockfile) || @unlink($lockfile))
$lockhandle = @fopen($lockfile, 'xb');
if ($lockhandle !== false) break;
$count++;
if ($count > 100) return false;
}
if (file_exists($logfilename))
{
$created = false;
$loghandle = @fopen($logfilename, 'ab');
}
else
{
$loghandle = @fopen($logfilename, 'xb');
if ($loghandle !== false)
{
$created = true;
$str = '#version: 1.0' . "\r\n" .
'#Fields: date time c-ip x-msg' . "\r\n";
fwrite($loghandle,$str);
}
}
if ($loghandle !== false)
{
$str = date('Y-m-d',$curtime) . "\t" .
date('H:i:s', $curtime) . "\t" .
(isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] :
'-') . "\t" .
'"' . str_replace('"', '""',
$message) . '"' . "\r\n";
fwrite($loghandle,$str);
fclose($loghandle);
if ($created) chmod($logfilename,0644); // Read and write for owner, read for everybody
else
$result = true;
}
else
{
$result = false;
}
fclose($lockhandle);
@unlink($lockfile);
return $result;
}
?>
----
Server IP: 69.147.83.197
Probable Submitter: 95.36.102.147
----
Manual Page -- http://www.php.net/manual/en/function.flock.php
Edit -- https://master.php.net/note/edit/99931
Del: integrated -- https://master.php.net/note/delete/99931/integrated
Del: useless -- https://master.php.net/note/delete/99931/useless
Del: bad code -- https://master.php.net/note/delete/99931/bad+code
Del: spam -- https://master.php.net/note/delete/99931/spam
Del: non-english -- https://master.php.net/note/delete/99931/non-english
Del: in docs -- https://master.php.net/note/delete/99931/in+docs
Del: other reasons-- https://master.php.net/note/delete/99931
Reject -- https://master.php.net/note/reject/99931
Search -- https://master.php.net/manage/user-notes.php