Skip to content

atomic_file_put_contents for concurrent cache access#4

Open
peterpostmann wants to merge 1 commit intoinouet:masterfrom
peterpostmann:atomic_file_put_contents
Open

atomic_file_put_contents for concurrent cache access#4
peterpostmann wants to merge 1 commit intoinouet:masterfrom
peterpostmann:atomic_file_put_contents

Conversation

@peterpostmann
Copy link
Copy Markdown

If multiple instances try to write a new cache file simultaneously the file will be inconsistent, because file_put_contents "is identical to calling fopen(), fwrite() and fclose() successively to write data to a file" [1]. This could be solved by using a lock as suggested in [2], but there is also another problem: If the file is read wile being written, only a partial file be read [3].

To solve both issues, the file is not written directly, but to a temporary file first and then moved.
$tmpName = $filename.'-'.static::guid();
file_put_contents($tmpName, $data));
rename($tmpName, $filename);
Rename is atomically overwrites the existing file, hence a read will return either the old or the new file, but no partial file. The file may be overwritten multiple times (by concurrent instances of the script, if the cache is expired), but the data will be the same, so this is not an issue.

For the temporary file a GUID is appended (to avoid writes to the same file). The cleanest solution would be to use $_SERVER['UNIQUE_ID'] but this depends on the Apache Module mod_unique_id, which is not a portable solution [4]

[1] http://php.net/manual/en/function.file-put-contents.php
[2] https://stackoverflow.com/questions/5479580/is-there-a-risk-in-running-file-put-contents-on-the-same-file-from-different-p
[3] https://stackoverflow.com/questions/4899737/should-lock-ex-on-both-read-write-be-atomic/4899822#4899822
[4] https://stackoverflow.com/questions/25196343/what-is-the-value-in-serverunique-id-used-for

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant