Index: storage/browser/blob/blob_storage_context.cc |
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc |
index acc086e57c04070c32968b932f0dbec5ebc218e8..1fecda89f5b6799136cab3bc4089840251ad8f3b 100644 |
--- a/storage/browser/blob/blob_storage_context.cc |
+++ b/storage/browser/blob/blob_storage_context.cc |
@@ -92,13 +92,9 @@ |
size_t num_files_with_unknown_size = 0; |
size_t num_building_dependent_blobs = 0; |
- bool found_memory_transport = false; |
- bool found_file_transport = false; |
- |
base::CheckedNumeric<uint64_t> checked_total_size = 0; |
base::CheckedNumeric<uint64_t> checked_total_memory_size = 0; |
- base::CheckedNumeric<uint64_t> checked_transport_quota_needed = 0; |
- base::CheckedNumeric<uint64_t> checked_copy_quota_needed = 0; |
+ base::CheckedNumeric<uint64_t> checked_memory_quota_needed = 0; |
for (scoped_refptr<BlobDataItem> input_item : input_builder.items_) { |
const DataElement& input_element = input_item->data_element(); |
@@ -109,19 +105,11 @@ |
if (IsBytes(type)) { |
DCHECK_NE(0 + DataElement::kUnknownSize, input_element.length()); |
- found_memory_transport = true; |
- if (found_file_transport) { |
- // We cannot have both memory and file transport items. |
- status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; |
- return; |
- } |
- contains_unpopulated_transport_items |= |
- (type == DataElement::TYPE_BYTES_DESCRIPTION); |
- checked_transport_quota_needed += length; |
+ checked_memory_quota_needed += length; |
checked_total_size += length; |
scoped_refptr<ShareableBlobDataItem> item = new ShareableBlobDataItem( |
std::move(input_item), ShareableBlobDataItem::QUOTA_NEEDED); |
- pending_transport_items.push_back(item); |
+ pending_memory_items.push_back(item); |
transport_items.push_back(item.get()); |
output_blob->AppendSharedBlobItem(std::move(item)); |
continue; |
@@ -186,14 +174,14 @@ |
copies.push_back(ItemCopyEntry(slice.first_source_item, |
slice.first_item_slice_offset, |
slice.dest_items.front())); |
- pending_copy_items.push_back(slice.dest_items.front()); |
+ pending_memory_items.push_back(slice.dest_items.front()); |
} |
if (slice.last_source_item) { |
copies.push_back( |
ItemCopyEntry(slice.last_source_item, 0, slice.dest_items.back())); |
- pending_copy_items.push_back(slice.dest_items.back()); |
- } |
- checked_copy_quota_needed += slice.copying_memory_size; |
+ pending_memory_items.push_back(slice.dest_items.back()); |
+ } |
+ checked_memory_quota_needed += slice.copying_memory_size; |
for (auto& shareable_item : slice.dest_items) { |
output_blob->AppendSharedBlobItem(std::move(shareable_item)); |
@@ -201,30 +189,14 @@ |
continue; |
} |
- // If the source item is a temporary file item, then we need to keep track |
- // of that and mark it as needing quota. |
- scoped_refptr<ShareableBlobDataItem> item; |
- if (BlobDataBuilder::IsFutureFileItem(input_element)) { |
- found_file_transport = true; |
- if (found_memory_transport) { |
- // We cannot have both memory and file transport items. |
- status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; |
- return; |
- } |
- contains_unpopulated_transport_items = true; |
- item = new ShareableBlobDataItem(std::move(input_item), |
- ShareableBlobDataItem::QUOTA_NEEDED); |
- pending_transport_items.push_back(item); |
- transport_items.push_back(item.get()); |
- checked_transport_quota_needed += length; |
- } else { |
- item = new ShareableBlobDataItem( |
- std::move(input_item), |
- ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA); |
- } |
+ DCHECK(!BlobDataBuilder::IsFutureFileItem(input_element)) |
+ << "File allocation not implemented."; |
if (length == DataElement::kUnknownSize) |
num_files_with_unknown_size++; |
+ scoped_refptr<ShareableBlobDataItem> item = new ShareableBlobDataItem( |
+ std::move(input_item), ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA); |
+ |
checked_total_size += length; |
output_blob->AppendSharedBlobItem(std::move(item)); |
} |
@@ -234,18 +206,14 @@ |
return; |
} |
if (!checked_total_size.IsValid() || !checked_total_memory_size.IsValid() || |
- !checked_transport_quota_needed.IsValid() || |
- !checked_copy_quota_needed.IsValid()) { |
+ !checked_memory_quota_needed.IsValid()) { |
status = BlobStatus::ERR_INVALID_CONSTRUCTION_ARGUMENTS; |
return; |
} |
total_size = checked_total_size.ValueOrDie(); |
total_memory_size = checked_total_memory_size.ValueOrDie(); |
- transport_quota_needed = checked_transport_quota_needed.ValueOrDie(); |
- copy_quota_needed = checked_copy_quota_needed.ValueOrDie(); |
- transport_quota_type = found_file_transport ? TransportQuotaType::FILE |
- : TransportQuotaType::MEMORY; |
- if (transport_quota_needed) { |
+ memory_quota_needed = checked_memory_quota_needed.ValueOrDie(); |
+ if (memory_quota_needed) { |
status = BlobStatus::PENDING_QUOTA; |
} else { |
status = BlobStatus::PENDING_INTERNALS; |
@@ -330,16 +298,8 @@ |
data_item = |
new BlobDataItem(std::move(element), source_item->data_handle_); |
- if (BlobDataBuilder::IsFutureFileItem(source_item->data_element())) { |
- // The source file isn't a real file yet (path is fake), so store the |
- // items we need to copy from later. |
- if (item_index == first_item_index) { |
- first_item_slice_offset = item_offset; |
- first_source_item = source_items[item_index]; |
- } else { |
- last_source_item = source_items[item_index]; |
- } |
- } |
+ DCHECK(!BlobDataBuilder::IsFutureFileItem(source_item->data_element())) |
+ << "File allocation unimplemented."; |
break; |
} |
case DataElement::TYPE_FILE_FILESYSTEM: { |
@@ -381,13 +341,8 @@ |
: memory_controller_(base::FilePath(), scoped_refptr<base::TaskRunner>()), |
ptr_factory_(this) {} |
-BlobStorageContext::BlobStorageContext( |
- base::FilePath storage_directory, |
- scoped_refptr<base::TaskRunner> file_runner) |
- : memory_controller_(std::move(storage_directory), std::move(file_runner)), |
- ptr_factory_(this) {} |
- |
-BlobStorageContext::~BlobStorageContext() {} |
+BlobStorageContext::~BlobStorageContext() { |
+} |
std::unique_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID( |
const std::string& uuid) { |
@@ -459,9 +414,14 @@ |
// stores the complete item representation in the internal data. |
BlobFlattener flattener(content, entry, ®istry_); |
- DCHECK(!flattener.contains_unpopulated_transport_items || |
+ DCHECK(flattener.status != BlobStatus::PENDING_TRANSPORT || |
+ !transport_allowed_callback) |
+ << "There is no pending content for the user to populate, so the " |
+ "callback should be null."; |
+ DCHECK(flattener.status != BlobStatus::PENDING_TRANSPORT || |
transport_allowed_callback) |
- << "If we have pending unpopulated content then a callback is required"; |
+ << "If we have pending content then there needs to be a callback " |
+ "present."; |
entry->set_size(flattener.total_size); |
entry->set_status(flattener.status); |
@@ -470,14 +430,8 @@ |
UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount", entry->items().size()); |
UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalSize", |
flattener.total_memory_size / 1024); |
- |
- uint64_t total_memory_needed = |
- flattener.copy_quota_needed + |
- (flattener.transport_quota_type == TransportQuotaType::MEMORY |
- ? flattener.transport_quota_needed |
- : 0); |
UMA_HISTOGRAM_COUNTS("Storage.Blob.TotalUnsharedSize", |
- total_memory_needed / 1024); |
+ flattener.memory_quota_needed / 1024); |
size_t num_building_dependent_blobs = 0; |
std::vector<std::unique_ptr<BlobDataHandle>> dependent_blobs; |
@@ -500,7 +454,7 @@ |
} |
entry->set_building_state(base::MakeUnique<BlobEntry::BuildingState>( |
- !flattener.pending_transport_items.empty(), transport_allowed_callback, |
+ !flattener.transport_items.empty(), transport_allowed_callback, |
num_building_dependent_blobs)); |
BlobEntry::BuildingState* building_state = entry->building_state_.get(); |
std::swap(building_state->copies, flattener.copies); |
@@ -514,52 +468,21 @@ |
return handle; |
} |
- // Avoid the state where we might grant only one quota. |
- if (!memory_controller_.CanReserveQuota(flattener.copy_quota_needed + |
- flattener.transport_quota_needed)) { |
+ if (!memory_controller_.CanReserveQuota(flattener.memory_quota_needed)) { |
CancelBuildingBlobInternal(entry, BlobStatus::ERR_OUT_OF_MEMORY); |
return handle; |
} |
- if (flattener.copy_quota_needed > 0) { |
- // The blob can complete during the execution of |ReserveMemoryQuota|. |
+ if (flattener.memory_quota_needed > 0) { |
+ // The blob can complete during the execution of this line. |
base::WeakPtr<QuotaAllocationTask> pending_request = |
memory_controller_.ReserveMemoryQuota( |
- std::move(flattener.pending_copy_items), |
- base::Bind(&BlobStorageContext::OnEnoughSpaceForCopies, |
+ std::move(flattener.pending_memory_items), |
+ base::Bind(&BlobStorageContext::OnEnoughSizeForMemory, |
ptr_factory_.GetWeakPtr(), content.uuid_)); |
// Building state will be null if the blob is already finished. |
if (entry->building_state_) |
- entry->building_state_->copy_quota_request = std::move(pending_request); |
- } |
- |
- if (flattener.transport_quota_needed > 0) { |
- base::WeakPtr<QuotaAllocationTask> pending_request; |
- |
- switch (flattener.transport_quota_type) { |
- case TransportQuotaType::MEMORY: { |
- // The blob can complete during the execution of |ReserveMemoryQuota|. |
- std::vector<BlobMemoryController::FileCreationInfo> empty_files; |
- pending_request = memory_controller_.ReserveMemoryQuota( |
- std::move(flattener.pending_transport_items), |
- base::Bind(&BlobStorageContext::OnEnoughSpaceForTransport, |
- ptr_factory_.GetWeakPtr(), content.uuid_, |
- base::Passed(&empty_files))); |
- break; |
- } |
- case TransportQuotaType::FILE: |
- pending_request = memory_controller_.ReserveFileQuota( |
- std::move(flattener.pending_transport_items), |
- base::Bind(&BlobStorageContext::OnEnoughSpaceForTransport, |
- ptr_factory_.GetWeakPtr(), content.uuid_)); |
- break; |
- } |
- |
- // Building state will be null if the blob is already finished. |
- if (entry->building_state_) { |
- entry->building_state_->transport_quota_request = |
- std::move(pending_request); |
- } |
+ entry->building_state_->memory_quota_request = std::move(pending_request); |
} |
if (entry->CanFinishBuilding()) |
@@ -699,26 +622,8 @@ |
const char* src_data = |
copy.source_item->item()->bytes() + copy.source_item_offset; |
copy.dest_item->item()->item_->SetToBytes(src_data, dest_size); |
- break; |
- } |
- case DataElement::TYPE_FILE: { |
- // If we expected a memory item (and our source was paged to disk) we |
- // free that memory. |
- if (dest_type == DataElement::TYPE_BYTES_DESCRIPTION) |
- copy.dest_item->set_memory_allocation(nullptr); |
- |
- const DataElement& source_element = |
- copy.source_item->item()->data_element(); |
- std::unique_ptr<DataElement> new_element(new DataElement()); |
- new_element->SetToFilePathRange( |
- source_element.path(), |
- source_element.offset() + copy.source_item_offset, dest_size, |
- source_element.expected_modification_time()); |
- scoped_refptr<BlobDataItem> new_item(new BlobDataItem( |
- std::move(new_element), copy.source_item->item()->data_handle_)); |
- copy.dest_item->set_item(std::move(new_item)); |
- break; |
- } |
+ } break; |
+ case DataElement::TYPE_FILE: |
case DataElement::TYPE_UNKNOWN: |
case DataElement::TYPE_BLOB: |
case DataElement::TYPE_BYTES_DESCRIPTION: |
@@ -765,10 +670,8 @@ |
NotifyTransportCompleteInternal(entry); |
} |
-void BlobStorageContext::OnEnoughSpaceForTransport( |
- const std::string& uuid, |
- std::vector<BlobMemoryController::FileCreationInfo> files, |
- bool success) { |
+void BlobStorageContext::OnEnoughSizeForMemory(const std::string& uuid, |
+ bool success) { |
if (!success) { |
CancelBuildingBlob(uuid, BlobStatus::ERR_OUT_OF_MEMORY); |
return; |
@@ -777,25 +680,15 @@ |
if (!entry || !entry->building_state_.get()) |
return; |
BlobEntry::BuildingState& building_state = *entry->building_state_; |
- DCHECK(!building_state.transport_quota_request); |
- DCHECK(building_state.transport_items_present); |
- |
- entry->set_status(BlobStatus::PENDING_TRANSPORT); |
- RequestTransport(entry, std::move(files)); |
- |
- if (entry->CanFinishBuilding()) |
- FinishBuilding(entry); |
-} |
- |
-void BlobStorageContext::OnEnoughSpaceForCopies(const std::string& uuid, |
- bool success) { |
- if (!success) { |
- CancelBuildingBlob(uuid, BlobStatus::ERR_OUT_OF_MEMORY); |
- return; |
- } |
- BlobEntry* entry = registry_.GetEntry(uuid); |
- if (!entry) |
- return; |
+ DCHECK(!building_state.memory_quota_request); |
+ |
+ if (building_state.transport_items_present) { |
+ entry->set_status(BlobStatus::PENDING_TRANSPORT); |
+ RequestTransport(entry, |
+ std::vector<BlobMemoryController::FileCreationInfo>()); |
+ } else { |
+ entry->set_status(BlobStatus::PENDING_INTERNALS); |
+ } |
if (entry->CanFinishBuilding()) |
FinishBuilding(entry); |
@@ -823,8 +716,12 @@ |
} |
void BlobStorageContext::ClearAndFreeMemory(BlobEntry* entry) { |
- if (entry->building_state_) |
- entry->building_state_->CancelRequests(); |
+ if (entry->building_state_) { |
+ BlobEntry::BuildingState* building_state = entry->building_state_.get(); |
+ if (building_state->memory_quota_request) { |
+ building_state->memory_quota_request->Cancel(); |
+ } |
+ } |
entry->ClearItems(); |
entry->ClearOffsets(); |
entry->set_size(0); |