List Info

Thread: note 78372 added to function.flock




note 78372 added to function.flock
user name
2007-10-08 20:55:45
If there is a file that´s excessively being rewritten by
many different users, you´ll note that two
almost-simultaneously accesses on that file could interfere
with each other. For example if there´s a chat history
containing only the last 25 chat lines. Now adding a line
also means deleting the very first one. So while that whole
writing is happening, another user might also add a line,
reading the file, which, at this point, is incomplete,
because it´s just being rewritten. The second user would
then rewrite an incomplete file and add its line to it,
meaning: you just got yourself some data loss!

If flock() was working at all, that might be the key to not
let those interferences happen - but flock() mostly won´t
work as expected (at least that´s my experience on any
linux webserver I´ve tried), and writing own
file-locking-functions comes with a lot of possible issues
that would finally result in corrupted files. Even though
it´s very unlikely, it´s not impossible and has happened
to me already.

So I came up with another solution for the
file-interference-problem:

1. A file that´s to be accessed will first be copied to a
temp-file directory and its last filemtime() is being stored
in a PHP-variable. The temp-file gets a random filename,
ensuring no other process is able to interfere with this
particular temp-file.
2. When the temp-file has been changed/rewritten/whatever,
there´ll be a check whether the filemtime() of the original
file has been changed since we copied it into our
temp-directory.
2.1. If filemtime() is still the same, the temp-file will
just be renamed/moved to the original filename, ensuring the
original file is never in a temporary state - only the
complete previous state or the complete new state.
2.2. But if filemtime() has been changed while our
PHP-process wanted to change its file, the temp-file will
just be deleted and our new PHP-fileclose-function will
return a FALSE, enabling whatever called that function to do
it again (ie. upto 5 times, until it returns TRUE).

These are the functions I´ve written for that purpose:

<?php
$dir_fileopen =
"../AN/INTERNAL/DIRECTORY/fileopen";

function randomid() {
	return time().substr(md5(microtime()), 0, rand(5, 12));
}

function cfopen($filename, $mode, $overwriteanyway = false)
{
	global $dir_fileopen;
	clearstatcache();
	do {
		$id = md5(randomid(rand(), TRUE));
		$tempfilename =
$dir_fileopen."/".$id.md5($filename);
	} while(file_exists($tempfilename));
	if (file_exists($filename)) {
		$newfile = false;
		copy($filename, $tempfilename);
	}else{
		$newfile = true;
	}
	$fp = fopen($tempfilename, $mode);
	return $fp ? array($fp, $filename, $id, filemtime($filename), $newfile, $overwriteanyway) :
false;
}

function cfwrite($fp,$string) { return fwrite($fp[0],
$string); }

function cfclose($fp, $debug = "off") {
	global $dir_fileopen;
	$success = fclose($fp[0]);
	clearstatcache();
	$tempfilename =
$dir_fileopen."/".$fp[2].md5($fp[1]);
	if ((filemtime($fp[1]) == $fp[3]) or ($fp[4]==true and
!file_exists($fp[1])) or $fp[5]==true) {
		rename($tempfilename, $fp[1]);
	}else{
		unlink($tempfilename);
		if ($debug != "off") echo "While writing,
another process accessed $fp[1]. To ensure file-integrity,
your changes were rejected.";
		$success = false;
	}
	return $success;
}
?>

$overwriteanyway, one of the parameters for cfopen(), means:
If cfclose() is used and the original file has changed, this
script won´t care and still overwrite the original file
with the new temp file. Anyway there won´t be any
writing-interference between two PHP processes, assuming
there can be no absolute simultaneousness between two (or
more) processes.
----
Server IP: 69.147.83.197
Probable Submitter: 89.57.236.211
----
Manual Page -- http:
//www.php.net/manual/en/function.flock.php
Edit        -- https://master
.php.net/note/edit/78372
Del: integrated  -- h
ttps://master.php.net/note/delete/78372/integrated
Del: useless     -- http
s://master.php.net/note/delete/78372/useless
Del: bad code    -- htt
ps://master.php.net/note/delete/78372/bad+code
Del: spam        -- https:/
/master.php.net/note/delete/78372/spam
Del: non-english -- 
https://master.php.net/note/delete/78372/non-english
Del: in docs     -- http
s://master.php.net/note/delete/78372/in+docs
Del: other reasons-- https://mast
er.php.net/note/delete/78372
Reject      -- https://mast
er.php.net/note/reject/78372
Search      -- https://
master.php.net/manage/user-notes.php

-- 
PHP Notes Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub
.php


[1]

about | contact  Other archives ( Real Estate discussion Medical topics )