3 final class PhabricatorDataCacheSpec
extends PhabricatorCacheSpec
{
7 public function setCacheSummary(array $cache_summary) {
8 $this->cacheSummary
= $cache_summary;
12 public function getCacheSummary() {
13 return $this->cacheSummary
;
16 public static function getActiveCacheSpec() {
17 $spec = new PhabricatorDataCacheSpec();
19 // NOTE: If APCu is installed, it reports that APC is installed.
20 if (extension_loaded('apc') && !extension_loaded('apcu')) {
22 } else if (extension_loaded('apcu')) {
23 $spec->initAPCuSpec();
25 $spec->initNoneSpec();
31 private function initAPCSpec() {
33 ->setName(pht('APC User Cache'))
34 ->setVersion(phpversion('apc'));
36 if (ini_get('apc.enabled')) {
39 ->setClearCacheCallback('apc_clear_cache');
40 $this->initAPCCommonSpec();
42 $this->setIsEnabled(false);
43 $this->raiseEnableAPCIssue();
47 private function initAPCuSpec() {
49 ->setName(pht('APCu'))
50 ->setVersion(phpversion('apcu'));
52 if (ini_get('apc.enabled')) {
53 if (function_exists('apcu_clear_cache')) {
54 $clear_callback = 'apcu_clear_cache';
56 $clear_callback = 'apc_clear_cache';
61 ->setClearCacheCallback($clear_callback);
62 $this->initAPCCommonSpec();
64 $this->setIsEnabled(false);
65 $this->raiseEnableAPCIssue();
69 private function initNoneSpec() {
70 if (version_compare(phpversion(), '5.5', '>=')) {
72 'Installing the "APCu" PHP extension will improve performance. '.
73 'This extension is strongly recommended. Without it, this software '.
74 'must rely on a very inefficient disk-based cache.');
77 ->newIssue('extension.apcu')
78 ->setShortName(pht('APCu'))
79 ->setName(pht('PHP Extension "APCu" Not Installed'))
80 ->setMessage($message)
81 ->addPHPExtension('apcu');
83 $this->raiseInstallAPCIssue();
87 private function initAPCCommonSpec() {
90 if (function_exists('apcu_sma_info')) {
91 $mem = apcu_sma_info();
92 $info = apcu_cache_info();
93 } else if (function_exists('apc_sma_info')) {
94 $mem = apc_sma_info();
95 $info = apc_cache_info('user');
101 $this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);
103 $this->setUsedMemory($info['mem_size']);
104 $this->setEntryCount(count($info['cache_list']));
106 $cache = $info['cache_list'];
108 foreach ($cache as $item) {
109 // Some older versions of APCu report the cachekey as "key", while
110 // newer APCu and APC report it as "info". Just check both indexes
111 // for commpatibility. See T13164 for details.
113 $info = idx($item, 'info');
114 if ($info === null) {
115 $info = idx($item, 'key');
118 if ($info === null) {
119 $key = '<unknown-key>';
121 $key = self
::getKeyPattern($info);
124 if (empty($state[$key])) {
125 $state[$key] = array(
131 $state[$key]['max'] = max($state[$key]['max'], $item['mem_size']);
132 $state[$key]['total'] +
= $item['mem_size'];
133 $state[$key]['count']++
;
137 $this->setCacheSummary($state);
140 private static function getKeyPattern($key) {
141 // If this key isn't in the current cache namespace, don't reveal any
142 // information about it.
143 $namespace = PhabricatorEnv
::getEnvConfig('phabricator.cache-namespace');
144 if (strncmp($key, $namespace.':', strlen($namespace) +
1)) {
145 return '<other-namespace>';
148 $key = preg_replace('/(?<![a-zA-Z])\d+(?![a-zA-Z])/', 'N', $key);
149 $key = preg_replace('/PHID-[A-Z]{4}-[a-z0-9]{20}/', 'PHID', $key);
151 // TODO: We should probably standardize how digests get embedded into cache
152 // keys to make this rule more generic.
153 $key = preg_replace('/:celerity:.*$/', ':celerity:X', $key);
154 $key = preg_replace('/:pkcs8:.*$/', ':pkcs8:X', $key);