Atomically appending a line to a file and creating it if it doesn't exist
<p>I'm trying to create a function (for purposes of logging)</p>

<pre><code>append($path, $data)
</code></pre>

<p>that</p>

<ol>
<li>creates $file if it doesn't exist and</li>
<li>atomically appends $data to it.</li>
</ol>

<p>It has to</p>

<ul>
<li>support high concurrency,</li>
<li>support long strings and</li>
<li>be as performant as possible.</li>
</ul>

<p>So far the best attempt is:</p>

<pre><code>function append($file, $data)
{
    // Ensure $file exists. Just opening it with 'w' or 'a' might cause
    // 1 process to clobber another's.
    $fp = @fopen($file, 'x');
    if ($fp)
        fclose($fp);

    // Append
    $lock = strlen($data) &gt; 4096; // assume PIPE_BUF is 4096 (Linux)

    $fp = fopen($file, 'a');
    if ($lock &amp;&amp; !flock($fp, LOCK_EX))
        throw new Exception('Cannot lock file: '.$file);
    fwrite($fp, $data);
    if ($lock)
        flock($fp, LOCK_UN);
    fclose($fp);
}
</code></pre>

<p>It works OK, but it seems to be a quite complex. Is there a cleaner (built-in?) way to do it?</p>
