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

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

Issue 2516713002: [BlobStorage] Implementing disk. (Closed)
Patch Set: test & windows fix Created 4 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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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_storage_context.h" 5 #include "storage/browser/blob/blob_storage_context.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <memory> 9 #include <memory>
10 #include <set> 10 #include <set>
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 BlobStorageContext::BlobFlattener::BlobFlattener( 85 BlobStorageContext::BlobFlattener::BlobFlattener(
86 const BlobDataBuilder& input_builder, 86 const BlobDataBuilder& input_builder,
87 BlobEntry* output_blob, 87 BlobEntry* output_blob,
88 BlobStorageRegistry* registry) { 88 BlobStorageRegistry* registry) {
89 const std::string& uuid = input_builder.uuid_; 89 const std::string& uuid = input_builder.uuid_;
90 std::set<std::string> dependent_blob_uuids; 90 std::set<std::string> dependent_blob_uuids;
91 91
92 size_t num_files_with_unknown_size = 0; 92 size_t num_files_with_unknown_size = 0;
93 size_t num_building_dependent_blobs = 0; 93 size_t num_building_dependent_blobs = 0;
94 94
95 bool found_memory_transport = false;
96 bool found_file_transport = false;
97
95 base::CheckedNumeric<uint64_t> checked_total_size = 0; 98 base::CheckedNumeric<uint64_t> checked_total_size = 0;
96 base::CheckedNumeric<uint64_t> checked_total_memory_size = 0; 99 base::CheckedNumeric<uint64_t> checked_total_memory_size = 0;
97 base::CheckedNumeric<uint64_t> checked_memory_quota_needed = 0; 100 base::CheckedNumeric<uint64_t> checked_transport_quota_needed = 0;
101 base::CheckedNumeric<uint64_t> checked_copy_quota_needed = 0;
98 102
99 for (scoped_refptr<BlobDataItem> input_item : input_builder.items_) { 103 for (scoped_refptr<BlobDataItem> input_item : input_builder.items_) {
100 const DataElement& input_element = input_item->data_element(); 104 const DataElement& input_element = input_item->data_element();
101 DataElement::Type type = input_element.type(); 105 DataElement::Type type = input_element.type();
102 uint64_t length = input_element.length(); 106 uint64_t length = input_element.length();
103 107
104 RecordBlobItemSizeStats(input_element); 108 RecordBlobItemSizeStats(input_element);
105 109
106 if (IsBytes(type)) { 110 if (IsBytes(type)) {
107 DCHECK_NE(0 + DataElement::kUnknownSize, input_element.length()); 111 DCHECK_NE(0 + DataElement::kUnknownSize, input_element.length());
108 checked_memory_quota_needed += length; 112 found_memory_transport = true;
113 if (found_file_transport) {
114 // We cannot have both memory and file transport items.
115 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
116 return;
117 }
118 checked_transport_quota_needed += length;
109 checked_total_size += length; 119 checked_total_size += length;
110 scoped_refptr<ShareableBlobDataItem> item = new ShareableBlobDataItem( 120 scoped_refptr<ShareableBlobDataItem> item = new ShareableBlobDataItem(
111 std::move(input_item), ShareableBlobDataItem::QUOTA_NEEDED); 121 std::move(input_item), ShareableBlobDataItem::QUOTA_NEEDED);
112 pending_memory_items.push_back(item); 122 pending_transport_items.push_back(item);
113 transport_items.push_back(item.get()); 123 transport_items.push_back(item.get());
114 output_blob->AppendSharedBlobItem(std::move(item)); 124 output_blob->AppendSharedBlobItem(std::move(item));
115 continue; 125 continue;
116 } 126 }
117 if (type == DataElement::TYPE_BLOB) { 127 if (type == DataElement::TYPE_BLOB) {
118 BlobEntry* ref_entry = registry->GetEntry(input_element.blob_uuid()); 128 BlobEntry* ref_entry = registry->GetEntry(input_element.blob_uuid());
119 129
120 if (!ref_entry || input_element.blob_uuid() == uuid) { 130 if (!ref_entry || input_element.blob_uuid() == uuid) {
121 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; 131 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
122 return; 132 return;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 !slice.total_memory_size.IsValid()) { 177 !slice.total_memory_size.IsValid()) {
168 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; 178 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
169 return; 179 return;
170 } 180 }
171 checked_total_memory_size += slice.total_memory_size; 181 checked_total_memory_size += slice.total_memory_size;
172 182
173 if (slice.first_source_item) { 183 if (slice.first_source_item) {
174 copies.push_back(ItemCopyEntry(slice.first_source_item, 184 copies.push_back(ItemCopyEntry(slice.first_source_item,
175 slice.first_item_slice_offset, 185 slice.first_item_slice_offset,
176 slice.dest_items.front())); 186 slice.dest_items.front()));
177 pending_memory_items.push_back(slice.dest_items.front()); 187 pending_copy_items.push_back(slice.dest_items.front());
178 } 188 }
179 if (slice.last_source_item) { 189 if (slice.last_source_item) {
180 copies.push_back( 190 copies.push_back(
181 ItemCopyEntry(slice.last_source_item, 0, slice.dest_items.back())); 191 ItemCopyEntry(slice.last_source_item, 0, slice.dest_items.back()));
182 pending_memory_items.push_back(slice.dest_items.back()); 192 pending_copy_items.push_back(slice.dest_items.back());
183 } 193 }
184 checked_memory_quota_needed += slice.copying_memory_size; 194 checked_copy_quota_needed += slice.copying_memory_size;
185 195
186 for (auto& shareable_item : slice.dest_items) { 196 for (auto& shareable_item : slice.dest_items) {
187 output_blob->AppendSharedBlobItem(std::move(shareable_item)); 197 output_blob->AppendSharedBlobItem(std::move(shareable_item));
188 } 198 }
189 continue; 199 continue;
190 } 200 }
191 201
192 DCHECK(!BlobDataBuilder::IsFutureFileItem(input_element)) 202 // If the source item is a temporary file item, then we need to keep track
193 << "File allocation not implemented."; 203 // of that and mark is as needing quota.
kinuko 2016/11/27 14:45:22 mark is -> mark it ?
dmurph 2016/11/28 19:20:36 Done.
204 scoped_refptr<ShareableBlobDataItem> item;
205 if (BlobDataBuilder::IsFutureFileItem(input_element)) {
206 found_file_transport = true;
207 if (found_memory_transport) {
208 // We cannot have both memory and file transport items.
209 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
210 return;
211 }
212 item = new ShareableBlobDataItem(std::move(input_item),
213 ShareableBlobDataItem::QUOTA_NEEDED);
214 pending_transport_items.push_back(item);
215 transport_items.push_back(item.get());
216 checked_transport_quota_needed += length;
217 } else {
218 item = new ShareableBlobDataItem(
219 std::move(input_item),
220 ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA);
221 }
194 if (length == DataElement::kUnknownSize) 222 if (length == DataElement::kUnknownSize)
195 num_files_with_unknown_size++; 223 num_files_with_unknown_size++;
196 224
197 scoped_refptr<ShareableBlobDataItem> item = new ShareableBlobDataItem(
198 std::move(input_item), ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA);
199
200 checked_total_size += length; 225 checked_total_size += length;
201 output_blob->AppendSharedBlobItem(std::move(item)); 226 output_blob->AppendSharedBlobItem(std::move(item));
202 } 227 }
203 228
204 if (num_files_with_unknown_size > 1 && input_builder.items_.size() > 1) { 229 if (num_files_with_unknown_size > 1 && input_builder.items_.size() > 1) {
205 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; 230 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
206 return; 231 return;
207 } 232 }
208 if (!checked_total_size.IsValid() || !checked_total_memory_size.IsValid() || 233 if (!checked_total_size.IsValid() || !checked_total_memory_size.IsValid() ||
209 !checked_memory_quota_needed.IsValid()) { 234 !checked_transport_quota_needed.IsValid() ||
235 !checked_copy_quota_needed.IsValid()) {
210 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; 236 status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS;
211 return; 237 return;
212 } 238 }
213 total_size = checked_total_size.ValueOrDie(); 239 total_size = checked_total_size.ValueOrDie();
214 total_memory_size = checked_total_memory_size.ValueOrDie(); 240 total_memory_size = checked_total_memory_size.ValueOrDie();
215 memory_quota_needed = checked_memory_quota_needed.ValueOrDie(); 241 transport_quota_needed = checked_transport_quota_needed.ValueOrDie();
216 if (memory_quota_needed) { 242 copy_quota_needed = checked_copy_quota_needed.ValueOrDie();
243 transport_quota_type = found_file_transport ? TransportQuotaType::FILE
244 : TransportQuotaType::MEMORY;
245 if (transport_quota_needed) {
217 status = BlobStatus::PENDING_QUOTA; 246 status = BlobStatus::PENDING_QUOTA;
218 } else { 247 } else {
219 status = BlobStatus::PENDING_INTERNALS; 248 status = BlobStatus::PENDING_INTERNALS;
220 } 249 }
221 } 250 }
222 251
223 BlobStorageContext::BlobFlattener::~BlobFlattener() {} 252 BlobStorageContext::BlobFlattener::~BlobFlattener() {}
224 253
225 BlobStorageContext::BlobSlice::BlobSlice(const BlobEntry& source, 254 BlobStorageContext::BlobSlice::BlobSlice(const BlobEntry& source,
226 uint64_t slice_offset, 255 uint64_t slice_offset,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 case DataElement::TYPE_FILE: { 320 case DataElement::TYPE_FILE: {
292 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.File", 321 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.File",
293 read_size / 1024); 322 read_size / 1024);
294 std::unique_ptr<DataElement> element(new DataElement()); 323 std::unique_ptr<DataElement> element(new DataElement());
295 element->SetToFilePathRange( 324 element->SetToFilePathRange(
296 source_item->path(), source_item->offset() + item_offset, read_size, 325 source_item->path(), source_item->offset() + item_offset, read_size,
297 source_item->expected_modification_time()); 326 source_item->expected_modification_time());
298 data_item = 327 data_item =
299 new BlobDataItem(std::move(element), source_item->data_handle_); 328 new BlobDataItem(std::move(element), source_item->data_handle_);
300 329
301 DCHECK(!BlobDataBuilder::IsFutureFileItem(source_item->data_element())) 330 if (BlobDataBuilder::IsFutureFileItem(source_item->data_element())) {
302 << "File allocation unimplemented."; 331 // Since we don't have file path / reference for our future file, we
332 // create another file item with this temporary file name. When our
333 // blob is finished constructing, all dependent blobs are done, and we
334 // can copy the handle over.
335 if (item_index == first_item_index) {
336 first_item_slice_offset = item_offset;
337 first_source_item = source_items[item_index];
338 } else {
339 last_source_item = source_items[item_index];
340 }
341 state = ShareableBlobDataItem::QUOTA_NEEDED;
342 }
303 break; 343 break;
304 } 344 }
305 case DataElement::TYPE_FILE_FILESYSTEM: { 345 case DataElement::TYPE_FILE_FILESYSTEM: {
306 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.FileSystem", 346 UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.BlobSlice.FileSystem",
307 read_size / 1024); 347 read_size / 1024);
308 std::unique_ptr<DataElement> element(new DataElement()); 348 std::unique_ptr<DataElement> element(new DataElement());
309 element->SetToFileSystemUrlRange( 349 element->SetToFileSystemUrlRange(
310 source_item->filesystem_url(), source_item->offset() + item_offset, 350 source_item->filesystem_url(), source_item->offset() + item_offset,
311 read_size, source_item->expected_modification_time()); 351 read_size, source_item->expected_modification_time());
312 data_item = new BlobDataItem(std::move(element)); 352 data_item = new BlobDataItem(std::move(element));
(...skipping 21 matching lines...) Expand all
334 item_offset = 0; 374 item_offset = 0;
335 } 375 }
336 } 376 }
337 377
338 BlobStorageContext::BlobSlice::~BlobSlice() {} 378 BlobStorageContext::BlobSlice::~BlobSlice() {}
339 379
340 BlobStorageContext::BlobStorageContext() 380 BlobStorageContext::BlobStorageContext()
341 : memory_controller_(base::FilePath(), scoped_refptr<base::TaskRunner>()), 381 : memory_controller_(base::FilePath(), scoped_refptr<base::TaskRunner>()),
342 ptr_factory_(this) {} 382 ptr_factory_(this) {}
343 383
344 BlobStorageContext::~BlobStorageContext() { 384 BlobStorageContext::BlobStorageContext(
345 } 385 const base::FilePath& storage_directory,
386 scoped_refptr<base::TaskRunner> file_runner)
387 : memory_controller_(std::move(storage_directory), std::move(file_runner)),
388 ptr_factory_(this) {}
389
390 BlobStorageContext::~BlobStorageContext() {}
346 391
347 std::unique_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID( 392 std::unique_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID(
348 const std::string& uuid) { 393 const std::string& uuid) {
349 BlobEntry* entry = registry_.GetEntry(uuid); 394 BlobEntry* entry = registry_.GetEntry(uuid);
350 if (!entry) 395 if (!entry)
351 return nullptr; 396 return nullptr;
352 return CreateHandle(uuid, entry); 397 return CreateHandle(uuid, entry);
353 } 398 }
354 399
355 std::unique_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL( 400 std::unique_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL(
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 << "If we have pending content then there needs to be a callback " 468 << "If we have pending content then there needs to be a callback "
424 "present."; 469 "present.";
425 470
426 entry->set_size(flattener.total_size); 471 entry->set_size(flattener.total_size);
427 entry->set_status(flattener.status); 472 entry->set_status(flattener.status);
428 std::unique_ptr<BlobDataHandle> handle = CreateHandle(content.uuid_, entry); 473 std::unique_ptr<BlobDataHandle> handle = CreateHandle(content.uuid_, entry);
429 474
430 UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount", entry->items().size()); 475 UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount", entry->items().size());
431 UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalSize", 476 UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalSize",
432 flattener.total_memory_size / 1024); 477 flattener.total_memory_size / 1024);
478
479 uint64_t total_memory_needed =
480 flattener.copy_quota_needed +
481 (flattener.transport_quota_type == TransportQuotaType::MEMORY
482 ? flattener.transport_quota_needed
483 : 0);
433 UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalUnsharedSize", 484 UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalUnsharedSize",
434 flattener.memory_quota_needed / 1024); 485 total_memory_needed / 1024);
435 486
436 size_t num_building_dependent_blobs = 0; 487 size_t num_building_dependent_blobs = 0;
437 std::vector<std::unique_ptr<BlobDataHandle>> dependent_blobs; 488 std::vector<std::unique_ptr<BlobDataHandle>> dependent_blobs;
438 // We hold a handle to all blobs we're using. This is important, as our memory 489 // We hold a handle to all blobs we're using. This is important, as our memory
439 // accounting can be delayed until OnEnoughSizeForBlobData is called, and we 490 // accounting can be delayed until OnEnoughSizeForBlobData is called, and we
440 // only free memory on canceling when we've done this accounting. If a 491 // only free memory on canceling when we've done this accounting. If a
441 // dependent blob is dereferenced, then we're the last blob holding onto that 492 // dependent blob is dereferenced, then we're the last blob holding onto that
442 // data item, and we need to account for that. So we prevent that case by 493 // data item, and we need to account for that. So we prevent that case by
443 // holding onto all blobs. 494 // holding onto all blobs.
444 for (const std::pair<std::string, BlobEntry*>& pending_blob : 495 for (const std::pair<std::string, BlobEntry*>& pending_blob :
445 flattener.dependent_blobs) { 496 flattener.dependent_blobs) {
446 dependent_blobs.push_back( 497 dependent_blobs.push_back(
447 CreateHandle(pending_blob.first, pending_blob.second)); 498 CreateHandle(pending_blob.first, pending_blob.second));
448 if (BlobStatusIsPending(pending_blob.second->status())) { 499 if (BlobStatusIsPending(pending_blob.second->status())) {
449 pending_blob.second->building_state_->build_completion_callbacks 500 pending_blob.second->building_state_->build_completion_callbacks
450 .push_back(base::Bind(&BlobStorageContext::OnDependentBlobFinished, 501 .push_back(base::Bind(&BlobStorageContext::OnDependentBlobFinished,
451 ptr_factory_.GetWeakPtr(), content.uuid_)); 502 ptr_factory_.GetWeakPtr(), content.uuid_));
452 num_building_dependent_blobs++; 503 num_building_dependent_blobs++;
453 } 504 }
454 } 505 }
455 506
456 entry->set_building_state(base::MakeUnique<BlobEntry::BuildingState>( 507 entry->set_building_state(base::MakeUnique<BlobEntry::BuildingState>(
457 !flattener.transport_items.empty(), transport_allowed_callback, 508 !flattener.pending_transport_items.empty(), transport_allowed_callback,
458 num_building_dependent_blobs)); 509 num_building_dependent_blobs));
459 BlobEntry::BuildingState* building_state = entry->building_state_.get(); 510 BlobEntry::BuildingState* building_state = entry->building_state_.get();
460 std::swap(building_state->copies, flattener.copies); 511 std::swap(building_state->copies, flattener.copies);
461 std::swap(building_state->dependent_blobs, dependent_blobs); 512 std::swap(building_state->dependent_blobs, dependent_blobs);
462 std::swap(building_state->transport_items, flattener.transport_items); 513 std::swap(building_state->transport_items, flattener.transport_items);
463 514
464 // Break ourselves if we have an error. BuildingState must be set first so the 515 // Break ourselves if we have an error. BuildingState must be set first so the
465 // callback is called correctly. 516 // callback is called correctly.
466 if (BlobStatusIsError(flattener.status)) { 517 if (BlobStatusIsError(flattener.status)) {
467 CancelBuildingBlobInternal(entry, flattener.status); 518 CancelBuildingBlobInternal(entry, flattener.status);
468 return handle; 519 return handle;
469 } 520 }
470 521
471 if (!memory_controller_.CanReserveQuota(flattener.memory_quota_needed)) { 522 // Avoid the state where we might grant only one quota.
523 if (!memory_controller_.CanReserveQuota(flattener.copy_quota_needed +
524 flattener.transport_quota_needed)) {
472 CancelBuildingBlobInternal(entry, BlobStatus::ERR_OUT_OF_MEMORY); 525 CancelBuildingBlobInternal(entry, BlobStatus::ERR_OUT_OF_MEMORY);
473 return handle; 526 return handle;
474 } 527 }
475 528
476 if (flattener.memory_quota_needed > 0) { 529 if (flattener.copy_quota_needed > 0) {
477 // The blob can complete during the execution of this line. 530 // The blob can complete during the execution of this line.
478 base::WeakPtr<QuotaAllocationTask> pending_request = 531 base::WeakPtr<QuotaAllocationTask> pending_request =
479 memory_controller_.ReserveMemoryQuota( 532 memory_controller_.ReserveMemoryQuota(
480 std::move(flattener.pending_memory_items), 533 std::move(flattener.pending_copy_items),
481 base::Bind(&BlobStorageContext::OnEnoughSizeForMemory, 534 base::Bind(&BlobStorageContext::OnEnoughSpaceForCopies,
482 ptr_factory_.GetWeakPtr(), content.uuid_)); 535 ptr_factory_.GetWeakPtr(), content.uuid_));
483 // Building state will be null if the blob is already finished. 536 // Building state will be null if the blob is already finished.
484 if (entry->building_state_) 537 if (entry->building_state_)
485 entry->building_state_->memory_quota_request = std::move(pending_request); 538 entry->building_state_->copy_quota_request = std::move(pending_request);
539 }
540
541 if (flattener.transport_quota_needed > 0) {
542 // The blob can complete during the execution of this line.
kinuko 2016/11/27 14:45:22 This comment looks misplaced (must be placed befor
dmurph 2016/11/28 19:20:36 Done.
543 base::WeakPtr<QuotaAllocationTask> pending_request;
544
545 switch (flattener.transport_quota_type) {
546 case TransportQuotaType::MEMORY:
547 pending_request = memory_controller_.ReserveMemoryQuota(
548 std::move(flattener.pending_transport_items),
549 base::Bind(&BlobStorageContext::OnEnoughSpaceForTransportByMemory,
550 ptr_factory_.GetWeakPtr(), content.uuid_));
551 break;
552 case TransportQuotaType::FILE:
553 pending_request = memory_controller_.ReserveFileQuota(
554 std::move(flattener.pending_transport_items),
555 base::Bind(&BlobStorageContext::OnEnoughSpaceForTransportByFiles,
556 ptr_factory_.GetWeakPtr(), content.uuid_));
557 break;
558 }
559
560 // Building state will be null if the blob is already finished.
561 if (entry->building_state_)
562 entry->building_state_->transport_quota_request =
563 std::move(pending_request);
486 } 564 }
487 565
488 if (entry->CanFinishBuilding()) 566 if (entry->CanFinishBuilding())
489 FinishBuilding(entry); 567 FinishBuilding(entry);
490 568
491 return handle; 569 return handle;
492 } 570 }
493 571
494 void BlobStorageContext::CancelBuildingBlob(const std::string& uuid, 572 void BlobStorageContext::CancelBuildingBlob(const std::string& uuid,
495 BlobStatus reason) { 573 BlobStatus reason) {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 // Our source item can be a file if it was a slice of an unpopulated file, 693 // Our source item can be a file if it was a slice of an unpopulated file,
616 // or a slice of data that was then paged to disk. 694 // or a slice of data that was then paged to disk.
617 size_t dest_size = static_cast<size_t>(copy.dest_item->item()->length()); 695 size_t dest_size = static_cast<size_t>(copy.dest_item->item()->length());
618 DataElement::Type dest_type = copy.dest_item->item()->type(); 696 DataElement::Type dest_type = copy.dest_item->item()->type();
619 switch (copy.source_item->item()->type()) { 697 switch (copy.source_item->item()->type()) {
620 case DataElement::TYPE_BYTES: { 698 case DataElement::TYPE_BYTES: {
621 DCHECK_EQ(dest_type, DataElement::TYPE_BYTES_DESCRIPTION); 699 DCHECK_EQ(dest_type, DataElement::TYPE_BYTES_DESCRIPTION);
622 const char* src_data = 700 const char* src_data =
623 copy.source_item->item()->bytes() + copy.source_item_offset; 701 copy.source_item->item()->bytes() + copy.source_item_offset;
624 copy.dest_item->item()->item_->SetToBytes(src_data, dest_size); 702 copy.dest_item->item()->item_->SetToBytes(src_data, dest_size);
625 } break; 703 break;
626 case DataElement::TYPE_FILE: 704 }
705 case DataElement::TYPE_FILE: {
706 // If we expected a memory item (and our source was paged to disk) we
707 // free that memory.
708 if (dest_type == DataElement::TYPE_BYTES_DESCRIPTION)
709 copy.dest_item->set_memory_allocation(nullptr);
710
711 const DataElement& source_element =
712 copy.source_item->item()->data_element();
713 std::unique_ptr<DataElement> new_element(new DataElement());
714 new_element->SetToFilePathRange(
715 source_element.path(),
716 source_element.offset() + copy.source_item_offset, dest_size,
717 source_element.expected_modification_time());
718 scoped_refptr<BlobDataItem> new_item(new BlobDataItem(
719 std::move(new_element), copy.source_item->item()->data_handle_));
720 copy.dest_item->set_item(std::move(new_item));
721 break;
722 }
627 case DataElement::TYPE_UNKNOWN: 723 case DataElement::TYPE_UNKNOWN:
628 case DataElement::TYPE_BLOB: 724 case DataElement::TYPE_BLOB:
629 case DataElement::TYPE_BYTES_DESCRIPTION: 725 case DataElement::TYPE_BYTES_DESCRIPTION:
630 case DataElement::TYPE_FILE_FILESYSTEM: 726 case DataElement::TYPE_FILE_FILESYSTEM:
631 case DataElement::TYPE_DISK_CACHE_ENTRY: 727 case DataElement::TYPE_DISK_CACHE_ENTRY:
632 NOTREACHED(); 728 NOTREACHED();
633 break; 729 break;
634 } 730 }
635 copy.dest_item->set_state(ShareableBlobDataItem::POPULATED_WITH_QUOTA); 731 copy.dest_item->set_state(ShareableBlobDataItem::POPULATED_WITH_QUOTA);
636 } 732 }
(...skipping 26 matching lines...) Expand all
663 BlobEntry::BuildingState* building_state = entry->building_state_.get(); 759 BlobEntry::BuildingState* building_state = entry->building_state_.get();
664 if (building_state->transport_allowed_callback) { 760 if (building_state->transport_allowed_callback) {
665 base::ResetAndReturn(&building_state->transport_allowed_callback) 761 base::ResetAndReturn(&building_state->transport_allowed_callback)
666 .Run(BlobStatus::PENDING_TRANSPORT, std::move(files)); 762 .Run(BlobStatus::PENDING_TRANSPORT, std::move(files));
667 return; 763 return;
668 } 764 }
669 DCHECK(files.empty()); 765 DCHECK(files.empty());
670 NotifyTransportCompleteInternal(entry); 766 NotifyTransportCompleteInternal(entry);
671 } 767 }
672 768
673 void BlobStorageContext::OnEnoughSizeForMemory(const std::string& uuid, 769 void BlobStorageContext::OnEnoughSpaceForTransportByFiles(
674 bool success) { 770 const std::string& uuid,
771 bool success,
772 std::vector<BlobMemoryController::FileCreationInfo> files) {
675 if (!success) { 773 if (!success) {
676 CancelBuildingBlob(uuid, BlobStatus::ERR_OUT_OF_MEMORY); 774 CancelBuildingBlob(uuid, BlobStatus::ERR_OUT_OF_MEMORY);
677 return; 775 return;
678 } 776 }
679 BlobEntry* entry = registry_.GetEntry(uuid); 777 BlobEntry* entry = registry_.GetEntry(uuid);
680 if (!entry || !entry->building_state_.get()) 778 if (!entry || !entry->building_state_.get())
681 return; 779 return;
682 BlobEntry::BuildingState& building_state = *entry->building_state_; 780 BlobEntry::BuildingState& building_state = *entry->building_state_;
683 DCHECK(!building_state.memory_quota_request); 781 DCHECK(!building_state.transport_quota_request);
782 DCHECK(building_state.transport_items_present);
684 783
685 if (building_state.transport_items_present) { 784 entry->set_status(BlobStatus::PENDING_TRANSPORT);
686 entry->set_status(BlobStatus::PENDING_TRANSPORT); 785 RequestTransport(entry, std::move(files));
687 RequestTransport(entry,
688 std::vector<BlobMemoryController::FileCreationInfo>());
689 } else {
690 entry->set_status(BlobStatus::PENDING_INTERNALS);
691 }
692 786
693 if (entry->CanFinishBuilding()) 787 if (entry->CanFinishBuilding())
694 FinishBuilding(entry); 788 FinishBuilding(entry);
789 }
790
791 void BlobStorageContext::OnEnoughSpaceForTransportByMemory(
792 const std::string& uuid,
793 bool success) {
794 OnEnoughSpaceForTransportByFiles(
795 uuid, success, std::vector<BlobMemoryController::FileCreationInfo>());
796 }
797
798 void BlobStorageContext::OnEnoughSpaceForCopies(const std::string& uuid,
799 bool success) {
800 if (!success) {
801 CancelBuildingBlob(uuid, BlobStatus::ERR_OUT_OF_MEMORY);
802 return;
803 }
804 BlobEntry* entry = registry_.GetEntry(uuid);
805 if (!entry)
806 return;
807
808 if (entry->CanFinishBuilding())
809 FinishBuilding(entry);
695 } 810 }
696 811
697 void BlobStorageContext::OnDependentBlobFinished( 812 void BlobStorageContext::OnDependentBlobFinished(
698 const std::string& owning_blob_uuid, 813 const std::string& owning_blob_uuid,
699 BlobStatus status) { 814 BlobStatus status) {
700 BlobEntry* entry = registry_.GetEntry(owning_blob_uuid); 815 BlobEntry* entry = registry_.GetEntry(owning_blob_uuid);
701 if (!entry || !entry->building_state_) 816 if (!entry || !entry->building_state_)
702 return; 817 return;
703 818
704 if (BlobStatusIsError(status)) { 819 if (BlobStatusIsError(status)) {
705 DCHECK_NE(BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, status) 820 DCHECK_NE(BlobStatus::ERR_BLOB_DEREFERENCED_WHILE_BUILDING, status)
706 << "Referenced blob should never be dereferenced while we " 821 << "Referenced blob should never be dereferenced while we "
707 << "are depending on it, as our system holds a handle."; 822 << "are depending on it, as our system holds a handle.";
708 CancelBuildingBlobInternal(entry, BlobStatus::ERR_REFERENCED_BLOB_BROKEN); 823 CancelBuildingBlobInternal(entry, BlobStatus::ERR_REFERENCED_BLOB_BROKEN);
709 return; 824 return;
710 } 825 }
711 DCHECK_GT(entry->building_state_->num_building_dependent_blobs, 0u); 826 DCHECK_GT(entry->building_state_->num_building_dependent_blobs, 0u);
712 --entry->building_state_->num_building_dependent_blobs; 827 --entry->building_state_->num_building_dependent_blobs;
713 828
714 if (entry->CanFinishBuilding()) 829 if (entry->CanFinishBuilding())
715 FinishBuilding(entry); 830 FinishBuilding(entry);
716 } 831 }
717 832
718 void BlobStorageContext::ClearAndFreeMemory(BlobEntry* entry) { 833 void BlobStorageContext::ClearAndFreeMemory(BlobEntry* entry) {
719 if (entry->building_state_) { 834 if (entry->building_state_) {
720 BlobEntry::BuildingState* building_state = entry->building_state_.get(); 835 BlobEntry::BuildingState* building_state = entry->building_state_.get();
721 if (building_state->memory_quota_request) { 836 if (building_state->copy_quota_request) {
722 building_state->memory_quota_request->Cancel(); 837 building_state->copy_quota_request->Cancel();
838 }
839 if (building_state->transport_quota_request) {
840 building_state->transport_quota_request->Cancel();
723 } 841 }
724 } 842 }
725 entry->ClearItems(); 843 entry->ClearItems();
726 entry->ClearOffsets(); 844 entry->ClearOffsets();
727 entry->set_size(0); 845 entry->set_size(0);
728 } 846 }
729 847
730 } // namespace storage 848 } // namespace storage
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698