Example #1
0
 /**
  * Release the locks when this goes out of scope
  */
 function __destruct()
 {
     $wasOk = $this->status->isOK();
     $this->status->merge($this->manager->unlockByType($this->pathsByType));
     if ($wasOk) {
         // Make sure StatusValue is OK, despite any unlockFiles() fatals
         $this->status->setResult(true, $this->status->value);
     }
 }
Example #2
0
 /**
  * Merge another status object into this one
  *
  * @param Status $other Other Status object
  * @param bool $overwriteValue Whether to override the "value" member
  */
 public function merge($other, $overwriteValue = false)
 {
     $this->sv->merge($other->sv, $overwriteValue);
 }
Example #3
0
 /**
  * Attempt a list of file operations sub-batches in series.
  *
  * The operations *in* each sub-batch will be done in parallel.
  * The caller is responsible for making sure the operations
  * within any given sub-batch do not depend on each other.
  * This will abort remaining ops on failure.
  *
  * @param array $pPerformOps Batches of file ops (batches use original indexes)
  * @param StatusValue $status
  */
 protected static function runParallelBatches(array $pPerformOps, StatusValue $status)
 {
     $aborted = false;
     // set to true on unexpected errors
     foreach ($pPerformOps as $performOpsBatch) {
         /** @var FileOp[] $performOpsBatch */
         if ($aborted) {
             // check batch op abort flag...
             // We can't continue (even with $ignoreErrors) as $predicates is wrong.
             // Log the remaining ops as failed for recovery...
             foreach ($performOpsBatch as $i => $fileOp) {
                 $status->success[$i] = false;
                 ++$status->failCount;
                 $performOpsBatch[$i]->logFailure('attempt_aborted');
             }
             continue;
         }
         /** @var StatusValue[] $statuses */
         $statuses = [];
         $opHandles = [];
         // Get the backend; all sub-batch ops belong to a single backend
         /** @var FileBackendStore $backend */
         $backend = reset($performOpsBatch)->getBackend();
         // Get the operation handles or actually do it if there is just one.
         // If attemptAsync() returns a StatusValue, it was either due to an error
         // or the backend does not support async ops and did it synchronously.
         foreach ($performOpsBatch as $i => $fileOp) {
             if (!isset($status->success[$i])) {
                 // didn't already fail in precheck()
                 // Parallel ops may be disabled in config due to missing dependencies,
                 // (e.g. needing popen()). When they are, $performOpsBatch has size 1.
                 $subStatus = count($performOpsBatch) > 1 ? $fileOp->attemptAsync() : $fileOp->attempt();
                 if ($subStatus->value instanceof FileBackendStoreOpHandle) {
                     $opHandles[$i] = $subStatus->value;
                     // deferred
                 } else {
                     $statuses[$i] = $subStatus;
                     // done already
                 }
             }
         }
         // Try to do all the operations concurrently...
         $statuses = $statuses + $backend->executeOpHandlesInternal($opHandles);
         // Marshall and merge all the responses (blocking)...
         foreach ($performOpsBatch as $i => $fileOp) {
             if (!isset($status->success[$i])) {
                 // didn't already fail in precheck()
                 $subStatus = $statuses[$i];
                 $status->merge($subStatus);
                 if ($subStatus->isOK()) {
                     $status->success[$i] = true;
                     ++$status->successCount;
                 } else {
                     $status->success[$i] = false;
                     ++$status->failCount;
                     $aborted = true;
                     // set abort flag; we can't continue
                 }
             }
         }
     }
 }