MediaWiki  1.23.12
FileOpBatch.php
Go to the documentation of this file.
1 <?php
34 class FileOpBatch {
35  /* Timeout related parameters */
36  const MAX_BATCH_SIZE = 1000; // integer
37 
57  public static function attempt( array $performOps, array $opts, FileJournal $journal ) {
58  $section = new ProfileSection( __METHOD__ );
59  $status = Status::newGood();
60 
61  $n = count( $performOps );
62  if ( $n > self::MAX_BATCH_SIZE ) {
63  $status->fatal( 'backend-fail-batchsize', $n, self::MAX_BATCH_SIZE );
64 
65  return $status;
66  }
67 
68  $batchId = $journal->getTimestampedUUID();
69  $ignoreErrors = !empty( $opts['force'] );
70  $journaled = empty( $opts['nonJournaled'] );
71  $maxConcurrency = isset( $opts['concurrency'] ) ? $opts['concurrency'] : 1;
72 
73  $entries = array(); // file journal entry list
74  $predicates = FileOp::newPredicates(); // account for previous ops in prechecks
75  $curBatch = array(); // concurrent FileOp sub-batch accumulation
76  $curBatchDeps = FileOp::newDependencies(); // paths used in FileOp sub-batch
77  $pPerformOps = array(); // ordered list of concurrent FileOp sub-batches
78  $lastBackend = null; // last op backend name
79  // Do pre-checks for each operation; abort on failure...
80  foreach ( $performOps as $index => $fileOp ) {
81  $backendName = $fileOp->getBackend()->getName();
82  $fileOp->setBatchId( $batchId ); // transaction ID
83  // Decide if this op can be done concurrently within this sub-batch
84  // or if a new concurrent sub-batch must be started after this one...
85  if ( $fileOp->dependsOn( $curBatchDeps )
86  || count( $curBatch ) >= $maxConcurrency
87  || ( $backendName !== $lastBackend && count( $curBatch ) )
88  ) {
89  $pPerformOps[] = $curBatch; // push this batch
90  $curBatch = array(); // start a new sub-batch
91  $curBatchDeps = FileOp::newDependencies();
92  }
93  $lastBackend = $backendName;
94  $curBatch[$index] = $fileOp; // keep index
95  // Update list of affected paths in this batch
96  $curBatchDeps = $fileOp->applyDependencies( $curBatchDeps );
97  // Simulate performing the operation...
98  $oldPredicates = $predicates;
99  $subStatus = $fileOp->precheck( $predicates ); // updates $predicates
100  $status->merge( $subStatus );
101  if ( $subStatus->isOK() ) {
102  if ( $journaled ) { // journal log entries
103  $entries = array_merge( $entries,
104  $fileOp->getJournalEntries( $oldPredicates, $predicates ) );
105  }
106  } else { // operation failed?
107  $status->success[$index] = false;
108  ++$status->failCount;
109  if ( !$ignoreErrors ) {
110  return $status; // abort
111  }
112  }
113  }
114  // Push the last sub-batch
115  if ( count( $curBatch ) ) {
116  $pPerformOps[] = $curBatch;
117  }
118 
119  // Log the operations in the file journal...
120  if ( count( $entries ) ) {
121  $subStatus = $journal->logChangeBatch( $entries, $batchId );
122  if ( !$subStatus->isOK() ) {
123  return $subStatus; // abort
124  }
125  }
126 
127  if ( $ignoreErrors ) { // treat precheck() fatals as mere warnings
128  $status->setResult( true, $status->value );
129  }
130 
131  // Attempt each operation (in parallel if allowed and possible)...
132  self::runParallelBatches( $pPerformOps, $status );
133 
134  return $status;
135  }
136 
148  protected static function runParallelBatches( array $pPerformOps, Status $status ) {
149  $aborted = false; // set to true on unexpected errors
150  foreach ( $pPerformOps as $performOpsBatch ) {
151  if ( $aborted ) { // check batch op abort flag...
152  // We can't continue (even with $ignoreErrors) as $predicates is wrong.
153  // Log the remaining ops as failed for recovery...
154  foreach ( $performOpsBatch as $i => $fileOp ) {
155  $performOpsBatch[$i]->logFailure( 'attempt_aborted' );
156  }
157  continue;
158  }
159  $statuses = array();
160  $opHandles = array();
161  // Get the backend; all sub-batch ops belong to a single backend
162  $backend = reset( $performOpsBatch )->getBackend();
163  // Get the operation handles or actually do it if there is just one.
164  // If attemptAsync() returns a Status, it was either due to an error
165  // or the backend does not support async ops and did it synchronously.
166  foreach ( $performOpsBatch as $i => $fileOp ) {
167  if ( !isset( $status->success[$i] ) ) { // didn't already fail in precheck()
168  // Parallel ops may be disabled in config due to missing dependencies,
169  // (e.g. needing popen()). When they are, $performOpsBatch has size 1.
170  $subStatus = ( count( $performOpsBatch ) > 1 )
171  ? $fileOp->attemptAsync()
172  : $fileOp->attempt();
173  if ( $subStatus->value instanceof FileBackendStoreOpHandle ) {
174  $opHandles[$i] = $subStatus->value; // deferred
175  } else {
176  $statuses[$i] = $subStatus; // done already
177  }
178  }
179  }
180  // Try to do all the operations concurrently...
181  $statuses = $statuses + $backend->executeOpHandlesInternal( $opHandles );
182  // Marshall and merge all the responses (blocking)...
183  foreach ( $performOpsBatch as $i => $fileOp ) {
184  if ( !isset( $status->success[$i] ) ) { // didn't already fail in precheck()
185  $subStatus = $statuses[$i];
186  $status->merge( $subStatus );
187  if ( $subStatus->isOK() ) {
188  $status->success[$i] = true;
189  ++$status->successCount;
190  } else {
191  $status->success[$i] = false;
192  ++$status->failCount;
193  $aborted = true; // set abort flag; we can't continue
194  }
195  }
196  }
197  }
198  }
199 }
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
Status\merge
merge( $other, $overwriteValue=false)
Merge another status object into this one.
Definition: Status.php:325
$n
$n
Definition: RandomTest.php:76
Status\newGood
static newGood( $value=null)
Factory function for good results.
Definition: Status.php:77
Status
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:40
ProfileSection
Class for handling function-scope profiling.
Definition: Profiler.php:60
FileJournal
Class for handling file operation journaling.
Definition: FileJournal.php:38
FileJournal\logChangeBatch
logChangeBatch(array $entries, $batchId)
Log changes made by a batch file operation.
Definition: FileJournal.php:98
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
$section
$section
Definition: Utf8Test.php:88
FileOpBatch\attempt
static attempt(array $performOps, array $opts, FileJournal $journal)
Attempt to perform a series of file operations.
Definition: FileOpBatch.php:57
FileOpBatch
Helper class for representing batch file operations.
Definition: FileOpBatch.php:34
FileBackendStoreOpHandle
FileBackendStore helper class for performing asynchronous file operations.
Definition: FileBackendStore.php:1812
FileOpBatch\MAX_BATCH_SIZE
const MAX_BATCH_SIZE
Definition: FileOpBatch.php:36
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
FileOpBatch\runParallelBatches
static runParallelBatches(array $pPerformOps, Status $status)
Attempt a list of file operations sub-batches in series.
Definition: FileOpBatch.php:148
FileJournal\getTimestampedUUID
getTimestampedUUID()
Get a statistically unique ID string.
Definition: FileJournal.php:77
FileOp\newDependencies
static newDependencies()
Get a new empty dependency tracking array for paths read/written to.
Definition: FileOp.php:150
FileOp\newPredicates
static newPredicates()
Get a new empty predicates array for precheck()
Definition: FileOp.php:141