Google Cloud Storage C++ Client  1.33.0
A C++ Client Library for Google Cloud Storage
object_write_stream.cc
Go to the documentation of this file.
1 // Copyright 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "google/cloud/storage/object_write_stream.h"
16 #include "google/cloud/storage/internal/hash_function.h"
17 #include "google/cloud/storage/internal/hash_validator.h"
18 #include "absl/memory/memory.h"
19 
20 namespace google {
21 namespace cloud {
22 namespace storage {
24 namespace {
25 std::unique_ptr<internal::ObjectWriteStreambuf> MakeErrorStreambuf() {
26  return absl::make_unique<internal::ObjectWriteStreambuf>(
27  absl::make_unique<internal::ResumableUploadSessionError>(
29  /*max_buffer_size=*/0, internal::CreateNullHashFunction(),
30  internal::HashValues{}, internal::CreateNullHashValidator(),
32 }
33 } // namespace
34 static_assert(std::is_move_assignable<ObjectWriteStream>::value,
35  "storage::ObjectWriteStream must be move assignable.");
36 static_assert(std::is_move_constructible<ObjectWriteStream>::value,
37  "storage::ObjectWriteStream must be move constructible.");
38 
40  : ObjectWriteStream(MakeErrorStreambuf()) {}
41 
43  std::unique_ptr<internal::ObjectWriteStreambuf> buf)
44  : std::basic_ostream<char>(buf.get()), buf_(std::move(buf)) {
45  // If buf_ is already closed, update internal state to represent
46  // the fact that no more bytes can be uploaded to this object.
47  if (buf_ && !buf_->IsOpen()) CloseBuf();
48 }
49 
51  : std::basic_ostream<char>(std::move(rhs)),
52  // The spec guarantees the base class move constructor only changes a few
53  // member variables in `std::basic_istream<>`, and there is no spooky
54  // action through virtual functions because there are no virtual
55  // functions. A good summary of the specification is "it calls the
56  // default constructor and then calls std::basic_ios<>::move":
57  // https://en.cppreference.com/w/cpp/io/basic_ios/move
58  // In fact, as that page indicates, the base classes are designed such
59  // that derived classes can define their own move constructor and move
60  // assignment.
61  buf_(std::move(rhs.buf_)),
62  metadata_(std::move(rhs.metadata_)),
63  headers_(std::move(rhs.headers_)),
64  payload_(std::move(rhs.payload_)) {
65  rhs.buf_ = MakeErrorStreambuf();
66  rhs.set_rdbuf(rhs.buf_.get());
67  set_rdbuf(buf_.get());
68  if (!buf_) {
69  setstate(std::ios::badbit | std::ios::eofbit);
70  } else {
71  if (!buf_->last_status().ok()) setstate(std::ios::badbit);
72  if (!buf_->IsOpen()) setstate(std::ios::eofbit);
73  }
74 }
75 
77  if (!IsOpen()) return;
78  // Disable exceptions, even if the application had enabled exceptions the
79  // destructor is supposed to mask them.
80  exceptions(std::ios_base::goodbit);
81  buf_->AutoFlushFinal();
82 }
83 
85  if (!buf_) return;
86  CloseBuf();
87 }
88 
89 void ObjectWriteStream::CloseBuf() {
90  auto response = buf_->Close();
91  if (!response.ok()) {
92  metadata_ = std::move(response).status();
93  setstate(std::ios_base::badbit);
94  return;
95  }
96  headers_ = {};
97  if (response->payload.has_value()) {
98  metadata_ = *std::move(response->payload);
99  }
100  if (metadata_ && !buf_->ValidateHash(*metadata_)) {
101  setstate(std::ios_base::badbit);
102  }
103 }
104 
106  ObjectWriteStream tmp;
107  swap(tmp);
108  tmp.buf_.reset();
109 }
110 
112 } // namespace storage
113 } // namespace cloud
114 } // namespace google