final protected static function isValidContainerName( $container ) {
// This accounts for Swift and S3 restrictions while leaving room
// for things like '.xxx' (hex shard chars) or '.seg' (segments).
+ // This disallows directory separators or traversal characters.
// Note that matching strings URL encode to the same string;
// in Swift, the length restriction is *after* URL encoding.
return preg_match( '/^[a-z0-9][a-z0-9-_]{0,199}$/i', $container );
/** @var Array Prioritized list of FileBackendStore objects */
protected $backends = array(); // array of (backend index => backends)
protected $masterIndex = -1; // integer; index of master backend
+ protected $syncChecks = 0; // integer bitfield
+
+ /* Possible internal backend consistency checks */
+ const CHECK_SIZE = 1;
+ const CHECK_TIME = 2;
/**
* Construct a proxy backend that consists of several internal backends.
* FileBackendStore class, but with these additional settings:
* 'class' : The name of the backend class
* 'isMultiMaster' : This must be set for one backend.
+ * 'syncChecks' : Integer bitfield of internal backend sync checks to perform.
+ * Possible bits include self::CHECK_SIZE and self::CHECK_TIME.
+ * The checks are done before allowing any file operations.
* @param $config Array
*/
public function __construct( array $config ) {
if ( $this->masterIndex < 0 ) { // need backends and must have a master
throw new MWException( 'No master backend defined.' );
}
+ $this->syncChecks = isset( $config['syncChecks'] )
+ ? $config['syncChecks']
+ : self::CHECK_SIZE;
}
/**
*/
public function consistencyCheck( array $paths ) {
$status = Status::newGood();
+ if ( $this->syncChecks == 0 ) {
+ return $status; // skip checks
+ }
$mBackend = $this->backends[$this->masterIndex];
foreach ( array_unique( $paths ) as $path ) {
if ( $mStat ) { // file is in master
if ( !$cStat ) { // file should exist
$status->fatal( 'backend-fail-synced', $path );
- } elseif ( $cStat['size'] != $mStat['size'] ) { // wrong size
- $status->fatal( 'backend-fail-synced', $path );
- } else {
+ continue;
+ }
+ if ( $this->syncChecks & self::CHECK_SIZE ) {
+ if ( $cStat['size'] != $mStat['size'] ) { // wrong size
+ $status->fatal( 'backend-fail-synced', $path );
+ continue;
+ }
+ }
+ if ( $this->syncChecks & self::CHECK_TIME ) {
$mTs = wfTimestamp( TS_UNIX, $mStat['mtime'] );
$cTs = wfTimestamp( TS_UNIX, $cStat['mtime'] );
if ( abs( $mTs - $cTs ) > 30 ) { // outdated file somewhere
$status->fatal( 'backend-fail-synced', $path );
+ continue;
}
}
} else { // file is not in master