| 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);
|
|
|