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

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: Settle on one name for the live blob journal. Created 7 years 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/logging.h" 8 #include "base/logging.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/strings/string_piece.h" 10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "content/browser/child_process_security_policy_impl.h"
15 #include "content/browser/indexed_db/indexed_db_blob_info.h"
13 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" 16 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
14 #include "content/browser/indexed_db/indexed_db_metadata.h" 17 #include "content/browser/indexed_db/indexed_db_metadata.h"
15 #include "content/browser/indexed_db/indexed_db_tracing.h" 18 #include "content/browser/indexed_db/indexed_db_tracing.h"
19 #include "content/browser/indexed_db/indexed_db_value.h"
16 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" 20 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
17 #include "content/browser/indexed_db/leveldb/leveldb_database.h" 21 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
18 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" 22 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
19 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 23 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
20 #include "content/common/indexed_db/indexed_db_key.h" 24 #include "content/common/indexed_db/indexed_db_key.h"
21 #include "content/common/indexed_db/indexed_db_key_path.h" 25 #include "content/common/indexed_db/indexed_db_key_path.h"
22 #include "content/common/indexed_db/indexed_db_key_range.h" 26 #include "content/common/indexed_db/indexed_db_key_range.h"
27 #include "content/public/browser/browser_thread.h"
28 #include "net/url_request/url_request_context.h"
23 #include "third_party/WebKit/public/platform/WebIDBTypes.h" 29 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
24 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" 30 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
25 #include "third_party/leveldatabase/env_chromium.h" 31 #include "third_party/leveldatabase/env_chromium.h"
32 #include "webkit/browser/blob/blob_data_handle.h"
33 #include "webkit/browser/fileapi/file_stream_writer.h"
34 #include "webkit/browser/fileapi/file_writer_delegate.h"
35 #include "webkit/browser/fileapi/local_file_stream_writer.h"
26 #include "webkit/common/database/database_identifier.h" 36 #include "webkit/common/database/database_identifier.h"
27 37
38 using base::FilePath;
28 using base::StringPiece; 39 using base::StringPiece;
40 using fileapi::FileWriterDelegate;
29 41
30 namespace content { 42 namespace content {
31 43
32 namespace { 44 namespace {
33 45
46 FilePath GetIDBBlobDirectoryName(const FilePath& pathBase,
47 int64 database_id) {
48 return pathBase.AppendASCII(base::StringPrintf("%lx", database_id));
49 }
50
51 FilePath GetIDBBlobDirectoryNameForKey(const FilePath& pathBase,
52 int64 database_id, int64 key) {
53 FilePath path = GetIDBBlobDirectoryName(pathBase, database_id);
54 path = path.AppendASCII(
55 base::StringPrintf("%x", static_cast<int>(key & 0x0000ff00) >> 8));
56 return path;
57 }
58
59 // This assumes a file path of dbId/3rd-byte-of-counter/counter.
60 bool MakeIDBBlobDirectory(
61 const FilePath& pathBase, int64 database_id, int64 key) {
62 FilePath path =
63 GetIDBBlobDirectoryNameForKey(pathBase, database_id, key);
64 return file_util::CreateDirectory(path);
65 }
66
34 static std::string ComputeOriginIdentifier(const GURL& origin_url) { 67 static std::string ComputeOriginIdentifier(const GURL& origin_url) {
35 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; 68 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
36 } 69 }
37 70
38 static base::FilePath ComputeFileName(const GURL& origin_url) { 71 static base::FilePath ComputeFileName(const GURL& origin_url) {
39 return base::FilePath() 72 return base::FilePath()
40 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) 73 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
41 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); 74 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
42 } 75 }
43 76
77 static base::FilePath ComputeBlobPath(const GURL& origin_url) {
78 return base::FilePath()
79 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
80 .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob"));
81 }
82
44 } // namespace 83 } // namespace
45 84
46 static const int64 kKeyGeneratorInitialNumber = 85 static const int64 kKeyGeneratorInitialNumber =
47 1; // From the IndexedDB specification. 86 1; // From the IndexedDB specification.
48 87
49 enum IndexedDBBackingStoreErrorSource { 88 enum IndexedDBBackingStoreErrorSource {
50 // 0 - 2 are no longer used. 89 // 0 - 2 are no longer used.
51 FIND_KEY_IN_INDEX = 3, 90 FIND_KEY_IN_INDEX = 3,
52 GET_IDBDATABASE_METADATA, 91 GET_IDBDATABASE_METADATA,
53 GET_INDEXES, 92 GET_INDEXES,
54 GET_KEY_GENERATOR_CURRENT_NUMBER, 93 GET_KEY_GENERATOR_CURRENT_NUMBER,
55 GET_OBJECT_STORES, 94 GET_OBJECT_STORES,
56 GET_RECORD, 95 GET_RECORD,
57 KEY_EXISTS_IN_OBJECT_STORE, 96 KEY_EXISTS_IN_OBJECT_STORE,
58 LOAD_CURRENT_ROW, 97 LOAD_CURRENT_ROW,
59 SET_UP_METADATA, 98 SET_UP_METADATA,
60 GET_PRIMARY_KEY_VIA_INDEX, 99 GET_PRIMARY_KEY_VIA_INDEX,
61 KEY_EXISTS_IN_INDEX, 100 KEY_EXISTS_IN_INDEX,
62 VERSION_EXISTS, 101 VERSION_EXISTS,
63 DELETE_OBJECT_STORE, 102 DELETE_OBJECT_STORE,
64 SET_MAX_OBJECT_STORE_ID, 103 SET_MAX_OBJECT_STORE_ID,
65 SET_MAX_INDEX_ID, 104 SET_MAX_INDEX_ID,
66 GET_NEW_DATABASE_ID, 105 GET_NEW_DATABASE_ID,
67 GET_NEW_VERSION_NUMBER, 106 GET_NEW_VERSION_NUMBER,
68 CREATE_IDBDATABASE_METADATA, 107 CREATE_IDBDATABASE_METADATA,
69 DELETE_DATABASE, 108 DELETE_DATABASE,
70 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro 109 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro
110 GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER,
111 GET_BLOB_INFO_FOR_RECORD,
112 DECODE_BLOB_JOURNAL,
71 GET_DATABASE_NAMES, 113 GET_DATABASE_NAMES,
72 INTERNAL_ERROR_MAX, 114 INTERNAL_ERROR_MAX,
73 }; 115 };
74 116
75 static void RecordInternalError(const char* type, 117 static void RecordInternalError(const char* type,
76 IndexedDBBackingStoreErrorSource location) { 118 IndexedDBBackingStoreErrorSource location) {
77 std::string name; 119 std::string name;
78 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); 120 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
79 base::Histogram::FactoryGet(name, 121 base::Histogram::FactoryGet(name,
80 1, 122 1,
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 } 404 }
363 405
364 class DefaultLevelDBFactory : public LevelDBFactory { 406 class DefaultLevelDBFactory : public LevelDBFactory {
365 public: 407 public:
366 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name, 408 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
367 const LevelDBComparator* comparator, 409 const LevelDBComparator* comparator,
368 scoped_ptr<LevelDBDatabase>* db, 410 scoped_ptr<LevelDBDatabase>* db,
369 bool* is_disk_full) OVERRIDE { 411 bool* is_disk_full) OVERRIDE {
370 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); 412 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
371 } 413 }
372 virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE { 414 virtual bool DestroyLevelDB(const FilePath& file_name) OVERRIDE {
373 return LevelDBDatabase::Destroy(file_name); 415 return LevelDBDatabase::Destroy(file_name);
374 } 416 }
375 }; 417 };
376 418
419 static bool GetBlobKeyGeneratorCurrentNumber(
420 LevelDBTransaction* leveldb_transaction, int64 database_id,
421 int64& blob_key_generator_current_number) {
422 const std::string key_gen_key =
423 DatabaseMetaDataKey::Encode(
424 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
425
426 // Default to initial number if not found.
427 int64 cur_number = DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber;
428 std::string data;
429
430 bool found = false;
431 bool ok = leveldb_transaction->Get(key_gen_key, &data, &found);
432 if (!ok) {
433 INTERNAL_READ_ERROR(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
434 return false;
435 }
436 if (found) {
437 StringPiece slice(data);
438 if (!DecodeVarInt(&slice, &cur_number) ||
439 !DatabaseMetaDataKey::IsValidBlobKey(cur_number)) {
440 INTERNAL_READ_ERROR(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
441 return false;
442 }
443 }
444 blob_key_generator_current_number = cur_number;
445 return true;
446 }
447
448 static bool UpdateBlobKeyGeneratorCurrentNumber(
449 LevelDBTransaction* leveldb_transaction, int64 database_id,
450 int64 blob_key_generator_current_number) {
451 #ifndef NDEBUG
452 int64 old_number;
453 if (!GetBlobKeyGeneratorCurrentNumber(leveldb_transaction, database_id,
454 old_number))
455 return false;
456 DCHECK_LT(old_number, blob_key_generator_current_number);
457 #endif
458 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(
459 blob_key_generator_current_number));
460 const std::string key =
461 DatabaseMetaDataKey::Encode(
462 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
463
464 PutInt(leveldb_transaction, key, blob_key_generator_current_number);
465 return true;
466 }
467
468 static bool DecodeBlobJournal(const std::string& data,
469 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
470 // TODO(ericu): Yell something on errors. If we persistently can't read the
471 // blob journal, the safe thing to do is to clear it and leak the blobs,
472 // though that may be costly. Still, database/directory deletion should always
473 // clean things up, and we can write an fsck that will do a full correction if
474 // need be.
475 IndexedDBBackingStore::Transaction::BlobJournalType output;
476 StringPiece slice(data);
477 while (!slice.empty()) {
478 int64 database_id = -1;
479 int64 blob_key = -1;
480 if (!DecodeVarInt(&slice, &database_id))
481 return false;
482 else if (!KeyPrefix::IsValidDatabaseId(database_id))
483 return false;
484 if (!DecodeVarInt(&slice, &blob_key)) {
485 return false;
486 } else if (!DatabaseMetaDataKey::IsValidBlobKey(blob_key) &&
487 (blob_key != DatabaseMetaDataKey::kAllBlobsKey)) {
488 return false;
489 }
490 output.push_back(std::make_pair(database_id, blob_key));
491 }
492 journal.swap(output);
493 return true;
494 }
495
496 static bool GetBlobJournalHelper(
497 bool ok, bool found,
498 const std::string& data,
499 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
500 if (!ok) {
501 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE);
502 return false;
503 }
504 journal.clear();
505 if (!found)
506 return true;
507 if (!data.size())
508 return true;
509 if (!DecodeBlobJournal(data, journal)) {
510 INTERNAL_READ_ERROR(DECODE_BLOB_JOURNAL);
511 return false;
512 }
513 return true;
514 }
515
516 static bool GetBlobJournal(
517 const StringPiece& leveldb_key,
518 LevelDBTransaction* leveldb_transaction,
519 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
520 std::string data;
521 bool found = false;
522 bool ok = leveldb_transaction->Get(leveldb_key, &data, &found);
523 return GetBlobJournalHelper(ok, found, data, journal);
524 }
525
526 static bool GetBlobJournal(
527 const StringPiece& leveldb_key,
528 LevelDBWriteOnlyTransaction* leveldb_transaction,
529 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
530 std::string data;
531 bool found = false;
532 bool ok = leveldb_transaction->Get(leveldb_key, &data, &found);
533 return GetBlobJournalHelper(ok, found, data, journal);
534 }
535
536 static std::string EncodeBlobJournalWithBlobList(
537 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
538 std::string data;
539 if (journal.size()) {
540 IndexedDBBackingStore::Transaction::BlobJournalType::const_iterator iter;
541 for (iter = journal.begin(); iter != journal.end(); ++iter) {
542 EncodeVarInt(iter->first, &data);
543 EncodeVarInt(iter->second, &data);
544 }
545 }
546 return data;
547 }
548
549 static void ClearBlobJournal(LevelDBTransaction* leveldb_transaction,
550 const std::string& level_db_key) {
551 leveldb_transaction->Remove(level_db_key);
552 }
553
554 static void UpdatePrimaryJournalWithBlobList(
555 LevelDBTransaction* leveldb_transaction,
556 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
557 const std::string leveldbKey = BlobJournalKey::Encode();
558 std::string data = EncodeBlobJournalWithBlobList(journal);
559 leveldb_transaction->Put(leveldbKey, &data);
560 }
561
562 static void UpdateLiveBlobJournalWithBlobList(
563 LevelDBTransaction* leveldb_transaction,
564 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
565 const std::string leveldbKey = LiveBlobJournalKey::Encode();
566 std::string data = EncodeBlobJournalWithBlobList(journal);
567 leveldb_transaction->Put(leveldbKey, &data);
568 }
569
570 static bool MergeBlobsIntoLiveBlobJournal(
571 LevelDBTransaction* leveldb_transaction,
572 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
573 IndexedDBBackingStore::Transaction::BlobJournalType old_journal;
574 std::string key = LiveBlobJournalKey::Encode();
575 if (!GetBlobJournal(key, leveldb_transaction, old_journal))
576 return false;
577
578 old_journal.insert(old_journal.end(), journal.begin(), journal.end());
579
580 UpdateLiveBlobJournalWithBlobList(leveldb_transaction, old_journal);
581 return true;
582 }
583
584 static void UpdateBlobJournalWithDatabase(
585 LevelDBWriteOnlyTransaction* leveldb_transaction, int64 database_id) {
586 IndexedDBBackingStore::Transaction::BlobJournalType journal;
587 journal.push_back(
588 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
589 const std::string key = BlobJournalKey::Encode();
590 std::string data = EncodeBlobJournalWithBlobList(journal);
591 leveldb_transaction->Put(key, &data);
592 }
593
594 static bool MergeDatabaseIntoLiveBlobJournal(
595 LevelDBWriteOnlyTransaction* leveldb_transaction, int64 database_id) {
596 IndexedDBBackingStore::Transaction::BlobJournalType journal;
597 std::string key = LiveBlobJournalKey::Encode();
598 if (!GetBlobJournal(key, leveldb_transaction, journal))
599 return false;
600 journal.push_back(
601 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
602 std::string data = EncodeBlobJournalWithBlobList(journal);
603 leveldb_transaction->Put(key, &data);
604 return true;
605 }
606
607 // Blob Data is encoded as { is_file [bool], key [int64 as varInt],
608 // type [string-with-length, may be empty], then [for Blobs] size
609 // [int64 as varInt] or [for Files] fileName [string-with-length] }
610 static std::string EncodeBlobData(
611 const std::vector<IndexedDBBlobInfo*>& blob_info) {
612 std::string ret;
613 std::vector<IndexedDBBlobInfo*>::const_iterator iter;
614 for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
615 const IndexedDBBlobInfo& info = **iter;
616 EncodeBool(info.is_file(), &ret);
617 EncodeVarInt(info.key(), &ret);
618 EncodeStringWithLength(info.type(), &ret);
619 if (info.is_file())
620 EncodeStringWithLength(info.file_name(), &ret);
621 else
622 EncodeVarInt(info.size(), &ret);
623 }
624 return ret;
625 }
626
627 static bool DecodeBlobData(
628 const std::string& data,
629 std::vector<IndexedDBBlobInfo>* output) {
630 std::vector<IndexedDBBlobInfo> ret;
631 output->clear();
632 StringPiece slice(data);
633 while (!slice.empty()) {
634 bool is_file;
635 int64 key;
636 string16 type;
637 int64 size;
638 string16 file_name;
639
640 if (!DecodeBool(&slice, &is_file))
641 return false;
642 if (!DecodeVarInt(&slice, &key) ||
643 !DatabaseMetaDataKey::IsValidBlobKey(key))
644 return false;
645 if (!DecodeStringWithLength(&slice, &type))
646 return false;
647 if (is_file) {
648 if (!DecodeStringWithLength(&slice, &file_name))
649 return false;
650 ret.push_back(IndexedDBBlobInfo(key, type, file_name));
651 } else {
652 if (!DecodeVarInt(&slice, &size) || size < 0)
653 return false;
654 ret.push_back(IndexedDBBlobInfo(type, static_cast<uint64>(size), key));
655 }
656 }
657 output->swap(ret);
658
659 return true;
660 }
661
377 IndexedDBBackingStore::IndexedDBBackingStore( 662 IndexedDBBackingStore::IndexedDBBackingStore(
663 IndexedDBFactory* indexed_db_factory,
378 const GURL& origin_url, 664 const GURL& origin_url,
665 const FilePath& blob_path,
666 net::URLRequestContext* request_context,
379 scoped_ptr<LevelDBDatabase> db, 667 scoped_ptr<LevelDBDatabase> db,
380 scoped_ptr<LevelDBComparator> comparator) 668 scoped_ptr<LevelDBComparator> comparator,
381 : origin_url_(origin_url), 669 base::TaskRunner* task_runner)
670 : indexed_db_factory_(indexed_db_factory),
671 origin_url_(origin_url),
382 origin_identifier_(ComputeOriginIdentifier(origin_url)), 672 origin_identifier_(ComputeOriginIdentifier(origin_url)),
673 blob_path_(blob_path),
674 request_context_(request_context),
675 task_runner_(task_runner),
383 db_(db.Pass()), 676 db_(db.Pass()),
384 comparator_(comparator.Pass()) {} 677 comparator_(comparator.Pass()),
678 active_blob_registry_(this) {}
385 679
386 IndexedDBBackingStore::~IndexedDBBackingStore() { 680 IndexedDBBackingStore::~IndexedDBBackingStore() {
681 if (!blob_path_.empty()) {
682 ChildProcessSecurityPolicyImpl* policy =
683 ChildProcessSecurityPolicyImpl::GetInstance();
684 for (std::set<int>::iterator iter = child_process_ids_granted_.begin();
685 iter != child_process_ids_granted_.end(); ++iter) {
686 policy->RevokeAllPermissionsForFile(*iter, blob_path_);
687 }
688 }
387 // db_'s destructor uses comparator_. The order of destruction is important. 689 // db_'s destructor uses comparator_. The order of destruction is important.
388 db_.reset(); 690 db_.reset();
389 comparator_.reset(); 691 comparator_.reset();
390 } 692 }
391 693
392 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier( 694 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier(
393 const std::string& primary_key, 695 const std::string& primary_key,
394 int64 version) 696 int64 version)
395 : primary_key_(primary_key), version_(version) { 697 : primary_key_(primary_key), version_(version) {
396 DCHECK(!primary_key.empty()); 698 DCHECK(!primary_key.empty());
(...skipping 18 matching lines...) Expand all
415 INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, 717 INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
416 INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, 718 INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
417 INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED, 719 INDEXED_DB_BACKING_STORE_OPEN_DISK_FULL_DEPRECATED,
418 INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, 720 INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
419 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, 721 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
420 INDEXED_DB_BACKING_STORE_OPEN_MAX, 722 INDEXED_DB_BACKING_STORE_OPEN_MAX,
421 }; 723 };
422 724
423 // static 725 // static
424 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 726 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
727 IndexedDBFactory* indexed_db_factory,
425 const GURL& origin_url, 728 const GURL& origin_url,
426 const base::FilePath& path_base, 729 const base::FilePath& path_base,
730 net::URLRequestContext* request_context,
427 blink::WebIDBDataLoss* data_loss, 731 blink::WebIDBDataLoss* data_loss,
428 std::string* data_loss_message, 732 std::string* data_loss_message,
429 bool* disk_full) { 733 bool* disk_full,
734 base::TaskRunner* task_runner,
735 bool clean_journal) {
430 *data_loss = blink::WebIDBDataLossNone; 736 *data_loss = blink::WebIDBDataLossNone;
431 DefaultLevelDBFactory leveldb_factory; 737 DefaultLevelDBFactory leveldb_factory;
432 return IndexedDBBackingStore::Open(origin_url, 738 return IndexedDBBackingStore::Open(indexed_db_factory,
739 origin_url,
433 path_base, 740 path_base,
741 request_context,
434 data_loss, 742 data_loss,
435 data_loss_message, 743 data_loss_message,
436 disk_full, 744 disk_full,
437 &leveldb_factory); 745 &leveldb_factory,
746 task_runner,
747 clean_journal);
438 } 748 }
439 749
440 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) { 750 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
441 if (origin_url.host() == "docs.google.com") 751 if (origin_url.host() == "docs.google.com")
442 return ".Docs"; 752 return ".Docs";
443 return std::string(); 753 return std::string();
444 } 754 }
445 755
446 static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result, 756 static void HistogramOpenStatus(IndexedDBBackingStoreOpenResult result,
447 const GURL& origin_url) { 757 const GURL& origin_url) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 min, 798 min,
489 max, 799 max,
490 num_buckets); 800 num_buckets);
491 return true; 801 return true;
492 } 802 }
493 return false; 803 return false;
494 } 804 }
495 805
496 // static 806 // static
497 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 807 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
808 IndexedDBFactory* indexed_db_factory,
498 const GURL& origin_url, 809 const GURL& origin_url,
499 const base::FilePath& path_base, 810 const base::FilePath& path_base,
811 net::URLRequestContext* request_context,
500 blink::WebIDBDataLoss* data_loss, 812 blink::WebIDBDataLoss* data_loss,
501 std::string* data_loss_message, 813 std::string* data_loss_message,
502 bool* is_disk_full, 814 bool* is_disk_full,
503 LevelDBFactory* leveldb_factory) { 815 LevelDBFactory* leveldb_factory,
816 base::TaskRunner* task_runner,
817 bool clean_journal) {
504 IDB_TRACE("IndexedDBBackingStore::Open"); 818 IDB_TRACE("IndexedDBBackingStore::Open");
505 DCHECK(!path_base.empty()); 819 DCHECK(!path_base.empty());
506 *data_loss = blink::WebIDBDataLossNone; 820 *data_loss = blink::WebIDBDataLossNone;
507 *data_loss_message = ""; 821 *data_loss_message = "";
508 *is_disk_full = false; 822 *is_disk_full = false;
509 823
510 scoped_ptr<LevelDBComparator> comparator(new Comparator()); 824 scoped_ptr<LevelDBComparator> comparator(new Comparator());
511 825
512 if (!IsStringASCII(path_base.AsUTF8Unsafe())) { 826 if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
513 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII, 827 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII,
514 origin_url); 828 origin_url);
515 } 829 }
516 if (!file_util::CreateDirectory(path_base)) { 830 if (!file_util::CreateDirectory(path_base)) {
517 LOG(ERROR) << "Unable to create IndexedDB database path " 831 LOG(ERROR) << "Unable to create IndexedDB database path "
518 << path_base.AsUTF8Unsafe(); 832 << path_base.AsUTF8Unsafe();
519 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY, 833 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY,
520 origin_url); 834 origin_url);
521 return scoped_refptr<IndexedDBBackingStore>(); 835 return scoped_refptr<IndexedDBBackingStore>();
522 } 836 }
523 837
524 const base::FilePath file_path = 838 const base::FilePath file_path =
525 path_base.Append(ComputeFileName(origin_url)); 839 path_base.Append(ComputeFileName(origin_url));
840 const base::FilePath blob_path =
841 path_base.Append(ComputeBlobPath(origin_url));
526 842
527 if (IsPathTooLong(file_path)) { 843 if (IsPathTooLong(file_path)) {
528 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG, 844 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG,
529 origin_url); 845 origin_url);
530 return scoped_refptr<IndexedDBBackingStore>(); 846 return scoped_refptr<IndexedDBBackingStore>();
531 } 847 }
848 // TODO(ericu): Check blob path length?
532 849
533 scoped_ptr<LevelDBDatabase> db; 850 scoped_ptr<LevelDBDatabase> db;
534 leveldb::Status status = leveldb_factory->OpenLevelDB( 851 leveldb::Status status = leveldb_factory->OpenLevelDB(
535 file_path, comparator.get(), &db, is_disk_full); 852 file_path, comparator.get(), &db, is_disk_full);
536 853
537 DCHECK(!db == !status.ok()); 854 DCHECK(!db == !status.ok());
538 if (!status.ok()) { 855 if (!status.ok()) {
539 if (leveldb_env::IndicatesDiskFull(status)) { 856 if (leveldb_env::IndicatesDiskFull(status)) {
540 *is_disk_full = true; 857 *is_disk_full = true;
541 } else if (leveldb_env::IsCorruption(status)) { 858 } else if (leveldb_env::IsCorruption(status)) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 origin_url); 917 origin_url);
601 } 918 }
602 919
603 if (!db) { 920 if (!db) {
604 NOTREACHED(); 921 NOTREACHED();
605 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, 922 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
606 origin_url); 923 origin_url);
607 return scoped_refptr<IndexedDBBackingStore>(); 924 return scoped_refptr<IndexedDBBackingStore>();
608 } 925 }
609 926
610 return Create(origin_url, db.Pass(), comparator.Pass()); 927 scoped_refptr<IndexedDBBackingStore> backing_store = Create(
928 indexed_db_factory, origin_url, blob_path, request_context, db.Pass(),
929 comparator.Pass(), task_runner);
930
931 if (clean_journal && !backing_store->CleanUpBlobJournal(
932 LiveBlobJournalKey::Encode()))
933 return scoped_refptr<IndexedDBBackingStore>();
934 return backing_store;
611 } 935 }
612 936
613 // static 937 // static
614 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 938 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
615 const GURL& origin_url) { 939 const GURL& origin_url) {
616 DefaultLevelDBFactory leveldb_factory; 940 DefaultLevelDBFactory leveldb_factory;
617 return IndexedDBBackingStore::OpenInMemory(origin_url, &leveldb_factory); 941 return IndexedDBBackingStore::OpenInMemory(origin_url, &leveldb_factory);
618 } 942 }
619 943
620 // static 944 // static
621 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 945 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
622 const GURL& origin_url, 946 const GURL& origin_url,
623 LevelDBFactory* leveldb_factory) { 947 LevelDBFactory* leveldb_factory) {
624 IDB_TRACE("IndexedDBBackingStore::OpenInMemory"); 948 IDB_TRACE("IndexedDBBackingStore::OpenInMemory");
625 949
626 scoped_ptr<LevelDBComparator> comparator(new Comparator()); 950 scoped_ptr<LevelDBComparator> comparator(new Comparator());
627 scoped_ptr<LevelDBDatabase> db = 951 scoped_ptr<LevelDBDatabase> db =
628 LevelDBDatabase::OpenInMemory(comparator.get()); 952 LevelDBDatabase::OpenInMemory(comparator.get());
629 if (!db) { 953 if (!db) {
630 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; 954 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
631 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, 955 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
632 origin_url); 956 origin_url);
633 return scoped_refptr<IndexedDBBackingStore>(); 957 return scoped_refptr<IndexedDBBackingStore>();
634 } 958 }
635 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); 959 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
636 960
637 return Create(origin_url, db.Pass(), comparator.Pass()); 961 return Create(
962 NULL, origin_url, FilePath(), NULL, db.Pass(), comparator.Pass(), NULL);
638 } 963 }
639 964
640 // static 965 // static
641 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( 966 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
967 IndexedDBFactory* indexed_db_factory,
642 const GURL& origin_url, 968 const GURL& origin_url,
969 const FilePath& blob_path,
970 net::URLRequestContext* request_context,
643 scoped_ptr<LevelDBDatabase> db, 971 scoped_ptr<LevelDBDatabase> db,
644 scoped_ptr<LevelDBComparator> comparator) { 972 scoped_ptr<LevelDBComparator> comparator,
973 base::TaskRunner* task_runner) {
645 // TODO(jsbell): Handle comparator name changes. 974 // TODO(jsbell): Handle comparator name changes.
646
647 scoped_refptr<IndexedDBBackingStore> backing_store( 975 scoped_refptr<IndexedDBBackingStore> backing_store(
648 new IndexedDBBackingStore(origin_url, db.Pass(), comparator.Pass())); 976 new IndexedDBBackingStore(indexed_db_factory, origin_url, blob_path,
977 request_context, db.Pass(), comparator.Pass(), task_runner));
649 if (!SetUpMetadata(backing_store->db_.get(), 978 if (!SetUpMetadata(backing_store->db_.get(),
650 backing_store->origin_identifier_)) 979 backing_store->origin_identifier_))
651 return scoped_refptr<IndexedDBBackingStore>(); 980 return scoped_refptr<IndexedDBBackingStore>();
652 981
653 return backing_store; 982 return backing_store;
654 } 983 }
655 984
985 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
986 if (!child_process_ids_granted_.count(child_process_id)) {
987 child_process_ids_granted_.insert(child_process_id);
988 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
989 child_process_id, blob_path_);
990 }
991 }
992
656 std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() { 993 std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() {
657 std::vector<string16> found_names; 994 std::vector<string16> found_names;
658 const std::string start_key = 995 const std::string start_key =
659 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_); 996 DatabaseNameKey::EncodeMinKeyForOrigin(origin_identifier_);
660 const std::string stop_key = 997 const std::string stop_key =
661 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_); 998 DatabaseNameKey::EncodeStopKeyForOrigin(origin_identifier_);
662 999
663 DCHECK(found_names.empty()); 1000 DCHECK(found_names.empty());
664 1001
665 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1002 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) 1060 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
724 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; 1061 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
725 1062
726 ok = GetMaxObjectStoreId( 1063 ok = GetMaxObjectStoreId(
727 db_.get(), metadata->id, &metadata->max_object_store_id); 1064 db_.get(), metadata->id, &metadata->max_object_store_id);
728 if (!ok) { 1065 if (!ok) {
729 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); 1066 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
730 return false; 1067 return false;
731 } 1068 }
732 1069
1070 int64 blob_key_generator_current_number =
1071 DatabaseMetaDataKey::kInvalidBlobKey;
1072
1073 ok = GetVarInt(db_.get(),
1074 DatabaseMetaDataKey::Encode(
1075 metadata->id,
1076 DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1077 &blob_key_generator_current_number,
1078 found);
1079 if (!ok) {
1080 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
1081 return false;
1082 }
1083 if (!*found ||
1084 !DatabaseMetaDataKey::IsValidBlobKey(blob_key_generator_current_number)) {
1085 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA);
1086 // TODO(ericu): If BLOB_KEY_GENERATOR_CURRENT_NUMBER isn't present,
1087 // initialize it to kBlobKeyGeneratorInitialNumber. We may also want to
1088 // verify that this object store predates blob support, or that there
1089 // aren't any blobs on disk.
1090 // This would be a read-modify-write, so we'd need a transaction,
1091 // and to double-check. It might just be easier to write it lazily
1092 // when we first try to increment it.
1093 return false;
1094 }
1095
733 return true; 1096 return true;
734 } 1097 }
735 1098
736 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction, 1099 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBTransaction* transaction,
737 int64* new_id) { 1100 int64* new_id) {
738 *new_id = -1; 1101 *new_id = -1;
739 int64 max_database_id = -1; 1102 int64 max_database_id = -1;
740 bool found = false; 1103 bool found = false;
741 bool ok = 1104 bool ok =
742 GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found); 1105 GetInt(transaction, MaxDatabaseIdKey::Encode(), &max_database_id, &found);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 DatabaseNameKey::Encode(origin_identifier_, name), 1137 DatabaseNameKey::Encode(origin_identifier_, name),
775 *row_id); 1138 *row_id);
776 PutString( 1139 PutString(
777 transaction.get(), 1140 transaction.get(),
778 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION), 1141 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
779 version); 1142 version);
780 PutVarInt(transaction.get(), 1143 PutVarInt(transaction.get(),
781 DatabaseMetaDataKey::Encode(*row_id, 1144 DatabaseMetaDataKey::Encode(*row_id,
782 DatabaseMetaDataKey::USER_INT_VERSION), 1145 DatabaseMetaDataKey::USER_INT_VERSION),
783 int_version); 1146 int_version);
1147 PutVarInt(
1148 transaction.get(),
1149 DatabaseMetaDataKey::Encode(*row_id,
1150 DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1151 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber);
784 if (!transaction->Commit()) { 1152 if (!transaction->Commit()) {
785 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA); 1153 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA);
786 return false; 1154 return false;
787 } 1155 }
788 return true; 1156 return true;
789 } 1157 }
790 1158
791 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion( 1159 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
792 IndexedDBBackingStore::Transaction* transaction, 1160 IndexedDBBackingStore::Transaction* transaction,
793 int64 row_id, 1161 int64 row_id,
794 int64 int_version) { 1162 int64 int_version) {
795 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) 1163 if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
796 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION; 1164 int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
797 DCHECK_GE(int_version, 0) << "int_version was " << int_version; 1165 DCHECK_GE(int_version, 0) << "int_version was " << int_version;
798 PutVarInt(transaction->transaction(), 1166 PutVarInt(transaction->transaction(),
799 DatabaseMetaDataKey::Encode(row_id, 1167 DatabaseMetaDataKey::Encode(row_id,
800 DatabaseMetaDataKey::USER_INT_VERSION), 1168 DatabaseMetaDataKey::USER_INT_VERSION),
801 int_version); 1169 int_version);
802 return true; 1170 return true;
803 } 1171 }
804 1172
805 static void DeleteRange(LevelDBTransaction* transaction, 1173 // Note that if you're deleting a range that contains user keys that have blob
806 const std::string& begin, 1174 // info, this won't clean up the blobs.
807 const std::string& end) { 1175 static void DeleteRangeByKeys(LevelDBTransaction* transaction,
1176 const std::string& begin,
1177 const std::string& end) {
808 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); 1178 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
809 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0; 1179 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0;
810 it->Next()) 1180 it->Next())
811 transaction->Remove(it->Key()); 1181 transaction->Remove(it->Key());
812 } 1182 }
813 1183
1184 // For a whole-object-store deletion, we still use the one-blob-record-at-a-time
1185 // deletion mechanism designed for normal transactions. We could go with the
1186 // nuke-the-whole-directory method used for deleteDatabase, but that would
1187 // complicate the kind of info we store in the LevelDBTransaction.
1188 static void DeleteBlobsInObjectStore(
1189 IndexedDBBackingStore::Transaction* transaction,
1190 int64 database_id, int64 object_store_id) {
1191 std::string start_key, end_key;
1192 start_key =
1193 BlobEntryKey::EncodeMinForObjectStore(database_id, object_store_id);
1194 end_key =
1195 BlobEntryKey::EncodeMaxForObjectStore(database_id, object_store_id);
1196
1197 scoped_ptr<LevelDBIterator> it =
1198 transaction->transaction()->CreateIterator();
1199 for (it->Seek(start_key);
1200 it->IsValid() && CompareKeys(it->Key(), end_key) < 0; it->Next()) {
1201 StringPiece key_piece(it->Key());
1202 std::string user_key =
1203 BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece);
1204 if (user_key.size())
1205 transaction->PutBlobInfo(database_id, object_store_id, user_key, NULL,
1206 NULL);
1207 else
1208 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA);
1209 }
1210 }
1211
1212 static bool GetBlobInfoForRecord(
1213 IndexedDBBackingStore* backing_store,
1214 LevelDBTransaction* leveldb_transaction,
1215 int64 database_id,
1216 const std::string& leveldb_key,
1217 IndexedDBValue* value) {
1218
1219 BlobEntryKey blob_entry_key;
1220 StringPiece leveldb_key_piece(leveldb_key);
1221 if (!BlobEntryKey::FromObjectStoreDataKey(
1222 &leveldb_key_piece, &blob_entry_key)) {
1223 NOTREACHED();
1224 return false;
1225 }
1226 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
1227 std::string encoded_key = blob_entry_key.Encode();
1228 it->Seek(encoded_key);
1229 if (it->IsValid() && CompareKeys(it->Key(), encoded_key) == 0) {
1230 if (!DecodeBlobData(it->Value().as_string(), &value->blob_info)) {
1231 INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD);
1232 return false;
1233 }
1234 std::vector<IndexedDBBlobInfo>::iterator iter;
1235 for (iter = value->blob_info.begin(); iter != value->blob_info.end();
1236 ++iter) {
1237 iter->set_file_path(
1238 backing_store->GetIDBBlobFileName(database_id, iter->key()));
1239 iter->set_mark_used_callback(
1240 backing_store->active_blob_registry()->GetAddBlobRefCallback(
1241 database_id, iter->key()));
1242 iter->set_release_callback(
1243 backing_store->active_blob_registry()->GetFinalReleaseCallback(
1244 database_id, iter->key()));
1245 if (iter->is_file()) {
1246 base::PlatformFileInfo info;
1247 if (file_util::GetFileInfo(iter->file_path(), &info)) {
1248 // This should always work, but it isn't fatal if it doesn't; it just
1249 // means a potential slow synchronous call from the renderer later.
1250 iter->set_last_modified(info.last_modified);
1251 iter->set_size(info.size);
1252 }
1253 }
1254 }
1255 }
1256 return true;
1257 }
1258
814 bool IndexedDBBackingStore::DeleteDatabase(const string16& name) { 1259 bool IndexedDBBackingStore::DeleteDatabase(const string16& name) {
815 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); 1260 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
816 scoped_ptr<LevelDBWriteOnlyTransaction> transaction = 1261 scoped_ptr<LevelDBWriteOnlyTransaction> transaction =
817 LevelDBWriteOnlyTransaction::Create(db_.get()); 1262 LevelDBWriteOnlyTransaction::Create(db_.get());
818 1263
1264 if (!CleanUpBlobJournal(BlobJournalKey::Encode()))
1265 return false;
1266
819 IndexedDBDatabaseMetadata metadata; 1267 IndexedDBDatabaseMetadata metadata;
820 bool success = false; 1268 bool success = false;
821 bool ok = GetIDBDatabaseMetaData(name, &metadata, &success); 1269 bool ok = GetIDBDatabaseMetaData(name, &metadata, &success);
822 if (!ok) 1270 if (!ok)
823 return false; 1271 return false;
824 if (!success) 1272 if (!success)
825 return true; 1273 return true;
826 1274
827 const std::string start_key = DatabaseMetaDataKey::Encode( 1275 const std::string start_key = DatabaseMetaDataKey::Encode(
828 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); 1276 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME);
829 const std::string stop_key = DatabaseMetaDataKey::Encode( 1277 const std::string stop_key = DatabaseMetaDataKey::Encode(
830 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); 1278 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME);
831 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1279 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
832 for (it->Seek(start_key); 1280 for (it->Seek(start_key);
833 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 1281 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
834 it->Next()) 1282 it->Next())
835 transaction->Remove(it->Key()); 1283 transaction->Remove(it->Key());
836 1284
837 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name); 1285 const std::string key = DatabaseNameKey::Encode(origin_identifier_, name);
838 transaction->Remove(key); 1286 transaction->Remove(key);
839 1287
1288 bool need_cleanup = false;
1289 if (active_blob_registry()->MarkDeletedCheckIfUsed(
1290 metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) {
1291 if (!MergeDatabaseIntoLiveBlobJournal(transaction.get(), metadata.id))
1292 return false;
1293 } else {
1294 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id);
1295 need_cleanup = true;
1296 }
1297
840 if (!transaction->Commit()) { 1298 if (!transaction->Commit()) {
841 INTERNAL_WRITE_ERROR(DELETE_DATABASE); 1299 INTERNAL_WRITE_ERROR(DELETE_DATABASE);
842 return false; 1300 return false;
843 } 1301 }
1302
1303 if (need_cleanup)
1304 CleanUpBlobJournal(BlobJournalKey::Encode());
1305
844 return true; 1306 return true;
845 } 1307 }
846 1308
847 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, 1309 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
848 const std::string& stop_key, 1310 const std::string& stop_key,
849 int64 object_store_id, 1311 int64 object_store_id,
850 int64 meta_data_type) { 1312 int64 meta_data_type) {
851 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1313 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
852 return false; 1314 return false;
853 1315
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1388 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
927 break; 1389 break;
928 } 1390 }
929 bool auto_increment; 1391 bool auto_increment;
930 { 1392 {
931 StringPiece slice(it->Value()); 1393 StringPiece slice(it->Value());
932 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) 1394 if (!DecodeBool(&slice, &auto_increment) || !slice.empty())
933 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1395 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
934 } 1396 }
935 1397
936 it->Next(); // Is evicatble. 1398 it->Next(); // Is evictable.
937 if (!CheckObjectStoreAndMetaDataType(it.get(), 1399 if (!CheckObjectStoreAndMetaDataType(it.get(),
938 stop_key, 1400 stop_key,
939 object_store_id, 1401 object_store_id,
940 ObjectStoreMetaDataKey::EVICTABLE)) { 1402 ObjectStoreMetaDataKey::EVICTABLE)) {
941 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1403 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
942 break; 1404 break;
943 } 1405 }
944 1406
945 it->Next(); // Last version. 1407 it->Next(); // Last version.
946 if (!CheckObjectStoreAndMetaDataType( 1408 if (!CheckObjectStoreAndMetaDataType(
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 &found); 1575 &found);
1114 if (!ok) { 1576 if (!ok) {
1115 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE); 1577 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE);
1116 return false; 1578 return false;
1117 } 1579 }
1118 if (!found) { 1580 if (!found) {
1119 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE); 1581 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE);
1120 return false; 1582 return false;
1121 } 1583 }
1122 1584
1123 DeleteRange( 1585 DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1586 DeleteRangeByKeys(
1124 leveldb_transaction, 1587 leveldb_transaction,
1125 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), 1588 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
1126 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1589 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id));
1127 1590
1128 leveldb_transaction->Remove( 1591 leveldb_transaction->Remove(
1129 ObjectStoreNamesKey::Encode(database_id, object_store_name)); 1592 ObjectStoreNamesKey::Encode(database_id, object_store_name));
1130 1593
1131 DeleteRange(leveldb_transaction, 1594 DeleteRangeByKeys(
1132 IndexFreeListKey::Encode(database_id, object_store_id, 0), 1595 leveldb_transaction,
1133 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); 1596 IndexFreeListKey::Encode(database_id, object_store_id, 0),
1134 DeleteRange(leveldb_transaction, 1597 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id));
1135 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), 1598 DeleteRangeByKeys(
1136 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1599 leveldb_transaction,
1600 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
1601 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id));
1137 1602
1138 return ClearObjectStore(transaction, database_id, object_store_id); 1603 return ClearObjectStore(transaction, database_id, object_store_id);
1139 } 1604 }
1140 1605
1141 bool IndexedDBBackingStore::GetRecord( 1606 bool IndexedDBBackingStore::GetRecord(
1142 IndexedDBBackingStore::Transaction* transaction, 1607 IndexedDBBackingStore::Transaction* transaction,
1143 int64 database_id, 1608 int64 database_id,
1144 int64 object_store_id, 1609 int64 object_store_id,
1145 const IndexedDBKey& key, 1610 const IndexedDBKey& key,
1146 std::string* record) { 1611 IndexedDBValue* record) {
1147 IDB_TRACE("IndexedDBBackingStore::GetRecord"); 1612 IDB_TRACE("IndexedDBBackingStore::GetRecord");
1148 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1613 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1149 return false; 1614 return false;
1150 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 1615 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1151 1616
1152 const std::string leveldb_key = 1617 const std::string leveldb_key =
1153 ObjectStoreDataKey::Encode(database_id, object_store_id, key); 1618 ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1154 std::string data; 1619 std::string data;
1155 1620
1156 record->clear(); 1621 record->clear();
(...skipping 11 matching lines...) Expand all
1168 return false; 1633 return false;
1169 } 1634 }
1170 1635
1171 int64 version; 1636 int64 version;
1172 StringPiece slice(data); 1637 StringPiece slice(data);
1173 if (!DecodeVarInt(&slice, &version)) { 1638 if (!DecodeVarInt(&slice, &version)) {
1174 INTERNAL_READ_ERROR(GET_RECORD); 1639 INTERNAL_READ_ERROR(GET_RECORD);
1175 return false; 1640 return false;
1176 } 1641 }
1177 1642
1178 *record = slice.as_string(); 1643 record->bits = slice.as_string();
1179 return true; 1644 return GetBlobInfoForRecord(
1645 this, leveldb_transaction, database_id, leveldb_key, record);
1180 } 1646 }
1181 1647
1182 WARN_UNUSED_RESULT static bool GetNewVersionNumber( 1648 WARN_UNUSED_RESULT static bool GetNewVersionNumber(
1183 LevelDBTransaction* transaction, 1649 LevelDBTransaction* transaction,
1184 int64 database_id, 1650 int64 database_id,
1185 int64 object_store_id, 1651 int64 object_store_id,
1186 int64* new_version_number) { 1652 int64* new_version_number) {
1187 const std::string last_version_key = ObjectStoreMetaDataKey::Encode( 1653 const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
1188 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); 1654 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
1189 1655
(...skipping 18 matching lines...) Expand all
1208 1674
1209 *new_version_number = version; 1675 *new_version_number = version;
1210 return true; 1676 return true;
1211 } 1677 }
1212 1678
1213 bool IndexedDBBackingStore::PutRecord( 1679 bool IndexedDBBackingStore::PutRecord(
1214 IndexedDBBackingStore::Transaction* transaction, 1680 IndexedDBBackingStore::Transaction* transaction,
1215 int64 database_id, 1681 int64 database_id,
1216 int64 object_store_id, 1682 int64 object_store_id,
1217 const IndexedDBKey& key, 1683 const IndexedDBKey& key,
1218 const std::string& value, 1684 IndexedDBValue& value,
1685 std::vector<webkit_blob::BlobDataHandle*>* handles,
1219 RecordIdentifier* record_identifier) { 1686 RecordIdentifier* record_identifier) {
1220 IDB_TRACE("IndexedDBBackingStore::PutRecord"); 1687 IDB_TRACE("IndexedDBBackingStore::PutRecord");
1221 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1688 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1222 return false; 1689 return false;
1223 DCHECK(key.IsValid()); 1690 DCHECK(key.IsValid());
1224 1691
1225 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 1692 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1226 int64 version = -1; 1693 int64 version = -1;
1227 bool ok = GetNewVersionNumber( 1694 bool ok = GetNewVersionNumber(
1228 leveldb_transaction, database_id, object_store_id, &version); 1695 leveldb_transaction, database_id, object_store_id, &version);
1229 if (!ok) 1696 if (!ok)
1230 return false; 1697 return false;
1231 DCHECK_GE(version, 0); 1698 DCHECK_GE(version, 0);
1232 const std::string object_storedata_key = 1699 const std::string object_store_data_key =
1233 ObjectStoreDataKey::Encode(database_id, object_store_id, key); 1700 ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1234 1701
1235 std::string v; 1702 std::string v;
1236 EncodeVarInt(version, &v); 1703 EncodeVarInt(version, &v);
1237 v.append(value); 1704 v.append(value.bits);
1238 1705
1239 leveldb_transaction->Put(object_storedata_key, &v); 1706 leveldb_transaction->Put(object_store_data_key, &v);
1707 transaction->PutBlobInfo(database_id, object_store_id, object_store_data_key,
1708 &value.blob_info, handles);
1709 DCHECK(!handles->size());
1240 1710
1241 const std::string exists_entry_key = 1711 const std::string exists_entry_key =
1242 ExistsEntryKey::Encode(database_id, object_store_id, key); 1712 ExistsEntryKey::Encode(database_id, object_store_id, key);
1243 std::string version_encoded; 1713 std::string version_encoded;
1244 EncodeInt(version, &version_encoded); 1714 EncodeInt(version, &version_encoded);
1245 leveldb_transaction->Put(exists_entry_key, &version_encoded); 1715 leveldb_transaction->Put(exists_entry_key, &version_encoded);
1246 1716
1247 std::string key_encoded; 1717 std::string key_encoded;
1248 EncodeIDBKey(key, &key_encoded); 1718 EncodeIDBKey(key, &key_encoded);
1249 record_identifier->Reset(key_encoded, version); 1719 record_identifier->Reset(key_encoded, version);
1250 return true; 1720 return true;
1251 } 1721 }
1252 1722
1253 bool IndexedDBBackingStore::ClearObjectStore( 1723 bool IndexedDBBackingStore::ClearObjectStore(
1254 IndexedDBBackingStore::Transaction* transaction, 1724 IndexedDBBackingStore::Transaction* transaction,
1255 int64 database_id, 1725 int64 database_id,
1256 int64 object_store_id) { 1726 int64 object_store_id) {
1257 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); 1727 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
1258 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1728 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1259 return false; 1729 return false;
1260 const std::string start_key = 1730 const std::string start_key =
1261 KeyPrefix(database_id, object_store_id).Encode(); 1731 KeyPrefix(database_id, object_store_id).Encode();
1262 const std::string stop_key = 1732 const std::string stop_key =
1263 KeyPrefix(database_id, object_store_id + 1).Encode(); 1733 KeyPrefix(database_id, object_store_id + 1).Encode();
1264 1734
1265 DeleteRange(transaction->transaction(), start_key, stop_key); 1735 DeleteRangeByKeys(transaction->transaction(), start_key, stop_key);
1736 DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1266 return true; 1737 return true;
1267 } 1738 }
1268 1739
1269 bool IndexedDBBackingStore::DeleteRecord( 1740 bool IndexedDBBackingStore::DeleteRecord(
1270 IndexedDBBackingStore::Transaction* transaction, 1741 IndexedDBBackingStore::Transaction* transaction,
1271 int64 database_id, 1742 int64 database_id,
1272 int64 object_store_id, 1743 int64 object_store_id,
1273 const RecordIdentifier& record_identifier) { 1744 const RecordIdentifier& record_identifier) {
1274 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); 1745 IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
1275 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1746 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1276 return false; 1747 return false;
1277 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 1748 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1278 1749
1279 const std::string object_store_data_key = ObjectStoreDataKey::Encode( 1750 const std::string object_store_data_key = ObjectStoreDataKey::Encode(
1280 database_id, object_store_id, record_identifier.primary_key()); 1751 database_id, object_store_id, record_identifier.primary_key());
1281 leveldb_transaction->Remove(object_store_data_key); 1752 leveldb_transaction->Remove(object_store_data_key);
1753 transaction->PutBlobInfo(database_id, object_store_id, object_store_data_key,
1754 NULL, NULL);
1282 1755
1283 const std::string exists_entry_key = ExistsEntryKey::Encode( 1756 const std::string exists_entry_key = ExistsEntryKey::Encode(
1284 database_id, object_store_id, record_identifier.primary_key()); 1757 database_id, object_store_id, record_identifier.primary_key());
1285 leveldb_transaction->Remove(exists_entry_key); 1758 leveldb_transaction->Remove(exists_entry_key);
1286 return true; 1759 return true;
1287 } 1760 }
1288 1761
1762 bool IndexedDBBackingStore::DeleteRange(
1763 IndexedDBBackingStore::Transaction* transaction,
1764 int64 database_id,
1765 int64 object_store_id,
1766 const IndexedDBKeyRange& key_range) {
1767 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1768 OpenObjectStoreCursor(transaction, database_id, object_store_id,
1769 key_range, indexed_db::CURSOR_NEXT);
1770 if (backing_store_cursor) {
1771 do {
1772 if (!DeleteRecord(
1773 transaction, database_id, object_store_id,
1774 backing_store_cursor->record_identifier()))
1775 return false;
1776 } while (backing_store_cursor->Continue());
1777 }
1778
1779 std::string blob_lower =
1780 BlobEntryKey::Encode(database_id, object_store_id,
1781 key_range.lower());
1782 std::string blob_upper =
1783 BlobEntryKey::Encode(database_id, object_store_id,
1784 key_range.upper());
1785 scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator();
1786 it->Seek(blob_lower);
1787 while (it->IsValid() && key_range.lowerOpen() &&
1788 CompareKeys(it->Key(), blob_lower) == 0)
1789 it->Next();
1790
1791 while (it->IsValid() &&
1792 ((key_range.upperOpen() &&
1793 CompareKeys(it->Key(), blob_upper) < 0) ||
1794 (!key_range.upperOpen() &&
1795 CompareKeys(it->Key(), blob_upper) <= 0))) {
1796 StringPiece key_piece(it->Key());
1797 std::string object_store_data_key =
1798 BlobEntryKey::ReencodeToObjectStoreDataKey(&key_piece);
1799 if (!object_store_data_key.size())
1800 return false;
1801 transaction->PutBlobInfo(database_id, object_store_id,
1802 object_store_data_key, NULL, NULL);
1803 it->Next();
1804 }
1805
1806 return true;
1807 }
1808
1289 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( 1809 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
1290 IndexedDBBackingStore::Transaction* transaction, 1810 IndexedDBBackingStore::Transaction* transaction,
1291 int64 database_id, 1811 int64 database_id,
1292 int64 object_store_id, 1812 int64 object_store_id,
1293 int64* key_generator_current_number) { 1813 int64* key_generator_current_number) {
1294 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1814 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1295 return false; 1815 return false;
1296 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1297 1816
1298 const std::string key_generator_current_number_key = 1817 const std::string key_generator_current_number_key =
1299 ObjectStoreMetaDataKey::Encode( 1818 ObjectStoreMetaDataKey::Encode(
1300 database_id, 1819 database_id,
1301 object_store_id, 1820 object_store_id,
1302 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER); 1821 ObjectStoreMetaDataKey::KEY_GENERATOR_CURRENT_NUMBER);
1303 1822
1304 *key_generator_current_number = -1; 1823 *key_generator_current_number = -1;
1305 std::string data; 1824 std::string data;
1306 1825
1307 bool found = false; 1826 bool found = false;
1308 bool ok = 1827 bool ok = transaction->transaction()->Get(
1309 leveldb_transaction->Get(key_generator_current_number_key, &data, &found); 1828 key_generator_current_number_key, &data, &found);
1310 if (!ok) { 1829 if (!ok) {
1311 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); 1830 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER);
1312 return false; 1831 return false;
1313 } 1832 }
1314 if (found && !data.empty()) { 1833 if (found && !data.empty()) {
1315 StringPiece slice(data); 1834 StringPiece slice(data);
1316 if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) { 1835 if (!DecodeInt(&slice, key_generator_current_number) || !slice.empty()) {
1317 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); 1836 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER);
1318 return false; 1837 return false;
1319 } 1838 }
1320 return true; 1839 return true;
1321 } 1840 }
1322 1841
1323 // Previously, the key generator state was not stored explicitly 1842 // Previously, the key generator state was not stored explicitly
1324 // but derived from the maximum numeric key present in existing 1843 // but derived from the maximum numeric key present in existing
1325 // data. This violates the spec as the data may be cleared but the 1844 // data. This violates the spec as the data may be cleared but the
1326 // key generator state must be preserved. 1845 // key generator state must be preserved.
1327 // TODO(jsbell): Fix this for all stores on database open? 1846 // TODO(jsbell): Fix this for all stores on database open?
1328 const std::string start_key = 1847 const std::string start_key =
1329 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey()); 1848 ObjectStoreDataKey::Encode(database_id, object_store_id, MinIDBKey());
1330 const std::string stop_key = 1849 const std::string stop_key =
1331 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey()); 1850 ObjectStoreDataKey::Encode(database_id, object_store_id, MaxIDBKey());
1332 1851
1333 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator(); 1852 scoped_ptr<LevelDBIterator> it = transaction->transaction()->CreateIterator();
1334 int64 max_numeric_key = 0; 1853 int64 max_numeric_key = 0;
1335 1854
1336 for (it->Seek(start_key); 1855 for (it->Seek(start_key);
1337 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 1856 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
1338 it->Next()) { 1857 it->Next()) {
1339 StringPiece slice(it->Key()); 1858 StringPiece slice(it->Key());
1340 ObjectStoreDataKey data_key; 1859 ObjectStoreDataKey data_key;
1341 if (!ObjectStoreDataKey::Decode(&slice, &data_key)) { 1860 if (!ObjectStoreDataKey::Decode(&slice, &data_key)) {
1342 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER); 1861 INTERNAL_READ_ERROR(GET_KEY_GENERATOR_CURRENT_NUMBER);
1343 return false; 1862 return false;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1414 StringPiece slice(data); 1933 StringPiece slice(data);
1415 if (!DecodeVarInt(&slice, &version)) 1934 if (!DecodeVarInt(&slice, &version))
1416 return false; 1935 return false;
1417 1936
1418 std::string encoded_key; 1937 std::string encoded_key;
1419 EncodeIDBKey(key, &encoded_key); 1938 EncodeIDBKey(key, &encoded_key);
1420 found_record_identifier->Reset(encoded_key, version); 1939 found_record_identifier->Reset(encoded_key, version);
1421 return true; 1940 return true;
1422 } 1941 }
1423 1942
1943 class IndexedDBBackingStore::Transaction::ChainedBlobWriter : public
1944 base::RefCounted<IndexedDBBackingStore::Transaction::ChainedBlobWriter> {
1945 public:
1946 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
1947 WriteDescriptorVec;
1948 ChainedBlobWriter(
1949 int64 database_id,
1950 IndexedDBBackingStore* backingStore,
1951 WriteDescriptorVec& blobs,
1952 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
1953 : waiting_for_callback_(false),
1954 database_id_(database_id),
1955 backing_store_(backingStore),
1956 callback_(callback),
1957 aborted_(false) {
1958 blobs_.swap(blobs);
1959 iter_ = blobs_.begin();
1960 WriteNextFile();
1961 }
1962 ~ChainedBlobWriter() {
1963 }
1964
1965 void set_delegate(scoped_ptr<FileWriterDelegate> delegate) {
1966 delegate_.reset(delegate.release());
1967 }
1968
1969 void ReportWriteCompletion(bool succeeded, int64 bytes_written) {
1970 // TODO(ericu): Is there any need to check bytes_written against what we
1971 // know, if we know it?
1972 DCHECK(waiting_for_callback_);
1973 DCHECK(!succeeded || bytes_written >= 0);
1974 waiting_for_callback_ = false;
1975 content::BrowserThread::DeleteSoon(
1976 content::BrowserThread::IO, FROM_HERE,
1977 delegate_.release());
1978 if (aborted_) {
1979 self_ref_ = NULL;
1980 return;
1981 }
1982 if (succeeded)
1983 WriteNextFile();
1984 else
1985 callback_->didFail();
1986 }
1987
1988 void Abort() {
1989 if (!waiting_for_callback_)
1990 return;
1991 self_ref_ = this;
1992 aborted_ = true;
1993 }
1994
1995 private:
1996 void WriteNextFile() {
1997 DCHECK(!waiting_for_callback_);
1998 DCHECK(!aborted_);
1999 if (iter_ == blobs_.end()) {
2000 DCHECK(!self_ref_);
2001 callback_->didSucceed();
2002 return;
2003 } else {
2004 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
2005 callback_->didFail();
2006 return;
2007 }
2008 waiting_for_callback_ = true;
2009 ++iter_;
2010 }
2011 }
2012
2013 bool waiting_for_callback_;
2014 scoped_refptr<ChainedBlobWriter> self_ref_;
2015 WriteDescriptorVec blobs_;
2016 WriteDescriptorVec::const_iterator iter_;
2017 int64 database_id_;
2018 IndexedDBBackingStore* backing_store_;
2019 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
2020 scoped_ptr<FileWriterDelegate> delegate_;
2021 bool aborted_;
2022 };
2023
2024 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
2025 public base::RefCounted<LocalWriteClosure> {
2026 public:
2027 LocalWriteClosure(
2028 IndexedDBBackingStore::Transaction::ChainedBlobWriter*
2029 chained_blob_writer_,
2030 base::TaskRunner* task_runner)
2031 : chained_blob_writer_(chained_blob_writer_),
2032 task_runner_(task_runner),
2033 bytes_written_(-1) {
2034 }
2035
2036 void Run(
2037 base::PlatformFileError rv,
2038 int64 bytes,
2039 FileWriterDelegate::WriteProgressStatus write_status) {
2040 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
2041 return; // We don't care about progress events.
2042 if (rv == base::PLATFORM_FILE_OK) {
2043 DCHECK(bytes >= 0);
2044 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED);
2045 bytes_written_ = bytes;
2046 } else {
2047 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
2048 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
2049 }
2050 task_runner_->PostTask(
2051 FROM_HERE,
2052 base::Bind(
2053 &LocalWriteClosure::callBlobCallbackOnIDBTaskRunner, this,
2054 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
2055 }
2056
2057 void writeBlobToFileOnIOThread(
2058 const FilePath& file_path, const GURL& blob_url,
2059 net::URLRequestContext* request_context) {
2060 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
2061 scoped_ptr<fileapi::FileStreamWriter> writer(
2062 fileapi::FileStreamWriter::CreateForLocalFile(
2063 task_runner_, file_path, 0, false));
2064 scoped_ptr<FileWriterDelegate> delegate(
2065 new FileWriterDelegate(writer.Pass()));
2066
2067 DCHECK(blob_url.is_valid());
2068 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
2069 blob_url, net::DEFAULT_PRIORITY, delegate.get()));
2070
2071 delegate->Start(blob_request.Pass(),
2072 base::Bind(&LocalWriteClosure::Run, this));
2073 chained_blob_writer_->set_delegate(delegate.Pass());
2074 }
2075
2076 private:
2077 void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
2078 DCHECK(task_runner_->RunsTasksOnCurrentThread());
2079 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
2080 }
2081
2082 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
2083 base::TaskRunner* task_runner_;
2084 int64 bytes_written_;
2085 };
2086
2087 bool IndexedDBBackingStore::WriteBlobFile(
2088 int64 database_id,
2089 const Transaction::WriteDescriptor& descriptor,
2090 Transaction::ChainedBlobWriter* chained_blob_writer) {
2091
2092 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
2093 return false;
2094
2095 FilePath path = GetIDBBlobFileName(database_id, descriptor.key());
2096
2097 if (descriptor.is_file()) {
2098 // TODO(ericu): Should we validate the snapshot date here?
2099 DCHECK(!descriptor.file_path().empty());
2100 if (!base::CopyFile(descriptor.file_path(), path))
2101 return false;
2102
2103 base::PlatformFileInfo info;
2104 if (file_util::GetFileInfo(descriptor.file_path(), &info)) {
2105 if (!file_util::TouchFile(path, info.last_accessed, info.last_modified))
2106 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
2107 } else {
2108 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
2109 }
2110
2111 task_runner_->PostTask(
2112 FROM_HERE,
2113 base::Bind(
2114 &Transaction::ChainedBlobWriter::ReportWriteCompletion,
2115 chained_blob_writer, true, info.size));
2116 } else {
2117 DCHECK(descriptor.url().is_valid());
2118 scoped_refptr<LocalWriteClosure> write_closure(
2119 new LocalWriteClosure(chained_blob_writer, task_runner_));
2120 content::BrowserThread::PostTask(
2121 content::BrowserThread::IO, FROM_HERE,
2122 base::Bind(
2123 &LocalWriteClosure::writeBlobToFileOnIOThread, write_closure.get(),
2124 path, descriptor.url(), request_context_));
2125 }
2126 return true;
2127 }
2128
2129 void IndexedDBBackingStore::ReportBlobUnused(
2130 int64 database_id,
2131 int64 blob_key) {
2132 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
2133 bool all_blobs = blob_key == DatabaseMetaDataKey::kAllBlobsKey;
2134 DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2135 scoped_refptr<LevelDBTransaction> transaction =
2136 new LevelDBTransaction(db_.get());
2137
2138 std::string live_blob_key = LiveBlobJournalKey::Encode();
2139 IndexedDBBackingStore::Transaction::BlobJournalType live_blob_journal;
2140 if (!GetBlobJournal(live_blob_key, transaction.get(), live_blob_journal))
2141 return;
2142 DCHECK(live_blob_journal.size());
2143
2144 std::string primary_key = BlobJournalKey::Encode();
2145 IndexedDBBackingStore::Transaction::BlobJournalType primary_journal;
2146 if (!GetBlobJournal(primary_key, transaction.get(), primary_journal))
2147 return;
2148
2149 IndexedDBBackingStore::Transaction::BlobJournalType::iterator journal_iter;
2150 // There are several cases to handle. If blob_key is kAllBlobsKey, we want to
2151 // remove all entries with database_id from the live_blob journal and add only
2152 // kAllBlobsKey to the primary journal. Otherwise if IsValidBlobKey(blob_key)
2153 // and we hit kAllBlobsKey for the right database_id in the journal, we leave
2154 // the kAllBlobsKey entry in the live_blob journal but add the specific blob
2155 // to the primary. Otherwise if IsValidBlobKey(blob_key) and we find a
2156 // matching (database_id, blob_key) tuple, we should move it to the primary
2157 // journal.
2158 IndexedDBBackingStore::Transaction::BlobJournalType new_live_blob_journal;
2159 for (journal_iter = live_blob_journal.begin();
2160 journal_iter != live_blob_journal.end(); ++journal_iter) {
2161 int64 current_database_id = journal_iter->first;
2162 int64 current_blob_key = journal_iter->second;
2163 bool current_all_blobs =
2164 current_blob_key == DatabaseMetaDataKey::kAllBlobsKey;
2165 DCHECK(KeyPrefix::IsValidDatabaseId(current_database_id) ||
2166 current_all_blobs);
2167 if (current_database_id == database_id && (all_blobs ||
2168 current_all_blobs || blob_key == current_blob_key)) {
2169 if (!all_blobs) {
2170 primary_journal.push_back(
2171 std::make_pair(database_id, current_blob_key));
2172 if (current_all_blobs)
2173 new_live_blob_journal.push_back(*journal_iter);
2174 new_live_blob_journal.insert(new_live_blob_journal.end(),
2175 ++journal_iter, live_blob_journal.end()); // All the rest.
2176 break;
2177 }
2178 } else {
2179 new_live_blob_journal.push_back(*journal_iter);
2180 }
2181 }
2182 if (all_blobs) {
2183 primary_journal.push_back(std::make_pair(
2184 database_id, DatabaseMetaDataKey::kAllBlobsKey));
2185 }
2186 UpdatePrimaryJournalWithBlobList(transaction.get(), primary_journal);
2187 UpdateLiveBlobJournalWithBlobList(transaction.get(), new_live_blob_journal);
2188 transaction->Commit();
2189 // We could just do the deletions/cleaning here, but if there are a lot of
2190 // blobs about to be garbage collected, it'd be better to wait and do them all
2191 // at once.
2192 journal_cleaning_timer_.Start(
2193 FROM_HERE, base::TimeDelta::FromSeconds(5), this,
2194 &IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn);
2195 }
2196
2197 // This assumes a file path of dbId/3rd-byte-of-counter/counter.
2198 FilePath IndexedDBBackingStore::GetIDBBlobFileName(
2199 int64 database_id, int64 key) {
2200 FilePath path = GetIDBBlobDirectoryNameForKey(blob_path_, database_id, key);
2201 path = path.AppendASCII(base::StringPrintf("%lx", key));
2202 return path;
2203 }
2204
1424 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, 2205 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
1425 const std::string& stop_key, 2206 const std::string& stop_key,
1426 int64 index_id, 2207 int64 index_id,
1427 unsigned char meta_data_type) { 2208 unsigned char meta_data_type) {
1428 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 2209 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1429 return false; 2210 return false;
1430 2211
1431 StringPiece slice(it->Key()); 2212 StringPiece slice(it->Key());
1432 IndexMetaDataKey meta_data_key; 2213 IndexMetaDataKey meta_data_key;
1433 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 2214 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 2297
1517 it->Next(); 2298 it->Next();
1518 } 2299 }
1519 2300
1520 (*indexes)[index_id] = IndexedDBIndexMetadata( 2301 (*indexes)[index_id] = IndexedDBIndexMetadata(
1521 index_name, index_id, key_path, index_unique, index_multi_entry); 2302 index_name, index_id, key_path, index_unique, index_multi_entry);
1522 } 2303 }
1523 return true; 2304 return true;
1524 } 2305 }
1525 2306
2307 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
2308 FilePath fileName = GetIDBBlobFileName(database_id, key);
2309 return base::DeleteFile(fileName, false);
2310 }
2311
2312 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
2313 FilePath dirName = GetIDBBlobDirectoryName(blob_path_, database_id);
2314 return base::DeleteFile(dirName, true);
2315 }
2316
2317 bool IndexedDBBackingStore::CleanUpBlobJournal(
2318 const std::string& level_db_key) {
2319 scoped_refptr<LevelDBTransaction> journal_transaction =
2320 new LevelDBTransaction(db_.get());
2321 IndexedDBBackingStore::Transaction::BlobJournalType journal;
2322 if (!GetBlobJournal(level_db_key, journal_transaction.get(),
2323 journal)) {
2324 return false;
2325 }
2326 if (!journal.size()) {
2327 return true;
2328 }
2329 if (journal.size()) {
2330 IndexedDBBackingStore::Transaction::BlobJournalType::iterator journal_iter;
2331 for (journal_iter = journal.begin(); journal_iter != journal.end();
2332 ++journal_iter) {
2333 int64 database_id = journal_iter->first;
2334 int64 blob_key = journal_iter->second;
2335 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
2336 if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
2337 RemoveBlobDirectory(database_id);
2338 } else {
2339 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2340 RemoveBlobFile(database_id, blob_key);
2341 }
2342 }
2343 }
2344 ClearBlobJournal(journal_transaction.get(), level_db_key);
2345 return journal_transaction->Commit();
2346 }
2347
2348 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() {
2349 CleanUpBlobJournal(BlobJournalKey::Encode());
2350 }
2351
1526 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction, 2352 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction,
1527 int64 database_id, 2353 int64 database_id,
1528 int64 object_store_id, 2354 int64 object_store_id,
1529 int64 index_id) { 2355 int64 index_id) {
1530 int64 max_index_id = -1; 2356 int64 max_index_id = -1;
1531 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 2357 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1532 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 2358 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1533 bool found = false; 2359 bool found = false;
1534 bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found); 2360 bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found);
1535 if (!ok) { 2361 if (!ok) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1588 int64 index_id) { 2414 int64 index_id) {
1589 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); 2415 IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
1590 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) 2416 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
1591 return false; 2417 return false;
1592 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 2418 LevelDBTransaction* leveldb_transaction = transaction->transaction();
1593 2419
1594 const std::string index_meta_data_start = 2420 const std::string index_meta_data_start =
1595 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); 2421 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
1596 const std::string index_meta_data_end = 2422 const std::string index_meta_data_end =
1597 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2423 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
1598 DeleteRange(leveldb_transaction, index_meta_data_start, index_meta_data_end); 2424 DeleteRangeByKeys(leveldb_transaction, index_meta_data_start,
2425 index_meta_data_end);
1599 2426
1600 const std::string index_data_start = 2427 const std::string index_data_start =
1601 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); 2428 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
1602 const std::string index_data_end = 2429 const std::string index_data_end =
1603 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2430 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
1604 DeleteRange(leveldb_transaction, index_data_start, index_data_end); 2431 DeleteRangeByKeys(leveldb_transaction, index_data_start, index_data_end);
1605 return true; 2432 return true;
1606 } 2433 }
1607 2434
1608 bool IndexedDBBackingStore::PutIndexDataForRecord( 2435 bool IndexedDBBackingStore::PutIndexDataForRecord(
1609 IndexedDBBackingStore::Transaction* transaction, 2436 IndexedDBBackingStore::Transaction* transaction,
1610 int64 database_id, 2437 int64 database_id,
1611 int64 object_store_id, 2438 int64 object_store_id,
1612 int64 index_id, 2439 int64 index_id,
1613 const IndexedDBKey& key, 2440 const IndexedDBKey& key,
1614 const RecordIdentifier& record_identifier) { 2441 const RecordIdentifier& record_identifier) {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1811 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); 2638 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX);
1812 return false; 2639 return false;
1813 } 2640 }
1814 2641
1815 StringPiece slice(found_encoded_primary_key); 2642 StringPiece slice(found_encoded_primary_key);
1816 return DecodeIDBKey(&slice, found_primary_key) && slice.empty(); 2643 return DecodeIDBKey(&slice, found_primary_key) && slice.empty();
1817 } 2644 }
1818 2645
1819 IndexedDBBackingStore::Cursor::Cursor( 2646 IndexedDBBackingStore::Cursor::Cursor(
1820 const IndexedDBBackingStore::Cursor* other) 2647 const IndexedDBBackingStore::Cursor* other)
1821 : transaction_(other->transaction_), 2648 : backing_store_(other->backing_store_),
2649 transaction_(other->transaction_),
2650 database_id_(other->database_id_),
1822 cursor_options_(other->cursor_options_), 2651 cursor_options_(other->cursor_options_),
1823 current_key_(new IndexedDBKey(*other->current_key_)) { 2652 current_key_(new IndexedDBKey(*other->current_key_)) {
1824 if (other->iterator_) { 2653 if (other->iterator_) {
1825 iterator_ = transaction_->CreateIterator(); 2654 iterator_ = transaction_->CreateIterator();
1826 2655
1827 if (other->iterator_->IsValid()) { 2656 if (other->iterator_->IsValid()) {
1828 iterator_->Seek(other->iterator_->Key()); 2657 iterator_->Seek(other->iterator_->Key());
1829 DCHECK(iterator_->IsValid()); 2658 DCHECK(iterator_->IsValid());
1830 } 2659 }
1831 } 2660 }
1832 } 2661 }
1833 2662
1834 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction, 2663 IndexedDBBackingStore::Cursor::Cursor(
1835 const CursorOptions& cursor_options) 2664 scoped_refptr<IndexedDBBackingStore> backing_store,
1836 : transaction_(transaction), cursor_options_(cursor_options) {} 2665 LevelDBTransaction* transaction,
2666 int64 database_id,
2667 const CursorOptions& cursor_options)
2668 : backing_store_(backing_store),
2669 transaction_(transaction),
2670 database_id_(database_id),
2671 cursor_options_(cursor_options) {
2672 }
1837 IndexedDBBackingStore::Cursor::~Cursor() {} 2673 IndexedDBBackingStore::Cursor::~Cursor() {}
1838 2674
1839 bool IndexedDBBackingStore::Cursor::FirstSeek() { 2675 bool IndexedDBBackingStore::Cursor::FirstSeek() {
1840 iterator_ = transaction_->CreateIterator(); 2676 iterator_ = transaction_->CreateIterator();
1841 if (cursor_options_.forward) 2677 if (cursor_options_.forward)
1842 iterator_->Seek(cursor_options_.low_key); 2678 iterator_->Seek(cursor_options_.low_key);
1843 else 2679 else
1844 iterator_->Seek(cursor_options_.high_key); 2680 iterator_->Seek(cursor_options_.high_key);
1845 2681
1846 return Continue(0, READY); 2682 return Continue(0, READY);
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
2006 } 2842 }
2007 2843
2008 const IndexedDBBackingStore::RecordIdentifier& 2844 const IndexedDBBackingStore::RecordIdentifier&
2009 IndexedDBBackingStore::Cursor::record_identifier() const { 2845 IndexedDBBackingStore::Cursor::record_identifier() const {
2010 return record_identifier_; 2846 return record_identifier_;
2011 } 2847 }
2012 2848
2013 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { 2849 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
2014 public: 2850 public:
2015 ObjectStoreKeyCursorImpl( 2851 ObjectStoreKeyCursorImpl(
2852 scoped_refptr<IndexedDBBackingStore> backing_store,
2016 LevelDBTransaction* transaction, 2853 LevelDBTransaction* transaction,
2854 int64 database_id,
2017 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 2855 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2018 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 2856 : IndexedDBBackingStore::Cursor(
2857 backing_store, transaction, database_id, cursor_options) {}
2019 2858
2020 virtual Cursor* Clone() OVERRIDE { 2859 virtual Cursor* Clone() OVERRIDE {
2021 return new ObjectStoreKeyCursorImpl(this); 2860 return new ObjectStoreKeyCursorImpl(this);
2022 } 2861 }
2023 2862
2024 // IndexedDBBackingStore::Cursor 2863 // IndexedDBBackingStore::Cursor
2025 virtual std::string* Value() OVERRIDE { 2864 virtual IndexedDBValue* Value() OVERRIDE {
2026 NOTREACHED(); 2865 NOTREACHED();
2027 return NULL; 2866 return NULL;
2028 } 2867 }
2029 virtual bool LoadCurrentRow() OVERRIDE; 2868 virtual bool LoadCurrentRow() OVERRIDE;
2030 2869
2031 protected: 2870 protected:
2032 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 2871 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2033 return ObjectStoreDataKey::Encode( 2872 return ObjectStoreDataKey::Encode(
2034 cursor_options_.database_id, cursor_options_.object_store_id, key); 2873 cursor_options_.database_id, cursor_options_.object_store_id, key);
2035 } 2874 }
(...skipping 29 matching lines...) Expand all
2065 std::string encoded_key; 2904 std::string encoded_key;
2066 EncodeIDBKey(*current_key_, &encoded_key); 2905 EncodeIDBKey(*current_key_, &encoded_key);
2067 record_identifier_.Reset(encoded_key, version); 2906 record_identifier_.Reset(encoded_key, version);
2068 2907
2069 return true; 2908 return true;
2070 } 2909 }
2071 2910
2072 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { 2911 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
2073 public: 2912 public:
2074 ObjectStoreCursorImpl( 2913 ObjectStoreCursorImpl(
2914 scoped_refptr<IndexedDBBackingStore> backing_store,
2075 LevelDBTransaction* transaction, 2915 LevelDBTransaction* transaction,
2916 int64 database_id,
2076 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 2917 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2077 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 2918 : IndexedDBBackingStore::Cursor(
2919 backing_store, transaction, database_id, cursor_options) {}
2078 2920
2079 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); } 2921 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
2080 2922
2081 // IndexedDBBackingStore::Cursor 2923 // IndexedDBBackingStore::Cursor
2082 virtual std::string* Value() OVERRIDE { return &current_value_; } 2924 virtual IndexedDBValue* Value() OVERRIDE { return &current_value_; }
2083 virtual bool LoadCurrentRow() OVERRIDE; 2925 virtual bool LoadCurrentRow() OVERRIDE;
2084 2926
2085 protected: 2927 protected:
2086 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 2928 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2087 return ObjectStoreDataKey::Encode( 2929 return ObjectStoreDataKey::Encode(
2088 cursor_options_.database_id, cursor_options_.object_store_id, key); 2930 cursor_options_.database_id, cursor_options_.object_store_id, key);
2089 } 2931 }
2090 virtual std::string EncodeKey(const IndexedDBKey& key, 2932 virtual std::string EncodeKey(const IndexedDBKey& key,
2091 const IndexedDBKey& primary_key) OVERRIDE { 2933 const IndexedDBKey& primary_key) OVERRIDE {
2092 NOTREACHED(); 2934 NOTREACHED();
2093 return std::string(); 2935 return std::string();
2094 } 2936 }
2095 2937
2096 private: 2938 private:
2097 explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other) 2939 explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
2098 : IndexedDBBackingStore::Cursor(other), 2940 : IndexedDBBackingStore::Cursor(other),
2099 current_value_(other->current_value_) {} 2941 current_value_(other->current_value_) {}
2100 2942
2101 std::string current_value_; 2943 IndexedDBValue current_value_;
2102 }; 2944 };
2103 2945
2104 bool ObjectStoreCursorImpl::LoadCurrentRow() { 2946 bool ObjectStoreCursorImpl::LoadCurrentRow() {
2105 StringPiece slice(iterator_->Key()); 2947 StringPiece key_slice(iterator_->Key());
2106 ObjectStoreDataKey object_store_data_key; 2948 ObjectStoreDataKey object_store_data_key;
2107 if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) { 2949 if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) {
2108 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2950 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2109 return false; 2951 return false;
2110 } 2952 }
2111 2953
2112 current_key_ = object_store_data_key.user_key(); 2954 current_key_ = object_store_data_key.user_key();
2113 2955
2114 int64 version; 2956 int64 version;
2115 slice = StringPiece(iterator_->Value()); 2957 StringPiece value_slice = StringPiece(iterator_->Value());
2116 if (!DecodeVarInt(&slice, &version)) { 2958 if (!DecodeVarInt(&value_slice, &version)) {
2117 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 2959 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2118 return false; 2960 return false;
2119 } 2961 }
2120 2962
2121 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. 2963 // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
2122 std::string encoded_key; 2964 std::string encoded_key;
2123 EncodeIDBKey(*current_key_, &encoded_key); 2965 EncodeIDBKey(*current_key_, &encoded_key);
2124 record_identifier_.Reset(encoded_key, version); 2966 record_identifier_.Reset(encoded_key, version);
2125 2967
2126 current_value_ = slice.as_string(); 2968 // TODO(ericu): Don't set bits until we know we've succeeded?
2127 return true; 2969 current_value_.bits = value_slice.as_string();
2970 return GetBlobInfoForRecord(backing_store_, transaction_, database_id_,
2971 iterator_->Key().as_string(), &current_value_);
2128 } 2972 }
2129 2973
2130 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { 2974 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
2131 public: 2975 public:
2132 IndexKeyCursorImpl( 2976 IndexKeyCursorImpl(
2977 scoped_refptr<IndexedDBBackingStore> backing_store,
2133 LevelDBTransaction* transaction, 2978 LevelDBTransaction* transaction,
2979 int64 database_id,
2134 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 2980 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2135 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 2981 : IndexedDBBackingStore::Cursor(
2982 backing_store, transaction, database_id, cursor_options) {}
2136 2983
2137 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); } 2984 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
2138 2985
2139 // IndexedDBBackingStore::Cursor 2986 // IndexedDBBackingStore::Cursor
2140 virtual std::string* Value() OVERRIDE { 2987 virtual IndexedDBValue* Value() OVERRIDE {
2141 NOTREACHED(); 2988 NOTREACHED();
2142 return NULL; 2989 return NULL;
2143 } 2990 }
2144 virtual const IndexedDBKey& primary_key() const OVERRIDE { 2991 virtual const IndexedDBKey& primary_key() const OVERRIDE {
2145 return *primary_key_; 2992 return *primary_key_;
2146 } 2993 }
2147 virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() 2994 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
2148 const { 2995 const OVERRIDE {
2149 NOTREACHED(); 2996 NOTREACHED();
2150 return record_identifier_; 2997 return record_identifier_;
2151 } 2998 }
2152 virtual bool LoadCurrentRow() OVERRIDE; 2999 virtual bool LoadCurrentRow() OVERRIDE;
2153 3000
2154 protected: 3001 protected:
2155 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 3002 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2156 return IndexDataKey::Encode(cursor_options_.database_id, 3003 return IndexDataKey::Encode(cursor_options_.database_id,
2157 cursor_options_.object_store_id, 3004 cursor_options_.object_store_id,
2158 cursor_options_.index_id, 3005 cursor_options_.index_id,
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2230 transaction_->Remove(iterator_->Key()); 3077 transaction_->Remove(iterator_->Key());
2231 return false; 3078 return false;
2232 } 3079 }
2233 3080
2234 return true; 3081 return true;
2235 } 3082 }
2236 3083
2237 class IndexCursorImpl : public IndexedDBBackingStore::Cursor { 3084 class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
2238 public: 3085 public:
2239 IndexCursorImpl( 3086 IndexCursorImpl(
3087 scoped_refptr<IndexedDBBackingStore> backing_store,
2240 LevelDBTransaction* transaction, 3088 LevelDBTransaction* transaction,
3089 int64 database_id,
2241 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3090 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2242 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3091 : IndexedDBBackingStore::Cursor(
3092 backing_store, transaction, database_id, cursor_options) {}
2243 3093
2244 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); } 3094 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
2245 3095
2246 // IndexedDBBackingStore::Cursor 3096 // IndexedDBBackingStore::Cursor
2247 virtual std::string* Value() OVERRIDE { return &current_value_; } 3097 virtual IndexedDBValue* Value() OVERRIDE { return &current_value_; }
2248 virtual const IndexedDBKey& primary_key() const OVERRIDE { 3098 virtual const IndexedDBKey& primary_key() const OVERRIDE {
2249 return *primary_key_; 3099 return *primary_key_;
2250 } 3100 }
2251 virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() 3101 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
2252 const { 3102 const OVERRIDE {
2253 NOTREACHED(); 3103 NOTREACHED();
2254 return record_identifier_; 3104 return record_identifier_;
2255 } 3105 }
2256 virtual bool LoadCurrentRow() OVERRIDE; 3106 virtual bool LoadCurrentRow() OVERRIDE;
2257 3107
2258 protected: 3108 protected:
2259 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 3109 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2260 return IndexDataKey::Encode(cursor_options_.database_id, 3110 return IndexDataKey::Encode(cursor_options_.database_id,
2261 cursor_options_.object_store_id, 3111 cursor_options_.object_store_id,
2262 cursor_options_.index_id, 3112 cursor_options_.index_id,
2263 key); 3113 key);
2264 } 3114 }
2265 virtual std::string EncodeKey(const IndexedDBKey& key, 3115 virtual std::string EncodeKey(const IndexedDBKey& key,
2266 const IndexedDBKey& primary_key) OVERRIDE { 3116 const IndexedDBKey& primary_key) OVERRIDE {
2267 return IndexDataKey::Encode(cursor_options_.database_id, 3117 return IndexDataKey::Encode(cursor_options_.database_id,
2268 cursor_options_.object_store_id, 3118 cursor_options_.object_store_id,
2269 cursor_options_.index_id, 3119 cursor_options_.index_id,
2270 key, 3120 key,
2271 primary_key); 3121 primary_key);
2272 } 3122 }
2273 3123
2274 private: 3124 private:
2275 explicit IndexCursorImpl(const IndexCursorImpl* other) 3125 explicit IndexCursorImpl(const IndexCursorImpl* other)
2276 : IndexedDBBackingStore::Cursor(other), 3126 : IndexedDBBackingStore::Cursor(other),
2277 primary_key_(new IndexedDBKey(*other->primary_key_)), 3127 primary_key_(new IndexedDBKey(*other->primary_key_)),
2278 current_value_(other->current_value_), 3128 current_value_(other->current_value_),
2279 primary_leveldb_key_(other->primary_leveldb_key_) {} 3129 primary_leveldb_key_(other->primary_leveldb_key_) {}
2280 3130
2281 scoped_ptr<IndexedDBKey> primary_key_; 3131 scoped_ptr<IndexedDBKey> primary_key_;
2282 std::string current_value_; 3132 IndexedDBValue current_value_;
2283 std::string primary_leveldb_key_; 3133 std::string primary_leveldb_key_;
2284 }; 3134 };
2285 3135
2286 bool IndexCursorImpl::LoadCurrentRow() { 3136 bool IndexCursorImpl::LoadCurrentRow() {
2287 StringPiece slice(iterator_->Key()); 3137 StringPiece slice(iterator_->Key());
2288 IndexDataKey index_data_key; 3138 IndexDataKey index_data_key;
2289 if (!IndexDataKey::Decode(&slice, &index_data_key)) { 3139 if (!IndexDataKey::Decode(&slice, &index_data_key)) {
2290 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3140 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2291 return false; 3141 return false;
2292 } 3142 }
2293 3143
2294 current_key_ = index_data_key.user_key(); 3144 current_key_ = index_data_key.user_key();
2295 DCHECK(current_key_); 3145 DCHECK(current_key_);
2296 3146
2297 slice = StringPiece(iterator_->Value()); 3147 slice = StringPiece(iterator_->Value());
2298 int64 index_data_version; 3148 int64 index_data_version;
2299 if (!DecodeVarInt(&slice, &index_data_version)) { 3149 if (!DecodeVarInt(&slice, &index_data_version)) {
2300 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3150 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2301 return false; 3151 return false;
2302 } 3152 }
2303 if (!DecodeIDBKey(&slice, &primary_key_)) { 3153 if (!DecodeIDBKey(&slice, &primary_key_)) {
2304 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3154 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2305 return false; 3155 return false;
2306 } 3156 }
2307 3157
3158 DCHECK_EQ(index_data_key.DatabaseId(), database_id_);
2308 primary_leveldb_key_ = 3159 primary_leveldb_key_ =
2309 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), 3160 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
2310 index_data_key.ObjectStoreId(), 3161 index_data_key.ObjectStoreId(),
2311 *primary_key_); 3162 *primary_key_);
2312 3163
2313 std::string result; 3164 std::string result;
2314 bool found = false; 3165 bool found = false;
2315 bool ok = transaction_->Get(primary_leveldb_key_, &result, &found); 3166 bool ok = transaction_->Get(primary_leveldb_key_, &result, &found);
2316 if (!ok) { 3167 if (!ok) {
2317 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3168 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
(...skipping 13 matching lines...) Expand all
2331 if (!DecodeVarInt(&slice, &object_store_data_version)) { 3182 if (!DecodeVarInt(&slice, &object_store_data_version)) {
2332 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3183 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2333 return false; 3184 return false;
2334 } 3185 }
2335 3186
2336 if (object_store_data_version != index_data_version) { 3187 if (object_store_data_version != index_data_version) {
2337 transaction_->Remove(iterator_->Key()); 3188 transaction_->Remove(iterator_->Key());
2338 return false; 3189 return false;
2339 } 3190 }
2340 3191
2341 current_value_ = slice.as_string(); 3192 current_value_.bits = slice.as_string();
2342 return true; 3193 return GetBlobInfoForRecord(backing_store_, transaction_, database_id_,
3194 primary_leveldb_key_, &current_value_);
2343 } 3195 }
2344 3196
2345 bool ObjectStoreCursorOptions( 3197 bool ObjectStoreCursorOptions(
2346 LevelDBTransaction* transaction, 3198 LevelDBTransaction* transaction,
2347 int64 database_id, 3199 int64 database_id,
2348 int64 object_store_id, 3200 int64 object_store_id,
2349 const IndexedDBKeyRange& range, 3201 const IndexedDBKeyRange& range,
2350 indexed_db::CursorDirection direction, 3202 indexed_db::CursorDirection direction,
2351 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) { 3203 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
2352 cursor_options->database_id = database_id; 3204 cursor_options->database_id = database_id;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2489 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3341 LevelDBTransaction* leveldb_transaction = transaction->transaction();
2490 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3342 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2491 if (!ObjectStoreCursorOptions(leveldb_transaction, 3343 if (!ObjectStoreCursorOptions(leveldb_transaction,
2492 database_id, 3344 database_id,
2493 object_store_id, 3345 object_store_id,
2494 range, 3346 range,
2495 direction, 3347 direction,
2496 &cursor_options)) 3348 &cursor_options))
2497 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3349 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2498 scoped_ptr<ObjectStoreCursorImpl> cursor( 3350 scoped_ptr<ObjectStoreCursorImpl> cursor(
2499 new ObjectStoreCursorImpl(leveldb_transaction, cursor_options)); 3351 new ObjectStoreCursorImpl(
3352 this, leveldb_transaction, database_id, cursor_options));
2500 if (!cursor->FirstSeek()) 3353 if (!cursor->FirstSeek())
2501 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3354 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2502 3355
2503 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3356 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2504 } 3357 }
2505 3358
2506 scoped_ptr<IndexedDBBackingStore::Cursor> 3359 scoped_ptr<IndexedDBBackingStore::Cursor>
2507 IndexedDBBackingStore::OpenObjectStoreKeyCursor( 3360 IndexedDBBackingStore::OpenObjectStoreKeyCursor(
2508 IndexedDBBackingStore::Transaction* transaction, 3361 IndexedDBBackingStore::Transaction* transaction,
2509 int64 database_id, 3362 int64 database_id,
2510 int64 object_store_id, 3363 int64 object_store_id,
2511 const IndexedDBKeyRange& range, 3364 const IndexedDBKeyRange& range,
2512 indexed_db::CursorDirection direction) { 3365 indexed_db::CursorDirection direction) {
2513 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); 3366 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
2514 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3367 LevelDBTransaction* leveldb_transaction = transaction->transaction();
2515 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3368 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2516 if (!ObjectStoreCursorOptions(leveldb_transaction, 3369 if (!ObjectStoreCursorOptions(leveldb_transaction,
2517 database_id, 3370 database_id,
2518 object_store_id, 3371 object_store_id,
2519 range, 3372 range,
2520 direction, 3373 direction,
2521 &cursor_options)) 3374 &cursor_options))
2522 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3375 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2523 scoped_ptr<ObjectStoreKeyCursorImpl> cursor( 3376 scoped_ptr<ObjectStoreKeyCursorImpl> cursor(
2524 new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options)); 3377 new ObjectStoreKeyCursorImpl(
3378 this, leveldb_transaction, database_id, cursor_options));
2525 if (!cursor->FirstSeek()) 3379 if (!cursor->FirstSeek())
2526 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3380 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2527 3381
2528 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3382 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2529 } 3383 }
2530 3384
2531 scoped_ptr<IndexedDBBackingStore::Cursor> 3385 scoped_ptr<IndexedDBBackingStore::Cursor>
2532 IndexedDBBackingStore::OpenIndexKeyCursor( 3386 IndexedDBBackingStore::OpenIndexKeyCursor(
2533 IndexedDBBackingStore::Transaction* transaction, 3387 IndexedDBBackingStore::Transaction* transaction,
2534 int64 database_id, 3388 int64 database_id,
2535 int64 object_store_id, 3389 int64 object_store_id,
2536 int64 index_id, 3390 int64 index_id,
2537 const IndexedDBKeyRange& range, 3391 const IndexedDBKeyRange& range,
2538 indexed_db::CursorDirection direction) { 3392 indexed_db::CursorDirection direction) {
2539 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); 3393 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
2540 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3394 LevelDBTransaction* leveldb_transaction = transaction->transaction();
2541 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3395 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2542 if (!IndexCursorOptions(leveldb_transaction, 3396 if (!IndexCursorOptions(leveldb_transaction,
2543 database_id, 3397 database_id,
2544 object_store_id, 3398 object_store_id,
2545 index_id, 3399 index_id,
2546 range, 3400 range,
2547 direction, 3401 direction,
2548 &cursor_options)) 3402 &cursor_options))
2549 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3403 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2550 scoped_ptr<IndexKeyCursorImpl> cursor( 3404 scoped_ptr<IndexKeyCursorImpl> cursor(
2551 new IndexKeyCursorImpl(leveldb_transaction, cursor_options)); 3405 new IndexKeyCursorImpl(
3406 this, leveldb_transaction, database_id, cursor_options));
2552 if (!cursor->FirstSeek()) 3407 if (!cursor->FirstSeek())
2553 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3408 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2554 3409
2555 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3410 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2556 } 3411 }
2557 3412
2558 scoped_ptr<IndexedDBBackingStore::Cursor> 3413 scoped_ptr<IndexedDBBackingStore::Cursor>
2559 IndexedDBBackingStore::OpenIndexCursor( 3414 IndexedDBBackingStore::OpenIndexCursor(
2560 IndexedDBBackingStore::Transaction* transaction, 3415 IndexedDBBackingStore::Transaction* transaction,
2561 int64 database_id, 3416 int64 database_id,
2562 int64 object_store_id, 3417 int64 object_store_id,
2563 int64 index_id, 3418 int64 index_id,
2564 const IndexedDBKeyRange& range, 3419 const IndexedDBKeyRange& range,
2565 indexed_db::CursorDirection direction) { 3420 indexed_db::CursorDirection direction) {
2566 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); 3421 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
2567 LevelDBTransaction* leveldb_transaction = transaction->transaction(); 3422 LevelDBTransaction* leveldb_transaction = transaction->transaction();
2568 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3423 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2569 if (!IndexCursorOptions(leveldb_transaction, 3424 if (!IndexCursorOptions(leveldb_transaction,
2570 database_id, 3425 database_id,
2571 object_store_id, 3426 object_store_id,
2572 index_id, 3427 index_id,
2573 range, 3428 range,
2574 direction, 3429 direction,
2575 &cursor_options)) 3430 &cursor_options))
2576 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3431 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2577 scoped_ptr<IndexCursorImpl> cursor( 3432 scoped_ptr<IndexCursorImpl> cursor(
2578 new IndexCursorImpl(leveldb_transaction, cursor_options)); 3433 new IndexCursorImpl(
3434 this, leveldb_transaction, database_id, cursor_options));
2579 if (!cursor->FirstSeek()) 3435 if (!cursor->FirstSeek())
2580 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3436 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2581 3437
2582 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3438 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2583 } 3439 }
2584 3440
2585 IndexedDBBackingStore::Transaction::Transaction( 3441 IndexedDBBackingStore::Transaction::Transaction(
2586 IndexedDBBackingStore* backing_store) 3442 IndexedDBBackingStore* backing_store)
2587 : backing_store_(backing_store) {} 3443 : backing_store_(backing_store),
3444 database_id_(-1) {
3445 }
2588 3446
2589 IndexedDBBackingStore::Transaction::~Transaction() {} 3447 IndexedDBBackingStore::Transaction::~Transaction() {
3448 BlobChangeMap::iterator iter = blob_change_map_.begin();
3449 for (; iter != blob_change_map_.end(); ++iter) {
3450 delete iter->second;
3451 }
3452 }
2590 3453
2591 void IndexedDBBackingStore::Transaction::Begin() { 3454 void IndexedDBBackingStore::Transaction::Begin() {
2592 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); 3455 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin");
2593 DCHECK(!transaction_.get()); 3456 DCHECK(!transaction_.get());
2594 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); 3457 transaction_ = new LevelDBTransaction(backing_store_->db_.get());
2595 } 3458 }
2596 3459
2597 bool IndexedDBBackingStore::Transaction::Commit() { 3460 static GURL getURLFromUUID(const string& uuid) {
2598 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3461 return GURL("blob:uuid/" + uuid);
2599 DCHECK(transaction_.get()); 3462 }
3463
3464 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() {
3465 DeleteHandles();
3466 }
3467
3468 void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetBlobInfo(
3469 std::vector<IndexedDBBlobInfo>* blob_info) {
3470 blob_info_.clear();
3471 if (blob_info)
3472 blob_info_.swap(*blob_info);
3473 }
3474
3475 void IndexedDBBackingStore::Transaction::BlobChangeRecord::DeleteHandles() {
3476 std::vector<webkit_blob::BlobDataHandle*>::iterator iter;
3477 for (iter = handles_.begin(); iter != handles_.end(); ++iter) {
3478 delete *iter;
3479 }
3480 handles_.clear();
3481 }
3482
3483 void IndexedDBBackingStore::Transaction::BlobChangeRecord::SetHandles(
3484 std::vector<webkit_blob::BlobDataHandle*>* handles) {
3485 DeleteHandles();
3486 if (handles)
3487 handles_.swap(*handles);
3488 }
3489
3490 bool IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
3491 BlobEntryKeyValuePairVec* new_blob_entries,
3492 WriteDescriptorVec* new_files_to_write) {
3493 BlobChangeMap::iterator iter = blob_change_map_.begin();
3494 new_blob_entries->clear();
3495 new_files_to_write->clear();
3496 if (iter != blob_change_map_.end()) {
3497 // Create LevelDBTransaction for the name generator seed and add-journal.
3498 scoped_refptr<LevelDBTransaction> pre_transaction =
3499 new LevelDBTransaction(backing_store_->db_.get());
3500 BlobJournalType journal;
3501 for (; iter != blob_change_map_.end(); ++iter) {
3502 std::vector<IndexedDBBlobInfo>::iterator info_iter;
3503 std::vector<IndexedDBBlobInfo*> new_blob_keys;
3504 for (info_iter = iter->second->mutable_blob_info().begin();
3505 info_iter != iter->second->mutable_blob_info().end(); ++info_iter) {
3506 int64 next_blob_key = -1;
3507 bool result = GetBlobKeyGeneratorCurrentNumber(
3508 pre_transaction.get(), database_id_, next_blob_key);
3509 if (!result || next_blob_key < 0)
3510 return false;
3511 BlobJournalEntryType journal_entry =
3512 std::make_pair(database_id_, next_blob_key);
3513 journal.push_back(journal_entry);
3514 if (info_iter->is_file()) {
3515 new_files_to_write->push_back(
3516 WriteDescriptor(info_iter->file_path(), next_blob_key));
3517 } else {
3518 new_files_to_write->push_back(
3519 WriteDescriptor(
3520 getURLFromUUID(info_iter->uuid()), next_blob_key));
3521 }
3522 info_iter->set_key(next_blob_key);
3523 new_blob_keys.push_back(&*info_iter);
3524 result = UpdateBlobKeyGeneratorCurrentNumber(
3525 pre_transaction.get(), database_id_, next_blob_key + 1);
3526 if (!result)
3527 return result;
3528 }
3529 BlobEntryKey blob_entry_key;
3530 StringPiece key_piece(iter->second->key());
3531 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3532 NOTREACHED();
3533 return false;
3534 }
3535 new_blob_entries->push_back(std::make_pair(blob_entry_key,
3536 EncodeBlobData(new_blob_keys)));
3537 }
3538 UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal);
3539 if (!pre_transaction->Commit())
3540 return false;
3541 }
3542 return true;
3543 }
3544
3545 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
3546 BlobChangeMap::iterator iter = blob_change_map_.begin();
3547 // Look up all old files to remove as part of the transaction, store their
3548 // names in blobs_to_remove_, and remove their old blob data entries.
3549 if (iter != blob_change_map_.end()) {
3550 scoped_ptr<LevelDBIterator> db_iter = transaction_->CreateIterator();
3551 for (; iter != blob_change_map_.end(); ++iter) {
3552 BlobEntryKey blob_entry_key;
3553 StringPiece key_piece(iter->second->key());
3554 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3555 NOTREACHED();
3556 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3557 transaction_ = NULL;
3558 return false;
3559 }
3560 if (database_id_ < 0)
3561 database_id_ = blob_entry_key.database_id();
3562 else
3563 DCHECK_EQ(database_id_, blob_entry_key.database_id());
3564 std::string blob_entry_key_bytes = blob_entry_key.Encode();
3565 db_iter->Seek(blob_entry_key_bytes);
3566 if (db_iter->IsValid()) {
3567 std::vector<IndexedDBBlobInfo> blob_info;
3568 if (!DecodeBlobData(db_iter->Value().as_string(), &blob_info)) {
3569 INTERNAL_READ_ERROR(TRANSACTION_COMMIT_METHOD);
3570 transaction_ = NULL;
3571 return false;
3572 }
3573 std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
3574 for (blob_info_iter = blob_info.begin();
3575 blob_info_iter != blob_info.end(); ++blob_info_iter)
3576 blobs_to_remove_.push_back(
3577 std::make_pair(database_id_, blob_info_iter->key()));
3578 transaction_->Remove(blob_entry_key_bytes);
3579 }
3580 }
3581 }
3582 return true;
3583 }
3584
3585 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper :
3586 public IndexedDBBackingStore::BlobWriteCallback {
3587 public:
3588 BlobWriteCallbackWrapper(
3589 IndexedDBBackingStore::Transaction* transaction,
3590 scoped_refptr<BlobWriteCallback> callback)
3591 : transaction_(transaction),
3592 callback_(callback) {
3593 }
3594 virtual void didSucceed() {
3595 callback_->didSucceed();
3596 transaction_->chained_blob_writer_ = NULL;
3597 }
3598 virtual void didFail() {
3599 callback_->didFail();
3600 transaction_->chained_blob_writer_ = NULL;
3601 }
3602 private:
3603 IndexedDBBackingStore::Transaction* transaction_;
3604 scoped_refptr<BlobWriteCallback> callback_;
3605 };
3606
3607 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
3608 BlobEntryKeyValuePairVec& new_blob_entries,
3609 WriteDescriptorVec& new_files_to_write,
3610 scoped_refptr<BlobWriteCallback> callback) {
3611 DCHECK_GT(new_files_to_write.size(), 0UL);
3612 DCHECK_GT(database_id_, 0);
3613 BlobEntryKeyValuePairVec::iterator blob_entry_iter;
3614 for (blob_entry_iter = new_blob_entries.begin();
3615 blob_entry_iter != new_blob_entries.end(); ++blob_entry_iter) {
3616 // Add the new blob-table entry for each blob to the main transaction, or
3617 // remove any entry that may exist if there's no new one.
3618 if (!blob_entry_iter->second.size())
3619 transaction_->Remove(blob_entry_iter->first.Encode());
3620 else
3621 transaction_->Put(blob_entry_iter->first.Encode(),
3622 &blob_entry_iter->second);
3623 }
3624 // Creating the writer will start it going asynchronously.
3625 chained_blob_writer_ = new ChainedBlobWriter(database_id_, backing_store_,
3626 new_files_to_write, new BlobWriteCallbackWrapper(this, callback));
3627 }
3628
3629 bool IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
3630 IndexedDBActiveBlobRegistry* registry =
3631 backing_store_->active_blob_registry();
3632 BlobJournalType::iterator iter;
3633 BlobJournalType primary_journal, live_blob_journal;
3634 for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
3635 ++iter) {
3636 if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
3637 live_blob_journal.push_back(*iter);
3638 else
3639 primary_journal.push_back(*iter);
3640 }
3641 UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
3642 if (!MergeBlobsIntoLiveBlobJournal(transaction_.get(), live_blob_journal))
3643 return false;
3644 // To signal how many blobs need attention right now.
3645 blobs_to_remove_.swap(primary_journal);
3646 return true;
3647 }
3648
3649 bool IndexedDBBackingStore::Transaction::CommitPhaseOne(
3650 scoped_refptr<BlobWriteCallback> callback) {
3651 IDB_TRACE("IndexedDBBackingStore::Transaction::commit");
3652 DCHECK(transaction_);
3653 DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
3654
3655 if (!backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode())) {
3656 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3657 transaction_ = NULL;
3658 return false;
3659 }
3660
3661 BlobEntryKeyValuePairVec new_blob_entries;
3662 WriteDescriptorVec new_files_to_write;
3663 // This commits the journal of blob files we're about to add, if any.
3664 if (!HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write)) {
3665 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3666 transaction_ = NULL;
3667 return false;
3668 }
3669
3670 DCHECK(!new_files_to_write.size() ||
3671 KeyPrefix::IsValidDatabaseId(database_id_));
3672 if (!CollectBlobFilesToRemove()) {
3673 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3674 transaction_ = NULL;
3675 return false;
3676 }
3677
3678 if (new_files_to_write.size()) {
3679 // This kicks off the writes of the new blobs, if any.
3680 // This call will zero out new_blob_entries and new_files_to_write.
3681 WriteNewBlobs(new_blob_entries, new_files_to_write, callback);
3682 // Remove the add journal, if any; once the blobs are written, and we
3683 // commit, this will do the cleanup.
3684 ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
3685 } else {
3686 callback->didSucceed();
3687 }
3688
3689 return true;
3690 }
3691
3692 bool IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
3693 if (blobs_to_remove_.size())
3694 if (!SortBlobsToRemove()) {
3695 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3696 transaction_ = NULL;
3697 return false;
3698 }
3699
2600 bool result = transaction_->Commit(); 3700 bool result = transaction_->Commit();
2601 transaction_ = NULL; 3701 transaction_ = NULL;
3702
2602 if (!result) 3703 if (!result)
2603 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); 3704 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3705 else if (blobs_to_remove_.size())
3706 backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
3707
2604 return result; 3708 return result;
2605 } 3709 }
2606 3710
2607 void IndexedDBBackingStore::Transaction::Rollback() { 3711 void IndexedDBBackingStore::Transaction::Rollback() {
2608 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 3712 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2609 DCHECK(transaction_.get()); 3713 DCHECK(transaction_.get());
3714 if (chained_blob_writer_) {
3715 chained_blob_writer_->Abort();
3716 chained_blob_writer_ = NULL;
3717 }
2610 transaction_->Rollback(); 3718 transaction_->Rollback();
2611 transaction_ = NULL; 3719 transaction_ = NULL;
2612 } 3720 }
2613 3721
3722 // This is storing an info, even if empty, even if the previous key had no blob
3723 // info that we know of. It duplicates a bunch of information stored in the
3724 // leveldb transaction, but only w.r.t. the user keys altered--we don't keep the
3725 // changes to exists or index keys here.
3726 void IndexedDBBackingStore::Transaction::PutBlobInfo(
3727 int64 database_id,
3728 int64 object_store_id,
3729 const std::string& key,
3730 std::vector<IndexedDBBlobInfo>* blob_info,
3731 std::vector<webkit_blob::BlobDataHandle*>* handles) {
3732 DCHECK_GT(key.size(), 0UL);
3733 if (database_id_ < 0)
3734 database_id_ = database_id;
3735 DCHECK_EQ(database_id_, database_id);
3736
3737 BlobChangeMap::iterator it = blob_change_map_.find(key);
3738 BlobChangeRecord *record = NULL;
3739 if (it == blob_change_map_.end()) {
3740 record = new BlobChangeRecord();
3741 blob_change_map_[key] = record;
3742 record->set_key(key);
3743 record->set_object_store_id(object_store_id);
3744 } else {
3745 record = it->second;
3746 }
3747 DCHECK_EQ(record->object_store_id(), object_store_id);
3748 record->SetBlobInfo(blob_info);
3749 record->SetHandles(handles);
3750 DCHECK(!handles || !handles->size());
3751 }
3752
3753 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3754 const GURL& url, int64_t key)
3755 : is_file_(false),
3756 url_(url),
3757 key_(key)
3758 {
3759 }
3760
3761 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3762 const FilePath& file_path, int64_t key)
3763 : is_file_(true),
3764 file_path_(file_path),
3765 key_(key)
3766 {
3767 }
3768
2614 } // namespace content 3769 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698