1
0
Fork 0

add size-based limit for files cache, fixes #1321

pull/1422/head
Galymzhan 2012-12-17 01:19:16 +06:00
parent 69f2230a4c
commit 219b489d01
4 changed files with 133 additions and 3 deletions

View File

@ -114,16 +114,27 @@ class Cache
return false;
}
public function gc($ttl)
public function gc($ttl, $cacheMaxSize)
{
$expire = new \DateTime();
$expire->modify('-'.$ttl.' seconds');
$finder = Finder::create()->files()->in($this->root)->date('until '.$expire->format('Y-m-d H:i:s'));
$finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
foreach ($finder as $file) {
unlink($file->getRealPath());
}
$totalCacheSize = $this->filesystem->size($this->root);
if ($totalCacheSize > $cacheMaxSize) {
$iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
while ($totalCacheSize > $cacheMaxSize && $iterator->valid()) {
$filepath = $iterator->current()->getRealPath();
$totalCacheSize -= $this->filesystem->size($filepath);
unlink($filepath);
$iterator->next();
}
}
return true;
}
@ -146,4 +157,9 @@ class Cache
return false;
}
protected function getFinder()
{
return Finder::create()->in($this->root)->files();
}
}

View File

@ -22,6 +22,7 @@ class Config
public static $defaultConfig = array(
'process-timeout' => 300,
'cache-ttl' => 15552000, // 6 months
'cache-files-maxsize' => '300MiB',
'vendor-dir' => 'vendor',
'bin-dir' => '{$vendor-dir}/bin',
'notify-on-install' => true,
@ -137,6 +138,25 @@ class Config
case 'cache-ttl':
return (int) $this->config[$key];
case 'cache-files-maxsize':
if (!preg_match('/^\s*(\d+)\s*([kmg]ib)?\s*$/i', $this->config[$key], $matches)) {
throw new \RuntimeException(
"composer.json contains invalid 'cache-files-maxsize' value: {$this->config[$key]}"
);
}
$size = $matches[1];
if (isset($matches[2])) {
switch (strtolower($matches[2])) {
case 'gib':
$size *= 1024;
case 'mib':
$size *= 1024;
case 'kib':
$size *= 1024;
}
}
return $size;
case 'cache-files-ttl':
if (isset($this->config[$key])) {
return (int) $this->config[$key];

View File

@ -56,7 +56,7 @@ class FileDownloader implements DownloaderInterface
$this->cache = $cache;
if ($this->cache && !self::$cacheCollected && !rand(0, 50)) {
$this->cache->gc($config->get('cache-ttl'));
$this->cache->gc($config->get('cache-ttl'), $config->get('cache-files-maxsize'));
}
self::$cacheCollected = true;
}

View File

@ -0,0 +1,94 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Test;
use Composer\Cache;
class CacheTest extends TestCase
{
private $files, $root, $finder, $cache;
public function setUp()
{
$this->root = sys_get_temp_dir() . '/composer_testdir';
$this->ensureDirectoryExistsAndClear($this->root);
$this->files = array();
$zeros = str_repeat('0', 1000);
for ($i = 0; $i < 4; $i++) {
file_put_contents("{$this->root}/cached.file{$i}.zip", $zeros);
$this->files[] = new \SplFileInfo("{$this->root}/cached.file{$i}.zip");
}
$this->finder = $this->getMock('Symfony\Component\Finder\Finder');
$io = $this->getMock('Composer\IO\IOInterface');
$this->cache = $this->getMock(
'Composer\Cache',
array('getFinder'),
array($io, $this->root)
);
$this->cache
->expects($this->any())
->method('getFinder')
->will($this->returnValue($this->finder));
}
public function testRemoveOutdatedFiles()
{
$outdated = array_slice($this->files, 1);
$this->finder
->expects($this->once())
->method('getIterator')
->will($this->returnValue(new \ArrayIterator($outdated)));
$this->finder
->expects($this->once())
->method('date')
->will($this->returnValue($this->finder));
$this->cache->gc(600, 1024 * 1024 * 1024);
for ($i = 1; $i < 4; $i++) {
$this->assertFileNotExists("{$this->root}/cached.file{$i}.zip");
}
$this->assertFileExists("{$this->root}/cached.file0.zip");
}
public function testRemoveFilesWhenCacheIsTooLarge()
{
$emptyFinder = $this->getMock('Symfony\Component\Finder\Finder');
$emptyFinder
->expects($this->once())
->method('getIterator')
->will($this->returnValue(new \EmptyIterator()));
$this->finder
->expects($this->once())
->method('date')
->will($this->returnValue($emptyFinder));
$this->finder
->expects($this->once())
->method('getIterator')
->will($this->returnValue(new \ArrayIterator($this->files)));
$this->finder
->expects($this->once())
->method('sortByAccessedTime')
->will($this->returnValue($this->finder));
$this->cache->gc(600, 1500);
for ($i = 0; $i < 3; $i++) {
$this->assertFileNotExists("{$this->root}/cached.file{$i}.zip");
}
$this->assertFileExists("{$this->root}/cached.file3.zip");
}
}