Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" | 5 #include "content/browser/indexed_db/indexed_db_backing_store.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
| 9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 SET_MAX_OBJECT_STORE_ID, | 119 SET_MAX_OBJECT_STORE_ID, |
| 120 SET_MAX_INDEX_ID, | 120 SET_MAX_INDEX_ID, |
| 121 GET_NEW_DATABASE_ID, | 121 GET_NEW_DATABASE_ID, |
| 122 GET_NEW_VERSION_NUMBER, | 122 GET_NEW_VERSION_NUMBER, |
| 123 CREATE_IDBDATABASE_METADATA, | 123 CREATE_IDBDATABASE_METADATA, |
| 124 DELETE_DATABASE, | 124 DELETE_DATABASE, |
| 125 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro | 125 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro |
| 126 GET_DATABASE_NAMES, | 126 GET_DATABASE_NAMES, |
| 127 DELETE_INDEX, | 127 DELETE_INDEX, |
| 128 CLEAR_OBJECT_STORE, | 128 CLEAR_OBJECT_STORE, |
| 129 DECODE_BLOB_JOURNAL, | |
| 129 INTERNAL_ERROR_MAX, | 130 INTERNAL_ERROR_MAX, |
| 130 }; | 131 }; |
| 131 | 132 |
| 132 static void RecordInternalError(const char* type, | 133 static void RecordInternalError(const char* type, |
| 133 IndexedDBBackingStoreErrorSource location) { | 134 IndexedDBBackingStoreErrorSource location) { |
| 134 std::string name; | 135 std::string name; |
| 135 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); | 136 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); |
| 136 base::Histogram::FactoryGet(name, | 137 base::Histogram::FactoryGet(name, |
| 137 1, | 138 1, |
| 138 INTERNAL_ERROR_MAX, | 139 INTERNAL_ERROR_MAX, |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 467 scoped_ptr<LevelDBDatabase>* db, | 468 scoped_ptr<LevelDBDatabase>* db, |
| 468 bool* is_disk_full) OVERRIDE { | 469 bool* is_disk_full) OVERRIDE { |
| 469 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); | 470 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); |
| 470 } | 471 } |
| 471 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) | 472 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) |
| 472 OVERRIDE { | 473 OVERRIDE { |
| 473 return LevelDBDatabase::Destroy(file_name); | 474 return LevelDBDatabase::Destroy(file_name); |
| 474 } | 475 } |
| 475 }; | 476 }; |
| 476 | 477 |
| 478 // TODO(ericu): Error recovery. If we persistently can't read the | |
| 479 // blob journal, the safe thing to do is to clear it and leak the blobs, | |
| 480 // though that may be costly. Still, database/directory deletion should always | |
| 481 // clean things up, and we can write an fsck that will do a full correction if | |
| 482 // need be. | |
| 483 template <typename T> | |
| 484 static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key, | |
| 485 T* leveldb_transaction, | |
| 486 BlobJournalType* journal) { | |
| 487 std::string data; | |
| 488 bool found = false; | |
| 489 leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found); | |
| 490 if (!s.ok()) { | |
| 491 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); | |
|
cmumford
2014/04/30 21:29:30
INTERNAL_READ_ERROR_UNTESTED assuming you don't ha
ericu
2014/04/30 22:16:10
I made the quick fix; no test yet.
cmumford
2014/04/30 22:40:09
Unfortunately all corruptions are not detectable a
| |
| 492 return s; | |
| 493 } | |
| 494 journal->clear(); | |
| 495 if (!found) | |
|
cmumford
2014/04/30 21:29:30
why not just (if !found || !data.size())?
ericu
2014/04/30 22:16:10
Done.
| |
| 496 return leveldb::Status::OK(); | |
| 497 if (!data.size()) | |
| 498 return leveldb::Status::OK(); | |
| 499 StringPiece slice(data); | |
| 500 if (!DecodeBlobJournal(&slice, journal)) { | |
| 501 INTERNAL_READ_ERROR(DECODE_BLOB_JOURNAL); | |
| 502 s = InternalInconsistencyStatus(); | |
| 503 } | |
| 504 return s; | |
| 505 } | |
| 506 | |
| 507 static void ClearBlobJournal(LevelDBTransaction* leveldb_transaction, | |
| 508 const std::string& level_db_key) { | |
| 509 leveldb_transaction->Remove(level_db_key); | |
|
cmumford
2014/04/30 21:29:30
A one line function doesn't seem worth the added c
ericu
2014/04/30 22:16:10
No, there's just the one line, called in two place
jsbell
2014/04/30 22:21:45
I like abstracting it.
| |
| 510 } | |
| 511 | |
| 512 static void UpdatePrimaryJournalWithBlobList( | |
| 513 LevelDBTransaction* leveldb_transaction, | |
| 514 const BlobJournalType& journal) { | |
| 515 const std::string leveldb_key = BlobJournalKey::Encode(); | |
| 516 std::string data; | |
| 517 EncodeBlobJournal(journal, &data); | |
| 518 leveldb_transaction->Put(leveldb_key, &data); | |
| 519 } | |
| 520 | |
| 521 static void UpdateLiveBlobJournalWithBlobList( | |
| 522 LevelDBTransaction* leveldb_transaction, | |
| 523 const BlobJournalType& journal) { | |
| 524 const std::string leveldb_key = LiveBlobJournalKey::Encode(); | |
| 525 std::string data; | |
| 526 EncodeBlobJournal(journal, &data); | |
| 527 leveldb_transaction->Put(leveldb_key, &data); | |
| 528 } | |
| 529 | |
| 530 static leveldb::Status MergeBlobsIntoLiveBlobJournal( | |
| 531 LevelDBTransaction* leveldb_transaction, | |
| 532 const BlobJournalType& journal) { | |
| 533 BlobJournalType old_journal; | |
| 534 std::string key = LiveBlobJournalKey::Encode(); | |
| 535 leveldb::Status s = GetBlobJournal(key, leveldb_transaction, &old_journal); | |
| 536 if (!s.ok()) | |
| 537 return s; | |
| 538 | |
| 539 old_journal.insert(old_journal.end(), journal.begin(), journal.end()); | |
| 540 | |
| 541 UpdateLiveBlobJournalWithBlobList(leveldb_transaction, old_journal); | |
| 542 return leveldb::Status::OK(); | |
| 543 } | |
| 544 | |
| 545 static void UpdateBlobJournalWithDatabase( | |
| 546 LevelDBDirectTransaction* leveldb_transaction, | |
| 547 int64 database_id) { | |
| 548 BlobJournalType journal; | |
| 549 journal.push_back( | |
| 550 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); | |
| 551 const std::string key = BlobJournalKey::Encode(); | |
| 552 std::string data; | |
| 553 EncodeBlobJournal(journal, &data); | |
| 554 leveldb_transaction->Put(key, &data); | |
| 555 } | |
| 556 | |
| 557 static leveldb::Status MergeDatabaseIntoLiveBlobJournal( | |
| 558 LevelDBDirectTransaction* leveldb_transaction, | |
| 559 int64 database_id) { | |
| 560 BlobJournalType journal; | |
| 561 std::string key = LiveBlobJournalKey::Encode(); | |
|
cmumford
2014/04/30 21:29:30
nit: I see that sometimes you use a const string f
ericu
2014/04/30 22:16:10
Nope; just an oversight. Fixed.
| |
| 562 leveldb::Status s = GetBlobJournal(key, leveldb_transaction, &journal); | |
| 563 if (!s.ok()) | |
| 564 return s; | |
| 565 journal.push_back( | |
| 566 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); | |
| 567 std::string data; | |
| 568 EncodeBlobJournal(journal, &data); | |
| 569 leveldb_transaction->Put(key, &data); | |
| 570 return leveldb::Status::OK(); | |
| 571 } | |
| 572 | |
| 477 IndexedDBBackingStore::IndexedDBBackingStore( | 573 IndexedDBBackingStore::IndexedDBBackingStore( |
| 478 IndexedDBFactory* indexed_db_factory, | 574 IndexedDBFactory* indexed_db_factory, |
| 479 const GURL& origin_url, | 575 const GURL& origin_url, |
| 480 const base::FilePath& blob_path, | 576 const base::FilePath& blob_path, |
| 481 net::URLRequestContext* request_context, | 577 net::URLRequestContext* request_context, |
| 482 scoped_ptr<LevelDBDatabase> db, | 578 scoped_ptr<LevelDBDatabase> db, |
| 483 scoped_ptr<LevelDBComparator> comparator, | 579 scoped_ptr<LevelDBComparator> comparator, |
| 484 base::TaskRunner* task_runner) | 580 base::TaskRunner* task_runner) |
| 485 : indexed_db_factory_(indexed_db_factory), | 581 : indexed_db_factory_(indexed_db_factory), |
| 486 origin_url_(origin_url), | 582 origin_url_(origin_url), |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1091 s = it->Next()) | 1187 s = it->Next()) |
| 1092 transaction->Remove(it->Key()); | 1188 transaction->Remove(it->Key()); |
| 1093 if (!s.ok()) { | 1189 if (!s.ok()) { |
| 1094 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); | 1190 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); |
| 1095 return s; | 1191 return s; |
| 1096 } | 1192 } |
| 1097 | 1193 |
| 1098 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); | 1194 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); |
| 1099 transaction->Remove(key); | 1195 transaction->Remove(key); |
| 1100 | 1196 |
| 1197 // TODO(ericu): Put the real calls to the blob journal code here. For now, | |
| 1198 // I've inserted fake calls so that we don't get "you didn't use this static | |
| 1199 // function" compiler errors. | |
| 1200 if (false) { | |
| 1201 scoped_refptr<LevelDBTransaction> fake_transaction = | |
| 1202 new LevelDBTransaction(NULL); | |
| 1203 BlobJournalType fake_journal; | |
| 1204 MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id); | |
| 1205 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id); | |
| 1206 MergeBlobsIntoLiveBlobJournal(fake_transaction.get(), fake_journal); | |
| 1207 } | |
| 1208 | |
| 1101 s = transaction->Commit(); | 1209 s = transaction->Commit(); |
| 1102 if (!s.ok()) { | 1210 if (!s.ok()) { |
| 1103 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); | 1211 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); |
| 1104 return s; | 1212 return s; |
| 1105 } | 1213 } |
| 1106 db_->Compact(start_key, stop_key); | 1214 db_->Compact(start_key, stop_key); |
| 1107 return s; | 1215 return s; |
| 1108 } | 1216 } |
| 1109 | 1217 |
| 1110 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, | 1218 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1927 FROM_HERE, | 2035 FROM_HERE, |
| 1928 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread, | 2036 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread, |
| 1929 write_closure.get(), | 2037 write_closure.get(), |
| 1930 path, | 2038 path, |
| 1931 descriptor.url(), | 2039 descriptor.url(), |
| 1932 request_context_)); | 2040 request_context_)); |
| 1933 } | 2041 } |
| 1934 return true; | 2042 return true; |
| 1935 } | 2043 } |
| 1936 | 2044 |
| 2045 void IndexedDBBackingStore::ReportBlobUnused(int64 database_id, | |
| 2046 int64 blob_key) { | |
| 2047 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
| 2048 bool all_blobs = blob_key == DatabaseMetaDataKey::kAllBlobsKey; | |
| 2049 DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobKey(blob_key)); | |
| 2050 scoped_refptr<LevelDBTransaction> transaction = | |
| 2051 new LevelDBTransaction(db_.get()); | |
| 2052 | |
| 2053 std::string live_blob_key = LiveBlobJournalKey::Encode(); | |
| 2054 BlobJournalType live_blob_journal; | |
| 2055 if (!GetBlobJournal(live_blob_key, transaction.get(), &live_blob_journal) | |
| 2056 .ok()) | |
| 2057 return; | |
| 2058 DCHECK(live_blob_journal.size()); | |
| 2059 | |
| 2060 std::string primary_key = BlobJournalKey::Encode(); | |
| 2061 BlobJournalType primary_journal; | |
| 2062 if (!GetBlobJournal(primary_key, transaction.get(), &primary_journal).ok()) | |
| 2063 return; | |
| 2064 | |
| 2065 BlobJournalType::iterator journal_iter; | |
|
jsbell
2014/04/30 21:18:05
nit: move into the for()'s init clause, since the
ericu
2014/04/30 21:21:14
Yeah, good point.
| |
| 2066 // There are several cases to handle. If blob_key is kAllBlobsKey, we want to | |
| 2067 // remove all entries with database_id from the live_blob journal and add only | |
| 2068 // kAllBlobsKey to the primary journal. Otherwise if IsValidBlobKey(blob_key) | |
| 2069 // and we hit kAllBlobsKey for the right database_id in the journal, we leave | |
| 2070 // the kAllBlobsKey entry in the live_blob journal but add the specific blob | |
| 2071 // to the primary. Otherwise if IsValidBlobKey(blob_key) and we find a | |
| 2072 // matching (database_id, blob_key) tuple, we should move it to the primary | |
| 2073 // journal. | |
| 2074 BlobJournalType new_live_blob_journal; | |
| 2075 for (journal_iter = live_blob_journal.begin(); | |
| 2076 journal_iter != live_blob_journal.end(); | |
| 2077 ++journal_iter) { | |
| 2078 int64 current_database_id = journal_iter->first; | |
| 2079 int64 current_blob_key = journal_iter->second; | |
| 2080 bool current_all_blobs = | |
| 2081 current_blob_key == DatabaseMetaDataKey::kAllBlobsKey; | |
| 2082 DCHECK(KeyPrefix::IsValidDatabaseId(current_database_id) || | |
| 2083 current_all_blobs); | |
| 2084 if (current_database_id == database_id && | |
| 2085 (all_blobs || current_all_blobs || blob_key == current_blob_key)) { | |
| 2086 if (!all_blobs) { | |
| 2087 primary_journal.push_back( | |
| 2088 std::make_pair(database_id, current_blob_key)); | |
| 2089 if (current_all_blobs) | |
| 2090 new_live_blob_journal.push_back(*journal_iter); | |
| 2091 new_live_blob_journal.insert(new_live_blob_journal.end(), | |
| 2092 ++journal_iter, | |
| 2093 live_blob_journal.end()); // All the rest. | |
| 2094 break; | |
| 2095 } | |
| 2096 } else { | |
| 2097 new_live_blob_journal.push_back(*journal_iter); | |
| 2098 } | |
| 2099 } | |
| 2100 if (all_blobs) { | |
| 2101 primary_journal.push_back( | |
| 2102 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); | |
| 2103 } | |
| 2104 UpdatePrimaryJournalWithBlobList(transaction.get(), primary_journal); | |
| 2105 UpdateLiveBlobJournalWithBlobList(transaction.get(), new_live_blob_journal); | |
| 2106 transaction->Commit(); | |
| 2107 // We could just do the deletions/cleaning here, but if there are a lot of | |
| 2108 // blobs about to be garbage collected, it'd be better to wait and do them all | |
| 2109 // at once. | |
| 2110 StartJournalCleaningTimer(); | |
| 2111 } | |
| 2112 | |
| 2113 // The this reference is a raw pointer that's declared Unretained inside the | |
| 2114 // timer code, so this won't confuse IndexedDBFactory's check for | |
| 2115 // HasLastBackingStoreReference. It's safe because if the backing store is | |
| 2116 // deleted, the timer will automatically be canceled on destruction. | |
| 2117 void IndexedDBBackingStore::StartJournalCleaningTimer() { | |
| 2118 journal_cleaning_timer_.Start( | |
| 2119 FROM_HERE, | |
| 2120 base::TimeDelta::FromSeconds(5), | |
| 2121 this, | |
| 2122 &IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn); | |
| 2123 } | |
| 2124 | |
| 1937 // This assumes a file path of dbId/second-to-LSB-of-counter/counter. | 2125 // This assumes a file path of dbId/second-to-LSB-of-counter/counter. |
| 1938 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) { | 2126 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) { |
| 1939 return GetBlobFileNameForKey(blob_path_, database_id, key); | 2127 return GetBlobFileNameForKey(blob_path_, database_id, key); |
| 1940 } | 2128 } |
| 1941 | 2129 |
| 1942 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, | 2130 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, |
| 1943 const std::string& stop_key, | 2131 const std::string& stop_key, |
| 1944 int64 index_id, | 2132 int64 index_id, |
| 1945 unsigned char meta_data_type) { | 2133 unsigned char meta_data_type) { |
| 1946 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) | 2134 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2058 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) { | 2246 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) { |
| 2059 FilePath fileName = GetBlobFileName(database_id, key); | 2247 FilePath fileName = GetBlobFileName(database_id, key); |
| 2060 return base::DeleteFile(fileName, false); | 2248 return base::DeleteFile(fileName, false); |
| 2061 } | 2249 } |
| 2062 | 2250 |
| 2063 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) { | 2251 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) { |
| 2064 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id); | 2252 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id); |
| 2065 return base::DeleteFile(dirName, true); | 2253 return base::DeleteFile(dirName, true); |
| 2066 } | 2254 } |
| 2067 | 2255 |
| 2256 leveldb::Status IndexedDBBackingStore::CleanUpBlobJournal( | |
| 2257 const std::string& level_db_key) { | |
| 2258 scoped_refptr<LevelDBTransaction> journal_transaction = | |
| 2259 new LevelDBTransaction(db_.get()); | |
| 2260 BlobJournalType journal; | |
| 2261 leveldb::Status s = | |
| 2262 GetBlobJournal(level_db_key, journal_transaction.get(), &journal); | |
| 2263 if (!s.ok()) | |
| 2264 return s; | |
| 2265 if (!journal.size()) | |
| 2266 return leveldb::Status::OK(); | |
|
cmumford
2014/04/30 21:29:30
No need to worry about journal_transaction->Commit
ericu
2014/04/30 22:16:10
I'm not sure what you mean. It's discarded on exi
cmumford
2014/04/30 22:32:33
I misread it - thought transaction was a param - m
| |
| 2267 BlobJournalType::iterator journal_iter; | |
| 2268 for (journal_iter = journal.begin(); journal_iter != journal.end(); | |
| 2269 ++journal_iter) { | |
| 2270 int64 database_id = journal_iter->first; | |
| 2271 int64 blob_key = journal_iter->second; | |
| 2272 DCHECK(KeyPrefix::IsValidDatabaseId(database_id)); | |
| 2273 if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) { | |
| 2274 RemoveBlobDirectory(database_id); | |
| 2275 } else { | |
| 2276 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); | |
| 2277 RemoveBlobFile(database_id, blob_key); | |
|
cmumford
2014/04/30 21:29:30
Since this returns false on error can we at least
ericu
2014/04/30 22:16:10
Actually, we should do more than that. Changed to
| |
| 2278 } | |
| 2279 } | |
| 2280 ClearBlobJournal(journal_transaction.get(), level_db_key); | |
| 2281 return journal_transaction->Commit(); | |
| 2282 } | |
| 2283 | |
| 2284 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() { | |
| 2285 CleanUpBlobJournal(BlobJournalKey::Encode()); | |
| 2286 } | |
| 2287 | |
| 2068 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( | 2288 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( |
| 2069 LevelDBTransaction* transaction, | 2289 LevelDBTransaction* transaction, |
| 2070 int64 database_id, | 2290 int64 database_id, |
| 2071 int64 object_store_id, | 2291 int64 object_store_id, |
| 2072 int64 index_id) { | 2292 int64 index_id) { |
| 2073 int64 max_index_id = -1; | 2293 int64 max_index_id = -1; |
| 2074 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( | 2294 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( |
| 2075 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); | 2295 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); |
| 2076 bool found = false; | 2296 bool found = false; |
| 2077 leveldb::Status s = | 2297 leveldb::Status s = |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2375 return InvalidDBKeyStatus(); | 2595 return InvalidDBKeyStatus(); |
| 2376 } | 2596 } |
| 2377 | 2597 |
| 2378 StringPiece slice(found_encoded_primary_key); | 2598 StringPiece slice(found_encoded_primary_key); |
| 2379 if (DecodeIDBKey(&slice, found_primary_key) && slice.empty()) | 2599 if (DecodeIDBKey(&slice, found_primary_key) && slice.empty()) |
| 2380 return s; | 2600 return s; |
| 2381 else | 2601 else |
| 2382 return InvalidDBKeyStatus(); | 2602 return InvalidDBKeyStatus(); |
| 2383 } | 2603 } |
| 2384 | 2604 |
| 2385 void IndexedDBBackingStore::ReportBlobUnused(int64 database_id, | |
| 2386 int64 blob_key) { | |
| 2387 // TODO(ericu) | |
| 2388 } | |
| 2389 | |
| 2390 IndexedDBBackingStore::Cursor::Cursor( | 2605 IndexedDBBackingStore::Cursor::Cursor( |
| 2391 const IndexedDBBackingStore::Cursor* other) | 2606 const IndexedDBBackingStore::Cursor* other) |
| 2392 : transaction_(other->transaction_), | 2607 : transaction_(other->transaction_), |
| 2393 cursor_options_(other->cursor_options_), | 2608 cursor_options_(other->cursor_options_), |
| 2394 current_key_(new IndexedDBKey(*other->current_key_)) { | 2609 current_key_(new IndexedDBKey(*other->current_key_)) { |
| 2395 if (other->iterator_) { | 2610 if (other->iterator_) { |
| 2396 iterator_ = transaction_->CreateIterator(); | 2611 iterator_ = transaction_->CreateIterator(); |
| 2397 | 2612 |
| 2398 if (other->iterator_->IsValid()) { | 2613 if (other->iterator_->IsValid()) { |
| 2399 leveldb::Status s = iterator_->Seek(other->iterator_->Key()); | 2614 leveldb::Status s = iterator_->Seek(other->iterator_->Key()); |
| (...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3314 const GURL& url, | 3529 const GURL& url, |
| 3315 int64_t key) | 3530 int64_t key) |
| 3316 : is_file_(false), url_(url), key_(key) {} | 3531 : is_file_(false), url_(url), key_(key) {} |
| 3317 | 3532 |
| 3318 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( | 3533 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( |
| 3319 const FilePath& file_path, | 3534 const FilePath& file_path, |
| 3320 int64_t key) | 3535 int64_t key) |
| 3321 : is_file_(true), file_path_(file_path), key_(key) {} | 3536 : is_file_(true), file_path_(file_path), key_(key) {} |
| 3322 | 3537 |
| 3323 } // namespace content | 3538 } // namespace content |
| OLD | NEW |