Chromium Code Reviews| Index: content/browser/indexed_db/indexed_db_leveldb_coding.cc |
| diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc |
| index 3a7028012a37beb119db04d8401a8397a684423a..716ccfe3c674688447a097b40b9346a141ec361f 100644 |
| --- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc |
| +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc |
| @@ -44,6 +44,12 @@ |
| // <0, 0, 0, 0> => backing store schema version [SchemaVersionKey] |
| // <0, 0, 0, 1> => maximum allocated database [MaxDatabaseIdKey] |
| // <0, 0, 0, 2> => SerializedScriptValue version [DataVersionKey] |
| +// <0, 0, 0, 3> |
| +// => Blob journal |
| +// The format of the journal is: {database_id, blobKey}*. |
| +// If the blobKey is AllBlobsKey, the whole database should be deleted. |
| +// [BlobJournalKey] |
| +// <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey] |
| // <0, 0, 0, 100, database id> |
| // => Existence implies the database id is in the free list |
| // [DatabaseFreeListKey] |
| @@ -59,6 +65,7 @@ |
| // <database id, 0, 0, 2> => IDB string version data (obsolete) |
| // <database id, 0, 0, 3> => maximum allocated object store id |
| // <database id, 0, 0, 4> => IDB integer version (var int) |
| +// <database id, 0, 0, 5> => blob key generator current number |
| // |
| // |
| // Object store metadata: [ObjectStoreMetaDataKey] |
| @@ -133,6 +140,14 @@ |
| // <database id, object store id, 2, user key> => "version" |
| // |
| // |
| +// Blob entry table: [BlobEntryKey] |
| +// -------------------------------- |
| +// |
| +// The prefix is followed by a type byte and the encoded IDB primary key. |
| +// |
| +// <database id, object store id, 3, user key> => array of IndexedDBBlobInfo |
| +// |
| +// |
| // Index data |
| // ---------- |
| // The prefix is followed by a type byte, the encoded IDB index key, a |
| @@ -163,8 +178,8 @@ using WebKit::WebIDBKeyPathTypeString; |
| namespace content { |
| // As most of the IndexedDBKeys and encoded values are short, we |
| -// initialize some Vectors with a default inline buffer size to reduce |
| -// the memory re-allocations when the Vectors are appended. |
| +// initialize some std::vectors with a default inline buffer size to reduce |
| +// the memory re-allocations when the std::vectors are appended. |
| static const size_t kDefaultInlineBufferSize = 32; |
| static const unsigned char kIndexedDBKeyNullTypeByte = 0; |
| @@ -179,12 +194,15 @@ static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0; |
| static const unsigned char kObjectStoreDataIndexId = 1; |
| static const unsigned char kExistsEntryIndexId = 2; |
| +static const unsigned char kBlobEntryIndexId = 3; |
| static const unsigned char kSchemaVersionTypeByte = 0; |
| static const unsigned char kMaxDatabaseIdTypeByte = 1; |
| static const unsigned char kDataVersionTypeByte = 2; |
| +static const unsigned char kBlobJournalTypeByte = 3; |
| +static const unsigned char kLiveBlobJournalTypeByte = 4; |
| static const unsigned char kMaxSimpleGlobalMetaDataTypeByte = |
| - 3; // Insert before this and increment. |
| + 5; // Insert before this and increment. |
| static const unsigned char kDatabaseFreeListTypeByte = 100; |
| static const unsigned char kDatabaseNameTypeByte = 201; |
| @@ -858,6 +876,34 @@ int Compare<ObjectStoreDataKey>(const StringPiece& a, |
| } |
| template <> |
| +int Compare<BlobEntryKey>(const StringPiece& a, |
| + const StringPiece& b, |
| + bool, |
| + bool* ok) { |
| + KeyPrefix prefix_a; |
| + KeyPrefix prefix_b; |
| + StringPiece slice_a(a); |
| + StringPiece slice_b(b); |
| + bool ok_a = KeyPrefix::Decode(&slice_a, &prefix_a); |
| + bool ok_b = KeyPrefix::Decode(&slice_b, &prefix_b); |
| + DCHECK(ok_a); |
| + DCHECK(ok_b); |
| + DCHECK(prefix_a.database_id_); |
| + DCHECK(prefix_a.object_store_id_); |
| + DCHECK_EQ(prefix_a.index_id_, BlobEntryKey::kSpecialIndexNumber); |
| + DCHECK(prefix_b.database_id_); |
| + DCHECK(prefix_b.object_store_id_); |
| + DCHECK_EQ(prefix_b.index_id_, BlobEntryKey::kSpecialIndexNumber); |
| + DCHECK(!slice_a.empty()); |
| + DCHECK(!slice_b.empty()); |
| + // Prefixes are not compared - it is assumed this was already done. |
| + DCHECK(!prefix_a.Compare(prefix_b)); |
| + |
| + return CompareSuffix<ObjectStoreDataKey>( |
| + &slice_a, &slice_b, false, ok); |
| +} |
| + |
| +template <> |
| int CompareSuffix<IndexDataKey>(StringPiece* slice_a, |
| StringPiece* slice_b, |
| bool only_compare_index_keys, |
| @@ -1036,6 +1082,15 @@ int Compare(const StringPiece& a, |
| &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok); |
| } |
| + case KeyPrefix::BLOB_ENTRY: { |
| + // Provide a stable ordering for invalid data. |
| + if (slice_a.empty() || slice_b.empty()) |
| + return CompareSizes(slice_a.size(), slice_b.size()); |
| + |
| + return CompareSuffix<BlobEntryKey>( |
| + &slice_a, &slice_b, /*only_compare_index_keys*/ false, ok); |
| + } |
| + |
| case KeyPrefix::INDEX_DATA: { |
| // Provide a stable ordering for invalid data. |
| if (slice_a.empty() || slice_b.empty()) |
| @@ -1237,6 +1292,8 @@ KeyPrefix::Type KeyPrefix::type() const { |
| return OBJECT_STORE_DATA; |
| if (index_id_ == kExistsEntryIndexId) |
| return EXISTS_ENTRY; |
| + if (index_id_ == kBlobEntryIndexId) |
| + return BLOB_ENTRY; |
| if (index_id_ >= kMinimumIndexId) |
| return INDEX_DATA; |
| @@ -1262,6 +1319,20 @@ std::string DataVersionKey::Encode() { |
| return ret; |
| } |
| +std::string BlobJournalKey::Encode() |
| +{ |
| + std::string ret = KeyPrefix::EncodeEmpty(); |
| + ret.push_back(kBlobJournalTypeByte); |
| + return ret; |
| +} |
| + |
| +std::string LiveBlobJournalKey::Encode() |
| +{ |
| + std::string ret = KeyPrefix::EncodeEmpty(); |
| + ret.push_back(kLiveBlobJournalTypeByte); |
| + return ret; |
| +} |
| + |
| DatabaseFreeListKey::DatabaseFreeListKey() : database_id_(-1) {} |
| bool DatabaseFreeListKey::Decode(StringPiece* slice, |
| @@ -1346,6 +1417,10 @@ int DatabaseNameKey::Compare(const DatabaseNameKey& other) { |
| return database_name_.compare(other.database_name_); |
| } |
| +bool DatabaseMetaDataKey::IsValidBlobKey(int64 blob_key) { |
| + return blob_key >= kBlobKeyGeneratorInitialNumber; |
| +} |
| + |
| std::string DatabaseMetaDataKey::Encode(int64 database_id, |
| MetaDataType meta_data_type) { |
| KeyPrefix prefix(database_id); |
| @@ -1752,6 +1827,103 @@ scoped_ptr<IndexedDBKey> ExistsEntryKey::user_key() const { |
| const int64 ExistsEntryKey::kSpecialIndexNumber = kExistsEntryIndexId; |
| +bool BlobEntryKey::Decode(StringPiece* slice, BlobEntryKey* result) { |
| + KeyPrefix prefix; |
| + if (!KeyPrefix::Decode(slice, &prefix)) |
| + return false; |
| + DCHECK(prefix.database_id_); |
| + DCHECK(prefix.object_store_id_); |
| + DCHECK_EQ(prefix.index_id_, kSpecialIndexNumber); |
| + |
| + if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_)) |
| + return false; |
| + result->database_id_ = prefix.database_id_; |
| + result->object_store_id_ = prefix.object_store_id_; |
| + |
| + return true; |
| +} |
| + |
| +bool BlobEntryKey::FromObjectStoreDataKey(StringPiece* slice, |
| + BlobEntryKey* result) { |
| + KeyPrefix prefix; |
| + if (!KeyPrefix::Decode(slice, &prefix)) |
| + return false; |
| + DCHECK(prefix.database_id_); |
| + DCHECK(prefix.object_store_id_); |
| + DCHECK_EQ(prefix.index_id_, ObjectStoreDataKey::kSpecialIndexNumber); |
| + |
| + if (!ExtractEncodedIDBKey(slice, &result->encoded_user_key_)) |
| + return false; |
| + result->database_id_ = prefix.database_id_; |
| + result->object_store_id_ = prefix.object_store_id_; |
| + return true; |
| +} |
| + |
| +std::string BlobEntryKey::EncodeToObjectStoreDataKey(StringPiece* slice) { |
|
jsbell
2013/09/13 00:12:21
What this method did wasn't obvious to me at the c
ericu
2013/11/20 23:05:39
Done.
|
| + BlobEntryKey key; |
| + if (!Decode(slice, &key)) |
| + return std::string(); |
| + |
| + return ObjectStoreDataKey::Encode( |
| + key.database_id_, key.object_store_id_, key.encoded_user_key_); |
| +} |
| + |
| +std::string BlobEntryKey::EncodeMinForObjectStore(int64 database_id, |
| + int64 object_store_id) { |
| + // Our implied encoded_user_key_ here is empty, the lowest possible key. |
| + return Encode(database_id, object_store_id, std::string()); |
| +} |
| + |
| +// This isn't technically the max for this object store--it's one higher, which |
| +// means that it's the first key /not/ in the range. That's more what we want, |
| +// but doesn't match the terminology elsewhere in this file, which is a bit |
| +// messy. |
| +std::string BlobEntryKey::EncodeMaxForObjectStore(int64 database_id, |
| + int64 object_store_id) |
| +{ |
| + DCHECK(KeyPrefix::ValidIds(database_id, object_store_id)); |
| + KeyPrefix prefix( |
| + KeyPrefix::CreateWithSpecialIndex(database_id, object_store_id, |
| + kSpecialIndexNumber + 1)); |
|
jsbell
2013/09/13 00:12:21
Can you introduce another const, rather than kSpec
ericu
2013/11/20 23:05:39
I think that might be confusing. The point is not
jsbell
2013/11/21 22:54:32
Got it, I wasn't paying attention to the usage (i.
|
| + return prefix.Encode(); |
| +} |
| + |
| +std::string BlobEntryKey::Encode() const |
| +{ |
| + DCHECK_GT(encoded_user_key_.size(), 0UL); |
| + return Encode(database_id_, object_store_id_, encoded_user_key_); |
| +} |
| + |
| +std::string BlobEntryKey::Encode(int64 database_id, |
| + int64 object_store_id, |
| + const IndexedDBKey& user_key) |
| +{ |
| + std::string encoded_key; |
| + EncodeIDBKey(user_key, &encoded_key); |
| + return Encode(database_id, object_store_id, encoded_key); |
| +} |
| + |
| +std::string BlobEntryKey::Encode( |
| + int64 database_id, int64 object_store_id, |
| + const std::string& encoded_user_key) { |
| + DCHECK(KeyPrefix::ValidIds(database_id, object_store_id)); |
| + KeyPrefix prefix( |
| + KeyPrefix::CreateWithSpecialIndex(database_id, object_store_id, |
| + kSpecialIndexNumber)); |
| + std::string ret = prefix.Encode(); |
| + ret.insert(ret.end(), encoded_user_key.begin(), encoded_user_key.end()); |
| + return ret; |
| +} |
| + |
| +int BlobEntryKey::Compare(const BlobEntryKey& other, bool* ok) |
| +{ |
| + DCHECK_GT(encoded_user_key_.size(), 0UL); |
| + DCHECK_GT(other.encoded_user_key_.size(), 0UL); |
| + return CompareEncodedIDBKeys(encoded_user_key_, other.encoded_user_key_, ok); |
| +} |
| + |
| +const int64 BlobEntryKey::kSpecialIndexNumber = kBlobEntryIndexId; |
| + |
| IndexDataKey::IndexDataKey() |
| : database_id_(-1), |
| object_store_id_(-1), |