Revert r107309, r113601, r113704, r113742, r113792, r113838, r113859, r113893, r11389...
authorRoan Kattouw <catrope@users.mediawiki.org>
Wed, 21 Mar 2012 00:16:50 +0000 (00:16 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Wed, 21 Mar 2012 00:16:50 +0000 (00:16 +0000)
All of these revisions are tagged with 'gerritmigration' and will be resubmitted into Gerrit after the Gerrit switchover. See also http://lists.wikimedia.org/pipermail/wikitech-l/2012-March/059124.html

34 files changed:
includes/AutoLoader.php
includes/api/ApiFeedContributions.php
includes/db/Database.php
includes/db/DatabasePostgres.php
includes/filerepo/FileRepo.php
includes/filerepo/backend/FileBackend.php
includes/filerepo/backend/FileBackendMultiWrite.php
includes/filerepo/backend/FileBackendStore.php
includes/filerepo/backend/FileOp.php
includes/filerepo/backend/filejournal/DBFileJournal.php [deleted file]
includes/filerepo/backend/filejournal/FileJournal.php [deleted file]
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/installer/DatabaseInstaller.php
includes/installer/PostgresUpdater.php
includes/specials/SpecialBlock.php
languages/messages/MessagesEn.php
languages/messages/MessagesFrp.php
languages/messages/MessagesIg.php
languages/messages/MessagesMk.php
languages/messages/MessagesMzn.php
languages/messages/MessagesNds_nl.php
languages/messages/MessagesOr.php
languages/messages/MessagesOs.php
languages/messages/MessagesQug.php
languages/messages/MessagesSa.php
languages/messages/MessagesSr_ec.php
languages/messages/MessagesWar.php
languages/messages/MessagesYue.php
maintenance/archives/patch-filejournal.sql [deleted file]
maintenance/dumpTextPass.php
maintenance/language/messages.inc
resources/mediawiki.action/mediawiki.action.watch.ajax.js
resources/mediawiki.api/mediawiki.api.watch.js

index ca31248..4ab5de8 100644 (file)
@@ -508,9 +508,6 @@ $wgAutoloadLocalClasses = array(
        'FSFileBackendFileList' => 'includes/filerepo/backend/FSFileBackend.php',
        'SwiftFileBackend' => 'includes/filerepo/backend/SwiftFileBackend.php',
        'SwiftFileBackendFileList' => 'includes/filerepo/backend/SwiftFileBackend.php',
-       'FileJournal' => 'includes/filerepo/backend/filejournal/FileJournal.php',
-       'DBFileJournal' => 'includes/filerepo/backend/filejournal/DBFileJournal.php',
-       'NullFileJournal' => 'includes/filerepo/backend/filejournal/FileJournal.php',
        'LockManagerGroup' => 'includes/filerepo/backend/lockmanager/LockManagerGroup.php',
        'LockManager' => 'includes/filerepo/backend/lockmanager/LockManager.php',
        'ScopedLock' => 'includes/filerepo/backend/lockmanager/LockManager.php',
index 4c12e1b..5df1ff6 100644 (file)
@@ -43,80 +43,56 @@ class ApiFeedContributions extends ApiBase {
        }
 
        public function execute() {
+               $params = $this->extractRequestParams();
 
                global $wgFeed, $wgFeedClasses, $wgSitename, $wgLanguageCode;
 
-               try {
-                       $params = $this->extractRequestParams();
-                       
-                       if( !$wgFeed ) {
-                               $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' );
-                       }
-       
-                       if( !isset( $wgFeedClasses[ $params['feedformat'] ] ) ) {
-                               $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' );
-                       }
+               if( !$wgFeed ) {
+                       $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' );
+               }
 
-                       global $wgMiserMode;
-                       if ( $params['showsizediff'] && $wgMiserMode ) {
-                               $this->dieUsage( 'Size difference is disabled in Miser Mode', 'sizediffdisabled' );
-                       }
-       
-                       $msg = wfMsgForContent( 'Contributions' );
-                       $feedTitle = $wgSitename . ' - ' . $msg . ' [' . $wgLanguageCode . ']';
-                       $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL();
-       
-                       $target = $params['user'] == 'newbies'
-                                       ? 'newbies'
-                                       : Title::makeTitleSafe( NS_USER, $params['user'] )->getText();
-       
-                       $feed = new $wgFeedClasses[$params['feedformat']] (
-                               $feedTitle,
-                               htmlspecialchars( $msg ),
-                               $feedUrl
-                       );
-       
-                       $pager = new ContribsPager( $this->getContext(), array(
-                               'target' => $target,
-                               'namespace' => $params['namespace'],
-                               'year' => $params['year'],
-                               'month' => $params['month'],
-                               'tagFilter' => $params['tagfilter'],
-                               'deletedOnly' => $params['deletedonly'],
-                               'topOnly' => $params['toponly'],
-                               'showSizeDiff' => $params['showsizediff'],
-                       ) );
-       
-                       $feedItems = array();
-                       if( $pager->getNumRows() > 0 ) {
-                               foreach ( $pager->mResult as $row ) {
-                                       $feedItems[] = $this->feedItem( $row );
-                               }
-                       }
-       
-                       ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
-                       
-               } catch ( Exception $e ) {
-                       // Error results should not be cached
-                       $this->getMain()->setCacheMaxAge( 0 );
-
-                       $feedTitle = $wgSitename . ' - Error - ' . wfMsgForContent( 'contributions' ) . ' [' . $wgLanguageCode . ']';
-                       $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL();
-
-                       $feedFormat = isset( $params['feedformat'] ) ? $params['feedformat'] : 'rss';
-                       $feed = new $wgFeedClasses[$feedFormat] ( $feedTitle, htmlspecialchars( wfMsgForContent( 'contributions' ) ), $feedUrl );
-
-                       if ( $e instanceof UsageException ) {
-                               $errorCode = $e->getCodeString();
-                       } else {
-                               // Something is seriously wrong
-                               $errorCode = 'internal_api_error';
-                       }
+               if( !isset( $wgFeedClasses[ $params['feedformat'] ] ) ) {
+                       $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' );
+               }
+
+               global $wgMiserMode;
+               if ( $params['showsizediff'] && $wgMiserMode ) {
+                       $this->dieUsage( 'Size difference is disabled in Miser Mode', 'sizediffdisabled' );
+               }
+
+               $msg = wfMsgForContent( 'Contributions' );
+               $feedTitle = $wgSitename . ' - ' . $msg . ' [' . $wgLanguageCode . ']';
+               $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL();
+
+               $target = $params['user'] == 'newbies'
+                               ? 'newbies'
+                               : Title::makeTitleSafe( NS_USER, $params['user'] )->getText();
+
+               $feed = new $wgFeedClasses[$params['feedformat']] (
+                       $feedTitle,
+                       htmlspecialchars( $msg ),
+                       $feedUrl
+               );
 
-                       $errorText = $e->getMessage();
-                       $feedItems[] = new FeedItem( "Error ($errorCode)", $errorText, '', '', '' );
-                       ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
+               $pager = new ContribsPager( $this->getContext(), array(
+                       'target' => $target,
+                       'namespace' => $params['namespace'],
+                       'year' => $params['year'],
+                       'month' => $params['month'],
+                       'tagFilter' => $params['tagfilter'],
+                       'deletedOnly' => $params['deletedonly'],
+                       'topOnly' => $params['toponly'],
+                       'showSizeDiff' => $params['showsizediff'],
+               ) );
+
+               $feedItems = array();
+               if( $pager->getNumRows() > 0 ) {
+                       foreach ( $pager->mResult as $row ) {
+                               $feedItems[] = $this->feedItem( $row );
+                       }
                }
+
+               ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems );
        }
 
        protected function feedItem( $row ) {
index 5c03617..47eb596 100644 (file)
@@ -680,7 +680,7 @@ abstract class DatabaseBase implements DatabaseType {
                $dbType = strtolower( $dbType );
                $class = 'Database' . ucfirst( $dbType );
 
-               if( in_array( $dbType, $canonicalDBTypes ) || ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) ) {
+               if( in_array( $dbType, $canonicalDBTypes ) ) {
                        return new $class(
                                isset( $p['host'] ) ? $p['host'] : false,
                                isset( $p['user'] ) ? $p['user'] : false,
@@ -689,6 +689,8 @@ abstract class DatabaseBase implements DatabaseType {
                                isset( $p['flags'] ) ? $p['flags'] : 0,
                                isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global'
                        );
+               } elseif ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) {
+                       return new $class( $p );
                } else {
                        return null;
                }
index e2b38f5..6452f54 100644 (file)
@@ -708,19 +708,14 @@ class DatabasePostgres extends DatabaseBase {
                # Replace reserved words with better ones
                switch( $name ) {
                        case 'user':
-                               return $this->realTableName( 'mwuser', $format );
+                               return 'mwuser';
                        case 'text':
-                               return $this->realTableName( 'pagecontent', $format );
+                               return 'pagecontent';
                        default:
-                               return $this->realTableName( $name, $format );
+                               return parent::tableName( $name, $format );
                }
        }
 
-       /* Don't cheat on installer */
-       function realTableName( $name, $format = 'quoted' ) {
-               return parent::tableName( $name, $format );
-       }
-
        /**
         * Return the next in a sequence, save the value for retrieval via insertId()
         * @return null
@@ -995,7 +990,7 @@ class DatabasePostgres extends DatabaseBase {
                if ( !$schema ) {
                        $schema = $this->getCoreSchema();
                }
-               $table = $this->realTableName( $table, 'raw' );
+               $table = $this->tableName( $table, 'raw' );
                $etable = $this->addQuotes( $table );
                $eschema = $this->addQuotes( $schema );
                $SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n "
index 1475043..0dd5466 100644 (file)
@@ -119,15 +119,6 @@ class FileRepo {
                return $this->backend;
        }
 
-       /**
-        * Get an explanatory message if this repo is read-only
-        * 
-        * @return string|bool Returns false if the repo is not read-only
-        */
-       public function getReadOnlyReason() {
-               return $this->backend->getReadOnlyReason();
-       }
-
        /**
         * Prepare a single zone or list of zones for usage.
         * See initDeletedDir() for additional setup needed for the 'deleted' zone.
index 9d82b5e..2a97afa 100644 (file)
@@ -45,8 +45,6 @@ abstract class FileBackend {
        protected $readOnly; // string; read-only explanation message
        /** @var LockManager */
        protected $lockManager;
-       /** @var FileJournal */
-       protected $fileJournal;
 
        /**
         * Create a new backend instance from configuration.
@@ -57,10 +55,8 @@ abstract class FileBackend {
         *                     This should consist of alphanumberic, '-', and '_' characters.
         *                     This name should not be changed after use.
         *     'wikiId'      : Prefix to container names that is unique to this wiki.
-        *                     It should only consist of alphanumberic, '-', and '_' characters.
+        *                     This should consist of alphanumberic, '-', and '_' characters.
         *     'lockManager' : Registered name of a file lock manager to use.
-        *     'fileJournal' : File journal configuration; see FileJournal::factory().
-        *                     Journals simply log changes to files stored in the backend.
         *     'readOnly'    : Write operations are disallowed if this is a non-empty string.
         *                     It should be an explanation for the backend being read-only.
         * 
@@ -77,9 +73,6 @@ abstract class FileBackend {
                $this->lockManager = ( $config['lockManager'] instanceof LockManager )
                        ? $config['lockManager']
                        : LockManagerGroup::singleton()->get( $config['lockManager'] );
-               $this->fileJournal = isset( $config['fileJournal'] )
-                       ? FileJournal::factory( $config['fileJournal'], $this->name )
-                       : FileJournal::factory( array( 'class' => 'NullFileJournal' ), $this->name );
                $this->readOnly = isset( $config['readOnly'] )
                        ? (string)$config['readOnly']
                        : '';
@@ -184,8 +177,6 @@ abstract class FileBackend {
         * 'allowStale'          : Don't require the latest available data.
         *                         This can increase performance for non-critical writes.
         *                         This has no effect unless the 'force' flag is set.
-        * 'nonJournaled'        : Don't log this operation batch in the file journal.
-        *                         This limits the ability of recovery scripts.
         * 
         * Remarks on locking:
         * File system paths given to operations should refer to files that are
index 9c3cf5b..52c71d6 100644 (file)
@@ -133,7 +133,7 @@ class FileBackendMultiWrite extends FileBackend {
                }
 
                // Actually attempt the operation batch...
-               $subStatus = FileOp::attemptBatch( $performOps, $opts, $this->fileJournal );
+               $subStatus = FileOp::attemptBatch( $performOps, $opts );
 
                $success = array();
                $failCount = 0;
index ff32925..e96f257 100644 (file)
@@ -708,7 +708,7 @@ abstract class FileBackendStore extends FileBackend {
                $this->clearCache();
 
                // Actually attempt the operation batch...
-               $subStatus = FileOp::attemptBatch( $performOps, $opts, $this->fileJournal );
+               $subStatus = FileOp::attemptBatch( $performOps, $opts );
 
                // Merge errors into status fields
                $status->merge( $subStatus );
index 6cee9f9..825a666 100644 (file)
@@ -24,7 +24,6 @@ abstract class FileOp {
        protected $state = self::STATE_NEW; // integer
        protected $failed = false; // boolean
        protected $useLatest = true; // boolean
-       protected $batchId; // string
 
        protected $sourceSha1; // string
        protected $destSameAsSource; // boolean
@@ -63,16 +62,6 @@ abstract class FileOp {
                $this->params = $params;
        }
 
-       /**
-        * Set the batch UUID this operation belongs to
-        *
-        * @param $batchId string
-        * @return void
-        */
-       final protected function setBatchId( $batchId ) {
-               $this->batchId = $batchId;
-       }
-
        /**
         * Whether to allow stale data for file reads and stat checks
         *
@@ -84,57 +73,43 @@ abstract class FileOp {
        }
 
        /**
-        * Attempt to perform a series of file operations.
+        * Attempt a series of file operations.
         * Callers are responsible for handling file locking.
         * 
         * $opts is an array of options, including:
-        * 'force'        : Errors that would normally cause a rollback do not.
-        *                  The remaining operations are still attempted if any fail.
-        * 'allowStale'   : Don't require the latest available data.
-        *                  This can increase performance for non-critical writes.
-        *                  This has no effect unless the 'force' flag is set.
-        * 'nonJournaled' : Don't log this operation batch in the file journal.
-        * 
+        * 'force'      : Errors that would normally cause a rollback do not.
+        *                The remaining operations are still attempted if any fail.
+        * 'allowStale' : Don't require the latest available data.
+        *                This can increase performance for non-critical writes.
+        *                This has no effect unless the 'force' flag is set.
+        *
         * The resulting Status will be "OK" unless:
         *     a) unexpected operation errors occurred (network partitions, disk full...)
         *     b) significant operation errors occured and 'force' was not set
         * 
         * @param $performOps Array List of FileOp operations
         * @param $opts Array Batch operation options
-        * @param $journal FileJournal Journal to log operations to
         * @return Status 
         */
-       final public static function attemptBatch(
-               array $performOps, array $opts, FileJournal $journal
-       ) {
+       final public static function attemptBatch( array $performOps, array $opts ) {
                $status = Status::newGood();
 
+               $allowStale = !empty( $opts['allowStale'] );
+               $ignoreErrors = !empty( $opts['force'] );
+
                $n = count( $performOps );
                if ( $n > self::MAX_BATCH_SIZE ) {
                        $status->fatal( 'backend-fail-batchsize', $n, self::MAX_BATCH_SIZE );
                        return $status;
                }
 
-               $batchId = $journal->getTimestampedUUID();
-               $allowStale = !empty( $opts['allowStale'] );
-               $ignoreErrors = !empty( $opts['force'] );
-               $journaled = empty( $opts['nonJournaled'] );
-
-               $entries = array(); // file journal entries
                $predicates = FileOp::newPredicates(); // account for previous op in prechecks
                // Do pre-checks for each operation; abort on failure...
                foreach ( $performOps as $index => $fileOp ) {
-                       $fileOp->setBatchId( $batchId );
                        $fileOp->allowStaleReads( $allowStale );
-                       $oldPredicates = $predicates;
-                       $subStatus = $fileOp->precheck( $predicates ); // updates $predicates
+                       $subStatus = $fileOp->precheck( $predicates );
                        $status->merge( $subStatus );
-                       if ( $subStatus->isOK() ) {
-                               if ( $journaled ) { // journal log entry
-                                       $entries = array_merge( $entries,
-                                               self::getJournalEntries( $fileOp, $oldPredicates, $predicates ) );
-                               }
-                       } else { // operation failed?
+                       if ( !$subStatus->isOK() ) { // operation failed?
                                $status->success[$index] = false;
                                ++$status->failCount;
                                if ( !$ignoreErrors ) {
@@ -143,15 +118,8 @@ abstract class FileOp {
                        }
                }
 
-               // Log the operations in file journal...
-               if ( count( $entries ) ) {
-                       $subStatus = $journal->logChangeBatch( $entries, $batchId );
-                       if ( !$subStatus->isOK() ) {
-                               return $subStatus; // abort
-                       }
-               }
-
-               if ( $ignoreErrors ) { // treat precheck() fatals as mere warnings
+               if ( $ignoreErrors ) {
+                       # Treat all precheck() fatals as merely warnings
                        $status->setResult( true, $status->value );
                }
 
@@ -186,46 +154,6 @@ abstract class FileOp {
                return $status;
        }
 
-       /**
-        * Get the file journal entries for a single file operation
-        * 
-        * @param $fileOp FileOp
-        * @param $oPredicates Array Pre-op information about files
-        * @param $nPredicates Array Post-op information about files
-        * @return Array
-        */
-       final protected static function getJournalEntries(
-               FileOp $fileOp, array $oPredicates, array $nPredicates
-       ) {
-               $nullEntries = array();
-               $updateEntries = array();
-               $deleteEntries = array();
-               $pathsUsed = array_merge( $fileOp->storagePathsRead(), $fileOp->storagePathsChanged() );
-               foreach ( $pathsUsed as $path ) {
-                       $nullEntries[] = array( // assertion for recovery
-                               'op'      => 'null',
-                               'path'    => $path,
-                               'newSha1' => $fileOp->fileSha1( $path, $oPredicates )
-                       );
-               }
-               foreach ( $fileOp->storagePathsChanged() as $path ) {
-                       if ( $nPredicates['sha1'][$path] === false ) { // deleted
-                               $deleteEntries[] = array(
-                                       'op'      => 'delete',
-                                       'path'    => $path,
-                                       'newSha1' => ''
-                               );
-                       } else { // created/updated
-                               $updateEntries[] = array(
-                                       'op'      => $fileOp->fileExists( $path, $oPredicates ) ? 'update' : 'create',
-                                       'path'    => $path,
-                                       'newSha1' => $nPredicates['sha1'][$path]
-                               );
-                       }
-               }
-               return array_merge( $nullEntries, $updateEntries, $deleteEntries );
-       }
-
        /**
         * Get the value of the parameter with the given name
         * 
@@ -424,8 +352,8 @@ abstract class FileOp {
                $params = $this->params;
                $params['failedAction'] = $action;
                try {
-                       wfDebugLog( 'FileOperation', get_class( $this ) .
-                               " failed (batch #{$this->batchId}): " . FormatJson::encode( $params ) );
+                       wfDebugLog( 'FileOperation',
+                               get_class( $this ) . ' failed: ' . FormatJson::encode( $params ) );
                } catch ( Exception $e ) {
                        // bad config? debug log error?
                }
diff --git a/includes/filerepo/backend/filejournal/DBFileJournal.php b/includes/filerepo/backend/filejournal/DBFileJournal.php
deleted file mode 100644 (file)
index 1eb9eca..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-<?php
-/**
- * @file
- * @ingroup FileJournal
- * @author Aaron Schulz
- */
-
-/**
- * Version of FileJournal that logs to a DB table
- * @since 1.20
- */
-class DBFileJournal extends FileJournal {
-       protected $wiki = false; // string; wiki DB name
-
-       /**
-        * Construct a new instance from configuration.
-        * $config includes:
-        *     'wiki' : wiki name to use for LoadBalancer
-        * 
-        * @param $config Array
-        */
-       protected function __construct( array $config ) {
-               parent::__construct( $config );
-
-               $this->wiki = $config['wiki'];
-       }
-
-       /**
-        * @see FileJournal::logChangeBatch()
-        * @return Status 
-        */
-       protected function doLogChangeBatch( array $entries, $batchId ) {
-               $status = Status::newGood();
-
-               $dbw = $this->getMasterDB();
-               if ( !$dbw ) {
-                       $status->fatal( 'filejournal-fail-dbconnect', $this->backend );
-                       return $status;
-               }
-               $now = wfTimestamp( TS_UNIX );
-
-               $data = array();
-               foreach ( $entries as $entry ) {
-                       $data[] = array(
-                               'fj_batch_uuid' => $batchId,
-                               'fj_backend'    => $this->backend,
-                               'fj_op'         => $entry['op'],
-                               'fj_path'       => $entry['path'],
-                               'fj_path_sha1'  => wfBaseConvert( sha1( $entry['path'] ), 16, 36, 31 ),
-                               'fj_new_sha1'   => $entry['newSha1'],
-                               'fj_timestamp'  => $dbw->timestamp( $now )
-                       );
-               }
-
-               try {
-                       $dbw->begin();
-                       $dbw->insert( 'filejournal', $data, __METHOD__ );
-                       $dbw->commit();
-               } catch ( DBError $e ) {
-                       $status->fatal( 'filejournal-fail-dbquery', $this->backend );
-                       return $status;
-               }
-
-               return $status;
-       }
-
-       /**
-        * @see FileJournal::purgeOldLogs()
-        * @return Status
-        */
-       protected function doPurgeOldLogs() {
-               $status = Status::newGood();
-               if ( $this->ttlDays <= 0 ) {
-                       return $status; // nothing to do
-               }
-
-               $dbw = $this->getMasterDB();
-               if ( !$dbw ) {
-                       $status->fatal( 'filejournal-fail-dbconnect', $this->backend );
-                       return $status;
-               }
-               $dbCutoff = $dbw->timestamp( time() - 86400 * $this->ttlDays );
-
-               try {
-                       $dbw->begin();
-                       $dbw->delete( 'filejournal',
-                               array( 'fj_timestamp < ' . $dbw->addQuotes( $dbCutoff ) ),
-                               __METHOD__
-                       );
-                       $dbw->commit();
-               } catch ( DBError $e ) {
-                       $status->fatal( 'filejournal-fail-dbquery', $this->backend );
-                       return $status;
-               }
-
-               return $status;
-       }
-
-       /**
-        * Get a master connection to the logging DB
-        * 
-        * @return DatabaseBase|null 
-        */
-       protected function getMasterDB() {
-               try {
-                       $lb = wfGetLBFactory()->newMainLB();
-                       return $lb->getConnection( DB_MASTER, array(), $this->wiki );
-               } catch ( DBConnectionError $e ) {
-                       return null;
-               }
-       }
-}
diff --git a/includes/filerepo/backend/filejournal/FileJournal.php b/includes/filerepo/backend/filejournal/FileJournal.php
deleted file mode 100644 (file)
index f60b7f9..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-<?php
-/**
- * @defgroup FileJournal File journal
- * @ingroup FileBackend
- */
-
-/**
- * @file
- * @ingroup FileJournal
- * @author Aaron Schulz
- */
-
-/**
- * @brief Class for handling file operation journaling.
- *
- * Subclasses should avoid throwing exceptions at all costs.
- *
- * @ingroup FileJournal
- * @since 1.20
- */
-abstract class FileJournal {
-       protected $backend; // string
-       protected $ttlDays; // integer
-
-       /**
-        * Construct a new instance from configuration.
-        * $config includes:
-        *     'ttlDays' : days to keep log entries around (false means "forever")
-        * 
-        * @param $config Array
-        */
-       protected function __construct( array $config ) {
-               $this->ttlDays = isset( $config['ttlDays'] ) ? $config['ttlDays'] : false;
-       }
-
-       /**
-        * Create an appropriate FileJournal object from config
-        * 
-        * @param $config Array
-        * @param $backend string A registered file backend name
-        * @return FileJournal
-        */
-       final public static function factory( array $config, $backend ) {
-               $class = $config['class'];
-               $jrn = new $class( $config );
-               if ( !$jrn instanceof self ) {
-                       throw new MWException( "Class given is not an instance of FileJournal." );
-               }
-               $jrn->backend = $backend;
-               return $jrn;
-       }
-
-       /**
-        * Get a statistically unique ID string
-        * 
-        * @return string <9 char TS_MW timestamp in base 36><22 random base 36 chars>
-        */
-       final public function getTimestampedUUID() {
-               $s = '';
-               for ( $i = 0; $i < 5; $i++ ) {
-                       $s .= mt_rand( 0, 2147483647 );
-               }
-               $s = wfBaseConvert( sha1( $s ), 16, 36, 31 );
-               return substr( wfBaseConvert( wfTimestamp( TS_MW ), 10, 36, 9 ) . $s, 0, 31 );
-       }
-
-       /**
-        * Log changes made by a batch file operation.
-        * $entries is an array of log entries, each of which contains:
-        *     op      : Basic operation name (create, store, copy, delete)
-        *     path    : The storage path of the file
-        *     newSha1 : The final base 36 SHA-1 of the file
-        * Note that 'false' should be used as the SHA-1 for non-existing files.
-        * 
-        * @param $entries Array List of file operations (each an array of parameters)
-        * @param $batchId string UUID string that identifies the operation batch
-        * @return Status
-        */
-       final public function logChangeBatch( array $entries, $batchId ) {
-               if ( !count( $entries ) ) {
-                       return Status::newGood();
-               }
-               return $this->doLogChangeBatch( $entries, $batchId );
-       }
-
-       /**
-        * @see FileJournal::logChangeBatch()
-        * 
-        * @param $entries Array List of file operations (each an array of parameters)
-        * @param $batchId string UUID string that identifies the operation batch
-        * @return Status
-        */
-       abstract protected function doLogChangeBatch( array $entries, $batchId );
-
-       /**
-        * Purge any old log entries
-        * 
-        * @return Status 
-        */
-       final public function purgeOldLogs() {
-               return $this->doPurgeOldLogs();
-       }
-
-       /**
-        * @see FileJournal::purgeOldLogs()
-        * @return Status
-        */
-       abstract protected function doPurgeOldLogs();
-}
-
-/**
- * Simple version of FileJournal that does nothing
- * @since 1.20
- */
-class NullFileJournal extends FileJournal {
-       /**
-        * @see FileJournal::logChangeBatch()
-        * @return Status 
-        */
-       protected function doLogChangeBatch( array $entries, $batchId ) {
-               return Status::newGood();
-       }
-
-       /**
-        * @see FileJournal::purgeOldLogs()
-        * @return Status
-        */
-       protected function doPurgeOldLogs() {
-               return Status::newGood();
-       }
-}
index 5e3763c..543f23f 100644 (file)
@@ -760,27 +760,16 @@ abstract class File {
         * @param $thumbUrl string Thumbnail URL
         * @param $params Array
         * @param $flags integer
-        * @param $status Status Optional status object to use for errors
         * @return MediaTransformOutput
         */
-       protected function transformErrorOutput(
-               $thumbPath, $thumbUrl, $params, $flags, Status $status = null
-       ) {
+       protected function transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags ) {
                global $wgIgnoreImageErrors;
 
                if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) {
                        return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params );
                } else {
-                       $badStatus = Status::newFatal( 'thumbnail-dest-create' );
-                       if ( $status ) { // additional, more detailed errors
-                               $badStatus->merge( $status );
-                       }
-                       $err = array();
-                       foreach ( $badStatus->getErrorsArray() as $item ) {
-                               $err[] = wfMsg( $item[0], array_slice( $item, 1 ) );
-                       }
                        return new MediaTransformError( 'thumbnail_error',
-                               $params['width'], 0, implode( "\n", $err ) ); // MTO does "\n" => "<br/>"
+                               $params['width'], 0, wfMsg( 'thumbnail-dest-create' ) );
                }
        }
 
@@ -886,8 +875,7 @@ abstract class File {
                                if ( $status->isOK() ) {
                                        $thumb->setStoragePath( $thumbPath );
                                } else {
-                                       $thumb = $this->transformErrorOutput(
-                                               $thumbPath, $thumbUrl, $params, $flags, $status );
+                                       $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags );
                                }
                        }
 
index 9731efc..cd26170 100644 (file)
@@ -908,13 +908,9 @@ class LocalFile extends File {
         */
        function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null ) {
                global $wgContLang;
-
-               if ( $this->getRepo()->getReadOnlyReason() !== false ) {
-                       return $this->readOnlyFatalStatus();
-               }
-
                // truncate nicely or the DB will do it for us
-               // non-nicely (dangling multi-byte chars, non-truncated version in cache).
+               // non-nicely (dangling multi-byte chars, non-truncated
+               // version in cache).
                $comment = $wgContLang->truncate( $comment, 255 );
                $this->lock(); // begin
                $status = $this->publish( $srcPath, $flags );
@@ -1179,10 +1175,6 @@ class LocalFile extends File {
         *     archive name, or an empty string if it was a new file.
         */
        function publishTo( $srcPath, $dstRel, $flags = 0 ) {
-               if ( $this->getRepo()->getReadOnlyReason() !== false ) {
-                       return $this->readOnlyFatalStatus();
-               }
-
                $this->lock(); // begin
 
                $archiveName = wfTimestamp( TS_MW ) . '!'. $this->getName();
@@ -1219,10 +1211,6 @@ class LocalFile extends File {
         * @return FileRepoStatus object.
         */
        function move( $target ) {
-               if ( $this->getRepo()->getReadOnlyReason() !== false ) {
-                       return $this->readOnlyFatalStatus();
-               }
-
                wfDebugLog( 'imagemove', "Got request to move {$this->name} to " . $target->getText() );
                $this->lock(); // begin
 
@@ -1262,10 +1250,6 @@ class LocalFile extends File {
         * @return FileRepoStatus object.
         */
        function delete( $reason, $suppress = false ) {
-               if ( $this->getRepo()->getReadOnlyReason() !== false ) {
-                       return $this->readOnlyFatalStatus();
-               }
-
                $this->lock(); // begin
 
                $batch = new LocalFileDeleteBatch( $this, $reason, $suppress );
@@ -1282,7 +1266,7 @@ class LocalFile extends File {
                }
                $status = $batch->execute();
 
-               if ( $status->isOK() ) {
+               if ( $status->ok ) {
                        // Update site_stats
                        $site_stats = $dbw->tableName( 'site_stats' );
                        $dbw->query( "UPDATE $site_stats SET ss_images=ss_images-1", __METHOD__ );
@@ -1309,10 +1293,6 @@ class LocalFile extends File {
         * @return FileRepoStatus object.
         */
        function deleteOld( $archiveName, $reason, $suppress = false ) {
-               if ( $this->getRepo()->getReadOnlyReason() !== false ) {
-                       return $this->readOnlyFatalStatus();
-               }
-
                $this->lock(); // begin
 
                $batch = new LocalFileDeleteBatch( $this, $reason, $suppress );
@@ -1322,7 +1302,7 @@ class LocalFile extends File {
 
                $this->unlock(); // done
 
-               if ( $status->isOK() ) {
+               if ( $status->ok ) {
                        $this->purgeDescription();
                        $this->purgeHistory();
                }
@@ -1342,12 +1322,6 @@ class LocalFile extends File {
         * @return FileRepoStatus
         */
        function restore( $versions = array(), $unsuppress = false ) {
-               if ( $this->getRepo()->getReadOnlyReason() !== false ) {
-                       return $this->readOnlyFatalStatus();
-               }
-
-               $this->lock(); // begin
-
                $batch = new LocalFileRestoreBatch( $this, $unsuppress );
 
                if ( !$versions ) {
@@ -1358,14 +1332,14 @@ class LocalFile extends File {
 
                $status = $batch->execute();
 
-               if ( $status->isGood() ) {
-                       $cleanupStatus = $batch->cleanup();
-                       $cleanupStatus->successCount = 0;
-                       $cleanupStatus->failCount = 0;
-                       $status->merge( $cleanupStatus );
+               if ( !$status->isGood() ) {
+                       return $status;
                }
 
-               $this->unlock(); // done
+               $cleanupStatus = $batch->cleanup();
+               $cleanupStatus->successCount = 0;
+               $cleanupStatus->failCount = 0;
+               $status->merge( $cleanupStatus );
 
                return $status;
        }
@@ -1470,14 +1444,6 @@ class LocalFile extends File {
                $dbw = $this->repo->getMasterDB();
                $dbw->rollback( __METHOD__ );
        }
-
-       /**
-        * @return Status 
-        */
-       protected function readOnlyFatalStatus() {
-               return $this->getRepo()->newFatal( 'filereadonlyerror', $this->getName(),
-                       $this->getRepo()->getName(), $this->getRepo()->getReadOnlyReason() );
-       }
 } // LocalFile class
 
 # ------------------------------------------------------------------------------
@@ -1745,7 +1711,7 @@ class LocalFileDeleteBatch {
                        $this->status->merge( $status );
                }
 
-               if ( !$this->status->isOK() ) {
+               if ( !$this->status->ok ) {
                        // Critical file deletion error
                        // Roll back inserts, release lock and abort
                        // TODO: delete the defunct filearchive rows if we are using a non-transactional DB
index 046fa16..14604c1 100644 (file)
@@ -158,7 +158,7 @@ abstract class DatabaseInstaller {
                }
                $this->db->selectDB( $this->getVar( 'wgDBname' ) );
 
-               if( $this->db->tableExists( 'archive', __METHOD__ ) ) {
+               if( $this->db->tableExists( 'user', __METHOD__ ) ) {
                        $status->warning( 'config-install-tables-exist' );
                        $this->enableLB();
                        return $status;
index 301c6d4..d4412cb 100644 (file)
@@ -27,11 +27,6 @@ class PostgresUpdater extends DatabaseUpdater {
         */
        protected function getCoreUpdateList() {
                return array(
-                       # rename tables 1.7.3 
-                       # r15791 Change reserved word table names "user" and "text"
-                       array( 'renameTable', 'user', 'mwuser'),
-                       array( 'renameTable', 'text', 'pagecontent'),
-
                        # new sequences
                        array( 'addSequence', 'logging_log_id_seq'          ),
                        array( 'addSequence', 'page_restrictions_pr_id_seq' ),
@@ -411,8 +406,7 @@ END;
        protected function renameTable( $old, $new ) {
                if ( $this->db->tableExists( $old ) ) {
                        $this->output( "Renaming table $old to $new\n" );
-                       $old = $this->db->realTableName( $old, "quoted" );
-                       $new = $this->db->realTableName( $new, "quoted" );
+                       $old = $this->db->addQuotes( $old );
                        $this->db->query( "ALTER TABLE $old RENAME TO $new" );
                }
        }
index a58e62e..5b5b356 100644 (file)
@@ -381,19 +381,19 @@ class SpecialBlock extends FormSpecialPage {
                        $this->getLanguage()->pipeList( $links )
                );
 
-               $userTitle = self::getTargetUserTitle( $this->target );
-               if( $userTitle ){
+               if( $this->target instanceof User ){
                        # Get relevant extracts from the block and suppression logs, if possible
+                       $userpage = $this->target->getUserPage();
                        $out = '';
 
                        LogEventsList::showLogExtract(
                                $out,
                                'block',
-                               $userTitle,
+                               $userpage,
                                '',
                                array(
                                        'lim' => 10,
-                                       'msgKey' => array( 'blocklog-showlog', $userTitle->getText() ),
+                                       'msgKey' => array( 'blocklog-showlog', $userpage->getText() ),
                                        'showIfEmpty' => false
                                )
                        );
@@ -404,12 +404,12 @@ class SpecialBlock extends FormSpecialPage {
                                LogEventsList::showLogExtract(
                                        $out,
                                        'suppress',
-                                       $userTitle,
+                                       $userpage,
                                        '',
                                        array(
                                                'lim' => 10,
                                                'conds' => array( 'log_action' => array( 'block', 'reblock', 'unblock' ) ),
-                                               'msgKey' => array( 'blocklog-showsuppresslog', $userTitle->getText() ),
+                                               'msgKey' => array( 'blocklog-showsuppresslog', $userpage->getText() ),
                                                'showIfEmpty' => false
                                        )
                                );
@@ -421,21 +421,6 @@ class SpecialBlock extends FormSpecialPage {
                return $text;
        }
 
-       /**
-        * Get a user page target for things like logs.
-        * This handles account and IP range targets.
-        * @param $target User|string
-        * @return Title|null
-        */
-       protected static function getTargetUserTitle( $target ) {
-               if( $target instanceof User ) {
-                       return $target->getUserPage();
-               } elseif ( IP::isIPAddress( $target ) ) {
-                       return Title::makeTitleSafe( NS_USER, $target );
-               }
-               return null;
-       }
-
        /**
         * Determine the target of the block, and the type of target
         * TODO: should be in Block.php?
index 39dcb3f..933cff1 100644 (file)
@@ -2277,9 +2277,6 @@ If the problem persists, contact an [[Special:ListUsers/sysop|administrator]].',
 'backend-fail-contenttype'   => 'Could not determine the content type of the file to store at "$1".',
 'backend-fail-batchsize'     => 'Storage backend given a batch of $1 file {{PLURAL:$1|operation|operations}}; the limit is $2 {{PLURAL:$2|operation|operations}}.',
 
-'filejournal-fail-dbconnect' => 'Could not connect to the journal database for storage backend "$1".',
-'filejournal-fail-dbquery'   => 'Could not update the journal database for storage backend "$1".',
-
 # Lock manager
 'lockmanager-notlocked'        => 'Could not unlock "$1"; it is not locked.',
 'lockmanager-fail-closelock'   => 'Could not close lock file for "$1".',
index a5f0420..bcb5377 100644 (file)
@@ -26,8 +26,8 @@ $namespaceNames = array(
        NS_MEDIA            => 'Mèdia',
        NS_SPECIAL          => 'Spèciâl',
        NS_TALK             => 'Discussion',
-       NS_USER             => 'Usanciér',
-       NS_USER_TALK        => 'Discussion_usanciér',
+       NS_USER             => 'Utilisator',
+       NS_USER_TALK        => 'Discussion_utilisator',
        NS_PROJECT_TALK     => 'Discussion_$1',
        NS_FILE             => 'Fichiér',
        NS_FILE_TALK        => 'Discussion_fichiér',
@@ -42,14 +42,13 @@ $namespaceNames = array(
 );
 
 $namespaceAliases = array(
-       'Discutar'              => NS_TALK,
-       'Utilisator'            => NS_USER,
+       'Discutar' => NS_TALK,
        'Discussion_Utilisator' => NS_USER_TALK,
-       'Émâge'                 => NS_FILE,
-       'Discussion_Émâge'      => NS_FILE_TALK,
-       'Discussion_Modèlo'     => NS_TEMPLATE_TALK,
-       'Discussion_Éde'        => NS_HELP_TALK,
-       'Discussion_Catègorie'  => NS_CATEGORY_TALK
+       'Émâge' => NS_FILE,
+       'Discussion_Émâge' => NS_FILE_TALK,
+       'Discussion_Modèlo' => NS_TEMPLATE_TALK,
+       'Discussion_Éde' => NS_HELP_TALK,
+       'Discussion_Catègorie' => NS_CATEGORY_TALK
 );
 
 $specialPageAliases = array(
index cda68db..5c8a413 100644 (file)
  */
 
 $namespaceNames = array(
-       NS_MEDIA            => 'Midia',
+       NS_MEDIA            => 'Nká',
        NS_SPECIAL          => 'Ihü_kárírí',
        NS_TALK             => 'Okwu',
-       NS_USER             => 'Ọbanife',
-       NS_USER_TALK        => 'Okwu_ọbanife',
+       NS_USER             => 'Ọ\'bànifé',
+       NS_USER_TALK        => 'Okwu_ọ\'bànifé',
        NS_PROJECT_TALK     => 'Okwu_$1',
-       NS_FILE             => 'Usòrò',
-       NS_FILE_TALK        => 'Okwu_usòrò',
-       NS_MEDIAWIKI        => 'MidiaWiki',
-       NS_MEDIAWIKI_TALK   => 'Okwu_MidiaWiki',
+       NS_FILE             => 'Ákwúkwó_orünotu',
+       NS_FILE_TALK        => 'Okwu_ákwúkwó_orünotu',
+       NS_MEDIAWIKI        => 'NkáWiki',
+       NS_MEDIAWIKI_TALK   => 'Okwu_NkáWiki',
        NS_TEMPLATE         => 'Àtụ',
        NS_TEMPLATE_TALK    => 'Okwu_àtụ',
-       NS_HELP             => 'Nkwadọ',
-       NS_HELP_TALK        => 'Okwu_nkwadọ',
-       NS_CATEGORY         => 'Òtù',
-       NS_CATEGORY_TALK    => 'Okwu_òtù',
-);
-
-$namespaceAliases = array(
-       'Nká'                  => NS_MEDIA,
-       'Ọ\'bànifé'            => NS_USER,
-       'Okwu_ọ\'bànifé'       => NS_USER_TALK,
-       'Ákwúkwó_orünotu'      => NS_FILE,
-       'Okwu_ákwúkwó_orünotu' => NS_FILE_TALK,
-       'NkáWiki'              => NS_MEDIAWIKI,
-       'Okwu_NkáWiki'         => NS_MEDIAWIKI_TALK,
-       'Nkwádọ'               => NS_HELP,
-       'Okwu_nkwádọ'          => NS_HELP_TALK,
-       'Ébéonọr'              => NS_CATEGORY,
-       'Okwu_ébéonọr'         => NS_CATEGORY_TALK,
+       NS_HELP             => 'Nkwádọ',
+       NS_HELP_TALK        => 'Okwu_nkwádọ',
+       NS_CATEGORY         => 'Ébéonọr',
+       NS_CATEGORY_TALK    => 'Okwu_ébéonọr',
 );
 
 $specialPageAliases = array(
index 7fcca67..d5a2ba5 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 $namespaceNames = array(
-       NS_MEDIA            => 'Ð\9cедиÑ\83м',
+       NS_MEDIA            => 'Ð\9cедиÑ\98а',
        NS_SPECIAL          => 'Специјална',
        NS_TALK             => 'Разговор',
        NS_USER             => 'Корисник',
@@ -42,9 +42,8 @@ $namespaceNames = array(
 );
 
 $namespaceAliases = array(
-       'Медија'            => NS_MEDIA,
-       'Специјални'        => NS_SPECIAL,
-       'Слика'             => NS_FILE,
+       'Специјални' => NS_SPECIAL,
+       'Слика' => NS_FILE,
        'Разговор_за_слика' => NS_FILE_TALK,
 );
 
index c6ab3d7..d29cbe2 100644 (file)
@@ -24,52 +24,46 @@ $fallback8bitEncoding = 'windows-1256';
 $rtl = true;
 
 $namespaceNames = array(
-       NS_MEDIA            => 'مدیا',
+       NS_MEDIA            => 'مه‌دیا',
        NS_SPECIAL          => 'شا',
-       NS_MAIN             => '',
        NS_TALK             => 'گپ',
        NS_USER             => 'کارور',
        NS_USER_TALK        => 'کارور_گپ',
        NS_PROJECT_TALK     => '$1_گپ',
        NS_FILE             => 'پرونده',
        NS_FILE_TALK        => 'پرونده_گپ',
-       NS_MEDIAWIKI        => 'مدیاویکی',
-       NS_MEDIAWIKI_TALK   => 'مدیاویکی_گپ',
+       NS_MEDIAWIKI        => 'مه‌دیاویکی',
+       NS_MEDIAWIKI_TALK   => 'مه‌دیاویکی_گپ',
        NS_TEMPLATE         => 'شابلون',
        NS_TEMPLATE_TALK    => 'شابلون_گپ',
-       NS_HELP             => 'رانما',
-       NS_HELP_TALK        => 'راÙ\86Ù\85ا_گپ',
+       NS_HELP             => 'راÙ\86Ù\87â\80\8cÙ\85ا',
+       NS_HELP_TALK        => 'راÙ\86Ù\87â\80\8cÙ\85ائÙ\87_گپ',
        NS_CATEGORY         => 'رج',
        NS_CATEGORY_TALK    => 'رج_گپ',
 );
 
 $namespaceAliases = array(
-       'مه‌دیا'         => NS_MEDIA,
        'مدیا'          => NS_MEDIA,
        'ویژه'          => NS_SPECIAL,
-       'بحث'           => NS_TALK,
+       'بحث'            => NS_TALK,
        'کاربر'         => NS_USER,
-       'بحث_کاربر'     => NS_USER_TALK,
-       'بحث_$1'        => NS_PROJECT_TALK,
+       'بحث_کاربر'      => NS_USER_TALK,
+       'بحث_$1'         => NS_PROJECT_TALK,
        'تصویر'         => NS_FILE,
        'پرونده'        => NS_FILE,
-       'بحث_تصویر'     => NS_FILE_TALK,
-       'بحث_پرونده'    => NS_FILE_TALK,
+       'بحث_تصویر'      => NS_FILE_TALK,
+       'بحث_پرونده'     => NS_FILE_TALK,
        'مدیاویکی'      => NS_MEDIAWIKI,
        'مه‌دیا ویکی'    => NS_MEDIAWIKI,
-       'مه‌دیاویکی'     => NS_MEDIAWIKI,
-       'مه‌دیاویکی_گپ'  => NS_MEDIAWIKI_TALK,
-       'بحث_مدیاویکی'  => NS_MEDIAWIKI_TALK,
+       'بحث_مدیاویکی'   => NS_MEDIAWIKI_TALK,
        'مه‌دیا ویکی گپ' => NS_MEDIAWIKI_TALK,
        'الگو'          => NS_TEMPLATE,
-       'بحث_الگو'      => NS_TEMPLATE_TALK,
+       'بحث_الگو'       => NS_TEMPLATE_TALK,
        'راهنما'        => NS_HELP,
-       'رانه‌ما'        => NS_HELP,
-       'رانه‌مائه_گپ'   => NS_HELP_TALK,
-       'بحث_راهنما'    => NS_HELP_TALK,
+       'بحث_راهنما'     => NS_HELP_TALK,
        'رانه‌مای گپ'    => NS_HELP_TALK,
        'رده'           => NS_CATEGORY,
-       'بحث_رده'       => NS_CATEGORY_TALK,
+       'بحث_رده'        => NS_CATEGORY_TALK,
 );
 
 $magicWords = array(
index 68006e2..db48562 100644 (file)
@@ -23,35 +23,30 @@ $fallback = 'nl';
 
 $namespaceNames = array(
        NS_MEDIA            => 'Media',
-       NS_SPECIAL          => 'Spesiaal',
+       NS_SPECIAL          => 'Speciaal',
        NS_TALK             => 'Overleg',
        NS_USER             => 'Gebruker',
        NS_USER_TALK        => 'Overleg_gebruker',
        NS_PROJECT_TALK     => 'Overleg_$1',
-       NS_FILE             => 'Bestaand',
-       NS_FILE_TALK        => 'Overleg_bestaand',
+       NS_FILE             => 'Ofbeelding',
+       NS_FILE_TALK        => 'Overleg_ofbeelding',
        NS_MEDIAWIKI        => 'MediaWiki',
        NS_MEDIAWIKI_TALK   => 'Overleg_MediaWiki',
        NS_TEMPLATE         => 'Mal',
        NS_TEMPLATE_TALK    => 'Overleg_mal',
        NS_HELP             => 'Hulpe',
        NS_HELP_TALK        => 'Overleg_hulpe',
-       NS_CATEGORY         => 'Kategorie',
-       NS_CATEGORY_TALK    => 'Overleg_kategorie',
+       NS_CATEGORY         => 'Kattegerie',
+       NS_CATEGORY_TALK    => 'Overleg_kattegerie',
 );
 
 $namespaceAliases = array(
-       'Speciaol'           => NS_SPECIAL,
-       'Speciaal'           => NS_SPECIAL,
-       'Sjabloon'           => NS_TEMPLATE,
-       'Overleg_sjabloon'   => NS_TEMPLATE_TALK,
-       'Ofbeelding'         => NS_FILE,
-       'Overleg_ofbeelding' => NS_FILE_TALK,
-       'Categorie'          => NS_CATEGORY,
-       'Overleg_categorie'  => NS_CATEGORY_TALK,
-       'Kattegerie'         => NS_CATEGORY,
-       'Overleg_categorie'  => NS_CATEGORY_TALK,
-       'Overleg_kattegerie' => NS_HELP_TALK,
+       'Speciaol'          => NS_SPECIAL,
+       'Sjabloon'          => NS_TEMPLATE,
+       'Overleg_sjabloon'  => NS_TEMPLATE_TALK,
+       'Categorie'         => NS_CATEGORY,
+       'Overleg_categorie' => NS_CATEGORY_TALK,
+       'Overleg_help'      => NS_HELP_TALK,
 );
 
 $dateFormats = array(
index 25a3f17..cae0679 100644 (file)
@@ -40,17 +40,17 @@ $namespaceNames = array(
        NS_MEDIA            => 'ମାଧ୍ୟମ',
        NS_SPECIAL          => 'ବିଶେଷ',
        NS_TALK             => 'ଆଲୋଚନା',
-       NS_USER             => 'ବ୍ୟବହାରକାରୀ',
-       NS_USER_TALK        => 'ବ୍ୟବହାରକାରୀଙ୍କ_ଆଲୋଚନା',
-       NS_PROJECT_TALK     => '$1_ଆଲୋଚନା',
+       NS_USER             => 'ବà­\8dà­\9fବାହାରà¬\95ାରà­\80',
+       NS_USER_TALK        => 'ବà­\8dà­\9fବାହାରà¬\95ାରà­\80à¬\99à­\8dà¬\95_à¬\86ଲà­\8bà¬\9aନା',
+       NS_PROJECT_TALK     => 'ଉଇକିପିଡ଼ିଆ_ଆଲୋଚନା',
        NS_FILE             => 'ଫାଇଲ',
        NS_FILE_TALK        => 'ଫାଇଲ_ଆଲୋଚନା',
        NS_MEDIAWIKI        => 'ମିଡ଼ିଆଉଇକି',
        NS_MEDIAWIKI_TALK   => 'ମିଡ଼ିଆଉଇକି_ଆଲୋଚନା',
-       NS_TEMPLATE         => 'à¬\9bାà¬\9eà­\8dà¬\9a',
-       NS_TEMPLATE_TALK    => 'à¬\9bାà¬\9eà­\8dà¬\9a_ଆଲୋଚନା',
-       NS_HELP             => 'ସହଯà­\8bà¬\97',
-       NS_HELP_TALK        => 'ସହଯà­\8bà¬\97_ଆଲୋଚନା',
+       NS_TEMPLATE         => 'à¬\9fà­\87ମà­\8dପଲà­\87à¬\9f',
+       NS_TEMPLATE_TALK    => 'à¬\9fà­\87ମà­\8dପଲà­\87à¬\9f_ଆଲୋଚନା',
+       NS_HELP             => 'ସାହାଯà­\8dà­\9f',
+       NS_HELP_TALK        => 'ସାହାଯà­\8dà­\9f_ଆଲୋଚନା',
        NS_CATEGORY         => 'ଶ୍ରେଣୀ',
        NS_CATEGORY_TALK    => 'ଶ୍ରେଣୀ_ଆଲୋଚନା',
 );
@@ -58,17 +58,10 @@ $namespaceNames = array(
 $namespaceAliases = array(
        'ବ୍ୟବହାରକାରି'          => NS_USER,
        'ବ୍ୟବହାରକାରିଁକ_ଆଲୋଚନା' => NS_USER_TALK,
-       'ବ୍ୟବାହାରକାରୀ'          => NS_USER,
-       'ବ୍ୟବାହାରକାରୀଙ୍କ_ଆଲୋଚନା' => NS_USER_TALK,
-       'ଉଇକିପିଡ଼ିଆ_ଆଲୋଚନା' => NS_PROJECT_TALK,
        'ଟେଁପଲେଟ'             => NS_TEMPLATE,
        'ଟେଁପଲେଟ_ଆଲୋଚନା'     => NS_TEMPLATE_TALK,
-       'ଟେମ୍ପଲେଟ'             => NS_TEMPLATE,
-       'ଟେମ୍ପଲେଟ_ଆଲୋଚନା'     => NS_TEMPLATE_TALK,
        'ବିଭାଗ'                => NS_CATEGORY,
        'ବିଭାଗିୟ_ଆଲୋଚନା'      => NS_CATEGORY_TALK,
-       'ସାହାଯ୍ୟ'                => NS_HELP,
-       'ସାହାଯ୍ୟ_ଆଲୋଚନା'      => NS_HELP_TALK,
 );
 
 $specialPageAliases = array(
index b6ed501..f4aa85b 100644 (file)
 $fallback = 'ru';
 
 $namespaceNames = array(
-       NS_MEDIA            => 'Медиа',
+       NS_MEDIA            => 'Media',
        NS_SPECIAL          => 'Сæрмагонд',
        NS_TALK             => 'Тæрхон',
        NS_USER             => 'Архайæг',
        NS_USER_TALK        => 'Архайæджы_ныхас',
-       NS_PROJECT_TALK     => '{{GRAMMAR:genitive|$1}}_тæрхон',
-       NS_FILE             => 'Файл',
-       NS_FILE_TALK        => 'Файлы_тæрхон',
+       NS_PROJECT_TALK     => 'Дискусси_$1',
+       NS_FILE             => 'Ð\9dÑ\8bв',
+       NS_FILE_TALK        => 'Ð\9dÑ\8bвы_тæрхон',
        NS_MEDIAWIKI        => 'MediaWiki',
-       NS_MEDIAWIKI_TALK   => 'MediaWiki-йы_тæрхон',
+       NS_MEDIAWIKI_TALK   => 'Тæрхон_MediaWiki',
        NS_TEMPLATE         => 'Шаблон',
        NS_TEMPLATE_TALK    => 'Шаблоны_тæрхон',
        NS_HELP             => 'Æххуыс',
@@ -38,19 +38,13 @@ $namespaceNames = array(
 $namespaceAliases = array(
        'Дискусси'                    => NS_TALK,
        'Архайæджы_дискусси'          => NS_USER_TALK,
-       'Дискусси_$1'                 => NS_PROJECT_TALK,
-       'Ныв'                         => NS_FILE,
-       'Нывы_тæрхон'                 => NS_FILE_TALK,
        'Нывы_тыххæй_дискусси'        => NS_FILE_TALK,
        'Дискусси_MediaWiki'          => NS_MEDIAWIKI_TALK,
-       'Тæрхон_MediaWiki'            => NS_MEDIAWIKI_TALK,
        'Шаблоны_тыххæй_дискусси'     => NS_TEMPLATE_TALK,
        'Æххуысы_тыххæй_дискусси'     => NS_HELP_TALK,
        'Категорийы_тыххæй_дискусси'  => NS_CATEGORY_TALK,
 );
 
-// Remove Russian aliases
-$namespaceGenderAliases = array();
 
 $magicWords = array(
        'redirect'                => array( '0', '#РАРВЫСТ', '#перенаправление', '#перенапр', '#REDIRECT' ),
index 6021bed..e22f416 100644 (file)
 
 $fallback = 'qu, es';
 
-$namespaceNames = array(
-       NS_MEDIA            => 'Midya',
-       NS_SPECIAL          => 'Sapak',
-       NS_TALK             => 'Rimanakuy',
-       NS_USER             => 'Rurak',
-       NS_USER_TALK        => 'Rurakpa_rimanakuy',
-       NS_PROJECT_TALK     => '$1-pa_rimanakuy',
-       NS_FILE             => 'Rikcha',
-       NS_FILE_TALK        => 'Rikchapa_rimanakuy',
-       NS_MEDIAWIKI        => 'MediaWiki',
-       NS_MEDIAWIKI_TALK   => 'MediaWikipa_rimanakuy',
-       NS_TEMPLATE         => 'Plantilla',
-       NS_TEMPLATE_TALK    => 'Plantillapa_rimanakuy',
-       NS_HELP             => 'Yanapa',
-       NS_HELP_TALK        => 'Yanapapak_rimanakuy',
-       NS_CATEGORY         => 'Samiyachiy',
-       NS_CATEGORY_TALK    => 'Samiyachiy_rimanakuy',
-);
-
 $messages = array(
 # User preference toggles
 'tog-underline'              => 'Tinkikunana uraypi aspishpa rikuchina',
index adc5a76..019fc5a 100644 (file)
@@ -44,7 +44,7 @@ $linkPrefixExtension = false;
 
 $namespaceNames = array(
        NS_MEDIA            => 'माध्यमम्',
-       NS_SPECIAL          => 'विशेषम्',
+       NS_SPECIAL          => 'विशेष',
        NS_TALK             => 'सम्भाषणम्',
        NS_USER             => 'योजकः',
        NS_USER_TALK        => 'योजकसम्भाषणम्',
@@ -63,7 +63,6 @@ $namespaceNames = array(
 
 $namespaceAliases = array(
        'माध्यम'             => NS_MEDIA,
-       'विशेष'              => NS_SPECIAL,
        'संभाषणं'            => NS_TALK,
        'योजकसंभाषणं'        => NS_USER_TALK,
        '$1संभाषणं'         => NS_PROJECT_TALK,
index 7215184..aea4c8b 100644 (file)
@@ -35,10 +35,10 @@ $namespaceNames = array(
        NS_USER             => 'Корисник',
        NS_USER_TALK        => 'Разговор_са_корисником',
        NS_PROJECT_TALK     => 'Разговор_о_$1',
-       NS_FILE             => 'ФаÑ\98л',
-       NS_FILE_TALK        => 'Разговор_о_фајлу',
-       NS_MEDIAWIKI        => 'Ð\9cедиÑ\98аÐ\92ики',
-       NS_MEDIAWIKI_TALK   => 'РазговоÑ\80_о_Ð\9cедиÑ\98аÐ\92икију',
+       NS_FILE             => 'Ð\94аÑ\82оÑ\82ека',
+       NS_FILE_TALK        => 'Разговор_о_датотеци',
+       NS_MEDIAWIKI        => 'Ð\9cедиÑ\98авики',
+       NS_MEDIAWIKI_TALK   => 'РазговоÑ\80_о_Ð\9cедиÑ\98авикију',
        NS_TEMPLATE         => 'Шаблон',
        NS_TEMPLATE_TALK    => 'Разговор_о_шаблону',
        NS_HELP             => 'Помоћ',
@@ -68,10 +68,6 @@ $namespaceAliases = array(
 
        'Слика'                   => NS_FILE,
        'Разговор_о_слици'        => NS_FILE_TALK,
-       "Датотека"                => NS_FILE,
-       "Разговор_о_датотеци"     => NS_FILE_TALK,
-       "Медијавики"              => NS_MEDIAWIKI,
-       "Разговор_о_Медијавикију" => NS_MEDIAWIKI_TALK,
        'МедијаВики'              => NS_MEDIAWIKI,
        'Разговор_о_МедијаВикију' => NS_MEDIAWIKI_TALK,
 );
index a4d4463..01dbb36 100644 (file)
  * @author לערי ריינהארט
  */
 
-$namespaceNames = array(
-       NS_MEDIA            => 'Medya',
-       NS_SPECIAL          => 'Pinaurog',
-       NS_TALK             => 'Hiruhimangraw',
-       NS_USER             => 'Gumaramit',
-       NS_USER_TALK        => 'Hiruhimangaw_hiton_gumaramit',
-       NS_PROJECT_TALK     => 'Hiruhimangraw_hiton_$1',
-       NS_FILE             => 'Fayl',
-       NS_FILE_TALK        => 'Hiruhimangraw_hiton_fayl',
-       NS_MEDIAWIKI        => 'MediaWiki',
-       NS_MEDIAWIKI_TALK   => 'Hiruhimangraw_hiton_MediaWiki',
-       NS_TEMPLATE         => 'Batakan',
-       NS_TEMPLATE_TALK    => 'Hiruhimangraw_hiton_batakan',
-       NS_HELP             => 'Bulig',
-       NS_HELP_TALK        => 'Hiruhimangaw_hiton_bulig',
-       NS_CATEGORY         => 'Kaarangay',
-       NS_CATEGORY_TALK    => 'Hiruhimangraw_hiton_kaarangay',
-);
-
 $specialPageAliases = array(
        'Allpages'                  => array( 'NgatananngaPakli' ),
        'Categories'                => array( 'Mga_kaarangay' ),
index 928dd18..161695e 100644 (file)
@@ -22,11 +22,11 @@ $namespaceNames = array(
        NS_TALK             => '傾偈',
        NS_USER             => '用戶',
        NS_USER_TALK        => '用戶傾偈',
-       NS_PROJECT_TALK     => '$1傾偈',
+       NS_PROJECT_TALK     => '$1_傾偈',
        NS_FILE             => '文件',
        NS_FILE_TALK        => '文件傾偈',
        NS_MEDIAWIKI        => 'MediaWiki',
-       NS_MEDIAWIKI_TALK   => 'MediaWiki傾偈',
+       NS_MEDIAWIKI_TALK   => 'MediaWiki_傾偈',
        NS_TEMPLATE         => '模',
        NS_TEMPLATE_TALK    => '模傾偈',
        NS_HELP             => '幫手',
@@ -47,7 +47,9 @@ $namespaceAliases = array(
        "用户 对话"                 => NS_USER_TALK,
        "用戶 討論"                 => NS_USER_TALK,
        "用户 讨论"                 => NS_USER_TALK,
-       '$1_傾偈'             => NS_PROJECT_TALK,
+       # This has never worked so it's unlikely to annoy anyone if I disable it -- TS
+       # "{$wgMetaNamespace} 討論" => NS_PROJECT_TALK,
+       # "{$wgMetaNamespace} 讨论" => NS_PROJECT_TALK,
        "檔"                   => NS_FILE,
        "檔案"                        => NS_FILE,
        "档"                   => NS_FILE,
@@ -66,7 +68,6 @@ $namespaceAliases = array(
        "图 讨论"            => NS_FILE_TALK,
        "圖像 討論"                 => NS_FILE_TALK,
        "图像 讨论"                 => NS_FILE_TALK,
-       'MediaWiki_傾偈'      => NS_FILE_TALK,
        "模 討論"            => NS_TEMPLATE_TALK,
        "模 讨论"            => NS_TEMPLATE_TALK,
        "幫助"                        => NS_HELP,
diff --git a/maintenance/archives/patch-filejournal.sql b/maintenance/archives/patch-filejournal.sql
deleted file mode 100644 (file)
index b7a7d09..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
--- File backend operation journal
-CREATE TABLE /*_*/filejournal (
-  -- Unique ID for each file operation
-  fj_id bigint unsigned NOT NULL PRIMARY KEY auto_increment,
-  -- UUID of the batch this operation belongs to
-  fj_batch_uuid varbinary(32) NOT NULL,
-  -- The registered file backend name
-  fj_backend varchar(255) NOT NULL,
-  -- The storage path that was affected (may be internal paths)
-  fj_path blob NOT NULL,
-  -- SHA-1 file path hash in base-36
-  fj_path_sha1 varbinary(32) NOT NULL default '',
-  -- Primitive operation description (create/update/delete)
-  fj_op varchar(16) NOT NULL default '',
-  -- SHA-1 file content hash in base-36
-  fj_new_sha1 varbinary(32) NOT NULL default '',
-  -- Timestamp of the batch operation
-  fj_timestamp varbinary(14) NOT NULL default ''
-);
-
-CREATE INDEX /*i*/fj_batch_id ON /*_*/filejournal (fj_batch_uuid,fj_id);
-CREATE INDEX /*i*/fj_path_id ON /*_*/filejournal (fj_path_sha1,fj_id);
-CREATE INDEX /*i*/fj_new_sha1 ON /*_*/filejournal (fj_new_sha1,fj_id);
-CREATE INDEX /*i*/fj_timestamp ON /*_*/filejournal (fj_timestamp);
index cdbd546..c03f3df 100644 (file)
@@ -41,7 +41,9 @@ class TextPassDumper extends BackupDumper {
        var $prefetchCountLast = 0;
        var $fetchCountLast = 0;
 
+       var $failures = 0;
        var $maxFailures = 5;
+       var $failedTextRetrievals = 0;
        var $maxConsecutiveFailedTextRetrievals = 200;
        var $failureTimeout = 5; // Seconds to sleep after db failure
 
@@ -69,54 +71,6 @@ class TextPassDumper extends BackupDumper {
         */
        protected $db;
 
-
-       /**
-        * Drop the database connection $this->db and try to get a new one.
-        *
-        * This function tries to get a /different/ connection if this is 
-        * possible. Hence, (if this is possible) it switches to a different
-        * failover upon each call.
-        *
-        * This function resets $this->lb and closes all connections on it.
-        *
-        * @throws MWException
-        */
-       function rotateDb() {
-               // Cleaning up old connections
-               if ( isset( $this->lb ) ) {
-                       $this->lb->closeAll();
-                       unset( $this->lb );
-               }
-               
-               if ( isset( $this->db ) && $this->db->isOpen() )
-                 {
-                         throw new MWException( 'DB is set and has not been closed by the Load Balancer' );
-                 }
-
-
-               unset( $this->db );
-
-               // Trying to set up new connection.
-               // We do /not/ retry upon failure, but delegate to encapsulating logic, to avoid
-               // individually retrying at different layers of code.
-
-               // 1. The LoadBalancer.
-               try {
-                       $this->lb = wfGetLBFactory()->newMainLB();                      
-               } catch (Exception $e) {
-                       throw new MWException( __METHOD__ . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" );
-               }
-
-
-               // 2. The Connection, through the load balancer.
-               try {
-                       $this->db = $this->lb->getConnection( DB_SLAVE, 'backup' );                             
-               } catch (Exception $e) {
-                       throw new MWException( __METHOD__ . " rotating DB failed to obtain new database (" . $e->getMessage() . ")" );
-               }
-       }
-       
-
        function initProgress( $history ) {
                parent::initProgress();
                $this->timeOfCheckpoint = $this->startTime;
@@ -133,19 +87,7 @@ class TextPassDumper extends BackupDumper {
 
                $this->initProgress( $this->history );
 
-               // We are trying to get an initial database connection to avoid that the
-               // first try of this request's first call to getText fails. However, if
-               // obtaining a good DB connection fails it's not a serious issue, as
-               // getText does retry upon failure and can start without having a working
-               // DB connection.
-               try {
-                       $this->rotateDb();
-               } catch (Exception $e) {
-                       // We do not even count this as failure. Just let eventual
-                       // watchdogs know.
-                       $this->progress( "Getting initial DB connection failed (" . 
-                               $e->getMessage() . ")" );
-               }
+               $this->db = $this->backupDb();
 
                $this->egress = new ExportProgressFilter( $this->sink, $this );
 
@@ -374,142 +316,98 @@ class TextPassDumper extends BackupDumper {
                return true;
        }
 
-       /**
-        * Tries to get the revision text for a revision id.
-        *
-        * Upon errors, retries (Up to $this->maxFailures tries each call).
-        * If still no good revision get could be found even after this retrying, "" is returned.
-        * If no good revision text could be returned for
-        * $this->maxConsecutiveFailedTextRetrievals consecutive calls to getText, MWException
-        * is thrown.
-        *
-        * @param $id string The revision id to get the text for
-        *
-        * @return string The revision text for $id, or ""
-        * @throws MWException
-        */
        function getText( $id ) {
-               $prefetchNotTried = true; // Whether or not we already tried to get the text via prefetch.
-               $text = false; // The candidate for a good text. false if no proper value.
-               $failures = 0; // The number of times, this invocation of getText already failed.
-
-               static $consecutiveFailedTextRetrievals = 0; // The number of times getText failed without
-                                                            // yielding a good text in between.
-
                $this->fetchCount++;
-
-               // To allow to simply return on success and do not have to worry about book keeping,
-               // we assume, this fetch works (possible after some retries). Nevertheless, we koop
-               // the old value, so we can restore it, if problems occur (See after the while loop).
-               $oldConsecutiveFailedTextRetrievals = $consecutiveFailedTextRetrievals;
-               $consecutiveFailedTextRetrievals = 0;
-
-               while ( $failures < $this->maxFailures ) {
-
-                       // As soon as we found a good text for the $id, we will return immediately.
-                       // Hence, if we make it past the try catch block, we know that we did not
-                       // find a good text.
-
-                       try {
-                               // Step 1: Get some text (or reuse from previous iteratuon if checking
-                               //         for plausibility failed)
-
-                               // Trying to get prefetch, if it has not been tried before
-                               if ( $text === false && isset( $this->prefetch ) && $prefetchNotTried ) {
-                                       $prefetchNotTried = false;
-                                       $tryIsPrefetch = true;
-                                       $text = $this->prefetch->prefetch( $this->thisPage, $this->thisRev );
-                                       if ( $text === null ) {
-                                               $text = false;
-                                       }
-                               }
-                               
-                               if ( $text === false ) {
-                                       // Fallback to asking the database
-                                       $tryIsPrefetch = false;
-                                       if ( $this->spawn ) {
-                                               $text = $this->getTextSpawned( $id );
-                                       } else {
-                                               $text = $this->getTextDb( $id );
-                                       }
-                               }
-
-                               if ( $text === false ) {
-                                       throw new MWException( "Generic error while obtaining text for id " . $id );
-                               }
-
-                               // We received a good candidate for the text of $id via some method
-                               
-                               // Step 2: Checking for plausibility and return the text if it is
-                               //         plausible
+               if ( isset( $this->prefetch ) ) {
+                       $text = $this->prefetch->prefetch( $this->thisPage, $this->thisRev );
+                       if ( $text !== null ) { // Entry missing from prefetch dump
+                               $dbr = wfGetDB( DB_SLAVE );
                                $revID = intval( $this->thisRev );
-                               if ( ! isset( $this->db ) ) {
-                                       throw new MWException( "No database available" );
-                               }
-                               $revLength = $this->db->selectField( 'revision', 'rev_len', array( 'rev_id' => $revID ) );                              
+                               $revLength = $dbr->selectField( 'revision', 'rev_len', array( 'rev_id' => $revID ) );
+                               // if length of rev text in file doesn't match length in db, we reload
+                               // this avoids carrying forward broken data from previous xml dumps
                                if( strlen( $text ) == $revLength ) {
-                                       if ( $tryIsPrefetch ) {
-                                               $this->prefetchCount++;
-                                       }
+                                       $this->prefetchCount++;
                                        return $text;
                                }
-                               
-                               $text = false;
-                               throw new MWException( "Received text is unplausible for id " . $id );
-
-                       } catch (Exception $e) {
-                               $msg = "getting/checking text " . $id . " failed (".$e->getMessage().")";
-                               if ( $failures + 1 < $this->maxFailures ) {
-                                       $msg .= " (Will retry " . ( $this->maxFailures - $failures - 1) . " more times)";
-                               }
-                               $this->progress( $msg );
                        }
-                       
-                       // Something went wrong; we did not a text that was plausible :(
-                       $failures++;
-
+               }
+               return $this->doGetText( $id );
+       }
 
-                       // After backing off for some time, we try to reboot the whole process as
-                       // much as possible to not carry over failures from one part to the other
-                       // parts
-                       sleep( $this->failureTimeout );
-                       try {
-                               $this->rotateDb();
-                               if ( $this->spawn ) {
+       private function doGetText( $id ) {
+               $id = intval( $id );
+               $this->failures = 0;
+               $ex = new MWException( "Graceful storage failure" );
+               while (true) {
+                       if ( $this->spawn ) {
+                               if ($this->failures) {
+                                       // we don't know why it failed, could be the child process
+                                       // borked, could be db entry busted, could be db server out to lunch,
+                                       // so cover all bases
                                        $this->closeSpawn();
                                        $this->openSpawn();
                                }
-                       } catch (Exception $e) {
-                               $this->progress( "Rebooting getText infrastructure failed (".$e->getMessage().")" .
-                                       " Trying to continue anyways" );
+                               $text = $this->getTextSpawned( $id );
+                       } else {
+                               $text = $this->getTextDbSafe( $id );
+                       }
+                       if ( $text === false ) {
+                               $this->failures++;
+                               if ( $this->failures > $this->maxFailures) {
+                                       $this->progress( "Failed to retrieve revision text for text id ".
+                                                                        "$id after $this->maxFailures tries, giving up" );
+                                       // were there so many bad retrievals in a row we want to bail?
+                                       // at some point we have to declare the dump irretrievably broken
+                                       $this->failedTextRetrievals++;
+                                       if ($this->failedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals) {
+                                               throw $ex;
+                                       } else {
+                                               // would be nice to return something better to the caller someday,
+                                               // log what we know about the failure and about the revision
+                                               return "";
+                                       }
+                               } else {
+                                       $this->progress( "Error $this->failures " .
+                                                                "of allowed $this->maxFailures retrieving revision text for text id $id! " .
+                                                                "Pausing $this->failureTimeout seconds before retry..." );
+                                       sleep( $this->failureTimeout );
+                               }
+                       } else {
+                               $this->failedTextRetrievals= 0;
+                               return $text;
                        }
                }
+               return '';
+       }
 
-               // Retirieving a good text for $id failed (at least) maxFailures times.
-               // We abort for this $id.
-
-               // Restoring the consecutive failures, and maybe aborting, if the dump
-               // is too broken.
-               $consecutiveFailedTextRetrievals = $oldConsecutiveFailedTextRetrievals + 1;
-               if ( $consecutiveFailedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals ) {
-                       throw new MWException( "Graceful storage failure" );
+       /**
+        * Fetch a text revision from the database, retrying in case of failure.
+        * This may survive some transitory errors by reconnecting, but
+        * may not survive a long-term server outage.
+        *
+        * FIXME: WTF? Why is it using a loop and then returning unconditionally?
+        * @param $id int
+        * @return bool|string
+        */
+       private function getTextDbSafe( $id ) {
+               while ( true ) {
+                       try {
+                               $text = $this->getTextDb( $id );
+                       } catch ( DBQueryError $ex ) {
+                               $text = false;
+                       }
+                       return $text;
                }
-
-               return "";
        }
 
-
        /**
         * May throw a database error if, say, the server dies during query.
         * @param $id
         * @return bool|string
-        * @throws MWException
         */
        private function getTextDb( $id ) {
                global $wgContLang;
-               if ( ! isset( $this->db ) ) {
-                       throw new MWException( __METHOD__ . "No database available" );
-               }
                $row = $this->db->selectRow( 'text',
                        array( 'old_text', 'old_flags' ),
                        array( 'old_id' => $id ),
index 093305e..c9afbfa 100644 (file)
@@ -408,7 +408,6 @@ $wgMessageStructure = array(
                'customjsprotected',
                'ns-specialprotected',
                'titleprotected',
-               'filereadonlyerror'
        ),
        'virus' => array(
                'virus-badscanner',
@@ -1378,11 +1377,6 @@ $wgMessageStructure = array(
                'backend-fail-batchsize'
        ),
 
-       'filejournal-errors' => array(
-               'filejournal-fail-dbconnect',
-               'filejournal-fail-dbquery'
-       ),
-
        'lockmanager-errors' => array(
                'lockmanager-notlocked',
                'lockmanager-fail-closelock',
index 8d3b8fa..f5f09f5 100644 (file)
  */
 ( function ( $, mw, undefined ) {
 
-       /**
-        * The name of the page to watch or unwatch.
-        */
-       var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
-
-       /**
-        * Update the link text, link href attribute and (if applicable)
-        * "loading" class.
-        *
-        * @param $link {jQuery} Anchor tag of (un)watch link.
-        * @param action {String} One of 'watch', 'unwatch'.
-        * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'.
-        */
-       function updateWatchLink( $link, action, state ) {
-               var accesskeyTip, msgKey, $li;
-
-               // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
-               msgKey = state === 'loading' ? action + 'ing' : action;
-               accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp );
+/**
+ * The name of the page to watch or unwatch.
+ */
+var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) );
+
+/**
+ * Update the link text, link href attribute and (if applicable)
+ * "loading" class.
+ *
+ * @param $link {jQuery} Anchor tag of (un)watch link
+ * @param action {String} One of 'watch', 'unwatch'.
+ * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'.
+ */
+function updateWatchLink( $link, action, state ) {
+       // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
+       var     msgKey = state === 'loading' ? action + 'ing' : action,
+               accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp ),
                $li = $link.closest( 'li' );
 
-               $link
-                       .text( mw.msg( msgKey ) )
-                       .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
-                               ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
-                       )
-                       .attr( 'href', mw.util.wikiScript() + '?' + $.param({
-                                       title: title,
-                                       action: action
-                               })
-                       );
-
-               // Special case for vector icon
-               if ( $li.hasClass( 'icon' ) ) {
-                       if ( state === 'loading' ) {
-                               $link.addClass( 'loading' );
-                       } else {
-                               $link.removeClass( 'loading' );
-                       }
+       $link
+               .text( mw.msg( msgKey ) )
+               .attr( 'title', mw.msg( 'tooltip-ca-' + action ) +
+                       ( accesskeyTip ? ' ' + accesskeyTip[0] : '' )
+               )
+               .attr( 'href', mw.util.wikiScript() + '?' + $.param({
+                               title: title,
+                               action: action
+                       })
+               );
+
+       // Special case for vector icon
+       if ( $li.hasClass( 'icon' ) ) {
+               if ( state === 'loading' ) {
+                       $link.addClass( 'loading' );
+               } else {
+                       $link.removeClass( 'loading' );
                }
        }
+}
 
-       /**
-        * @todo This should be moved somewhere more accessible.
-        * @param url {String}
-        * @return {String} The extracted action, defaults to 'view'.
-        */
-       function mwUriGetAction( url ) {
-               var action, actionPaths, key, i, m, parts;
-
-               actionPaths = mw.config.get( 'wgActionPaths' );
-
-               // @todo: Does MediaWiki give action path or query param
-               // precedence ? If the former, move this to the bottom
-               action = mw.util.getParamValue( 'action', url );
-               if ( action !== null ) {
-                       return action;
-               }
-
-               for ( key in actionPaths ) {
-                       if ( actionPaths.hasOwnProperty( key ) ) {
-                               parts = actionPaths[key].split( '$1' );
-                               for ( i = 0; i < parts.length; i += 1 ) {
-                                       parts[i] = $.escapeRE( parts[i] );
-                               }
-                               m = new RegExp( parts.join( '(.+)' ) ).exec( url );
-                               if ( m && m[1] ) {
-                                       return key;
-                               }
+/**
+ * @todo This should be moved somewhere more accessible.
+ * @param url {String}
+ * @return {String} The extracted action, defaults to 'view'.
+ */
+function mwUriGetAction( url ) {
+       var     actionPaths = mw.config.get( 'wgActionPaths' ),
+               key, parts, m, action;
+
+       // @todo: Does MediaWiki give action path or query param
+       // precedence ? If the former, move this to the bottom
+       action = mw.util.getParamValue( 'action', url );
+       if ( action !== null ) {
+               return action;
+       }
 
+       for ( key in actionPaths ) {
+               if ( actionPaths.hasOwnProperty( key ) ) {
+                       parts = actionPaths[key].split( '$1' );
+                       for ( i = 0; i < parts.length; i += 1 ) {
+                               parts[i] = $.escapeRE( parts[i] );
                        }
+                       m = new RegExp( parts.join( '(.+)' ) ).exec( url );
+                       if ( m && m[1] ) {
+                               return key;
+                       }
+               
                }
-
-               return 'view';
        }
 
-       $( document ).ready( function () {
-               var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
-                       '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
-                       '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
+       return 'view';
+}
 
-               // Allowing people to add inline animated links is a little scary
-               $links = $links.filter( ':not( #bodyContent *, #content * )' );
+$( document ).ready( function() {
+       var $links = $( '.mw-watchlink a, a.mw-watchlink, ' +
+               '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' +
+               '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' );
 
-               $links.click( function ( e ) {
-                       var action, api, $link; 
+       // Allowing people to add inline animated links is a little scary
+       $links = $links.filter( ':not( #bodyContent *, #content * )' );
 
+       $links.click( function( e ) {
+               var     $link, api,
                        action = mwUriGetAction( this.href );
 
-                       if ( action !== 'watch' && action !== 'unwatch' ) {
-                               // Could not extract target action from link url,
-                               // let native browsing handle it further
-                               return true;
-                       }
-                       e.preventDefault();
-                       e.stopPropagation();
-
-                       $link = $( this );
-
-                       updateWatchLink( $link, action, 'loading' );
-
-                       api = new mw.Api();
-                       api[action](
-                               title,
-                               // Success
-                               function ( watchResponse ) {
-                                       var $li, otherAction;
-
-                                       otherAction = action === 'watch' ? 'unwatch' : 'watch';
+               if ( action !== 'watch' && action !== 'unwatch' ) {
+                       // Could not extract target action from link url,
+                       // let native browsing handle it further
+                       return true;
+               }
+               e.preventDefault();
+               e.stopPropagation();
+               
+               $link = $( this );
+
+               updateWatchLink( $link, action, 'loading' );
+
+               api = new mw.Api();
+               api[action](
+                       title,
+                       // Success
+                       function( watchResponse ) {
+                               var     otherAction = action === 'watch' ? 'unwatch' : 'watch',
                                        $li = $link.closest( 'li' );
 
-                                       mw.util.jsMessage( watchResponse.message, 'ajaxwatch' );
-
-                                       // Set link to opposite
-                                       updateWatchLink( $link, otherAction );
-
-                                       // Most common ID style
-                                       if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) {
-                                               $li.prop( 'id', 'ca-' + otherAction );
-                                       }
-
-                                       // Bug 12395 - update the watch checkbox on edit pages when the
-                                       // page is watched or unwatched via the tab.
-                                       if ( watchResponse.watched !== undefined ) {
-                                               $( '#wpWatchthis' ).prop( 'checked', true );
-                                       } else {
-                                               $( '#wpWatchthis' ).removeProp( 'checked' );
-                                       }
-                               },
-                               // Error
-                               function () {
-                                       var cleanTitle, html, link;
-
-                                       // Reset link to non-loading mode
-                                       updateWatchLink( $link, action );
-
-                                       // Format error message
-                                       cleanTitle = title.replace( /_/g, ' ' );
-                                       link = mw.html.element(
-                                               'a', {
-                                                       href: mw.util.wikiGetlink( title ),
-                                                       title: cleanTitle
-                                               }, cleanTitle
-                                       );
-                                       html = mw.msg( 'watcherrortext', link );
-
-                                       // Report to user about the error
-                                       mw.util.jsMessage( html, 'ajaxwatch' );
+                               mw.util.jsMessage( watchResponse.message, 'ajaxwatch' );
+
+                               // Set link to opposite
+                               updateWatchLink( $link, otherAction );
 
+                               // Most common ID style
+                               if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) {
+                                       $li.prop( 'id', 'ca-' + otherAction );
+                               }
+                               
+                               // Bug 12395 - update the watch checkbox on edit pages when the
+                               // page is watched or unwatched via the tab.
+                               if ( watchResponse.watched !== undefined ) {
+                                       $( '#wpWatchthis' ).prop( 'checked', true );
+                               } else {
+                                       $( '#wpWatchthis' ).removeProp( 'checked' );
                                }
-                       );
-               });
+                       },
+                       // Error
+                       function(){             
+
+                               // Reset link to non-loading mode
+                               updateWatchLink( $link, action );
+                               
+                               // Format error message
+                               var cleanTitle = title.replace( /_/g, ' ' );
+                               var link = mw.html.element(
+                                       'a', {
+                                               'href': mw.util.wikiGetlink( title ),
+                                               'title': cleanTitle
+                                       }, cleanTitle
+                               );
+                               var html = mw.msg( 'watcherrortext', link );
+                               
+                               // Report to user about the error
+                               mw.util.jsMessage( html, 'ajaxwatch' );
+
+                       }
+               );
        });
 
-}( jQuery, mediaWiki ) );
+});
+
+})( jQuery, mediaWiki );
index 302a2d3..8ed6832 100644 (file)
@@ -4,51 +4,47 @@
  */
 ( function( $, mw ) {
 
-       /**
-        * @context {mw.Api}
-        */
-       function doWatchInternal( page, success, err, addParams ) {
-               var params = {
-                       action: 'watch',
-                       title: String( page ),
-                       token: mw.user.tokens.get( 'watchToken' ),
-                       uselang: mw.config.get( 'wgUserLanguage' )
-               };
-               function ok( data ) {
-                       success( data.watch );
-               }
-               if ( addParams ) {
-                       $.extend( params, addParams );
-               }
-               return this.post( params, { ok: ok, err: err } );
-       }
-
        $.extend( mw.Api.prototype, {
                /**
                 * Convinience method for 'action=watch'.
                 *
                 * @param page {String|mw.Title} Full page name or instance of mw.Title
-                * @param success {Function} Callback to which the watch object will be passed.
-                * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and
+                * @param success {Function} callback to which the watch object will be passed
+                * watch object contains 'title' (full page name), 'watched' (boolean) and
                 * 'message' (parsed HTML of the 'addedwatchtext' message).
-                * @param err {Function} Error callback (optional)
+                * @param _unwatch {Boolean} Internally used to re-use this logic for unwatch(),
+                * do not use outside this module.
+                * @param err {Function} callback if error (optional)
                 * @return {jqXHR}
                 */
-               watch: function ( page, success, err ) {
-                       return doWatchInternal.call( this, page, success, err );
+               watch: function( page, success, err, _unwatch ) {
+                       var params, ok;
+                       params = {
+                               action: 'watch',
+                               title: String( page ),
+                               token: mw.user.tokens.get( 'watchToken' ),
+                               uselang: mw.config.get( 'wgUserLanguage' )
+                       };
+                       if ( _unwatch ) {
+                               params.unwatch = 1;
+                       }
+                       ok = function( data ) {
+                               success( data.watch );
+                       };
+                       return this.post( params, { ok: ok, err: err } );
                },
                /**
                 * Convinience method for 'action=watch&unwatch=1'.
                 *
                 * @param page {String|mw.Title} Full page name or instance of mw.Title
-                * @param success {Function} Callback to which the watch object will be passed.
-                * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and
+                * @param success {Function} callback to which the watch object will be passed
+                * watch object contains 'title' (full page name), 'unwatched' (boolean) and
                 * 'message' (parsed HTML of the 'removedwatchtext' message).
-                * @param err {Function} Error callback (optional)
+                * @param err {Function} callback if error (optional)
                 * @return {jqXHR}
                 */
-               unwatch: function ( page, success, err ) {
-                       return doWatchInternal.call( this, page, success, err, { unwatch: 1 } );
+               unwatch: function( page, success, err ) {
+                       return this.watch( page, success, err, true );
                }
 
        } );