Exemplo n.º 1
0
 /**
  * Shut down, close connections and destroy the cached instance.
  * 
  */
 static function destroyInstance()
 {
     if (self::$instance) {
         self::$instance->shutdown();
         self::$instance->forEachLBCallMethod('closeAll');
         self::$instance = null;
     }
 }
Exemplo n.º 2
0
 /**
  * @dataProvider getLBFactoryClassProvider
  */
 public function testGetLBFactoryClass($expected, $deprecated)
 {
     $mockDB = $this->getMockBuilder('DatabaseMysql')->disableOriginalConstructor()->getMock();
     $config = array('class' => $deprecated, 'connection' => $mockDB, 'sectionsByDB' => array(), 'sectionLoads' => array(), 'serverTemplate' => array());
     $this->hideDeprecated('$wgLBFactoryConf must be updated. See RELEASE-NOTES for details');
     $result = LBFactory::getLBFactoryClass($config);
     $this->assertEquals($expected, $result);
 }
Exemplo n.º 3
0
 /**
  * @param array $conf An associative array with one member:
  *  - connection: The IDatabase connection object
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     if (!isset($conf['connection'])) {
         throw new InvalidArgumentException("Missing 'connection' argument.");
     }
     $lb = new LoadBalancerSingle(array_merge($this->baseLoadBalancerParams(), $conf));
     $this->initLoadBalancer($lb);
     $this->lb = $lb;
 }
Exemplo n.º 4
0
 /**
  * @see LBFactory::__construct()
  * @param array $conf Parameters of LBFactory::__construct() as well as:
  *   - servers : list of server configuration maps to Database::factory().
  *      Additionally, the server maps should have a 'load' key, which is used to decide
  *      how often clients connect to one server verses the others. A 'max lag' key should
  *      also be set on server maps, indicating how stale the data can be before the load
  *      balancer tries to avoid using it. The map can have 'is static' set to disable blocking
  *      replication sync checks (intended for archive servers with unchanging data).
  *   - externalClusters : map of cluster names to server arrays. The servers arrays have the
  *      same format as "servers" above.
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->servers = isset($conf['servers']) ? $conf['servers'] : [];
     foreach ($this->servers as $i => $server) {
         if ($i == 0) {
             $this->servers[$i]['master'] = true;
         } else {
             $this->servers[$i]['replica'] = true;
         }
     }
     $this->externalClusters = isset($conf['externalClusters']) ? $conf['externalClusters'] : [];
     $this->loadMonitorClass = isset($conf['loadMonitorClass']) ? $conf['loadMonitorClass'] : 'LoadMonitor';
 }
Exemplo n.º 5
0
 /**
  * Handle some last-minute setup here.
  */
 public function finalSetup()
 {
     global $wgCommandLineMode, $wgShowSQLErrors, $wgServer;
     global $wgDBadminuser, $wgDBadminpassword;
     global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf;
     # Turn off output buffering again, it might have been turned on in the settings files
     if (ob_get_level()) {
         ob_end_flush();
     }
     # Same with these
     $wgCommandLineMode = true;
     # Override $wgServer
     if ($this->hasOption('server')) {
         $wgServer = $this->getOption('server', $wgServer);
     }
     # If these were passed, use them
     if ($this->mDbUser) {
         $wgDBadminuser = $this->mDbUser;
     }
     if ($this->mDbPass) {
         $wgDBadminpassword = $this->mDbPass;
     }
     if ($this->getDbType() == self::DB_ADMIN && isset($wgDBadminuser)) {
         $wgDBuser = $wgDBadminuser;
         $wgDBpassword = $wgDBadminpassword;
         if ($wgDBservers) {
             /**
              * @var $wgDBservers array
              */
             foreach ($wgDBservers as $i => $server) {
                 $wgDBservers[$i]['user'] = $wgDBuser;
                 $wgDBservers[$i]['password'] = $wgDBpassword;
             }
         }
         if (isset($wgLBFactoryConf['serverTemplate'])) {
             $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
             $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
         }
         LBFactory::destroyInstance();
     }
     $this->afterFinalSetup();
     $wgShowSQLErrors = true;
     @set_time_limit(0);
     $this->adjustMemoryLimit();
 }
Exemplo n.º 6
0
 /**
  * @param array $conf An associative array with one member:
  *  - connection: The DatabaseBase connection object
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->lb = new LoadBalancerSingle(['readOnlyReason' => $this->readOnlyReason, 'trxProfiler' => $this->trxProfiler] + $conf);
 }
Exemplo n.º 7
0
 /**
  * @param DeferrableUpdate $update
  * @param LBFactory $lbFactory
  * @param integer $stage
  * @return ErrorPageError|null
  */
 private static function runUpdate(DeferrableUpdate $update, LBFactory $lbFactory, $stage)
 {
     $guiError = null;
     try {
         $fnameTrxOwner = get_class($update) . '::doUpdate';
         $lbFactory->beginMasterChanges($fnameTrxOwner);
         $update->doUpdate();
         $lbFactory->commitMasterChanges($fnameTrxOwner);
     } catch (Exception $e) {
         // Reporting GUI exceptions does not work post-send
         if ($e instanceof ErrorPageError && $stage === self::PRESEND) {
             $guiError = $e;
         }
         MWExceptionHandler::rollbackMasterChangesAndLog($e);
     }
     return $guiError;
 }
Exemplo n.º 8
0
 /**
  * Handle some last-minute setup here.
  */
 public function finalSetup()
 {
     global $wgCommandLineMode, $wgShowSQLErrors, $wgServer;
     global $wgDBadminuser, $wgDBadminpassword;
     global $wgDBuser, $wgDBpassword, $wgDBservers, $wgLBFactoryConf;
     # Turn off output buffering again, it might have been turned on in the settings files
     if (ob_get_level()) {
         ob_end_flush();
     }
     # Same with these
     $wgCommandLineMode = true;
     # Override $wgServer
     if ($this->hasOption('server')) {
         $wgServer = $this->getOption('server', $wgServer);
     }
     # If these were passed, use them
     if ($this->mDbUser) {
         $wgDBadminuser = $this->mDbUser;
     }
     if ($this->mDbPass) {
         $wgDBadminpassword = $this->mDbPass;
     }
     if ($this->getDbType() == self::DB_ADMIN && isset($wgDBadminuser)) {
         $wgDBuser = $wgDBadminuser;
         $wgDBpassword = $wgDBadminpassword;
         if ($wgDBservers) {
             /**
              * @var $wgDBservers array
              */
             foreach ($wgDBservers as $i => $server) {
                 $wgDBservers[$i]['user'] = $wgDBuser;
                 $wgDBservers[$i]['password'] = $wgDBpassword;
             }
         }
         if (isset($wgLBFactoryConf['serverTemplate'])) {
             $wgLBFactoryConf['serverTemplate']['user'] = $wgDBuser;
             $wgLBFactoryConf['serverTemplate']['password'] = $wgDBpassword;
         }
         LBFactory::destroyInstance();
     }
     $this->afterFinalSetup();
     $wgShowSQLErrors = true;
     // @codingStandardsIgnoreStart Allow error supppression. wfSuppressWarnings()
     // is not avaiable.
     @set_time_limit(0);
     // @codingStandardsIgnoreStart
     $this->adjustMemoryLimit();
     // Per-script profiling; useful for debugging
     $forcedProfiler = $this->getOption('profiler');
     if ($forcedProfiler === 'text') {
         Profiler::setInstance(new ProfilerSimpleText(array()));
         Profiler::instance()->setTemplated(true);
     } elseif ($forcedProfiler === 'trace') {
         Profiler::setInstance(new ProfilerSimpleTrace(array()));
         Profiler::instance()->setTemplated(true);
     }
 }
Exemplo n.º 9
0
 protected function exportGroup(MessageGroup $group, $multi = false)
 {
     // Make sure all existing connections are dead,
     // we can't use them in forked children.
     LBFactory::destroyInstance();
     $server = TTMServer::primary();
     $id = $group->getId();
     $sourceLanguage = $group->getSourceLanguage();
     if ($multi) {
         $stats = MessageGroupStats::forGroup($id);
         $this->statusLine("Loaded stats for {$id}\n");
     } else {
         $this->statusLine("Loading stats... ", 4);
         $stats = MessageGroupStats::forGroup($id);
         $this->output("done!", 4);
         $this->statusLine("Inserting sources: ", 5);
     }
     $collection = $group->initCollection($sourceLanguage);
     $collection->filter('ignored');
     $collection->filter('optional');
     $collection->initMessages();
     $sids = array();
     $counter = 0;
     foreach ($collection->keys() as $mkey => $title) {
         $def = $collection[$mkey]->definition();
         $sids[$mkey] = $server->insertSource($title, $sourceLanguage, $def);
         if (++$counter % $this->mBatchSize === 0 && !$multi) {
             wfWaitForSlaves(10);
             $this->output('.', 5);
         }
     }
     $total = count($sids);
     if ($multi) {
         $this->statusLine("Inserted {$total} source entries for {$id}\n");
     } else {
         $this->output("{$total} entries", 5);
         $this->statusLine("Inserting translations...", 6);
     }
     $dbw = $server->getDB(DB_MASTER);
     foreach ($stats as $targetLanguage => $numbers) {
         if ($targetLanguage === $sourceLanguage) {
             continue;
         }
         if ($numbers[MessageGroupStats::TRANSLATED] === 0) {
             continue;
         }
         if (!$multi) {
             $this->output(sprintf("%19s  ", $targetLanguage), $targetLanguage);
         }
         $collection->resetForNewLanguage($targetLanguage);
         $collection->filter('ignored');
         $collection->filter('optional');
         $collection->filter('translated', false);
         $collection->loadTranslations();
         $inserts = array();
         foreach ($collection->keys() as $mkey => $title) {
             $inserts[] = array('tmt_sid' => $sids[$mkey], 'tmt_lang' => $targetLanguage, 'tmt_text' => $collection[$mkey]->translation());
         }
         do {
             $batch = array_splice($inserts, 0, $this->mBatchSize);
             $dbw->insert('translate_tmt', $batch, __METHOD__);
             if (!$multi) {
                 $this->output('.', $targetLanguage);
             }
             wfWaitForSlaves(10);
         } while (count($inserts));
     }
     if ($multi) {
         $this->statusLine("Inserted translations for {$id}\n");
     }
 }
Exemplo n.º 10
0
/**
 * Get the load balancer factory object
 *
 * @return LBFactory
 */
function wfGetLBFactory()
{
    return LBFactory::singleton();
}
 protected function resetStateForFork()
 {
     // Child, reseed because there is no bug in PHP:
     // http://bugs.php.net/bug.php?id=42465
     mt_srand(getmypid());
     // Make sure all existing connections are dead,
     // we can't use them in forked children.
     LBFactory::destroyInstance();
 }
Exemplo n.º 12
0
 private function scriptDone($script)
 {
     global $wgDBuser, $wgDBpassword, $wgDBadminuser, $wgDBadminpassword, $wgDBuserold, $wgDBpasswordold;
     if ($script->getDbType() === Maintenance::DB_ADMIN && isset($wgDBadminuser)) {
         $wgDBuser = $wgDBuserold;
         $wgDBpassword = $wgDBpasswordold;
         unset($GLOBALS['wgDBuserold'], $GLOBALS['wgDBpasswordold']);
         LBFactory::destroyInstance();
     }
     $goptions = $this->metadata[$this->type]['option'];
     $gargs = $this->metadata[$this->type]['arg'];
     if ($goptions != array()) {
         foreach ($goptions as $a) {
             if ($a['type'] == 'textarea' && $a['tmpfile'] && file_exists($a['tmpfile'])) {
                 unlink($a['tmpfile']);
             }
         }
     }
     if ($gargs != array()) {
         foreach ($gargs as $a) {
             if ($a['type'] == 'textarea' && $a['tmpfile'] && file_exists($a['tmpfile'])) {
                 unlink($a['tmpfile']);
             }
         }
     }
 }
Exemplo n.º 13
0
 /**
  * @see LBFactory::__construct()
  *
  * Template override precedence (highest => lowest):
  *   - templateOverridesByServer
  *   - masterTemplateOverrides
  *   - templateOverridesBySection/templateOverridesByCluster
  *   - externalTemplateOverrides
  *   - serverTemplate
  * Overrides only work on top level keys (so nested values will not be merged).
  *
  * Server configuration maps should be of the format Database::factory() requires.
  * Additionally, a 'max lag' key should also be set on server maps, indicating how stale the
  * data can be before the load balancer tries to avoid using it. The map can have 'is static'
  * set to disable blocking  replication sync checks (intended for archive servers with
  * unchanging data).
  *
  * @param array $conf Parameters of LBFactory::__construct() as well as:
  *   - sectionsByDB                Map of database names to section names.
  *   - sectionLoads                2-d map. For each section, gives a map of server names to
  *                                 load ratios. For example:
  *                                 [
  *                                     'section1' => [
  *                                         'db1' => 100,
  *                                         'db2' => 100
  *                                     ]
  *                                 ]
  *   - serverTemplate              Server configuration map intended for Database::factory().
  *                                 Note that "host", "hostName" and "load" entries will be
  *                                 overridden by "sectionLoads" and "hostsByName".
  *   - groupLoadsBySection         3-d map giving server load ratios for each section/group.
  *                                 For example:
  *                                 [
  *                                     'section1' => [
  *                                         'group1' => [
  *                                             'db1' => 100,
  *                                             'db2' => 100
  *                                         ]
  *                                     ]
  *                                 ]
  *   - groupLoadsByDB              3-d map giving server load ratios by DB name.
  *   - hostsByName                 Map of hostname to IP address.
  *   - externalLoads               Map of external storage cluster name to server load map.
  *   - externalTemplateOverrides   Set of server configuration maps overriding
  *                                 "serverTemplate" for external storage.
  *   - templateOverridesByServer   2-d map overriding "serverTemplate" and
  *                                 "externalTemplateOverrides" on a server-by-server basis.
  *                                 Applies to both core and external storage.
  *   - templateOverridesBySection  2-d map overriding the server configuration maps by section.
  *   - templateOverridesByCluster  2-d map overriding the server configuration maps by external
  *                                 storage cluster.
  *   - masterTemplateOverrides     Server configuration map overrides for all master servers.
  *   - loadMonitorClass            Name of the LoadMonitor class to always use.
  *   - readOnlyBySection           A map of section name to read-only message.
  *                                 Missing or false for read/write.
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->conf = $conf;
     $required = ['sectionsByDB', 'sectionLoads', 'serverTemplate'];
     $optional = ['groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer', 'templateOverridesByCluster', 'templateOverridesBySection', 'masterTemplateOverrides', 'readOnlyBySection', 'loadMonitorClass'];
     foreach ($required as $key) {
         if (!isset($conf[$key])) {
             throw new InvalidArgumentException(__CLASS__ . ": {$key} is required.");
         }
         $this->{$key} = $conf[$key];
     }
     foreach ($optional as $key) {
         if (isset($conf[$key])) {
             $this->{$key} = $conf[$key];
         }
     }
 }
Exemplo n.º 14
0
 *
 * @note As of version 1.27, MediaWiki is only beginning to use dependency injection.
 * The services defined here do not yet fully represent all services used by core,
 * much of the code still relies on global state for this accessing services.
 *
 * @since 1.27
 *
 * @see docs/injection.txt for an overview of using dependency injection in the
 *      MediaWiki code base.
 */
use MediaWiki\Interwiki\ClassicInterwikiLookup;
use MediaWiki\Linker\LinkRendererFactory;
use MediaWiki\MediaWikiServices;
return ['DBLoadBalancerFactory' => function (MediaWikiServices $services) {
    $config = $services->getMainConfig()->get('LBFactoryConf');
    $class = LBFactory::getLBFactoryClass($config);
    if (!isset($config['readOnlyReason'])) {
        // TODO: replace the global wfConfiguredReadOnlyReason() with a service.
        $config['readOnlyReason'] = wfConfiguredReadOnlyReason();
    }
    return new $class($config);
}, 'DBLoadBalancer' => function (MediaWikiServices $services) {
    // just return the default LB from the DBLoadBalancerFactory service
    return $services->getDBLoadBalancerFactory()->getMainLB();
}, 'SiteStore' => function (MediaWikiServices $services) {
    $rawSiteStore = new DBSiteStore($services->getDBLoadBalancer());
    // TODO: replace wfGetCache with a CacheFactory service.
    // TODO: replace wfIsHHVM with a capabilities service.
    $cache = wfGetCache(wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING);
    return new CachingSiteStore($rawSiteStore, $cache);
}, 'SiteLookup' => function (MediaWikiServices $services) {
Exemplo n.º 15
0
 function tearDown()
 {
     LBFactory::destroyInstance();
 }
Exemplo n.º 16
0
 /**
  * @param array $conf An associative array with one member:
  *  - connection: The DatabaseBase connection object
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->lb = new LoadBalancerSingle($conf);
 }
Exemplo n.º 17
0
 /**
  * @param array $conf An associative array with one member:
  *  - connection: The DatabaseBase connection object
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $conf['readOnlyReason'] = $this->readOnlyReason;
     $this->lb = new LoadBalancerSingle($conf);
 }
Exemplo n.º 18
0
}
$dbw = wfGetDB(DB_SLAVE);
// define socket which listens for a break signal
$socket = socket_create_listen("9876");
// port is freely chosen
socket_set_nonblock($socket);
// max number of threads to be considered to calculate sleeping time
define('MAX_THREADS_CONSIDERED', 10);
global $wgLoadBalancer;
print "-------------------------------------------------\n";
print " Running jobs... ({$rate} jobs/second)    \t\t \n";
print "-------------------------------------------------\n";
for (;;) {
    // determine the most lagged slave
    // if $lag == -1, there's no slave.
    list($host, $lag) = LBFactory::singleton()->getMainLB()->getMaxLag();
    if ($lag == -1) {
        // make sleeping time adaptive to database load.
        $runningThreads = smwfGetNumOfRunningThreads($dbw);
        $runningThreads = $runningThreads <= MAX_THREADS_CONSIDERED ? $runningThreads : MAX_THREADS_CONSIDERED;
        // wait depending on user-defined $rate and server load
        sleep(1 / $rate + $runningThreads);
    } else {
        // wait for most lagged slave to be *below* 1/$rate + 3 seconds lag time.
        wfWaitForSlaves(1 / $rate + 3);
    }
    // get next job
    $job = Job::pop();
    // is there a break signal?
    $accept_sock = @socket_accept($socket);
    if ($accept_sock !== false) {
Exemplo n.º 19
0
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->loadMonitorClass = isset($conf['loadMonitorClass']) ? $conf['loadMonitorClass'] : null;
 }
Exemplo n.º 20
0
 /**
  * execute
  *
  * Main entry point for class
  *
  * @author Krzysztof Krzyżaniak <*****@*****.**>
  *
  * @return integer: wikia id or null if wikia is not handled by WikiFactory
  */
 public function execute()
 {
     wfProfileIn(__METHOD__);
     global $wgCityId, $wgDevelEnvironment, $wgDBservers, $wgLBFactoryConf, $wgDBserver, $wgContLang;
     /**
      * Hook to allow extensions to alter the initialization.  For example,
      * setting the mCityID then returning true will override which wiki
      * to use.
      *
      * @author Sean Colombo
      */
     if (!wfRunHooks('WikiFactory::execute', array(&$this))) {
         wfProfileOut(__METHOD__);
         return $this->mWikiID;
     }
     /**
      * load balancer uses one method which demand wgContLang defined
      * See BugId: 12474
      */
     $wgContLang = new StubObject('wgContLang');
     /**
      * local cache, change to CACHE_ACCEL for local
      */
     global $wgWikiFactoryCacheType;
     $oMemc = wfGetCache($wgWikiFactoryCacheType);
     if (empty($this->mAlwaysFromDB)) {
         /**
          * remember! for http requests we only known $this->mServerName
          * (domain), $this->mCityId is unknown (set to false in constructor)
          */
         wfProfileIn(__METHOD__ . "-domaincache");
         $key = WikiFactory::getDomainKey($this->mServerName);
         $this->mDomain = $oMemc->get($key);
         $this->mDomain = isset($this->mDomain["id"]) ? $this->mDomain : array();
         $this->debug("reading from cache, key {$key}");
         wfProfileOut(__METHOD__ . "-domaincache");
     }
     if (!isset($this->mDomain["id"]) || $this->mAlwaysFromDB) {
         wfProfileIn(__METHOD__ . "-domaindb");
         /**
          * first run or cache expired
          */
         $dbr = $this->getDB();
         /**
          * interactive/cmdline case. We know city_id so we don't have to
          * ask city_domains table
          */
         if ($this->mCityID || $this->mCityDB) {
             $oRow = $dbr->selectRow(array("city_list"), array("city_id", "city_public", "city_factory_timestamp", "city_url", "city_dbname"), $this->mCityID ? array("city_list.city_id" => $this->mCityID) : array("city_list.city_dbname" => $this->mCityDB), __METHOD__ . '::domaindb');
             if (isset($oRow->city_id)) {
                 preg_match("/http[s]*\\:\\/\\/(.+)\$/", $oRow->city_url, $matches);
                 $host = rtrim($matches[1], "/");
                 $this->mCityID = $oRow->city_id;
                 $this->mWikiID = $oRow->city_id;
                 $this->mIsWikiaActive = $oRow->city_public;
                 $this->mCityHost = $host;
                 $this->mCityDB = $oRow->city_dbname;
                 $this->mTimestamp = $oRow->city_factory_timestamp;
                 $this->mDomain = array("id" => $oRow->city_id, "host" => $host, "active" => $oRow->city_public, "time" => $oRow->city_factory_timestamp, "db" => $this->mCityDB);
             }
         } else {
             /**
              * request from HTTPD case. We only know server name so we
              * have to ask city_domains table
              */
             $oRow = $dbr->selectRow(array("city_domains", "city_list"), array("city_list.city_id", "city_public", "city_factory_timestamp", "city_domain", "city_url", "city_dbname"), array("city_domains.city_id = city_list.city_id", "city_domains.city_domain" => $this->mServerName), __METHOD__ . '::servername');
             if (isset($oRow->city_id) && $oRow->city_id > 0) {
                 $oRow->city_domain = strtolower($oRow->city_domain);
                 preg_match("/http[s]*\\:\\/\\/(.+)\$/", $oRow->city_url, $matches);
                 $host = rtrim($matches[1], "/");
                 if ($oRow->city_domain == $this->mServerName && $this->mServerName) {
                     $this->mWikiID = $oRow->city_id;
                     $this->mIsWikiaActive = $oRow->city_public;
                     $this->mCityHost = $host;
                     $this->mCityDB = $oRow->city_dbname;
                     $this->mTimestamp = $oRow->city_factory_timestamp;
                     $this->mDomain = array("id" => $oRow->city_id, "host" => $host, "active" => $oRow->city_public, "time" => $oRow->city_factory_timestamp, "db" => $oRow->city_dbname);
                 }
             }
         }
         if (empty($this->mAlwaysFromDB) && !empty($this->mWikiID)) {
             /**
              * store value in cache
              */
             $oMemc->set(WikiFactory::getDomainKey($this->mServerName), $this->mDomain, $this->mExpireDomainCacheTimeout);
         }
         $this->debug("city_id={$this->mWikiID}, reading from database key {$this->mServerName}");
         wfProfileOut(__METHOD__ . "-domaindb");
     } else {
         /**
          * data taken from cache
          */
         $this->mWikiID = $this->mDomain["id"];
         $this->mCityHost = $this->mDomain["host"];
         $this->mIsWikiaActive = $this->mDomain["active"];
         $this->mTimestamp = isset($this->mDomain["time"]) ? $this->mDomain["time"] : null;
         $this->mCityDB = isset($this->mDomain["db"]) ? $this->mDomain["db"] : false;
     }
     /**
      * save default var values for Special:WikiFactory
      * @todo this should be smarter...
      */
     if ($this->mWikiID == 177) {
         $this->mSaveDefaults = true;
     }
     /**
      * redirection to another url
      */
     if ($this->mIsWikiaActive == 2) {
         $this->debug("city_id={$this->mWikiID};city_public={$this->mIsWikiaActive}), redirected to {$this->mCityHost}");
         header("X-Redirected-By-WF: 2");
         header("Location: http://{$this->mCityHost}/", true, 301);
         wfProfileOut(__METHOD__);
         exit(0);
     }
     /**
      * if $this->mCityURL different from city_url we redirect to city_url
      * (as main server)
      *
      * mCityHost may contain path after url (memory-alpha, dofus), we just
      * split this for comparing hosts.
      */
     list($host, $path) = array_pad(explode("/", $this->mCityHost, 2), 2, false);
     /**
      * check if domain from browser is different than main domain for wiki
      */
     $cond1 = !empty($host) && !empty($this->mServerName) && strtolower($host) != $this->mServerName;
     /**
      * check if not additional domain was used (then we redirect anyway)
      */
     $cond2 = !empty($host) && $this->mAlternativeDomainUsed && $host != $this->mOldServerName;
     if (($cond1 || $cond2) && empty($wgDevelEnvironment)) {
         $url = wfGetCurrentUrl();
         /**
          * now recombine url from parts
          */
         if (preg_match("!^/{$path}!", $url["path"]) == 0) {
             $url["path"] = "/{$path}" . $url["path"];
         }
         $target = $url["scheme"] . "://" . $host . $url["path"];
         $target = isset($url["query"]) ? $target . "?" . $url["query"] : $target;
         $this->debug("redirected from {$url["url"]} to {$target}");
         header("X-Redirected-By-WF: NotPrimary");
         header("Location: {$target}", true, 301);
         wfProfileOut(__METHOD__);
         exit(0);
     }
     /**
      * if wikia is not defined or is marked for closing we redirect to
      * Not_a_valid_Wikia
      * @todo the -1 status should probably be removed or defined more precisely
      */
     if (empty($this->mWikiID) || $this->mIsWikiaActive == -1) {
         if (!$this->mCommandLine) {
             global $wgNotAValidWikia;
             $this->debug("redirected to {$wgNotAValidWikia}, {$this->mWikiID} {$this->mIsWikiaActive}");
             if ($this->mIsWikiaActive < 0) {
                 header("X-Redirected-By-WF: MarkedForClosing");
             } else {
                 header("X-Redirected-By-WF: NotAValidWikia");
             }
             header("Location: {$wgNotAValidWikia}");
             wfProfileOut(__METHOD__);
             exit(0);
         }
     }
     /**
      * if wikia is disabled and is not Commandline mode we redirect it to
      * dump directory.
      */
     if (empty($this->mIsWikiaActive) || $this->mIsWikiaActive == -2) {
         if (!$this->mCommandLine) {
             global $wgNotAValidWikia;
             if ($this->mCityDB) {
                 $database = strtolower($this->mCityDB);
                 $redirect = sprintf("http://%s/wiki/Special:CloseWiki/information/%s", $wgDevelEnvironment ? "www.awc.wikia-inc.com" : "community.wikia.com", $database);
             } else {
                 $redirect = $wgNotAValidWikia;
             }
             $this->debug("disabled and not commandline, redirected to {$redirect}, {$this->mWikiID} {$this->mIsWikiaActive}");
             header("X-Redirected-By-WF: Dump");
             header("Location: {$redirect}");
             wfProfileOut(__METHOD__);
             exit(0);
         }
     }
     /**
      * for yellowikis.wikia check geolocation and for GB -> redirect to owikis
      * @author Przemek Piotrowski (Nef)
      */
     if (0 === strpos($this->mServerName, 'yellowikis.')) {
         header("X-Redirected-By-WF: Geo");
         global $wgLocationOfGeoIPDatabase;
         if (!empty($wgLocationOfGeoIPDatabase) && file_exists($wgLocationOfGeoIPDatabase)) {
             /**
              * ProxyTools methods cannot be used because PT is not loaded at this point.
              * PT cannot be just included as it requires a lot to be initialized first )-:
              *
              * Order is *important* here! Proxy are added "from the right side"
              * to the combined HTTP_X_FORWARDED_FOR + REMOTE_ADDR.
              */
             $ips = array();
             if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                 $ips = preg_split('/\\s*,\\s*/', $_SERVER['HTTP_X_FORWARDED_FOR']);
             }
             if (!empty($_SERVER['REMOTE_ADDR'])) {
                 $ips[] = $_SERVER['REMOTE_ADDR'];
             }
             if (!empty($ips[0])) {
                 require_once 'Net/GeoIP.php';
                 try {
                     $geoip = Net_GeoIP::getInstance($wgLocationOfGeoIPDatabase);
                     if ('GB' == $geoip->lookupCountryCode($ips[0])) {
                         header("X-Redirected-By-WF: Geo");
                         /**
                          * just exit, no redirect at all
                          */
                         wfProfileOut(__METHOD__);
                         exit(0);
                     }
                 } catch (Exception $e) {
                     #--- ignore exception, redirect is an option, not a necessity
                 }
             }
         }
     }
     /**
      * get info about city variables from memcached and then check,
      * maybe memcached is down and returned only error code
      */
     if (empty($this->mAlwaysFromDB)) {
         wfProfileIn(__METHOD__ . "-varscache");
         /**
          * first from serialized file
          */
         $key = WikiFactory::getVarsKey($this->mWikiID);
         $data = $oMemc->get($key);
         if (isset($data["stamp"]) && $data["stamp"] == $this->mTimestamp) {
             $this->mVariables = isset($data["data"]) && is_array($data["data"]) ? $data["data"] : array();
             $this->debug("wikifactory: reading from cache, key {$key}, count " . count($this->mVariables));
         } else {
             $this->debug("wikifactory: timestamp doesn't match. Cache expired");
         }
         wfProfileOut(__METHOD__ . "-varscache");
     }
     /**
      * if wgDBname is not defined we get all variables from database
      */
     if (!isset($this->mVariables["wgDBname"])) {
         wfProfileIn(__METHOD__ . "-varsdb");
         $dbr = $this->getDB();
         $oRes = $dbr->select(array("city_variables", "city_variables_pool"), array("cv_name", "cv_value"), array("cv_id = cv_variable_id", "cv_city_id = {$this->mWikiID}"), __METHOD__ . '::varsdb');
         while ($oRow = $dbr->fetchObject($oRes)) {
             #--- some magic, rewritting path, etc legacy data
             global $_variable_key, $_variable_value;
             set_error_handler("wfUnserializeHandler");
             $_variable_key = $oRow->cv_name;
             $_variable_value = $oRow->cv_value;
             $tUnserVal = unserialize($oRow->cv_value);
             restore_error_handler();
             if (!empty($wgDevelEnvironment) && $oRow->cv_name === "wgServer") {
                 /**
                  * skip this variable
                  */
                 unset($this->mVariables[$oRow->cv_name]);
                 $this->debug("{$oRow->cv_name} with value {$tUnserVal} skipped");
             } else {
                 $this->mVariables[$oRow->cv_name] = $tUnserVal;
             }
         }
         $dbr->freeResult($oRes);
         /**
          * wgArticlePath
          */
         if (!isset($this->mVariables['wgArticlePath'])) {
             $this->mVariables['wgArticlePath'] = $GLOBALS['wgArticlePath'];
         }
         /**
          * read tags for this wiki, store in global variable as array
          * @name $wgWikiFactoryTags
          */
         wfProfileIn(__METHOD__ . "-tagsdb");
         $this->mVariables["wgWikiFactoryTags"] = array();
         $sth = $dbr->select(array("city_tag", "city_tag_map"), array("id", "name"), array("city_tag.id = city_tag_map.tag_id", "city_id = {$this->mWikiID}"), __METHOD__ . '::tagsdb');
         while ($row = $dbr->fetchObject($sth)) {
             $this->mVariables["wgWikiFactoryTags"][$row->id] = $row->name;
         }
         $dbr->freeResult($sth);
         $this->debug("reading tags from database, id {$this->mWikiID}, count " . count($this->mVariables["wgWikiFactoryTags"]));
         wfProfileOut(__METHOD__ . "-tagsdb");
         if (empty($this->mAlwaysFromDB)) {
             /**
              * cache as well some values even if they are not defined in database
              * it will prevent GlobalTitle from doing empty selects
              * BugId: 12463
              */
             foreach ($this->mCacheAnyway as $cvar) {
                 if (!isset($this->mVariables[$cvar]) && isset($GLOBALS[$cvar])) {
                     $this->mVariables[$cvar] = $GLOBALS[$cvar];
                 }
             }
             /**
              * store values in memcache
              */
             $oMemc->set(WikiFactory::getVarsKey($this->mWikiID), array("stamp" => $this->mTimestamp, "data" => $this->mVariables), $this->mExpireValuesCacheTimeout);
         }
         $this->debug("reading from database, id {$this->mWikiID}, count " . count($this->mVariables));
         wfProfileOut(__METHOD__ . "-varsdb");
         /**
          * maybe upgrade database to current schema
          */
         if ($this->mCheckUpgrade === true) {
             $this->maybeUpgrade();
         }
     }
     // @author macbre
     wfRunHooks('WikiFactory::executeBeforeTransferToGlobals', array(&$this));
     /**
      * transfer configuration variables from database to GLOBALS
      */
     if (is_array($this->mVariables)) {
         foreach ($this->mVariables as $key => $value) {
             $tValue = $value;
             #--- check, maybe there are variables in variable
             if (is_string($tValue)) {
                 preg_match_all('/(\\$\\w+)[^\\w]*/', $tValue, $aMatches);
                 if (is_array($aMatches[1])) {
                     foreach ($aMatches[1] as $tKey) {
                         /**
                          * dolar sign in key should be removed
                          * (str_replace is faster than regexp)
                          */
                         $tKeyParsed = str_replace('$', '', $tKey);
                         if (!is_numeric($tKeyParsed)) {
                             #--- replace only if key is not $1, $2 etc.
                             if (array_key_exists($tKeyParsed, $this->mVariables)) {
                                 $tValue = str_replace($tKey, $this->mVariables[$tKeyParsed], $tValue);
                             } else {
                                 if (isset($GLOBALS[$tKeyParsed])) {
                                     $tValue = str_replace($tKey, $GLOBALS[$tKeyParsed], $tValue);
                                 }
                             }
                         }
                     }
                 }
             }
             /**
              * merge local values with global
              */
             switch ($key) {
                 case "wgNamespacesWithSubpagesLocal":
                     $this->LocalToGlobalArray($tValue, $GLOBALS["wgNamespacesWithSubpages"]);
                     break;
                 case "wgExtraNamespacesLocal":
                     $this->LocalToGlobalArray($tValue, $GLOBALS["wgExtraNamespaces"]);
                     break;
                 case "wgFileExtensionsLocal":
                     $this->LocalToGlobalArray($tValue, $GLOBALS["wgFileExtensions"], true);
                     break;
                 case "wgTrustedMediaFormatsLocal":
                     $this->LocalToGlobalArray($tValue, $GLOBALS["wgTrustedMediaFormats"]);
                     break;
                 case "wgFileBlacklistLocal":
                     $this->LocalToGlobalArray($tValue, $GLOBALS["wgFileBlacklist"]);
                     break;
             }
             if ($key == 'wgServer') {
                 $headers = Wikia::getAllHeaders();
                 if (array_key_exists('X-Original-Host', $headers) && !empty($headers['X-Original-Host'])) {
                     global $wgConf;
                     $tValue = 'http://' . $headers['X-Original-Host'];
                     $wgConf->localVHosts = array_merge($wgConf->localVHosts, array($headers['X-Original-Host']));
                 }
             }
             try {
                 if ($this->mSaveDefaults) {
                     $GLOBALS['wgPreWikiFactoryValues'][$key] = $tValue;
                 }
                 $GLOBALS[$key] = $tValue;
             } catch (Exception $e) {
                 #--- so far do nothing
             }
         }
     }
     $wgCityId = $this->mWikiID;
     /**
      * set/replace $wgDBname in $wgDBservers
      */
     if (isset($wgDBservers) && is_array($wgDBservers) && isset($this->mVariables["wgDBname"])) {
         foreach ($wgDBservers as $index => $server) {
             $wgDBservers[$index]["dbname"] = $this->mVariables["wgDBname"];
         }
     }
     if (isset($wgLBFactoryConf) && is_array($wgLBFactoryConf) && isset($this->mVariables["wgDBname"])) {
         $wgLBFactoryConf['serverTemplate']['dbname'] = $this->mVariables["wgDBname"];
         /**
          * set wgDBserver for cluster based on $wgLBFactoryConf
          */
         $cluster = isset($this->mVariables["wgDBcluster"]) ? $this->mVariables["wgDBcluster"] : "DEFAULT";
         if (isset($wgLBFactoryConf["sectionLoads"][$cluster])) {
             $keys = array_keys($wgLBFactoryConf["sectionLoads"][$cluster]);
             $db = array_shift($keys);
             if (isset($wgLBFactoryConf["hostsByName"][$db])) {
                 $wgDBserver = $wgLBFactoryConf["hostsByName"][$db];
                 $this->debug("wgDBserver for cluster {$cluster} set to {$wgDBserver}");
             }
         }
     }
     wfRunHooks('WikiFactory::onExecuteComplete', array(&$this));
     wfProfileOut(__METHOD__);
     /**
      * cleanup and finally return wiki id
      */
     LBFactory::destroyInstance();
     return $this->mWikiID;
 }
Exemplo n.º 21
0
 /**
  * Constructor, always call this from child classes.
  */
 public function __construct()
 {
     global $wgExtensionMessagesFiles, $wgUser;
     // Disable the i18n cache and LoadBalancer
     Language::getLocalisationCache()->disableBackend();
     LBFactory::disableBackend();
     // Load the installer's i18n file.
     $wgExtensionMessagesFiles['MediawikiInstaller'] = dirname(__FILE__) . '/Installer.i18n.php';
     // Having a user with id = 0 safeguards us from DB access via User::loadOptions().
     $wgUser = User::newFromId(0);
     $this->settings = $this->internalDefaults;
     foreach ($this->defaultVarNames as $var) {
         $this->settings[$var] = $GLOBALS[$var];
     }
     $compiledDBs = array();
     foreach (self::getDBTypes() as $type) {
         $installer = $this->getDBInstaller($type);
         if (!$installer->isCompiled()) {
             continue;
         }
         $compiledDBs[] = $type;
         $defaults = $installer->getGlobalDefaults();
         foreach ($installer->getGlobalNames() as $var) {
             if (isset($defaults[$var])) {
                 $this->settings[$var] = $defaults[$var];
             } else {
                 $this->settings[$var] = $GLOBALS[$var];
             }
         }
     }
     $this->setVar('_CompiledDBs', $compiledDBs);
     $this->parserTitle = Title::newFromText('Installer');
     $this->parserOptions = new ParserOptions();
     // language will  be wrong :(
     $this->parserOptions->setEditSection(false);
 }
 /**
  * Set up LBFactory so that wfGetDB() etc. works.
  * We set up a special LBFactory instance which returns the current
  * installer connection.
  */
 public function enableLB()
 {
     $status = $this->getConnection();
     if (!$status->isOK()) {
         throw new MWException(__METHOD__ . ': unexpected DB connection error');
     }
     LBFactory::setInstance(new LBFactory_Single(array('connection' => $status->value)));
 }
Exemplo n.º 23
0
 /**
  * Issue a commit on all masters who are currently in a transaction and have
  * made changes to the database. It also supports sometimes waiting for the
  * local wiki's replica DBs to catch up. See the documentation for
  * $wgJobSerialCommitThreshold for more.
  *
  * @param LBFactory $lbFactory
  * @param Job $job
  * @param string $fnameTrxOwner
  * @throws DBError
  */
 private function commitMasterChanges(LBFactory $lbFactory, Job $job, $fnameTrxOwner)
 {
     global $wgJobSerialCommitThreshold;
     $time = false;
     $lb = $lbFactory->getMainLB(wfWikiID());
     if ($wgJobSerialCommitThreshold !== false && $lb->getServerCount() > 1) {
         // Generally, there is one master connection to the local DB
         $dbwSerial = $lb->getAnyOpenConnection($lb->getWriterIndex());
         // We need natively blocking fast locks
         if ($dbwSerial && $dbwSerial->namedLocksEnqueue()) {
             $time = $dbwSerial->pendingWriteQueryDuration($dbwSerial::ESTIMATE_DB_APPLY);
             if ($time < $wgJobSerialCommitThreshold) {
                 $dbwSerial = false;
             }
         } else {
             $dbwSerial = false;
         }
     } else {
         // There are no replica DBs or writes are all to foreign DB (we don't handle that)
         $dbwSerial = false;
     }
     if (!$dbwSerial) {
         $lbFactory->commitMasterChanges($fnameTrxOwner);
         return;
     }
     $ms = intval(1000 * $time);
     $msg = $job->toString() . " COMMIT ENQUEUED [{$ms}ms of writes]";
     $this->logger->info($msg);
     $this->debugCallback($msg);
     // Wait for an exclusive lock to commit
     if (!$dbwSerial->lock('jobrunner-serial-commit', __METHOD__, 30)) {
         // This will trigger a rollback in the main loop
         throw new DBError($dbwSerial, "Timed out waiting on commit queue.");
     }
     $unlocker = new ScopedCallback(function () use($dbwSerial) {
         $dbwSerial->unlock('jobrunner-serial-commit', __METHOD__);
     });
     // Wait for the replica DBs to catch up
     $pos = $lb->getMasterPos();
     if ($pos) {
         $lb->waitForAll($pos);
     }
     // Actually commit the DB master changes
     $lbFactory->commitMasterChanges($fnameTrxOwner);
     ScopedCallback::consume($unlocker);
 }
Exemplo n.º 24
0
 /**
  * Set the instance to be the given object
  *
  * @param LBFactory $instance
  */
 static function setInstance($instance)
 {
     self::destroyInstance();
     self::$instance = $instance;
 }
 /**
  * @param LBFactory $lbFactory
  * @param WikiPage $page
  * @param Revision $newRev
  * @throws MWException
  */
 protected function notifyUpdatesForRevision(LBFactory $lbFactory, WikiPage $page, Revision $newRev)
 {
     $config = RequestContext::getMain()->getConfig();
     $title = $page->getTitle();
     // Get the new revision
     if (!$newRev->getContent()) {
         return;
         // deleted?
     }
     // Get the prior revision (the same for null edits)
     if ($newRev->getParentId()) {
         $oldRev = Revision::newFromId($newRev->getParentId(), Revision::READ_LATEST);
         if (!$oldRev->getContent()) {
             return;
             // deleted?
         }
     } else {
         $oldRev = null;
     }
     // Parse the new revision and get the categories
     $categoryChanges = $this->getExplicitCategoriesChanges($title, $newRev, $oldRev);
     list($categoryInserts, $categoryDeletes) = $categoryChanges;
     if (!$categoryInserts && !$categoryDeletes) {
         return;
         // nothing to do
     }
     $catMembChange = new CategoryMembershipChange($title, $newRev);
     $catMembChange->checkTemplateLinks();
     $batchSize = $config->get('UpdateRowsPerQuery');
     $insertCount = 0;
     foreach ($categoryInserts as $categoryName) {
         $categoryTitle = Title::makeTitle(NS_CATEGORY, $categoryName);
         $catMembChange->triggerCategoryAddedNotification($categoryTitle);
         if ($insertCount++ && $insertCount % $batchSize == 0) {
             $lbFactory->commitAndWaitForReplication(__METHOD__, $this->ticket);
         }
     }
     foreach ($categoryDeletes as $categoryName) {
         $categoryTitle = Title::makeTitle(NS_CATEGORY, $categoryName);
         $catMembChange->triggerCategoryRemovedNotification($categoryTitle);
         if ($insertCount++ && $insertCount++ % $batchSize == 0) {
             $lbFactory->commitAndWaitForReplication(__METHOD__, $this->ticket);
         }
     }
 }
Exemplo n.º 26
0
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->chronProt = new ChronologyProtector();
     $this->loadMonitorClass = isset($conf['loadMonitorClass']) ? $conf['loadMonitorClass'] : null;
 }
Exemplo n.º 27
0
 /**
  * Constructor, always call this from child classes.
  */
 public function __construct()
 {
     global $wgMessagesDirs, $wgUser;
     // Disable the i18n cache
     Language::getLocalisationCache()->disableBackend();
     // Disable LoadBalancer and wfGetDB etc.
     LBFactory::disableBackend();
     // Disable object cache (otherwise CACHE_ANYTHING will try CACHE_DB and
     // SqlBagOStuff will then throw since we just disabled wfGetDB)
     $GLOBALS['wgMemc'] = new EmptyBagOStuff();
     ObjectCache::clear();
     $emptyCache = array('class' => 'EmptyBagOStuff');
     $GLOBALS['wgObjectCaches'] = array(CACHE_NONE => $emptyCache, CACHE_DB => $emptyCache, CACHE_ANYTHING => $emptyCache, CACHE_MEMCACHED => $emptyCache);
     // Load the installer's i18n.
     $wgMessagesDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
     // Having a user with id = 0 safeguards us from DB access via User::loadOptions().
     $wgUser = User::newFromId(0);
     $this->settings = $this->internalDefaults;
     foreach ($this->defaultVarNames as $var) {
         $this->settings[$var] = $GLOBALS[$var];
     }
     $this->doEnvironmentPreps();
     $this->compiledDBs = array();
     foreach (self::getDBTypes() as $type) {
         $installer = $this->getDBInstaller($type);
         if (!$installer->isCompiled()) {
             continue;
         }
         $this->compiledDBs[] = $type;
     }
     $this->parserTitle = Title::newFromText('Installer');
     $this->parserOptions = new ParserOptions();
     // language will be wrong :(
     $this->parserOptions->setEditSection(false);
 }
Exemplo n.º 28
0
 /**
  * @param array $conf
  * @throws MWException
  */
 public function __construct(array $conf)
 {
     parent::__construct($conf);
     $this->chronProt = new ChronologyProtector();
     $this->conf = $conf;
     $required = array('sectionsByDB', 'sectionLoads', 'serverTemplate');
     $optional = array('groupLoadsBySection', 'groupLoadsByDB', 'hostsByName', 'externalLoads', 'externalTemplateOverrides', 'templateOverridesByServer', 'templateOverridesByCluster', 'masterTemplateOverrides', 'readOnlyBySection', 'loadMonitorClass');
     foreach ($required as $key) {
         if (!isset($conf[$key])) {
             throw new MWException(__CLASS__ . ": {$key} is required in configuration");
         }
         $this->{$key} = $conf[$key];
     }
     foreach ($optional as $key) {
         if (isset($conf[$key])) {
             $this->{$key} = $conf[$key];
         }
     }
 }
Exemplo n.º 29
0
 /**
  * Constructor, always call this from child classes.
  */
 public function __construct()
 {
     global $wgMessagesDirs, $wgUser;
     // Disable the i18n cache and LoadBalancer
     Language::getLocalisationCache()->disableBackend();
     LBFactory::disableBackend();
     // Load the installer's i18n.
     $wgMessagesDirs['MediawikiInstaller'] = __DIR__ . '/i18n';
     // Having a user with id = 0 safeguards us from DB access via User::loadOptions().
     $wgUser = User::newFromId(0);
     $this->settings = $this->internalDefaults;
     foreach ($this->defaultVarNames as $var) {
         $this->settings[$var] = $GLOBALS[$var];
     }
     $this->compiledDBs = array();
     foreach (self::getDBTypes() as $type) {
         $installer = $this->getDBInstaller($type);
         if (!$installer->isCompiled()) {
             continue;
         }
         $this->compiledDBs[] = $type;
     }
     $this->parserTitle = Title::newFromText('Installer');
     $this->parserOptions = new ParserOptions();
     // language will  be wrong :(
     $this->parserOptions->setEditSection(false);
 }