Post by Lucanos » Mon Mar 14, 2011 1:59 pm

Hi Guys,

I (like a number of members from a quick search of the Forums and Google) have been having intermittent issues whereby I would get a number of PHP errors dumped at the top of most pages stating something like (borrowing error content from http://forum.opencart.com/viewtopic.php ... he#p131780):

Code: Select all

PHP Warning: unlink(/home/julugu/public_html/system/cache/cache.category.38.2.0.1295512099) [<a href='function.unlink'>function.unlink</a>]: No such file or directory in /home/julugu/public_html/system/library/cache.php on line 14
My take on the message is that the /system/library/cache.php script is trying to delete an already deleted cache file. Looking at the code within the script:

Code: Select all

  	public function __construct() {
      $files = glob(DIR_CACHE . 'cache.*');
		
      if ($files) {
        foreach ($files as $file) {
          $time = substr(strrchr($file, '.'), 1);

          if ($time < time()) {
            if (file_exists($file)) {
              @unlink($file);
            }
          }
    		}
      }
    }
It is already checking whether the file exists prior to performing the unlink(), so this is very strange.

As much as this is a sub-optimal solution, I have modified this function of the cache.php file, in my own install, as follows:

Code: Select all

  public function __construct() {
		$files = glob(DIR_CACHE . 'cache.*');
		if ($files) {
			foreach ($files as $file) {
				$time = substr(strrchr($file, '.'), 1);
        if ($time < time() && file_exists($file)) {
          @touch($file);
          @unlink($file);
        }
      }
    }
  }
What it now does is, again, checks whether the file exists, but then, before it executes the unlink() function, it uses the touch() function. This means that, if the file exists, it's access and modification times are modified, and if the file does not exist (which has been tripping the unlink() function up lately), it creates it, so it is there to be deleted.

I also found that the get() function pulls an array of all cache files matching the specified key, but, in the case where two cache files, with the same key, but different expiry stamps were found, it would return the oldest of the two (rather than the youngest). To resolve this I added a call to array_reverse() to flip the sorted order of the returned files and resolve this, although a more permanent solution (where the older matching file(s) were deleted) might be in order.

And further, I added functionality to use file_get_contents() and file_put_contents() (where available) for the inserting and retrieval of data into and from the cache files.

I have attached the modified cache.php file (renamed cache.txt) for reference, should anyone want to do so.

Attachments

Modified cache.php file from /system/library/


Newbie

Posts

Joined
Mon Mar 14, 2011 1:39 pm

Post by Qphoria » Mon Mar 14, 2011 10:29 pm

I've already made a few different changes for the get. Actually, the foreach seems moot in the get function because the construct should be deleting old files anyway and I have never seen 2 files for the same list ever. So the assumption I made is that the glob in get will always return a max of 1 file in the array.

I will try the touch() tho. THanks!

Image


User avatar
Administrator

Posts

Joined
Tue Jul 22, 2008 3:02 am
Who is online

Users browsing this forum: No registered users and 4 guests