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

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: added shared memory test, and fixed memory leak Created 4 years, 10 months 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 <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <algorithm> 9 #include <algorithm>
10 #include <limits> 10 #include <limits>
(...skipping 30 matching lines...) Expand all
41 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {} 41 BlobReader::FileStreamReaderProvider::~FileStreamReaderProvider() {}
42 42
43 BlobReader::BlobReader( 43 BlobReader::BlobReader(
44 const BlobDataHandle* blob_handle, 44 const BlobDataHandle* blob_handle,
45 scoped_ptr<FileStreamReaderProvider> file_stream_provider, 45 scoped_ptr<FileStreamReaderProvider> file_stream_provider,
46 base::SequencedTaskRunner* file_task_runner) 46 base::SequencedTaskRunner* file_task_runner)
47 : file_stream_provider_(std::move(file_stream_provider)), 47 : file_stream_provider_(std::move(file_stream_provider)),
48 file_task_runner_(file_task_runner), 48 file_task_runner_(file_task_runner),
49 net_error_(net::OK), 49 net_error_(net::OK),
50 weak_factory_(this) { 50 weak_factory_(this) {
51 if (blob_handle) { 51 if (blob_handle && !blob_handle->IsBroken()) {
52 blob_data_ = blob_handle->CreateSnapshot(); 52 blob_handle_.reset(new BlobDataHandle(*blob_handle));
53 } 53 }
54 } 54 }
55 55
56 BlobReader::~BlobReader() { 56 BlobReader::~BlobReader() {
57 STLDeleteValues(&index_to_reader_); 57 STLDeleteValues(&index_to_reader_);
58 } 58 }
59 59
60 BlobReader::Status BlobReader::CalculateSize( 60 BlobReader::Status BlobReader::CalculateSize(
61 const net::CompletionCallback& done) { 61 const net::CompletionCallback& done) {
62 DCHECK(!total_size_calculated_); 62 DCHECK(!total_size_calculated_);
63 DCHECK(size_callback_.is_null()); 63 DCHECK(size_callback_.is_null());
64 if (!blob_data_.get()) { 64 if (!blob_handle_.get() || blob_handle_->IsBroken()) {
65 return ReportError(net::ERR_FILE_NOT_FOUND); 65 return ReportError(net::ERR_FILE_NOT_FOUND);
66 } 66 }
67 67 if (blob_handle_->IsBeingBuilt()) {
68 net_error_ = net::OK; 68 blob_handle_->RunOnConstructionComplete(base::Bind(
69 total_size_ = 0; 69 &BlobReader::AsyncCalculateSize, weak_factory_.GetWeakPtr(), done));
70 const auto& items = blob_data_->items(); 70 return Status::IO_PENDING;
71 item_length_list_.resize(items.size());
72 pending_get_file_info_count_ = 0;
73 for (size_t i = 0; i < items.size(); ++i) {
74 const BlobDataItem& item = *items.at(i);
75 if (IsFileType(item.type())) {
76 ++pending_get_file_info_count_;
77 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
78 if (!reader) {
79 return ReportError(net::ERR_FAILED);
80 }
81 int64_t length_output = reader->GetLength(base::Bind(
82 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
83 if (length_output == net::ERR_IO_PENDING) {
84 continue;
85 }
86 if (length_output < 0) {
87 return ReportError(length_output);
88 }
89 // We got the length right away
90 --pending_get_file_info_count_;
91 uint64_t resolved_length;
92 if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
93 return ReportError(net::ERR_FILE_NOT_FOUND);
94 }
95 if (!AddItemLength(i, resolved_length)) {
96 return ReportError(net::ERR_FAILED);
97 }
98 continue;
99 }
100
101 if (!AddItemLength(i, item.length()))
102 return ReportError(net::ERR_FAILED);
103 } 71 }
104 72 blob_data_ = blob_handle_->CreateSnapshot();
105 if (pending_get_file_info_count_ == 0) { 73 return CalculateSizeImpl(done);
106 DidCountSize();
107 return Status::DONE;
108 }
109 // Note: We only set the callback if we know that we're an async operation.
110 size_callback_ = done;
111 return Status::IO_PENDING;
112 } 74 }
113 75
114 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) { 76 BlobReader::Status BlobReader::SetReadRange(uint64_t offset, uint64_t length) {
115 if (!blob_data_.get()) { 77 if (!blob_handle_.get() || blob_handle_->IsBroken()) {
116 return ReportError(net::ERR_FILE_NOT_FOUND); 78 return ReportError(net::ERR_FILE_NOT_FOUND);
117 } 79 }
118 if (!total_size_calculated_) { 80 if (!total_size_calculated_) {
119 return ReportError(net::ERR_FAILED); 81 return ReportError(net::ERR_FAILED);
120 } 82 }
121 if (offset + length > total_size_) { 83 if (offset + length > total_size_) {
122 return ReportError(net::ERR_FILE_NOT_FOUND); 84 return ReportError(net::ERR_FILE_NOT_FOUND);
123 } 85 }
124 // Skip the initial items that are not in the range. 86 // Skip the initial items that are not in the range.
125 remaining_bytes_ = length; 87 remaining_bytes_ = length;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 read_callback_.Reset(); 174 read_callback_.Reset();
213 read_buf_ = nullptr; 175 read_buf_ = nullptr;
214 done.Run(net_error); 176 done.Run(net_error);
215 } 177 }
216 178
217 BlobReader::Status BlobReader::ReportError(int net_error) { 179 BlobReader::Status BlobReader::ReportError(int net_error) {
218 net_error_ = net_error; 180 net_error_ = net_error;
219 return Status::NET_ERROR; 181 return Status::NET_ERROR;
220 } 182 }
221 183
184 void BlobReader::AsyncCalculateSize(const net::CompletionCallback& done,
185 bool async_succeeded) {
186 if (!async_succeeded) {
187 InvalidateCallbacksAndDone(net::ERR_FAILED, done);
188 return;
189 }
190 DCHECK(!blob_handle_->IsBroken()) << "Callback should have returned false.";
191 blob_data_ = blob_handle_->CreateSnapshot();
192 Status size_status = CalculateSizeImpl(done);
193 if (size_status == Status::NET_ERROR)
194 InvalidateCallbacksAndDone(net_error_, done);
195 }
196
197 BlobReader::Status BlobReader::CalculateSizeImpl(
198 const net::CompletionCallback& done) {
199 DCHECK(!total_size_calculated_);
200 DCHECK(size_callback_.is_null());
201
202 net_error_ = net::OK;
203 total_size_ = 0;
204 const auto& items = blob_data_->items();
205 item_length_list_.resize(items.size());
206 pending_get_file_info_count_ = 0;
207 for (size_t i = 0; i < items.size(); ++i) {
208 const BlobDataItem& item = *items.at(i);
209 if (IsFileType(item.type())) {
210 ++pending_get_file_info_count_;
211 storage::FileStreamReader* const reader = GetOrCreateFileReaderAtIndex(i);
212 if (!reader) {
213 return ReportError(net::ERR_FAILED);
214 }
215 int64_t length_output = reader->GetLength(base::Bind(
216 &BlobReader::DidGetFileItemLength, weak_factory_.GetWeakPtr(), i));
217 if (length_output == net::ERR_IO_PENDING) {
218 continue;
219 }
220 if (length_output < 0) {
221 return ReportError(length_output);
222 }
223 // We got the length right away
224 --pending_get_file_info_count_;
225 uint64_t resolved_length;
226 if (!ResolveFileItemLength(item, length_output, &resolved_length)) {
227 return ReportError(net::ERR_FILE_NOT_FOUND);
228 }
229 if (!AddItemLength(i, resolved_length)) {
230 return ReportError(net::ERR_FAILED);
231 }
232 continue;
233 }
234
235 if (!AddItemLength(i, item.length()))
236 return ReportError(net::ERR_FAILED);
237 }
238
239 if (pending_get_file_info_count_ == 0) {
240 DidCountSize();
241 return Status::DONE;
242 }
243 // Note: We only set the callback if we know that we're an async operation.
244 size_callback_ = done;
245 return Status::IO_PENDING;
246 }
247
222 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) { 248 bool BlobReader::AddItemLength(size_t index, uint64_t item_length) {
223 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) { 249 if (item_length > std::numeric_limits<uint64_t>::max() - total_size_) {
224 return false; 250 return false;
225 } 251 }
226 252
227 // Cache the size and add it to the total size. 253 // Cache the size and add it to the total size.
228 DCHECK_LT(index, item_length_list_.size()); 254 DCHECK_LT(index, item_length_list_.size());
229 item_length_list_[index] = item_length; 255 item_length_list_[index] = item_length;
230 total_size_ += item_length; 256 total_size_ += item_length;
231 return true; 257 return true;
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 index_to_reader_.erase(found); 586 index_to_reader_.erase(found);
561 return; 587 return;
562 } 588 }
563 found->second = reader.release(); 589 found->second = reader.release();
564 } else if (reader.get()) { 590 } else if (reader.get()) {
565 index_to_reader_[current_item_index_] = reader.release(); 591 index_to_reader_[current_item_index_] = reader.release();
566 } 592 }
567 } 593 }
568 594
569 } // namespace storage 595 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698