Overview
  • Namespace
  • Class

Namespaces

  • OpenCloud
    • Autoscale
      • Resource
    • CloudMonitoring
      • Collection
      • Exception
      • Resource
    • Common
      • Collection
      • Constants
      • Exceptions
      • Http
        • Message
      • Log
      • Resource
      • Service
    • Compute
      • Constants
      • Exception
      • Resource
    • Database
      • Resource
    • DNS
      • Collection
      • Resource
    • Identity
      • Constants
      • Resource
    • Image
      • Enum
      • Resource
        • JsonPatch
        • Schema
    • LoadBalancer
      • Collection
      • Enum
      • Resource
    • Networking
      • Resource
    • ObjectStore
      • Constants
      • Exception
      • Resource
      • Upload
    • Orchestration
      • Resource
    • Queues
      • Collection
      • Exception
      • Resource
    • Volume
      • Resource

Classes

  • OpenCloud\Volume\Resource\Snapshot
  • OpenCloud\Volume\Resource\Volume
  • OpenCloud\Volume\Resource\VolumeType
  1 <?php
  2 /**
  3  * Copyright 2012-2014 Rackspace US, Inc.
  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  * You may obtain a copy of the License at
  8  *
  9  * http://www.apache.org/licenses/LICENSE-2.0
 10  *
 11  * Unless required by applicable law or agreed to in writing, software
 12  * distributed under the License is distributed on an "AS IS" BASIS,
 13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  * See the License for the specific language governing permissions and
 15  * limitations under the License.
 16  */
 17 
 18 namespace OpenCloud\ObjectStore\Upload;
 19 
 20 use Exception;
 21 use Guzzle\Http\EntityBody;
 22 use OpenCloud\Common\Exceptions\RuntimeException;
 23 use OpenCloud\Common\Http\Client;
 24 use OpenCloud\ObjectStore\Exception\UploadException;
 25 
 26 /**
 27  * Contains abstract functionality for transfer objects.
 28  */
 29 class AbstractTransfer
 30 {
 31     /**
 32      * Minimum chunk size is 1MB.
 33      */
 34     const MIN_PART_SIZE = 1048576;
 35 
 36     /**
 37      * Maximum chunk size is 5GB.
 38      */
 39     const MAX_PART_SIZE = 5368709120;
 40 
 41     /**
 42      * Default chunk size is 1GB.
 43      */
 44     const DEFAULT_PART_SIZE = 1073741824;
 45 
 46     /**
 47      * @var \OpenCloud\Common\Http\Client The client object which handles all HTTP interactions
 48      */
 49     protected $client;
 50 
 51     /**
 52      * @var \Guzzle\Http\EntityBody The payload being transferred
 53      */
 54     protected $entityBody;
 55 
 56     /**
 57      * The current state of the transfer responsible for, among other things, holding an itinerary of uploaded parts
 58      *
 59      * @var \OpenCloud\ObjectStore\Upload\TransferState
 60      */
 61     protected $transferState;
 62 
 63     /**
 64      * @var array User-defined key/pair options
 65      */
 66     protected $options;
 67 
 68     /**
 69      * @var int
 70      */
 71     protected $partSize;
 72 
 73     /**
 74      * @var array Defaults that will always override user-defined options
 75      */
 76     protected $defaultOptions = array(
 77         'concurrency'    => true,
 78         'partSize'       => self::DEFAULT_PART_SIZE,
 79         'prefix'         => 'segment',
 80         'doPartChecksum' => true
 81     );
 82 
 83     /**
 84      * @return static
 85      */
 86     public static function newInstance()
 87     {
 88         return new static();
 89     }
 90 
 91     /**
 92      * @param Client $client
 93      * @return $this
 94      */
 95     public function setClient(Client $client)
 96     {
 97         $this->client = $client;
 98 
 99         return $this;
100     }
101 
102     /**
103      * @param EntityBody $entityBody
104      * @return $this
105      */
106     public function setEntityBody(EntityBody $entityBody)
107     {
108         $this->entityBody = $entityBody;
109 
110         return $this;
111     }
112 
113     /**
114      * @param TransferState $transferState
115      * @return $this
116      */
117     public function setTransferState(TransferState $transferState)
118     {
119         $this->transferState = $transferState;
120 
121         return $this;
122     }
123 
124     /**
125      * @return array
126      */
127     public function getOptions()
128     {
129         return $this->options;
130     }
131 
132     /**
133      * @param $options
134      * @return $this
135      */
136     public function setOptions($options)
137     {
138         $this->options = $options;
139 
140         return $this;
141     }
142 
143     /**
144      * @param $option The key being updated
145      * @param $value  The option's value
146      * @return $this
147      */
148     public function setOption($option, $value)
149     {
150         $this->options[$option] = $value;
151 
152         return $this;
153     }
154 
155     public function getPartSize()
156     {
157         return $this->partSize;
158     }
159 
160     /**
161      * @return $this
162      */
163     public function setup()
164     {
165         $this->options = array_merge($this->defaultOptions, $this->options);
166         $this->partSize = $this->validatePartSize();
167 
168         return $this;
169     }
170 
171     /**
172      * Make sure the part size falls within a valid range
173      *
174      * @return mixed
175      */
176     protected function validatePartSize()
177     {
178         $min = min($this->options['partSize'], self::MAX_PART_SIZE);
179 
180         return max($min, self::MIN_PART_SIZE);
181     }
182 
183     /**
184      * Initiates the upload procedure.
185      *
186      * @return \Guzzle\Http\Message\Response
187      * @throws RuntimeException If the transfer is not in a "running" state
188      * @throws UploadException  If any errors occur during the upload
189      * @codeCoverageIgnore
190      */
191     public function upload()
192     {
193         if (!$this->transferState->isRunning()) {
194             throw new RuntimeException('The transfer has been aborted.');
195         }
196 
197         try {
198             $this->transfer();
199             $response = $this->createManifest();
200         } catch (Exception $e) {
201             throw new UploadException($this->transferState, $e);
202         }
203 
204         return $response;
205     }
206 
207     /**
208      * With large uploads, you must create a manifest file. Although each segment or TransferPart remains
209      * individually addressable, the manifest file serves as the unified file (i.e. the 5GB download) which, when
210      * retrieved, streams all the segments concatenated.
211      *
212      * @link http://docs.rackspace.com/files/api/v1/cf-devguide/content/Large_Object_Creation-d1e2019.html
213      * @return \Guzzle\Http\Message\Response
214      * @codeCoverageIgnore
215      */
216     private function createManifest()
217     {
218         $parts = array();
219 
220         foreach ($this->transferState as $part) {
221             $parts[] = (object) array(
222                 'path'       => $part->getPath(),
223                 'etag'       => $part->getETag(),
224                 'size_bytes' => $part->getContentLength()
225             );
226         }
227 
228         $headers = array(
229             'Content-Length'    => 0,
230             'X-Object-Manifest' => sprintf('%s/%s/%s/',
231                 $this->options['containerName'],
232                 $this->options['objectName'],
233                 $this->options['prefix']
234             )
235         );
236 
237         $url = clone $this->options['containerUrl'];
238         $url->addPath($this->options['objectName']);
239 
240         return $this->client->put($url, $headers)->send();
241     }
242 }
243 
API documentation generated by ApiGen