Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: storage/browser/blob/blob_reader.cc

Issue 1234813004: [BlobAsync] Asynchronous Blob Construction Final Patch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@blob-protocol-change
Patch Set: comments Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "storage/browser/blob/blob_reader.h" 5 #include "storage/browser/blob/blob_reader.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 28 matching lines...) Expand all
39 39
40 BlobReader::BlobReader( 40 BlobReader::BlobReader(
41 const BlobDataHandle* blob_handle, 41 const BlobDataHandle* blob_handle,
42 scoped_ptr<FileStreamReaderProvider> file_stream_provider, 42 scoped_ptr<FileStreamReaderProvider> file_stream_provider,
43 base::SequencedTaskRunner* file_task_runner) 43 base::SequencedTaskRunner* file_task_runner)
44 : file_stream_provider_(file_stream_provider.Pass()), 44 : file_stream_provider_(file_stream_provider.Pass()),
45 file_task_runner_(file_task_runner), 45 file_task_runner_(file_task_runner),
46 net_error_(net::OK), 46 net_error_(net::OK),
47 weak_factory_(this) { 47 weak_factory_(this) {
48 if (blob_handle) { 48 if (blob_handle) {
49 blob_data_ = blob_handle->CreateSnapshot().Pass(); 49 blob_handle_.reset(new BlobDataHandle(*blob_handle));
50 } 50 }
51 } 51 }
52 52
53 BlobReader::~BlobReader() { 53 BlobReader::~BlobReader() {
54 STLDeleteValues(&index_to_reader_); 54 STLDeleteValues(&index_to_reader_);
55 } 55 }
56 56
57 BlobReader::Status BlobReader::CalculateSize( 57 BlobReader::Status BlobReader::CalculateSize(
58 const net::CompletionCallback& done) { 58 const net::CompletionCallback& done) {
59 DCHECK(!total_size_calculated_); 59 DCHECK(!total_size_calculated_);
60 DCHECK(size_callback_.is_null()); 60 DCHECK(size_callback_.is_null());
61 if (!blob_data_.get()) { 61 if (!blob_handle_.get()) {
62 return ReportError(net::ERR_FILE_NOT_FOUND); 62 return ReportError(net::ERR_FILE_NOT_FOUND);
63 } 63 }
64 64 if (blob_handle_->IsAsyncConstructing()) {
65 net_error_ = net::OK; 65 blob_handle_->RunOnConstructionComplete(base::Bind(
66 total_size_ = 0; 66 &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done));
67 const auto& items = blob_data_->items(); 67 return Status::IO_PENDING;
68 item_length_list_.resize(items.size());
69 pending_get_file_info_count_ = 0;
70 for (size_t i = 0; i < items.size(); ++i) {
71 const BlobDataItem& item = *items.at(i);
72 if (IsFileType(item.type())) {
73 ++pending_get_file_info_count_;
74 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
75 if (!reader) {
76 return ReportError(net::ERR_FAILED);
77 }
78 int64_t length_output = reader->GetLength(base::Bind(
79 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
80 if (length_output == net::ERR_IO_PENDING) {
81 continue;
82 }
83 if (length_output < 0) {
84 return ReportError(length_output);
85 }
86 // We got the length right away
87 --pending_get_file_info_count_;
88 uint64_t resolved_length;
89 if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
90 return ReportError(net::ERR_FILE_NOT_FOUND);
91 }
92 if (!AddItemLength(i, resolved_length)) {
93 return ReportError(net::ERR_FAILED);
94 }
95 continue;
96 }
97
98 if (!AddItemLength(i, item.length()))
99 return ReportError(net::ERR_FAILED);
100 } 68 }
101 69 blob_data_ = blob_handle_->CreateSnapshot().Pass();
102 if (pending_get_file_info_count_ == 0) { 70 return CalculateSizeImpl(done);
103 DidCountSize();
104 return Status::DONE;
105 }
106 // Note: We only set the callback if we know that we're an async operation.
107 size_callback_ = done;
108 return Status::IO_PENDING;
109 } 71 }
110 72
111 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { 73 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) {
112 if (!blob_data_.get()) { 74 if (!blob_handle_.get()) {
113 return ReportError(net::ERR_FILE_NOT_FOUND); 75 return ReportError(net::ERR_FILE_NOT_FOUND);
114 } 76 }
115 if (!total_size_calculated_) { 77 if (!total_size_calculated_) {
116 return ReportError(net::ERR_FAILED); 78 return ReportError(net::ERR_FAILED);
117 } 79 }
118 if (offset + length > total_size_) { 80 if (offset + length > total_size_) {
119 return ReportError(net::ERR_FILE_NOT_FOUND); 81 return ReportError(net::ERR_FILE_NOT_FOUND);
120 } 82 }
121 // Skip the initial items that are not in the range. 83 // Skip the initial items that are not in the range.
122 remaining_bytes_ = length; 84 remaining_bytes_ = length;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 read_callback_.Reset(); 171 read_callback_.Reset();
210 read_buf_ = nullptr; 172 read_buf_ = nullptr;
211 done.Run(net_error); 173 done.Run(net_error);
212 } 174 }
213 175
214 BlobReader::Status BlobReader::ReportError(int net_error) { 176 BlobReader::Status BlobReader::ReportError(int net_error) {
215 net_error_ = net_error; 177 net_error_ = net_error;
216 return Status::NET_ERROR; 178 return Status::NET_ERROR;
217 } 179 }
218 180
181 void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done,
182 bool async_succeeded) {
183 if (!async_succeeded) {
184 InvalidateCallbacksAndDone(net::ERR_FAILED, done);
185 }
186 blob_data_ = blob_handle_->CreateSnapshot().Pass();
187 Status size_status = CalculateSizeImpl(done);
188 switch (size_status) {
189 case Status::DONE:
190 case Status::IO_PENDING:
191 return;
192 case Status::NET_ERROR:
193 InvalidateCallbacksAndDone(net_error_, done);
194 return;
195 }
196 }
197
198 BlobReader::Status BlobReader::CalculateSizeImpl(
199 const net::CompletionCallback& done) {
200 DCHECK(!total_size_calculated_);
201 DCHECK(size_callback_.is_null());
202
203 net_error_ = net::OK;
204 total_size_ = 0;
205 const auto& items = blob_data_->items();
206 item_length_list_.resize(items.size());
207 pending_get_file_info_count_ = 0;
208 for (size_t i = 0; i < items.size(); ++i) {
209 const BlobDataItem& item = *items.at(i);
210 if (IsFileType(item.type())) {
211 ++pending_get_file_info_count_;
212 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
213 if (!reader) {
214 return ReportError(net::ERR_FAILED);
215 }
216 int64_t length_output = reader->GetLength(base::Bind(
217 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
218 if (length_output == net::ERR_IO_PENDING) {
219 continue;
220 }
221 if (length_output < 0) {
222 return ReportError(length_output);
223 }
224 // We got the length right away
225 --pending_get_file_info_count_;
226 uint64_t resolved_length;
227 if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
228 return ReportError(net::ERR_FILE_NOT_FOUND);
229 }
230 if (!AddItemLength(i, resolved_length)) {
231 return ReportError(net::ERR_FAILED);
232 }
233 continue;
234 }
235
236 if (!AddItemLength(i, item.length()))
237 return ReportError(net::ERR_FAILED);
238 }
239
240 if (pending_get_file_info_count_ == 0) {
241 DidCountSize();
242 return Status::DONE;
243 }
244 // Note: We only set the callback if we know that we're an async operation.
245 size_callback_ = done;
246 return Status::IO_PENDING;
247 }
248
219 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { 249 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) {
220 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { 250 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) {
221 return false; 251 return false;
222 } 252 }
223 253
224 // Cache the size and add it to the total size. 254 // Cache the size and add it to the total size.
225 DCHECK_LT(index, item_length_list_.size()); 255 DCHECK_LT(index, item_length_list_.size());
226 item_length_list_[index] = item_length; 256 item_length_list_[index] = item_length;
227 total_size_ += item_length; 257 total_size_ += item_length;
228 return true; 258 return true;
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 index_to_reader_.erase(found); 590 index_to_reader_.erase(found);
561 return; 591 return;
562 } 592 }
563 found->second = reader.release(); 593 found->second = reader.release();
564 } else if (reader.get()) { 594 } else if (reader.get()) {
565 index_to_reader_[current_item_index_] = reader.release(); 595 index_to_reader_[current_item_index_] = reader.release();
566 } 596 }
567 } 597 }
568 598
569 } // namespace storage 599 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698