function createCache()
 {
     if (!isset($this->cache)) {
         global $wgPageAttachment_useInternalCache;
         global $wgPageAttachment_internalCacheType;
         if (isset($wgPageAttachment_useInternalCache) && $wgPageAttachment_useInternalCache == true) {
             if (isset($wgPageAttachment_internalCacheType)) {
                 if ($wgPageAttachment_internalCacheType == 'SQLite3') {
                     $this->cache = new Provider\SQLiteCache();
                 } else {
                     if ($wgPageAttachment_internalCacheType == 'Database') {
                         $this->cache = new Provider\DatabaseCache();
                     } else {
                         print '<br/>*** ERROR ***************************************************************<br/>';
                         print 'PageAttachment internal cache is enabled.<br/>';
                         print 'However, invalid PageAttachment internal cache type specified: ' . $wgPageAttachment_internalCacheType . '<br/>';
                         print '*************************************************************************<br/>';
                     }
                 }
             } else {
                 print '<br/>*** ERROR ***************************************************************<br/>';
                 print 'PageAttachment internal cache is enabled.<br/>';
                 print 'However, PageAttachment internal cache type is not specified.<br/>';
                 print '*************************************************************************<br/>';
             }
         } else {
             $mwCacheObj = \wfGetMainCache();
             $this->cache = new Provider\MWCacheObjWrapper($mwCacheObj);
         }
     }
     return $this->cache;
 }
 /**
  * @params include:
  *   - objectCache : Name of an object cache registered in $wgObjectCaches.
  *                   This defaults to the one specified by $wgMainCacheType.
  *   - cacheTTL    : Seconds to cache the aggregate data before regenerating.
  * @param array $params
  */
 protected function __construct(array $params)
 {
     parent::__construct($params);
     $this->cache = isset($params['objectCache']) ? wfGetCache($params['objectCache']) : wfGetMainCache();
     $this->cacheTTL = isset($params['cacheTTL']) ? $params['cacheTTL'] : 180;
     // 3 min
 }
Exemplo n.º 3
0
 public function __construct($parent)
 {
     global $wgMemc;
     $this->parent = $parent;
     $this->srvCache = ObjectCache::newAccelerator(array(), 'hash');
     $this->mainCache = $wgMemc ?: wfGetMainCache();
 }
Exemplo n.º 4
0
 /**
  * Construct a new instance from configuration.
  * 
  * $config paramaters 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).
  *     '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.
  *
  * @param Array $config 
  */
 public function __construct(array $config)
 {
     $this->dbServers = isset($config['dbServers']) ? $config['dbServers'] : array();
     // likely just using 'localDBMaster'
     // Sanitize dbsByBucket config to prevent PHP errors
     $this->dbsByBucket = array_filter($config['dbsByBucket'], 'is_array');
     $this->dbsByBucket = array_values($this->dbsByBucket);
     // 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->dbsByBucket as $bucket) {
         if (count($bucket) > 1) {
             // Tracks peers that couldn't be queried recently to avoid lengthy
             // connection timeouts. This is useless if each bucket has one peer.
             $this->statusCache = wfGetMainCache();
             break;
         }
     }
     $this->session = '';
     for ($i = 0; $i < 5; $i++) {
         $this->session .= mt_rand(0, 2147483647);
     }
     $this->session = wfBaseConvert(sha1($this->session), 16, 36, 31);
 }
 function setUp()
 {
     global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, $wgDeferredUpdateList, $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache, $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo, $parserMemc, $wgThumbnailScriptPath, $wgScriptPath, $wgArticlePath, $wgStyleSheetPath, $wgScript, $wgStylePath;
     $wgScript = '/index.php';
     $wgScriptPath = '/';
     $wgArticlePath = '/wiki/$1';
     $wgStyleSheetPath = '/skins';
     $wgStylePath = '/skins';
     $wgThumbnailScriptPath = false;
     $wgLocalFileRepo = array('class' => 'LocalRepo', 'name' => 'local', 'directory' => wfTempDir() . '/test-repo', 'url' => 'http://example.com/images', 'deletedDir' => wfTempDir() . '/test-repo/delete', 'hashLevels' => 2, 'transformVia404' => false);
     $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface';
     $wgNamespaceAliases['Image'] = NS_FILE;
     $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK;
     $wgEnableParserCache = false;
     $wgDeferredUpdateList = array();
     $wgMemc = wfGetMainCache();
     $messageMemc = wfGetMessageCacheStorage();
     $parserMemc = wfGetParserCacheStorage();
     // $wgContLang = new StubContLang;
     $wgUser = new User();
     $context = new RequestContext();
     $wgLang = $context->getLang();
     $wgOut = $context->getOutput();
     $wgParser = new StubObject('wgParser', $wgParserConf['class'], array($wgParserConf));
     $wgRequest = new WebRequest();
     if ($wgStyleDirectory === false) {
         $wgStyleDirectory = "{$IP}/skins";
     }
 }
Exemplo n.º 6
0
 /**
  * @since 1.21
  * @deprecated 1.25 Construct a SiteStore instance directly instead.
  *
  * @param ORMTable|null $sitesTable
  * @param BagOStuff|null $cache
  *
  * @return SiteStore
  */
 public static function newInstance(ORMTable $sitesTable = null, BagOStuff $cache = null)
 {
     if ($cache === null) {
         $cache = wfGetMainCache();
     }
     $siteStore = new DBSiteStore();
     return new static($siteStore, $cache);
 }
Exemplo n.º 7
0
 /**
  * Initialization
  */
 private static function init()
 {
     clearstatcache();
     self::$cache =& wfGetMainCache();
     if (self::$cache instanceof FakeMemCachedClient) {
         self::$realCache = false;
     }
 }
 public function execute()
 {
     $force = $this->getOption('force', false);
     $this->source = $this->getOption('source', 'https://en.wikipedia.org/w/api.php');
     $this->cache = wfGetMainCache();
     $data = $this->fetchLinks();
     if ($data === false) {
         $this->error("Error during fetching data.");
     } else {
         $this->doPopulate($data, $force);
     }
 }
Exemplo n.º 9
0
 function setUp()
 {
     global $wgContLang, $wgNamespaceProtection, $wgNamespaceAliases;
     global $wgHooks, $IP;
     $wgContLang = Language::factory('en');
     //Setup CLI arguments
     if ($this->getCliArg('regex=')) {
         $this->regex = $this->getCliArg('regex=');
     } else {
         # Matches anything
         $this->regex = '';
     }
     $this->keepUploads = $this->getCliArg('keep-uploads');
     $tmpGlobals = array();
     $tmpGlobals['wgScript'] = '/index.php';
     $tmpGlobals['wgScriptPath'] = '/';
     $tmpGlobals['wgArticlePath'] = '/wiki/$1';
     $tmpGlobals['wgStyleSheetPath'] = '/skins';
     $tmpGlobals['wgStylePath'] = '/skins';
     $tmpGlobals['wgThumbnailScriptPath'] = false;
     $tmpGlobals['wgLocalFileRepo'] = array('class' => 'LocalRepo', 'name' => 'local', 'url' => 'http://example.com/images', 'hashLevels' => 2, 'transformVia404' => false, 'backend' => 'local-backend');
     $tmpGlobals['wgForeignFileRepos'] = array();
     $tmpGlobals['wgEnableParserCache'] = false;
     $tmpGlobals['wgHooks'] = $wgHooks;
     $tmpGlobals['wgDeferredUpdateList'] = array();
     $tmpGlobals['wgMemc'] = wfGetMainCache();
     $tmpGlobals['messageMemc'] = wfGetMessageCacheStorage();
     $tmpGlobals['parserMemc'] = wfGetParserCacheStorage();
     // $tmpGlobals['wgContLang'] = new StubContLang;
     $tmpGlobals['wgUser'] = new User();
     $context = new RequestContext();
     $tmpGlobals['wgLang'] = $context->getLanguage();
     $tmpGlobals['wgOut'] = $context->getOutput();
     $tmpGlobals['wgParser'] = new StubObject('wgParser', $GLOBALS['wgParserConf']['class'], array($GLOBALS['wgParserConf']));
     $tmpGlobals['wgRequest'] = $context->getRequest();
     if ($GLOBALS['wgStyleDirectory'] === false) {
         $tmpGlobals['wgStyleDirectory'] = "{$IP}/skins";
     }
     foreach ($tmpGlobals as $var => $val) {
         if (array_key_exists($var, $GLOBALS)) {
             $this->savedInitialGlobals[$var] = $GLOBALS[$var];
         }
         $GLOBALS[$var] = $val;
     }
     $this->savedWeirdGlobals['mw_namespace_protection'] = $wgNamespaceProtection[NS_MEDIAWIKI];
     $this->savedWeirdGlobals['image_alias'] = $wgNamespaceAliases['Image'];
     $this->savedWeirdGlobals['image_talk_alias'] = $wgNamespaceAliases['Image_talk'];
     $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface';
     $wgNamespaceAliases['Image'] = NS_FILE;
     $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK;
 }
Exemplo n.º 10
0
 function getLagTimes($serverIndexes, $wiki)
 {
     wfProfileIn(__METHOD__);
     $expiry = 5;
     $requestRate = 10;
     global $wgMemc;
     if (empty($wgMemc)) {
         $wgMemc = wfGetMainCache();
     }
     $masterName = $this->parent->getServerName(0);
     $memcKey = wfMemcKey('lag_times', $masterName);
     $times = $wgMemc->get($memcKey);
     if ($times) {
         # Randomly recache with probability rising over $expiry
         $elapsed = time() - $times['timestamp'];
         $chance = max(0, ($expiry - $elapsed) * $requestRate);
         if (mt_rand(0, $chance) != 0) {
             unset($times['timestamp']);
             wfProfileOut(__METHOD__);
             return $times;
         }
         wfIncrStats('lag_cache_miss_expired');
     } else {
         wfIncrStats('lag_cache_miss_absent');
     }
     # Cache key missing or expired
     $times = array();
     foreach ($serverIndexes as $i) {
         if ($i == 0) {
             # Master
             $times[$i] = 0;
         } elseif (false !== ($conn = $this->parent->getAnyOpenConnection($i))) {
             $times[$i] = $conn->getLag();
         } elseif (false !== ($conn = $this->parent->openConnection($i, $wiki))) {
             $times[$i] = $conn->getLag();
         }
     }
     # Add a timestamp key so we know when it was cached
     $times['timestamp'] = time();
     $wgMemc->set($memcKey, $times, $expiry);
     # But don't give the timestamp to the caller
     unset($times['timestamp']);
     $lagTimes = $times;
     wfProfileOut(__METHOD__);
     return $lagTimes;
 }
Exemplo n.º 11
0
 public static function suite()
 {
     $suite = new PHPUnit_Framework_TestSuite();
     self::$iter = new TestFileIterator(PARSER_TESTS);
     foreach (self::$iter as $i => $test) {
         $suite->addTest(new ParserUnitTest($i, $test['test']));
         self::$count++;
     }
     unset($tests);
     self::$parser = new PTShell();
     self::$iter->setParser(self::$parser);
     self::$parser->recorder->start();
     self::$parser->setupDatabase();
     self::$iter->rewind();
     /* } */
     /* function setUp() { */
     global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, $wgDeferredUpdateList, $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgEnableParserCache, $wgMessageCache, $wgUseDatabaseMessages, $wgMsgCacheExpiry, $parserMemc, $wgNamespaceAliases, $wgNamespaceProtection, $wgLocalFileRepo, $wgNamespacesWithSubpages, $wgThumbnailScriptPath, $wgScriptPath, $wgArticlePath, $wgStyleSheetPath, $wgScript, $wgStylePath;
     $wgScript = '/index.php';
     $wgScriptPath = '/';
     $wgArticlePath = '/wiki/$1';
     $wgStyleSheetPath = '/skins';
     $wgStylePath = '/skins';
     $wgThumbnailScriptPath = false;
     $wgLocalFileRepo = array('class' => 'LocalRepo', 'name' => 'local', 'directory' => '', 'url' => 'http://example.com/images', 'hashLevels' => 2, 'transformVia404' => false);
     $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface';
     $wgNamespaceAliases['Image'] = NS_FILE;
     $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK;
     $wgEnableParserCache = false;
     $wgDeferredUpdateList = array();
     $wgMemc =& wfGetMainCache();
     $messageMemc =& wfGetMessageCacheStorage();
     $parserMemc =& wfGetParserCacheStorage();
     $wgContLang = new StubContLang();
     $wgUser = new StubUser();
     $wgLang = new StubUserLang();
     $wgOut = new StubObject('wgOut', 'OutputPage');
     $wgParser = new StubObject('wgParser', $wgParserConf['class'], array($wgParserConf));
     $wgRequest = new WebRequest();
     $wgMessageCache = new StubObject('wgMessageCache', 'MessageCache', array($messageMemc, $wgUseDatabaseMessages, $wgMsgCacheExpiry, wfWikiID()));
     if ($wgStyleDirectory === false) {
         $wgStyleDirectory = "{$IP}/skins";
     }
     return $suite;
 }
Exemplo n.º 12
0
 protected function setUp()
 {
     global $wgParser, $wgParserConf, $IP, $messageMemc, $wgMemc, $wgUser, $wgLang, $wgOut, $wgRequest, $wgStyleDirectory, $wgParserCacheType, $wgNamespaceAliases, $wgNamespaceProtection, $parserMemc;
     $tmpDir = $this->getNewTempDirectory();
     $tmpGlobals = [];
     $tmpGlobals['wgScript'] = '/index.php';
     $tmpGlobals['wgScriptPath'] = '/';
     $tmpGlobals['wgArticlePath'] = '/wiki/$1';
     $tmpGlobals['wgStylePath'] = '/skins';
     $tmpGlobals['wgThumbnailScriptPath'] = false;
     $tmpGlobals['wgLocalFileRepo'] = ['class' => 'LocalRepo', 'name' => 'local', 'url' => 'http://example.com/images', 'hashLevels' => 2, 'transformVia404' => false, 'backend' => new FSFileBackend(['name' => 'local-backend', 'wikiId' => wfWikiID(), 'containerPaths' => ['local-public' => "{$tmpDir}/test-repo/public", 'local-thumb' => "{$tmpDir}/test-repo/thumb", 'local-temp' => "{$tmpDir}/test-repo/temp", 'local-deleted' => "{$tmpDir}/test-repo/delete"]])];
     foreach ($tmpGlobals as $var => $val) {
         if (array_key_exists($var, $GLOBALS)) {
             $this->savedGlobals[$var] = $GLOBALS[$var];
         }
         $GLOBALS[$var] = $val;
     }
     $wgNamespaceProtection[NS_MEDIAWIKI] = 'editinterface';
     $wgNamespaceAliases['Image'] = NS_FILE;
     $wgNamespaceAliases['Image_talk'] = NS_FILE_TALK;
     $wgParserCacheType = CACHE_NONE;
     DeferredUpdates::clearPendingUpdates();
     $wgMemc = wfGetMainCache();
     $messageMemc = wfGetMessageCacheStorage();
     $parserMemc = wfGetParserCacheStorage();
     RequestContext::resetMain();
     $context = RequestContext::getMain();
     $wgUser = new User();
     $wgLang = $context->getLanguage();
     $wgOut = $context->getOutput();
     $wgParser = new StubObject('wgParser', $wgParserConf['class'], [$wgParserConf]);
     $wgRequest = $context->getRequest();
     if ($wgStyleDirectory === false) {
         $wgStyleDirectory = "{$IP}/skins";
     }
     RepoGroup::destroySingleton();
     FileBackendGroup::destroySingleton();
 }
 public function __construct()
 {
     global $IP;
     // No Setup.php yet. Initialise everything by ourselves
     require_once $IP . '/includes/GlobalFunctions.php';
     require_once $IP . '/includes/ObjectCache.php';
     $wgMemc = wfGetMainCache();
     // Caching not yet working
     $cached = false;
     //$wgMemc->get( 'configurewmf:data' );
     if ($cached) {
         $this->overrides = $cached;
         return;
     }
     $dbr = self::getSlaveDB();
     $r = $dbr->select('config_overrides', array('cfg_target', 'cfg_value'), null, __METHOD__);
     $overrides = array();
     while ($row = $dbr->fetchObject($r)) {
         $overrides[] = array('target' => $row->cfg_target, 'value' => unserialize($row->cfg_value));
     }
     $wgMemc->set('configurewmf:data', $overrides);
     $this->overrides = $overrides;
 }
Exemplo n.º 14
0
 /**
  * @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)
  *    swiftAnonUser      : Swift user used for end-user requests (account:username)
  *    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")
  *	  swiftTimeout       : number of seconds timeout consistent with php-cloudfiles. Default: 10
  */
 public function __construct(array $config)
 {
     parent::__construct($config);
     // Required settings
     $this->auth = new CF_Authentication($config['swiftUser'], $config['swiftKey'], null, $config['swiftAuthUrl']);
     /* <Wikia> */
     if (!empty($config['debug'])) {
         $this->auth->setDebug($config['debug']);
     }
     $this->swiftTimeout = isset($config['swiftTimeout']) ? intval($config['swiftTimeout']) : 10;
     /* </Wikia> */
     // Optional settings
     $this->authTTL = isset($config['swiftAuthTTL']) ? $config['swiftAuthTTL'] : 120;
     // some sane number
     $this->swiftAnonUser = isset($config['swiftAnonUser']) ? $config['swiftAnonUser'] : '';
     $this->shardViaHashLevels = isset($config['shardViaHashLevels']) ? $config['shardViaHashLevels'] : '';
     /* <Wikia> */
     // caching credentials
     if (!empty($config['cacheAuthInfo']) && $config['cacheAuthInfo'] === true) {
         $this->srvCache = wfGetMainCache();
     }
     $this->srvCache = $this->srvCache ? $this->srvCache : new EmptyBagOStuff();
     /* </Wikia> */
 }
Exemplo n.º 15
0
 /**
  * Purges the internal and external cache of the site list, forcing the list
  * of sites to be re-read from the database.
  *
  * @since 1.21
  */
 public function reset()
 {
     wfProfileIn(__METHOD__);
     // purge cache
     $cache = wfGetMainCache();
     $cache->delete($this->getCacheKey());
     $this->sites = null;
     wfProfileOut(__METHOD__);
 }
Exemplo n.º 16
0
 /**
  * Start a transaction and lock the image for update
  * Increments a reference counter if the lock is already held
  * @throws MWException
  * @return bool True if the image exists, false otherwise
  */
 function lock()
 {
     $dbw = $this->repo->getMasterDB();
     if (!$this->locked) {
         if (!$dbw->trxLevel()) {
             $dbw->begin(__METHOD__);
             $this->lockedOwnTrx = true;
         }
         $this->locked++;
         // Bug 54736: use simple lock to handle when the file does not exist.
         // SELECT FOR UPDATE only locks records not the gaps where there are none.
         $cache = wfGetMainCache();
         $key = $this->getCacheKey();
         if (!$cache->lock($key, 5)) {
             throw new MWException("Could not acquire lock for '{$this->getName()}.'");
         }
         $dbw->onTransactionIdle(function () use($cache, $key) {
             $cache->unlock($key);
             // release on commit
         });
     }
     return $dbw->selectField('image', '1', array('img_name' => $this->getName()), __METHOD__, array('FOR UPDATE'));
 }
Exemplo n.º 17
0
// Useful debug output
if ($wgCommandLineMode) {
    wfDebug("\n\nStart command line script {$self}\n");
} else {
    $debug = "\n\nStart request {$wgRequest->getMethod()} {$wgRequest->getRequestURL()}\n";
    if ($wgDebugPrintHttpHeaders) {
        $debug .= "HTTP HEADERS:\n";
        foreach ($wgRequest->getAllHeaders() as $name => $value) {
            $debug .= "{$name}: {$value}\n";
        }
    }
    wfDebug($debug);
}
Profiler::instance()->scopedProfileOut($ps_misc);
$ps_memcached = Profiler::instance()->scopedProfileIn($fname . '-memcached');
$wgMemc = wfGetMainCache();
$messageMemc = wfGetMessageCacheStorage();
$parserMemc = wfGetParserCacheStorage();
wfDebugLog('caches', 'cluster: ' . get_class($wgMemc) . ', WAN: ' . ($wgMainWANCache === CACHE_NONE ? 'CACHE_NONE' : $wgMainWANCache) . ', stash: ' . $wgMainStash . ', message: ' . get_class($messageMemc) . ', parser: ' . get_class($parserMemc) . ', session: ' . get_class(ObjectCache::getInstance($wgSessionCacheType)));
Profiler::instance()->scopedProfileOut($ps_memcached);
// Most of the config is out, some might want to run hooks here.
Hooks::run('SetupAfterCache');
$ps_globals = Profiler::instance()->scopedProfileIn($fname . '-globals');
/**
 * @var Language $wgContLang
 */
$wgContLang = Language::factory($wgLanguageCode);
$wgContLang->initContLang();
// Now that variant lists may be available...
$wgRequest->interpolateTitle();
if (!is_object($wgAuth)) {
 /**
  * Highlight a code-block using a particular lexer.
  *
  * @param string $code Code to highlight.
  * @param string|null $lang Language name, or null to use plain markup.
  * @param array $args Associative array of additional arguments.
  *  If it contains a 'line' key, the output will include line numbers.
  *  If it includes a 'highlight' key, the value will be parsed as a
  *  comma-separated list of lines and line-ranges to highlight.
  *  If it contains a 'start' key, the value will be used as the line at which to
  *  start highlighting.
  *  If it contains a 'inline' key, the output will not be wrapped in `<div><pre/></div>`.
  * @return Status Status object, with HTML representing the highlighted
  *  code as its value.
  */
 protected static function highlight($code, $lang = null, $args = array())
 {
     global $wgPygmentizePath;
     $status = new Status();
     $lexer = self::getLexer($lang);
     if ($lexer === null && $lang !== null) {
         $status->warning('syntaxhighlight-error-unknown-language', $lang);
     }
     $length = strlen($code);
     if (strlen($code) > self::HIGHLIGHT_MAX_BYTES) {
         $status->warning('syntaxhighlight-error-exceeds-size-limit', $length, self::HIGHLIGHT_MAX_BYTES);
         $lexer = null;
     }
     if (wfShellExecDisabled() !== false) {
         $status->warning('syntaxhighlight-error-pygments-invocation-failure');
         wfWarn('MediaWiki determined that it cannot invoke Pygments. ' . 'As a result, SyntaxHighlight_GeSHi will not perform any syntax highlighting. ' . 'See the debug log for details: ' . 'https://www.mediawiki.org/wiki/Manual:$wgDebugLogFile');
         $lexer = null;
     }
     $inline = isset($args['inline']);
     if ($lexer === null) {
         if ($inline) {
             $status->value = htmlspecialchars(trim($code), ENT_NOQUOTES);
         } else {
             $pre = Html::element('pre', array(), $code);
             $status->value = Html::rawElement('div', array('class' => self::HIGHLIGHT_CSS_CLASS), $pre);
         }
         return $status;
     }
     $options = array('cssclass' => self::HIGHLIGHT_CSS_CLASS, 'encoding' => 'utf-8');
     // Line numbers
     if (isset($args['line'])) {
         $options['linenos'] = 'inline';
     }
     if ($lexer === 'php' && strpos($code, '<?php') === false) {
         $options['startinline'] = 1;
     }
     // Highlight specific lines
     if (isset($args['highlight'])) {
         $lines = self::parseHighlightLines($args['highlight']);
         if (count($lines)) {
             $options['hl_lines'] = implode(' ', $lines);
         }
     }
     // Starting line number
     if (isset($args['start'])) {
         $options['linenostart'] = $args['start'];
     }
     if ($inline) {
         $options['nowrap'] = 1;
     }
     $cache = wfGetMainCache();
     $cacheKey = self::makeCacheKey($code, $lexer, $options);
     $output = $cache->get($cacheKey);
     if ($output === false) {
         $optionPairs = array();
         foreach ($options as $k => $v) {
             $optionPairs[] = "{$k}={$v}";
         }
         $builder = new ProcessBuilder();
         $builder->setPrefix($wgPygmentizePath);
         $process = $builder->add('-l')->add($lexer)->add('-f')->add('html')->add('-O')->add(implode(',', $optionPairs))->getProcess();
         $process->setInput($code);
         $process->run();
         if (!$process->isSuccessful()) {
             $status->warning('syntaxhighlight-error-pygments-invocation-failure');
             wfWarn('Failed to invoke Pygments: ' . $process->getErrorOutput());
             $status->value = self::highlight($code, null, $args)->getValue();
             return $status;
         }
         $output = $process->getOutput();
         $cache->set($cacheKey, $output);
     }
     if ($inline) {
         $output = trim($output);
     }
     $status->value = $output;
     return $status;
 }
Exemplo n.º 19
0
	/**
	 * @params include:
	 *  - sectionsByWiki      : A map of wiki IDs to section names.
	 *                          Wikis will default to using the section "default".
	 *  - partitionsBySection : Map of section names to maps of (partition name => weight).
	 *                          A section called 'default' must be defined if not all wikis
	 *                          have explicitly defined sections.
	 *  - configByPartition   : Map of queue partition names to configuration arrays.
	 *                          These configuration arrays are passed to JobQueue::factory().
	 *                          The options set here are overriden by those passed to this
	 *                          the federated queue itself (e.g. 'order' and 'claimTTL').
	 *  - partitionsNoPush    : List of partition names that can handle pop() but not push().
	 *                          This can be used to migrate away from a certain partition.
	 * @param array $params
	 */
	protected function __construct( array $params ) {
		parent::__construct( $params );
		$section = isset( $params['sectionsByWiki'][$this->wiki] )
			? $params['sectionsByWiki'][$this->wiki]
			: 'default';
		if ( !isset( $params['partitionsBySection'][$section] ) ) {
			throw new MWException( "No configuration for section '$section'." );
		}
		// Get the full partition map
		$this->partitionMap = $params['partitionsBySection'][$section];
		arsort( $this->partitionMap, SORT_NUMERIC );
		// Get the partitions jobs can actually be pushed to
		$partitionPushMap = $this->partitionMap;
		if ( isset( $params['partitionsNoPush'] ) ) {
			foreach ( $params['partitionsNoPush'] as $partition ) {
				unset( $partitionPushMap[$partition] );
			}
		}
		// Get the config to pass to merge into each partition queue config
		$baseConfig = $params;
		foreach ( array( 'class', 'sectionsByWiki',
			'partitionsBySection', 'configByPartition', 'partitionsNoPush' ) as $o )
		{
			unset( $baseConfig[$o] );
		}
		// Get the partition queue objects
		foreach ( $this->partitionMap as $partition => $w ) {
			if ( !isset( $params['configByPartition'][$partition] ) ) {
				throw new MWException( "No configuration for partition '$partition'." );
			}
			$this->partitionQueues[$partition] = JobQueue::factory(
				$baseConfig + $params['configByPartition'][$partition] );
		}
		// Get the ring of partitions to push jobs into
		$this->partitionPushRing = new HashRing( $partitionPushMap );
		// Aggregate cache some per-queue values if there are multiple partition queues
		$this->cache = count( $this->partitionMap ) > 1 ? wfGetMainCache() : new EmptyBagOStuff();
	}
Exemplo n.º 20
0
 /**
  * execute
  *
  * entry point for TaskExecutor
  *
  * @access public
  * @author eloy@wikia
  *
  * @param mixed $params default null - task data from wikia_tasks table
  *
  * @return boolean - status of operation
  */
 public function execute($params = null)
 {
     global $IP, $wgWikiaLocalSettingsPath, $wgWikiaAdminSettingsPath, $wgExtensionMessagesFiles;
     $this->mTaskID = $params->task_id;
     $this->mParams = unserialize($params->task_arguments);
     $city_id = $this->mParams["city_id"];
     $command = $this->mParams["command"];
     $type = $this->mParams["type"];
     $server = $this->mParams["server"];
     $this->addLog("wgServer for this site is: {$server}");
     if ($city_id && $command) {
         $this->mWikiId = $city_id;
         /**
          * execute maintenance script
          */
         $cmd = sprintf("SERVER_ID={$city_id} php {$IP}/{$command} --server={$server} --conf {$wgWikiaLocalSettingsPath} --aconf {$wgWikiaAdminSettingsPath}");
         $this->addLog("Running {$cmd}");
         $retval = wfShellExec($cmd, $status);
         $this->addLog($retval);
         if ($type == "ACWLocal" || $type == "CWLocal") {
             $cmd = sprintf("SERVER_ID={$city_id} php {$IP}/maintenance/update.php --server={$server} --quick --nopurge --conf {$wgWikiaLocalSettingsPath} --aconf {$wgWikiaAdminSettingsPath}");
             $this->addLog("Running {$cmd}");
             $retval = wfShellExec($cmd, $status);
             $this->addLog($retval);
             $cmd = sprintf("SERVER_ID={$city_id} php {$IP}/maintenance/initStats.php --server={$server} --conf {$wgWikiaLocalSettingsPath} --aconf {$wgWikiaAdminSettingsPath}");
             $this->addLog("Running {$cmd}");
             $retval = wfShellExec($cmd, $status);
             $this->addLog($retval);
             $cmd = sprintf("SERVER_ID={$city_id} php {$IP}/maintenance/refreshLinks.php --server={$server} --new-only --conf {$wgWikiaLocalSettingsPath} --aconf {$wgWikiaAdminSettingsPath}");
             $this->addLog("Running {$cmd}");
             $retval = wfShellExec($cmd, $status);
             $this->addLog($retval);
             $this->addLog("Remove edit lock");
             $oVariable = WikiFactory::getVarByName('wgReadOnly', $city_id);
             if (isset($oVariable->cv_variable_id)) {
                 WikiFactory::removeVarById($oVariable->cv_variable_id, $city_id);
                 WikiFactory::clearCache($city_id);
             }
         }
         $dbname = WikiFactory::IDtoDB($city_id);
         $cmd = sprintf("perl /usr/wikia/backend/bin/scribe/events_local_users.pl --usedb={$dbname} ");
         $this->addLog("Running {$cmd}");
         $retval = wfShellExec($cmd, $status);
         $this->addLog($retval);
         /**
          * once again clear cache at the very end
          */
         $wgMemc = wfGetMainCache();
         $wgMemc->delete(WikiFactory::getVarsKey($city_id));
     }
     return true;
 }
Exemplo n.º 21
0
 /**
  * @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();
 }
Exemplo n.º 22
0
 public function tearDown()
 {
     // Don't screw anyone else
     F::app()->wg->Memc = wfGetMainCache();
 }
Exemplo n.º 23
0
 /**
  * @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();
 }
Exemplo n.º 24
0
 /**
  * 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;
 }
Exemplo n.º 25
0
 public function newFileFetcher()
 {
     return new CachingFileFetcher($this->gitHubFetcher === 'mediawiki' ? new MediaWikiFileFetcher() : new SimpleFileFetcher(), new CombinatoryCache(array(new SimpleInMemoryCache(), new MediaWikiCache(wfGetMainCache(), $this->cacheTime))));
 }
Exemplo n.º 26
0
 /**
  * @covers CachingSiteStore::clear
  */
 public function testClear()
 {
     $store = new CachingSiteStore(new HashSiteStore(), wfGetMainCache());
     $this->assertTrue($store->clear());
     $site = $store->getSite('enwiki');
     $this->assertNull($site);
     $sites = $store->getSites();
     $this->assertEquals(0, $sites->count());
 }
Exemplo n.º 27
0
 public function maintenance($server)
 {
     global $wgCityId, $IP;
     $cmd = sprintf("SERVER_ID={$wgCityId} php {$IP}/maintenance/update.php --server={$server} --quick --nopurge");
     $output = wfShellExec($cmd, $exitStatus);
     $this->info('run update.php', ['exitStatus' => $exitStatus, 'output' => $output]);
     $cmd = sprintf("SERVER_ID={$wgCityId} php {$IP}/maintenance/initStats.php --server={$server}");
     $output = wfShellExec($cmd, $exitStatus);
     $this->info('run initStats.php', ['exitStatus' => $exitStatus, 'output' => $output]);
     $cmd = sprintf("SERVER_ID={$wgCityId} php {$IP}/maintenance/refreshLinks.php --server={$server} --new-only");
     $output = wfShellExec($cmd, $exitStatus);
     $this->info('run refreshLinks.php', ['exitStatus' => $exitStatus, 'output' => $output]);
     $this->info("Remove edit lock");
     $variable = \WikiFactory::getVarByName('wgReadOnly', $wgCityId);
     if (isset($variable->cv_variable_id)) {
         \WikiFactory::removeVarById($variable->cv_variable_id, $wgCityId);
         \WikiFactory::clearCache($wgCityId);
     }
     $dbname = \WikiFactory::IDtoDB($wgCityId);
     $founder = $this->founder->getId();
     $cmd = sprintf("perl /usr/wikia/backend/bin/scribe/events_local_users.pl --usedb={$dbname} --user={$founder} ");
     $output = wfShellExec($cmd, $exitStatus);
     $this->info('run events_local_users.pl', ['exitStatus' => $exitStatus, 'output' => $output]);
     $wgMemc = wfGetMainCache();
     $wgMemc->delete(\WikiFactory::getVarsKey($wgCityId));
     return true;
 }
Exemplo n.º 28
0
 static function initCacheSupport()
 {
     self::$cache =& wfGetMainCache();
     if (self::$cache instanceof FakeMemCachedClient) {
         self::$realCache = false;
     }
 }
Exemplo n.º 29
0
 /**
  * If patrol is possible, output a patrol UI box. This is called from the
  * footer section of ordinary page views. If patrol is not possible or not
  * desired, does nothing.
  * Side effect: When the patrol link is build, this method will call
  * OutputPage::preventClickjacking() and load mediawiki.page.patrol.ajax.
  *
  * @return bool
  */
 public function showPatrolFooter()
 {
     global $wgUseNPPatrol, $wgUseRCPatrol, $wgEnableAPI, $wgEnableWriteAPI;
     $outputPage = $this->getContext()->getOutput();
     $user = $this->getContext()->getUser();
     $cache = wfGetMainCache();
     $rc = false;
     if (!$this->getTitle()->quickUserCan('patrol', $user) || !($wgUseRCPatrol || $wgUseNPPatrol)) {
         // Patrolling is disabled or the user isn't allowed to
         return false;
     }
     // New page patrol: Get the timestamp of the oldest revison which
     // the revision table holds for the given page. Then we look
     // whether it's within the RC lifespan and if it is, we try
     // to get the recentchanges row belonging to that entry
     // (with rc_new = 1).
     if ($this->mRevision && !RecentChange::isInRCLifespan($this->mRevision->getTimestamp(), 21600)) {
         // The current revision is already older than what could be in the RC table
         // 6h tolerance because the RC might not be cleaned out regularly
         return false;
     }
     // Check for cached results
     $key = wfMemcKey('NotPatrollablePage', $this->getTitle()->getArticleID());
     if ($cache->get($key)) {
         return false;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $oldestRevisionTimestamp = $dbr->selectField('revision', 'MIN( rev_timestamp )', array('rev_page' => $this->getTitle()->getArticleID()), __METHOD__);
     if ($oldestRevisionTimestamp && RecentChange::isInRCLifespan($oldestRevisionTimestamp, 21600)) {
         // 6h tolerance because the RC might not be cleaned out regularly
         $rc = RecentChange::newFromConds(array('rc_new' => 1, 'rc_timestamp' => $oldestRevisionTimestamp, 'rc_namespace' => $this->getTitle()->getNamespace(), 'rc_cur_id' => $this->getTitle()->getArticleID()), __METHOD__, array('USE INDEX' => 'new_name_timestamp'));
     } else {
         // Cache the information we gathered above in case we can't patrol
         // Don't cache in case we can patrol as this could change
         $cache->set($key, '1');
     }
     if (!$rc) {
         // Don't cache: This can be hit if the page gets accessed very fast after
         // its creation or in case we have high slave lag. In case the revision is
         // too old, we will already return above.
         return false;
     }
     if ($rc->getAttribute('rc_patrolled')) {
         // Patrolled RC entry around
         // Cache the information we gathered above in case we can't patrol
         // Don't cache in case we can patrol as this could change
         $cache->set($key, '1');
         return false;
     }
     if ($rc->getPerformer()->equals($user)) {
         // Don't show a patrol link for own creations. If the user could
         // patrol them, they already would be patrolled
         return false;
     }
     $rcid = $rc->getAttribute('rc_id');
     $token = $user->getEditToken($rcid);
     $outputPage->preventClickjacking();
     if ($wgEnableAPI && $wgEnableWriteAPI && $user->isAllowed('writeapi')) {
         $outputPage->addModules('mediawiki.page.patrol.ajax');
     }
     $link = Linker::linkKnown($this->getTitle(), wfMessage('markaspatrolledtext')->escaped(), array(), array('action' => 'markpatrolled', 'rcid' => $rcid, 'token' => $token));
     $outputPage->addHTML("<div class='patrollink'>" . wfMessage('markaspatrolledlink')->rawParams($link)->escaped() . '</div>');
     return true;
 }
Exemplo n.º 30
0
 public function getLagTimes($serverIndexes, $wiki)
 {
     if (count($serverIndexes) == 1 && reset($serverIndexes) == 0) {
         // Single server only, just return zero without caching
         return array(0 => 0);
     }
     $section = new ProfileSection(__METHOD__);
     $expiry = 5;
     $requestRate = 10;
     global $wgMemc;
     if (empty($wgMemc)) {
         $wgMemc = wfGetMainCache();
     }
     $masterName = $this->parent->getServerName(0);
     $memcKey = wfMemcKey('lag_times', $masterName);
     $times = $wgMemc->get($memcKey);
     if (is_array($times)) {
         # Randomly recache with probability rising over $expiry
         $elapsed = time() - $times['timestamp'];
         $chance = max(0, ($expiry - $elapsed) * $requestRate);
         if (mt_rand(0, $chance) != 0) {
             unset($times['timestamp']);
             // hide from caller
             return $times;
         }
         wfIncrStats('lag_cache_miss_expired');
     } else {
         wfIncrStats('lag_cache_miss_absent');
     }
     # Cache key missing or expired
     if ($wgMemc->add("{$memcKey}:lock", 1, 10)) {
         # Let this process alone update the cache value
         $unlocker = new ScopedCallback(function () use($wgMemc, $memcKey) {
             $wgMemc->delete($memcKey);
         });
     } elseif (is_array($times)) {
         # Could not acquire lock but an old cache exists, so use it
         unset($times['timestamp']);
         // hide from caller
         return $times;
     }
     $times = array();
     foreach ($serverIndexes as $i) {
         if ($i == 0) {
             # Master
             $times[$i] = 0;
         } elseif (false !== ($conn = $this->parent->getAnyOpenConnection($i))) {
             $times[$i] = $conn->getLag();
         } elseif (false !== ($conn = $this->parent->openConnection($i, $wiki))) {
             $times[$i] = $conn->getLag();
         }
     }
     # Add a timestamp key so we know when it was cached
     $times['timestamp'] = time();
     $wgMemc->set($memcKey, $times, $expiry + 10);
     unset($times['timestamp']);
     // hide from caller
     return $times;
 }