Index: storage/browser/blob/blob_flattener.cc |
diff --git a/storage/browser/blob/blob_flattener.cc b/storage/browser/blob/blob_flattener.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..57c5244eec905a5196d287fa227781879e23a7b3 |
--- /dev/null |
+++ b/storage/browser/blob/blob_flattener.cc |
@@ -0,0 +1,114 @@ |
+// TODO: Insert description here. (generated by dmurph) |
+ |
+#include "storage/browser/blob/blob_flattener.h" |
+ |
+#include <limits> |
+#include <set> |
+#include <utility> |
+ |
+#include "storage/browser/blob/blob_async_transport_request_builder.h" |
+#include "storage/browser/blob/blob_data_builder.h" |
+#include "storage/browser/blob/blob_storage_context.h" |
+#include "storage/browser/blob/blob_storage_registry.h" |
+#include "storage/browser/blob/shareable_blob_data_item.h" |
+ |
+namespace storage { |
+namespace { |
+using ItemCopyEntry = BlobStorageRegistry::ItemCopyEntry; |
+using BlobEntry = BlobStorageRegistry::Entry; |
+ |
+bool IsBytes(DataElement::Type type) { |
+ return type == DataElement::TYPE_BYTES || |
+ type == DataElement::TYPE_BYTES_DESCRIPTION; |
+} |
+ |
+} // namespace |
+ |
+// static |
+BlobFlattener::BlobFlattener(const BlobDataBuilder& transportation_result, |
+ InternalBlobData* output_blob, |
+ BlobStorageRegistry* registry) { |
+ const std::vector<scoped_refptr<BlobDataItem>>& transport_items = |
+ transportation_result.items_; |
+ const std::string& uuid = transportation_result.uuid_; |
+ |
+ std::set<std::string> dependent_blob_uuids; |
+ for (size_t transport_item_index = 0; |
+ transport_item_index < transport_items.size(); transport_item_index++) { |
+ scoped_refptr<BlobDataItem> transport_item = |
+ transport_items[transport_item_index]; |
+ |
+ DataElement::Type type = transport_item->type(); |
+ contains_pending_content |= type == DataElement::TYPE_BYTES_DESCRIPTION; |
+ |
+ if (IsBytes(type)) { |
+ memory_needed += transport_item->length(); |
+ total_size += transport_item->length(); |
+ output_blob->AppendSharedBlobItem( |
+ uuid, new ShareableBlobDataItem(std::move(transport_item))); |
+ } else if (type == DataElement::TYPE_BLOB) { |
+ BlobEntry* ref_entry = registry->GetEntry(transport_item->blob_uuid()); |
+ |
+ if (!ref_entry || BlobStatusIsError(ref_entry->status) || |
+ transport_item->blob_uuid() == uuid) { |
+ contains_broken_references = true; |
+ return; |
+ } |
+ |
+ if (dependent_blob_uuids.find(transport_item->blob_uuid()) == |
+ dependent_blob_uuids.end()) { |
+ dependent_blobs.push_back( |
+ std::make_pair(transport_item->blob_uuid(), ref_entry)); |
+ dependent_blob_uuids.insert(transport_item->blob_uuid()); |
+ } |
+ |
+ uint64_t length = |
+ transport_item->length() == std::numeric_limits<uint64_t>::max() |
Marijn Kruisselbrink
2016/07/12 21:33:06
if ::max() is a magic number for the length of a t
dmurph
2016/07/14 01:04:31
Yes, that sounds good.
|
+ ? ref_entry->data.total_size() |
+ : transport_item->length(); |
+ |
+ total_size += length; |
+ |
+ // If we're referencing the whole blob, then we don't need to slice. |
+ if (transport_item->offset() == 0 && |
+ length == ref_entry->data.total_size()) { |
+ for (const auto& shareable_item : ref_entry->data.items()) { |
+ output_blob->AppendSharedBlobItem(uuid, shareable_item); |
+ } |
+ continue; |
+ } |
+ |
+ BlobSlice slice(ref_entry->data, transport_item->offset(), |
+ transport_item->length()); |
+ |
+ if (slice.has_sliced_first_memory_item) { |
+ copies.push_back(ItemCopyEntry(slice.first_source_item, |
+ slice.first_item_slice_offset, |
+ slice.dest_items.front())); |
+ } |
+ |
+ memory_needed += slice.copying_memory_size; |
+ for (auto& shareable_item : slice.dest_items) { |
+ output_blob->AppendSharedBlobItem(uuid, std::move(shareable_item)); |
+ } |
+ |
+ if (slice.has_sliced_last_memory_item) { |
+ copies.push_back( |
+ ItemCopyEntry(slice.last_source_item, 0, slice.dest_items.back())); |
Marijn Kruisselbrink
2016/07/12 21:33:06
Does this work? Above you've moved all the items i
dmurph
2016/07/14 01:04:31
Yep, nice bug catch.
|
+ } |
+ } else { |
+ if (type == DataElement::TYPE_FILE) { |
+ contains_pending_content = |
+ transport_item->path().value() == |
+ BlobDataBuilder::kAppendFutureFileTemporaryFileName; |
+ } |
+ total_size += transport_item->length(); |
+ output_blob->AppendSharedBlobItem( |
+ uuid, new ShareableBlobDataItem(std::move(transport_item))); |
+ } |
+ } |
+} |
+ |
+BlobFlattener::~BlobFlattener() {} |
+ |
+} // namespace storage |