/**
  * Update the query cache as needed
  *
  * @param DatabaseBase $dbw
  * @param int $days How many days user must be idle before he is considered inactive
  * @param int $window Maximum time range of new data to scan (in seconds)
  * @return int|bool UNIX timestamp the cache is now up-to-date as of (false on error)
  */
 protected static function doQueryCacheUpdate(DatabaseBase $dbw, $days, $window)
 {
     $lockKey = wfWikiID() . '-activeusers';
     if (!$dbw->lock($lockKey, __METHOD__, 1)) {
         return false;
         // exclusive update (avoids duplicate entries)
     }
     $now = time();
     $cTime = $dbw->selectField('querycache_info', 'qci_timestamp', array('qci_type' => 'activeusers'));
     $cTimeUnix = $cTime ? wfTimestamp(TS_UNIX, $cTime) : 1;
     // Pick the date range to fetch from. This is normally from the last
     // update to till the present time, but has a limited window for sanity.
     // If the window is limited, multiple runs are need to fully populate it.
     $sTimestamp = max($cTimeUnix, $now - $days * 86400);
     $eTimestamp = min($sTimestamp + $window, $now);
     // Get all the users active since the last update
     $res = $dbw->select(array('recentchanges'), array('rc_user_text', 'lastedittime' => 'MAX(rc_timestamp)'), array('rc_user > 0', 'rc_type != ' . $dbw->addQuotes(RC_EXTERNAL), 'rc_log_type IS NULL OR rc_log_type != ' . $dbw->addQuotes('newusers'), 'rc_timestamp >= ' . $dbw->addQuotes($dbw->timestamp($sTimestamp)), 'rc_timestamp <= ' . $dbw->addQuotes($dbw->timestamp($eTimestamp))), __METHOD__, array('GROUP BY' => array('rc_user_text'), 'ORDER BY' => 'NULL'));
     $names = array();
     foreach ($res as $row) {
         $names[$row->rc_user_text] = $row->lastedittime;
     }
     // Rotate out users that have not edited in too long (according to old data set)
     $dbw->delete('querycachetwo', array('qcc_type' => 'activeusers', 'qcc_value < ' . $dbw->addQuotes($now - $days * 86400)), __METHOD__);
     // Find which of the recently active users are already accounted for
     if (count($names)) {
         $res = $dbw->select('querycachetwo', array('user_name' => 'qcc_title'), array('qcc_type' => 'activeusers', 'qcc_namespace' => NS_USER, 'qcc_title' => array_keys($names)), __METHOD__);
         foreach ($res as $row) {
             unset($names[$row->user_name]);
         }
     }
     // Insert the users that need to be added to the list (which their last edit time
     if (count($names)) {
         $newRows = array();
         foreach ($names as $name => $lastEditTime) {
             $newRows[] = array('qcc_type' => 'activeusers', 'qcc_namespace' => NS_USER, 'qcc_title' => $name, 'qcc_value' => wfTimestamp(TS_UNIX, $lastEditTime), 'qcc_namespacetwo' => 0, 'qcc_titletwo' => '');
         }
         foreach (array_chunk($newRows, 500) as $rowBatch) {
             $dbw->insert('querycachetwo', $rowBatch, __METHOD__);
             if (!$dbw->trxLevel()) {
                 wfWaitForSlaves();
             }
         }
     }
     // Touch the data freshness timestamp
     $dbw->replace('querycache_info', array('qci_type'), array('qci_type' => 'activeusers', 'qci_timestamp' => $dbw->timestamp($eTimestamp)), __METHOD__);
     $dbw->unlock($lockKey, __METHOD__);
     return $eTimestamp;
 }
 /**
  * Update the usage count in the property statistics table for all
  * properties. This function also initialises the required entry for
  * all properties that have IDs in the SMW IDs table.
  *
  * @since 1.8
  * @param boolean $verbose
  * @param DatabaseBase $dbw used for writing
  */
 protected function refreshPropertyStatistics($verbose, $dbw)
 {
     $this->reportProgress("Updating property statistics. This may take a while.\n", $verbose);
     $res = $dbw->select(SMWSql3SmwIds::tableName, array('smw_id', 'smw_title'), array('smw_namespace' => SMW_NS_PROPERTY), __METHOD__);
     $propertyTables = SMWSQLStore3::getPropertyTables();
     foreach ($res as $row) {
         $this->reportProgress('.', $verbose);
         $usageCount = 0;
         foreach ($propertyTables as $propertyTable) {
             if ($propertyTable->isFixedPropertyTable() && $propertyTable->getFixedProperty() != $row->smw_title) {
                 // This table cannot store values for this property
                 continue;
             }
             $propRow = $dbw->selectRow($propertyTable->getName(), 'Count(*) as count', $propertyTable->isFixedPropertyTable() ? array() : array('p_id' => $row->smw_id), __METHOD__);
             $usageCount += $propRow->count;
         }
         $dbw->replace(SMWSQLStore3::PROPERTY_STATISTICS_TABLE, 'p_id', array('p_id' => $row->smw_id, 'usage_count' => $usageCount), __METHOD__);
     }
     $this->reportProgress("\nUpdated statistics for {$res->numRows()} Properties.\n", $verbose);
     $dbw->freeResult($res);
 }
 /**
  * Create some initial DB entries for important built-in properties. Having the DB contents predefined
  * allows us to safe DB calls when certain data is needed. At the same time, the entries in the DB
  * make sure that DB-based functions work as with all other properties.
  */
 protected function setupPredefinedProperties($verbose, DatabaseBase $db)
 {
     global $wgDBtype;
     $this->reportProgress("Setting up internal property indices ...\n", $verbose);
     // Check if we already have this structure
     $borderiw = $db->selectField(SMWSQLStore3::ID_TABLE, 'smw_iw', 'smw_id=' . $db->addQuotes(\SMWSql3SmwIds::FXD_PROP_BORDER_ID));
     if ($borderiw != SMW_SQL3_SMWBORDERIW) {
         $this->reportProgress("   ... allocating space for internal properties ...\n", $verbose);
         $this->store->smwIds->moveSMWPageID(\SMWSql3SmwIds::FXD_PROP_BORDER_ID);
         // make sure position 50 is empty
         $db->insert(SMWSQLStore3::ID_TABLE, array('smw_id' => \SMWSql3SmwIds::FXD_PROP_BORDER_ID, 'smw_title' => '', 'smw_namespace' => 0, 'smw_iw' => SMW_SQL3_SMWBORDERIW, 'smw_subobject' => '', 'smw_sortkey' => ''), 'SMW::setup');
         // put dummy "border element" on index 50
         $this->reportProgress('   ', $verbose);
         for ($i = 0; $i < \SMWSql3SmwIds::FXD_PROP_BORDER_ID; $i++) {
             // make way for built-in ids
             $this->store->smwIds->moveSMWPageID($i);
             $this->reportProgress('.', $verbose);
         }
         $this->reportProgress("   done.\n", $verbose);
     } else {
         $this->reportProgress("   ... space for internal properties already allocated.\n", $verbose);
     }
     // now write actual properties; do that each time, it is cheap enough and we can update sortkeys by current language
     $this->reportProgress("   ... writing entries for internal properties ...", $verbose);
     foreach (SMWSql3SmwIds::$special_ids as $prop => $id) {
         $p = new SMWDIProperty($prop);
         $db->replace(SMWSQLStore3::ID_TABLE, array('smw_id'), array('smw_id' => $id, 'smw_title' => $p->getKey(), 'smw_namespace' => SMW_NS_PROPERTY, 'smw_iw' => $this->store->smwIds->getPropertyInterwiki($p), 'smw_subobject' => '', 'smw_sortkey' => $p->getLabel()), 'SMW::setup');
     }
     $this->reportProgress(" done.\n", $verbose);
     if ($wgDBtype == 'postgres') {
         $sequenceIndex = SMWSQLStore3::ID_TABLE . '_smw_id_seq';
         $this->reportProgress(" ... updating {$sequenceIndex} sequence accordingly.\n", $verbose);
         $max = $db->selectField(SMWSQLStore3::ID_TABLE, 'max(smw_id)', array(), __METHOD__);
         $max += 1;
         $db->query("ALTER SEQUENCE {$sequenceIndex} RESTART WITH {$max}", __METHOD__);
     }
     $this->reportProgress("Internal properties initialized successfully.\n", $verbose);
 }
Esempio n. 4
0
 function replace($table, $uniqueIndexes, $rows, $fname = 'DatabaseSqlite::replace')
 {
     if (!count($rows)) {
         return true;
     }
     # SQLite can't handle multi-row replaces, so divide up into multiple single-row queries
     if (isset($rows[0]) && is_array($rows[0])) {
         $ret = true;
         foreach ($rows as $k => $v) {
             if (!parent::replace($table, $uniqueIndexes, $v, "{$fname}/multi-row")) {
                 $ret = false;
             }
         }
     } else {
         $ret = parent::replace($table, $uniqueIndexes, $rows, "{$fname}/single-row");
     }
     return $ret;
 }