PageRenderTime 43ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/backwpup/sdk/Aws/Aws/S3/Model/MultipartUpload/ParallelTransfer.php

https://bitbucket.org/cesarmedrano/cesarmedrano
PHP | 124 lines | 68 code | 16 blank | 40 comment | 12 complexity | aec4bcf415f03aa4810612a2eee1064d MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License").
  6. * You may not use this file except in compliance with the License.
  7. * A copy of the License is located at
  8. *
  9. * http://aws.amazon.com/apache2.0
  10. *
  11. * or in the "license" file accompanying this file. This file is distributed
  12. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  13. * express or implied. See the License for the specific language governing
  14. * permissions and limitations under the License.
  15. */
  16. namespace Aws\S3\Model\MultipartUpload;
  17. use Aws\Common\Exception\RuntimeException;
  18. use Aws\Common\Enum\DateFormat;
  19. use Aws\Common\Enum\UaString as Ua;
  20. use Guzzle\Http\EntityBody;
  21. use Guzzle\Http\ReadLimitEntityBody;
  22. /**
  23. * Transfers multipart upload parts in parallel
  24. */
  25. class ParallelTransfer extends AbstractTransfer
  26. {
  27. /**
  28. * {@inheritdoc}
  29. */
  30. protected function init()
  31. {
  32. parent::init();
  33. if (!$this->source->isLocal() || $this->source->getWrapper() != 'plainfile') {
  34. throw new RuntimeException('The source data must be a local file stream when uploading in parallel.');
  35. }
  36. if (empty($this->options['concurrency'])) {
  37. throw new RuntimeException('The `concurrency` option must be specified when instantiating.');
  38. }
  39. }
  40. /**
  41. * {@inheritdoc}
  42. */
  43. protected function transfer()
  44. {
  45. $totalParts = (int) ceil($this->source->getContentLength() / $this->partSize);
  46. $concurrency = min($totalParts, $this->options['concurrency']);
  47. $partsToSend = $this->prepareParts($concurrency);
  48. $eventData = $this->getEventData();
  49. while (!$this->stopped && count($this->state) < $totalParts) {
  50. $currentTotal = count($this->state);
  51. $commands = array();
  52. for ($i = 0; $i < $concurrency && $i + $currentTotal < $totalParts; $i++) {
  53. // Move the offset to the correct position
  54. $partsToSend[$i]->setOffset(($currentTotal + $i) * $this->partSize);
  55. // @codeCoverageIgnoreStart
  56. if ($partsToSend[$i]->getContentLength() == 0) {
  57. break;
  58. }
  59. // @codeCoverageIgnoreEnd
  60. $params = $this->state->getUploadId()->toParams();
  61. $eventData['command'] = $this->client->getCommand('UploadPart', array_replace($params, array(
  62. 'PartNumber' => count($this->state) + 1 + $i,
  63. 'Body' => $partsToSend[$i],
  64. 'ContentMD5' => (bool) $this->options['part_md5'],
  65. Ua::OPTION => Ua::MULTIPART_UPLOAD
  66. )));
  67. $commands[] = $eventData['command'];
  68. // Notify any listeners of the part upload
  69. $this->dispatch(self::BEFORE_PART_UPLOAD, $eventData);
  70. }
  71. // Allow listeners to stop the transfer if needed
  72. if ($this->stopped) {
  73. break;
  74. }
  75. // Execute each command, iterate over the results, and add to the transfer state
  76. /** @var $command \Guzzle\Service\Command\OperationCommand */
  77. foreach ($this->client->execute($commands) as $command) {
  78. $this->state->addPart(UploadPart::fromArray(array(
  79. 'PartNumber' => count($this->state) + 1,
  80. 'ETag' => $command->getResponse()->getHeader('ETag', true),
  81. 'Size' => (int) $command->getResponse()->getHeader('Content-Length', true),
  82. 'LastModified' => gmdate(DateFormat::RFC2822)
  83. )));
  84. $eventData['command'] = $command;
  85. // Notify any listeners the the part was uploaded
  86. $this->dispatch(self::AFTER_PART_UPLOAD, $eventData);
  87. }
  88. }
  89. }
  90. /**
  91. * Prepare the entity body handles to use while transferring
  92. *
  93. * @param int $concurrency Number of parts to prepare
  94. *
  95. * @return array Parts to send
  96. */
  97. protected function prepareParts($concurrency)
  98. {
  99. $url = $this->source->getUri();
  100. // Use the source EntityBody as the first part
  101. $parts = array(new ReadLimitEntityBody($this->source, $this->partSize));
  102. // Open EntityBody handles for each part to upload in parallel
  103. for ($i = 1; $i < $concurrency; $i++) {
  104. $parts[] = new ReadLimitEntityBody(new EntityBody(fopen($url, 'r')), $this->partSize);
  105. }
  106. return $parts;
  107. }
  108. }