AWS SDK for C++  0.14.3
AWS SDK for C++
UploadFileRequest.h
Go to the documentation of this file.
1 
2 /*
3  * Copyright 2010-2015 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 
17 #pragma once
18 
20 
22 
26 
28 
30 
31 #include <fstream>
32 
33 namespace Aws
34 {
35 namespace S3
36 {
37  class S3Client;
38 
39  namespace Model
40  {
41  class CompletedPart;
42  }
43 } // namespace S3
44 
45 namespace Http
46 {
47  class HttpRequest;
48 }
49 
50 namespace Transfer
51 {
52 
53 
54 // PartRequestRecord is an individual piece of a multi part upload.
55 // m_partRequest contains the information S3 cares about for the request
56 // m_buffer is our buffer we used for the request and will reuse when this request is done
57 // m_partMd5 is to make sure our Md5 matches when the request returns successfully
58 // m_retries lets us retry the same request using this record in case of a failure
59 // up to PART_RETRY_MAX (2 default) attempts
61 {
62 public:
63 
64  PartRequestRecord(const std::shared_ptr<UploadBuffer>& thisBuffer) : m_buffer(thisBuffer),
65  m_retries(0)
66  { }
67 
68  PartRequestRecord() : m_retries(0) { }
69 
70  std::shared_ptr<UploadBuffer> m_buffer;
73  uint32_t m_retries;
74 };
75 
76 class AWS_TRANSFER_API UploadFileRequest : public S3FileRequest, public std::enable_shared_from_this<UploadFileRequest>
77 {
78 public:
79  UploadFileRequest(const Aws::String& fileName,
80  const Aws::String& bucketName,
81  const Aws::String& keyName,
82  const Aws::String& contentType,
84  const std::shared_ptr<Aws::S3::S3Client>& s3Client,
85  bool createBucket,
86  bool doConsistencyChecks);
87  UploadFileRequest(const Aws::String& fileName,
88  const Aws::String& bucketName,
89  const Aws::String& keyName,
90  const Aws::String& contentType,
91  const std::shared_ptr<Aws::S3::S3Client>& s3Client,
92  bool createBucket,
93  bool doConsistencyChecks);
94  UploadFileRequest(const Aws::String& fileName,
95  const Aws::String& bucketName,
96  const Aws::String& keyName,
97  const Aws::String& contentType,
98  const Aws::Map<Aws::String, Aws::String>& metadata,
99  const std::shared_ptr<Aws::S3::S3Client>& s3Client,
100  bool createBucket,
101  bool doConsistencyChecks);
102  virtual ~UploadFileRequest();
103 
104  // How many parts have we at least begun to upload
105  uint32_t GetPartCount() const;
106 
107  // How many parts have we completed
108  size_t GetCompletedPartCount() const;
109 
110  // Total number of parts we'll be dividing the file into for upload
111  uint32_t GetTotalParts() const { return m_totalParts; }
112 
113  // DoneWithRequests is Requested parts == TotalParts (Happens just before the final requests return and IsDone is set when all goes well)
114  bool DoneWithRequests() const;
115 
116  // This is a 5MB or less upload, we do not want to perform a multi part upload
117  bool IsSinglePartUpload() const;
118 
119  // Our catch all for "done and we've heard back on all parts" - hearing back on outstanding part uploads after a failure or cancel
120  // Is necessary to prevent the smart pointer from going out of scope when a future .get() call has not returned.
121  bool AllPartsReturned() const;
122 
123  // How many parts do we have left to start sending (Parts which have begun upload are not considered "remaining" for the purpose of this call)
124  uint32_t GetPartsRemaining() const;
125 
126  size_t GetPendingParts() const;
127 
128  // Data progress callback
129  void OnDataSent(const Aws::Http::HttpRequest*, long long);
130 
131  // How many buffers are we currently holding on to
132  size_t GetResourcesInUse() const;
133 
134  // How many parts have been returned
135  uint32_t GetPartsReturned() const;
136 
137  uint32_t GetTotalPartRetries() const;
138 
139  // Consistency check diagnostics
140  bool HasSentConsistencyChecks() const { return m_sentConsistencyChecks.load(); }
141  bool HasPassedHeadObject() const { return m_headObjectPassed.load(); }
142  bool HasPassedGetObject() const { return m_getObjectPassed.load(); }
143  bool HasPassedListObjects() const { return m_listObjectsPassed.load(); }
144 
145  friend class TransferClient;
146 
147 protected:
148 
149  virtual bool DoCancelAction() override;
150  virtual void SetDone() override;
151 private:
152  // TransferClient uses these calls
153  bool ProcessBuffer(const std::shared_ptr<UploadBuffer>& buffer);
154 
155  uint64_t ReadNextPart(const std::shared_ptr<UploadBuffer>& buffer, std::shared_ptr<Aws::IOStream>& streamBuf, uint32_t& partNum);
156 
157  void AddCompletedPart(PartRequestRecord& partRequest, const Aws::String& eTag);
158  void CompleteUpload();
159  void HandlePartFailure(const Aws::S3::Model::UploadPartOutcome& thisOutcome, PartRequestRecord& partRequest);
160 
161  // The primary lifecycle routine - Create a bucket if needed, Wait for it to propagate, Create a multi part upload if needed, start processing, etc
162  bool ContinueUpload();
163 
164  // Send out our requests to check for consistency
165  void DoConsistencyChecks();
166 
167  // We just received a positive result, let's see if we should now consider the upload a success
168  void CheckConsistencyCompletion();
169 
170  void CheckGetObject();
171  void CheckHeadObject();
172  void CheckListObjects();
173 
174  bool CreateBucket();
175  bool WaitForBucketToPropagate();
176  bool CreateMultipartUpload();
177  virtual bool IsReady() const override;
178 
179  bool HasUploadId() const;
180  const Aws::String& GetUploadId() const { return m_uploadId; }
181  // Testing
182  void CreateStreamBuffer(std::shared_ptr<Aws::IOStream>& streamBuf) const;
183 
184  void DoRetry(PartRequestRecord& partRequest);
185 
186  bool RequestPart(uint32_t partId);
187 
188  void ReusePart(PartRequestRecord& partRequest);
189 
190  void PartReturned(PartRequestRecord& partRequest);
191 
192  void SingleUploadComplete();
193 
194  bool HandleCreateBucketOutcome(const Aws::S3::Model::CreateBucketRequest& request,
195  const Aws::S3::Model::CreateBucketOutcome& createBucketOutcome);
196 
197  bool HandleCreateMultipartUploadOutcome(const Aws::S3::Model::CreateMultipartUploadRequest& request,
199 
200  bool HandleHeadBucketOutcome(const Aws::S3::Model::HeadBucketRequest& request,
201  const Aws::S3::Model::HeadBucketOutcome& outcome);
202 
203  bool HandleUploadPartOutcome(const Aws::S3::Model::UploadPartRequest& request,
204  const Aws::S3::Model::UploadPartOutcome& outcome);
205 
206  bool HandleCompleteMultipartUploadOutcome(const Aws::S3::Model::CompleteMultipartUploadRequest& request,
208 
209  bool HandlePutObjectOutcome(const Aws::S3::Model::PutObjectRequest& request,
210  const Aws::S3::Model::PutObjectOutcome& outcome);
211 
212  bool HandleHeadObjectOutcome(const Aws::S3::Model::HeadObjectRequest& request,
213  const Aws::S3::Model::HeadObjectOutcome& outcome);
214 
215  bool HandleGetObjectOutcome(const Aws::S3::Model::GetObjectRequest& request,
216  const Aws::S3::Model::GetObjectOutcome& outcome);
217 
218  bool HandleListObjectsOutcome(const Aws::S3::Model::ListObjectsRequest& request,
219  const Aws::S3::Model::ListObjectsOutcome& outcome);
220 
221  void AddReadyBuffer(std::shared_ptr<UploadBuffer> buffer);
222  bool GetReadyBuffer(std::shared_ptr<UploadBuffer>& buffer);
223  bool ProcessAvailableBuffers();
224 
225  // Uploads 5mb or less need to perform a single put call - attempting to do a multi part upload with these small
226  // files can cause failures in S3
227  bool DoSingleObjectUpload(std::shared_ptr<Aws::IOStream>& streamBuf, uint64_t bytesRead);
228 
229  void SendPutObjectRequest(const Aws::S3::Model::PutObjectRequest& request);
230 
231  bool IsUsingBuffer(const std::shared_ptr<UploadBuffer>& buffer) const;
232 
233  void CheckReacquireBuffers();
234 
235  void ReleaseResources();
236 
237  void SetResourceSet(std::shared_ptr<UploadBufferScopedResourceSetType>& bufferSet);
238 
239  std::shared_ptr<UploadBufferScopedResourceSetType > m_resources;
240 
241  mutable std::mutex m_fileRequestMutex;
242 
243  std::mutex m_resourceMutex;
244  std::mutex m_completePartMutex;
245  std::mutex m_reuseMutex;
246  mutable std::mutex m_pendingMutex;
247  std::mutex m_bufferMutex;
248 
249  uint64_t m_bytesRemaining;
250 
251  std::atomic<uint32_t> m_partCount;
252  std::atomic<uint32_t> m_partsReturned;
253  std::atomic<uint32_t> m_totalPartRetries;
254 
255  std::atomic<bool> m_createBucket;
256  std::atomic<bool> m_createBucketPending;
257  std::atomic<bool> m_bucketCreated;
258  std::atomic<bool> m_createMultipartUploadPending;
259  std::atomic<bool> m_headBucketPending;
260  std::atomic<bool> m_completeMultipartUploadPending;
261 
262  bool m_bucketPropagated;
263 
264  uint32_t m_totalParts;
265 
266  Aws::IFStream m_fileStream;
267 
270 
272 
273  Aws::String m_contentType;
275  Aws::String m_uploadId;
276  uint32_t m_createMultipartRetries;
277  uint32_t m_createBucketRetries;
278  uint32_t m_completeRetries;
279  uint32_t m_singleRetry;
280  bool m_doConsistencyChecks;
281 
282  // S3 propagation checks to optionally check for consistency before returning "done"
283  std::atomic<bool> m_sentConsistencyChecks;
284  std::atomic<bool> m_headObjectPassed;
285  std::atomic<bool> m_getObjectPassed;
286  std::atomic<bool> m_listObjectsPassed;
287 
288  unsigned m_headObjectRetries;
289  unsigned m_getObjectRetries;
290  unsigned m_listObjectsRetries;
291  unsigned m_headBucketRetries;
292 };
293 
294 
295 
296 } // namespace Transfer
297 } // namespace Aws
298 
Aws::Utils::ByteBuffer m_partMd5
std::map< K, V, std::less< K >, Aws::Allocator< std::pair< const K, V > > > Map
Definition: AWSMap.h:28
std::basic_ifstream< char, std::char_traits< char > > IFStream
Definition: AWSStreamFwd.h:27
std::shared_ptr< UploadBuffer > m_buffer
PartRequestRecord(const std::shared_ptr< UploadBuffer > &thisBuffer)
std::list< T, Aws::Allocator< T > > List
Definition: AWSList.h:27
Aws::S3::Model::UploadPartRequest m_partRequest
#define AWS_TRANSFER_API
std::basic_string< char, std::char_traits< char >, Aws::Allocator< char > > String
Definition: AWSString.h:97
JSON (JavaScript Object Notation).