Overview

Namespaces

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

Classes

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