| 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 9680e4d4413f88bec7cfbea9abcc34e0ec34eb15..992a785643277c2a61ab588f31d5009ae9096b93 100644
|
| --- a/storage/browser/blob/blob_storage_context.cc
|
| +++ b/storage/browser/blob/blob_storage_context.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/logging.h"
|
| #include "base/message_loop/message_loop_proxy.h"
|
| #include "base/metrics/histogram.h"
|
| +#include "base/stl_util.h"
|
| #include "storage/browser/blob/blob_data_handle.h"
|
| #include "storage/common/blob/blob_data.h"
|
| #include "url/gurl.h"
|
| @@ -43,9 +44,10 @@ BlobStorageContext::BlobMapEntry::BlobMapEntry()
|
| : refcount(0), flags(0) {
|
| }
|
|
|
| -BlobStorageContext::BlobMapEntry::BlobMapEntry(
|
| - int refcount, int flags, BlobData* data)
|
| - : refcount(refcount), flags(flags), data(data) {
|
| +BlobStorageContext::BlobMapEntry::BlobMapEntry(int refcount,
|
| + int flags,
|
| + BlobDataBuilder* data)
|
| + : refcount(refcount), flags(flags), data_builder(data) {
|
| }
|
|
|
| BlobStorageContext::BlobMapEntry::~BlobMapEntry() {
|
| @@ -56,42 +58,43 @@ BlobStorageContext::BlobStorageContext()
|
| }
|
|
|
| BlobStorageContext::~BlobStorageContext() {
|
| + STLDeleteContainerPairSecondPointers(blob_map_.begin(), blob_map_.end());
|
| }
|
|
|
| -scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromUUID(
|
| +scoped_ptr<BlobDataSnapshotHandle> BlobStorageContext::GetBlobDataFromUUID(
|
| const std::string& uuid) {
|
| - scoped_ptr<BlobDataHandle> result;
|
| + scoped_ptr<BlobDataSnapshotHandle> result;
|
| BlobMap::iterator found = blob_map_.find(uuid);
|
| if (found == blob_map_.end())
|
| return result.Pass();
|
| - if (found->second.flags & EXCEEDED_MEMORY)
|
| + auto* entry = found->second;
|
| + if (entry->flags & EXCEEDED_MEMORY)
|
| return result.Pass();
|
| - DCHECK(!(found->second.flags & BEING_BUILT));
|
| - result.reset(new BlobDataHandle(
|
| - found->second.data.get(), this, base::MessageLoopProxy::current().get()));
|
| + DCHECK(!(entry->flags & BEING_BUILT));
|
| + result.reset(
|
| + new BlobDataSnapshotHandle(new BlobDataSnapshot(*entry->data.get()), this,
|
| + base::MessageLoopProxy::current().get()));
|
| return result.Pass();
|
| }
|
|
|
| -scoped_ptr<BlobDataHandle> BlobStorageContext::GetBlobDataFromPublicURL(
|
| +scoped_ptr<BlobDataSnapshotHandle> BlobStorageContext::GetBlobDataFromPublicURL(
|
| const GURL& url) {
|
| BlobURLMap::iterator found = public_blob_urls_.find(
|
| BlobUrlHasRef(url) ? ClearBlobUrlRef(url) : url);
|
| if (found == public_blob_urls_.end())
|
| - return scoped_ptr<BlobDataHandle>();
|
| + return scoped_ptr<BlobDataSnapshotHandle>();
|
| return GetBlobDataFromUUID(found->second);
|
| }
|
|
|
| -scoped_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob(
|
| - const BlobData* data) {
|
| - StartBuildingBlob(data->uuid());
|
| - for (std::vector<BlobData::Item>::const_iterator iter =
|
| - data->items().begin();
|
| - iter != data->items().end(); ++iter) {
|
| - AppendBlobDataItem(data->uuid(), *iter);
|
| +scoped_ptr<BlobDataSnapshotHandle> BlobStorageContext::AddFinishedBlob(
|
| + const BlobDataBuilder& data) {
|
| + StartBuildingBlob(data.uuid_);
|
| + for (const auto& blob_item : data.items_) {
|
| + AppendBlobDataItem(data.uuid_, *(blob_item->item_));
|
| }
|
| - FinishBuildingBlob(data->uuid(), data->content_type());
|
| - scoped_ptr<BlobDataHandle> handle = GetBlobDataFromUUID(data->uuid());
|
| - DecrementBlobRefCount(data->uuid());
|
| + FinishBuildingBlob(data.uuid_, data.content_type_);
|
| + scoped_ptr<BlobDataSnapshotHandle> handle = GetBlobDataFromUUID(data.uuid_);
|
| + DecrementBlobRefCount(data.uuid_);
|
| return handle.Pass();
|
| }
|
|
|
| @@ -117,18 +120,19 @@ void BlobStorageContext::RevokePublicBlobURL(const GURL& blob_url) {
|
|
|
| void BlobStorageContext::StartBuildingBlob(const std::string& uuid) {
|
| DCHECK(!IsInUse(uuid) && !uuid.empty());
|
| - blob_map_[uuid] = BlobMapEntry(1, BEING_BUILT, new BlobData(uuid));
|
| + blob_map_[uuid] = new BlobMapEntry(1, BEING_BUILT, new BlobDataBuilder(uuid));
|
| }
|
|
|
| -void BlobStorageContext::AppendBlobDataItem(
|
| - const std::string& uuid, const BlobData::Item& item) {
|
| +void BlobStorageContext::AppendBlobDataItem(const std::string& uuid,
|
| + const DataElement& item) {
|
| DCHECK(IsBeingBuilt(uuid));
|
| BlobMap::iterator found = blob_map_.find(uuid);
|
| if (found == blob_map_.end())
|
| return;
|
| - if (found->second.flags & EXCEEDED_MEMORY)
|
| + auto* entry = found->second;
|
| + if (entry->flags & EXCEEDED_MEMORY)
|
| return;
|
| - BlobData* target_blob_data = found->second.data.get();
|
| + BlobDataBuilder* target_blob_data = entry->data_builder.get();
|
| DCHECK(target_blob_data);
|
|
|
| bool exceeded_memory = false;
|
| @@ -149,31 +153,30 @@ void BlobStorageContext::AppendBlobDataItem(
|
| UMA_HISTOGRAM_COUNTS("Storage.Blob.StorageSizeBeforeAppend",
|
| memory_usage_ / 1024);
|
| switch (item.type()) {
|
| - case BlobData::Item::TYPE_BYTES:
|
| + case DataElement::TYPE_BYTES:
|
| UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Bytes", length / 1024);
|
| DCHECK(!item.offset());
|
| exceeded_memory = !AppendBytesItem(target_blob_data, item.bytes(),
|
| static_cast<int64>(length));
|
| break;
|
| - case BlobData::Item::TYPE_FILE:
|
| + case DataElement::TYPE_FILE:
|
| UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.File", length / 1024);
|
| - AppendFileItem(target_blob_data, item.path(), item.offset(), length,
|
| - item.expected_modification_time());
|
| + AppendFileItem(target_blob_data, item.path(), item.offset(),
|
| + item.length(), item.expected_modification_time());
|
| break;
|
| - case BlobData::Item::TYPE_FILE_FILESYSTEM:
|
| + case DataElement::TYPE_FILE_FILESYSTEM:
|
| UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.FileSystem", length / 1024);
|
| AppendFileSystemFileItem(target_blob_data, item.filesystem_url(),
|
| - item.offset(), length,
|
| + item.offset(), item.length(),
|
| item.expected_modification_time());
|
| break;
|
| - case BlobData::Item::TYPE_BLOB: {
|
| + case DataElement::TYPE_BLOB: {
|
| UMA_HISTOGRAM_COUNTS("Storage.BlobItemSize.Blob", length / 1024);
|
| - scoped_ptr<BlobDataHandle> src = GetBlobDataFromUUID(item.blob_uuid());
|
| + scoped_ptr<BlobDataSnapshotHandle> src =
|
| + GetBlobDataFromUUID(item.blob_uuid());
|
| if (src)
|
| - exceeded_memory = !ExpandStorageItems(target_blob_data,
|
| - src->data(),
|
| - item.offset(),
|
| - item.length());
|
| + exceeded_memory = !ExpandStorageItems(target_blob_data, *src->data(),
|
| + item.offset(), item.length());
|
| break;
|
| }
|
| default:
|
| @@ -188,8 +191,8 @@ void BlobStorageContext::AppendBlobDataItem(
|
| // as a stop gap, we'll prevent memory usage over a max amount.
|
| if (exceeded_memory) {
|
| memory_usage_ -= target_blob_data->GetMemoryUsage();
|
| - found->second.flags |= EXCEEDED_MEMORY;
|
| - found->second.data = new BlobData(uuid);
|
| + entry->flags |= EXCEEDED_MEMORY;
|
| + entry->data_builder.reset(new BlobDataBuilder(uuid));
|
| return;
|
| }
|
| }
|
| @@ -200,13 +203,15 @@ void BlobStorageContext::FinishBuildingBlob(
|
| BlobMap::iterator found = blob_map_.find(uuid);
|
| if (found == blob_map_.end())
|
| return;
|
| - found->second.data->set_content_type(content_type);
|
| - found->second.flags &= ~BEING_BUILT;
|
| + auto* entry = found->second;
|
| + entry->data_builder->set_content_type(content_type);
|
| + entry->data = entry->data_builder->Build().Pass();
|
| + entry->data_builder.reset();
|
| + entry->flags &= ~BEING_BUILT;
|
| UMA_HISTOGRAM_COUNTS("Storage.Blob.ItemCount",
|
| - found->second.data->items().size());
|
| - UMA_HISTOGRAM_BOOLEAN(
|
| - "Storage.Blob.ExceededMemory",
|
| - (found->second.flags & EXCEEDED_MEMORY) == EXCEEDED_MEMORY);
|
| + entry->data->items().size());
|
| + UMA_HISTOGRAM_BOOLEAN("Storage.Blob.ExceededMemory",
|
| + (entry->flags & EXCEEDED_MEMORY) == EXCEEDED_MEMORY);
|
| }
|
|
|
| void BlobStorageContext::CancelBuildingBlob(const std::string& uuid) {
|
| @@ -220,60 +225,60 @@ void BlobStorageContext::IncrementBlobRefCount(const std::string& uuid) {
|
| DCHECK(false);
|
| return;
|
| }
|
| - ++(found->second.refcount);
|
| + ++(found->second->refcount);
|
| }
|
|
|
| void BlobStorageContext::DecrementBlobRefCount(const std::string& uuid) {
|
| BlobMap::iterator found = blob_map_.find(uuid);
|
| if (found == blob_map_.end())
|
| return;
|
| - DCHECK_EQ(found->second.data->uuid(), uuid);
|
| - if (--(found->second.refcount) == 0) {
|
| - memory_usage_ -= found->second.data->GetMemoryUsage();
|
| + auto* entry = found->second;
|
| + DCHECK_EQ(entry->data->uuid(), uuid);
|
| + if (--(entry->refcount) == 0) {
|
| + memory_usage_ -= entry->data->GetMemoryUsage();
|
| + delete entry;
|
| blob_map_.erase(found);
|
| }
|
| }
|
|
|
| bool BlobStorageContext::ExpandStorageItems(
|
| - BlobData* target_blob_data, BlobData* src_blob_data,
|
| - uint64 offset, uint64 length) {
|
| - DCHECK(target_blob_data && src_blob_data &&
|
| - length != static_cast<uint64>(-1));
|
| -
|
| - std::vector<BlobData::Item>::const_iterator iter =
|
| - src_blob_data->items().begin();
|
| + BlobDataBuilder* target_blob_data,
|
| + const BlobDataSnapshot& src_blob_data,
|
| + uint64 offset,
|
| + uint64 length) {
|
| + DCHECK(target_blob_data && length != static_cast<uint64>(-1));
|
| +
|
| + auto& items = src_blob_data.items();
|
| + auto iter = items.begin();
|
| if (offset) {
|
| - for (; iter != src_blob_data->items().end(); ++iter) {
|
| - if (offset >= iter->length())
|
| - offset -= iter->length();
|
| + for (; iter != items.end(); ++iter) {
|
| + const BlobDataItem& item = *(iter->get());
|
| + if (offset >= item.length())
|
| + offset -= item.length();
|
| else
|
| break;
|
| }
|
| }
|
|
|
| - for (; iter != src_blob_data->items().end() && length > 0; ++iter) {
|
| - uint64 current_length = iter->length() - offset;
|
| + for (; iter != items.end() && length > 0; ++iter) {
|
| + const BlobDataItem& item = *(iter->get());
|
| + uint64 current_length = item.length() - offset;
|
| uint64 new_length = current_length > length ? length : current_length;
|
| - if (iter->type() == BlobData::Item::TYPE_BYTES) {
|
| + if (iter->get()->type() == DataElement::TYPE_BYTES) {
|
| if (!AppendBytesItem(
|
| target_blob_data,
|
| - iter->bytes() + static_cast<size_t>(iter->offset() + offset),
|
| + item.bytes() + static_cast<size_t>(item.offset() + offset),
|
| static_cast<int64>(new_length))) {
|
| return false; // exceeded memory
|
| }
|
| - } else if (iter->type() == BlobData::Item::TYPE_FILE) {
|
| - AppendFileItem(target_blob_data,
|
| - iter->path(),
|
| - iter->offset() + offset,
|
| - new_length,
|
| - iter->expected_modification_time());
|
| + } else if (item.type() == DataElement::TYPE_FILE) {
|
| + AppendFileItem(target_blob_data, item.path(), item.offset() + offset,
|
| + new_length, item.expected_modification_time());
|
| } else {
|
| - DCHECK(iter->type() == BlobData::Item::TYPE_FILE_FILESYSTEM);
|
| - AppendFileSystemFileItem(target_blob_data,
|
| - iter->filesystem_url(),
|
| - iter->offset() + offset,
|
| - new_length,
|
| - iter->expected_modification_time());
|
| + DCHECK(item.type() == DataElement::TYPE_FILE_FILESYSTEM);
|
| + AppendFileSystemFileItem(target_blob_data, item.filesystem_url(),
|
| + item.offset() + offset, new_length,
|
| + item.expected_modification_time());
|
| }
|
| length -= new_length;
|
| offset = 0;
|
| @@ -281,36 +286,40 @@ bool BlobStorageContext::ExpandStorageItems(
|
| return true;
|
| }
|
|
|
| -bool BlobStorageContext::AppendBytesItem(
|
| - BlobData* target_blob_data, const char* bytes, int64 length) {
|
| +bool BlobStorageContext::AppendBytesItem(BlobDataBuilder* target_blob_data,
|
| + const char* bytes,
|
| + int64 length) {
|
| if (length < 0) {
|
| DCHECK(false);
|
| return false;
|
| }
|
| - if (memory_usage_ + length > kMaxMemoryUsage)
|
| + if (memory_usage_ + length > kMaxMemoryUsage) {
|
| return false;
|
| + }
|
| target_blob_data->AppendData(bytes, static_cast<size_t>(length));
|
| memory_usage_ += length;
|
| return true;
|
| }
|
|
|
| void BlobStorageContext::AppendFileItem(
|
| - BlobData* target_blob_data,
|
| - const base::FilePath& file_path, uint64 offset, uint64 length,
|
| + BlobDataBuilder* target_blob_data,
|
| + const base::FilePath& file_path,
|
| + uint64 offset,
|
| + uint64 length,
|
| const base::Time& expected_modification_time) {
|
| - target_blob_data->AppendFile(file_path, offset, length,
|
| - expected_modification_time);
|
| -
|
| // It may be a temporary file that should be deleted when no longer needed.
|
| scoped_refptr<ShareableFileReference> shareable_file =
|
| ShareableFileReference::Get(file_path);
|
| - if (shareable_file.get())
|
| - target_blob_data->AttachShareableFileReference(shareable_file.get());
|
| +
|
| + target_blob_data->AppendFile(file_path, offset, length,
|
| + expected_modification_time, shareable_file);
|
| }
|
|
|
| void BlobStorageContext::AppendFileSystemFileItem(
|
| - BlobData* target_blob_data,
|
| - const GURL& filesystem_url, uint64 offset, uint64 length,
|
| + BlobDataBuilder* target_blob_data,
|
| + const GURL& filesystem_url,
|
| + uint64 offset,
|
| + uint64 length,
|
| const base::Time& expected_modification_time) {
|
| target_blob_data->AppendFileSystemFile(filesystem_url, offset, length,
|
| expected_modification_time);
|
| @@ -324,7 +333,7 @@ bool BlobStorageContext::IsBeingBuilt(const std::string& uuid) {
|
| BlobMap::iterator found = blob_map_.find(uuid);
|
| if (found == blob_map_.end())
|
| return false;
|
| - return found->second.flags & BEING_BUILT;
|
| + return (found->second->flags & BEING_BUILT) && found->second->data_builder;
|
| }
|
|
|
| bool BlobStorageContext::IsUrlRegistered(const GURL& blob_url) {
|
|
|