@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
at upstream/main 130 lines 3.5 kB view raw
1<?php 2 3final class PhabricatorDataCacheSpec extends PhabricatorCacheSpec { 4 5 private $cacheSummary; 6 7 public function setCacheSummary(array $cache_summary) { 8 $this->cacheSummary = $cache_summary; 9 return $this; 10 } 11 12 public function getCacheSummary() { 13 return $this->cacheSummary; 14 } 15 16 public static function getActiveCacheSpec() { 17 $spec = new PhabricatorDataCacheSpec(); 18 19 if (extension_loaded('apcu')) { 20 $spec->initAPCuSpec(); 21 } else { 22 $spec->initNoneSpec(); 23 } 24 25 return $spec; 26 } 27 28 private function initAPCuSpec() { 29 $this 30 ->setName(pht('APCu')) 31 ->setVersion(phpversion('apcu')); 32 33 if (ini_get('apc.enabled')) { 34 if (function_exists('apcu_clear_cache')) { 35 $clear_callback = 'apcu_clear_cache'; 36 } 37 38 $this 39 ->setIsEnabled(true) 40 ->setClearCacheCallback($clear_callback); 41 $this->initAPCCommonSpec(); 42 } else { 43 $this->setIsEnabled(false); 44 $this->raiseEnableAPCIssue(); 45 } 46 } 47 48 private function initNoneSpec() { 49 $message = pht( 50 'Installing the "APCu" PHP extension will improve performance. '. 51 'This extension is strongly recommended. Without it, this software '. 52 'must rely on a very inefficient disk-based cache.'); 53 54 $this 55 ->newIssue('extension.apcu') 56 ->setShortName(pht('APCu')) 57 ->setName(pht('PHP Extension "APCu" Not Installed')) 58 ->setMessage($message) 59 ->addPHPExtension('apcu'); 60 } 61 62 private function initAPCCommonSpec() { 63 $state = array(); 64 65 if (function_exists('apcu_sma_info')) { 66 $mem = apcu_sma_info(); 67 $info = apcu_cache_info(); 68 } else { 69 $mem = null; 70 } 71 72 if ($mem) { 73 $this->setTotalMemory($mem['num_seg'] * $mem['seg_size']); 74 75 $this->setUsedMemory($info['mem_size']); 76 $this->setEntryCount(count($info['cache_list'])); 77 78 $cache = $info['cache_list']; 79 $state = array(); 80 foreach ($cache as $item) { 81 // Some older versions of APCu report the cachekey as "key", while 82 // newer APCu report it as "info". Just check both indexes for 83 // compatibility. See T13164 for details. 84 85 $info = idx($item, 'info'); 86 if ($info === null) { 87 $info = idx($item, 'key'); 88 } 89 90 if ($info === null) { 91 $key = '<unknown-key>'; 92 } else { 93 $key = self::getKeyPattern($info); 94 } 95 96 if (empty($state[$key])) { 97 $state[$key] = array( 98 'max' => 0, 99 'total' => 0, 100 'count' => 0, 101 ); 102 } 103 $state[$key]['max'] = max($state[$key]['max'], $item['mem_size']); 104 $state[$key]['total'] += $item['mem_size']; 105 $state[$key]['count']++; 106 } 107 } 108 109 $this->setCacheSummary($state); 110 } 111 112 private static function getKeyPattern($key) { 113 // If this key isn't in the current cache namespace, don't reveal any 114 // information about it. 115 $namespace = PhabricatorEnv::getEnvConfig('phabricator.cache-namespace'); 116 if (strncmp($key, $namespace.':', strlen($namespace) + 1)) { 117 return '<other-namespace>'; 118 } 119 120 $key = preg_replace('/(?<![a-zA-Z])\d+(?![a-zA-Z])/', 'N', $key); 121 $key = preg_replace('/PHID-[A-Z]{4}-[a-z0-9]{20}/', 'PHID', $key); 122 123 // TODO: We should probably standardize how digests get embedded into cache 124 // keys to make this rule more generic. 125 $key = preg_replace('/:celerity:.*$/', ':celerity:X', $key); 126 $key = preg_replace('/:pkcs8:.*$/', ':pkcs8:X', $key); 127 128 return $key; 129 } 130}