Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: content/browser/indexed_db/indexed_db_backing_store.cc

Issue 197333009: Handling LevelDB errors encountered after open. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/json/json_reader.h"
9 #include "base/json/json_writer.h"
8 #include "base/logging.h" 10 #include "base/logging.h"
9 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/platform_file.h"
10 #include "base/strings/string_piece.h" 13 #include "base/strings/string_piece.h"
11 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "content/browser/indexed_db/indexed_db_database_error.h"
13 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" 17 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
14 #include "content/browser/indexed_db/indexed_db_metadata.h" 18 #include "content/browser/indexed_db/indexed_db_metadata.h"
15 #include "content/browser/indexed_db/indexed_db_tracing.h" 19 #include "content/browser/indexed_db/indexed_db_tracing.h"
16 #include "content/browser/indexed_db/indexed_db_value.h" 20 #include "content/browser/indexed_db/indexed_db_value.h"
17 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" 21 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
18 #include "content/browser/indexed_db/leveldb/leveldb_database.h" 22 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
19 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" 23 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
20 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 24 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
21 #include "content/common/indexed_db/indexed_db_key.h" 25 #include "content/common/indexed_db/indexed_db_key.h"
22 #include "content/common/indexed_db/indexed_db_key_path.h" 26 #include "content/common/indexed_db/indexed_db_key_path.h"
(...skipping 12 matching lines...) Expand all
35 static std::string ComputeOriginIdentifier(const GURL& origin_url) { 39 static std::string ComputeOriginIdentifier(const GURL& origin_url) {
36 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; 40 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
37 } 41 }
38 42
39 static base::FilePath ComputeFileName(const GURL& origin_url) { 43 static base::FilePath ComputeFileName(const GURL& origin_url) {
40 return base::FilePath() 44 return base::FilePath()
41 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) 45 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
42 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); 46 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
43 } 47 }
44 48
49 static base::FilePath ComputeCorruptionFileName(const GURL& origin_url) {
50 return ComputeFileName(origin_url).Append("corruption_info.json");
jsbell 2014/03/26 18:16:58 Doesn't this put the file in the directory, which
cmumford 2014/03/26 21:40:36 No, we call DestroyDB when the db is determined to
51 }
52
45 } // namespace 53 } // namespace
46 54
47 static const int64 kKeyGeneratorInitialNumber = 55 static const int64 kKeyGeneratorInitialNumber =
48 1; // From the IndexedDB specification. 56 1; // From the IndexedDB specification.
49 57
50 enum IndexedDBBackingStoreErrorSource { 58 enum IndexedDBBackingStoreErrorSource {
51 // 0 - 2 are no longer used. 59 // 0 - 2 are no longer used.
52 FIND_KEY_IN_INDEX = 3, 60 FIND_KEY_IN_INDEX = 3,
53 GET_IDBDATABASE_METADATA, 61 GET_IDBDATABASE_METADATA,
54 GET_INDEXES, 62 GET_INDEXES,
(...skipping 23 matching lines...) Expand all
78 std::string name; 86 std::string name;
79 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); 87 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
80 base::Histogram::FactoryGet(name, 88 base::Histogram::FactoryGet(name,
81 1, 89 1,
82 INTERNAL_ERROR_MAX, 90 INTERNAL_ERROR_MAX,
83 INTERNAL_ERROR_MAX + 1, 91 INTERNAL_ERROR_MAX + 1,
84 base::HistogramBase::kUmaTargetedHistogramFlag) 92 base::HistogramBase::kUmaTargetedHistogramFlag)
85 ->Add(location); 93 ->Add(location);
86 } 94 }
87 95
88 // Use to signal conditions that usually indicate developer error, but 96 // Use to signal conditions caused by data corruption.
89 // could be caused by data corruption. A macro is used instead of an 97 // A macro is used instead of an inline function so that the assert and log
90 // inline function so that the assert and log report the line number. 98 // report the line number.
91 #define REPORT_ERROR(type, location) \ 99 #define REPORT_ERROR(type, location) \
92 do { \ 100 do { \
93 LOG(ERROR) << "IndexedDB " type " Error: " #location; \ 101 LOG(ERROR) << "IndexedDB " type " Error: " #location; \
94 NOTREACHED(); \
95 RecordInternalError(type, location); \ 102 RecordInternalError(type, location); \
96 } while (0) 103 } while (0)
97 104
98 #define INTERNAL_READ_ERROR(location) REPORT_ERROR("Read", location) 105 #define INTERNAL_READ_ERROR(location) REPORT_ERROR("Read", location)
99 #define INTERNAL_CONSISTENCY_ERROR(location) \ 106 #define INTERNAL_CONSISTENCY_ERROR(location) \
100 REPORT_ERROR("Consistency", location) 107 REPORT_ERROR("Consistency", location)
101 #define INTERNAL_WRITE_ERROR(location) REPORT_ERROR("Write", location) 108 #define INTERNAL_WRITE_ERROR(location) REPORT_ERROR("Write", location)
102 109
110 // Use to signal conditions that usually indicate developer error, but
111 // could be caused by data corruption. A macro is used instead of an
jsbell 2014/03/26 18:16:58 Maybe add to the comment that anything that could
cmumford 2014/03/26 21:40:36 Done.
112 // inline function so that the assert and log report the line number.
113 #define REPORT_ERROR_UNTESTED(type, location) \
114 do { \
115 LOG(ERROR) << "IndexedDB " type " Error: " #location; \
116 NOTREACHED(); \
117 RecordInternalError(type, location); \
118 } while (0)
119
120 #define INTERNAL_READ_ERROR_UNTESTED(location) \
121 REPORT_ERROR_UNTESTED("Read", location)
122 #define INTERNAL_CONSISTENCY_ERROR_UNTESTED(location) \
123 REPORT_ERROR_UNTESTED("Consistency", location)
124 #define INTERNAL_WRITE_ERROR_UNTESTED(location) \
125 REPORT_ERROR_UNTESTED("Write", location)
126
103 static void PutBool(LevelDBTransaction* transaction, 127 static void PutBool(LevelDBTransaction* transaction,
104 const StringPiece& key, 128 const StringPiece& key,
105 bool value) { 129 bool value) {
106 std::string buffer; 130 std::string buffer;
107 EncodeBool(value, &buffer); 131 EncodeBool(value, &buffer);
108 transaction->Put(key, &buffer); 132 transaction->Put(key, &buffer);
109 } 133 }
110 134
111 // Was able to use LevelDB to read the data w/o error, but the data read was not 135 // Was able to use LevelDB to read the data w/o error, but the data read was not
112 // in the expected format. 136 // in the expected format.
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 const std::string data_version_key = DataVersionKey::Encode(); 294 const std::string data_version_key = DataVersionKey::Encode();
271 295
272 scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db); 296 scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db);
273 297
274 int64 db_schema_version = 0; 298 int64 db_schema_version = 0;
275 int64 db_data_version = 0; 299 int64 db_data_version = 0;
276 bool found = false; 300 bool found = false;
277 leveldb::Status s = 301 leveldb::Status s =
278 GetInt(transaction.get(), schema_version_key, &db_schema_version, &found); 302 GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
279 if (!s.ok()) { 303 if (!s.ok()) {
280 INTERNAL_READ_ERROR(SET_UP_METADATA); 304 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
281 return false; 305 return false;
282 } 306 }
283 if (!found) { 307 if (!found) {
284 // Initialize new backing store. 308 // Initialize new backing store.
285 db_schema_version = kLatestKnownSchemaVersion; 309 db_schema_version = kLatestKnownSchemaVersion;
286 PutInt(transaction.get(), schema_version_key, db_schema_version); 310 PutInt(transaction.get(), schema_version_key, db_schema_version);
287 db_data_version = latest_known_data_version; 311 db_data_version = latest_known_data_version;
288 PutInt(transaction.get(), data_version_key, db_data_version); 312 PutInt(transaction.get(), data_version_key, db_data_version);
289 } else { 313 } else {
290 // Upgrade old backing store. 314 // Upgrade old backing store.
291 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion); 315 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion);
292 if (db_schema_version < 1) { 316 if (db_schema_version < 1) {
293 db_schema_version = 1; 317 db_schema_version = 1;
294 PutInt(transaction.get(), schema_version_key, db_schema_version); 318 PutInt(transaction.get(), schema_version_key, db_schema_version);
295 const std::string start_key = 319 const std::string start_key =
296 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier); 320 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier);
297 const std::string stop_key = 321 const std::string stop_key =
298 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier); 322 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier);
299 scoped_ptr<LevelDBIterator> it = db->CreateIterator(); 323 scoped_ptr<LevelDBIterator> it = db->CreateIterator();
300 for (it->Seek(start_key); 324 for (it->Seek(start_key);
301 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 325 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
302 it->Next()) { 326 it->Next()) {
303 int64 database_id = 0; 327 int64 database_id = 0;
304 found = false; 328 found = false;
305 s = GetInt(transaction.get(), it->Key(), &database_id, &found); 329 s = GetInt(transaction.get(), it->Key(), &database_id, &found);
306 if (!s.ok()) { 330 if (!s.ok()) {
307 INTERNAL_READ_ERROR(SET_UP_METADATA); 331 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
308 return false; 332 return false;
309 } 333 }
310 if (!found) { 334 if (!found) {
311 INTERNAL_CONSISTENCY_ERROR(SET_UP_METADATA); 335 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
312 return false; 336 return false;
313 } 337 }
314 std::string int_version_key = DatabaseMetaDataKey::Encode( 338 std::string int_version_key = DatabaseMetaDataKey::Encode(
315 database_id, DatabaseMetaDataKey::USER_INT_VERSION); 339 database_id, DatabaseMetaDataKey::USER_INT_VERSION);
316 PutVarInt(transaction.get(), 340 PutVarInt(transaction.get(),
317 int_version_key, 341 int_version_key,
318 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); 342 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
319 } 343 }
320 } 344 }
321 if (db_schema_version < 2) { 345 if (db_schema_version < 2) {
322 db_schema_version = 2; 346 db_schema_version = 2;
323 PutInt(transaction.get(), schema_version_key, db_schema_version); 347 PutInt(transaction.get(), schema_version_key, db_schema_version);
324 db_data_version = blink::kSerializedScriptValueVersion; 348 db_data_version = blink::kSerializedScriptValueVersion;
325 PutInt(transaction.get(), data_version_key, db_data_version); 349 PutInt(transaction.get(), data_version_key, db_data_version);
326 } 350 }
327 } 351 }
328 352
329 // All new values will be written using this serialization version. 353 // All new values will be written using this serialization version.
330 found = false; 354 found = false;
331 s = GetInt(transaction.get(), data_version_key, &db_data_version, &found); 355 s = GetInt(transaction.get(), data_version_key, &db_data_version, &found);
332 if (!s.ok()) { 356 if (!s.ok()) {
333 INTERNAL_READ_ERROR(SET_UP_METADATA); 357 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
334 return false; 358 return false;
335 } 359 }
336 if (!found) { 360 if (!found) {
337 INTERNAL_CONSISTENCY_ERROR(SET_UP_METADATA); 361 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
338 return false; 362 return false;
339 } 363 }
340 if (db_data_version < latest_known_data_version) { 364 if (db_data_version < latest_known_data_version) {
341 db_data_version = latest_known_data_version; 365 db_data_version = latest_known_data_version;
342 PutInt(transaction.get(), data_version_key, db_data_version); 366 PutInt(transaction.get(), data_version_key, db_data_version);
343 } 367 }
344 368
345 DCHECK_EQ(db_schema_version, kLatestKnownSchemaVersion); 369 DCHECK_EQ(db_schema_version, kLatestKnownSchemaVersion);
346 DCHECK_EQ(db_data_version, latest_known_data_version); 370 DCHECK_EQ(db_data_version, latest_known_data_version);
347 371
348 s = transaction->Commit(); 372 s = transaction->Commit();
349 if (!s.ok()) { 373 if (!s.ok()) {
350 INTERNAL_WRITE_ERROR(SET_UP_METADATA); 374 INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
351 return false; 375 return false;
352 } 376 }
353 return true; 377 return true;
354 } 378 }
355 379
356 template <typename DBOrTransaction> 380 template <typename DBOrTransaction>
357 WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId( 381 WARN_UNUSED_RESULT static leveldb::Status GetMaxObjectStoreId(
358 DBOrTransaction* db, 382 DBOrTransaction* db,
359 int64 database_id, 383 int64 database_id,
360 int64* max_object_store_id) { 384 int64* max_object_store_id) {
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength", 531 "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
508 component_length, 532 component_length,
509 min, 533 min,
510 max, 534 max,
511 num_buckets); 535 num_buckets);
512 return true; 536 return true;
513 } 537 }
514 return false; 538 return false;
515 } 539 }
516 540
541 // Assumes caller has already closed the backing store.
jsbell 2014/03/26 18:16:58 Move this comment to the header file?
cmumford 2014/03/26 21:40:36 Done.
542 leveldb::Status IndexedDBBackingStore::DestroyBackingStore(
543 const base::FilePath& path_base,
544 const GURL& origin_url) {
545 const base::FilePath file_path =
546 path_base.Append(ComputeFileName(origin_url));
547 DefaultLevelDBFactory leveldb_factory;
548 return leveldb_factory.DestroyLevelDB(file_path);
549 }
550
551 bool IndexedDBBackingStore::ReadCorruptionInfo(const base::FilePath& path_base,
552 const GURL& origin_url,
553 std::string& message) {
554
555 const base::FilePath info_path =
556 path_base.Append(ComputeCorruptionFileName(origin_url));
557
558 if (IsPathTooLong(info_path))
559 return false;
560
561 const int64 max_json_len = 4096;
562 int64 file_size(0);
563 if (!GetFileSize(info_path, &file_size) || file_size > max_json_len)
564 return false;
565
566 bool created(false);
567 base::PlatformFileError error(base::PLATFORM_FILE_OK);
568 base::PlatformFile file = base::CreatePlatformFile(
569 info_path,
570 base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
571 &created,
572 &error);
573 bool success = false;
574 if (file) {
575 std::vector<char> bytes(file_size);
576 if (file_size == base::ReadPlatformFile(file, 0, &bytes[0], file_size)) {
jsbell 2014/03/26 18:16:58 &bytes[0] is undefined behavior if the vector leng
cmumford 2014/03/26 21:40:36 Done.
577 std::string input_js(&bytes[0], file_size);
578 base::JSONReader reader;
579 scoped_ptr<base::Value> val(reader.ReadToValue(input_js));
580 if (val) {
jsbell 2014/03/26 18:16:58 Add: && val->GetType() == base::Value::TYPE_DICTIO
cmumford 2014/03/26 21:40:36 Done.
581 base::DictionaryValue* dict_val =
582 static_cast<base::DictionaryValue*>(val.get());
583 success = dict_val->GetString("message", &message);
584 }
585 }
586 base::ClosePlatformFile(file);
587 }
588
589 base::DeleteFile(info_path, false);
590
591 return success;
592 }
593
594 bool IndexedDBBackingStore::RecordCorruptionInfo(
595 const base::FilePath& path_base,
596 const GURL& origin_url,
597 const IndexedDBDatabaseError& dberror) {
jsbell 2014/03/26 18:16:58 Since this only serializes the message, and since
cmumford 2014/03/26 21:40:36 OK. Either way those two functions should be symme
jsbell 2014/03/26 22:49:00 Yep - having it store all the error fields would a
598 const base::FilePath info_path =
599 path_base.Append(ComputeCorruptionFileName(origin_url));
600 if (IsPathTooLong(info_path))
601 return false;
602
603 base::DictionaryValue root_dict;
604 root_dict.SetString("message", dberror.message());
605 std::string output_js;
606 base::JSONWriter::Write(&root_dict, &output_js);
607
608 bool created(false);
609 base::PlatformFileError error(base::PLATFORM_FILE_OK);
610 base::PlatformFile file = base::CreatePlatformFile(
611 info_path,
612 base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
613 &created,
614 &error);
615 bool success = false;
616 if (file) {
jsbell 2014/03/26 18:16:58 Early exit instead, which would let you eliminate
cmumford 2014/03/26 21:40:36 Done.
617 int written =
618 base::WritePlatformFile(file, 0, output_js.c_str(), output_js.length());
619 base::ClosePlatformFile(file);
620 success = (size_t(written) == output_js.length());
621 }
622
623 return success;
624 }
625
517 // static 626 // static
518 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 627 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
519 const GURL& origin_url, 628 const GURL& origin_url,
520 const base::FilePath& path_base, 629 const base::FilePath& path_base,
521 blink::WebIDBDataLoss* data_loss, 630 blink::WebIDBDataLoss* data_loss,
522 std::string* data_loss_message, 631 std::string* data_loss_message,
523 bool* is_disk_full, 632 bool* is_disk_full,
524 LevelDBFactory* leveldb_factory) { 633 LevelDBFactory* leveldb_factory) {
525 IDB_TRACE("IndexedDBBackingStore::Open"); 634 IDB_TRACE("IndexedDBBackingStore::Open");
526 DCHECK(!path_base.empty()); 635 DCHECK(!path_base.empty());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 if (leveldb_env::IndicatesDiskFull(status)) { 669 if (leveldb_env::IndicatesDiskFull(status)) {
561 *is_disk_full = true; 670 *is_disk_full = true;
562 } else if (leveldb_env::IsCorruption(status)) { 671 } else if (leveldb_env::IsCorruption(status)) {
563 *data_loss = blink::WebIDBDataLossTotal; 672 *data_loss = blink::WebIDBDataLossTotal;
564 *data_loss_message = leveldb_env::GetCorruptionMessage(status); 673 *data_loss_message = leveldb_env::GetCorruptionMessage(status);
565 } 674 }
566 } 675 }
567 676
568 bool is_schema_known = false; 677 bool is_schema_known = false;
569 if (db) { 678 if (db) {
570 bool ok = IsSchemaKnown(db.get(), &is_schema_known); 679 std::string corruption_message;
571 if (!ok) { 680 if (ReadCorruptionInfo(path_base, origin_url, corruption_message)) {
572 LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as " 681 LOG(ERROR) << "IndexedDB recovering from a corrupted (and deleted) "
573 "failure to open"; 682 "database.";
574 HistogramOpenStatus( 683 HistogramOpenStatus(
575 INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA, 684 INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
jsbell 2014/03/26 18:16:58 Add a new histogram value?
cmumford 2014/03/26 21:40:36 Done.
576 origin_url); 685 origin_url);
577 db.reset(); 686 db.reset();
578 *data_loss = blink::WebIDBDataLossTotal; 687 *data_loss = blink::WebIDBDataLossTotal;
579 *data_loss_message = "I/O error checking schema"; 688 *data_loss_message =
580 } else if (!is_schema_known) { 689 "IndexedDB (database was corrupt): " + corruption_message;
581 LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it " 690 } else {
582 "as failure to open"; 691 bool ok = IsSchemaKnown(db.get(), &is_schema_known);
jsbell 2014/03/26 18:16:58 Merge this into the else i.e. "else if (IsSchemaKn
583 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA, 692 if (!ok) {
584 origin_url); 693 LOG(ERROR) << "IndexedDB had IO error checking schema, treating it as "
585 db.reset(); 694 "failure to open";
586 *data_loss = blink::WebIDBDataLossTotal; 695 HistogramOpenStatus(
587 *data_loss_message = "Unknown schema"; 696 INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
697 origin_url);
698 db.reset();
699 *data_loss = blink::WebIDBDataLossTotal;
700 *data_loss_message = "I/O error checking schema";
701 } else if (!is_schema_known) {
702 LOG(ERROR) << "IndexedDB backing store had unknown schema, treating it "
703 "as failure to open";
704 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_SCHEMA,
705 origin_url);
706 db.reset();
707 *data_loss = blink::WebIDBDataLossTotal;
708 *data_loss_message = "Unknown schema";
709 }
588 } 710 }
589 } 711 }
590 712
591 DCHECK(status.ok() || !is_schema_known || leveldb_env::IsIOError(status) || 713 DCHECK(status.ok() || !is_schema_known || leveldb_env::IsIOError(status) ||
592 leveldb_env::IsCorruption(status)); 714 leveldb_env::IsCorruption(status));
593 715
594 if (db) { 716 if (db) {
595 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url); 717 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_SUCCESS, origin_url);
596 } else if (leveldb_env::IsIOError(status)) { 718 } else if (leveldb_env::IsIOError(status)) {
597 LOG(ERROR) << "Unable to open backing store, not trying to recover - " 719 LOG(ERROR) << "Unable to open backing store, not trying to recover - "
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
683 805
684 DCHECK(found_names.empty()); 806 DCHECK(found_names.empty());
685 807
686 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 808 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
687 for (it->Seek(start_key); 809 for (it->Seek(start_key);
688 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 810 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
689 it->Next()) { 811 it->Next()) {
690 StringPiece slice(it->Key()); 812 StringPiece slice(it->Key());
691 DatabaseNameKey database_name_key; 813 DatabaseNameKey database_name_key;
692 if (!DatabaseNameKey::Decode(&slice, &database_name_key)) { 814 if (!DatabaseNameKey::Decode(&slice, &database_name_key)) {
693 INTERNAL_CONSISTENCY_ERROR(GET_DATABASE_NAMES); 815 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_DATABASE_NAMES);
694 continue; 816 continue;
695 } 817 }
696 found_names.push_back(database_name_key.database_name()); 818 found_names.push_back(database_name_key.database_name());
697 } 819 }
698 return found_names; 820 return found_names;
699 } 821 }
700 822
701 leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData( 823 leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData(
702 const base::string16& name, 824 const base::string16& name,
703 IndexedDBDatabaseMetadata* metadata, 825 IndexedDBDatabaseMetadata* metadata,
704 bool* found) { 826 bool* found) {
705 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); 827 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
706 *found = false; 828 *found = false;
707 829
708 leveldb::Status s = GetInt(db_.get(), key, &metadata->id, found); 830 leveldb::Status s = GetInt(db_.get(), key, &metadata->id, found);
709 if (!s.ok()) { 831 if (!s.ok()) {
710 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); 832 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
711 return s; 833 return s;
712 } 834 }
713 if (!*found) 835 if (!*found)
714 return leveldb::Status::OK(); 836 return leveldb::Status::OK();
715 837
716 s = GetString(db_.get(), 838 s = GetString(db_.get(),
717 DatabaseMetaDataKey::Encode(metadata->id, 839 DatabaseMetaDataKey::Encode(metadata->id,
718 DatabaseMetaDataKey::USER_VERSION), 840 DatabaseMetaDataKey::USER_VERSION),
719 &metadata->version, 841 &metadata->version,
720 found); 842 found);
721 if (!s.ok()) { 843 if (!s.ok()) {
722 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); 844 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
723 return s; 845 return s;
724 } 846 }
725 if (!*found) { 847 if (!*found) {
726 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA); 848 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
727 return InternalInconsistencyStatus(); 849 return InternalInconsistencyStatus();
728 } 850 }
729 851
730 s = GetVarInt(db_.get(), 852 s = GetVarInt(db_.get(),
731 DatabaseMetaDataKey::Encode( 853 DatabaseMetaDataKey::Encode(
732 metadata->id, DatabaseMetaDataKey::USER_INT_VERSION), 854 metadata->id, DatabaseMetaDataKey::USER_INT_VERSION),
733 &metadata->int_version, 855 &metadata->int_version,
734 found); 856 found);
735 if (!s.ok()) { 857 if (!s.ok()) {
736 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); 858 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
737 return s; 859 return s;
738 } 860 }
739 if (!*found) { 861 if (!*found) {
740 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA); 862 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
741 return InternalInconsistencyStatus(); 863 return InternalInconsistencyStatus();
742 } 864 }
743 865
744 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) 866 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
745 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; 867 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
746 868
747 s = GetMaxObjectStoreId( 869 s = GetMaxObjectStoreId(
748 db_.get(), metadata->id, &metadata->max_object_store_id); 870 db_.get(), metadata->id, &metadata->max_object_store_id);
749 if (!s.ok()) { 871 if (!s.ok()) {
750 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); 872 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
751 } 873 }
752 874
753 return s; 875 return s;
754 } 876 }
755 877
756 WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId( 878 WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId(
757 LevelDBTransaction* transaction, 879 LevelDBTransaction* transaction,
758 int64* new_id) { 880 int64* new_id) {
759 *new_id = -1; 881 *new_id = -1;
760 int64 max_database_id = -1; 882 int64 max_database_id = -1;
761 bool found = false; 883 bool found = false;
762 leveldb::Status s = 884 leveldb::Status s =
763 GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found); 885 GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found);
764 if (!s.ok()) { 886 if (!s.ok()) {
765 INTERNAL_READ_ERROR(GET_NEW_DATABASE_ID); 887 INTERNAL_READ_ERROR_UNTESTED(GET_NEW_DATABASE_ID);
766 return s; 888 return s;
767 } 889 }
768 if (!found) 890 if (!found)
769 max_database_id = 0; 891 max_database_id = 0;
770 892
771 DCHECK_GE(max_database_id, 0); 893 DCHECK_GE(max_database_id, 0);
772 894
773 int64 database_id = max_database_id + 1; 895 int64 database_id = max_database_id + 1;
774 PutInt(transaction, MaxDatabaseIdKey::Encode(), database_id); 896 PutInt(transaction, MaxDatabaseIdKey::Encode(), database_id);
775 *new_id = database_id; 897 *new_id = database_id;
(...skipping 22 matching lines...) Expand all
798 PutString( 920 PutString(
799 transaction.get(), 921 transaction.get(),
800 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION), 922 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
801 version); 923 version);
802 PutVarInt(transaction.get(), 924 PutVarInt(transaction.get(),
803 DatabaseMetaDataKey::Encode(*row_id, 925 DatabaseMetaDataKey::Encode(*row_id,
804 DatabaseMetaDataKey::USER_INT_VERSION), 926 DatabaseMetaDataKey::USER_INT_VERSION),
805 int_version); 927 int_version);
806 s = transaction->Commit(); 928 s = transaction->Commit();
807 if (!s.ok()) 929 if (!s.ok())
808 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA); 930 INTERNAL_WRITE_ERROR_UNTESTED(CREATE_IDBDATABASE_METADATA);
809 return s; 931 return s;
810 } 932 }
811 933
812 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion( 934 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
813 IndexedDBBackingStore::Transaction* transaction, 935 IndexedDBBackingStore::Transaction* transaction,
814 int64 row_id, 936 int64 row_id,
815 int64 int_version) { 937 int64 int_version) {
816 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) 938 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
817 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; 939 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
818 DCHECK_GE(int_version, 0) << "int_version was " << int_version; 940 DCHECK_GE(int_version, 0) << "int_version was " << int_version;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 for (it->Seek(start_key); 976 for (it->Seek(start_key);
855 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 977 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
856 it->Next()) 978 it->Next())
857 transaction->Remove(it->Key()); 979 transaction->Remove(it->Key());
858 980
859 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); 981 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
860 transaction->Remove(key); 982 transaction->Remove(key);
861 983
862 s = transaction->Commit(); 984 s = transaction->Commit();
863 if (!s.ok()) { 985 if (!s.ok()) {
864 INTERNAL_WRITE_ERROR(DELETE_DATABASE); 986 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
865 return s; 987 return s;
866 } 988 }
867 db_->Compact(start_key, stop_key); 989 db_->Compact(start_key, stop_key);
868 return s; 990 return s;
869 } 991 }
870 992
871 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, 993 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
872 const std::string& stop_key, 994 const std::string& stop_key,
873 int64 object_store_id, 995 int64 object_store_id,
874 int64 meta_data_type) { 996 int64 meta_data_type) {
(...skipping 27 matching lines...) Expand all
902 DCHECK(object_stores->empty()); 1024 DCHECK(object_stores->empty());
903 1025
904 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1026 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
905 it->Seek(start_key); 1027 it->Seek(start_key);
906 while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { 1028 while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
907 StringPiece slice(it->Key()); 1029 StringPiece slice(it->Key());
908 ObjectStoreMetaDataKey meta_data_key; 1030 ObjectStoreMetaDataKey meta_data_key;
909 bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key); 1031 bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key);
910 DCHECK(ok); 1032 DCHECK(ok);
911 if (meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) { 1033 if (meta_data_key.MetaDataType() != ObjectStoreMetaDataKey::NAME) {
912 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1034 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
913 // Possible stale metadata, but don't fail the load. 1035 // Possible stale metadata, but don't fail the load.
914 it->Next(); 1036 it->Next();
915 continue; 1037 continue;
916 } 1038 }
917 1039
918 int64 object_store_id = meta_data_key.ObjectStoreId(); 1040 int64 object_store_id = meta_data_key.ObjectStoreId();
919 1041
920 // TODO(jsbell): Do this by direct key lookup rather than iteration, to 1042 // TODO(jsbell): Do this by direct key lookup rather than iteration, to
921 // simplify. 1043 // simplify.
922 base::string16 object_store_name; 1044 base::string16 object_store_name;
923 { 1045 {
924 StringPiece slice(it->Value()); 1046 StringPiece slice(it->Value());
925 if (!DecodeString(&slice, &object_store_name) || !slice.empty()) 1047 if (!DecodeString(&slice, &object_store_name) || !slice.empty())
926 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1048 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
927 } 1049 }
928 1050
929 it->Next(); 1051 it->Next();
930 if (!CheckObjectStoreAndMetaDataType(it.get(), 1052 if (!CheckObjectStoreAndMetaDataType(it.get(),
931 stop_key, 1053 stop_key,
932 object_store_id, 1054 object_store_id,
933 ObjectStoreMetaDataKey::KEY_PATH)) { 1055 ObjectStoreMetaDataKey::KEY_PATH)) {
934 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1056 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
935 break; 1057 break;
936 } 1058 }
937 IndexedDBKeyPath key_path; 1059 IndexedDBKeyPath key_path;
938 { 1060 {
939 StringPiece slice(it->Value()); 1061 StringPiece slice(it->Value());
940 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) 1062 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
941 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1063 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
942 } 1064 }
943 1065
944 it->Next(); 1066 it->Next();
945 if (!CheckObjectStoreAndMetaDataType( 1067 if (!CheckObjectStoreAndMetaDataType(
946 it.get(), 1068 it.get(),
947 stop_key, 1069 stop_key,
948 object_store_id, 1070 object_store_id,
949 ObjectStoreMetaDataKey::AUTO_INCREMENT)) { 1071 ObjectStoreMetaDataKey::AUTO_INCREMENT)) {
950 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1072 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
951 break; 1073 break;
952 } 1074 }
953 bool auto_increment; 1075 bool auto_increment;
954 { 1076 {
955 StringPiece slice(it->Value()); 1077 StringPiece slice(it->Value());
956 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) 1078 if (!DecodeBool(&slice, &auto_increment) || !slice.empty())
957 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1079 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
958 } 1080 }
959 1081
960 it->Next(); // Is evicatble. 1082 it->Next(); // Is evicatble.
961 if (!CheckObjectStoreAndMetaDataType(it.get(), 1083 if (!CheckObjectStoreAndMetaDataType(it.get(),
962 stop_key, 1084 stop_key,
963 object_store_id, 1085 object_store_id,
964 ObjectStoreMetaDataKey::EVICTABLE)) { 1086 ObjectStoreMetaDataKey::EVICTABLE)) {
965 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1087 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
966 break; 1088 break;
967 } 1089 }
968 1090
969 it->Next(); // Last version. 1091 it->Next(); // Last version.
970 if (!CheckObjectStoreAndMetaDataType( 1092 if (!CheckObjectStoreAndMetaDataType(
971 it.get(), 1093 it.get(),
972 stop_key, 1094 stop_key,
973 object_store_id, 1095 object_store_id,
974 ObjectStoreMetaDataKey::LAST_VERSION)) { 1096 ObjectStoreMetaDataKey::LAST_VERSION)) {
975 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1097 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
976 break; 1098 break;
977 } 1099 }
978 1100
979 it->Next(); // Maximum index id allocated. 1101 it->Next(); // Maximum index id allocated.
980 if (!CheckObjectStoreAndMetaDataType( 1102 if (!CheckObjectStoreAndMetaDataType(
981 it.get(), 1103 it.get(),
982 stop_key, 1104 stop_key,
983 object_store_id, 1105 object_store_id,
984 ObjectStoreMetaDataKey::MAX_INDEX_ID)) { 1106 ObjectStoreMetaDataKey::MAX_INDEX_ID)) {
985 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1107 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
986 break; 1108 break;
987 } 1109 }
988 int64 max_index_id; 1110 int64 max_index_id;
989 { 1111 {
990 StringPiece slice(it->Value()); 1112 StringPiece slice(it->Value());
991 if (!DecodeInt(&slice, &max_index_id) || !slice.empty()) 1113 if (!DecodeInt(&slice, &max_index_id) || !slice.empty())
992 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1114 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
993 } 1115 }
994 1116
995 it->Next(); // [optional] has key path (is not null) 1117 it->Next(); // [optional] has key path (is not null)
996 if (CheckObjectStoreAndMetaDataType(it.get(), 1118 if (CheckObjectStoreAndMetaDataType(it.get(),
997 stop_key, 1119 stop_key,
998 object_store_id, 1120 object_store_id,
999 ObjectStoreMetaDataKey::HAS_KEY_PATH)) { 1121 ObjectStoreMetaDataKey::HAS_KEY_PATH)) {
1000 bool has_key_path; 1122 bool has_key_path;
1001 { 1123 {
1002 StringPiece slice(it->Value()); 1124 StringPiece slice(it->Value());
1003 if (!DecodeBool(&slice, &has_key_path)) 1125 if (!DecodeBool(&slice, &has_key_path))
1004 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1126 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1005 } 1127 }
1006 // This check accounts for two layers of legacy coding: 1128 // This check accounts for two layers of legacy coding:
1007 // (1) Initially, has_key_path was added to distinguish null vs. string. 1129 // (1) Initially, has_key_path was added to distinguish null vs. string.
1008 // (2) Later, null vs. string vs. array was stored in the key_path itself. 1130 // (2) Later, null vs. string vs. array was stored in the key_path itself.
1009 // So this check is only relevant for string-type key_paths. 1131 // So this check is only relevant for string-type key_paths.
1010 if (!has_key_path && 1132 if (!has_key_path &&
1011 (key_path.type() == blink::WebIDBKeyPathTypeString && 1133 (key_path.type() == blink::WebIDBKeyPathTypeString &&
1012 !key_path.string().empty())) { 1134 !key_path.string().empty())) {
1013 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1135 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1014 break; 1136 break;
1015 } 1137 }
1016 if (!has_key_path) 1138 if (!has_key_path)
1017 key_path = IndexedDBKeyPath(); 1139 key_path = IndexedDBKeyPath();
1018 it->Next(); 1140 it->Next();
1019 } 1141 }
1020 1142
1021 int64 key_generator_current_number = -1; 1143 int64 key_generator_current_number = -1;
1022 if (CheckObjectStoreAndMetaDataType( 1144 if (CheckObjectStoreAndMetaDataType(
1023 it.get(), 1145 it.get(),
1024 stop_key, 1146 stop_key,
1025 object_store_id, 1147 object_store_id,
1026 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) { 1148 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER)) {
1027 StringPiece slice(it->Value()); 1149 StringPiece slice(it->Value());
1028 if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty()) 1150 if (!DecodeInt(&slice, &key_generator_current_number) || !slice.empty())
1029 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1151 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_OBJECT_STORES);
1030 1152
1031 // TODO(jsbell): Return key_generator_current_number, cache in 1153 // TODO(jsbell): Return key_generator_current_number, cache in
1032 // object store, and write lazily to backing store. For now, 1154 // object store, and write lazily to backing store. For now,
1033 // just assert that if it was written it was valid. 1155 // just assert that if it was written it was valid.
1034 DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber); 1156 DCHECK_GE(key_generator_current_number, kKeyGeneratorInitialNumber);
1035 it->Next(); 1157 it->Next();
1036 } 1158 }
1037 1159
1038 IndexedDBObjectStoreMetadata metadata(object_store_name, 1160 IndexedDBObjectStoreMetadata metadata(object_store_name,
1039 object_store_id, 1161 object_store_id,
(...skipping 12 matching lines...) Expand all
1052 WARN_UNUSED_RESULT static leveldb::Status SetMaxObjectStoreId( 1174 WARN_UNUSED_RESULT static leveldb::Status SetMaxObjectStoreId(
1053 LevelDBTransaction* transaction, 1175 LevelDBTransaction* transaction,
1054 int64 database_id, 1176 int64 database_id,
1055 int64 object_store_id) { 1177 int64 object_store_id) {
1056 const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode( 1178 const std::string max_object_store_id_key = DatabaseMetaDataKey::Encode(
1057 database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID); 1179 database_id, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID);
1058 int64 max_object_store_id = -1; 1180 int64 max_object_store_id = -1;
1059 leveldb::Status s = GetMaxObjectStoreId( 1181 leveldb::Status s = GetMaxObjectStoreId(
1060 transaction, max_object_store_id_key, &max_object_store_id); 1182 transaction, max_object_store_id_key, &max_object_store_id);
1061 if (!s.ok()) { 1183 if (!s.ok()) {
1062 INTERNAL_READ_ERROR(SET_MAX_OBJECT_STORE_ID); 1184 INTERNAL_READ_ERROR_UNTESTED(SET_MAX_OBJECT_STORE_ID);
1063 return s; 1185 return s;
1064 } 1186 }
1065 1187
1066 if (object_store_id <= max_object_store_id) { 1188 if (object_store_id <= max_object_store_id) {
1067 INTERNAL_CONSISTENCY_ERROR(SET_MAX_OBJECT_STORE_ID); 1189 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_MAX_OBJECT_STORE_ID);
1068 return InternalInconsistencyStatus(); 1190 return InternalInconsistencyStatus();
1069 } 1191 }
1070 PutInt(transaction, max_object_store_id_key, object_store_id); 1192 PutInt(transaction, max_object_store_id_key, object_store_id);
1071 return s; 1193 return s;
1072 } 1194 }
1073 1195
1196 void IndexedDBBackingStore::Flush() { db_->CompactAll(); }
1197
1074 leveldb::Status IndexedDBBackingStore::CreateObjectStore( 1198 leveldb::Status IndexedDBBackingStore::CreateObjectStore(
1075 IndexedDBBackingStore::Transaction* transaction, 1199 IndexedDBBackingStore::Transaction* transaction,
1076 int64 database_id, 1200 int64 database_id,
1077 int64 object_store_id, 1201 int64 object_store_id,
1078 const base::string16& name, 1202 const base::string16& name,
1079 const IndexedDBKeyPath& key_path, 1203 const IndexedDBKeyPath& key_path,
1080 bool auto_increment) { 1204 bool auto_increment) {
1081 IDB_TRACE("IndexedDBBackingStore::CreateObjectStore"); 1205 IDB_TRACE("IndexedDBBackingStore::CreateObjectStore");
1082 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1206 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1083 return InvalidDBKeyStatus(); 1207 return InvalidDBKeyStatus();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 1257
1134 base::string16 object_store_name; 1258 base::string16 object_store_name;
1135 bool found = false; 1259 bool found = false;
1136 leveldb::Status s = 1260 leveldb::Status s =
1137 GetString(leveldb_transaction, 1261 GetString(leveldb_transaction,
1138 ObjectStoreMetaDataKey::Encode( 1262 ObjectStoreMetaDataKey::Encode(
1139 database_id, object_store_id, ObjectStoreMetaDataKey::NAME), 1263 database_id, object_store_id, ObjectStoreMetaDataKey::NAME),
1140 &object_store_name, 1264 &object_store_name,
1141 &found); 1265 &found);
1142 if (!s.ok()) { 1266 if (!s.ok()) {
1143 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE); 1267 INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1144 return s; 1268 return s;
1145 } 1269 }
1146 if (!found) { 1270 if (!found) {
1147 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE); 1271 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1148 return InternalInconsistencyStatus(); 1272 return InternalInconsistencyStatus();
1149 } 1273 }
1150 1274
1151 DeleteRange( 1275 DeleteRange(
1152 leveldb_transaction, 1276 leveldb_transaction,
1153 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), 1277 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
1154 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1278 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id));
1155 1279
1156 leveldb_transaction->Remove( 1280 leveldb_transaction->Remove(
1157 ObjectStoreNamesKey::Encode(database_id, object_store_name)); 1281 ObjectStoreNamesKey::Encode(database_id, object_store_name));
(...skipping 27 matching lines...) Expand all
1185 1309
1186 bool found = false; 1310 bool found = false;
1187 leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found); 1311 leveldb::Status s = leveldb_transaction->Get(leveldb_key, &data, &found);
1188 if (!s.ok()) { 1312 if (!s.ok()) {
1189 INTERNAL_READ_ERROR(GET_RECORD); 1313 INTERNAL_READ_ERROR(GET_RECORD);
1190 return s; 1314 return s;
1191 } 1315 }
1192 if (!found) 1316 if (!found)
1193 return s; 1317 return s;
1194 if (data.empty()) { 1318 if (data.empty()) {
1195 INTERNAL_READ_ERROR(GET_RECORD); 1319 INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
1196 return leveldb::Status::NotFound("Record contained no data"); 1320 return leveldb::Status::NotFound("Record contained no data");
1197 } 1321 }
1198 1322
1199 int64 version; 1323 int64 version;
1200 StringPiece slice(data); 1324 StringPiece slice(data);
1201 if (!DecodeVarInt(&slice, &version)) { 1325 if (!DecodeVarInt(&slice, &version)) {
1202 INTERNAL_READ_ERROR(GET_RECORD); 1326 INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
1203 return InternalInconsistencyStatus(); 1327 return InternalInconsistencyStatus();
1204 } 1328 }
1205 1329
1206 record->bits = slice.as_string(); 1330 record->bits = slice.as_string();
1207 return s; 1331 return s;
1208 } 1332 }
1209 1333
1210 WARN_UNUSED_RESULT static leveldb::Status GetNewVersionNumber( 1334 WARN_UNUSED_RESULT static leveldb::Status GetNewVersionNumber(
1211 LevelDBTransaction* transaction, 1335 LevelDBTransaction* transaction,
1212 int64 database_id, 1336 int64 database_id,
1213 int64 object_store_id, 1337 int64 object_store_id,
1214 int64* new_version_number) { 1338 int64* new_version_number) {
1215 const std::string last_version_key = ObjectStoreMetaDataKey::Encode( 1339 const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
1216 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); 1340 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
1217 1341
1218 *new_version_number = -1; 1342 *new_version_number = -1;
1219 int64 last_version = -1; 1343 int64 last_version = -1;
1220 bool found = false; 1344 bool found = false;
1221 leveldb::Status s = 1345 leveldb::Status s =
1222 GetInt(transaction, last_version_key, &last_version, &found); 1346 GetInt(transaction, last_version_key, &last_version, &found);
1223 if (!s.ok()) { 1347 if (!s.ok()) {
1224 INTERNAL_READ_ERROR(GET_NEW_VERSION_NUMBER); 1348 INTERNAL_READ_ERROR_UNTESTED(GET_NEW_VERSION_NUMBER);
1225 return s; 1349 return s;
1226 } 1350 }
1227 if (!found) 1351 if (!found)
1228 last_version = 0; 1352 last_version = 0;
1229 1353
1230 DCHECK_GE(last_version, 0); 1354 DCHECK_GE(last_version, 0);
1231 1355
1232 int64 version = last_version + 1; 1356 int64 version = last_version + 1;
1233 PutInt(transaction, last_version_key, version); 1357 PutInt(transaction, last_version_key, version);
1234 1358
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 object_store_id, 1454 object_store_id,
1331 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER); 1455 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
1332 1456
1333 *key_generator_current_number = -1; 1457 *key_generator_current_number = -1;
1334 std::string data; 1458 std::string data;
1335 1459
1336 bool found = false; 1460 bool found = false;
1337 leveldb::Status s = 1461 leveldb::Status s =
1338 leveldb_transaction->Get(key_generator_current_number_key, &data, &found); 1462 leveldb_transaction->Get(key_generator_current_number_key, &data, &found);
1339 if (!s.ok()) { 1463 if (!s.ok()) {
1340 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); 1464 INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
1341 return s; 1465 return s;
1342 } 1466 }
1343 if (found && !data.empty()) { 1467 if (found && !data.empty()) {
1344 StringPiece slice(data); 1468 StringPiece slice(data);
1345 if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) { 1469 if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) {
1346 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); 1470 INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
1347 return InternalInconsistencyStatus(); 1471 return InternalInconsistencyStatus();
1348 } 1472 }
1349 return s; 1473 return s;
1350 } 1474 }
1351 1475
1352 // Previously, the key generator state was not stored explicitly 1476 // Previously, the key generator state was not stored explicitly
1353 // but derived from the maximum numeric key present in existing 1477 // but derived from the maximum numeric key present in existing
1354 // data. This violates the spec as the data may be cleared but the 1478 // data. This violates the spec as the data may be cleared but the
1355 // key generator state must be preserved. 1479 // key generator state must be preserved.
1356 // TODO(jsbell): Fix this for all stores on database open? 1480 // TODO(jsbell): Fix this for all stores on database open?
1357 const std::string start_key = 1481 const std::string start_key =
1358 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); 1482 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
1359 const std::string stop_key = 1483 const std::string stop_key =
1360 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); 1484 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
1361 1485
1362 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); 1486 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
1363 int64 max_numeric_key = 0; 1487 int64 max_numeric_key = 0;
1364 1488
1365 for (it->Seek(start_key); 1489 for (it->Seek(start_key);
1366 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 1490 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
1367 it->Next()) { 1491 it->Next()) {
1368 StringPiece slice(it->Key()); 1492 StringPiece slice(it->Key());
1369 ObjectStoreDataKey data_key; 1493 ObjectStoreDataKey data_key;
1370 if (!ObjectStoreDataKey::Decode(&slice, &data_key)) { 1494 if (!ObjectStoreDataKey::Decode(&slice, &data_key)) {
1371 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); 1495 INTERNAL_READ_ERROR_UNTESTED(GET_KEY_GENERATOR_CURRENT_NUMBER);
1372 return InternalInconsistencyStatus(); 1496 return InternalInconsistencyStatus();
1373 } 1497 }
1374 scoped_ptr<IndexedDBKey> user_key = data_key.user_key(); 1498 scoped_ptr<IndexedDBKey> user_key = data_key.user_key();
1375 if (user_key->type() == blink::WebIDBKeyTypeNumber) { 1499 if (user_key->type() == blink::WebIDBKeyTypeNumber) {
1376 int64 n = static_cast<int64>(user_key->number()); 1500 int64 n = static_cast<int64>(user_key->number());
1377 if (n > max_numeric_key) 1501 if (n > max_numeric_key)
1378 max_numeric_key = n; 1502 max_numeric_key = n;
1379 } 1503 }
1380 } 1504 }
1381 1505
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1423 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1547 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1424 return InvalidDBKeyStatus(); 1548 return InvalidDBKeyStatus();
1425 *found = false; 1549 *found = false;
1426 const std::string leveldb_key = 1550 const std::string leveldb_key =
1427 ObjectStoreDataKey::Encode(database_id, object_store_id, key); 1551 ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1428 std::string data; 1552 std::string data;
1429 1553
1430 leveldb::Status s = 1554 leveldb::Status s =
1431 transaction->transaction()->Get(leveldb_key, &data, found); 1555 transaction->transaction()->Get(leveldb_key, &data, found);
1432 if (!s.ok()) { 1556 if (!s.ok()) {
1433 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); 1557 INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_OBJECT_STORE);
1434 return s; 1558 return s;
1435 } 1559 }
1436 if (!*found) 1560 if (!*found)
1437 return leveldb::Status::OK(); 1561 return leveldb::Status::OK();
1438 if (!data.size()) { 1562 if (!data.size()) {
1439 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE); 1563 INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_OBJECT_STORE);
1440 return InternalInconsistencyStatus(); 1564 return InternalInconsistencyStatus();
1441 } 1565 }
1442 1566
1443 int64 version; 1567 int64 version;
1444 StringPiece slice(data); 1568 StringPiece slice(data);
1445 if (!DecodeVarInt(&slice, &version)) 1569 if (!DecodeVarInt(&slice, &version))
1446 return InternalInconsistencyStatus(); 1570 return InternalInconsistencyStatus();
1447 1571
1448 std::string encoded_key; 1572 std::string encoded_key;
1449 EncodeIDBKey(key, &encoded_key); 1573 EncodeIDBKey(key, &encoded_key);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1486 DCHECK(indexes->empty()); 1610 DCHECK(indexes->empty());
1487 1611
1488 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1612 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
1489 it->Seek(start_key); 1613 it->Seek(start_key);
1490 while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) { 1614 while (it->IsValid() && CompareKeys(it->Key(), stop_key) < 0) {
1491 StringPiece slice(it->Key()); 1615 StringPiece slice(it->Key());
1492 IndexMetaDataKey meta_data_key; 1616 IndexMetaDataKey meta_data_key;
1493 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 1617 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
1494 DCHECK(ok); 1618 DCHECK(ok);
1495 if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) { 1619 if (meta_data_key.meta_data_type() != IndexMetaDataKey::NAME) {
1496 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1620 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1497 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail 1621 // Possible stale metadata due to http://webkit.org/b/85557 but don't fail
1498 // the load. 1622 // the load.
1499 it->Next(); 1623 it->Next();
1500 continue; 1624 continue;
1501 } 1625 }
1502 1626
1503 // TODO(jsbell): Do this by direct key lookup rather than iteration, to 1627 // TODO(jsbell): Do this by direct key lookup rather than iteration, to
1504 // simplify. 1628 // simplify.
1505 int64 index_id = meta_data_key.IndexId(); 1629 int64 index_id = meta_data_key.IndexId();
1506 base::string16 index_name; 1630 base::string16 index_name;
1507 { 1631 {
1508 StringPiece slice(it->Value()); 1632 StringPiece slice(it->Value());
1509 if (!DecodeString(&slice, &index_name) || !slice.empty()) 1633 if (!DecodeString(&slice, &index_name) || !slice.empty())
1510 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1634 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1511 } 1635 }
1512 1636
1513 it->Next(); // unique flag 1637 it->Next(); // unique flag
1514 if (!CheckIndexAndMetaDataKey( 1638 if (!CheckIndexAndMetaDataKey(
1515 it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) { 1639 it.get(), stop_key, index_id, IndexMetaDataKey::UNIQUE)) {
1516 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1640 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1517 break; 1641 break;
1518 } 1642 }
1519 bool index_unique; 1643 bool index_unique;
1520 { 1644 {
1521 StringPiece slice(it->Value()); 1645 StringPiece slice(it->Value());
1522 if (!DecodeBool(&slice, &index_unique) || !slice.empty()) 1646 if (!DecodeBool(&slice, &index_unique) || !slice.empty())
1523 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1647 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1524 } 1648 }
1525 1649
1526 it->Next(); // key_path 1650 it->Next(); // key_path
1527 if (!CheckIndexAndMetaDataKey( 1651 if (!CheckIndexAndMetaDataKey(
1528 it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) { 1652 it.get(), stop_key, index_id, IndexMetaDataKey::KEY_PATH)) {
1529 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1653 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1530 break; 1654 break;
1531 } 1655 }
1532 IndexedDBKeyPath key_path; 1656 IndexedDBKeyPath key_path;
1533 { 1657 {
1534 StringPiece slice(it->Value()); 1658 StringPiece slice(it->Value());
1535 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty()) 1659 if (!DecodeIDBKeyPath(&slice, &key_path) || !slice.empty())
1536 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1660 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1537 } 1661 }
1538 1662
1539 it->Next(); // [optional] multi_entry flag 1663 it->Next(); // [optional] multi_entry flag
1540 bool index_multi_entry = false; 1664 bool index_multi_entry = false;
1541 if (CheckIndexAndMetaDataKey( 1665 if (CheckIndexAndMetaDataKey(
1542 it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) { 1666 it.get(), stop_key, index_id, IndexMetaDataKey::MULTI_ENTRY)) {
1543 StringPiece slice(it->Value()); 1667 StringPiece slice(it->Value());
1544 if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty()) 1668 if (!DecodeBool(&slice, &index_multi_entry) || !slice.empty())
1545 INTERNAL_CONSISTENCY_ERROR(GET_INDEXES); 1669 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_INDEXES);
1546 1670
1547 it->Next(); 1671 it->Next();
1548 } 1672 }
1549 1673
1550 (*indexes)[index_id] = IndexedDBIndexMetadata( 1674 (*indexes)[index_id] = IndexedDBIndexMetadata(
1551 index_name, index_id, key_path, index_unique, index_multi_entry); 1675 index_name, index_id, key_path, index_unique, index_multi_entry);
1552 } 1676 }
1553 return leveldb::Status::OK(); 1677 return leveldb::Status::OK();
1554 } 1678 }
1555 1679
1556 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( 1680 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
1557 LevelDBTransaction* transaction, 1681 LevelDBTransaction* transaction,
1558 int64 database_id, 1682 int64 database_id,
1559 int64 object_store_id, 1683 int64 object_store_id,
1560 int64 index_id) { 1684 int64 index_id) {
1561 int64 max_index_id = -1; 1685 int64 max_index_id = -1;
1562 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 1686 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1563 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 1687 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1564 bool found = false; 1688 bool found = false;
1565 leveldb::Status s = 1689 leveldb::Status s =
1566 GetInt(transaction, max_index_id_key, &max_index_id, &found); 1690 GetInt(transaction, max_index_id_key, &max_index_id, &found);
1567 if (!s.ok()) { 1691 if (!s.ok()) {
1568 INTERNAL_READ_ERROR(SET_MAX_INDEX_ID); 1692 INTERNAL_READ_ERROR_UNTESTED(SET_MAX_INDEX_ID);
1569 return s; 1693 return s;
1570 } 1694 }
1571 if (!found) 1695 if (!found)
1572 max_index_id = kMinimumIndexId; 1696 max_index_id = kMinimumIndexId;
1573 1697
1574 if (index_id <= max_index_id) { 1698 if (index_id <= max_index_id) {
1575 INTERNAL_CONSISTENCY_ERROR(SET_MAX_INDEX_ID); 1699 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_MAX_INDEX_ID);
1576 return InternalInconsistencyStatus(); 1700 return InternalInconsistencyStatus();
1577 } 1701 }
1578 1702
1579 PutInt(transaction, max_index_id_key, index_id); 1703 PutInt(transaction, max_index_id_key, index_id);
1580 return s; 1704 return s;
1581 } 1705 }
1582 1706
1583 leveldb::Status IndexedDBBackingStore::CreateIndex( 1707 leveldb::Status IndexedDBBackingStore::CreateIndex(
1584 IndexedDBBackingStore::Transaction* transaction, 1708 IndexedDBBackingStore::Transaction* transaction,
1585 int64 database_id, 1709 int64 database_id,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1703 int64 object_store_id, 1827 int64 object_store_id,
1704 int64 version, 1828 int64 version,
1705 const std::string& encoded_primary_key, 1829 const std::string& encoded_primary_key,
1706 bool* exists) { 1830 bool* exists) {
1707 const std::string key = 1831 const std::string key =
1708 ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key); 1832 ExistsEntryKey::Encode(database_id, object_store_id, encoded_primary_key);
1709 std::string data; 1833 std::string data;
1710 1834
1711 leveldb::Status s = transaction->Get(key, &data, exists); 1835 leveldb::Status s = transaction->Get(key, &data, exists);
1712 if (!s.ok()) { 1836 if (!s.ok()) {
1713 INTERNAL_READ_ERROR(VERSION_EXISTS); 1837 INTERNAL_READ_ERROR_UNTESTED(VERSION_EXISTS);
1714 return s; 1838 return s;
1715 } 1839 }
1716 if (!*exists) 1840 if (!*exists)
1717 return s; 1841 return s;
1718 1842
1719 StringPiece slice(data); 1843 StringPiece slice(data);
1720 int64 decoded; 1844 int64 decoded;
1721 if (!DecodeInt(&slice, &decoded) || !slice.empty()) 1845 if (!DecodeInt(&slice, &decoded) || !slice.empty())
1722 return InternalInconsistencyStatus(); 1846 return InternalInconsistencyStatus();
1723 *exists = (decoded == version); 1847 *exists = (decoded == version);
(...skipping 23 matching lines...) Expand all
1747 for (;;) { 1871 for (;;) {
1748 if (!it->IsValid()) 1872 if (!it->IsValid())
1749 return leveldb::Status::OK(); 1873 return leveldb::Status::OK();
1750 if (CompareIndexKeys(it->Key(), leveldb_key) > 0) 1874 if (CompareIndexKeys(it->Key(), leveldb_key) > 0)
1751 return leveldb::Status::OK(); 1875 return leveldb::Status::OK();
1752 1876
1753 StringPiece slice(it->Value()); 1877 StringPiece slice(it->Value());
1754 1878
1755 int64 version; 1879 int64 version;
1756 if (!DecodeVarInt(&slice, &version)) { 1880 if (!DecodeVarInt(&slice, &version)) {
1757 INTERNAL_READ_ERROR(FIND_KEY_IN_INDEX); 1881 INTERNAL_READ_ERROR_UNTESTED(FIND_KEY_IN_INDEX);
1758 return InternalInconsistencyStatus(); 1882 return InternalInconsistencyStatus();
1759 } 1883 }
1760 *found_encoded_primary_key = slice.as_string(); 1884 *found_encoded_primary_key = slice.as_string();
1761 1885
1762 bool exists = false; 1886 bool exists = false;
1763 leveldb::Status s = VersionExists(leveldb_transaction, 1887 leveldb::Status s = VersionExists(leveldb_transaction,
1764 database_id, 1888 database_id,
1765 object_store_id, 1889 object_store_id,
1766 version, 1890 version,
1767 *found_encoded_primary_key, 1891 *found_encoded_primary_key,
(...skipping 25 matching lines...) Expand all
1793 bool found = false; 1917 bool found = false;
1794 std::string found_encoded_primary_key; 1918 std::string found_encoded_primary_key;
1795 leveldb::Status s = FindKeyInIndex(transaction, 1919 leveldb::Status s = FindKeyInIndex(transaction,
1796 database_id, 1920 database_id,
1797 object_store_id, 1921 object_store_id,
1798 index_id, 1922 index_id,
1799 key, 1923 key,
1800 &found_encoded_primary_key, 1924 &found_encoded_primary_key,
1801 &found); 1925 &found);
1802 if (!s.ok()) { 1926 if (!s.ok()) {
1803 INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX); 1927 INTERNAL_READ_ERROR_UNTESTED(GET_PRIMARY_KEY_VIA_INDEX);
1804 return s; 1928 return s;
1805 } 1929 }
1806 if (!found) 1930 if (!found)
1807 return s; 1931 return s;
1808 if (!found_encoded_primary_key.size()) { 1932 if (!found_encoded_primary_key.size()) {
1809 INTERNAL_READ_ERROR(GET_PRIMARY_KEY_VIA_INDEX); 1933 INTERNAL_READ_ERROR_UNTESTED(GET_PRIMARY_KEY_VIA_INDEX);
1810 return InvalidDBKeyStatus(); 1934 return InvalidDBKeyStatus();
1811 } 1935 }
1812 1936
1813 StringPiece slice(found_encoded_primary_key); 1937 StringPiece slice(found_encoded_primary_key);
1814 if (DecodeIDBKey(&slice, primary_key) && slice.empty()) 1938 if (DecodeIDBKey(&slice, primary_key) && slice.empty())
1815 return s; 1939 return s;
1816 else 1940 else
1817 return InvalidDBKeyStatus(); 1941 return InvalidDBKeyStatus();
1818 } 1942 }
1819 1943
(...skipping 12 matching lines...) Expand all
1832 *exists = false; 1956 *exists = false;
1833 std::string found_encoded_primary_key; 1957 std::string found_encoded_primary_key;
1834 leveldb::Status s = FindKeyInIndex(transaction, 1958 leveldb::Status s = FindKeyInIndex(transaction,
1835 database_id, 1959 database_id,
1836 object_store_id, 1960 object_store_id,
1837 index_id, 1961 index_id,
1838 index_key, 1962 index_key,
1839 &found_encoded_primary_key, 1963 &found_encoded_primary_key,
1840 exists); 1964 exists);
1841 if (!s.ok()) { 1965 if (!s.ok()) {
1842 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); 1966 INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_INDEX);
1843 return s; 1967 return s;
1844 } 1968 }
1845 if (!*exists) 1969 if (!*exists)
1846 return leveldb::Status::OK(); 1970 return leveldb::Status::OK();
1847 if (found_encoded_primary_key.empty()) { 1971 if (found_encoded_primary_key.empty()) {
1848 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); 1972 INTERNAL_READ_ERROR_UNTESTED(KEY_EXISTS_IN_INDEX);
1849 return InvalidDBKeyStatus(); 1973 return InvalidDBKeyStatus();
1850 } 1974 }
1851 1975
1852 StringPiece slice(found_encoded_primary_key); 1976 StringPiece slice(found_encoded_primary_key);
1853 if (DecodeIDBKey(&slice, found_primary_key) && slice.empty()) 1977 if (DecodeIDBKey(&slice, found_primary_key) && slice.empty())
1854 return s; 1978 return s;
1855 else 1979 else
1856 return InvalidDBKeyStatus(); 1980 return InvalidDBKeyStatus();
1857 } 1981 }
1858 1982
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 2205
2082 private: 2206 private:
2083 explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other) 2207 explicit ObjectStoreKeyCursorImpl(const ObjectStoreKeyCursorImpl* other)
2084 : IndexedDBBackingStore::Cursor(other) {} 2208 : IndexedDBBackingStore::Cursor(other) {}
2085 }; 2209 };
2086 2210
2087 bool ObjectStoreKeyCursorImpl::LoadCurrentRow() { 2211 bool ObjectStoreKeyCursorImpl::LoadCurrentRow() {
2088 StringPiece slice(iterator_->Key()); 2212 StringPiece slice(iterator_->Key());
2089 ObjectStoreDataKey object_store_data_key; 2213 ObjectStoreDataKey object_store_data_key;
2090 if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) { 2214 if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) {
2091 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2215 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2092 return false; 2216 return false;
2093 } 2217 }
2094 2218
2095 current_key_ = object_store_data_key.user_key(); 2219 current_key_ = object_store_data_key.user_key();
2096 2220
2097 int64 version; 2221 int64 version;
2098 slice = StringPiece(iterator_->Value()); 2222 slice = StringPiece(iterator_->Value());
2099 if (!DecodeVarInt(&slice, &version)) { 2223 if (!DecodeVarInt(&slice, &version)) {
2100 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2224 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2101 return false; 2225 return false;
2102 } 2226 }
2103 2227
2104 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. 2228 // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
2105 std::string encoded_key; 2229 std::string encoded_key;
2106 EncodeIDBKey(*current_key_, &encoded_key); 2230 EncodeIDBKey(*current_key_, &encoded_key);
2107 record_identifier_.Reset(encoded_key, version); 2231 record_identifier_.Reset(encoded_key, version);
2108 2232
2109 return true; 2233 return true;
2110 } 2234 }
(...skipping 27 matching lines...) Expand all
2138 : IndexedDBBackingStore::Cursor(other), 2262 : IndexedDBBackingStore::Cursor(other),
2139 current_value_(other->current_value_) {} 2263 current_value_(other->current_value_) {}
2140 2264
2141 IndexedDBValue current_value_; 2265 IndexedDBValue current_value_;
2142 }; 2266 };
2143 2267
2144 bool ObjectStoreCursorImpl::LoadCurrentRow() { 2268 bool ObjectStoreCursorImpl::LoadCurrentRow() {
2145 StringPiece key_slice(iterator_->Key()); 2269 StringPiece key_slice(iterator_->Key());
2146 ObjectStoreDataKey object_store_data_key; 2270 ObjectStoreDataKey object_store_data_key;
2147 if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) { 2271 if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) {
2148 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2272 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2149 return false; 2273 return false;
2150 } 2274 }
2151 2275
2152 current_key_ = object_store_data_key.user_key(); 2276 current_key_ = object_store_data_key.user_key();
2153 2277
2154 int64 version; 2278 int64 version;
2155 StringPiece value_slice = StringPiece(iterator_->Value()); 2279 StringPiece value_slice = StringPiece(iterator_->Value());
2156 if (!DecodeVarInt(&value_slice, &version)) { 2280 if (!DecodeVarInt(&value_slice, &version)) {
2157 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2281 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2158 return false; 2282 return false;
2159 } 2283 }
2160 2284
2161 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. 2285 // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
2162 std::string encoded_key; 2286 std::string encoded_key;
2163 EncodeIDBKey(*current_key_, &encoded_key); 2287 EncodeIDBKey(*current_key_, &encoded_key);
2164 record_identifier_.Reset(encoded_key, version); 2288 record_identifier_.Reset(encoded_key, version);
2165 2289
2166 current_value_.bits = value_slice.as_string(); 2290 current_value_.bits = value_slice.as_string();
2167 return true; 2291 return true;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2212 : IndexedDBBackingStore::Cursor(other), 2336 : IndexedDBBackingStore::Cursor(other),
2213 primary_key_(new IndexedDBKey(*other->primary_key_)) {} 2337 primary_key_(new IndexedDBKey(*other->primary_key_)) {}
2214 2338
2215 scoped_ptr<IndexedDBKey> primary_key_; 2339 scoped_ptr<IndexedDBKey> primary_key_;
2216 }; 2340 };
2217 2341
2218 bool IndexKeyCursorImpl::LoadCurrentRow() { 2342 bool IndexKeyCursorImpl::LoadCurrentRow() {
2219 StringPiece slice(iterator_->Key()); 2343 StringPiece slice(iterator_->Key());
2220 IndexDataKey index_data_key; 2344 IndexDataKey index_data_key;
2221 if (!IndexDataKey::Decode(&slice, &index_data_key)) { 2345 if (!IndexDataKey::Decode(&slice, &index_data_key)) {
2222 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2346 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2223 return false; 2347 return false;
2224 } 2348 }
2225 2349
2226 current_key_ = index_data_key.user_key(); 2350 current_key_ = index_data_key.user_key();
2227 DCHECK(current_key_); 2351 DCHECK(current_key_);
2228 2352
2229 slice = StringPiece(iterator_->Value()); 2353 slice = StringPiece(iterator_->Value());
2230 int64 index_data_version; 2354 int64 index_data_version;
2231 if (!DecodeVarInt(&slice, &index_data_version)) { 2355 if (!DecodeVarInt(&slice, &index_data_version)) {
2232 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2356 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2233 return false; 2357 return false;
2234 } 2358 }
2235 2359
2236 if (!DecodeIDBKey(&slice, &primary_key_) || !slice.empty()) { 2360 if (!DecodeIDBKey(&slice, &primary_key_) || !slice.empty()) {
2237 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2361 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2238 return false; 2362 return false;
2239 } 2363 }
2240 2364
2241 std::string primary_leveldb_key = 2365 std::string primary_leveldb_key =
2242 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), 2366 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
2243 index_data_key.ObjectStoreId(), 2367 index_data_key.ObjectStoreId(),
2244 *primary_key_); 2368 *primary_key_);
2245 2369
2246 std::string result; 2370 std::string result;
2247 bool found = false; 2371 bool found = false;
2248 leveldb::Status s = transaction_->Get(primary_leveldb_key, &result, &found); 2372 leveldb::Status s = transaction_->Get(primary_leveldb_key, &result, &found);
2249 if (!s.ok()) { 2373 if (!s.ok()) {
2250 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2374 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2251 return false; 2375 return false;
2252 } 2376 }
2253 if (!found) { 2377 if (!found) {
2254 transaction_->Remove(iterator_->Key()); 2378 transaction_->Remove(iterator_->Key());
2255 return false; 2379 return false;
2256 } 2380 }
2257 if (!result.size()) { 2381 if (!result.size()) {
2258 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2382 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2259 return false; 2383 return false;
2260 } 2384 }
2261 2385
2262 int64 object_store_data_version; 2386 int64 object_store_data_version;
2263 slice = StringPiece(result); 2387 slice = StringPiece(result);
2264 if (!DecodeVarInt(&slice, &object_store_data_version)) { 2388 if (!DecodeVarInt(&slice, &object_store_data_version)) {
2265 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2389 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2266 return false; 2390 return false;
2267 } 2391 }
2268 2392
2269 if (object_store_data_version != index_data_version) { 2393 if (object_store_data_version != index_data_version) {
2270 transaction_->Remove(iterator_->Key()); 2394 transaction_->Remove(iterator_->Key());
2271 return false; 2395 return false;
2272 } 2396 }
2273 2397
2274 return true; 2398 return true;
2275 } 2399 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2320 2444
2321 scoped_ptr<IndexedDBKey> primary_key_; 2445 scoped_ptr<IndexedDBKey> primary_key_;
2322 IndexedDBValue current_value_; 2446 IndexedDBValue current_value_;
2323 std::string primary_leveldb_key_; 2447 std::string primary_leveldb_key_;
2324 }; 2448 };
2325 2449
2326 bool IndexCursorImpl::LoadCurrentRow() { 2450 bool IndexCursorImpl::LoadCurrentRow() {
2327 StringPiece slice(iterator_->Key()); 2451 StringPiece slice(iterator_->Key());
2328 IndexDataKey index_data_key; 2452 IndexDataKey index_data_key;
2329 if (!IndexDataKey::Decode(&slice, &index_data_key)) { 2453 if (!IndexDataKey::Decode(&slice, &index_data_key)) {
2330 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2454 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2331 return false; 2455 return false;
2332 } 2456 }
2333 2457
2334 current_key_ = index_data_key.user_key(); 2458 current_key_ = index_data_key.user_key();
2335 DCHECK(current_key_); 2459 DCHECK(current_key_);
2336 2460
2337 slice = StringPiece(iterator_->Value()); 2461 slice = StringPiece(iterator_->Value());
2338 int64 index_data_version; 2462 int64 index_data_version;
2339 if (!DecodeVarInt(&slice, &index_data_version)) { 2463 if (!DecodeVarInt(&slice, &index_data_version)) {
2340 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2464 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2341 return false; 2465 return false;
2342 } 2466 }
2343 if (!DecodeIDBKey(&slice, &primary_key_)) { 2467 if (!DecodeIDBKey(&slice, &primary_key_)) {
2344 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2468 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2345 return false; 2469 return false;
2346 } 2470 }
2347 2471
2348 primary_leveldb_key_ = 2472 primary_leveldb_key_ =
2349 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), 2473 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
2350 index_data_key.ObjectStoreId(), 2474 index_data_key.ObjectStoreId(),
2351 *primary_key_); 2475 *primary_key_);
2352 2476
2353 std::string result; 2477 std::string result;
2354 bool found = false; 2478 bool found = false;
2355 leveldb::Status s = transaction_->Get(primary_leveldb_key_, &result, &found); 2479 leveldb::Status s = transaction_->Get(primary_leveldb_key_, &result, &found);
2356 if (!s.ok()) { 2480 if (!s.ok()) {
2357 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2481 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2358 return false; 2482 return false;
2359 } 2483 }
2360 if (!found) { 2484 if (!found) {
2361 transaction_->Remove(iterator_->Key()); 2485 transaction_->Remove(iterator_->Key());
2362 return false; 2486 return false;
2363 } 2487 }
2364 if (!result.size()) { 2488 if (!result.size()) {
2365 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2489 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2366 return false; 2490 return false;
2367 } 2491 }
2368 2492
2369 int64 object_store_data_version; 2493 int64 object_store_data_version;
2370 slice = StringPiece(result); 2494 slice = StringPiece(result);
2371 if (!DecodeVarInt(&slice, &object_store_data_version)) { 2495 if (!DecodeVarInt(&slice, &object_store_data_version)) {
2372 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2496 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2373 return false; 2497 return false;
2374 } 2498 }
2375 2499
2376 if (object_store_data_version != index_data_version) { 2500 if (object_store_data_version != index_data_version) {
2377 transaction_->Remove(iterator_->Key()); 2501 transaction_->Remove(iterator_->Key());
2378 return false; 2502 return false;
2379 } 2503 }
2380 2504
2381 current_value_.bits = slice.as_string(); 2505 current_value_.bits = slice.as_string();
2382 return true; 2506 return true;
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
2633 DCHECK(!transaction_.get()); 2757 DCHECK(!transaction_.get());
2634 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); 2758 transaction_ = new LevelDBTransaction(backing_store_->db_.get());
2635 } 2759 }
2636 2760
2637 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 2761 leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
2638 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 2762 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit");
2639 DCHECK(transaction_.get()); 2763 DCHECK(transaction_.get());
2640 leveldb::Status s = transaction_->Commit(); 2764 leveldb::Status s = transaction_->Commit();
2641 transaction_ = NULL; 2765 transaction_ = NULL;
2642 if (!s.ok()) 2766 if (!s.ok())
2643 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); 2767 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
2644 return s; 2768 return s;
2645 } 2769 }
2646 2770
2647 void IndexedDBBackingStore::Transaction::Rollback() { 2771 void IndexedDBBackingStore::Transaction::Rollback() {
2648 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 2772 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2649 DCHECK(transaction_.get()); 2773 DCHECK(transaction_.get());
2650 transaction_->Rollback(); 2774 transaction_->Rollback();
2651 transaction_ = NULL; 2775 transaction_ = NULL;
2652 } 2776 }
2653 2777
2654 } // namespace content 2778 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698