Skip to content

Commit 7cd6e18

Browse files
[Cache] Optimize & wire PhpFilesAdapter
1 parent 14bcd79 commit 7cd6e18

10 files changed

+215
-609
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ before_install:
4747
- if [[ $PHP != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
4848
- if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi
4949
- if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi
50+
- if [[ ! $skip ]]; then echo opcache.enable_cli = 1 >> $INI_FILE; fi
5051
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi
5152
- if [[ ! $skip && $PHP = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi
5253
- if [[ ! $skip && $PHP = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.10 && echo apc.enable_cli = 1 >> $INI_FILE); fi

appveyor.yml

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ install:
3535
- IF %PHP%==1 echo date.timezone="UTC" >> php.ini-min
3636
- IF %PHP%==1 echo extension_dir=ext >> php.ini-min
3737
- IF %PHP%==1 copy /Y php.ini-min php.ini-max
38+
- IF %PHP%==1 echo zend_extension=php_opcache.dll >> php.ini-max
39+
- IF %PHP%==1 echo opcache.enable_cli=1 >> php.ini-max
3840
- IF %PHP%==1 echo extension=php_openssl.dll >> php.ini-max
3941
- IF %PHP%==1 echo extension=php_apcu.dll >> php.ini-max
4042
- IF %PHP%==1 echo apc.enable_cli=1 >> php.ini-max

src/Symfony/Component/Cache/Adapter/AbstractAdapter.php

+9
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ function ($deferred, $namespace, &$expiredIds) {
7070

7171
public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
7272
{
73+
if (!ApcuAdapter::isSupported() && PhpFilesAdapter::isSupported()) {
74+
$opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory);
75+
if (null !== $logger) {
76+
$opcache->setLogger($logger);
77+
}
78+
79+
return $opcache;
80+
}
81+
7382
$fs = new FilesystemAdapter($namespace, $defaultLifetime, $directory);
7483
if (null !== $logger) {
7584
$fs->setLogger($logger);

src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php

+6-59
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,17 @@
1111

1212
namespace Symfony\Component\Cache\Adapter;
1313

14-
use Symfony\Component\Cache\Adapter\Helper\FilesCacheHelper;
15-
1614
/**
1715
* @author Nicolas Grekas <p@tchwork.com>
1816
*/
1917
class FilesystemAdapter extends AbstractAdapter
2018
{
21-
/**
22-
* @var FilesCacheHelper
23-
*/
24-
protected $filesCacheHelper;
19+
use FilesystemAdapterTrait;
2520

26-
/**
27-
* @param string $namespace Cache namespace
28-
* @param int $defaultLifetime Default lifetime for cache items
29-
* @param null $directory Path where cache items should be stored, defaults to sys_get_temp_dir().'/symfony-cache'
30-
*/
3121
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
3222
{
33-
parent::__construct($namespace, $defaultLifetime);
34-
$this->filesCacheHelper = new FilesCacheHelper($directory, $namespace);
23+
parent::__construct('', $defaultLifetime);
24+
$this->init($namespace, $directory);
3525
}
3626

3727
/**
@@ -43,7 +33,7 @@ protected function doFetch(array $ids)
4333
$now = time();
4434

4535
foreach ($ids as $id) {
46-
$file = $this->filesCacheHelper->getFilePath($id);
36+
$file = $this->getFile($id);
4737
if (!$h = @fopen($file, 'rb')) {
4838
continue;
4939
}
@@ -70,41 +60,11 @@ protected function doFetch(array $ids)
7060
*/
7161
protected function doHave($id)
7262
{
73-
$file = $this->filesCacheHelper->getFilePath($id);
63+
$file = $this->getFile($id);
7464

7565
return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id)));
7666
}
7767

78-
/**
79-
* {@inheritdoc}
80-
*/
81-
protected function doClear($namespace)
82-
{
83-
$ok = true;
84-
$directory = $this->filesCacheHelper->getDirectory();
85-
86-
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
87-
$ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
88-
}
89-
90-
return $ok;
91-
}
92-
93-
/**
94-
* {@inheritdoc}
95-
*/
96-
protected function doDelete(array $ids)
97-
{
98-
$ok = true;
99-
100-
foreach ($ids as $id) {
101-
$file = $this->filesCacheHelper->getFilePath($id);
102-
$ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
103-
}
104-
105-
return $ok;
106-
}
107-
10868
/**
10969
* {@inheritdoc}
11070
*/
@@ -114,22 +74,9 @@ protected function doSave(array $values, $lifetime)
11474
$expiresAt = $lifetime ? time() + $lifetime : PHP_INT_MAX;
11575

11676
foreach ($values as $id => $value) {
117-
$fileContent = $this->createCacheFileContent($id, $value, $expiresAt);
118-
$ok = $this->filesCacheHelper->saveFileForId($id, $fileContent, $expiresAt) && $ok;
77+
$ok = $this->write($this->getFile($id, true), $expiresAt."\n".rawurlencode($id)."\n".serialize($value), $expiresAt) && $ok;
11978
}
12079

12180
return $ok;
12281
}
123-
124-
/**
125-
* @param string $id
126-
* @param mixed $value
127-
* @param int $expiresAt
128-
*
129-
* @return string
130-
*/
131-
protected function createCacheFileContent($id, $value, $expiresAt)
132-
{
133-
return $expiresAt."\n".rawurlencode($id)."\n".serialize($value);
134-
}
13582
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Cache\Adapter;
13+
14+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
15+
16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
trait FilesystemAdapterTrait
20+
{
21+
private $directory;
22+
private $tmp;
23+
24+
private function init($namespace, $directory)
25+
{
26+
if (!isset($directory[0])) {
27+
$directory = sys_get_temp_dir().'/symfony-cache';
28+
}
29+
if (isset($namespace[0])) {
30+
if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) {
31+
throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0]));
32+
}
33+
$directory .= '/'.$namespace;
34+
}
35+
if (!file_exists($dir = $directory.'/.')) {
36+
@mkdir($directory, 0777, true);
37+
}
38+
if (false === $dir = realpath($dir)) {
39+
throw new InvalidArgumentException(sprintf('Cache directory does not exist (%s)', $directory));
40+
}
41+
if (!is_writable($dir .= DIRECTORY_SEPARATOR)) {
42+
throw new InvalidArgumentException(sprintf('Cache directory is not writable (%s)', $directory));
43+
}
44+
// On Windows the whole path is limited to 258 chars
45+
if ('\\' === DIRECTORY_SEPARATOR && strlen($dir) > 234) {
46+
throw new InvalidArgumentException(sprintf('Cache directory too long (%s)', $directory));
47+
}
48+
49+
$this->directory = $dir;
50+
$this->tmp = $this->directory.uniqid('', true);
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
protected function doClear($namespace)
57+
{
58+
$ok = true;
59+
60+
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
61+
$ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
62+
}
63+
64+
return $ok;
65+
}
66+
67+
/**
68+
* {@inheritdoc}
69+
*/
70+
protected function doDelete(array $ids)
71+
{
72+
$ok = true;
73+
74+
foreach ($ids as $id) {
75+
$file = $this->getFile($id);
76+
$ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
77+
}
78+
79+
return $ok;
80+
}
81+
82+
private function write($file, $data, $expiresAt = null)
83+
{
84+
if (false === @file_put_contents($this->tmp, $data)) {
85+
return false;
86+
}
87+
if (null !== $expiresAt) {
88+
@touch($this->tmp, $expiresAt);
89+
}
90+
91+
if (@rename($this->tmp, $file)) {
92+
return true;
93+
}
94+
@unlink($this->tmp);
95+
96+
return false;
97+
}
98+
99+
private function getFile($id, $mkdir = false)
100+
{
101+
$hash = str_replace('/', '-', base64_encode(md5(static::class.$id, true)));
102+
$dir = $this->directory.$hash[0].DIRECTORY_SEPARATOR.$hash[1].DIRECTORY_SEPARATOR;
103+
104+
if ($mkdir && !file_exists($dir)) {
105+
@mkdir($dir, 0777, true);
106+
}
107+
108+
return $dir.substr($hash, 2, -2);
109+
}
110+
}

src/Symfony/Component/Cache/Adapter/Helper/FilesCacheHelper.php

-137
This file was deleted.

0 commit comments

Comments
 (0)