public function __construct($parent) { global $wgMemc; $this->parent = $parent; $this->srvCache = ObjectCache::newAccelerator(array(), 'hash'); $this->mainCache = $wgMemc ?: wfGetMainCache(); }
public function __construct() { // We use a try/catch instead of the $fallback parameter because // we don't want to fail here if $wgObjectCaches is not configured // properly for APC setup try { $this->cache = ObjectCache::newAccelerator(); } catch (MWException $e) { $this->cache = new EmptyBagOStuff(); } }
/** * Returns a given template function if found, otherwise throws an exception. * @param string $templateName The name of the template (without file suffix) * @return callable * @throws RuntimeException */ protected function getTemplate($templateName) { // If a renderer has already been defined for this template, reuse it if (isset($this->renderers[$templateName]) && is_callable($this->renderers[$templateName])) { return $this->renderers[$templateName]; } $filename = $this->getTemplateFilename($templateName); if (!file_exists($filename)) { throw new RuntimeException("Could not locate template: {$filename}"); } // Read the template file $fileContents = file_get_contents($filename); // Generate a quick hash for cache invalidation $fastHash = md5($fileContents); // Fetch a secret key for building a keyed hash of the PHP code $config = ConfigFactory::getDefaultInstance()->makeConfig('main'); $secretKey = $config->get('SecretKey'); if ($secretKey) { // See if the compiled PHP code is stored in cache. $cache = ObjectCache::newAccelerator(CACHE_ANYTHING); $key = $cache->makeKey('template', $templateName, $fastHash); $code = $this->forceRecompile ? null : $cache->get($key); if (!$code) { $code = $this->compileForEval($fileContents, $filename); // Prefix the cached code with a keyed hash (64 hex chars) as an integrity check $cache->set($key, hash_hmac('sha256', $code, $secretKey) . $code); } else { // Verify the integrity of the cached PHP code $keyedHash = substr($code, 0, 64); $code = substr($code, 64); if ($keyedHash !== hash_hmac('sha256', $code, $secretKey)) { // Generate a notice if integrity check fails trigger_error("Template failed integrity check: {$filename}"); } } // If there is no secret key available, don't use cache } else { $code = $this->compileForEval($fileContents, $filename); } $renderer = eval($code); if (!is_callable($renderer)) { throw new RuntimeException("Requested template, {$templateName}, is not callable"); } $this->renderers[$templateName] = $renderer; return $renderer; }
/** * Return IDs that are sequential *only* for this node and bucket * * @see UIDGenerator::newSequentialPerNodeID() * @param string $bucket Arbitrary bucket name (should be ASCII) * @param int $bits Bit size (16 to 48) of resulting numbers before wrap-around * @param int $count Number of IDs to return (1 to 10000) * @param int $flags (supports UIDGenerator::QUICK_VOLATILE) * @return array Ordered list of float integer values * @throws MWException */ protected function getSequentialPerNodeIDs($bucket, $bits, $count, $flags) { if ($count <= 0) { return array(); // nothing to do } elseif ($count > 10000) { throw new MWException("Number of requested IDs ({$count}) is too high."); } elseif ($bits < 16 || $bits > 48) { throw new MWException("Requested bit size ({$bits}) is out of range."); } $counter = null; // post-increment persistent counter value // Use APC/eAccelerator/xcache if requested, available, and not in CLI mode; // Counter values would not survive accross script instances in CLI mode. $cache = null; if ($flags & self::QUICK_VOLATILE && PHP_SAPI !== 'cli') { try { $cache = ObjectCache::newAccelerator(array()); } catch (Exception $e) { // not supported } } if ($cache) { $counter = $cache->incr($bucket, $count); if ($counter === false) { if (!$cache->add($bucket, (int) $count)) { throw new MWException('Unable to set value to ' . get_class($cache)); } $counter = $count; } } // Note: use of fmod() avoids "division by zero" on 32 bit machines if ($counter === null) { $path = wfTempDir() . '/mw-' . __CLASS__ . '-' . rawurlencode($bucket) . '-48'; // Get the UID lock file handle if (isset($this->fileHandles[$path])) { $handle = $this->fileHandles[$path]; } else { $handle = fopen($path, 'cb+'); $this->fileHandles[$path] = $handle ?: null; // cache } // Acquire the UID lock file if ($handle === false) { throw new MWException("Could not open '{$path}'."); } elseif (!flock($handle, LOCK_EX)) { fclose($handle); throw new MWException("Could not acquire '{$path}'."); } // Fetch the counter value and increment it... rewind($handle); $counter = floor(trim(fgets($handle))) + $count; // fetch as float // Write back the new counter value ftruncate($handle, 0); rewind($handle); fwrite($handle, fmod($counter, pow(2, 48))); // warp-around as needed fflush($handle); // Release the UID lock file flock($handle, LOCK_UN); } $ids = array(); $divisor = pow(2, $bits); $currentId = floor($counter - $count); // pre-increment counter value for ($i = 0; $i < $count; ++$i) { $ids[] = fmod(++$currentId, $divisor); } return $ids; }
/** * Construct a new instance from configuration. * * @param array $config Parameters include: * - dbServers : Associative array of DB names to server configuration. * Configuration is an associative array that includes: * - host : DB server name * - dbname : DB name * - type : DB type (mysql,postgres,...) * - user : DB user * - password : DB user password * - tablePrefix : DB table prefix * - flags : DB flags (see DatabaseBase) * - dbsByBucket : Array of 1-16 consecutive integer keys, starting from 0, * each having an odd-numbered list of DB names (peers) as values. * Any DB named 'localDBMaster' will automatically use the DB master * settings for this wiki (without the need for a dbServers entry). * Only use 'localDBMaster' if the domain is a valid wiki ID. * - lockExpiry : Lock timeout (seconds) for dropped connections. [optional] * This tells the DB server how long to wait before assuming * connection failure and releasing all the locks for a session. */ public function __construct(array $config) { parent::__construct($config); $this->dbServers = isset($config['dbServers']) ? $config['dbServers'] : array(); // likely just using 'localDBMaster' // Sanitize srvsByBucket config to prevent PHP errors $this->srvsByBucket = array_filter($config['dbsByBucket'], 'is_array'); $this->srvsByBucket = array_values($this->srvsByBucket); // consecutive if (isset($config['lockExpiry'])) { $this->lockExpiry = $config['lockExpiry']; } else { $met = ini_get('max_execution_time'); $this->lockExpiry = $met ? $met : 60; // use some sane amount if 0 } $this->safeDelay = $this->lockExpiry <= 0 ? 60 : $this->lockExpiry; // cover worst case foreach ($this->srvsByBucket as $bucket) { if (count($bucket) > 1) { // multiple peers // Tracks peers that couldn't be queried recently to avoid lengthy // connection timeouts. This is useless if each bucket has one peer. try { $this->statusCache = ObjectCache::newAccelerator(); } catch (Exception $e) { trigger_error(__CLASS__ . " using multiple DB peers without apc, xcache, or wincache."); } break; } } $this->session = wfRandomString(31); }
/** * Compile a LESS file into CSS. * * Keeps track of all used files and adds them to localFileRefs. * * @since 1.22 * @since 1.27 Added $context paramter. * @throws Exception If less.php encounters a parse error * @param string $fileName File path of LESS source * @param ResourceLoaderContext $context Context in which to generate script * @return string CSS source */ protected function compileLessFile($fileName, ResourceLoaderContext $context) { static $cache; if (!$cache) { $cache = ObjectCache::newAccelerator(CACHE_ANYTHING); } // Construct a cache key from the LESS file name and a hash digest // of the LESS variables used for compilation. $vars = $this->getLessVars($context); ksort($vars); $varsHash = hash('md4', serialize($vars)); $cacheKey = $cache->makeGlobalKey('LESS', $fileName, $varsHash); $cachedCompile = $cache->get($cacheKey); // If we got a cached value, we have to validate it by getting a // checksum of all the files that were loaded by the parser and // ensuring it matches the cached entry's. if (isset($cachedCompile['hash'])) { $contentHash = FileContentsHasher::getFileContentsHash($cachedCompile['files']); if ($contentHash === $cachedCompile['hash']) { $this->localFileRefs = array_merge($this->localFileRefs, $cachedCompile['files']); return $cachedCompile['css']; } } $compiler = ResourceLoader::getLessCompiler($this->getConfig(), $vars); $css = $compiler->parseFile($fileName)->getCss(); $files = $compiler->AllParsedFiles(); $this->localFileRefs = array_merge($this->localFileRefs, $files); $cache->set($cacheKey, array('css' => $css, 'files' => $files, 'hash' => FileContentsHasher::getFileContentsHash($files)), 60 * 60 * 24); // 86400 seconds, or 24 hours. return $css; }
public function __construct($parent) { $this->parent = $parent; $this->srvCache = ObjectCache::newAccelerator('hash'); $this->mainCache = ObjectCache::getLocalClusterInstance(); }
/** * @see FileBackendStore::__construct() * Additional $config params include: * - swiftAuthUrl : Swift authentication server URL * - swiftUser : Swift user used by MediaWiki (account:username) * - swiftKey : Swift authentication key for the above user * - swiftAuthTTL : Swift authentication TTL (seconds) * - swiftTempUrlKey : Swift "X-Account-Meta-Temp-URL-Key" value on the account. * Do not set this until it has been set in the backend. * - swiftAnonUser : Swift user used for end-user requests (account:username). * If set, then views of public containers are assumed to go * through this user. If not set, then public containers are * accessible to unauthenticated requests via ".r:*" in the ACL. * - swiftUseCDN : Whether a Cloud Files Content Delivery Network is set up * - swiftCDNExpiry : How long (in seconds) to store content in the CDN. * If files may likely change, this should probably not exceed * a few days. For example, deletions may take this long to apply. * If object purging is enabled, however, this is not an issue. * - swiftCDNPurgable : Whether object purge requests are allowed by the CDN. * - shardViaHashLevels : Map of container names to sharding config with: * - base : base of hash characters, 16 or 36 * - levels : the number of hash levels (and digits) * - repeat : hash subdirectories are prefixed with all the * parent hash directory names (e.g. "a/ab/abc") * - cacheAuthInfo : Whether to cache authentication tokens in APC, XCache, ect. * If those are not available, then the main cache will be used. * This is probably insecure in shared hosting environments. * - rgwS3AccessKey : Ragos Gateway S3 "access key" value on the account. * Do not set this until it has been set in the backend. * This is used for generating expiring pre-authenticated URLs. * Only use this when using rgw and to work around * http://tracker.newdream.net/issues/3454. * - rgwS3SecretKey : Ragos Gateway S3 "secret key" value on the account. * Do not set this until it has been set in the backend. * This is used for generating expiring pre-authenticated URLs. * Only use this when using rgw and to work around * http://tracker.newdream.net/issues/3454. */ public function __construct(array $config) { parent::__construct($config); if (!class_exists('CF_Constants')) { throw new MWException('SwiftCloudFiles extension not installed.'); } // Required settings $this->auth = new CF_Authentication($config['swiftUser'], $config['swiftKey'], null, $config['swiftAuthUrl']); // Optional settings $this->authTTL = isset($config['swiftAuthTTL']) ? $config['swiftAuthTTL'] : 5 * 60; // some sane number $this->swiftAnonUser = isset($config['swiftAnonUser']) ? $config['swiftAnonUser'] : ''; $this->swiftTempUrlKey = isset($config['swiftTempUrlKey']) ? $config['swiftTempUrlKey'] : ''; $this->shardViaHashLevels = isset($config['shardViaHashLevels']) ? $config['shardViaHashLevels'] : ''; $this->swiftUseCDN = isset($config['swiftUseCDN']) ? $config['swiftUseCDN'] : false; $this->swiftCDNExpiry = isset($config['swiftCDNExpiry']) ? $config['swiftCDNExpiry'] : 12 * 3600; // 12 hours is safe (tokens last 24 hours per http://docs.openstack.org) $this->swiftCDNPurgable = isset($config['swiftCDNPurgable']) ? $config['swiftCDNPurgable'] : true; $this->rgwS3AccessKey = isset($config['rgwS3AccessKey']) ? $config['rgwS3AccessKey'] : ''; $this->rgwS3SecretKey = isset($config['rgwS3SecretKey']) ? $config['rgwS3SecretKey'] : ''; // Cache container information to mask latency $this->memCache = wfGetMainCache(); // Process cache for container info $this->connContainerCache = new ProcessCacheLRU(300); // Cache auth token information to avoid RTTs if (!empty($config['cacheAuthInfo'])) { if (PHP_SAPI === 'cli') { $this->srvCache = wfGetMainCache(); // preferrably memcached } else { try { // look for APC, XCache, WinCache, ect... $this->srvCache = ObjectCache::newAccelerator(array()); } catch (Exception $e) { } } } $this->srvCache = $this->srvCache ? $this->srvCache : new EmptyBagOStuff(); }
/** * Determine if an image exists on the 'bad image list'. * * The format of MediaWiki:Bad_image_list is as follows: * * Only list items (lines starting with "*") are considered * * The first link on a line must be a link to a bad image * * Any subsequent links on the same line are considered to be exceptions, * i.e. articles where the image may occur inline. * * @param string $name The image name to check * @param Title|bool $contextTitle The page on which the image occurs, if known * @param string $blacklist Wikitext of a file blacklist * @return bool */ function wfIsBadImage($name, $contextTitle = false, $blacklist = null) { # Handle redirects; callers almost always hit wfFindFile() anyway, # so just use that method because it has a fast process cache. $file = wfFindFile($name); // get the final name $name = $file ? $file->getTitle()->getDBkey() : $name; # Run the extension hook $bad = false; if (!Hooks::run('BadImage', array($name, &$bad))) { return $bad; } $cache = ObjectCache::newAccelerator('hash'); $key = wfMemcKey('bad-image-list', $blacklist === null ? 'default' : md5($blacklist)); $badImages = $cache->get($key); if ($badImages === false) { // cache miss if ($blacklist === null) { $blacklist = wfMessage('bad_image_list')->inContentLanguage()->plain(); // site list } # Build the list now $badImages = array(); $lines = explode("\n", $blacklist); foreach ($lines as $line) { # List items only if (substr($line, 0, 1) !== '*') { continue; } # Find all links $m = array(); if (!preg_match_all('/\\[\\[:?(.*?)\\]\\]/', $line, $m)) { continue; } $exceptions = array(); $imageDBkey = false; foreach ($m[1] as $i => $titleText) { $title = Title::newFromText($titleText); if (!is_null($title)) { if ($i == 0) { $imageDBkey = $title->getDBkey(); } else { $exceptions[$title->getPrefixedDBkey()] = true; } } } if ($imageDBkey !== false) { $badImages[$imageDBkey] = $exceptions; } } $cache->set($key, $badImages, 60); } $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false; $bad = isset($badImages[$name]) && !isset($badImages[$name][$contextKey]); return $bad; }
/** * Get the hostname and lag time of the most-lagged slave. * This is useful for maintenance scripts that need to throttle their updates. * May attempt to open connections to slaves on the default DB. If there is * no lag, the maximum lag will be reported as -1. * * @param bool|string $wiki Wiki ID, or false for the default database * @return array ( host, max lag, index of max lagged host ) */ function getMaxLag($wiki = false) { $maxLag = -1; $host = ''; $maxIndex = 0; if ($this->getServerCount() <= 1) { // no replication = no lag return array($host, $maxLag, $maxIndex); } // Try to get the max lag info from the server cache $key = 'loadbalancer:maxlag:cluster:' . $this->mServers[0]['host']; $cache = ObjectCache::newAccelerator(array(), 'hash'); $maxLagInfo = $cache->get($key); // (host, lag, index) // Fallback to connecting to each slave and getting the lag if (!$maxLagInfo) { foreach ($this->mServers as $i => $conn) { if ($i == $this->getWriterIndex()) { continue; // nothing to check } $conn = false; if ($wiki === false) { $conn = $this->getAnyOpenConnection($i); } if (!$conn) { $conn = $this->openConnection($i, $wiki); } if (!$conn) { continue; } $lag = $conn->getLag(); if ($lag > $maxLag) { $maxLag = $lag; $host = $this->mServers[$i]['host']; $maxIndex = $i; } } $maxLagInfo = array($host, $maxLag, $maxIndex); $cache->set($key, $maxLagInfo, 5); } return $maxLagInfo; }
/** * Return a singleton instance, based on the global configs. * @return HKDF */ protected static function singleton() { global $wgHKDFAlgorithm, $wgHKDFSecret, $wgSecretKey; $secret = $wgHKDFSecret ?: $wgSecretKey; if (!$secret) { throw new MWException("Cannot use MWCryptHKDF without a secret."); } // In HKDF, the context can be known to the attacker, but this will // keep simultaneous runs from producing the same output. $context = array(); $context[] = microtime(); $context[] = getmypid(); $context[] = gethostname(); // Setup salt cache. Use APC, or fallback to the main cache if it isn't setup try { $cache = ObjectCache::newAccelerator(array()); } catch (Exception $e) { $cache = wfGetMainCache(); } if (is_null(self::$singleton)) { self::$singleton = new self($secret, $wgHKDFAlgorithm, $cache, $context); } return self::$singleton; }
/** * Load a library from the given file and execute it in the base environment. * @param string File name/path to load * @return mixed the export list, or null if there isn't one. */ protected function loadLibraryFromFile($fileName) { static $cache = null; if (!$cache) { $cache = ObjectCache::newAccelerator(array(), 'hash'); } $mtime = filemtime($fileName); if ($mtime === false) { throw new MWException('Lua file does not exist: ' . $fileName); } $cacheKey = wfGlobalCacheKey(__CLASS__, $fileName); $fileData = $cache->get($cacheKey); $code = false; if ($fileData) { list($code, $cachedMtime) = $fileData; if ($cachedMtime < $mtime) { $code = false; } } if (!$code) { $code = file_get_contents($fileName); if ($code === false) { throw new MWException('Lua file does not exist: ' . $fileName); } $cache->set($cacheKey, array($code, $mtime), 60 * 5); } # Prepending an "@" to the chunk name makes Lua think it is a filename $module = $this->getInterpreter()->loadString($code, '@' . basename($fileName)); $ret = $this->getInterpreter()->callFunction($module); return isset($ret[0]) ? $ret[0] : null; }
public function __construct($parent) { $this->parent = $parent; $this->srvCache = ObjectCache::newAccelerator('hash'); $this->mainCache = wfGetMainCache(); }
/** * Record stats on slow function calls. * * @param string $moduleName * @param string $functionName * @param int $timing Function execution time in milliseconds. */ public static function reportTiming($moduleName, $functionName, $timing) { global $wgScribuntoGatherFunctionStats, $wgScribuntoSlowFunctionThreshold; if (!$wgScribuntoGatherFunctionStats) { return; } $threshold = $wgScribuntoSlowFunctionThreshold; if (!(is_float($threshold) && $threshold > 0 && $threshold < 1)) { return; } static $cache; if (!$cache) { $cache = ObjectCache::newAccelerator(CACHE_NONE); } // To control the sampling rate, we keep a compact histogram of // observations in APC, and extract the Nth percentile (specified // via $wgScribuntoSlowFunctionThreshold; defaults to 0.90). // We need APC and \RunningStat\PSquare to do that. if (!class_exists('\\RunningStat\\PSquare') || $cache instanceof EmptyBagOStuff) { return; } $key = $cache->makeGlobalKey(__METHOD__, $threshold); // This is a classic "read-update-write" critical section with no // mutual exclusion, but the only consequence is that some samples // will be dropped. We only need enough samples to estimate the // the shape of the data, so that's fine. $ps = $cache->get($key) ?: new \RunningStat\PSquare($threshold); $ps->addObservation($timing); $cache->set($key, $ps, 60); if ($ps->getCount() < 1000 || $timing < $ps->getValue()) { return; } static $stats; if (!$stats) { $stats = RequestContext::getMain()->getStats(); } $metricKey = sprintf('scribunto.traces.%s__%s__%s', wfWikiId(), $moduleName, $functionName); $stats->timing($metricKey, $timing); }
/** * Constructor. */ public function __construct() { $this->cache = ObjectCache::newAccelerator('hash'); }
/** * @return float[] */ public static function getDefaultBoostTemplates() { if (self::$defaultBoostTemplates === null) { $cache = \ObjectCache::newAccelerator(CACHE_NONE); self::$defaultBoostTemplates = $cache->getWithSetCallback($cache->makeKey('cirrussearch-boost-templates'), 600, function () { $source = wfMessage('cirrussearch-boost-templates')->inContentLanguage(); if (!$source->isDisabled()) { $lines = Util::parseSettingsInMessage($source->plain()); return Util::parseBoostTemplates(implode(' ', $lines)); // Now parse the templates } return array(); }); } return self::$defaultBoostTemplates; }
/** * @see FileBackendStore::__construct() * Additional $config params include: * - swiftAuthUrl : Swift authentication server URL * - swiftUser : Swift user used by MediaWiki (account:username) * - swiftKey : Swift authentication key for the above user * - swiftAuthTTL : Swift authentication TTL (seconds) * - swiftTempUrlKey : Swift "X-Account-Meta-Temp-URL-Key" value on the account. * Do not set this until it has been set in the backend. * - shardViaHashLevels : Map of container names to sharding config with: * - base : base of hash characters, 16 or 36 * - levels : the number of hash levels (and digits) * - repeat : hash subdirectories are prefixed with all the * parent hash directory names (e.g. "a/ab/abc") * - cacheAuthInfo : Whether to cache authentication tokens in APC, XCache, ect. * If those are not available, then the main cache will be used. * This is probably insecure in shared hosting environments. * - rgwS3AccessKey : Rados Gateway S3 "access key" value on the account. * Do not set this until it has been set in the backend. * This is used for generating expiring pre-authenticated URLs. * Only use this when using rgw and to work around * http://tracker.newdream.net/issues/3454. * - rgwS3SecretKey : Rados Gateway S3 "secret key" value on the account. * Do not set this until it has been set in the backend. * This is used for generating expiring pre-authenticated URLs. * Only use this when using rgw and to work around * http://tracker.newdream.net/issues/3454. */ public function __construct(array $config) { parent::__construct($config); // Required settings $this->swiftAuthUrl = $config['swiftAuthUrl']; $this->swiftUser = $config['swiftUser']; $this->swiftKey = $config['swiftKey']; // Optional settings $this->authTTL = isset($config['swiftAuthTTL']) ? $config['swiftAuthTTL'] : 15 * 60; // some sane number $this->swiftTempUrlKey = isset($config['swiftTempUrlKey']) ? $config['swiftTempUrlKey'] : ''; $this->shardViaHashLevels = isset($config['shardViaHashLevels']) ? $config['shardViaHashLevels'] : ''; $this->rgwS3AccessKey = isset($config['rgwS3AccessKey']) ? $config['rgwS3AccessKey'] : ''; $this->rgwS3SecretKey = isset($config['rgwS3SecretKey']) ? $config['rgwS3SecretKey'] : ''; // HTTP helper client $this->http = new MultiHttpClient(array()); // Cache container information to mask latency if (isset($config['wanCache']) && $config['wanCache'] instanceof WANObjectCache) { $this->memCache = $config['wanCache']; } // Process cache for container info $this->containerStatCache = new ProcessCacheLRU(300); // Cache auth token information to avoid RTTs if (!empty($config['cacheAuthInfo'])) { if (PHP_SAPI === 'cli') { $this->srvCache = wfGetMainCache(); // preferrably memcached } else { try { // look for APC, XCache, WinCache, ect... $this->srvCache = ObjectCache::newAccelerator(array()); } catch (Exception $e) { } } } $this->srvCache = $this->srvCache ?: new EmptyBagOStuff(); }
/** * Extract more like this settings from the i18n message cirrussearch-morelikethis-settings */ private static function overrideMoreLikeThisOptionsFromMessage() { global $wgCirrusSearchMoreLikeThisConfig, $wgCirrusSearchMoreLikeThisUseFields, $wgCirrusSearchMoreLikeThisAllowedFields, $wgCirrusSearchMoreLikeThisMaxQueryTermsLimit, $wgCirrusSearchMoreLikeThisFields; $cache = \ObjectCache::newAccelerator(CACHE_NONE); $lines = $cache->getWithSetCallback($cache->makeKey('cirrussearch-morelikethis-settings'), 600, function () { $source = wfMessage('cirrussearch-morelikethis-settings')->inContentLanguage(); if ($source && $source->isDisabled()) { return array(); } return Util::parseSettingsInMessage($source->plain()); }); foreach ($lines as $line) { list($k, $v) = explode(':', $line, 2); switch ($k) { case 'min_doc_freq': case 'max_doc_freq': case 'max_query_terms': case 'min_term_freq': case 'min_word_len': case 'max_word_len': if (is_numeric($v) && $v >= 0) { $wgCirrusSearchMoreLikeThisConfig[$k] = intval($v); } else { if ($v === 'null') { unset($wgCirrusSearchMoreLikeThisConfig[$k]); } } break; case 'percent_terms_to_match': if (is_numeric($v) && $v > 0 && $v <= 1) { $wgCirrusSearchMoreLikeThisConfig[$k] = $v; } else { if ($v === 'null') { unset($wgCirrusSearchMoreLikeThisConfig[$k]); } } break; case 'fields': $wgCirrusSearchMoreLikeThisFields = array_intersect(array_map('trim', explode(',', $v)), $wgCirrusSearchMoreLikeThisAllowedFields); break; case 'use_fields': if ($v === 'true') { $wgCirrusSearchMoreLikeThisUseFields = true; } else { if ($v === 'false') { $wgCirrusSearchMoreLikeThisUseFields = false; } } break; } if ($wgCirrusSearchMoreLikeThisConfig['max_query_terms'] > $wgCirrusSearchMoreLikeThisMaxQueryTermsLimit) { $wgCirrusSearchMoreLikeThisConfig['max_query_terms'] = $wgCirrusSearchMoreLikeThisMaxQueryTermsLimit; } } }
/** * Get the namespace display name in the preferred variant. * * @param int $index Namespace id * @param string|null $variant Variant code or null for preferred variant * @return string Namespace name for display */ public function convertNamespace($index, $variant = null) { if ($index === NS_MAIN) { return ''; } if ($variant === null) { $variant = $this->getPreferredVariant(); } $cache = ObjectCache::newAccelerator(CACHE_NONE); $key = wfMemcKey('languageconverter', 'namespace-text', $index, $variant); $nsVariantText = $cache->get($key); if ($nsVariantText !== false) { return $nsVariantText; } // First check if a message gives a converted name in the target variant. $nsConvMsg = wfMessage('conversion-ns' . $index)->inLanguage($variant); if ($nsConvMsg->exists()) { $nsVariantText = $nsConvMsg->plain(); } // Then check if a message gives a converted name in content language // which needs extra translation to the target variant. if ($nsVariantText === false) { $nsConvMsg = wfMessage('conversion-ns' . $index)->inContentLanguage(); if ($nsConvMsg->exists()) { $nsVariantText = $this->translate($nsConvMsg->plain(), $variant); } } if ($nsVariantText === false) { // No message exists, retrieve it from the target variant's namespace names. $langObj = $this->mLangObj->factory($variant); $nsVariantText = $langObj->getFormattedNsText($index); } $cache->set($key, $nsVariantText, 60); return $nsVariantText; }
/** * Constructor. * * FIXME: It is possible to construct a Database object with no associated * connection object, by specifying no parameters to __construct(). This * feature is deprecated and should be removed. * * DatabaseBase subclasses should not be constructed directly in external * code. DatabaseBase::factory() should be used instead. * * @param array $params Parameters passed from DatabaseBase::factory() */ function __construct(array $params) { global $wgDBprefix, $wgDBmwschema, $wgCommandLineMode; $this->mTrxAtomicLevels = new SplStack(); $this->srvCache = ObjectCache::newAccelerator('hash'); $server = $params['host']; $user = $params['user']; $password = $params['password']; $dbName = $params['dbname']; $flags = $params['flags']; $tablePrefix = $params['tablePrefix']; $schema = $params['schema']; $foreign = $params['foreign']; $this->mFlags = $flags; if ($this->mFlags & DBO_DEFAULT) { if ($wgCommandLineMode) { $this->mFlags &= ~DBO_TRX; } else { $this->mFlags |= DBO_TRX; } } $this->mSessionVars = $params['variables']; /** Get the default table prefix*/ if ($tablePrefix === 'get from global') { $this->mTablePrefix = $wgDBprefix; } else { $this->mTablePrefix = $tablePrefix; } /** Get the database schema*/ if ($schema === 'get from global') { $this->mSchema = $wgDBmwschema; } else { $this->mSchema = $schema; } $this->mForeign = $foreign; if (isset($params['trxProfiler'])) { $this->trxProfiler = $params['trxProfiler']; // override } if ($user) { $this->open($server, $user, $password, $dbName); } }
/** * Run JavaScript or CSS data through a filter, caching the filtered result for future calls. * * Available filters are: * * - minify-js \see JavaScriptMinifier::minify * - minify-css \see CSSMin::minify * * If $data is empty, only contains whitespace or the filter was unknown, * $data is returned unmodified. * * @param string $filter Name of filter to run * @param string $data Text to filter, such as JavaScript or CSS text * @param array $options Keys: * - (bool) cache: Whether to allow caching this data. Default: true. * @return string Filtered data, or a comment containing an error message */ public static function filter($filter, $data, array $options = array()) { if (strpos($data, ResourceLoader::FILTER_NOMIN) !== false) { return $data; } if (isset($options['cache']) && $options['cache'] === false) { return self::applyFilter($filter, $data); } $stats = RequestContext::getMain()->getStats(); $cache = ObjectCache::newAccelerator(CACHE_ANYTHING); $key = wfGlobalCacheKey('resourceloader', 'filter', $filter, self::$filterCacheVersion, md5($data)); $result = $cache->get($key); if ($result === false) { $stats->increment("resourceloader_cache.{$filter}.miss"); $result = self::applyFilter($filter, $data); $cache->set($key, $result, 24 * 3600); } else { $stats->increment("resourceloader_cache.{$filter}.hit"); } if ($result === null) { // Cached failure $result = $data; } return $result; }
/** * Compute a non-cryptographic string hash of a file's contents. * If the file does not exist or cannot be read, returns an empty string. * * @since 1.26 Uses MD4 instead of SHA1. * @param string $filePath File path * @return string Hash */ protected static function safeFileHash($filePath) { static $cache; if (!$cache) { $cache = ObjectCache::newAccelerator(CACHE_NONE); } MediaWiki\suppressWarnings(); $mtime = filemtime($filePath); MediaWiki\restoreWarnings(); if (!$mtime) { return ''; } $cacheKey = wfGlobalCacheKey('resourceloader', __METHOD__, $filePath); $cachedHash = $cache->get($cacheKey); if (isset($cachedHash['mtime']) && $cachedHash['mtime'] === $mtime) { return $cachedHash['hash']; } MediaWiki\suppressWarnings(); $contents = file_get_contents($filePath); MediaWiki\restoreWarnings(); if (!$contents) { return ''; } $hash = hash('md4', $contents); $cache->set($cacheKey, array('mtime' => $mtime, 'hash' => $hash), 60 * 60 * 24); return $hash; }
/** * @param BagOStuff $memCached A cache instance. If none, fall back to CACHE_NONE. * @param bool $useDB * @param int $expiry Lifetime for cache. @see $mExpiry. */ function __construct($memCached, $useDB, $expiry) { global $wgUseLocalMessageCache; if (!$memCached) { $memCached = wfGetCache(CACHE_NONE); } $this->mMemc = $memCached; $this->mDisable = !$useDB; $this->mExpiry = $expiry; if ($wgUseLocalMessageCache) { $this->localCache = ObjectCache::newAccelerator(CACHE_NONE); } else { $this->localCache = wfGetCache(CACHE_NONE); } $this->wanCache = ObjectCache::getMainWANInstance(); }
/** * Run JavaScript or CSS data through a filter, caching the filtered result for future calls. * * Available filters are: * * - minify-js \see JavaScriptMinifier::minify * - minify-css \see CSSMin::minify * * If $data is empty, only contains whitespace or the filter was unknown, * $data is returned unmodified. * * @param string $filter Name of filter to run * @param string $data Text to filter, such as JavaScript or CSS text * @param array $options For back-compat, can also be the boolean value for "cacheReport". Keys: * - (bool) cache: Whether to allow caching this data. Default: true. * - (bool) cacheReport: Whether to include the "cache key" report comment. Default: false. * @return string Filtered data, or a comment containing an error message */ public function filter($filter, $data, $options = array()) { // Back-compat if (is_bool($options)) { $options = array('cacheReport' => $options); } // Defaults $options += array('cache' => true, 'cacheReport' => false); $stats = RequestContext::getMain()->getStats(); // Don't filter empty content if (trim($data) === '') { return $data; } if (!in_array($filter, array('minify-js', 'minify-css'))) { $this->logger->warning('Invalid filter {filter}', array('filter' => $filter)); return $data; } if (!$options['cache']) { $result = self::applyFilter($filter, $data, $this->config); } else { $key = wfGlobalCacheKey('resourceloader', 'filter', $filter, self::$filterCacheVersion, md5($data)); $cache = ObjectCache::newAccelerator(CACHE_ANYTHING); $cacheEntry = $cache->get($key); if (is_string($cacheEntry)) { $stats->increment("resourceloader_cache.{$filter}.hit"); return $cacheEntry; } $result = ''; try { $statStart = microtime(true); $result = self::applyFilter($filter, $data, $this->config); $statTiming = microtime(true) - $statStart; $stats->increment("resourceloader_cache.{$filter}.miss"); $stats->timing("resourceloader_cache.{$filter}.timing", 1000 * $statTiming); if ($options['cacheReport']) { $result .= "\n/* cache key: {$key} */"; } // Set a TTL since HHVM's APC doesn't have any limitation or eviction logic. $cache->set($key, $result, 24 * 3600); } catch (Exception $e) { MWExceptionHandler::logException($e); $this->logger->warning('Minification failed: {exception}', array('exception' => $e)); $this->errors[] = self::formatExceptionNoComment($e); } } return $result; }