Index: storage/common/blob/blob_data.h |
diff --git a/storage/common/blob/blob_data.h b/storage/common/blob/blob_data.h |
index 2f48546585b302b6587cc8d2855681dca017f49c..5850e851e90f75e615959b1e96c6403c562ff0c5 100644 |
--- a/storage/common/blob/blob_data.h |
+++ b/storage/common/blob/blob_data.h |
@@ -18,15 +18,80 @@ |
#include "url/gurl.h" |
namespace storage { |
+class BlobDataBuilder; |
+class BlobStorageContext; |
+ |
+// Ref counted blob item. This class owns the backing data of the blob item. |
+// The backing data is immutable, and cannot change after creation. |
+// The purpose of this class is to allow the resource to stick around in the |
+// snapshot even after the resource was swapped in the blob (either to disk or |
+// to memory) by the BlobStorageContext. |
+class STORAGE_COMMON_EXPORT BlobDataItem |
+ : public base::RefCountedThreadSafe<BlobDataItem> { |
+ public: |
+ storage::DataElement::Type type() const { return item_->type(); } |
+ const char* bytes() const { return item_->bytes(); } |
+ const base::FilePath& path() const { return item_->path(); } |
+ const GURL& filesystem_url() const { return item_->filesystem_url(); } |
+ const std::string& blob_uuid() const { return item_->blob_uuid(); } |
+ uint64 offset() const { return item_->offset(); } |
+ uint64 length() const { return item_->length(); } |
+ const base::Time& expected_modification_time() const { |
+ return item_->expected_modification_time(); |
+ } |
+ const DataElement& data_element() const { return *item_; } |
+ const DataElement* data_element_ptr() const { return item_.get(); } |
+ |
+ private: |
+ friend class BlobDataBuilder; |
+ friend class BlobStorageContext; |
+ friend class base::RefCountedThreadSafe<BlobDataItem>; |
+ BlobDataItem(scoped_ptr<DataElement> item); |
+ BlobDataItem(scoped_ptr<DataElement> item, |
+ scoped_refptr<ShareableFileReference> file_handle); |
+ virtual ~BlobDataItem(); |
+ |
+ scoped_ptr<storage::DataElement> item_; |
+ scoped_refptr<ShareableFileReference> file_handle_; |
+}; |
-class STORAGE_COMMON_EXPORT BlobData |
- : public base::RefCounted<BlobData> { |
+// Snapshot of a Blob. This snapshot holds a refcount of the current |
+// blob item resources so the backing storage for these items will stick |
+// around for the lifetime of this object. (The data represented by a blob is |
+// immutable, but the backing store can change). This structure thread safe. |
+class STORAGE_COMMON_EXPORT BlobDataSnapshot { |
public: |
- typedef storage::DataElement Item; |
+ BlobDataSnapshot(const BlobDataSnapshot& other); |
+ ~BlobDataSnapshot(); |
+ const std::string& uuid() const { return uuid_; } |
+ const std::vector<scoped_refptr<BlobDataItem>>& items() const { |
+ return items_; |
+ } |
+ const std::string& content_type() const { return content_type_; } |
+ const std::string& content_disposition() const { |
+ return content_disposition_; |
+ } |
+ size_t GetMemoryUsage() const; |
- // TODO(michaeln): remove the empty ctor when we fully transition to uuids. |
- BlobData(); |
- explicit BlobData(const std::string& uuid); |
+ private: |
+ friend class BlobDataBuilder; |
+ BlobDataSnapshot(const std::string& uuid, |
+ const std::string& content_type, |
+ const std::string& content_disposition, |
+ const std::vector<scoped_refptr<BlobDataItem>>& items); |
+ |
+ const std::string uuid_; |
+ const std::string content_type_; |
+ const std::string content_disposition_; |
+ const std::vector<scoped_refptr<BlobDataItem>> items_; |
+}; |
+ |
+class STORAGE_COMMON_EXPORT BlobDataBuilder { |
+ public: |
+ explicit BlobDataBuilder(const std::string& uuid); |
+ virtual ~BlobDataBuilder(); |
+ |
+ const std::string& uuid() const { return uuid_; } |
void AppendData(const std::string& data) { |
AppendData(data.c_str(), data.size()); |
@@ -34,61 +99,96 @@ class STORAGE_COMMON_EXPORT BlobData |
void AppendData(const char* data, size_t length); |
- void AppendFile(const base::FilePath& file_path, uint64 offset, uint64 length, |
+ void AppendFile(const base::FilePath& file_path, |
+ uint64 offset, |
+ uint64 length, |
const base::Time& expected_modification_time); |
+ |
+ void AppendFile(const base::FilePath& file_path, |
+ uint64 offset, |
+ uint64 length, |
+ const base::Time& expected_modification_time, |
+ scoped_refptr<ShareableFileReference> shareable_file); |
+ |
void AppendBlob(const std::string& uuid, uint64 offset, uint64 length); |
void AppendFileSystemFile(const GURL& url, uint64 offset, uint64 length, |
const base::Time& expected_modification_time); |
- void AttachShareableFileReference(ShareableFileReference* reference) { |
- shareable_files_.push_back(reference); |
- } |
- |
- const std::string& uuid() const { return uuid_; } |
- const std::vector<Item>& items() const { return items_; } |
- const std::string& content_type() const { return content_type_; } |
void set_content_type(const std::string& content_type) { |
content_type_ = content_type; |
} |
- const std::string& content_disposition() const { |
- return content_disposition_; |
- } |
void set_content_disposition(const std::string& content_disposition) { |
content_disposition_ = content_disposition; |
} |
- int64 GetMemoryUsage() const; |
+ size_t GetMemoryUsage() const; |
+ |
+ scoped_ptr<BlobDataSnapshot> Build(); |
private: |
- friend class base::RefCounted<BlobData>; |
- virtual ~BlobData(); |
+ friend class BlobStorageContext; |
+ friend bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b); |
+ friend bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b); |
std::string uuid_; |
std::string content_type_; |
std::string content_disposition_; |
- std::vector<Item> items_; |
- std::vector<scoped_refptr<ShareableFileReference> > shareable_files_; |
+ std::vector<scoped_refptr<BlobDataItem>> items_; |
- DISALLOW_COPY_AND_ASSIGN(BlobData); |
+ DISALLOW_COPY_AND_ASSIGN(BlobDataBuilder); |
}; |
#if defined(UNIT_TEST) |
-inline bool operator==(const BlobData& a, const BlobData& b) { |
- if (a.content_type() != b.content_type()) |
+inline bool operator==(const BlobDataItem& a, const BlobDataItem& b) { |
+ return a.data_element() == b.data_element(); |
+} |
+ |
+inline bool operator!=(const BlobDataItem& a, const BlobDataItem& b) { |
+ return !(a == b); |
+} |
+ |
+inline bool operator==(const BlobDataBuilder& a, const BlobDataBuilder& b) { |
+ if (a.content_type_ != b.content_type_) |
return false; |
- if (a.content_disposition() != b.content_disposition()) |
+ if (a.content_disposition_ != b.content_disposition_) |
return false; |
- if (a.items().size() != b.items().size()) |
+ if (a.items_.size() != b.items_.size()) |
return false; |
+ for (size_t i = 0; i < a.items_.size(); ++i) { |
+ if (a.items_[i] != b.items_[i]) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+inline bool operator==(const BlobDataSnapshot& a, const BlobDataBuilder& b) { |
michaeln
2015/01/16 00:09:09
an odd operator
dmurph
2015/01/16 23:45:56
It's to make testing easier. We grab a snapshot a
|
+ if (a.content_type() != b.content_type_) { |
+ printf("content type\n"); |
+ return false; |
+ } |
+ if (a.content_disposition() != b.content_disposition_) { |
+ printf("content disposition\n"); |
+ return false; |
+ } |
+ if (a.items().size() != b.items_.size()) { |
+ printf("items size\n"); |
+ return false; |
+ } |
for (size_t i = 0; i < a.items().size(); ++i) { |
- if (a.items()[i] != b.items()[i]) |
+ if (*(a.items()[i]) != *(b.items_[i])) { |
+ printf("item\n"); |
return false; |
+ } |
} |
return true; |
} |
-inline bool operator!=(const BlobData& a, const BlobData& b) { |
+inline bool operator!=(const BlobDataSnapshot& a, const BlobDataBuilder& b) { |
+ return !(a == b); |
+} |
+ |
+inline bool operator!=(const BlobDataBuilder& a, const BlobDataBuilder& b) { |
return !(a == b); |
} |
#endif // defined(UNIT_TEST) |