1

I made a simple database driven php website. Now i am trying to implement some simple caching to the site. i tried this from somewhere

<?php
      $reqfilename="test";
      $cachetime = 60*5; // 5 minutes
      $cachefile = "cache/".$reqfilename.".html";
      $cf2="cache/".$reqfilename."2.html";
      if (file_exists($cachefile) && ((time() - $cachetime) < filemtime($cachefile))) 
      { 
         include($cachefile);
         exit;
      }
      ob_start(); 
?>
CONTENT OF THE PAGE GOES HERE
<?php   
        $fp = @fopen($cf2, 'w'); 
        if($fp){
            fwrite($fp, ob_get_contents());
            fclose($fp); 
            rename($cf2,$cachefile);
        }   
        ob_end_flush(); 
?>

But what if the cache file is being renamed and someone requests the page. Will there be an error displayed or just the user will experience a delay?

To reduce the time of the cache file being modified only, I am using rename instead of directly writing on the original cache file

Correct code to do this (based on answer by webbiedave below)

<?php
      $reqfilename="test";
      $cachetime = 60*5; // 5 minutes
      $cachefile = "cache/".$reqfilename.".html";

      if (file_exists($cachefile) && ((time() - $cachetime) < filemtime($cachefile))) 
      { 
         include($cachefile);
         exit;
      }
      ob_start(); 
?>
CONTENT OF THE PAGE GOES HERE
<?php   
        $fp = @fopen($cachefile, 'w'); 
    if (flock($fp, LOCK_EX | LOCK_NB)) {
    fwrite($fp, ob_get_contents());
    flock($fp, LOCK_UN);
    fclose($fp); 
    }

    ob_end_flush(); ?>

2 Answers 2

1

Renaming the file isn't the source of your problem. The main race condition with your script is multiple requests detecting an expired mtime and all writing to test2.html.

A better approach is to perform an exclusive, non-blocking flock (assuming non-windows) immediately after detecting an expired mtime, buffer the output, overwrite the file and release the lock. If flock returns false, then another process is writing to it and the current process should skip the write entirely.

If a request is made during the lock, the web server will wait until the file write is complete (and the lock released), then serve the file.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks.. thats exactly what I was looking for.. earlier didn't thought of LOCK_NB. Thanks again.
0

I don't think your source will work properly because you don't delete the cache-file

1 Comment

Why should i delete the cache file. The file is being renamed as the file which will be used to display the page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.