Path: blob/master/src/applications/cache/spec/PhabricatorDataCacheSpec.php
12242 views
<?php12final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec {34private $cacheSummary;56public function setCacheSummary(array $cache_summary) {7$this->cacheSummary = $cache_summary;8return $this;9}1011public function getCacheSummary() {12return $this->cacheSummary;13}1415public static function getActiveCacheSpec() {16$spec = new PhabricatorDataCacheSpec();1718// NOTE: If APCu is installed, it reports that APC is installed.19if (extension_loaded('apc') && !extension_loaded('apcu')) {20$spec->initAPCSpec();21} else if (extension_loaded('apcu')) {22$spec->initAPCuSpec();23} else {24$spec->initNoneSpec();25}2627return $spec;28}2930private function initAPCSpec() {31$this32->setName(pht('APC User Cache'))33->setVersion(phpversion('apc'));3435if (ini_get('apc.enabled')) {36$this37->setIsEnabled(true)38->setClearCacheCallback('apc_clear_cache');39$this->initAPCCommonSpec();40} else {41$this->setIsEnabled(false);42$this->raiseEnableAPCIssue();43}44}4546private function initAPCuSpec() {47$this48->setName(pht('APCu'))49->setVersion(phpversion('apcu'));5051if (ini_get('apc.enabled')) {52if (function_exists('apcu_clear_cache')) {53$clear_callback = 'apcu_clear_cache';54} else {55$clear_callback = 'apc_clear_cache';56}5758$this59->setIsEnabled(true)60->setClearCacheCallback($clear_callback);61$this->initAPCCommonSpec();62} else {63$this->setIsEnabled(false);64$this->raiseEnableAPCIssue();65}66}6768private function initNoneSpec() {69if (version_compare(phpversion(), '5.5', '>=')) {70$message = pht(71'Installing the "APCu" PHP extension will improve performance. '.72'This extension is strongly recommended. Without it, this software '.73'must rely on a very inefficient disk-based cache.');7475$this76->newIssue('extension.apcu')77->setShortName(pht('APCu'))78->setName(pht('PHP Extension "APCu" Not Installed'))79->setMessage($message)80->addPHPExtension('apcu');81} else {82$this->raiseInstallAPCIssue();83}84}8586private function initAPCCommonSpec() {87$state = array();8889if (function_exists('apcu_sma_info')) {90$mem = apcu_sma_info();91$info = apcu_cache_info();92} else if (function_exists('apc_sma_info')) {93$mem = apc_sma_info();94$info = apc_cache_info('user');95} else {96$mem = null;97}9899if ($mem) {100$this->setTotalMemory($mem['num_seg'] * $mem['seg_size']);101102$this->setUsedMemory($info['mem_size']);103$this->setEntryCount(count($info['cache_list']));104105$cache = $info['cache_list'];106$state = array();107foreach ($cache as $item) {108// Some older versions of APCu report the cachekey as "key", while109// newer APCu and APC report it as "info". Just check both indexes110// for commpatibility. See T13164 for details.111112$info = idx($item, 'info');113if ($info === null) {114$info = idx($item, 'key');115}116117if ($info === null) {118$key = '<unknown-key>';119} else {120$key = self::getKeyPattern($info);121}122123if (empty($state[$key])) {124$state[$key] = array(125'max' => 0,126'total' => 0,127'count' => 0,128);129}130$state[$key]['max'] = max($state[$key]['max'], $item['mem_size']);131$state[$key]['total'] += $item['mem_size'];132$state[$key]['count']++;133}134}135136$this->setCacheSummary($state);137}138139private static function getKeyPattern($key) {140// If this key isn't in the current cache namespace, don't reveal any141// information about it.142$namespace = PhabricatorEnv::getEnvConfig('phabricator.cache-namespace');143if (strncmp($key, $namespace.':', strlen($namespace) + 1)) {144return '<other-namespace>';145}146147$key = preg_replace('/(?<![a-zA-Z])\d+(?![a-zA-Z])/', 'N', $key);148$key = preg_replace('/PHID-[A-Z]{4}-[a-z0-9]{20}/', 'PHID', $key);149150// TODO: We should probably standardize how digests get embedded into cache151// keys to make this rule more generic.152$key = preg_replace('/:celerity:.*$/', ':celerity:X', $key);153$key = preg_replace('/:pkcs8:.*$/', ':pkcs8:X', $key);154155return $key;156}157}158159160