Skip to content

Commit dd69e6a

Browse files
committed
feat(storage): Add full object checksum validation at finalization for JSON path
1 parent 2426f6e commit dd69e6a

File tree

5 files changed

+53
-25
lines changed

5 files changed

+53
-25
lines changed

.bazelignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ cmake-build-debug/
55
cmake-build-coverage/
66
cmake-build-release/
77
.build/
8+
_build/

google/cloud/storage/internal/object_requests.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,9 @@ class UploadChunkRequest
534534
HashValues const& known_object_hashes() const { return known_object_hashes_; }
535535

536536
HashFunction& hash_function() const { return *hash_function_; }
537+
std::shared_ptr<HashFunction> hash_function_ptr() const {
538+
return hash_function_;
539+
}
537540

538541
bool last_chunk() const { return upload_size_.has_value(); }
539542
std::size_t payload_size() const { return TotalBytes(payload_); }

google/cloud/storage/internal/object_write_streambuf.cc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,22 +144,26 @@ void ObjectWriteStreambuf::FlushFinal() {
144144

145145
// Calculate the portion of the buffer that needs to be uploaded, if any.
146146
auto const actual_size = put_area_size();
147+
HashValues final_hashes = known_hashes_;
148+
if (hash_function_) {
149+
hash_function_->Update(committed_size_, {pbase(), actual_size});
150+
final_hashes = hash_function_->Finish();
151+
hash_function_.reset();
152+
}
147153

148154
// After this point the session will be closed, and no more calls to the hash
149155
// function are possible.
150156
auto upload_request = UploadChunkRequest(upload_id_, committed_size_,
151157
{ConstBuffer(pbase(), actual_size)},
152-
hash_function_, known_hashes_);
158+
hash_function_, final_hashes);
153159
request_.ForEachOption(internal::CopyCommonOptions(upload_request));
154160
OptionsSpan const span(span_options_);
155161
auto response = connection_->UploadChunk(upload_request);
156162
if (!response) {
157163
last_status_ = std::move(response).status();
158164
return;
159165
}
160-
161-
auto function = std::move(hash_function_);
162-
hash_values_ = std::move(*function).Finish();
166+
hash_values_ = final_hashes;
163167

164168
committed_size_ = response->committed_size.value_or(0);
165169
metadata_ = std::move(response->payload);
@@ -203,6 +207,9 @@ void ObjectWriteStreambuf::FlushRoundChunk(ConstBufferSequence buffers) {
203207
auto upload_request =
204208
UploadChunkRequest(upload_id_, committed_size_, payload, hash_function_);
205209
request_.ForEachOption(internal::CopyCommonOptions(upload_request));
210+
upload_request.ForEachOption([](auto const& opt) {
211+
std::cout << "DEBUG: option=" << opt << "\n";
212+
});
206213
OptionsSpan const span(span_options_);
207214
auto response = connection_->UploadChunk(upload_request);
208215
if (!response) {

google/cloud/storage/internal/rest/stub.cc

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -770,12 +770,23 @@ StatusOr<QueryResumableUploadResponse> RestStub::UploadChunk(
770770
// default (at least in this case), and that wastes bandwidth as the content
771771
// length is known.
772772
builder.AddHeader("Transfer-Encoding", {});
773-
auto offset = request.offset();
774-
for (auto const& b : request.payload()) {
775-
request.hash_function().Update(offset,
776-
absl::string_view{b.data(), b.size()});
777-
offset += b.size();
778-
}
773+
auto hash_function = request.hash_function_ptr();
774+
if (hash_function) {
775+
auto offset = request.offset();
776+
for (auto const& b : request.payload()) {
777+
hash_function->Update(offset, absl::string_view{b.data(), b.size()});
778+
offset += b.size();
779+
}
780+
}
781+
if (request.last_chunk()) {
782+
auto const& hashes = request.known_object_hashes();
783+
if (!hashes.crc32c.empty()) {
784+
builder.AddHeader("x-goog-hash", "crc32c=" + hashes.crc32c);
785+
}
786+
if (!hashes.md5.empty()) {
787+
builder.AddHeader("x-goog-hash", "md5=" + hashes.md5);
788+
}
789+
}
779790

780791
auto failure_predicate = [](rest::HttpStatusCode code) {
781792
return (code != rest::HttpStatusCode::kResumeIncomplete &&

google/cloud/storage/quickstart/quickstart.cc

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,25 @@
1818
#include <string>
1919

2020
int main(int argc, char* argv[]) {
21-
if (argc != 2) {
22-
std::cerr << "Missing bucket name.\n";
23-
std::cerr << "Usage: quickstart <bucket-name>\n";
24-
return 1;
25-
}
26-
std::string const bucket_name = argv[1];
21+
// if (argc != 2) {
22+
// std::cerr << "Missing bucket name.\n";
23+
// std::cerr << "Usage: quickstart <bucket-name>\n";
24+
// return 1;
25+
// }
26+
std::string const bucket_name = "vaibhav-test-001";
2727

2828
// Create a client to communicate with Google Cloud Storage. This client
2929
// uses the default configuration for authentication and project id.
3030
auto client = google::cloud::storage::Client();
3131

32-
auto writer = client.WriteObject(bucket_name, "quickstart.txt");
33-
writer << "Hello World!";
32+
auto writer = client.WriteObject(bucket_name, "quickstart1.txt");
33+
std::string x ="Hello World1!";
34+
for(int i=0;i<17;i++){
35+
x+=x;
36+
}
37+
for(int i=0;i<15;i++){
38+
writer << x.data();
39+
}
3440
writer.Close();
3541
if (!writer.metadata()) {
3642
std::cerr << "Error creating object: " << writer.metadata().status()
@@ -39,14 +45,14 @@ int main(int argc, char* argv[]) {
3945
}
4046
std::cout << "Successfully created object: " << *writer.metadata() << "\n";
4147

42-
auto reader = client.ReadObject(bucket_name, "quickstart.txt");
43-
if (!reader) {
44-
std::cerr << "Error reading object: " << reader.status() << "\n";
45-
return 1;
46-
}
48+
// auto reader = client.ReadObject(bucket_name, "quickstart.txt");
49+
// if (!reader) {
50+
// std::cerr << "Error reading object: " << reader.status() << "\n";
51+
// return 1;
52+
// }
4753

48-
std::string contents{std::istreambuf_iterator<char>{reader}, {}};
49-
std::cout << contents << "\n";
54+
// std::string contents{std::istreambuf_iterator<char>{reader}, {}};
55+
// std::cout << contents << "\n";
5056

5157
return 0;
5258
}

0 commit comments

Comments
 (0)