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

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

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

Powered by Google App Engine
This is Rietveld 408576698