2015-04-07 23:38:03 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {
|
|
|
|
|
2015-04-08 01:00:18 +02:00
|
|
|
private $cacheSummary;
|
|
|
|
|
|
|
|
public function setCacheSummary(array $cache_summary) {
|
|
|
|
$this->cacheSummary = $cache_summary;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCacheSummary() {
|
|
|
|
return $this->cacheSummary;
|
|
|
|
}
|
|
|
|
|
2015-04-07 23:38:03 +02:00
|
|
|
public static function getActiveCacheSpec() {
|
|
|
|
$spec = new PhabricatorDataCacheSpec();
|
2015-04-08 20:31:01 +02:00
|
|
|
|
2015-04-07 23:38:03 +02:00
|
|
|
// NOTE: If APCu is installed, it reports that APC is installed.
|
|
|
|
if (extension_loaded('apc') && !extension_loaded('apcu')) {
|
2015-04-08 20:31:01 +02:00
|
|
|
$spec->initAPCSpec();
|
2015-04-07 23:38:03 +02:00
|
|
|
} else if (extension_loaded('apcu')) {
|
2015-04-08 20:31:01 +02:00
|
|
|
$spec->initAPCuSpec();
|
2015-04-07 23:38:03 +02:00
|
|
|
} else {
|
2015-04-08 20:31:01 +02:00
|
|
|
$spec->initNoneSpec();
|
2015-04-07 23:38:03 +02:00
|
|
|
}
|
2015-04-08 20:31:01 +02:00
|
|
|
|
|
|
|
return $spec;
|
2015-04-07 23:38:03 +02:00
|
|
|
}
|
|
|
|
|
2015-04-08 20:31:01 +02:00
|
|
|
private function initAPCSpec() {
|
|
|
|
$this
|
2015-04-07 23:38:03 +02:00
|
|
|
->setName(pht('APC User Cache'))
|
|
|
|
->setVersion(phpversion('apc'));
|
|
|
|
|
|
|
|
if (ini_get('apc.enabled')) {
|
2015-09-10 23:18:52 +02:00
|
|
|
$this
|
|
|
|
->setIsEnabled(true)
|
|
|
|
->setClearCacheCallback('apc_clear_cache');
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->initAPCCommonSpec();
|
2015-04-07 23:38:03 +02:00
|
|
|
} else {
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->setIsEnabled(false);
|
|
|
|
$this->raiseEnableAPCIssue();
|
2015-04-07 23:38:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:31:01 +02:00
|
|
|
private function initAPCuSpec() {
|
|
|
|
$this
|
2015-04-07 23:38:03 +02:00
|
|
|
->setName(pht('APCu'))
|
|
|
|
->setVersion(phpversion('apcu'));
|
|
|
|
|
|
|
|
if (ini_get('apc.enabled')) {
|
2015-09-10 23:18:52 +02:00
|
|
|
$this
|
|
|
|
->setIsEnabled(true)
|
|
|
|
->setClearCacheCallback('apc_clear_cache');
|
2015-04-08 20:32:30 +02:00
|
|
|
$this->initAPCCommonSpec();
|
2015-04-07 23:38:03 +02:00
|
|
|
} else {
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->setIsEnabled(false);
|
|
|
|
$this->raiseEnableAPCIssue();
|
2015-04-07 23:38:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-09 03:01:58 +02:00
|
|
|
private function initNoneSpec() {
|
2015-04-07 23:38:03 +02:00
|
|
|
if (version_compare(phpversion(), '5.5', '>=')) {
|
2015-04-08 20:31:01 +02:00
|
|
|
$message = pht(
|
Make disk-based setup caches more correct (but slower)
Summary:
Fixes T9599. When APC/APCu are not available, we fall back to a disk-based cache.
We try to share this cache across webserver processes like APC/APCu would be shared in order to improve performance, but are just kind of guessing how to coordinate it. From T9599, it sounds like we don't always get this right in every configuration.
Since this is complicated and error prone, just stop trying to do this. This cache has bad performance anyway (no production install should be using it), and we have much better APC/APCu setup instructions now than we did when I wrote this. Just using the PID is simpler and more correct.
Test Plan:
- Artificially disabled APC.
- Reloaded the page, saw all the setup stuff run.
- Reloaded the page, saw no setup stuff run (i.e., cache was hit).
- Restarted the webserver.
- Reloaded the page, saw all the setup stuff run.
- Reloaded again, got a cache hit.
I don't really know how to reproduce the exact problem with the parent PID not working, but from T9599 it sounds like this fixed the issue and from my test plan we still appear to get correct behavior in the standard/common case.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T9599
Differential Revision: https://secure.phabricator.com/D14302
2015-10-19 20:14:46 +02:00
|
|
|
'Installing the "APCu" PHP extension will improve performance. '.
|
|
|
|
'This extension is strongly recommended. Without it, Phabricator '.
|
|
|
|
'must rely on a very inefficient disk-based cache.');
|
2015-04-08 20:31:01 +02:00
|
|
|
|
|
|
|
$this
|
|
|
|
->newIssue('extension.apcu')
|
|
|
|
->setShortName(pht('APCu'))
|
|
|
|
->setName(pht('PHP Extension "APCu" Not Installed'))
|
|
|
|
->setMessage($message)
|
|
|
|
->addPHPExtension('apcu');
|
2015-04-07 23:38:03 +02:00
|
|
|
} else {
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->raiseInstallAPCIssue();
|
2015-04-07 23:38:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:32:30 +02:00
|
|
|
private function initAPCCommonSpec() {
|
2015-04-08 00:08:47 +02:00
|
|
|
$mem = apc_sma_info();
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
|
2015-04-08 00:08:47 +02:00
|
|
|
|
|
|
|
$info = apc_cache_info('user');
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->setUsedMemory($info['mem_size']);
|
|
|
|
$this->setEntryCount(count($info['cache_list']));
|
2015-04-08 01:00:18 +02:00
|
|
|
|
|
|
|
$cache = $info['cache_list'];
|
|
|
|
$state = array();
|
|
|
|
foreach ($cache as $item) {
|
2015-04-13 20:11:18 +02:00
|
|
|
$info = idx($item, 'info', '<unknown-key>');
|
|
|
|
$key = self::getKeyPattern($info);
|
2015-04-08 01:00:18 +02:00
|
|
|
if (empty($state[$key])) {
|
|
|
|
$state[$key] = array(
|
|
|
|
'max' => 0,
|
|
|
|
'total' => 0,
|
|
|
|
'count' => 0,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
$state[$key]['max'] = max($state[$key]['max'], $item['mem_size']);
|
|
|
|
$state[$key]['total'] += $item['mem_size'];
|
|
|
|
$state[$key]['count']++;
|
|
|
|
}
|
|
|
|
|
2015-04-08 20:31:01 +02:00
|
|
|
$this->setCacheSummary($state);
|
2015-04-08 01:00:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private static function getKeyPattern($key) {
|
|
|
|
// If this key isn't in the current cache namespace, don't reveal any
|
|
|
|
// information about it.
|
|
|
|
$namespace = PhabricatorEnv::getEnvConfig('phabricator.cache-namespace');
|
|
|
|
if (strncmp($key, $namespace.':', strlen($namespace) + 1)) {
|
|
|
|
return '<other-namespace>';
|
|
|
|
}
|
|
|
|
|
|
|
|
$key = preg_replace('/(?<![a-zA-Z])\d+(?![a-zA-Z])/', 'N', $key);
|
|
|
|
$key = preg_replace('/PHID-[A-Z]{4}-[a-z0-9]{20}/', 'PHID', $key);
|
|
|
|
|
|
|
|
// TODO: We should probably standardize how digests get embedded into cache
|
|
|
|
// keys to make this rule more generic.
|
|
|
|
$key = preg_replace('/:celerity:.*$/', ':celerity:X', $key);
|
|
|
|
$key = preg_replace('/:pkcs8:.*$/', ':pkcs8:X', $key);
|
|
|
|
|
|
|
|
return $key;
|
2015-04-08 00:08:47 +02:00
|
|
|
}
|
2015-04-07 23:38:03 +02:00
|
|
|
}
|