public static function merge(BloomCache $bcache, $domain, $virtualKey, array $status) { $limit = 1000; $dbr = wfGetDB(DB_SLAVE, array(), $domain); $res = $dbr->select('logging', array('log_namespace', 'log_title', 'log_id', 'log_timestamp'), array('log_id > ' . $dbr->addQuotes((int) $status['lastID'])), __METHOD__, array('ORDER BY' => 'log_id', 'LIMIT' => $limit)); $updates = array(); if ($res->numRows() > 0) { $members = array(); foreach ($res as $row) { $members[] = "{$virtualKey}:{$row->log_namespace}:{$row->log_title}"; } $lastID = $row->log_id; $lastTime = $row->log_timestamp; if (!$bcache->add('shared', $members)) { return false; } $updates['lastID'] = $lastID; $updates['asOfTime'] = wfTimestamp(TS_UNIX, $lastTime); } else { $updates['asOfTime'] = microtime(true); } $updates['epoch'] = $status['epoch'] ?: microtime(true); $bcache->setStatus($virtualKey, $updates); return $updates; }
public function execute() { $type = $this->getOption('filter'); $domain = $this->getOption('domain'); $bcache = BloomCache::get($this->getOption('cache')); $delay = $this->getOption('delay', 100000.0); if (!method_exists("BloomFilter{$type}", 'merge')) { $this->error("No \"BloomFilter{$type}::merge\" method found.", 1); } $virtualKey = "{$domain}:{$type}"; $status = $bcache->getStatus($virtualKey); if ($status == false) { $this->error("Could not query virtual bloom filter '{$virtualKey}'.", 1); } $startTime = microtime(true); $this->output("Current timestamp is '{$startTime}'.\n"); $this->output("Current filter timestamp is '{$status['asOfTime']}'.\n"); do { $status = call_user_func_array(array("BloomFilter{$type}", 'merge'), array($bcache, $domain, $virtualKey, $status)); if ($status == false) { $this->error("Could not query virtual bloom filter '{$virtualKey}'.", 1); } $this->output("Filter updated to timestamp '{$status['asOfTime']}'.\n"); usleep($delay); } while ($status['asOfTime'] && $status['asOfTime'] < $startTime); $this->output("Done, filter {$type} of domain {$domain} reached time '{$startTime}'.\n"); }
protected function tearDown() { parent::tearDown(); $fcache = BloomCache::get('main'); if ($fcache instanceof BloomCacheRedis) { $fcache->delete("unit-testing-" . self::$suffix); } }
/** * @params include: * - redisServers : list of servers (address:<port>) (the first is the master) * - redisConf : additional redis configuration * * @param array $config */ public function __construct(array $config) { parent::__construct($config); $redisConf = $config['redisConfig']; $redisConf['serializer'] = 'none'; // manage that in this class $this->redisPool = RedisConnectionPool::singleton($redisConf); $this->servers = $config['redisServers']; $this->lockMgr = new RedisLockManager(array('lockServers' => array('srv1' => $this->servers[0]), 'srvsByBucket' => array(0 => array('srv1')), 'redisConfig' => $config['redisConfig'])); }
public function __construct(array $config) { parent::__construct(array('cacheId' => 'none')); }
/** * Show the error text for a missing article. For articles in the MediaWiki * namespace, show the default message text. To be called from Article::view(). */ public function showMissingArticle() { global $wgSend404Code; $outputPage = $this->getContext()->getOutput(); // Whether the page is a root user page of an existing user (but not a subpage) $validUserPage = false; $title = $this->getTitle(); # Show info in user (talk) namespace. Does the user exist? Is he blocked? if ($title->getNamespace() == NS_USER || $title->getNamespace() == NS_USER_TALK) { $parts = explode('/', $title->getText()); $rootPart = $parts[0]; $user = User::newFromName($rootPart, false); $ip = User::isIP($rootPart); $block = Block::newFromTarget($user, $user); if (!($user && $user->isLoggedIn()) && !$ip) { # User does not exist $outputPage->wrapWikiMsg("<div class=\"mw-userpage-userdoesnotexist error\">\n\$1\n</div>", array('userpage-userdoesnotexist-view', wfEscapeWikiText($rootPart))); } elseif (!is_null($block) && $block->getType() != Block::TYPE_AUTO) { # Show log extract if the user is currently blocked LogEventsList::showLogExtract($outputPage, 'block', MWNamespace::getCanonicalName(NS_USER) . ':' . $block->getTarget(), '', array('lim' => 1, 'showIfEmpty' => false, 'msgKey' => array('blocked-notice-logextract', $user->getName()))); $validUserPage = !$title->isSubpage(); } else { $validUserPage = !$title->isSubpage(); } } wfRunHooks('ShowMissingArticle', array($this)); // Give extensions a chance to hide their (unrelated) log entries $logTypes = array('delete', 'move'); $conds = array("log_action != 'revision'"); wfRunHooks('Article::MissingArticleConditions', array(&$conds, $logTypes)); # Show delete and move logs $member = $title->getNamespace() . ':' . $title->getDBkey(); // @todo: move optimization to showLogExtract()? if (BloomCache::get('main')->check(wfWikiId(), 'TitleHasLogs', $member)) { LogEventsList::showLogExtract($outputPage, $logTypes, $title, '', array('lim' => 10, 'conds' => $conds, 'showIfEmpty' => false, 'msgKey' => array('moveddeleted-notice'))); } if (!$this->mPage->hasViewableContent() && $wgSend404Code && !$validUserPage) { // If there's no backing content, send a 404 Not Found // for better machine handling of broken links. $this->getContext()->getRequest()->response()->header("HTTP/1.1 404 Not Found"); } // Also apply the robot policy for nonexisting pages (even if a 404 was used for sanity) $policy = $this->getRobotPolicy('view'); $outputPage->setIndexPolicy($policy['index']); $outputPage->setFollowPolicy($policy['follow']); $hookResult = wfRunHooks('BeforeDisplayNoArticleText', array($this)); if (!$hookResult) { return; } # Show error message $oldid = $this->getOldID(); if ($oldid) { $text = wfMessage('missing-revision', $oldid)->plain(); } elseif ($title->getNamespace() === NS_MEDIAWIKI) { // Use the default message text $text = $title->getDefaultMessageText(); } elseif ($title->quickUserCan('create', $this->getContext()->getUser()) && $title->quickUserCan('edit', $this->getContext()->getUser())) { $message = $this->getContext()->getUser()->isLoggedIn() ? 'noarticletext' : 'noarticletextanon'; $text = wfMessage($message)->plain(); } else { $text = wfMessage('noarticletext-nopermission')->plain(); } $text = "<div class='noarticletext'>\n{$text}\n</div>"; $outputPage->addWikiText($text); }
/** * Inserts the entry into the logging table. * @param IDatabase $dbw * @return int ID of the log entry * @throws MWException */ public function insert(IDatabase $dbw = null) { global $wgContLang; $dbw = $dbw ?: wfGetDB(DB_MASTER); $id = $dbw->nextSequenceValue('logging_log_id_seq'); if ($this->timestamp === null) { $this->timestamp = wfTimestampNow(); } # Trim spaces on user supplied text $comment = trim($this->getComment()); # Truncate for whole multibyte characters. $comment = $wgContLang->truncate($comment, 255); $data = array('log_id' => $id, 'log_type' => $this->getType(), 'log_action' => $this->getSubtype(), 'log_timestamp' => $dbw->timestamp($this->getTimestamp()), 'log_user' => $this->getPerformer()->getId(), 'log_user_text' => $this->getPerformer()->getName(), 'log_namespace' => $this->getTarget()->getNamespace(), 'log_title' => $this->getTarget()->getDBkey(), 'log_page' => $this->getTarget()->getArticleID(), 'log_comment' => $comment, 'log_params' => serialize((array) $this->getParameters())); if (isset($this->deleted)) { $data['log_deleted'] = $this->deleted; } $dbw->insert('logging', $data, __METHOD__); $this->id = !is_null($id) ? $id : $dbw->insertId(); $rows = array(); foreach ($this->relations as $tag => $values) { if (!strlen($tag)) { throw new MWException("Got empty log search tag."); } if (!is_array($values)) { $values = array($values); } foreach ($values as $value) { $rows[] = array('ls_field' => $tag, 'ls_value' => $value, 'ls_log_id' => $this->id); } } if (count($rows)) { $dbw->insert('log_search', $rows, __METHOD__, 'IGNORE'); } // Update any bloom filter cache $member = $this->getTarget()->getNamespace() . ':' . $this->getTarget()->getDBkey(); BloomCache::get('main')->insert(wfWikiId(), 'TitleHasLogs', $member); return $this->id; }