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--;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
 /**
  * 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);
 }
Ejemplo n.º 4
0
 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));
 }
Ejemplo n.º 6
0
 /**
  * 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);
 }
Ejemplo n.º 7
0
/**
 * 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;
}
Ejemplo n.º 8
0
 /**
  * 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;
 }
Ejemplo n.º 9
0
 /**
  * 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);
     }
 }
Ejemplo n.º 10
0
/**
 * 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);
}
Ejemplo n.º 11
0
 /**
  * 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;
 }
Ejemplo n.º 12
0
 /**
  * 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());
                 }
             }
         }
     }
 }
Ejemplo n.º 13
0
 /**
  * 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);
 }
Ejemplo n.º 14
0
 /**
  * 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);
 }
Ejemplo n.º 16
0
 /**
  * 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;
 }
Ejemplo n.º 17
0
 /**
  * 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;
 }
Ejemplo n.º 18
0
 /**
  * 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;
 }
Ejemplo n.º 19
0
 /**
  * @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);
 }
Ejemplo n.º 20
0
 /**
  * @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));
 }
Ejemplo n.º 21
0
 /**
  * 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";
 }
Ejemplo n.º 22
0
 /**
  * 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);
 }