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

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

Issue 18023022: Blob support for IDB [Chromium] (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: DeleteRange now seems to work. Created 6 years, 7 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 | Annotate | Revision Log
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/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/format_macros.h" 9 #include "base/format_macros.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 GET_NEW_DATABASE_ID, 121 GET_NEW_DATABASE_ID,
122 GET_NEW_VERSION_NUMBER, 122 GET_NEW_VERSION_NUMBER,
123 CREATE_IDBDATABASE_METADATA, 123 CREATE_IDBDATABASE_METADATA,
124 DELETE_DATABASE, 124 DELETE_DATABASE,
125 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro 125 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro
126 GET_DATABASE_NAMES, 126 GET_DATABASE_NAMES,
127 DELETE_INDEX, 127 DELETE_INDEX,
128 CLEAR_OBJECT_STORE, 128 CLEAR_OBJECT_STORE,
129 READ_BLOB_JOURNAL, 129 READ_BLOB_JOURNAL,
130 DECODE_BLOB_JOURNAL, 130 DECODE_BLOB_JOURNAL,
131 GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER,
132 GET_BLOB_INFO_FOR_RECORD,
131 INTERNAL_ERROR_MAX, 133 INTERNAL_ERROR_MAX,
132 }; 134 };
133 135
134 static void RecordInternalError(const char* type, 136 static void RecordInternalError(const char* type,
135 IndexedDBBackingStoreErrorSource location) { 137 IndexedDBBackingStoreErrorSource location) {
136 std::string name; 138 std::string name;
137 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); 139 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
138 base::Histogram::FactoryGet(name, 140 base::Histogram::FactoryGet(name,
139 1, 141 1,
140 INTERNAL_ERROR_MAX, 142 INTERNAL_ERROR_MAX,
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 return content::Compare(a, b, false /*index_keys*/); 299 return content::Compare(a, b, false /*index_keys*/);
298 } 300 }
299 301
300 const char* IndexedDBBackingStore::Comparator::Name() const { 302 const char* IndexedDBBackingStore::Comparator::Name() const {
301 return "idb_cmp1"; 303 return "idb_cmp1";
302 } 304 }
303 305
304 // 0 - Initial version. 306 // 0 - Initial version.
305 // 1 - Adds UserIntVersion to DatabaseMetaData. 307 // 1 - Adds UserIntVersion to DatabaseMetaData.
306 // 2 - Adds DataVersion to to global metadata. 308 // 2 - Adds DataVersion to to global metadata.
307 static const int64 kLatestKnownSchemaVersion = 2; 309 // 3 - Adds metadata needed for blob support.
310 static const int64 kLatestKnownSchemaVersion = 3;
308 WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) { 311 WARN_UNUSED_RESULT static bool IsSchemaKnown(LevelDBDatabase* db, bool* known) {
309 int64 db_schema_version = 0; 312 int64 db_schema_version = 0;
310 bool found = false; 313 bool found = false;
311 leveldb::Status s = 314 leveldb::Status s =
312 GetInt(db, SchemaVersionKey::Encode(), &db_schema_version, &found); 315 GetInt(db, SchemaVersionKey::Encode(), &db_schema_version, &found);
313 if (!s.ok()) 316 if (!s.ok())
314 return false; 317 return false;
315 if (!found) { 318 if (!found) {
316 *known = true; 319 *known = true;
317 return true; 320 return true;
(...skipping 16 matching lines...) Expand all
334 337
335 if (db_data_version > latest_known_data_version) { 338 if (db_data_version > latest_known_data_version) {
336 *known = false; 339 *known = false;
337 return true; 340 return true;
338 } 341 }
339 342
340 *known = true; 343 *known = true;
341 return true; 344 return true;
342 } 345 }
343 346
344 WARN_UNUSED_RESULT static bool SetUpMetadata( 347 // TODO(ericu): Move this down into the member section of this file. I'm
345 LevelDBDatabase* db, 348 // leaving it here for this CL as it's easier to see the diffs in place.
346 const std::string& origin_identifier) { 349 WARN_UNUSED_RESULT bool IndexedDBBackingStore::SetUpMetadata() {
347 const uint32 latest_known_data_version = 350 const uint32 latest_known_data_version =
348 blink::kSerializedScriptValueVersion; 351 blink::kSerializedScriptValueVersion;
349 const std::string schema_version_key = SchemaVersionKey::Encode(); 352 const std::string schema_version_key = SchemaVersionKey::Encode();
350 const std::string data_version_key = DataVersionKey::Encode(); 353 const std::string data_version_key = DataVersionKey::Encode();
351 354
352 scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db); 355 scoped_refptr<LevelDBTransaction> transaction =
356 new LevelDBTransaction(db_.get());
353 357
354 int64 db_schema_version = 0; 358 int64 db_schema_version = 0;
355 int64 db_data_version = 0; 359 int64 db_data_version = 0;
356 bool found = false; 360 bool found = false;
357 leveldb::Status s = 361 leveldb::Status s =
358 GetInt(transaction.get(), schema_version_key, &db_schema_version, &found); 362 GetInt(transaction.get(), schema_version_key, &db_schema_version, &found);
359 if (!s.ok()) { 363 if (!s.ok()) {
360 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); 364 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
361 return false; 365 return false;
362 } 366 }
363 if (!found) { 367 if (!found) {
364 // Initialize new backing store. 368 // Initialize new backing store.
365 db_schema_version = kLatestKnownSchemaVersion; 369 db_schema_version = kLatestKnownSchemaVersion;
366 PutInt(transaction.get(), schema_version_key, db_schema_version); 370 PutInt(transaction.get(), schema_version_key, db_schema_version);
367 db_data_version = latest_known_data_version; 371 db_data_version = latest_known_data_version;
368 PutInt(transaction.get(), data_version_key, db_data_version); 372 PutInt(transaction.get(), data_version_key, db_data_version);
373 // If a blob directory already exists for this database, blow it away. It's
374 // leftover from a partially-purged previous generation of data.
375 if (!base::DeleteFile(blob_path_, true)) {
376 INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
377 return false;
378 }
369 } else { 379 } else {
370 // Upgrade old backing store. 380 // Upgrade old backing store.
371 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion); 381 DCHECK_LE(db_schema_version, kLatestKnownSchemaVersion);
372 if (db_schema_version < 1) { 382 if (db_schema_version < 1) {
373 db_schema_version = 1; 383 db_schema_version = 1;
374 PutInt(transaction.get(), schema_version_key, db_schema_version); 384 PutInt(transaction.get(), schema_version_key, db_schema_version);
375 const std::string start_key = 385 const std::string start_key =
376 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier); 386 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
377 const std::string stop_key = 387 const std::string stop_key =
378 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier); 388 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
379 scoped_ptr<LevelDBIterator> it = db->CreateIterator(); 389 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
380 for (s = it->Seek(start_key); 390 for (s = it->Seek(start_key);
381 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 391 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
382 s = it->Next()) { 392 s = it->Next()) {
383 int64 database_id = 0; 393 int64 database_id = 0;
384 found = false; 394 found = false;
385 s = GetInt(transaction.get(), it->Key(), &database_id, &found); 395 s = GetInt(transaction.get(), it->Key(), &database_id, &found);
386 if (!s.ok()) { 396 if (!s.ok()) {
387 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); 397 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
388 return false; 398 return false;
389 } 399 }
390 if (!found) { 400 if (!found) {
391 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA); 401 INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
392 return false; 402 return false;
393 } 403 }
394 std::string int_version_key = DatabaseMetaDataKey::Encode( 404 std::string int_version_key = DatabaseMetaDataKey::Encode(
395 database_id, DatabaseMetaDataKey::USER_INT_VERSION); 405 database_id, DatabaseMetaDataKey::USER_INT_VERSION);
396 PutVarInt(transaction.get(), 406 PutVarInt(transaction.get(),
397 int_version_key, 407 int_version_key,
398 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION); 408 IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
399 } 409 }
400 } 410 }
401 if (s.ok() && db_schema_version < 2) { 411 if (s.ok() && db_schema_version < 2) {
402 db_schema_version = 2; 412 db_schema_version = 2;
403 PutInt(transaction.get(), schema_version_key, db_schema_version); 413 PutInt(transaction.get(), schema_version_key, db_schema_version);
404 db_data_version = blink::kSerializedScriptValueVersion; 414 db_data_version = blink::kSerializedScriptValueVersion;
405 PutInt(transaction.get(), data_version_key, db_data_version); 415 PutInt(transaction.get(), data_version_key, db_data_version);
406 } 416 }
417 if (db_schema_version < 3) {
418 db_schema_version = 3;
419 if (!base::DeleteFile(blob_path_, true)) {
420 INTERNAL_WRITE_ERROR_UNTESTED(SET_UP_METADATA);
421 return false;
422 }
423 }
407 } 424 }
408 425
409 if (!s.ok()) { 426 if (!s.ok()) {
410 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA); 427 INTERNAL_READ_ERROR_UNTESTED(SET_UP_METADATA);
411 return false; 428 return false;
412 } 429 }
413 430
414 // All new values will be written using this serialization version. 431 // All new values will be written using this serialization version.
415 found = false; 432 found = false;
416 s = GetInt(transaction.get(), data_version_key, &db_data_version, &found); 433 s = GetInt(transaction.get(), data_version_key, &db_data_version, &found);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 scoped_ptr<LevelDBDatabase>* db, 490 scoped_ptr<LevelDBDatabase>* db,
474 bool* is_disk_full) OVERRIDE { 491 bool* is_disk_full) OVERRIDE {
475 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); 492 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
476 } 493 }
477 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) 494 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
478 OVERRIDE { 495 OVERRIDE {
479 return LevelDBDatabase::Destroy(file_name); 496 return LevelDBDatabase::Destroy(file_name);
480 } 497 }
481 }; 498 };
482 499
500 static bool GetBlobKeyGeneratorCurrentNumber(
501 LevelDBTransaction* leveldb_transaction,
502 int64 database_id,
503 int64* blob_key_generator_current_number) {
504 const std::string key_gen_key = DatabaseMetaDataKey::Encode(
505 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
506
507 // Default to initial number if not found.
508 int64 cur_number = DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber;
509 std::string data;
510
511 bool found = false;
512 bool ok = leveldb_transaction->Get(key_gen_key, &data, &found).ok();
513 if (!ok) {
514 INTERNAL_READ_ERROR_UNTESTED(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
515 return false;
516 }
517 if (found) {
518 StringPiece slice(data);
519 if (!DecodeVarInt(&slice, &cur_number) || !slice.empty() ||
520 !DatabaseMetaDataKey::IsValidBlobKey(cur_number)) {
521 INTERNAL_READ_ERROR_UNTESTED(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
522 return false;
523 }
524 }
525 *blob_key_generator_current_number = cur_number;
526 return true;
527 }
528
529 static bool UpdateBlobKeyGeneratorCurrentNumber(
530 LevelDBTransaction* leveldb_transaction,
531 int64 database_id,
532 int64 blob_key_generator_current_number) {
533 #ifndef NDEBUG
534 int64 old_number;
535 if (!GetBlobKeyGeneratorCurrentNumber(
536 leveldb_transaction, database_id, &old_number))
537 return false;
538 DCHECK_LT(old_number, blob_key_generator_current_number);
539 #endif
540 DCHECK(
541 DatabaseMetaDataKey::IsValidBlobKey(blob_key_generator_current_number));
542 const std::string key = DatabaseMetaDataKey::Encode(
543 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
544
545 PutVarInt(leveldb_transaction, key, blob_key_generator_current_number);
546 return true;
547 }
548
483 // TODO(ericu): Error recovery. If we persistently can't read the 549 // TODO(ericu): Error recovery. If we persistently can't read the
484 // blob journal, the safe thing to do is to clear it and leak the blobs, 550 // blob journal, the safe thing to do is to clear it and leak the blobs,
485 // though that may be costly. Still, database/directory deletion should always 551 // though that may be costly. Still, database/directory deletion should always
486 // clean things up, and we can write an fsck that will do a full correction if 552 // clean things up, and we can write an fsck that will do a full correction if
487 // need be. 553 // need be.
488 template <typename T> 554 template <typename T>
489 static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key, 555 static leveldb::Status GetBlobJournal(const StringPiece& leveldb_key,
490 T* leveldb_transaction, 556 T* leveldb_transaction,
491 BlobJournalType* journal) { 557 BlobJournalType* journal) {
492 std::string data; 558 std::string data;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 if (!s.ok()) 632 if (!s.ok())
567 return s; 633 return s;
568 journal.push_back( 634 journal.push_back(
569 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey)); 635 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
570 std::string data; 636 std::string data;
571 EncodeBlobJournal(journal, &data); 637 EncodeBlobJournal(journal, &data);
572 leveldb_transaction->Put(key, &data); 638 leveldb_transaction->Put(key, &data);
573 return leveldb::Status::OK(); 639 return leveldb::Status::OK();
574 } 640 }
575 641
642 // Blob Data is encoded as a series of:
643 // { is_file [bool], key [int64 as varInt],
644 // type [string-with-length, may be empty],
645 // (for Blobs only) size [int64 as varInt]
646 // (for Files only) fileName [string-with-length]
647 // }
648 // There is no length field; just read until you run out of data.
649 static std::string EncodeBlobData(
650 const std::vector<IndexedDBBlobInfo*>& blob_info) {
651 std::string ret;
652 std::vector<IndexedDBBlobInfo*>::const_iterator iter;
653 for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
654 const IndexedDBBlobInfo& info = **iter;
655 EncodeBool(info.is_file(), &ret);
656 EncodeVarInt(info.key(), &ret);
657 EncodeStringWithLength(info.type(), &ret);
658 if (info.is_file())
659 EncodeStringWithLength(info.file_name(), &ret);
660 else
661 EncodeVarInt(info.size(), &ret);
662 }
663 return ret;
664 }
665
666 static bool DecodeBlobData(const std::string& data,
667 std::vector<IndexedDBBlobInfo>* output) {
668 std::vector<IndexedDBBlobInfo> ret;
669 output->clear();
670 StringPiece slice(data);
671 while (!slice.empty()) {
672 bool is_file;
673 int64 key;
674 base::string16 type;
675 int64 size;
676 base::string16 file_name;
677
678 if (!DecodeBool(&slice, &is_file))
679 return false;
680 if (!DecodeVarInt(&slice, &key) ||
681 !DatabaseMetaDataKey::IsValidBlobKey(key))
682 return false;
683 if (!DecodeStringWithLength(&slice, &type))
684 return false;
685 if (is_file) {
686 if (!DecodeStringWithLength(&slice, &file_name))
687 return false;
688 ret.push_back(IndexedDBBlobInfo(key, type, file_name));
689 } else {
690 if (!DecodeVarInt(&slice, &size) || size < 0)
691 return false;
692 ret.push_back(IndexedDBBlobInfo(type, static_cast<uint64>(size), key));
693 }
694 }
695 output->swap(ret);
696
697 return true;
698 }
699
576 IndexedDBBackingStore::IndexedDBBackingStore( 700 IndexedDBBackingStore::IndexedDBBackingStore(
577 IndexedDBFactory* indexed_db_factory, 701 IndexedDBFactory* indexed_db_factory,
578 const GURL& origin_url, 702 const GURL& origin_url,
579 const base::FilePath& blob_path, 703 const base::FilePath& blob_path,
580 net::URLRequestContext* request_context, 704 net::URLRequestContext* request_context,
581 scoped_ptr<LevelDBDatabase> db, 705 scoped_ptr<LevelDBDatabase> db,
582 scoped_ptr<LevelDBComparator> comparator, 706 scoped_ptr<LevelDBComparator> comparator,
583 base::TaskRunner* task_runner) 707 base::TaskRunner* task_runner)
584 : indexed_db_factory_(indexed_db_factory), 708 : indexed_db_factory_(indexed_db_factory),
585 origin_url_(origin_url), 709 origin_url_(origin_url),
586 blob_path_(blob_path), 710 blob_path_(blob_path),
587 origin_identifier_(ComputeOriginIdentifier(origin_url)), 711 origin_identifier_(ComputeOriginIdentifier(origin_url)),
588 request_context_(request_context), 712 request_context_(request_context),
589 task_runner_(task_runner), 713 task_runner_(task_runner),
590 db_(db.Pass()), 714 db_(db.Pass()),
591 comparator_(comparator.Pass()), 715 comparator_(comparator.Pass()),
592 active_blob_registry_(this) {} 716 active_blob_registry_(this) {
717 }
593 718
594 IndexedDBBackingStore::~IndexedDBBackingStore() { 719 IndexedDBBackingStore::~IndexedDBBackingStore() {
595 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) { 720 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
596 ChildProcessSecurityPolicyImpl* policy = 721 ChildProcessSecurityPolicyImpl* policy =
597 ChildProcessSecurityPolicyImpl::GetInstance(); 722 ChildProcessSecurityPolicyImpl::GetInstance();
598 std::set<int>::const_iterator iter; 723 std::set<int>::const_iterator iter;
599 for (iter = child_process_ids_granted_.begin(); 724 for (iter = child_process_ids_granted_.begin();
600 iter != child_process_ids_granted_.end(); 725 iter != child_process_ids_granted_.end();
601 ++iter) { 726 ++iter) {
602 policy->RevokeAllPermissionsForFile(*iter, blob_path_); 727 policy->RevokeAllPermissionsForFile(*iter, blob_path_);
(...skipping 28 matching lines...) Expand all
631 INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED, 756 INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_FAILED,
632 INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS, 757 INDEXED_DB_BACKING_STORE_OPEN_CLEANUP_REOPEN_SUCCESS,
633 INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA, 758 INDEXED_DB_BACKING_STORE_OPEN_FAILED_IO_ERROR_CHECKING_SCHEMA,
634 INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, 759 INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
635 INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, 760 INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
636 INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, 761 INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
637 INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED, 762 INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED,
638 INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, 763 INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
639 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, 764 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
640 INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION, 765 INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
766 INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR,
641 INDEXED_DB_BACKING_STORE_OPEN_MAX, 767 INDEXED_DB_BACKING_STORE_OPEN_MAX,
642 }; 768 };
643 769
644 // static 770 // static
645 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 771 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
646 IndexedDBFactory* indexed_db_factory, 772 IndexedDBFactory* indexed_db_factory,
647 const GURL& origin_url, 773 const GURL& origin_url,
648 const base::FilePath& path_base, 774 const base::FilePath& path_base,
649 net::URLRequestContext* request_context, 775 net::URLRequestContext* request_context,
650 blink::WebIDBDataLoss* data_loss, 776 blink::WebIDBDataLoss* data_loss,
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
916 origin_url); 1042 origin_url);
917 } 1043 }
918 1044
919 if (!db) { 1045 if (!db) {
920 NOTREACHED(); 1046 NOTREACHED();
921 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, 1047 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
922 origin_url); 1048 origin_url);
923 return scoped_refptr<IndexedDBBackingStore>(); 1049 return scoped_refptr<IndexedDBBackingStore>();
924 } 1050 }
925 1051
926 return Create(indexed_db_factory, 1052 scoped_refptr<IndexedDBBackingStore> backing_store =
927 origin_url, 1053 Create(indexed_db_factory,
928 blob_path, 1054 origin_url,
929 request_context, 1055 blob_path,
930 db.Pass(), 1056 request_context,
931 comparator.Pass(), 1057 db.Pass(),
932 task_runner); 1058 comparator.Pass(),
1059 task_runner);
1060
1061 if (clean_journal && backing_store &&
1062 !backing_store->CleanUpBlobJournal(LiveBlobJournalKey::Encode()).ok()) {
1063 HistogramOpenStatus(
1064 INDEXED_DB_BACKING_STORE_OPEN_FAILED_CLEANUP_JOURNAL_ERROR, origin_url);
1065 return scoped_refptr<IndexedDBBackingStore>();
1066 }
1067 return backing_store;
933 } 1068 }
934 1069
935 // static 1070 // static
936 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 1071 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
937 const GURL& origin_url, 1072 const GURL& origin_url,
938 base::TaskRunner* task_runner) { 1073 base::TaskRunner* task_runner) {
939 DefaultLevelDBFactory leveldb_factory; 1074 DefaultLevelDBFactory leveldb_factory;
940 return IndexedDBBackingStore::OpenInMemory( 1075 return IndexedDBBackingStore::OpenInMemory(
941 origin_url, &leveldb_factory, task_runner); 1076 origin_url, &leveldb_factory, task_runner);
942 } 1077 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 base::TaskRunner* task_runner) { 1114 base::TaskRunner* task_runner) {
980 // TODO(jsbell): Handle comparator name changes. 1115 // TODO(jsbell): Handle comparator name changes.
981 scoped_refptr<IndexedDBBackingStore> backing_store( 1116 scoped_refptr<IndexedDBBackingStore> backing_store(
982 new IndexedDBBackingStore(indexed_db_factory, 1117 new IndexedDBBackingStore(indexed_db_factory,
983 origin_url, 1118 origin_url,
984 blob_path, 1119 blob_path,
985 request_context, 1120 request_context,
986 db.Pass(), 1121 db.Pass(),
987 comparator.Pass(), 1122 comparator.Pass(),
988 task_runner)); 1123 task_runner));
989 if (!SetUpMetadata(backing_store->db_.get(), 1124 if (!backing_store->SetUpMetadata())
990 backing_store->origin_identifier_))
991 return scoped_refptr<IndexedDBBackingStore>(); 1125 return scoped_refptr<IndexedDBBackingStore>();
992 1126
993 return backing_store; 1127 return backing_store;
994 } 1128 }
995 1129
996 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) { 1130 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
997 if (!child_process_ids_granted_.count(child_process_id)) { 1131 if (!child_process_ids_granted_.count(child_process_id)) {
998 child_process_ids_granted_.insert(child_process_id); 1132 child_process_ids_granted_.insert(child_process_id);
999 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( 1133 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
1000 child_process_id, blob_path_); 1134 child_process_id, blob_path_);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 1211
1078 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) 1212 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
1079 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; 1213 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
1080 1214
1081 s = GetMaxObjectStoreId( 1215 s = GetMaxObjectStoreId(
1082 db_.get(), metadata->id, &metadata->max_object_store_id); 1216 db_.get(), metadata->id, &metadata->max_object_store_id);
1083 if (!s.ok()) { 1217 if (!s.ok()) {
1084 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA); 1218 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1085 } 1219 }
1086 1220
1221 // We don't cache this, we just check it if it's there.
1222 int64 blob_key_generator_current_number =
1223 DatabaseMetaDataKey::kInvalidBlobKey;
1224
1225 s = GetVarInt(
1226 db_.get(),
1227 DatabaseMetaDataKey::Encode(
1228 metadata->id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1229 &blob_key_generator_current_number,
1230 found);
1231 if (!s.ok()) {
1232 INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1233 return s;
1234 }
1235 if (!*found) {
1236 // This database predates blob support.
1237 *found = true;
1238 } else if (!DatabaseMetaDataKey::IsValidBlobKey(
1239 blob_key_generator_current_number)) {
1240 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1241 return InternalInconsistencyStatus();
1242 }
1243
1087 return s; 1244 return s;
1088 } 1245 }
1089 1246
1090 WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId( 1247 WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId(
1091 LevelDBTransaction* transaction, 1248 LevelDBTransaction* transaction,
1092 int64* new_id) { 1249 int64* new_id) {
1093 *new_id = -1; 1250 *new_id = -1;
1094 int64 max_database_id = -1; 1251 int64 max_database_id = -1;
1095 bool found = false; 1252 bool found = false;
1096 leveldb::Status s = 1253 leveldb::Status s =
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1130 DatabaseNameKey::Encode(origin_identifier_, name), 1287 DatabaseNameKey::Encode(origin_identifier_, name),
1131 *row_id); 1288 *row_id);
1132 PutString( 1289 PutString(
1133 transaction.get(), 1290 transaction.get(),
1134 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION), 1291 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
1135 version); 1292 version);
1136 PutVarInt(transaction.get(), 1293 PutVarInt(transaction.get(),
1137 DatabaseMetaDataKey::Encode(*row_id, 1294 DatabaseMetaDataKey::Encode(*row_id,
1138 DatabaseMetaDataKey::USER_INT_VERSION), 1295 DatabaseMetaDataKey::USER_INT_VERSION),
1139 int_version); 1296 int_version);
1297 PutVarInt(
1298 transaction.get(),
1299 DatabaseMetaDataKey::Encode(
1300 *row_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1301 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber);
1302
1140 s = transaction->Commit(); 1303 s = transaction->Commit();
1141 if (!s.ok()) 1304 if (!s.ok())
1142 INTERNAL_WRITE_ERROR_UNTESTED(CREATE_IDBDATABASE_METADATA); 1305 INTERNAL_WRITE_ERROR_UNTESTED(CREATE_IDBDATABASE_METADATA);
1143 return s; 1306 return s;
1144 } 1307 }
1145 1308
1146 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion( 1309 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
1147 IndexedDBBackingStore::Transaction* transaction, 1310 IndexedDBBackingStore::Transaction* transaction,
1148 int64 row_id, 1311 int64 row_id,
1149 int64 int_version) { 1312 int64 int_version) {
1150 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) 1313 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
1151 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; 1314 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
1152 DCHECK_GE(int_version, 0) << "int_version was " << int_version; 1315 DCHECK_GE(int_version, 0) << "int_version was " << int_version;
1153 PutVarInt(transaction->transaction(), 1316 PutVarInt(transaction->transaction(),
1154 DatabaseMetaDataKey::Encode(row_id, 1317 DatabaseMetaDataKey::Encode(row_id,
1155 DatabaseMetaDataKey::USER_INT_VERSION), 1318 DatabaseMetaDataKey::USER_INT_VERSION),
1156 int_version); 1319 int_version);
1157 return true; 1320 return true;
1158 } 1321 }
1159 1322
1160 static leveldb::Status DeleteRange(LevelDBTransaction* transaction, 1323 // Note that if you're deleting a range that contains user keys that have blob
1161 const std::string& begin, 1324 // info, this won't clean up the blobs.
1162 const std::string& end) { 1325 static leveldb::Status DeleteRangeByKeys(LevelDBTransaction* transaction,
1326 const std::string& begin,
1327 const std::string& end,
1328 bool upper_open) {
1163 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); 1329 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
1164 leveldb::Status s; 1330 leveldb::Status s;
1165 for (s = it->Seek(begin); 1331 for (s = it->Seek(begin);
1166 s.ok() && it->IsValid() && CompareKeys(it->Key(), end) < 0; 1332 s.ok() && it->IsValid() &&
1333 (upper_open ?
1334 CompareKeys(it->Key(), end) < 0 :
1335 CompareKeys(it->Key(), end) <= 0);
1167 s = it->Next()) 1336 s = it->Next())
1168 transaction->Remove(it->Key()); 1337 transaction->Remove(it->Key());
1169 return s; 1338 return s;
1170 } 1339 }
1171 1340
1341 static leveldb::Status DeleteBlobsInRange(
1342 IndexedDBBackingStore::Transaction* transaction,
1343 int64 database_id,
1344 int64 object_store_id,
1345 const std::string& start_key,
1346 const std::string& end_key,
1347 bool upper_open) {
1348
1349 scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator();
1350 leveldb::Status s = it->Seek(start_key);
1351 for (; s.ok() && it->IsValid() &&
1352 (upper_open ?
1353 CompareKeys(it->Key(), end_key) < 0 :
1354 CompareKeys(it->Key(), end_key) <= 0);
1355 s = it->Next()) {
1356 StringPiece key_piece(it->Key());
1357 std::string user_key =
1358 BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece);
1359 if (!user_key.size()) {
1360 INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
1361 return InternalInconsistencyStatus();
1362 }
1363 transaction->PutBlobInfo(
1364 database_id, object_store_id, user_key, NULL, NULL);
1365 }
1366 return s;
1367 }
1368
1369 // For a whole-object-store deletion, we still use the one-blob-record-at-a-time
1370 // deletion mechanism designed for normal transactions. We could go with the
1371 // nuke-the-whole-directory method used for deleteDatabase if we structured the
1372 // directories accordingly, but that would complicate the kind of info we store
1373 // in the LevelDBTransaction and lengthen paths.
1374 static leveldb::Status DeleteBlobsInObjectStore(
1375 IndexedDBBackingStore::Transaction* transaction,
1376 int64 database_id,
1377 int64 object_store_id) {
1378 std::string start_key, end_key;
1379 start_key =
1380 BlobEntryKey::EncodeMinKeyForObjectStore(database_id, object_store_id);
1381 end_key =
1382 BlobEntryKey::EncodeStopKeyForObjectStore(database_id, object_store_id);
1383 return DeleteBlobsInRange(transaction, database_id, object_store_id,
1384 start_key, end_key, true);
1385 }
1386
1172 leveldb::Status IndexedDBBackingStore::DeleteDatabase( 1387 leveldb::Status IndexedDBBackingStore::DeleteDatabase(
1173 const base::string16& name) { 1388 const base::string16& name) {
1174 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); 1389 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
1175 scoped_ptr<LevelDBDirectTransaction> transaction = 1390 scoped_ptr<LevelDBDirectTransaction> transaction =
1176 LevelDBDirectTransaction::Create(db_.get()); 1391 LevelDBDirectTransaction::Create(db_.get());
1177 1392
1393 leveldb::Status s;
1394 s = CleanUpBlobJournal(BlobJournalKey::Encode());
1395 if (!s.ok())
1396 return s;
1397
1178 IndexedDBDatabaseMetadata metadata; 1398 IndexedDBDatabaseMetadata metadata;
1179 bool success = false; 1399 bool success = false;
1180 leveldb::Status s = GetIDBDatabaseMetaData(name, &metadata, &success); 1400 s = GetIDBDatabaseMetaData(name, &metadata, &success);
1181 if (!s.ok()) 1401 if (!s.ok())
1182 return s; 1402 return s;
1183 if (!success) 1403 if (!success)
1184 return leveldb::Status::OK(); 1404 return leveldb::Status::OK();
1185 1405
1186 const std::string start_key = DatabaseMetaDataKey::Encode( 1406 const std::string start_key = DatabaseMetaDataKey::Encode(
1187 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); 1407 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME);
1188 const std::string stop_key = DatabaseMetaDataKey::Encode( 1408 const std::string stop_key = DatabaseMetaDataKey::Encode(
1189 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); 1409 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME);
1190 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1410 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
1191 for (s = it->Seek(start_key); 1411 for (s = it->Seek(start_key);
1192 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 1412 s.ok() && it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
1193 s = it->Next()) 1413 s = it->Next())
1194 transaction->Remove(it->Key()); 1414 transaction->Remove(it->Key());
1195 if (!s.ok()) { 1415 if (!s.ok()) {
1196 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); 1416 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
1197 return s; 1417 return s;
1198 } 1418 }
1199 1419
1200 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); 1420 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
1201 transaction->Remove(key); 1421 transaction->Remove(key);
1202 1422
1203 // TODO(ericu): Put the real calls to the blob journal code here. For now, 1423 bool need_cleanup = false;
1204 // I've inserted fake calls so that we don't get "you didn't use this static 1424 if (active_blob_registry()->MarkDeletedCheckIfUsed(
1205 // function" compiler errors. 1425 metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) {
1206 if (false) { 1426 s = MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id);
1207 scoped_refptr<LevelDBTransaction> fake_transaction = 1427 if (!s.ok())
1208 new LevelDBTransaction(NULL); 1428 return s;
1209 BlobJournalType fake_journal; 1429 } else {
1210 MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id);
1211 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id); 1430 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id);
1212 MergeBlobsIntoLiveBlobJournal(fake_transaction.get(), fake_journal); 1431 need_cleanup = true;
1213 } 1432 }
1214 1433
1215 s = transaction->Commit(); 1434 s = transaction->Commit();
1216 if (!s.ok()) { 1435 if (!s.ok()) {
1217 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE); 1436 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_DATABASE);
1218 return s; 1437 return s;
1219 } 1438 }
1439
1440 if (need_cleanup)
1441 CleanUpBlobJournal(BlobJournalKey::Encode());
1442
1220 db_->Compact(start_key, stop_key); 1443 db_->Compact(start_key, stop_key);
1221 return s; 1444 return s;
1222 } 1445 }
1223 1446
1224 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, 1447 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
1225 const std::string& stop_key, 1448 const std::string& stop_key,
1226 int64 object_store_id, 1449 int64 object_store_id,
1227 int64 meta_data_type) { 1450 int64 meta_data_type) {
1228 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1451 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1229 return false; 1452 return false;
1230 1453
1231 StringPiece slice(it->Key()); 1454 StringPiece slice(it->Key());
1232 ObjectStoreMetaDataKey meta_data_key; 1455 ObjectStoreMetaDataKey meta_data_key;
1233 bool ok = ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key); 1456 bool ok =
1457 ObjectStoreMetaDataKey::Decode(&slice, &meta_data_key) && slice.empty();
1234 DCHECK(ok); 1458 DCHECK(ok);
1235 if (meta_data_key.ObjectStoreId() != object_store_id) 1459 if (meta_data_key.ObjectStoreId() != object_store_id)
1236 return false; 1460 return false;
1237 if (meta_data_key.MetaDataType() != meta_data_type) 1461 if (meta_data_key.MetaDataType() != meta_data_type)
1238 return false; 1462 return false;
1239 return true; 1463 return ok;
1240 } 1464 }
1241 1465
1242 // TODO(jsbell): This should do some error handling rather than 1466 // TODO(jsbell): This should do some error handling rather than
1243 // plowing ahead when bad data is encountered. 1467 // plowing ahead when bad data is encountered.
1244 leveldb::Status IndexedDBBackingStore::GetObjectStores( 1468 leveldb::Status IndexedDBBackingStore::GetObjectStores(
1245 int64 database_id, 1469 int64 database_id,
1246 IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) { 1470 IndexedDBDatabaseMetadata::ObjectStoreMap* object_stores) {
1247 IDB_TRACE("IndexedDBBackingStore::GetObjectStores"); 1471 IDB_TRACE("IndexedDBBackingStore::GetObjectStores");
1248 if (!KeyPrefix::IsValidDatabaseId(database_id)) 1472 if (!KeyPrefix::IsValidDatabaseId(database_id))
1249 return InvalidDBKeyStatus(); 1473 return InvalidDBKeyStatus();
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1518 &found); 1742 &found);
1519 if (!s.ok()) { 1743 if (!s.ok()) {
1520 INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE); 1744 INTERNAL_READ_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1521 return s; 1745 return s;
1522 } 1746 }
1523 if (!found) { 1747 if (!found) {
1524 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE); 1748 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1525 return InternalInconsistencyStatus(); 1749 return InternalInconsistencyStatus();
1526 } 1750 }
1527 1751
1528 s = DeleteRange( 1752 s = DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1753 if (!s.ok()) {
1754 INTERNAL_CONSISTENCY_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1755 return s;
1756 }
1757
1758 s = DeleteRangeByKeys(
1529 leveldb_transaction, 1759 leveldb_transaction,
1530 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), 1760 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
1531 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1761 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id),
1762 true);
1532 1763
1533 if (s.ok()) { 1764 if (s.ok()) {
1534 leveldb_transaction->Remove( 1765 leveldb_transaction->Remove(
1535 ObjectStoreNamesKey::Encode(database_id, object_store_name)); 1766 ObjectStoreNamesKey::Encode(database_id, object_store_name));
1536 1767
1537 s = DeleteRange( 1768 s = DeleteRangeByKeys(
1538 leveldb_transaction, 1769 leveldb_transaction,
1539 IndexFreeListKey::Encode(database_id, object_store_id, 0), 1770 IndexFreeListKey::Encode(database_id, object_store_id, 0),
1540 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); 1771 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id),
1772 true);
1541 } 1773 }
1542 1774
1543 if (s.ok()) { 1775 if (s.ok()) {
1544 s = DeleteRange( 1776 s = DeleteRangeByKeys(
1545 leveldb_transaction, 1777 leveldb_transaction,
1546 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), 1778 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
1547 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1779 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id),
1780 true);
1548 } 1781 }
1549 1782
1550 if (!s.ok()) { 1783 if (!s.ok()) {
1551 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE); 1784 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_OBJECT_STORE);
1552 return s; 1785 return s;
1553 } 1786 }
1554 1787
1555 return ClearObjectStore(transaction, database_id, object_store_id); 1788 return ClearObjectStore(transaction, database_id, object_store_id);
1556 } 1789 }
1557 1790
(...skipping 28 matching lines...) Expand all
1586 } 1819 }
1587 1820
1588 int64 version; 1821 int64 version;
1589 StringPiece slice(data); 1822 StringPiece slice(data);
1590 if (!DecodeVarInt(&slice, &version)) { 1823 if (!DecodeVarInt(&slice, &version)) {
1591 INTERNAL_READ_ERROR_UNTESTED(GET_RECORD); 1824 INTERNAL_READ_ERROR_UNTESTED(GET_RECORD);
1592 return InternalInconsistencyStatus(); 1825 return InternalInconsistencyStatus();
1593 } 1826 }
1594 1827
1595 record->bits = slice.as_string(); 1828 record->bits = slice.as_string();
1596 return s; 1829 return transaction->GetBlobInfoForRecord(database_id, leveldb_key, record);
1597 } 1830 }
1598 1831
1599 WARN_UNUSED_RESULT static leveldb::Status GetNewVersionNumber( 1832 WARN_UNUSED_RESULT static leveldb::Status GetNewVersionNumber(
1600 LevelDBTransaction* transaction, 1833 LevelDBTransaction* transaction,
1601 int64 database_id, 1834 int64 database_id,
1602 int64 object_store_id, 1835 int64 object_store_id,
1603 int64* new_version_number) { 1836 int64* new_version_number) {
1604 const std::string last_version_key = ObjectStoreMetaDataKey::Encode( 1837 const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
1605 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); 1838 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
1606 1839
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 int64 database_id, 1913 int64 database_id,
1681 int64 object_store_id) { 1914 int64 object_store_id) {
1682 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); 1915 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
1683 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1916 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1684 return InvalidDBKeyStatus(); 1917 return InvalidDBKeyStatus();
1685 const std::string start_key = 1918 const std::string start_key =
1686 KeyPrefix(database_id, object_store_id).Encode(); 1919 KeyPrefix(database_id, object_store_id).Encode();
1687 const std::string stop_key = 1920 const std::string stop_key =
1688 KeyPrefix(database_id, object_store_id + 1).Encode(); 1921 KeyPrefix(database_id, object_store_id + 1).Encode();
1689 1922
1690 leveldb::Status s = 1923 leveldb::Status s = DeleteRangeByKeys(
1691 DeleteRange(transaction->transaction(), start_key, stop_key); 1924 transaction->transaction(), start_key, stop_key, true);
1692 if (!s.ok()) 1925 if (!s.ok()) {
1693 INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE); 1926 INTERNAL_WRITE_ERROR(CLEAR_OBJECT_STORE);
1694 return s; 1927 return s;
1928 }
1929 return DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1695 } 1930 }
1696 1931
1697 leveldb::Status IndexedDBBackingStore::DeleteRecord( 1932 leveldb::Status IndexedDBBackingStore::DeleteRecord(
1698 IndexedDBBackingStore::Transaction* transaction, 1933 IndexedDBBackingStore::Transaction* transaction,
1699 int64 database_id, 1934 int64 database_id,
1700 int64 object_store_id, 1935 int64 object_store_id,
1701 const RecordIdentifier& record_identifier) { 1936 const RecordIdentifier& record_identifier) {
1702 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); 1937 IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
1703 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1938 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1704 return InvalidDBKeyStatus(); 1939 return InvalidDBKeyStatus();
1705 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 1940 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1706 1941
1707 const std::string object_store_data_key = ObjectStoreDataKey::Encode( 1942 const std::string object_store_data_key = ObjectStoreDataKey::Encode(
1708 database_id, object_store_id, record_identifier.primary_key()); 1943 database_id, object_store_id, record_identifier.primary_key());
1709 leveldb_transaction->Remove(object_store_data_key); 1944 leveldb_transaction->Remove(object_store_data_key);
1710 transaction->PutBlobInfo( 1945 transaction->PutBlobInfo(
1711 database_id, object_store_id, object_store_data_key, NULL, NULL); 1946 database_id, object_store_id, object_store_data_key, NULL, NULL);
1712 1947
1713 const std::string exists_entry_key = ExistsEntryKey::Encode( 1948 const std::string exists_entry_key = ExistsEntryKey::Encode(
1714 database_id, object_store_id, record_identifier.primary_key()); 1949 database_id, object_store_id, record_identifier.primary_key());
1715 leveldb_transaction->Remove(exists_entry_key); 1950 leveldb_transaction->Remove(exists_entry_key);
1716 return leveldb::Status::OK(); 1951 return leveldb::Status::OK();
1717 } 1952 }
1718 1953
1954 // TODO(ericu): Exists entries as well? Anything to do index-wise?
1955 leveldb::Status IndexedDBBackingStore::DeleteRange(
1956 IndexedDBBackingStore::Transaction* transaction,
1957 int64 database_id,
1958 int64 object_store_id,
1959 const IndexedDBKeyRange& key_range) {
1960 leveldb::Status s;
1961 scoped_ptr<IndexedDBBackingStore::Cursor> start_cursor =
1962 OpenObjectStoreCursor(transaction,
1963 database_id,
1964 object_store_id,
1965 key_range,
1966 indexed_db::CURSOR_NEXT,
1967 &s);
1968 if (!s.ok())
1969 return s;
1970 if (!start_cursor)
1971 return leveldb::Status::OK(); // Empty range == delete success.
1972
1973 scoped_ptr<IndexedDBBackingStore::Cursor> end_cursor =
1974 OpenObjectStoreCursor(transaction,
1975 database_id,
1976 object_store_id,
1977 key_range,
1978 indexed_db::CURSOR_PREV,
1979 &s);
1980
1981 if (!s.ok())
1982 return s;
1983 if (!end_cursor)
1984 return leveldb::Status::OK(); // Empty range == delete success.
1985 // TODO(ericu): Is that right? Or perhaps only in single-key ranges, in which
1986 // case we should give an error here and check differently above?
1987
1988 BlobEntryKey start_blob_key, end_blob_key;
1989
1990 std::string start_key = ObjectStoreDataKey::Encode(
1991 database_id, object_store_id, start_cursor->key());
1992 base::StringPiece start_key_piece(start_key);
1993 if (!BlobEntryKey::FromObjectStoreDataKey(&start_key_piece, &start_blob_key))
1994 return InternalInconsistencyStatus();
1995 std::string end_key = ObjectStoreDataKey::Encode(
1996 database_id, object_store_id, end_cursor->key());
1997 base::StringPiece end_key_piece(end_key);
1998 if (!BlobEntryKey::FromObjectStoreDataKey(&end_key_piece, &end_blob_key))
1999 return InternalInconsistencyStatus();
2000
2001 s = DeleteBlobsInRange(transaction, database_id, object_store_id,
2002 start_blob_key.Encode(), end_blob_key.Encode(), false);
2003 if (!s.ok())
2004 return s;
2005 s = DeleteRangeByKeys(transaction->transaction(), start_key, end_key, false);
2006 if (!s.ok())
2007 return s;
2008 start_key = ExistsEntryKey::Encode(
2009 database_id, object_store_id, start_cursor->key());
2010 end_key = ExistsEntryKey::Encode(
2011 database_id, object_store_id, end_cursor->key());
2012 return DeleteRangeByKeys(
2013 transaction->transaction(), start_key, end_key, false);
2014 }
2015
1719 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( 2016 leveldb::Status IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
1720 IndexedDBBackingStore::Transaction* transaction, 2017 IndexedDBBackingStore::Transaction* transaction,
1721 int64 database_id, 2018 int64 database_id,
1722 int64 object_store_id, 2019 int64 object_store_id,
1723 int64* key_generator_current_number) { 2020 int64* key_generator_current_number) {
1724 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 2021 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1725 return InvalidDBKeyStatus(); 2022 return InvalidDBKeyStatus();
1726 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 2023 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1727 2024
1728 const std::string key_generator_current_number_key = 2025 const std::string key_generator_current_number_key =
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
2283 } else { 2580 } else {
2284 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key)); 2581 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2285 if (!RemoveBlobFile(database_id, blob_key)) 2582 if (!RemoveBlobFile(database_id, blob_key))
2286 return IOErrorStatus(); 2583 return IOErrorStatus();
2287 } 2584 }
2288 } 2585 }
2289 ClearBlobJournal(journal_transaction.get(), level_db_key); 2586 ClearBlobJournal(journal_transaction.get(), level_db_key);
2290 return journal_transaction->Commit(); 2587 return journal_transaction->Commit();
2291 } 2588 }
2292 2589
2590 leveldb::Status IndexedDBBackingStore::Transaction::GetBlobInfoForRecord(
2591 int64 database_id,
2592 const std::string& object_store_data_key,
2593 IndexedDBValue* value) {
2594 BlobChangeRecord* change_record = NULL;
2595 BlobChangeMap::const_iterator blob_iter =
2596 blob_change_map_.find(object_store_data_key);
2597 if (blob_iter != blob_change_map_.end()) {
2598 change_record = blob_iter->second;
2599 } else {
2600 blob_iter = incognito_blob_map_.find(object_store_data_key);
2601 if (blob_iter != incognito_blob_map_.end())
2602 change_record = blob_iter->second;
2603 }
2604 if (change_record) {
2605 // Either we haven't written the blob to disk yet or we're in incognito
2606 // mode, so we have to send back the one they sent us. This change record
2607 // includes the original UUID.
2608 value->blob_info = change_record->blob_info();
2609 return leveldb::Status::OK();
2610 }
2611
2612 BlobEntryKey blob_entry_key;
2613 StringPiece leveldb_key_piece(object_store_data_key);
2614 if (!BlobEntryKey::FromObjectStoreDataKey(&leveldb_key_piece,
2615 &blob_entry_key)) {
2616 NOTREACHED();
2617 return InternalInconsistencyStatus();
2618 }
2619 scoped_ptr<LevelDBIterator> it = transaction()->CreateIterator();
2620 std::string encoded_key = blob_entry_key.Encode();
2621 leveldb::Status s = it->Seek(encoded_key);
2622 if (!s.ok())
2623 return s;
2624 if (it->IsValid() && CompareKeys(it->Key(), encoded_key) == 0) {
2625 if (!DecodeBlobData(it->Value().as_string(), &value->blob_info)) {
2626 INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD);
2627 return InternalInconsistencyStatus();
2628 }
2629 std::vector<IndexedDBBlobInfo>::iterator iter;
2630 for (iter = value->blob_info.begin(); iter != value->blob_info.end();
2631 ++iter) {
2632 iter->set_file_path(
2633 backing_store_->GetBlobFileName(database_id, iter->key()));
2634 iter->set_mark_used_callback(
2635 backing_store_->active_blob_registry()->GetAddBlobRefCallback(
2636 database_id, iter->key()));
2637 iter->set_release_callback(
2638 backing_store_->active_blob_registry()->GetFinalReleaseCallback(
2639 database_id, iter->key()));
2640 if (iter->is_file()) {
2641 base::File::Info info;
2642 if (base::GetFileInfo(iter->file_path(), &info)) {
2643 // This should always work, but it isn't fatal if it doesn't; it just
2644 // means a potential slow synchronous call from the renderer later.
2645 iter->set_last_modified(info.last_modified);
2646 iter->set_size(info.size);
2647 }
2648 }
2649 }
2650 }
2651 return leveldb::Status::OK();
2652 }
2653
2293 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() { 2654 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() {
2294 CleanUpBlobJournal(BlobJournalKey::Encode()); 2655 CleanUpBlobJournal(BlobJournalKey::Encode());
2295 } 2656 }
2296 2657
2297 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( 2658 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
2298 LevelDBTransaction* transaction, 2659 LevelDBTransaction* transaction,
2299 int64 database_id, 2660 int64 database_id,
2300 int64 object_store_id, 2661 int64 object_store_id,
2301 int64 index_id) { 2662 int64 index_id) {
2302 int64 max_index_id = -1; 2663 int64 max_index_id = -1;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2363 int64 index_id) { 2724 int64 index_id) {
2364 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); 2725 IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
2365 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) 2726 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
2366 return InvalidDBKeyStatus(); 2727 return InvalidDBKeyStatus();
2367 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 2728 LevelDBTransaction* leveldb_transaction = transaction->transaction();
2368 2729
2369 const std::string index_meta_data_start = 2730 const std::string index_meta_data_start =
2370 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); 2731 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
2371 const std::string index_meta_data_end = 2732 const std::string index_meta_data_end =
2372 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2733 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
2373 leveldb::Status s = DeleteRange( 2734 leveldb::Status s = DeleteRangeByKeys(
2374 leveldb_transaction, index_meta_data_start, index_meta_data_end); 2735 leveldb_transaction, index_meta_data_start, index_meta_data_end, true);
2375 2736
2376 if (s.ok()) { 2737 if (s.ok()) {
2377 const std::string index_data_start = 2738 const std::string index_data_start =
2378 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); 2739 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
2379 const std::string index_data_end = 2740 const std::string index_data_end =
2380 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2741 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
2381 s = DeleteRange(leveldb_transaction, index_data_start, index_data_end); 2742 s = DeleteRangeByKeys(
2743 leveldb_transaction, index_data_start, index_data_end, true);
2382 } 2744 }
2383 2745
2384 if (!s.ok()) 2746 if (!s.ok())
2385 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX); 2747 INTERNAL_WRITE_ERROR_UNTESTED(DELETE_INDEX);
2386 2748
2387 return s; 2749 return s;
2388 } 2750 }
2389 2751
2390 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord( 2752 leveldb::Status IndexedDBBackingStore::PutIndexDataForRecord(
2391 IndexedDBBackingStore::Transaction* transaction, 2753 IndexedDBBackingStore::Transaction* transaction,
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
2606 2968
2607 StringPiece slice(found_encoded_primary_key); 2969 StringPiece slice(found_encoded_primary_key);
2608 if (DecodeIDBKey(&slice, found_primary_key) && slice.empty()) 2970 if (DecodeIDBKey(&slice, found_primary_key) && slice.empty())
2609 return s; 2971 return s;
2610 else 2972 else
2611 return InvalidDBKeyStatus(); 2973 return InvalidDBKeyStatus();
2612 } 2974 }
2613 2975
2614 IndexedDBBackingStore::Cursor::Cursor( 2976 IndexedDBBackingStore::Cursor::Cursor(
2615 const IndexedDBBackingStore::Cursor* other) 2977 const IndexedDBBackingStore::Cursor* other)
2616 : transaction_(other->transaction_), 2978 : backing_store_(other->backing_store_),
2979 transaction_(other->transaction_),
2980 database_id_(other->database_id_),
2617 cursor_options_(other->cursor_options_), 2981 cursor_options_(other->cursor_options_),
2618 current_key_(new IndexedDBKey(*other->current_key_)) { 2982 current_key_(new IndexedDBKey(*other->current_key_)) {
2619 if (other->iterator_) { 2983 if (other->iterator_) {
2620 iterator_ = transaction_->CreateIterator(); 2984 iterator_ = transaction_->transaction()->CreateIterator();
2621 2985
2622 if (other->iterator_->IsValid()) { 2986 if (other->iterator_->IsValid()) {
2623 leveldb::Status s = iterator_->Seek(other->iterator_->Key()); 2987 leveldb::Status s = iterator_->Seek(other->iterator_->Key());
2624 // TODO(cmumford): Handle this error (crbug.com/363397) 2988 // TODO(cmumford): Handle this error (crbug.com/363397)
2625 DCHECK(iterator_->IsValid()); 2989 DCHECK(iterator_->IsValid());
2626 } 2990 }
2627 } 2991 }
2628 } 2992 }
2629 2993
2630 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction, 2994 IndexedDBBackingStore::Cursor::Cursor(
2631 const CursorOptions& cursor_options) 2995 scoped_refptr<IndexedDBBackingStore> backing_store,
2632 : transaction_(transaction), cursor_options_(cursor_options) {} 2996 IndexedDBBackingStore::Transaction* transaction,
2997 int64 database_id,
2998 const CursorOptions& cursor_options)
2999 : backing_store_(backing_store),
3000 transaction_(transaction),
3001 database_id_(database_id),
3002 cursor_options_(cursor_options) {
3003 }
2633 IndexedDBBackingStore::Cursor::~Cursor() {} 3004 IndexedDBBackingStore::Cursor::~Cursor() {}
2634 3005
2635 bool IndexedDBBackingStore::Cursor::FirstSeek(leveldb::Status* s) { 3006 bool IndexedDBBackingStore::Cursor::FirstSeek(leveldb::Status* s) {
2636 iterator_ = transaction_->CreateIterator(); 3007 iterator_ = transaction_->transaction()->CreateIterator();
2637 if (cursor_options_.forward) 3008 if (cursor_options_.forward)
2638 *s = iterator_->Seek(cursor_options_.low_key); 3009 *s = iterator_->Seek(cursor_options_.low_key);
2639 else 3010 else
2640 *s = iterator_->Seek(cursor_options_.high_key); 3011 *s = iterator_->Seek(cursor_options_.high_key);
2641 if (!s->ok()) 3012 if (!s->ok())
2642 return false; 3013 return false;
2643 3014
2644 return Continue(0, READY, s); 3015 return Continue(0, READY, s);
2645 } 3016 }
2646 3017
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2809 } 3180 }
2810 3181
2811 const IndexedDBBackingStore::RecordIdentifier& 3182 const IndexedDBBackingStore::RecordIdentifier&
2812 IndexedDBBackingStore::Cursor::record_identifier() const { 3183 IndexedDBBackingStore::Cursor::record_identifier() const {
2813 return record_identifier_; 3184 return record_identifier_;
2814 } 3185 }
2815 3186
2816 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { 3187 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
2817 public: 3188 public:
2818 ObjectStoreKeyCursorImpl( 3189 ObjectStoreKeyCursorImpl(
2819 LevelDBTransaction* transaction, 3190 scoped_refptr<IndexedDBBackingStore> backing_store,
3191 IndexedDBBackingStore::Transaction* transaction,
3192 int64 database_id,
2820 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3193 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2821 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3194 : IndexedDBBackingStore::Cursor(backing_store,
3195 transaction,
3196 database_id,
3197 cursor_options) {}
2822 3198
2823 virtual Cursor* Clone() OVERRIDE { 3199 virtual Cursor* Clone() OVERRIDE {
2824 return new ObjectStoreKeyCursorImpl(this); 3200 return new ObjectStoreKeyCursorImpl(this);
2825 } 3201 }
2826 3202
2827 // IndexedDBBackingStore::Cursor 3203 // IndexedDBBackingStore::Cursor
2828 virtual IndexedDBValue* value() OVERRIDE { 3204 virtual IndexedDBValue* value() OVERRIDE {
2829 NOTREACHED(); 3205 NOTREACHED();
2830 return NULL; 3206 return NULL;
2831 } 3207 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2868 std::string encoded_key; 3244 std::string encoded_key;
2869 EncodeIDBKey(*current_key_, &encoded_key); 3245 EncodeIDBKey(*current_key_, &encoded_key);
2870 record_identifier_.Reset(encoded_key, version); 3246 record_identifier_.Reset(encoded_key, version);
2871 3247
2872 return true; 3248 return true;
2873 } 3249 }
2874 3250
2875 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { 3251 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
2876 public: 3252 public:
2877 ObjectStoreCursorImpl( 3253 ObjectStoreCursorImpl(
2878 LevelDBTransaction* transaction, 3254 scoped_refptr<IndexedDBBackingStore> backing_store,
3255 IndexedDBBackingStore::Transaction* transaction,
3256 int64 database_id,
2879 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3257 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2880 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3258 : IndexedDBBackingStore::Cursor(backing_store,
3259 transaction,
3260 database_id,
3261 cursor_options) {}
2881 3262
2882 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); } 3263 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
2883 3264
2884 // IndexedDBBackingStore::Cursor 3265 // IndexedDBBackingStore::Cursor
2885 virtual IndexedDBValue* value() OVERRIDE { return &current_value_; } 3266 virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
2886 virtual bool LoadCurrentRow() OVERRIDE; 3267 virtual bool LoadCurrentRow() OVERRIDE;
2887 3268
2888 protected: 3269 protected:
2889 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 3270 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2890 return ObjectStoreDataKey::Encode( 3271 return ObjectStoreDataKey::Encode(
(...skipping 28 matching lines...) Expand all
2919 if (!DecodeVarInt(&value_slice, &version)) { 3300 if (!DecodeVarInt(&value_slice, &version)) {
2920 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3301 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
2921 return false; 3302 return false;
2922 } 3303 }
2923 3304
2924 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. 3305 // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
2925 std::string encoded_key; 3306 std::string encoded_key;
2926 EncodeIDBKey(*current_key_, &encoded_key); 3307 EncodeIDBKey(*current_key_, &encoded_key);
2927 record_identifier_.Reset(encoded_key, version); 3308 record_identifier_.Reset(encoded_key, version);
2928 3309
3310 if (!transaction_->GetBlobInfoForRecord(database_id_,
3311 iterator_->Key().as_string(),
3312 &current_value_).ok()) {
3313 return false;
3314 }
2929 current_value_.bits = value_slice.as_string(); 3315 current_value_.bits = value_slice.as_string();
2930 return true; 3316 return true;
2931 } 3317 }
2932 3318
2933 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { 3319 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
2934 public: 3320 public:
2935 IndexKeyCursorImpl( 3321 IndexKeyCursorImpl(
2936 LevelDBTransaction* transaction, 3322 scoped_refptr<IndexedDBBackingStore> backing_store,
3323 IndexedDBBackingStore::Transaction* transaction,
3324 int64 database_id,
2937 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3325 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2938 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3326 : IndexedDBBackingStore::Cursor(backing_store,
3327 transaction,
3328 database_id,
3329 cursor_options) {}
2939 3330
2940 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); } 3331 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
2941 3332
2942 // IndexedDBBackingStore::Cursor 3333 // IndexedDBBackingStore::Cursor
2943 virtual IndexedDBValue* value() OVERRIDE { 3334 virtual IndexedDBValue* value() OVERRIDE {
2944 NOTREACHED(); 3335 NOTREACHED();
2945 return NULL; 3336 return NULL;
2946 } 3337 }
2947 virtual const IndexedDBKey& primary_key() const OVERRIDE { 3338 virtual const IndexedDBKey& primary_key() const OVERRIDE {
2948 return *primary_key_; 3339 return *primary_key_;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3001 return false; 3392 return false;
3002 } 3393 }
3003 3394
3004 std::string primary_leveldb_key = 3395 std::string primary_leveldb_key =
3005 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), 3396 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
3006 index_data_key.ObjectStoreId(), 3397 index_data_key.ObjectStoreId(),
3007 *primary_key_); 3398 *primary_key_);
3008 3399
3009 std::string result; 3400 std::string result;
3010 bool found = false; 3401 bool found = false;
3011 leveldb::Status s = transaction_->Get(primary_leveldb_key, &result, &found); 3402 leveldb::Status s =
3403 transaction_->transaction()->Get(primary_leveldb_key, &result, &found);
3012 if (!s.ok()) { 3404 if (!s.ok()) {
3013 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3405 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3014 return false; 3406 return false;
3015 } 3407 }
3016 if (!found) { 3408 if (!found) {
3017 transaction_->Remove(iterator_->Key()); 3409 transaction_->transaction()->Remove(iterator_->Key());
3018 return false; 3410 return false;
3019 } 3411 }
3020 if (!result.size()) { 3412 if (!result.size()) {
3021 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3413 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3022 return false; 3414 return false;
3023 } 3415 }
3024 3416
3025 int64 object_store_data_version; 3417 int64 object_store_data_version;
3026 slice = StringPiece(result); 3418 slice = StringPiece(result);
3027 if (!DecodeVarInt(&slice, &object_store_data_version)) { 3419 if (!DecodeVarInt(&slice, &object_store_data_version)) {
3028 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3420 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3029 return false; 3421 return false;
3030 } 3422 }
3031 3423
3032 if (object_store_data_version != index_data_version) { 3424 if (object_store_data_version != index_data_version) {
3033 transaction_->Remove(iterator_->Key()); 3425 transaction_->transaction()->Remove(iterator_->Key());
3034 return false; 3426 return false;
3035 } 3427 }
3036 3428
3037 return true; 3429 return true;
3038 } 3430 }
3039 3431
3040 class IndexCursorImpl : public IndexedDBBackingStore::Cursor { 3432 class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
3041 public: 3433 public:
3042 IndexCursorImpl( 3434 IndexCursorImpl(
3043 LevelDBTransaction* transaction, 3435 scoped_refptr<IndexedDBBackingStore> backing_store,
3436 IndexedDBBackingStore::Transaction* transaction,
3437 int64 database_id,
3044 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3438 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
3045 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3439 : IndexedDBBackingStore::Cursor(backing_store,
3440 transaction,
3441 database_id,
3442 cursor_options) {}
3046 3443
3047 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); } 3444 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
3048 3445
3049 // IndexedDBBackingStore::Cursor 3446 // IndexedDBBackingStore::Cursor
3050 virtual IndexedDBValue* value() OVERRIDE { return &current_value_; } 3447 virtual IndexedDBValue* value() OVERRIDE { return &current_value_; }
3051 virtual const IndexedDBKey& primary_key() const OVERRIDE { 3448 virtual const IndexedDBKey& primary_key() const OVERRIDE {
3052 return *primary_key_; 3449 return *primary_key_;
3053 } 3450 }
3054 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier() 3451 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
3055 const OVERRIDE { 3452 const OVERRIDE {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3101 int64 index_data_version; 3498 int64 index_data_version;
3102 if (!DecodeVarInt(&slice, &index_data_version)) { 3499 if (!DecodeVarInt(&slice, &index_data_version)) {
3103 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3500 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3104 return false; 3501 return false;
3105 } 3502 }
3106 if (!DecodeIDBKey(&slice, &primary_key_)) { 3503 if (!DecodeIDBKey(&slice, &primary_key_)) {
3107 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3504 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3108 return false; 3505 return false;
3109 } 3506 }
3110 3507
3508 DCHECK_EQ(index_data_key.DatabaseId(), database_id_);
3111 primary_leveldb_key_ = 3509 primary_leveldb_key_ =
3112 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), 3510 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
3113 index_data_key.ObjectStoreId(), 3511 index_data_key.ObjectStoreId(),
3114 *primary_key_); 3512 *primary_key_);
3115 3513
3116 std::string result; 3514 std::string result;
3117 bool found = false; 3515 bool found = false;
3118 leveldb::Status s = transaction_->Get(primary_leveldb_key_, &result, &found); 3516 leveldb::Status s =
3517 transaction_->transaction()->Get(primary_leveldb_key_, &result, &found);
3119 if (!s.ok()) { 3518 if (!s.ok()) {
3120 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3519 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3121 return false; 3520 return false;
3122 } 3521 }
3123 if (!found) { 3522 if (!found) {
3124 transaction_->Remove(iterator_->Key()); 3523 transaction_->transaction()->Remove(iterator_->Key());
3125 return false; 3524 return false;
3126 } 3525 }
3127 if (!result.size()) { 3526 if (!result.size()) {
3128 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3527 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3129 return false; 3528 return false;
3130 } 3529 }
3131 3530
3132 int64 object_store_data_version; 3531 int64 object_store_data_version;
3133 slice = StringPiece(result); 3532 slice = StringPiece(result);
3134 if (!DecodeVarInt(&slice, &object_store_data_version)) { 3533 if (!DecodeVarInt(&slice, &object_store_data_version)) {
3135 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW); 3534 INTERNAL_READ_ERROR_UNTESTED(LOAD_CURRENT_ROW);
3136 return false; 3535 return false;
3137 } 3536 }
3138 3537
3139 if (object_store_data_version != index_data_version) { 3538 if (object_store_data_version != index_data_version) {
3140 transaction_->Remove(iterator_->Key()); 3539 transaction_->transaction()->Remove(iterator_->Key());
3141 return false; 3540 return false;
3142 } 3541 }
3143 3542
3144 current_value_.bits = slice.as_string(); 3543 current_value_.bits = slice.as_string();
3145 return true; 3544 return transaction_->GetBlobInfoForRecord(database_id_,
3545 primary_leveldb_key_,
3546 &current_value_).ok();
3146 } 3547 }
3147 3548
3148 bool ObjectStoreCursorOptions( 3549 bool ObjectStoreCursorOptions(
3149 LevelDBTransaction* transaction, 3550 LevelDBTransaction* transaction,
3150 int64 database_id, 3551 int64 database_id,
3151 int64 object_store_id, 3552 int64 object_store_id,
3152 const IndexedDBKeyRange& range, 3553 const IndexedDBKeyRange& range,
3153 indexed_db::CursorDirection direction, 3554 indexed_db::CursorDirection direction,
3154 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) { 3555 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
3155 cursor_options->database_id = database_id; 3556 cursor_options->database_id = database_id;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
3302 *s = leveldb::Status::OK(); 3703 *s = leveldb::Status::OK();
3303 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3704 LevelDBTransaction* leveldb_transaction = transaction->transaction();
3304 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3705 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3305 if (!ObjectStoreCursorOptions(leveldb_transaction, 3706 if (!ObjectStoreCursorOptions(leveldb_transaction,
3306 database_id, 3707 database_id,
3307 object_store_id, 3708 object_store_id,
3308 range, 3709 range,
3309 direction, 3710 direction,
3310 &cursor_options)) 3711 &cursor_options))
3311 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3712 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3312 scoped_ptr<ObjectStoreCursorImpl> cursor( 3713 scoped_ptr<ObjectStoreCursorImpl> cursor(new ObjectStoreCursorImpl(
3313 new ObjectStoreCursorImpl(leveldb_transaction, cursor_options)); 3714 this, transaction, database_id, cursor_options));
3314 if (!cursor->FirstSeek(s)) 3715 if (!cursor->FirstSeek(s))
3315 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3716 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3316 3717
3317 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3718 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3318 } 3719 }
3319 3720
3320 scoped_ptr<IndexedDBBackingStore::Cursor> 3721 scoped_ptr<IndexedDBBackingStore::Cursor>
3321 IndexedDBBackingStore::OpenObjectStoreKeyCursor( 3722 IndexedDBBackingStore::OpenObjectStoreKeyCursor(
3322 IndexedDBBackingStore::Transaction* transaction, 3723 IndexedDBBackingStore::Transaction* transaction,
3323 int64 database_id, 3724 int64 database_id,
3324 int64 object_store_id, 3725 int64 object_store_id,
3325 const IndexedDBKeyRange& range, 3726 const IndexedDBKeyRange& range,
3326 indexed_db::CursorDirection direction, 3727 indexed_db::CursorDirection direction,
3327 leveldb::Status* s) { 3728 leveldb::Status* s) {
3328 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); 3729 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
3329 *s = leveldb::Status::OK(); 3730 *s = leveldb::Status::OK();
3330 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3731 LevelDBTransaction* leveldb_transaction = transaction->transaction();
3331 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3732 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3332 if (!ObjectStoreCursorOptions(leveldb_transaction, 3733 if (!ObjectStoreCursorOptions(leveldb_transaction,
3333 database_id, 3734 database_id,
3334 object_store_id, 3735 object_store_id,
3335 range, 3736 range,
3336 direction, 3737 direction,
3337 &cursor_options)) 3738 &cursor_options))
3338 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3739 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3339 scoped_ptr<ObjectStoreKeyCursorImpl> cursor( 3740 scoped_ptr<ObjectStoreKeyCursorImpl> cursor(new ObjectStoreKeyCursorImpl(
3340 new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options)); 3741 this, transaction, database_id, cursor_options));
3341 if (!cursor->FirstSeek(s)) 3742 if (!cursor->FirstSeek(s))
3342 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3743 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3343 3744
3344 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3745 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3345 } 3746 }
3346 3747
3347 scoped_ptr<IndexedDBBackingStore::Cursor> 3748 scoped_ptr<IndexedDBBackingStore::Cursor>
3348 IndexedDBBackingStore::OpenIndexKeyCursor( 3749 IndexedDBBackingStore::OpenIndexKeyCursor(
3349 IndexedDBBackingStore::Transaction* transaction, 3750 IndexedDBBackingStore::Transaction* transaction,
3350 int64 database_id, 3751 int64 database_id,
3351 int64 object_store_id, 3752 int64 object_store_id,
3352 int64 index_id, 3753 int64 index_id,
3353 const IndexedDBKeyRange& range, 3754 const IndexedDBKeyRange& range,
3354 indexed_db::CursorDirection direction, 3755 indexed_db::CursorDirection direction,
3355 leveldb::Status* s) { 3756 leveldb::Status* s) {
3356 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); 3757 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
3357 *s = leveldb::Status::OK(); 3758 *s = leveldb::Status::OK();
3358 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3759 LevelDBTransaction* leveldb_transaction = transaction->transaction();
3359 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3760 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3360 if (!IndexCursorOptions(leveldb_transaction, 3761 if (!IndexCursorOptions(leveldb_transaction,
3361 database_id, 3762 database_id,
3362 object_store_id, 3763 object_store_id,
3363 index_id, 3764 index_id,
3364 range, 3765 range,
3365 direction, 3766 direction,
3366 &cursor_options)) 3767 &cursor_options))
3367 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3768 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3368 scoped_ptr<IndexKeyCursorImpl> cursor( 3769 scoped_ptr<IndexKeyCursorImpl> cursor(
3369 new IndexKeyCursorImpl(leveldb_transaction, cursor_options)); 3770 new IndexKeyCursorImpl(this, transaction, database_id, cursor_options));
3370 if (!cursor->FirstSeek(s)) 3771 if (!cursor->FirstSeek(s))
3371 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3772 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3372 3773
3373 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3774 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3374 } 3775 }
3375 3776
3376 scoped_ptr<IndexedDBBackingStore::Cursor> 3777 scoped_ptr<IndexedDBBackingStore::Cursor>
3377 IndexedDBBackingStore::OpenIndexCursor( 3778 IndexedDBBackingStore::OpenIndexCursor(
3378 IndexedDBBackingStore::Transaction* transaction, 3779 IndexedDBBackingStore::Transaction* transaction,
3379 int64 database_id, 3780 int64 database_id,
3380 int64 object_store_id, 3781 int64 object_store_id,
3381 int64 index_id, 3782 int64 index_id,
3382 const IndexedDBKeyRange& range, 3783 const IndexedDBKeyRange& range,
3383 indexed_db::CursorDirection direction, 3784 indexed_db::CursorDirection direction,
3384 leveldb::Status* s) { 3785 leveldb::Status* s) {
3385 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); 3786 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
3386 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3787 LevelDBTransaction* leveldb_transaction = transaction->transaction();
3387 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3788 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
3388 if (!IndexCursorOptions(leveldb_transaction, 3789 if (!IndexCursorOptions(leveldb_transaction,
3389 database_id, 3790 database_id,
3390 object_store_id, 3791 object_store_id,
3391 index_id, 3792 index_id,
3392 range, 3793 range,
3393 direction, 3794 direction,
3394 &cursor_options)) 3795 &cursor_options))
3395 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3796 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3396 scoped_ptr<IndexCursorImpl> cursor( 3797 scoped_ptr<IndexCursorImpl> cursor(
3397 new IndexCursorImpl(leveldb_transaction, cursor_options)); 3798 new IndexCursorImpl(this, transaction, database_id, cursor_options));
3398 if (!cursor->FirstSeek(s)) 3799 if (!cursor->FirstSeek(s))
3399 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3800 return scoped_ptr<IndexedDBBackingStore::Cursor>();
3400 3801
3401 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3802 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
3402 } 3803 }
3403 3804
3404 IndexedDBBackingStore::Transaction::Transaction( 3805 IndexedDBBackingStore::Transaction::Transaction(
3405 IndexedDBBackingStore* backing_store) 3806 IndexedDBBackingStore* backing_store)
3406 : backing_store_(backing_store), database_id_(-1) { 3807 : backing_store_(backing_store), database_id_(-1) {
3407 } 3808 }
(...skipping 12 matching lines...) Expand all
3420 3821
3421 // If incognito, this snapshots blobs just as the above transaction_ 3822 // If incognito, this snapshots blobs just as the above transaction_
3422 // constructor snapshots the leveldb. 3823 // constructor snapshots the leveldb.
3423 BlobChangeMap::const_iterator iter; 3824 BlobChangeMap::const_iterator iter;
3424 for (iter = backing_store_->incognito_blob_map_.begin(); 3825 for (iter = backing_store_->incognito_blob_map_.begin();
3425 iter != backing_store_->incognito_blob_map_.end(); 3826 iter != backing_store_->incognito_blob_map_.end();
3426 ++iter) 3827 ++iter)
3427 incognito_blob_map_[iter->first] = iter->second->Clone().release(); 3828 incognito_blob_map_[iter->first] = iter->second->Clone().release();
3428 } 3829 }
3429 3830
3430 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 3831 static GURL getURLFromUUID(const string& uuid) {
3431 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3832 return GURL("blob:uuid/" + uuid);
3432 DCHECK(transaction_.get()); 3833 }
3433 leveldb::Status s = transaction_->Commit(); 3834
3835 leveldb::Status IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
3836 BlobEntryKeyValuePairVec* new_blob_entries,
3837 WriteDescriptorVec* new_files_to_write) {
3838 if (backing_store_->is_incognito())
3839 return leveldb::Status::OK();
3840
3841 BlobChangeMap::iterator iter = blob_change_map_.begin();
3842 new_blob_entries->clear();
3843 new_files_to_write->clear();
3844 if (iter != blob_change_map_.end()) {
3845 // Create LevelDBTransaction for the name generator seed and add-journal.
3846 scoped_refptr<LevelDBTransaction> pre_transaction =
3847 new LevelDBTransaction(backing_store_->db_.get());
3848 BlobJournalType journal;
3849 for (; iter != blob_change_map_.end(); ++iter) {
3850 std::vector<IndexedDBBlobInfo>::iterator info_iter;
3851 std::vector<IndexedDBBlobInfo*> new_blob_keys;
3852 for (info_iter = iter->second->mutable_blob_info().begin();
3853 info_iter != iter->second->mutable_blob_info().end();
3854 ++info_iter) {
3855 int64 next_blob_key = -1;
3856 bool result = GetBlobKeyGeneratorCurrentNumber(
3857 pre_transaction.get(), database_id_, &next_blob_key);
3858 if (!result || next_blob_key < 0)
3859 return InternalInconsistencyStatus();
3860 BlobJournalEntryType journal_entry =
3861 std::make_pair(database_id_, next_blob_key);
3862 journal.push_back(journal_entry);
3863 if (info_iter->is_file()) {
3864 new_files_to_write->push_back(
3865 WriteDescriptor(info_iter->file_path(), next_blob_key));
3866 } else {
3867 new_files_to_write->push_back(WriteDescriptor(
3868 getURLFromUUID(info_iter->uuid()), next_blob_key));
3869 }
3870 info_iter->set_key(next_blob_key);
3871 new_blob_keys.push_back(&*info_iter);
3872 result = UpdateBlobKeyGeneratorCurrentNumber(
3873 pre_transaction.get(), database_id_, next_blob_key + 1);
3874 if (!result)
3875 return InternalInconsistencyStatus();
3876 }
3877 BlobEntryKey blob_entry_key;
3878 StringPiece key_piece(iter->second->key());
3879 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3880 NOTREACHED();
3881 return InternalInconsistencyStatus();
3882 }
3883 new_blob_entries->push_back(
3884 std::make_pair(blob_entry_key, EncodeBlobData(new_blob_keys)));
3885 }
3886 UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal);
3887 if (!pre_transaction->Commit().ok())
3888 return InternalInconsistencyStatus();
3889 }
3890 return leveldb::Status::OK();
3891 }
3892
3893 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
3894 if (backing_store_->is_incognito())
3895 return true;
3896
3897 BlobChangeMap::const_iterator iter = blob_change_map_.begin();
3898 // Look up all old files to remove as part of the transaction, store their
3899 // names in blobs_to_remove_, and remove their old blob data entries.
3900 if (iter != blob_change_map_.end()) {
3901 scoped_ptr<LevelDBIterator> db_iter = transaction_->CreateIterator();
3902 for (; iter != blob_change_map_.end(); ++iter) {
3903 BlobEntryKey blob_entry_key;
3904 StringPiece key_piece(iter->second->key());
3905 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3906 NOTREACHED();
3907 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3908 transaction_ = NULL;
3909 return false;
3910 }
3911 if (database_id_ < 0)
3912 database_id_ = blob_entry_key.database_id();
3913 else
3914 DCHECK_EQ(database_id_, blob_entry_key.database_id());
3915 std::string blob_entry_key_bytes = blob_entry_key.Encode();
3916 db_iter->Seek(blob_entry_key_bytes);
3917 if (db_iter->IsValid() &&
3918 !CompareKeys(db_iter->Key(), blob_entry_key_bytes)) {
3919 std::vector<IndexedDBBlobInfo> blob_info;
3920 if (!DecodeBlobData(db_iter->Value().as_string(), &blob_info)) {
3921 INTERNAL_READ_ERROR(TRANSACTION_COMMIT_METHOD);
3922 transaction_ = NULL;
3923 return false;
3924 }
3925 std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
3926 for (blob_info_iter = blob_info.begin();
3927 blob_info_iter != blob_info.end();
3928 ++blob_info_iter)
3929 blobs_to_remove_.push_back(
3930 std::make_pair(database_id_, blob_info_iter->key()));
3931 transaction_->Remove(blob_entry_key_bytes);
3932 }
3933 }
3934 }
3935 return true;
3936 }
3937
3938 leveldb::Status IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
3939 IndexedDBActiveBlobRegistry* registry =
3940 backing_store_->active_blob_registry();
3941 BlobJournalType::iterator iter;
3942 BlobJournalType primary_journal, live_blob_journal;
3943 for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
3944 ++iter) {
3945 if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
3946 live_blob_journal.push_back(*iter);
3947 else
3948 primary_journal.push_back(*iter);
3949 }
3950 UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
3951 leveldb::Status s =
3952 MergeBlobsIntoLiveBlobJournal(transaction_.get(), live_blob_journal);
3953 if (!s.ok())
3954 return s;
3955 // To signal how many blobs need attention right now.
3956 blobs_to_remove_.swap(primary_journal);
3957 return leveldb::Status::OK();
3958 }
3959
3960 leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseOne(
3961 scoped_refptr<BlobWriteCallback> callback) {
3962 IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseOne");
3963 DCHECK(transaction_);
3964 DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
3965
3966 leveldb::Status s;
3967
3968 s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
3969 if (!s.ok()) {
3970 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3971 transaction_ = NULL;
3972 return s;
3973 }
3974
3975 BlobEntryKeyValuePairVec new_blob_entries;
3976 WriteDescriptorVec new_files_to_write;
3977 s = HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write);
3978 if (!s.ok()) {
3979 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3980 transaction_ = NULL;
3981 return s;
3982 }
3983
3984 DCHECK(!new_files_to_write.size() ||
3985 KeyPrefix::IsValidDatabaseId(database_id_));
3986 if (!CollectBlobFilesToRemove()) {
3987 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3988 transaction_ = NULL;
3989 return InternalInconsistencyStatus();
3990 }
3991
3992 if (new_files_to_write.size()) {
3993 // This kicks off the writes of the new blobs, if any.
3994 // This call will zero out new_blob_entries and new_files_to_write.
3995 WriteNewBlobs(new_blob_entries, new_files_to_write, callback);
3996 // Remove the add journal, if any; once the blobs are written, and we
3997 // commit, this will do the cleanup.
3998 ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
3999 } else {
4000 callback->Run(true);
4001 }
4002
4003 return leveldb::Status::OK();
4004 }
4005
4006 leveldb::Status IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
4007 IDB_TRACE("IndexedDBBackingStore::Transaction::CommitPhaseTwo");
4008 leveldb::Status s;
4009 if (blobs_to_remove_.size()) {
4010 s = SortBlobsToRemove();
4011 if (!s.ok()) {
4012 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
4013 transaction_ = NULL;
4014 return s;
4015 }
4016 }
4017
4018 s = transaction_->Commit();
3434 transaction_ = NULL; 4019 transaction_ = NULL;
3435 4020
3436 if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) { 4021 if (s.ok() && backing_store_->is_incognito() && !blob_change_map_.empty()) {
3437 BlobChangeMap& target_map = backing_store_->incognito_blob_map_; 4022 BlobChangeMap& target_map = backing_store_->incognito_blob_map_;
3438 BlobChangeMap::iterator iter; 4023 BlobChangeMap::iterator iter;
3439 for (iter = blob_change_map_.begin(); iter != blob_change_map_.end(); 4024 for (iter = blob_change_map_.begin(); iter != blob_change_map_.end();
3440 ++iter) { 4025 ++iter) {
3441 BlobChangeMap::iterator target_record = target_map.find(iter->first); 4026 BlobChangeMap::iterator target_record = target_map.find(iter->first);
3442 if (target_record != target_map.end()) { 4027 if (target_record != target_map.end()) {
3443 delete target_record->second; 4028 delete target_record->second;
3444 target_map.erase(target_record); 4029 target_map.erase(target_record);
3445 } 4030 }
3446 if (iter->second) { 4031 if (iter->second) {
3447 target_map[iter->first] = iter->second; 4032 target_map[iter->first] = iter->second;
3448 iter->second = NULL; 4033 iter->second = NULL;
3449 } 4034 }
3450 } 4035 }
3451 } 4036 }
3452 if (!s.ok()) 4037 if (!s.ok())
3453 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); 4038 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
4039 else if (blobs_to_remove_.size())
4040 s = backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
4041
3454 return s; 4042 return s;
3455 } 4043 }
3456 4044
3457 4045
3458 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper 4046 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
3459 : public IndexedDBBackingStore::BlobWriteCallback { 4047 : public IndexedDBBackingStore::BlobWriteCallback {
3460 public: 4048 public:
3461 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction, 4049 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
3462 scoped_refptr<BlobWriteCallback> callback) 4050 scoped_refptr<BlobWriteCallback> callback)
3463 : transaction_(transaction), callback_(callback) {} 4051 : transaction_(transaction), callback_(callback) {}
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
3579 const GURL& url, 4167 const GURL& url,
3580 int64_t key) 4168 int64_t key)
3581 : is_file_(false), url_(url), key_(key) {} 4169 : is_file_(false), url_(url), key_(key) {}
3582 4170
3583 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor( 4171 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3584 const FilePath& file_path, 4172 const FilePath& file_path,
3585 int64_t key) 4173 int64_t key)
3586 : is_file_(true), file_path_(file_path), key_(key) {} 4174 : is_file_(true), file_path_(file_path), key_(key) {}
3587 4175
3588 } // namespace content 4176 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698