We were seeing similar errors. We have an extension installed that was creating tens of thousands of cache files (a hook added in the "getTotalProducts(...)" function). In addition to errors like these, we found the site slowed to a crawl. We have improved the situation greatly, perhaps resolved it altogether, by modifying the "upload/system/library/cache.php" script.
The version of OpenCart we are using is 1.5.1.3.1. I've peeked at the OpenCart 1.5.6 version and, though the code has changed slightly between the two versions, it appears the reworking we did remains applicable and will be beneficial to those having similar problems with degraded performance and cache file unlinking errors.
In a nutshell, the current caching implementation requests a "glob(...)" in the cache directory at instantiation (in version 1.5.1.3.1 but not in version 1.5.6) and also again every time the "get(...)" and "set(...)" (via the delete(...)) functions are called. The "glob(...)" function is expensive, especially with tens of thousands of directory entries, and this was devastating to performance. Furthermore, in version 1.5.1.3.1, a call to "clearstatcache(...)" was being made after each unique cache file unlink. A single clearing of the cache after completion would suffice. For race conditions where a cache file is unlinked by another process, there is currently no "@" prefix to the "unlink(...)" call to hide the error (which really isn't an error because, ultimately, the file is gone as desired).
So ... to improve in these areas ... try replacing the contents of the "upload/system/library/cache.php" script with these contents (and let the forum know if it helps -- maybe the ideas here will find their way into the code base) :
Code: Select all
<?php
final class Cache
{
private $expire = 3600;
private $files = NULL;
public function __construct()
{
$files = @glob(DIR_CACHE . 'cache.*');
if($files === FALSE)
{
$files = array();
}
foreach($files as $cnt => $file)
{
$time = substr(strrchr($file, '.'), 1);
if($time < time())
{
if(@file_exists($file))
{
@unlink($file);
}
unset($files[$cnt]);
}
}
clearstatcache();
$files = array_values($files);
$this->files = $files;
}
public function get($key)
{
$cache = NULL;
$target = DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.';
$length = strlen($target);
foreach($this->files as $file)
{
if(strncmp($file, $target, $length) == 0)
{
$cache = @file_get_contents($file);
if($cache)
{
$cache = unserialize($cache);
}
}
}
return $cache;
}
public function set($key, $value)
{
$file = DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.' . (time() + $this->expire);
$handle = @fopen($file, 'w');
if($handle)
{
@fwrite($handle, serialize($value));
@fclose($handle);
$this->files[] = $file;
}
}
public function delete($key)
{
$target = DIR_CACHE . 'cache.' . preg_replace('/[^A-Z0-9\._-]/i', '', $key) . '.';
$length = strlen($target);
foreach($this->files as $file)
{
if(strncmp($file, $target, $length) == 0)
{
if(@file_exists($file))
{
@unlink($file);
}
}
}
clearstatcache();
}
}
?>
Good luck!