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

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

Powered by Google App Engine
This is Rietveld 408576698