function recursiveParseArray($array) { static $recurseLevel = 0; $recurseLevel++; if ($recurseLevel > 90) { print var_dump($array); die(wfBacktrace()); } global $subject, $rootPost; if (is_array($array) && isset($array['title'])) { $subject = $array['title']; recursiveParseArray($array['content']); $rootPost = null; } elseif (is_array($array) && isset($array['user'])) { // We have a post. $t = createPost($array, $subject, $rootPost); if (!$rootPost) { $rootPost = $t; } } elseif (is_array($array)) { foreach ($array as $info) { recursiveParseArray($info); } $rootPost = null; } $recurseLevel--; }
function wfCheckPAD($url, $pad) { global $wgServer, $wgTitle, $wgCookieDomain; if ($wgServer == "http://testers.wikihow.com") { return true; } if (($wgServer == "http://www.wikihow.com" || strpos(wfHostname(), "wikihow.com") !== false) && strpos($pad, "whstatic") === false) { $alerts = new MailAddress("*****@*****.**"); // format of date to correspond to varnish file 04/Dec/2010:07:19:06 -0800 $now = date("d/M/Y:h:i:s O"); $subject = "Not using PAD for thumbnail on " . wfHostname() . " - " . $now; $body = "article {$wgTitle->getFullURL()}\n\n\nUrl: {$url} \n\n \npad {$pad} \n\n\nserver variables " . print_r($_SERVER, true) . "\n\n allheaders: " . print_r(getallheaders(), true) . "\n\n wgserver {$wgServer}\n\ncookie domain {$wgCookieDomain}\n\n Title " . print_r($wgTitle, true) . "\n\nbacktrace: " . strip_tags(wfBacktrace()); UserMailer::send($alerts, $alerts, $subject, $body, $alerts); error_log($body); wfDebug($body); } return true; }
/** * Simple one line backtrace logger * * @example Wikia::logBacktrace(__METHOD__); * @author Maciej Brencz <*****@*****.**> * * @param String $method - use __METHOD__ * * @deprecated use WikiaLogger instead */ public static function logBacktrace($method) { $backtrace = trim(strip_tags(wfBacktrace())); $message = str_replace("\n", '/', $backtrace); // add URL when logging from AJAX requests if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['SCRIPT_URL'] === '/wikia.php') { $message .= " URL: {$_SERVER['REQUEST_URI']}"; } Wikia::log($method, false, $message, true); }
private function skippedNamespace($obj) { if ($obj instanceof Title) { $ns = $obj->getNamespace(); } elseif ($obj instanceof Revision) { $ns = $obj->getTitle()->getNamespace(); } elseif ($obj instanceof WikiRevision) { $ns = $obj->title->getNamespace(); } else { echo wfBacktrace(); $this->error("Cannot get namespace of object in " . __METHOD__, true); } return is_array($this->nsFilter) && !in_array($ns, $this->nsFilter); }
/** * @param string $expect * @param string $query */ protected function reportExpectationViolated($expect, $query) { global $wgRequest; $n = $this->expect[$expect]; $by = $this->expectBy[$expect]; $this->logger->info("[{$wgRequest->getMethod()}] Expectation ({$expect} <= {$n}) by {$by} not met:\n{$query}\n" . wfBacktrace(true)); }
/** * Usually aborts on failure. If errors are explicitly ignored, returns success. * * @param $sql String: SQL query * @param $fname String: Name of the calling function, for profiling/SHOW PROCESSLIST * comment (you can use __METHOD__ or add some extra info) * @param $tempIgnore Bool: Whether to avoid throwing an exception on errors... * maybe best to catch the exception instead? * @return true for a successful write query, ResultWrapper object for a successful read query, * or false on failure if $tempIgnore set * @throws DBQueryError Thrown when the database returns an error of any kind */ public function query($sql, $fname = '', $tempIgnore = false) { global $wgProfiling; // XXADDED by Reuben to log slower queries global $wgCommandLineMode; $LOG_SLOW = 30; $startTime = microtime(true); if ($wgProfiling) { # generalizeSQL will probably cut down the query to reasonable # logging size most of the time. The substr is really just a sanity check. # Who's been wasting my precious column space? -- TS #$profName = 'query: ' . $fname . ' ' . substr( Database::generalizeSQL( $sql ), 0, 255 ); if (is_null($this->getLBInfo('master'))) { $queryProf = 'query: ' . substr(Database::generalizeSQL($sql), 0, 255); $totalProf = 'Database::query'; } else { $queryProf = 'query-m: ' . substr(Database::generalizeSQL($sql), 0, 255); $totalProf = 'Database::query-master'; } wfProfileIn($totalProf); wfProfileIn($queryProf); } $this->mLastQuery = $sql; # Add a comment for easy SHOW PROCESSLIST interpretation #if ( $fname ) { global $wgUser; if (is_object($wgUser) && !$wgUser instanceof StubObject) { $userName = $wgUser->getName(); if (mb_strlen($userName) > 15) { $userName = mb_substr($userName, 0, 15) . '...'; } $userName = str_replace('/', '', $userName); } else { $userName = ''; } $commentedSql = preg_replace('/\\s/', " /* {$fname} {$userName} */ ", $sql, 1); #} else { # $commentedSql = $sql; #} # If DBO_TRX is set, start a transaction if ($this->mFlags & DBO_TRX && !$this->trxLevel() && $sql != 'BEGIN' && $sql != 'COMMIT' && $sql != 'ROLLBACK') { // avoid establishing transactions for SHOW and SET statements too - // that would delay transaction initializations to once connection // is really used by application $sqlstart = substr($sql, 0, 10); // very much worth it, benchmark certified(tm) if (strpos($sqlstart, "SHOW ") !== 0 and strpos($sqlstart, "SET ") !== 0) { $this->begin(); } } if ($this->debug()) { $sqlx = substr($commentedSql, 0, 500); $sqlx = strtr($sqlx, "\t\n", ' '); wfDebug("SQL: {$sqlx}\n"); } # Do the query and handle errors $ret = $this->doQuery($commentedSql); # Try reconnecting if the connection was lost if (false === $ret && ($this->lastErrno() == 2013 || $this->lastErrno() == 2006)) { # Transaction is gone, like it or not $this->mTrxLevel = 0; wfDebug("Connection lost, reconnecting...\n"); if ($this->ping()) { wfDebug("Reconnected\n"); $sqlx = substr($commentedSql, 0, 500); $sqlx = strtr($sqlx, "\t\n", ' '); global $wgRequestTime; $elapsed = round(microtime(true) - $wgRequestTime, 3); wfLogDBError("Connection lost and reconnected after {$elapsed}s, query: {$sqlx}\n"); $ret = $this->doQuery($commentedSql); } else { wfDebug("Failed\n"); } // XXCHANGED -- Reuben hack: we've found that our database drivers timeout // after 10 minutes of inactivity in a long-running script. We've found that // the mysql_ping() that's called right now doesn't work to reconnect, but // that closing and re-opening the connection usually works. if (false === $ret && $this->lastErrno() == 2006) { error_log('Encountered Reuben MySQL error 2006 DB hack. Re-connecting to server ' . $this->mServer); @$this->close(); $this->mConn = null; $this->open($this->mServer, $this->mUser, $this->mPassword, $this->mDBname); $this->ping(); $ret = $this->doQuery($commentedSql); } } if (false === $ret) { $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore); } if (!defined('IS_PROD_EN_SITE')) { define('IS_PROD_EN_SITE', true); } if (!$wgCommandLineMode && IS_PROD_EN_SITE && $LOG_SLOW > 0) { $total = microtime(true) - $startTime; if ($total >= $LOG_SLOW) { $prof = substr($sql, 0, 1000); $totalStr = sprintf('%.2f', $total) . 's'; $backtrace = wfBacktrace(); $hostname = gethostname(); if (strpos($hostname, 'spare') === false) { $msg = "This query took {$totalStr}:<br>\n<br>\n{$prof}<br>\n<br>\n{$backtrace}<br>\nGenerated on {$hostname}<br>\n"; $headers = 'MIME-Version: 1.0' . "\r\n"; $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n"; mail('reuben@wikihow.com,jordan@wikihow.com', 'Slow query: ' . $totalStr, $msg, $headers); } } } if ($wgProfiling) { wfProfileOut($queryProf); wfProfileOut($totalProf); } return $this->resultObject($ret); }
/** * Work out the IP address based on various globals * For trusted proxies, use the XFF client IP (first of the chain) * @return string */ function wfGetIP() { global $wgIP; # Return cached result if (!empty($wgIP)) { return $wgIP; } /* collect the originating ips */ # Client connecting to this webserver if (isset($_SERVER['REMOTE_ADDR'])) { $ipchain = array(IP::canonicalize($_SERVER['REMOTE_ADDR'])); } else { # Running on CLI? $ipchain = array('127.0.0.1'); } $ip = $ipchain[0]; # Append XFF on to $ipchain $forwardedFor = wfGetForwardedFor(); if (isset($forwardedFor)) { $xff = array_map('trim', explode(',', $forwardedFor)); $xff = array_reverse($xff); $ipchain = array_merge($ipchain, $xff); } # Step through XFF list and find the last address in the list which is a trusted server # Set $ip to the IP address given by that trusted server, unless the address is not sensible (e.g. private) foreach ($ipchain as $i => $curIP) { $curIP = IP::canonicalize($curIP); if (wfIsTrustedProxy($curIP)) { if (isset($ipchain[$i + 1]) && IP::isPublic($ipchain[$i + 1])) { $ip = $ipchain[$i + 1]; } } else { break; } } if (strpos($ip, "192.168.100") !== false) { $msg = "wfGetIP: Bad IP {$ip} " . print_r($_SERVER, true) . print_r($wgUser, true) . wfBacktrace() . "\n"; wfDebug($msg); } wfDebug("IP: {$ip}\n"); $wgIP = $ip; return $ip; }
/** * Really opens a connection. Uncached. * Returns a Database object whether or not the connection was successful. * @access private * * @param array $server * @param bool $dbNameOverride * @throws MWException * @return DatabaseBase */ protected function reallyOpenConnection($server, $dbNameOverride = false) { if (!is_array($server)) { throw new MWException('You must update your load-balancing configuration. ' . 'See DefaultSettings.php entry for $wgDBservers.'); } if ($dbNameOverride !== false) { $server['dbname'] = $dbNameOverride; } // Log when many connection are made on requests if (++$this->connsOpened >= self::CONN_HELD_WARN_THRESHOLD) { $masterAddr = $this->getServerName(0); wfDebugLog('DBPerformance', __METHOD__ . ": " . "{$this->connsOpened}+ connections made (master={$masterAddr})\n" . wfBacktrace(true)); } # Create object try { $db = DatabaseBase::factory($server['type'], $server); } catch (DBConnectionError $e) { // FIXME: This is probably the ugliest thing I have ever done to // PHP. I'm half-expecting it to segfault, just out of disgust. -- TS $db = $e->db; } $db->setLBInfo($server); if (isset($server['fakeSlaveLag'])) { $db->setFakeSlaveLag($server['fakeSlaveLag']); } if (isset($server['fakeMaster'])) { $db->setFakeMaster(true); } return $db; }
/** * Show a warning that $function is deprecated. * This will send it to the following locations: * - Debug toolbar, with one item per function and caller, if $wgDebugToolbar * is set to true. * - PHP's error log, with level E_USER_DEPRECATED, if $wgDevelopmentWarnings * is set to true. * - MediaWiki's debug log, if $wgDevelopmentWarnings is set to false. * * @since 1.19 * @param string $function Function that is deprecated. * @param string|bool $version Version in which the function was deprecated. * @param string|bool $component Component to which the function belongs. * If false, it is assumbed the function is in MediaWiki core. * @param $callerOffset integer: How far up the callstack is the original * caller. 2 = function that called the function that called * MWDebug::deprecated() (Added in 1.20). * @return mixed */ public static function deprecated($function, $version = false, $component = false, $callerOffset = 2) { $callerDescription = self::getCallerDescription($callerOffset); $callerFunc = $callerDescription['func']; $sendToLog = true; // Check to see if there already was a warning about this function if (isset(self::$deprecationWarnings[$function][$callerFunc])) { return; } elseif (isset(self::$deprecationWarnings[$function])) { if (self::$enabled) { $sendToLog = false; } else { return; } } self::$deprecationWarnings[$function][$callerFunc] = true; if ($version) { global $wgDeprecationReleaseLimit; if ($wgDeprecationReleaseLimit && $component === false) { # Strip -* off the end of $version so that branches can use the # format #.##-branchname to avoid issues if the branch is merged into # a version of MediaWiki later than what it was branched from $comparableVersion = preg_replace('/-.*$/', '', $version); # If the comparableVersion is larger than our release limit then # skip the warning message for the deprecation if (version_compare($wgDeprecationReleaseLimit, $comparableVersion, '<')) { $sendToLog = false; } } $component = $component === false ? 'MediaWiki' : $component; $msg = "Use of {$function} was deprecated in {$component} {$version}."; } else { $msg = "Use of {$function} is deprecated."; } if ($sendToLog) { global $wgDevelopmentWarnings; // we could have a more specific $wgDeprecationWarnings setting. self::sendMessage($msg, $callerDescription, 'deprecated', $wgDevelopmentWarnings ? E_USER_DEPRECATED : false); } if (self::$enabled) { $logMsg = htmlspecialchars($msg) . Html::rawElement('div', array('class' => 'mw-debug-backtrace'), Html::element('span', array(), 'Backtrace:') . wfBacktrace()); self::$log[] = array('msg' => $logMsg, 'type' => 'deprecated', 'caller' => $callerFunc); } }
/** * Die with a backtrace * This is meant as a debugging aid to track down where bad data comes from. * Shouldn't be used in production code except maybe in "shouldn't happen" areas. * * @param string $msg Message shown when dieing. */ function wfDebugDieBacktrace($msg = '') { global $wgCommandLineMode; $backtrace = wfBacktrace(); if ($backtrace !== false) { if ($wgCommandLineMode) { $msg .= "\nBacktrace:\n{$backtrace}"; } else { $msg .= "\n<p>Backtrace:</p>\n{$backtrace}"; } } echo $msg; die(-1); }
/** * What is the length of this page? * Uses link cache, adding it if necessary * * @param $flags Int a bit field; may be Title::GAID_FOR_UPDATE to select for update * @return Int */ public function getLength($flags = 0) { if ($this->mLength != -1) { return $this->mLength; } # Calling getArticleID() loads the field from cache as needed if (!$this->getArticleID($flags)) { return $this->mLength = 0; } $linkCache = LinkCache::singleton(); $cached = $linkCache->getGoodLinkFieldObj($this, 'length'); if ($cached === null) { # check the assumption that the cache actually knows about this title # XXX: this does apparently happen, see https://bugzilla.wikimedia.org/show_bug.cgi?id=37209 # as a stop gap, perhaps log this, but don't throw an exception? wfDebug("LinkCache doesn't currently know about this title: " . $this->getPrefixedDBkey()); wfDebug(wfBacktrace()); } $this->mLength = intval($cached); return $this->mLength; }
/** * Invalidate a set of IDs, right now */ function invalidateIDs(ResultWrapper $res) { global $wgUseFileCache, $wgUseSquid; if ($res->numRows() == 0) { return; } $dbw = wfGetDB(DB_MASTER); $timestamp = $dbw->timestamp(); $done = false; while (!$done) { # Get all IDs in this query into an array $ids = array(); for ($i = 0; $i < $this->mRowsPerQuery; $i++) { $row = $res->fetchRow(); if ($row) { $ids[] = $row[0]; } else { $done = true; break; } } if (!count($ids)) { break; } # Update page_touched $dbw->update('page', array('page_touched' => $timestamp), array('page_id IN (' . $dbw->makeList($ids) . ')'), __METHOD__); wfDebug(date("r") . " PURGE invalidng ids " . print_r($ids, true) . "\n"); wfDebug(wfBacktrace()); # Update squid if ($wgUseSquid || $wgUseFileCache) { $titles = Title::newFromIDs($ids); if ($wgUseSquid) { $u = SquidUpdate::newFromTitles($titles); $u->doUpdate(); } # Update file cache if ($wgUseFileCache) { foreach ($titles as $title) { $cm = new HTMLFileCache($title); @unlink($cm->fileCacheName()); } } } } }
/** * Adds a depreciation entry to the log, along with a backtrace * * @param $function * @param $version * @param $component * @return mixed */ public static function deprecated($function, $version, $component) { if (!self::$enabled) { return; } // Chain: This function -> wfDeprecated -> deprecatedFunction -> caller $caller = wfGetCaller(4); // Check to see if there already was a warning about this function $functionString = "{$function}-{$caller}"; if (in_array($functionString, self::$deprecationWarnings)) { return; } $version = $version === false ? '(unknown version)' : $version; $component = $component === false ? 'MediaWiki' : $component; $msg = htmlspecialchars("Use of function {$function} was deprecated in {$component} {$version}"); $msg .= Html::rawElement('div', array('class' => 'mw-debug-backtrace'), Html::element('span', array(), 'Backtrace:') . wfBacktrace()); self::$deprecationWarnings[] = $functionString; self::$log[] = array('msg' => $msg, 'type' => 'deprecated', 'caller' => $caller); }
/** * Initialize (if necessary) and return a session token value * which can be used in edit forms to show that the user's * login credentials aren't being hijacked with a foreign form * submission. * * @param mixed $salt - Optional function-specific data for hash. * Use a string or an array of strings. * @return string * @public */ function editToken($salt = '') { if ($this->isAnon()) { return EDIT_TOKEN_SUFFIX; } else { if (!isset($_SESSION['wsEditToken'])) { $token = $this->generateToken(); $_SESSION['wsEditToken'] = $token; // debug $_SESSION['wsEditToken_set'] = wfTimestampNow(); $_SESSION['wsEditToken_hostname'] = wfHostname(); $_SESSION['wsEditToken_debug'] = "Hostname:\n" . wfHostname() . "\nSession ID: " . session_id() . "\nGET:\n" . print_r($_GET, true) . "\nPOST:\n" . print_r($_POST, true) . "\n" . wfBacktrace(); } else { $token = $_SESSION['wsEditToken']; } if (is_array($salt)) { $salt = implode('|', $salt); } return md5($token . $salt) . EDIT_TOKEN_SUFFIX; } }
/** * @param Language|StubUserLang $language * @param UsageAccumulator $usageAccumulator * * @return LanguageAwareRenderer * @throws MWException */ private function newLanguageAwareRenderer($language, UsageAccumulator $usageAccumulator) { if (!$language instanceof Language) { wfDebugLog('T107711', get_class($language) . ' is not a Language object.', 'all', array('trace' => wfBacktrace(true))); } StubUserLang::unstub($language); $entityStatementsRenderer = new StatementTransclusionInteractor($language, $this->propertyIdResolver, $this->snaksFinder, $this->newSnakFormatterForLanguage($language, $usageAccumulator), $this->entityLookup); return new LanguageAwareRenderer($language, $entityStatementsRenderer); }
/** * Run an SQL query and return the result. Normally throws a DBQueryError * on failure. If errors are ignored, returns false instead. * * In new code, the query wrappers select(), insert(), update(), delete(), * etc. should be used where possible, since they give much better DBMS * independence and automatically quote or validate user input in a variety * of contexts. This function is generally only useful for queries which are * explicitly DBMS-dependent and are unsupported by the query wrappers, such * as CREATE TABLE. * * However, the query wrappers themselves should call this function. * * @param string $sql SQL query * @param string $fname Name of the calling function, for profiling/SHOW PROCESSLIST * comment (you can use __METHOD__ or add some extra info) * @param bool $tempIgnore Whether to avoid throwing an exception on errors... * maybe best to catch the exception instead? * @throws MWException * @return bool|ResultWrapper True for a successful write query, ResultWrapper object * for a successful read query, or false on failure if $tempIgnore set */ public function query($sql, $fname = __METHOD__, $tempIgnore = false) { global $wgUser; $this->mLastQuery = $sql; $isWriteQuery = $this->isWriteQuery($sql); if ($isWriteQuery) { $reason = $this->getReadOnlyReason(); if ($reason !== false) { throw new DBReadOnlyError($this, "Database is read-only: {$reason}"); } # Set a flag indicating that writes have been done $this->mDoneWrites = microtime(true); } # Add a comment for easy SHOW PROCESSLIST interpretation if (is_object($wgUser) && $wgUser->isItemLoaded('name')) { $userName = $wgUser->getName(); if (mb_strlen($userName) > 15) { $userName = mb_substr($userName, 0, 15) . '...'; } $userName = str_replace('/', '', $userName); } else { $userName = ''; } // Add trace comment to the begin of the sql string, right after the operator. // Or, for one-word queries (like "BEGIN" or COMMIT") add it to the end (bug 42598) $commentedSql = preg_replace('/\\s|$/', " /* {$fname} {$userName} */ ", $sql, 1); if (!$this->mTrxLevel && $this->getFlag(DBO_TRX) && $this->isTransactableQuery($sql)) { $this->begin(__METHOD__ . " ({$fname})"); $this->mTrxAutomatic = true; } # Keep track of whether the transaction has write queries pending if ($this->mTrxLevel && !$this->mTrxDoneWrites && $isWriteQuery) { $this->mTrxDoneWrites = true; $this->getTransactionProfiler()->transactionWritingIn($this->mServer, $this->mDBname, $this->mTrxShortId); } $isMaster = !is_null($this->getLBInfo('master')); # generalizeSQL will probably cut down the query to reasonable # logging size most of the time. The substr is really just a sanity check. if ($isMaster) { $queryProf = 'query-m: ' . substr(DatabaseBase::generalizeSQL($sql), 0, 255); $totalProf = 'DatabaseBase::query-master'; } else { $queryProf = 'query: ' . substr(DatabaseBase::generalizeSQL($sql), 0, 255); $totalProf = 'DatabaseBase::query'; } # Include query transaction state $queryProf .= $this->mTrxShortId ? " [TRX#{$this->mTrxShortId}]" : ""; $profiler = Profiler::instance(); if (!$profiler instanceof ProfilerStub) { $totalProfSection = $profiler->scopedProfileIn($totalProf); $queryProfSection = $profiler->scopedProfileIn($queryProf); } if ($this->debug()) { wfDebugLog('queries', sprintf("%s: %s", $this->mDBname, $sql)); } $queryId = MWDebug::query($sql, $fname, $isMaster); # Avoid fatals if close() was called $this->assertOpen(); # Do the query and handle errors $startTime = microtime(true); $ret = $this->doQuery($commentedSql); $queryRuntime = microtime(true) - $startTime; # Log the query time and feed it into the DB trx profiler $this->getTransactionProfiler()->recordQueryCompletion($queryProf, $startTime, $isWriteQuery, $this->affectedRows()); MWDebug::queryTime($queryId); # Try reconnecting if the connection was lost if (false === $ret && $this->wasErrorReissuable()) { # Transaction is gone, like it or not $hadTrx = $this->mTrxLevel; // possible lost transaction $this->mTrxLevel = 0; $this->mTrxIdleCallbacks = array(); // bug 65263 $this->mTrxPreCommitCallbacks = array(); // bug 65263 wfDebug("Connection lost, reconnecting...\n"); # Stash the last error values since ping() might clear them $lastError = $this->lastError(); $lastErrno = $this->lastErrno(); if ($this->ping()) { wfDebug("Reconnected\n"); $server = $this->getServer(); $msg = __METHOD__ . ": lost connection to {$server}; reconnected"; wfDebugLog('DBPerformance', "{$msg}:\n" . wfBacktrace(true)); if ($hadTrx) { # Leave $ret as false and let an error be reported. # Callers may catch the exception and continue to use the DB. $this->reportQueryError($lastError, $lastErrno, $sql, $fname, $tempIgnore); } else { # Should be safe to silently retry (no trx and thus no callbacks) $startTime = microtime(true); $ret = $this->doQuery($commentedSql); $queryRuntime = microtime(true) - $startTime; # Log the query time and feed it into the DB trx profiler $this->getTransactionProfiler()->recordQueryCompletion($queryProf, $startTime, $isWriteQuery, $this->affectedRows()); } } else { wfDebug("Failed\n"); } } if (false === $ret) { $this->reportQueryError($this->lastError(), $this->lastErrno(), $sql, $fname, $tempIgnore); } $res = $this->resultObject($ret); // Destroy profile sections in the opposite order to their creation ScopedCallback::consume($queryProfSection); ScopedCallback::consume($totalProfSection); if ($isWriteQuery && $this->mTrxLevel) { $this->mTrxWriteDuration += $queryRuntime; } return $res; }
/** * Wait for a slave DB to reach a specified master position * * This will connect to the master to get an accurate position if $pos is not given * * @param IDatabase $conn Slave DB * @param DBMasterPos|bool $pos Master position; default: current position * @param integer $timeout Timeout in seconds * @return bool Success * @since 1.27 */ public function safeWaitForMasterPos(IDatabase $conn, $pos = false, $timeout = 10) { if ($this->getServerCount() == 1 || !$conn->getLBInfo('slave')) { return true; // server is not a slave DB } $pos = $pos ?: $this->getConnection(DB_MASTER)->getMasterPos(); if (!$pos) { return false; // something is misconfigured } $result = $conn->masterPosWait($pos, $timeout); if ($result == -1 || is_null($result)) { $msg = __METHOD__ . ": Timed out waiting on {$conn->getServer()} pos {$pos}"; wfDebugLog('replication', "{$msg}\n"); wfDebugLog('DBPerformance', "{$msg}:\n" . wfBacktrace(true)); $ok = false; } else { wfDebugLog('replication', __METHOD__ . ": Done\n"); $ok = true; } return $ok; }
/** * Really opens a connection. Uncached. * Returns a Database object whether or not the connection was successful. * @access private * * @param array $server * @param bool $dbNameOverride * @throws MWException * @return DatabaseBase */ protected function reallyOpenConnection($server, $dbNameOverride = false) { if (!is_array($server)) { throw new MWException('You must update your load-balancing configuration. ' . 'See DefaultSettings.php entry for $wgDBservers.'); } if ($dbNameOverride !== false) { $server['dbname'] = $dbNameOverride; } // Let the handle know what the cluster master is (e.g. "db1052") $masterName = $this->getServerName(0); $server['clusterMasterHost'] = $masterName; // Log when many connection are made on requests if (++$this->connsOpened >= self::CONN_HELD_WARN_THRESHOLD) { wfDebugLog('DBPerformance', __METHOD__ . ": " . "{$this->connsOpened}+ connections made (master={$masterName})\n" . wfBacktrace(true)); } # Create object try { $db = DatabaseBase::factory($server['type'], $server); } catch (DBConnectionError $e) { // FIXME: This is probably the ugliest thing I have ever done to // PHP. I'm half-expecting it to segfault, just out of disgust. -- TS $db = $e->db; } $db->setLBInfo($server); $db->setLazyMasterHandle($this->getLazyConnectionRef(DB_MASTER, array(), $db->getWikiID())); $db->setTransactionProfiler($this->trxProfiler); return $db; }
/** * @param $oname * @param $val * @deprecated use set(Global|Local)Preference set(Global|Local)Attribute or set(Global|Local)Flag */ public function setOption($oname, $val) { $this->warning("calling setOption", ["class" => "user", "type" => "setoption", "source" => wfBacktrace(true)]); $this->setOptionHelper($oname, $val); }
/** * @param string $expect * @param string $query * @param string|float|int $actual [optional] */ protected function reportExpectationViolated($expect, $query, $actual = null) { $n = $this->expect[$expect]; $by = $this->expectBy[$expect]; $actual = $actual !== null ? " (actual: {$actual})" : ""; $this->logger->info("Expectation ({$expect} <= {$n}) by {$by} not met{$actual}:\n{$query}\n" . wfBacktrace(true)); }
/** * Debugging function that prints a value and an optional backtrace * @param $value mixed Value to print * @param $name string Description of the printed value * @param $backtrace bool If true, print a backtrace */ public static function debugPrint($value, $name = 'unknown', $backtrace = false) { print "\n\n<pre><b>Debugging value '{$name}':</b>\n\n"; var_export($value); if ($backtrace) { print "\n" . wfBacktrace(); } print "\n</pre>\n"; }
/** * Simple one line backtrace logger * * @example Wikia::logBacktrace(__METHOD__); * @author Maciej Brencz <*****@*****.**> * * @param String $method - use __METHOD__ */ public static function logBacktrace($method) { $backtrace = trim(strip_tags(wfBacktrace())); $message = str_replace("\n", '/', $backtrace); Wikia::log($method, false, $message, true); }