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

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: Merge fixes [builds, untested] Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_backing_store.h" 5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/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/leveldatabase/env_chromium.h" 30 #include "third_party/leveldatabase/env_chromium.h"
31 #include "webkit/browser/fileapi/file_writer_delegate.h"
32 #include "webkit/browser/fileapi/local_file_stream_writer.h"
25 33
34 using base::FilePath;
26 using base::StringPiece; 35 using base::StringPiece;
36 using fileapi::FileWriterDelegate;
27 37
28 // TODO(jsbell): Make blink push the version during the open() call. 38 // TODO(jsbell): Make blink push the version during the open() call.
29 static const uint32 kWireVersion = 2; 39 static const uint32 kWireVersion = 2;
30 40
31 namespace content { 41 namespace content {
32 42
43 namespace {
44
45 FilePath GetIDBBlobDirectoryName(const FilePath& pathBase,
46 int64 database_id) {
47 return pathBase.AppendASCII(base::StringPrintf("%lx", database_id));
48 }
49
50 FilePath GetIDBBlobDirectoryNameForKey(const FilePath& pathBase,
51 int64 database_id, int64 key) {
52 FilePath path = GetIDBBlobDirectoryName(pathBase, database_id);
53 path = path.AppendASCII(
54 base::StringPrintf("%x", static_cast<int>(key & 0x0000ff00) >> 8));
55 return path;
56 }
57
58 // This assumes a file path of dbId/3rd-byte-of-counter/counter.
59 bool MakeIDBBlobDirectory(
60 const FilePath& pathBase, int64 database_id, int64 key) {
61 FilePath path =
62 GetIDBBlobDirectoryNameForKey(pathBase, database_id, key);
63 return file_util::CreateDirectory(path);
64 }
65
66 } // anonymous namespace
67
33 static const int64 kKeyGeneratorInitialNumber = 68 static const int64 kKeyGeneratorInitialNumber =
34 1; // From the IndexedDB specification. 69 1; // From the IndexedDB specification.
35 70
36 enum IndexedDBBackingStoreErrorSource { 71 enum IndexedDBBackingStoreErrorSource {
37 // 0 - 2 are no longer used. 72 // 0 - 2 are no longer used.
38 FIND_KEY_IN_INDEX = 3, 73 FIND_KEY_IN_INDEX = 3,
39 GET_IDBDATABASE_METADATA, 74 GET_IDBDATABASE_METADATA,
40 GET_INDEXES, 75 GET_INDEXES,
41 GET_KEY_GENERATOR_CURRENT_NUMBER, 76 GET_KEY_GENERATOR_CURRENT_NUMBER,
42 GET_OBJECT_STORES, 77 GET_OBJECT_STORES,
43 GET_RECORD, 78 GET_RECORD,
44 KEY_EXISTS_IN_OBJECT_STORE, 79 KEY_EXISTS_IN_OBJECT_STORE,
45 LOAD_CURRENT_ROW, 80 LOAD_CURRENT_ROW,
46 SET_UP_METADATA, 81 SET_UP_METADATA,
47 GET_PRIMARY_KEY_VIA_INDEX, 82 GET_PRIMARY_KEY_VIA_INDEX,
48 KEY_EXISTS_IN_INDEX, 83 KEY_EXISTS_IN_INDEX,
49 VERSION_EXISTS, 84 VERSION_EXISTS,
50 DELETE_OBJECT_STORE, 85 DELETE_OBJECT_STORE,
51 SET_MAX_OBJECT_STORE_ID, 86 SET_MAX_OBJECT_STORE_ID,
52 SET_MAX_INDEX_ID, 87 SET_MAX_INDEX_ID,
53 GET_NEW_DATABASE_ID, 88 GET_NEW_DATABASE_ID,
54 GET_NEW_VERSION_NUMBER, 89 GET_NEW_VERSION_NUMBER,
55 CREATE_IDBDATABASE_METADATA, 90 CREATE_IDBDATABASE_METADATA,
56 DELETE_DATABASE, 91 DELETE_DATABASE,
57 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro 92 TRANSACTION_COMMIT_METHOD, // TRANSACTION_COMMIT is a WinNT.h macro
93 GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER,
94 GET_BLOB_INFO_FOR_RECORD,
95 DECODE_BLOB_JOURNAL,
58 GET_DATABASE_NAMES, 96 GET_DATABASE_NAMES,
59 INTERNAL_ERROR_MAX, 97 INTERNAL_ERROR_MAX,
60 }; 98 };
61 99
62 static void RecordInternalError(const char* type, 100 static void RecordInternalError(const char* type,
63 IndexedDBBackingStoreErrorSource location) { 101 IndexedDBBackingStoreErrorSource location) {
64 std::string name; 102 std::string name;
65 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error"); 103 name.append("WebCore.IndexedDB.BackingStore.").append(type).append("Error");
66 base::Histogram::FactoryGet(name, 104 base::Histogram::FactoryGet(name,
67 1, 105 1,
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 } 385 }
348 386
349 class DefaultLevelDBFactory : public LevelDBFactory { 387 class DefaultLevelDBFactory : public LevelDBFactory {
350 public: 388 public:
351 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name, 389 virtual leveldb::Status OpenLevelDB(const base::FilePath& file_name,
352 const LevelDBComparator* comparator, 390 const LevelDBComparator* comparator,
353 scoped_ptr<LevelDBDatabase>* db, 391 scoped_ptr<LevelDBDatabase>* db,
354 bool* is_disk_full) OVERRIDE { 392 bool* is_disk_full) OVERRIDE {
355 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full); 393 return LevelDBDatabase::Open(file_name, comparator, db, is_disk_full);
356 } 394 }
357 virtual bool DestroyLevelDB(const base::FilePath& file_name) OVERRIDE { 395 virtual bool DestroyLevelDB(const FilePath& file_name) OVERRIDE {
358 return LevelDBDatabase::Destroy(file_name); 396 return LevelDBDatabase::Destroy(file_name);
359 } 397 }
360 }; 398 };
361 399
400 static bool GetBlobKeyGeneratorCurrentNumber(
401 LevelDBTransaction* leveldb_transaction, int64 database_id,
402 int64& blob_key_generator_current_number) {
403 const std::string key_gen_key =
404 DatabaseMetaDataKey::Encode(
405 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
406
407 // Default to initial number if not found.
408 int64 cur_number = DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber;
409 std::string data;
410
411 bool found = false;
412 bool ok = leveldb_transaction->Get(key_gen_key, &data, &found);
413 if (!ok) {
414 INTERNAL_READ_ERROR(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
415 return false;
416 }
417 if (found) {
418 StringPiece slice(data);
419 if (!DecodeVarInt(&slice, &cur_number) ||
420 !DatabaseMetaDataKey::IsValidBlobKey(cur_number)) {
421 INTERNAL_READ_ERROR(GET_BLOB_KEY_GENERATOR_CURRENT_NUMBER);
422 return false;
423 }
424 }
425 blob_key_generator_current_number = cur_number;
426 return true;
427 }
428
429 static bool UpdateBlobKeyGeneratorCurrentNumber(
430 LevelDBTransaction* leveldb_transaction, int64 database_id,
431 int64 blob_key_generator_current_number) {
432 #ifndef NDEBUG
433 int64 old_number;
434 if (!GetBlobKeyGeneratorCurrentNumber(leveldb_transaction, database_id,
435 old_number))
436 return false;
437 DCHECK_LT(old_number, blob_key_generator_current_number);
438 #endif
439 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(
440 blob_key_generator_current_number));
441 const std::string key =
442 DatabaseMetaDataKey::Encode(
443 database_id, DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER);
444
445 PutInt(leveldb_transaction, key, blob_key_generator_current_number);
446 return true;
447 }
448
449 static bool DecodeBlobJournal(const std::string& data,
450 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
451 // TODO(ericu): Yell something on errors. If we persistently can't read the
452 // blob journal, the safe thing to do is to clear it and leak the blobs,
453 // though that may be costly. Still, database/directory deletion should always
454 // clean things up, and we can write an fsck that will do a full correction if
455 // need be.
456 IndexedDBBackingStore::Transaction::BlobJournalType output;
457 StringPiece slice(data);
458 while (!slice.empty()) {
459 int64 database_id = -1;
460 int64 blob_key = -1;
461 if (!DecodeVarInt(&slice, &database_id))
462 return false;
463 else if (!KeyPrefix::IsValidDatabaseId(database_id))
464 return false;
465 if (!DecodeVarInt(&slice, &blob_key)) {
466 return false;
467 } else if (!DatabaseMetaDataKey::IsValidBlobKey(blob_key) &&
468 (blob_key != DatabaseMetaDataKey::kAllBlobsKey)) {
469 return false;
470 }
471 output.push_back(std::make_pair(database_id, blob_key));
472 }
473 journal.swap(output);
474 return true;
475 }
476
477 static bool GetBlobJournalHelper(
478 bool ok, bool found,
479 const std::string& data,
480 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
481 if (!ok) {
482 INTERNAL_READ_ERROR(KEY_EXISTS_IN_OBJECT_STORE);
483 return false;
484 }
485 journal.clear();
486 if (!found)
487 return true;
488 if (!data.size())
489 return true;
490 if (!DecodeBlobJournal(data, journal)) {
491 INTERNAL_READ_ERROR(DECODE_BLOB_JOURNAL);
492 return false;
493 }
494 return true;
495 }
496
497 static bool GetBlobJournal(
498 const StringPiece& leveldb_key,
499 LevelDBTransaction* leveldb_transaction,
500 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
501 std::string data;
502 bool found = false;
503 bool ok = leveldb_transaction->Get(leveldb_key, &data, &found);
504 return GetBlobJournalHelper(ok, found, data, journal);
505 }
506
507 static bool GetBlobJournal(
508 const StringPiece& leveldb_key,
509 LevelDBWriteOnlyTransaction* leveldb_transaction,
510 IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
511 std::string data;
512 bool found = false;
513 bool ok = leveldb_transaction->Get(leveldb_key, &data, &found);
514 return GetBlobJournalHelper(ok, found, data, journal);
515 }
516
517 static std::string EncodeBlobJournalWithBlobList(
518 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
519 std::string data;
520 if (journal.size()) {
521 IndexedDBBackingStore::Transaction::BlobJournalType::const_iterator iter;
522 for (iter = journal.begin(); iter != journal.end(); ++iter) {
523 EncodeVarInt(iter->first, &data);
524 EncodeVarInt(iter->second, &data);
525 }
526 }
527 return data;
528 }
529
530 static void ClearBlobJournal(LevelDBTransaction* leveldb_transaction,
531 const std::string& level_db_key) {
532 leveldb_transaction->Remove(level_db_key);
533 }
534
535 static void UpdatePrimaryJournalWithBlobList(
536 LevelDBTransaction* leveldb_transaction,
537 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
538 const std::string leveldbKey = BlobJournalKey::Encode();
539 std::string data = EncodeBlobJournalWithBlobList(journal);
540 leveldb_transaction->Put(leveldbKey, &data);
541 }
542
543 static void UpdateSecondaryJournalWithBlobList(
544 LevelDBTransaction* leveldb_transaction,
545 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
546 const std::string leveldbKey = LiveBlobJournalKey::Encode();
547 std::string data = EncodeBlobJournalWithBlobList(journal);
548 leveldb_transaction->Put(leveldbKey, &data);
549 }
550
551 static bool MergeBlobsIntoSecondaryJournal(
552 LevelDBTransaction* leveldb_transaction,
553 const IndexedDBBackingStore::Transaction::BlobJournalType& journal) {
554 IndexedDBBackingStore::Transaction::BlobJournalType old_journal;
555 std::string key = LiveBlobJournalKey::Encode();
556 if (!GetBlobJournal(key, leveldb_transaction, old_journal))
557 return false;
558
559 fprintf(stderr, "ERICU: Secondary: old %lu entries, new %lu entries.\n",
560 old_journal.size(), journal.size());
561 old_journal.insert(old_journal.end(), journal.begin(), journal.end());
562 fprintf(stderr, "ERICU: final %lu entries.\n", old_journal.size());
563
564 UpdateSecondaryJournalWithBlobList(leveldb_transaction, old_journal);
565 return true;
566 }
567
568 static void UpdateBlobJournalWithDatabase(
569 LevelDBWriteOnlyTransaction* leveldb_transaction, int64 database_id) {
570 IndexedDBBackingStore::Transaction::BlobJournalType journal;
571 journal.push_back(
572 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
573 const std::string key = BlobJournalKey::Encode();
574 std::string data = EncodeBlobJournalWithBlobList(journal);
575 leveldb_transaction->Put(key, &data);
576 }
577
578 static bool MergeDatabaseIntoSecondaryJournal(
579 LevelDBWriteOnlyTransaction* leveldb_transaction, int64 database_id) {
580 IndexedDBBackingStore::Transaction::BlobJournalType journal;
581 std::string key = LiveBlobJournalKey::Encode();
582 if (!GetBlobJournal(key, leveldb_transaction, journal))
583 return false;
584 journal.push_back(
585 std::make_pair(database_id, DatabaseMetaDataKey::kAllBlobsKey));
586 std::string data = EncodeBlobJournalWithBlobList(journal);
587 leveldb_transaction->Put(key, &data);
588 return true;
589 }
590
591 // Blob Data is encoded as { is_file [bool], key [int64 as varInt],
592 // type [string-with-length, may be empty], then [for Blobs] size
593 // [int64 as varInt] or [for Files] fileName [string-with-length] }
594 static std::string EncodeBlobData(
595 const std::vector<IndexedDBBlobInfo*>& blob_info) {
596 std::string ret;
597 std::vector<IndexedDBBlobInfo*>::const_iterator iter;
598 for (iter = blob_info.begin(); iter != blob_info.end(); ++iter) {
599 const IndexedDBBlobInfo& info = **iter;
600 EncodeBool(info.is_file(), &ret);
601 EncodeVarInt(info.key(), &ret);
602 EncodeStringWithLength(info.type(), &ret);
603 if (info.is_file())
604 EncodeStringWithLength(info.file_name(), &ret);
605 else
606 EncodeVarInt(info.size(), &ret);
607 }
608 return ret;
609 }
610
611 static bool DecodeBlobData(
612 const std::string& data,
613 std::vector<IndexedDBBlobInfo>* output) {
614 std::vector<IndexedDBBlobInfo> ret;
615 output->clear();
616 StringPiece slice(data);
617 while (!slice.empty()) {
618 bool is_file;
619 int64 key;
620 string16 type;
621 int64 size;
622 string16 file_name;
623
624 if (!DecodeBool(&slice, &is_file))
625 return false;
626 if (!DecodeVarInt(&slice, &key) ||
627 !DatabaseMetaDataKey::IsValidBlobKey(key))
628 return false;
629 if (!DecodeStringWithLength(&slice, &type))
630 return false;
631 if (is_file) {
632 if (!DecodeStringWithLength(&slice, &file_name))
633 return false;
634 ret.push_back(IndexedDBBlobInfo(type, file_name, key));
635 } else {
636 if (!DecodeVarInt(&slice, &size) || size < 0)
637 return false;
638 ret.push_back(IndexedDBBlobInfo(type, static_cast<uint64>(size), key));
639 }
640 }
641 output->swap(ret);
642
643 return true;
644 }
645
362 IndexedDBBackingStore::IndexedDBBackingStore( 646 IndexedDBBackingStore::IndexedDBBackingStore(
363 const std::string& identifier, 647 const std::string& identifier,
648 const FilePath& blob_path,
649 net::URLRequestContext* request_context,
364 scoped_ptr<LevelDBDatabase> db, 650 scoped_ptr<LevelDBDatabase> db,
365 scoped_ptr<LevelDBComparator> comparator) 651 scoped_ptr<LevelDBComparator> comparator,
652 base::TaskRunner* task_runner)
366 : identifier_(identifier), 653 : identifier_(identifier),
654 blob_path_(blob_path),
655 request_context_(request_context),
656 task_runner_(task_runner),
367 db_(db.Pass()), 657 db_(db.Pass()),
368 comparator_(comparator.Pass()), 658 comparator_(comparator.Pass()),
369 weak_factory_(this) {} 659 active_blob_registry_(this),
660 weak_factory_(this) {
661 }
370 662
371 IndexedDBBackingStore::~IndexedDBBackingStore() { 663 IndexedDBBackingStore::~IndexedDBBackingStore() {
664 if (!blob_path_.empty()) {
665 ChildProcessSecurityPolicyImpl* policy =
666 ChildProcessSecurityPolicyImpl::GetInstance();
667 for (std::set<int>::iterator iter = child_process_ids_granted_.begin();
668 iter != child_process_ids_granted_.end(); ++iter) {
669 policy->RevokeAllPermissionsForFile(*iter, blob_path_);
670 }
671 }
372 // db_'s destructor uses comparator_. The order of destruction is important. 672 // db_'s destructor uses comparator_. The order of destruction is important.
373 db_.reset(); 673 db_.reset();
374 comparator_.reset(); 674 comparator_.reset();
375 } 675 }
376 676
377 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier( 677 IndexedDBBackingStore::RecordIdentifier::RecordIdentifier(
378 const std::string& primary_key, 678 const std::string& primary_key,
379 int64 version) 679 int64 version)
380 : primary_key_(primary_key), version_(version) { 680 : primary_key_(primary_key), version_(version) {
381 DCHECK(!primary_key.empty()); 681 DCHECK(!primary_key.empty());
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 } 735 }
436 } 736 }
437 default: 737 default:
438 return true; 738 return true;
439 } 739 }
440 return true; 740 return true;
441 } 741 }
442 742
443 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 743 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
444 const std::string& origin_identifier, 744 const std::string& origin_identifier,
445 const base::FilePath& path_base, 745 const FilePath& path_base,
446 const std::string& file_identifier, 746 const std::string& file_identifier,
447 WebKit::WebIDBCallbacks::DataLoss* data_loss) { 747 net::URLRequestContext* request_context,
748 WebKit::WebIDBCallbacks::DataLoss* data_loss,
749 base::TaskRunner* task_runner,
750 bool clean_journal) {
448 *data_loss = WebKit::WebIDBCallbacks::DataLossNone; 751 *data_loss = WebKit::WebIDBCallbacks::DataLossNone;
449 DefaultLevelDBFactory leveldb_factory; 752 DefaultLevelDBFactory leveldb_factory;
450 return IndexedDBBackingStore::Open(origin_identifier, 753 return IndexedDBBackingStore::Open(origin_identifier,
451 path_base, 754 path_base,
452 file_identifier, 755 file_identifier,
756 request_context,
453 data_loss, 757 data_loss,
454 &leveldb_factory); 758 &leveldb_factory,
759 task_runner,
760 clean_journal);
455 } 761 }
456 762
457 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 763 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
458 const std::string& origin_identifier, 764 const std::string& origin_identifier,
459 const base::FilePath& path_base, 765 const FilePath& path_base,
460 const std::string& file_identifier, 766 const std::string& file_identifier,
767 net::URLRequestContext* request_context,
461 WebKit::WebIDBCallbacks::DataLoss* data_loss, 768 WebKit::WebIDBCallbacks::DataLoss* data_loss,
462 LevelDBFactory* leveldb_factory) { 769 LevelDBFactory* leveldb_factory,
770 base::TaskRunner* task_runner,
771 bool clean_journal) {
463 IDB_TRACE("IndexedDBBackingStore::Open"); 772 IDB_TRACE("IndexedDBBackingStore::Open");
464 DCHECK(!path_base.empty()); 773 DCHECK(!path_base.empty());
465 *data_loss = WebKit::WebIDBCallbacks::DataLossNone; 774 *data_loss = WebKit::WebIDBCallbacks::DataLossNone;
466 775
467 scoped_ptr<LevelDBComparator> comparator(new Comparator()); 776 scoped_ptr<LevelDBComparator> comparator(new Comparator());
468 777
469 if (!IsStringASCII(path_base.AsUTF8Unsafe())) { 778 if (!IsStringASCII(path_base.AsUTF8Unsafe())) {
470 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus", 779 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
471 1, 780 1,
472 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX, 781 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
473 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1, 782 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
474 base::HistogramBase::kUmaTargetedHistogramFlag) 783 base::HistogramBase::kUmaTargetedHistogramFlag)
475 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII); 784 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ATTEMPT_NON_ASCII);
476 } 785 }
477 if (!file_util::CreateDirectory(path_base)) { 786 if (!file_util::CreateDirectory(path_base)) {
478 LOG(ERROR) << "Unable to create IndexedDB database path " 787 LOG(ERROR) << "Unable to create IndexedDB database path "
479 << path_base.AsUTF8Unsafe(); 788 << path_base.AsUTF8Unsafe();
480 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus", 789 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
481 1, 790 1,
482 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX, 791 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
483 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1, 792 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
484 base::HistogramBase::kUmaTargetedHistogramFlag) 793 base::HistogramBase::kUmaTargetedHistogramFlag)
485 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY); 794 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_DIRECTORY);
486 return scoped_refptr<IndexedDBBackingStore>(); 795 return scoped_refptr<IndexedDBBackingStore>();
487 } 796 }
488 797
489 base::FilePath identifier_path = 798 base::FilePath db_dir_name =
490 base::FilePath().AppendASCII(origin_identifier) 799 FilePath().AppendASCII(origin_identifier).
491 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); 800 AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
801 base::FilePath blob_dir_name =
802 FilePath().AppendASCII(origin_identifier).
803 AddExtension(FILE_PATH_LITERAL(".indexeddb.blob"));
492 804
493 int limit = file_util::GetMaximumPathComponentLength(path_base); 805 int limit = file_util::GetMaximumPathComponentLength(path_base);
494 if (limit == -1) { 806 if (limit == -1) {
495 DLOG(WARNING) << "GetMaximumPathComponentLength returned -1"; 807 DLOG(WARNING) << "GetMaximumPathComponentLength returned -1";
496 // In limited testing, ChromeOS returns 143, other OSes 255. 808 // In limited testing, ChromeOS returns 143, other OSes 255.
497 #if defined(OS_CHROMEOS) 809 #if defined(OS_CHROMEOS)
498 limit = 143; 810 limit = 143;
499 #else 811 #else
500 limit = 255; 812 limit = 255;
501 #endif 813 #endif
502 } 814 }
503 if (identifier_path.value().length() > static_cast<uint32_t>(limit)) { 815 if (db_dir_name.value().length() > static_cast<uint32_t>(limit)) {
504 DLOG(WARNING) << "Path component length (" 816 DLOG(WARNING) << "Path component length ("
505 << identifier_path.value().length() << ") exceeds maximum (" 817 << db_dir_name.value().length() << ") exceeds maximum ("
506 << limit << ") allowed by this filesystem."; 818 << limit << ") allowed by this filesystem.";
507 const int min = 140; 819 const int min = 140;
508 const int max = 300; 820 const int max = 300;
509 const int num_buckets = 12; 821 const int num_buckets = 12;
510 // TODO(dgrogan): Remove WebCore from these histogram names. 822 // TODO(dgrogan): Remove WebCore from these histogram names.
511 UMA_HISTOGRAM_CUSTOM_COUNTS( 823 UMA_HISTOGRAM_CUSTOM_COUNTS(
512 "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength", 824 "WebCore.IndexedDB.BackingStore.OverlyLargeOriginLength",
513 identifier_path.value().length(), 825 db_dir_name.value().length(),
514 min, 826 min,
515 max, 827 max,
516 num_buckets); 828 num_buckets);
517 // TODO(dgrogan): Translate the FactoryGet calls to 829 // TODO(dgrogan): Translate the FactoryGet calls to
518 // UMA_HISTOGRAM_ENUMERATION. FactoryGet was the most direct translation 830 // UMA_HISTOGRAM_ENUMERATION. FactoryGet was the most direct translation
519 // from the WebCore code. 831 // from the WebCore code.
520 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus", 832 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
521 1, 833 1,
522 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX, 834 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
523 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1, 835 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
524 base::HistogramBase::kUmaTargetedHistogramFlag) 836 base::HistogramBase::kUmaTargetedHistogramFlag)
525 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG); 837 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_ORIGIN_TOO_LONG);
526 return scoped_refptr<IndexedDBBackingStore>(); 838 return scoped_refptr<IndexedDBBackingStore>();
527 } 839 }
528 840
529 base::FilePath file_path = path_base.Append(identifier_path); 841 FilePath file_path = path_base.Append(db_dir_name);
842 FilePath blob_path = path_base.Append(blob_dir_name);
530 843
531 bool is_disk_full = false; 844 bool is_disk_full = false;
532 scoped_ptr<LevelDBDatabase> db; 845 scoped_ptr<LevelDBDatabase> db;
533 leveldb::Status status = leveldb_factory->OpenLevelDB( 846 leveldb::Status status = leveldb_factory->OpenLevelDB(
534 file_path, comparator.get(), &db, &is_disk_full); 847 file_path, comparator.get(), &db, &is_disk_full);
535 848
536 if (db) { 849 if (db) {
537 bool known = false; 850 bool known = false;
538 bool ok = IsSchemaKnown(db.get(), &known); 851 bool ok = IsSchemaKnown(db.get(), &known);
539 if (!ok) { 852 if (!ok) {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 NOTREACHED(); 941 NOTREACHED();
629 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus", 942 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
630 1, 943 1,
631 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX, 944 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
632 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1, 945 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
633 base::HistogramBase::kUmaTargetedHistogramFlag) 946 base::HistogramBase::kUmaTargetedHistogramFlag)
634 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR); 947 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR);
635 return scoped_refptr<IndexedDBBackingStore>(); 948 return scoped_refptr<IndexedDBBackingStore>();
636 } 949 }
637 950
638 return Create(file_identifier, db.Pass(), comparator.Pass()); 951 scoped_refptr<IndexedDBBackingStore> backing_store = Create(
952 file_identifier, blob_path, request_context, db.Pass(), comparator.Pass(),
953 task_runner);
954
955 if (clean_journal)
956 fprintf(stderr, "ERICU: first open of DB since boot.\n");
957 if (clean_journal && !backing_store->CleanUpBlobJournal(
958 LiveBlobJournalKey::Encode()))
959 return scoped_refptr<IndexedDBBackingStore>();
960 return backing_store;
639 } 961 }
640 962
641 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 963 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
642 const std::string& file_identifier) { 964 const std::string& file_identifier) {
643 DefaultLevelDBFactory leveldb_factory; 965 DefaultLevelDBFactory leveldb_factory;
644 return IndexedDBBackingStore::OpenInMemory(file_identifier, &leveldb_factory); 966 return IndexedDBBackingStore::OpenInMemory(file_identifier, &leveldb_factory);
645 } 967 }
646 968
647 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 969 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
648 const std::string& file_identifier, 970 const std::string& file_identifier,
(...skipping 13 matching lines...) Expand all
662 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_FAILED); 984 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_FAILED);
663 return scoped_refptr<IndexedDBBackingStore>(); 985 return scoped_refptr<IndexedDBBackingStore>();
664 } 986 }
665 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus", 987 base::Histogram::FactoryGet("WebCore.IndexedDB.BackingStore.OpenStatus",
666 1, 988 1,
667 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX, 989 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX,
668 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1, 990 INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MAX + 1,
669 base::HistogramBase::kUmaTargetedHistogramFlag) 991 base::HistogramBase::kUmaTargetedHistogramFlag)
670 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS); 992 ->Add(INDEXED_DB_LEVEL_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS);
671 993
672 return Create(file_identifier, db.Pass(), comparator.Pass()); 994 return Create(file_identifier, FilePath(), NULL, db.Pass(),
995 comparator.Pass(), NULL);
673 } 996 }
674 997
675 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( 998 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
676 const std::string& identifier, 999 const std::string& identifier,
1000 const FilePath& blob_path,
1001 net::URLRequestContext* request_context,
677 scoped_ptr<LevelDBDatabase> db, 1002 scoped_ptr<LevelDBDatabase> db,
678 scoped_ptr<LevelDBComparator> comparator) { 1003 scoped_ptr<LevelDBComparator> comparator,
1004 base::TaskRunner* task_runner) {
679 // TODO(jsbell): Handle comparator name changes. 1005 // TODO(jsbell): Handle comparator name changes.
680 scoped_refptr<IndexedDBBackingStore> backing_store( 1006 scoped_refptr<IndexedDBBackingStore> backing_store(
681 new IndexedDBBackingStore(identifier, db.Pass(), comparator.Pass())); 1007 new IndexedDBBackingStore(identifier, blob_path, request_context,
1008 db.Pass(), comparator.Pass(), task_runner));
682 1009
683 if (!SetUpMetadata(backing_store->db_.get(), identifier)) 1010 if (!SetUpMetadata(backing_store->db_.get(), identifier))
684 return scoped_refptr<IndexedDBBackingStore>(); 1011 return scoped_refptr<IndexedDBBackingStore>();
685 1012
686 return backing_store; 1013 return backing_store;
687 } 1014 }
688 1015
1016 void IndexedDBBackingStore::GrantChildProcessPermissions(int child_process_id) {
1017 if (!child_process_ids_granted_.count(child_process_id)) {
1018 child_process_ids_granted_.insert(child_process_id);
1019 ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadDirectory(
1020 child_process_id, blob_path_);
1021 }
1022 }
1023
689 std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() { 1024 std::vector<string16> IndexedDBBackingStore::GetDatabaseNames() {
690 std::vector<string16> found_names; 1025 std::vector<string16> found_names;
691 const std::string start_key = 1026 const std::string start_key =
692 DatabaseNameKey::EncodeMinKeyForOrigin(identifier_); 1027 DatabaseNameKey::EncodeMinKeyForOrigin(identifier_);
693 const std::string stop_key = 1028 const std::string stop_key =
694 DatabaseNameKey::EncodeStopKeyForOrigin(identifier_); 1029 DatabaseNameKey::EncodeStopKeyForOrigin(identifier_);
695 1030
696 DCHECK(found_names.empty()); 1031 DCHECK(found_names.empty());
697 1032
698 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1033 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) 1091 if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
757 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION; 1092 metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
758 1093
759 ok = GetMaxObjectStoreId( 1094 ok = GetMaxObjectStoreId(
760 db_.get(), metadata->id, &metadata->max_object_store_id); 1095 db_.get(), metadata->id, &metadata->max_object_store_id);
761 if (!ok) { 1096 if (!ok) {
762 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA); 1097 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
763 return false; 1098 return false;
764 } 1099 }
765 1100
1101 int64 blob_key_generator_current_number =
1102 DatabaseMetaDataKey::kInvalidBlobKey;
1103
1104 ok = GetVarInt(db_.get(),
1105 DatabaseMetaDataKey::Encode(
1106 metadata->id,
1107 DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1108 &blob_key_generator_current_number,
1109 found);
1110 if (!ok) {
1111 INTERNAL_READ_ERROR(GET_IDBDATABASE_METADATA);
1112 return false;
1113 }
1114 if (!*found ||
1115 !DatabaseMetaDataKey::IsValidBlobKey(blob_key_generator_current_number)) {
1116 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA);
1117 // TODO(ericu): If BLOB_KEY_GENERATOR_CURRENT_NUMBER isn't present,
1118 // initialize it to kBlobKeyGeneratorInitialNumber. We may also want to
1119 // verify that this object store predates blob support, or that there
1120 // aren't any blobs on disk.
1121 // This would be a read-modify-write, so we'd need a transaction,
1122 // and to double-check. It might just be easier to write it lazily
1123 // when we first try to increment it.
1124 return false;
1125 }
1126
766 return true; 1127 return true;
767 } 1128 }
768 1129
769 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBDatabase* db, 1130 WARN_UNUSED_RESULT static bool GetNewDatabaseId(LevelDBDatabase* db,
770 int64* new_id) { 1131 int64* new_id) {
771 scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db); 1132 scoped_refptr<LevelDBTransaction> transaction = new LevelDBTransaction(db);
772 1133
773 *new_id = -1; 1134 *new_id = -1;
774 int64 max_database_id = -1; 1135 int64 max_database_id = -1;
775 bool found = false; 1136 bool found = false;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 PutInt( 1172 PutInt(
812 transaction.get(), DatabaseNameKey::Encode(identifier_, name), *row_id); 1173 transaction.get(), DatabaseNameKey::Encode(identifier_, name), *row_id);
813 PutString( 1174 PutString(
814 transaction.get(), 1175 transaction.get(),
815 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION), 1176 DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
816 version); 1177 version);
817 PutVarInt(transaction.get(), 1178 PutVarInt(transaction.get(),
818 DatabaseMetaDataKey::Encode(*row_id, 1179 DatabaseMetaDataKey::Encode(*row_id,
819 DatabaseMetaDataKey::USER_INT_VERSION), 1180 DatabaseMetaDataKey::USER_INT_VERSION),
820 int_version); 1181 int_version);
1182 PutVarInt(
1183 transaction.get(),
1184 DatabaseMetaDataKey::Encode(*row_id,
1185 DatabaseMetaDataKey::BLOB_KEY_GENERATOR_CURRENT_NUMBER),
1186 DatabaseMetaDataKey::kBlobKeyGeneratorInitialNumber);
821 if (!transaction->Commit()) { 1187 if (!transaction->Commit()) {
822 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA); 1188 INTERNAL_WRITE_ERROR(CREATE_IDBDATABASE_METADATA);
823 return false; 1189 return false;
824 } 1190 }
825 return true; 1191 return true;
826 } 1192 }
827 1193
828 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion( 1194 bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
829 IndexedDBBackingStore::Transaction* transaction, 1195 IndexedDBBackingStore::Transaction* transaction,
830 int64 row_id, 1196 int64 row_id,
(...skipping 12 matching lines...) Expand all
843 IndexedDBBackingStore::Transaction* transaction, 1209 IndexedDBBackingStore::Transaction* transaction,
844 int64 row_id, 1210 int64 row_id,
845 const string16& version) { 1211 const string16& version) {
846 PutString( 1212 PutString(
847 Transaction::LevelDBTransactionFrom(transaction), 1213 Transaction::LevelDBTransactionFrom(transaction),
848 DatabaseMetaDataKey::Encode(row_id, DatabaseMetaDataKey::USER_VERSION), 1214 DatabaseMetaDataKey::Encode(row_id, DatabaseMetaDataKey::USER_VERSION),
849 version); 1215 version);
850 return true; 1216 return true;
851 } 1217 }
852 1218
853 static void DeleteRange(LevelDBTransaction* transaction, 1219 // Note that if you're deleting a range that contains user keys that have blob
854 const std::string& begin, 1220 // info, this won't clean up the blobs.
855 const std::string& end) { 1221 static void DeleteRangeHelper(LevelDBTransaction* transaction,
1222 const std::string& begin,
1223 const std::string& end) {
856 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator(); 1224 scoped_ptr<LevelDBIterator> it = transaction->CreateIterator();
857 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0; 1225 for (it->Seek(begin); it->IsValid() && CompareKeys(it->Key(), end) < 0;
858 it->Next()) 1226 it->Next())
859 transaction->Remove(it->Key()); 1227 transaction->Remove(it->Key());
860 } 1228 }
861 1229
1230 // For a whole-object-store deletion, we still use the one-blob-record-at-a-time
1231 // deletion mechanism designed for normal transactions. We could go with the
1232 // nuke-the-whole-directory method used for deleteDatabase, but that would
1233 // complicate the kind of info we store in the LevelDBTransaction.
1234 static void DeleteBlobsInObjectStore(
1235 IndexedDBBackingStore::Transaction* transaction,
1236 int64 database_id, int64 object_store_id) {
1237 fprintf(stderr, "ERICU: DeleteBlobsInObjectStore.\n");
1238 std::string start_key, end_key;
1239 start_key =
1240 BlobEntryKey::EncodeMinForObjectStore(database_id, object_store_id);
1241 end_key =
1242 BlobEntryKey::EncodeMaxForObjectStore(database_id, object_store_id);
1243
1244 scoped_ptr<LevelDBIterator> it =
1245 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(
1246 transaction)->CreateIterator();
1247 for (it->Seek(start_key);
1248 it->IsValid() && CompareKeys(it->Key(), end_key) < 0; it->Next()) {
1249 StringPiece key_piece(it->Key());
1250 std::string user_key = BlobEntryKey::EncodeToObjectStoreDataKey(&key_piece);
1251 if (user_key.size())
1252 transaction->PutBlobInfo(database_id, object_store_id, user_key, NULL);
1253 else
1254 INTERNAL_CONSISTENCY_ERROR(GET_IDBDATABASE_METADATA);
1255 }
1256 }
1257
1258 static bool GetBlobInfoForRecord(
1259 IndexedDBBackingStore* backing_store,
1260 LevelDBTransaction* leveldb_transaction,
1261 int64 database_id,
1262 const std::string& leveldb_key,
1263 IndexedDBValue* value) {
1264
1265 BlobEntryKey blob_entry_key;
1266 StringPiece leveldb_key_piece(leveldb_key);
1267 if (!BlobEntryKey::FromObjectStoreDataKey(
1268 &leveldb_key_piece, &blob_entry_key)) {
1269 NOTREACHED();
1270 return false;
1271 }
1272 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
1273 std::string encoded_key = blob_entry_key.Encode();
1274 it->Seek(encoded_key);
1275 if (it->IsValid() && CompareKeys(it->Key(), encoded_key) == 0) {
1276 if (!DecodeBlobData(it->Value().as_string(), &value->blob_info)) {
1277 INTERNAL_READ_ERROR(GET_BLOB_INFO_FOR_RECORD);
1278 return false;
1279 }
1280 std::vector<IndexedDBBlobInfo>::iterator iter;
1281 for (iter = value->blob_info.begin(); iter != value->blob_info.end();
1282 ++iter) {
1283 iter->set_file_path(
1284 backing_store->GetIDBBlobFileName(database_id, iter->key()));
1285 iter->set_mark_used_callback(
1286 backing_store->active_blob_registry()->GetMarkUsedCallback(
1287 database_id, iter->key()));
1288 iter->set_release_callback(
1289 backing_store->active_blob_registry()->GetReleaseCallback(
1290 database_id, iter->key()));
1291 if (iter->is_file()) {
1292 base::PlatformFileInfo info;
1293 if (file_util::GetFileInfo(iter->file_path(), &info)) {
1294 // This should always work, but it isn't fatal if it doesn't; it just
1295 // means a potential slow synchronous call from the renderer later.
1296 iter->set_last_modified(info.last_modified);
1297 iter->set_size(info.size);
1298 }
1299 }
1300 }
1301 }
1302 return true;
1303 }
1304
862 bool IndexedDBBackingStore::DeleteDatabase(const string16& name) { 1305 bool IndexedDBBackingStore::DeleteDatabase(const string16& name) {
863 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase"); 1306 IDB_TRACE("IndexedDBBackingStore::DeleteDatabase");
864 scoped_ptr<LevelDBWriteOnlyTransaction> transaction = 1307 scoped_ptr<LevelDBWriteOnlyTransaction> transaction =
865 LevelDBWriteOnlyTransaction::Create(db_.get()); 1308 LevelDBWriteOnlyTransaction::Create(db_.get());
866 1309
1310 if (!CleanUpBlobJournal(BlobJournalKey::Encode()))
1311 return false;
1312
867 IndexedDBDatabaseMetadata metadata; 1313 IndexedDBDatabaseMetadata metadata;
868 bool success = false; 1314 bool success = false;
869 bool ok = GetIDBDatabaseMetaData(name, &metadata, &success); 1315 bool ok = GetIDBDatabaseMetaData(name, &metadata, &success);
870 if (!ok) 1316 if (!ok)
871 return false; 1317 return false;
872 if (!success) 1318 if (!success)
873 return true; 1319 return true;
874 1320
875 const std::string start_key = DatabaseMetaDataKey::Encode( 1321 const std::string start_key = DatabaseMetaDataKey::Encode(
876 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME); 1322 metadata.id, DatabaseMetaDataKey::ORIGIN_NAME);
877 const std::string stop_key = DatabaseMetaDataKey::Encode( 1323 const std::string stop_key = DatabaseMetaDataKey::Encode(
878 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME); 1324 metadata.id + 1, DatabaseMetaDataKey::ORIGIN_NAME);
879 scoped_ptr<LevelDBIterator> it = db_->CreateIterator(); 1325 scoped_ptr<LevelDBIterator> it = db_->CreateIterator();
880 for (it->Seek(start_key); 1326 for (it->Seek(start_key);
881 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0; 1327 it->IsValid() && CompareKeys(it->Key(), stop_key) < 0;
882 it->Next()) 1328 it->Next())
883 transaction->Remove(it->Key()); 1329 transaction->Remove(it->Key());
884 1330
885 const std::string key = DatabaseNameKey::Encode(identifier_, name); 1331 const std::string key = DatabaseNameKey::Encode(identifier_, name);
886 transaction->Remove(key); 1332 transaction->Remove(key);
887 1333
1334 bool need_cleanup = false;
1335 if (active_blob_registry()->MarkDeletedCheckIfUsed(
1336 metadata.id, DatabaseMetaDataKey::kAllBlobsKey)) {
1337 if (!MergeDatabaseIntoSecondaryJournal(transaction.get(), metadata.id))
1338 return false;
1339 } else {
1340 UpdateBlobJournalWithDatabase(transaction.get(), metadata.id);
1341 need_cleanup = true;
1342 }
1343
888 if (!transaction->Commit()) { 1344 if (!transaction->Commit()) {
889 INTERNAL_WRITE_ERROR(DELETE_DATABASE); 1345 INTERNAL_WRITE_ERROR(DELETE_DATABASE);
890 return false; 1346 return false;
891 } 1347 }
1348
1349 if (need_cleanup)
1350 CleanUpBlobJournal(BlobJournalKey::Encode());
1351
892 return true; 1352 return true;
893 } 1353 }
894 1354
895 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it, 1355 static bool CheckObjectStoreAndMetaDataType(const LevelDBIterator* it,
896 const std::string& stop_key, 1356 const std::string& stop_key,
897 int64 object_store_id, 1357 int64 object_store_id,
898 int64 meta_data_type) { 1358 int64 meta_data_type) {
899 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1359 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
900 return false; 1360 return false;
901 1361
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1434 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
975 break; 1435 break;
976 } 1436 }
977 bool auto_increment; 1437 bool auto_increment;
978 { 1438 {
979 StringPiece slice(it->Value()); 1439 StringPiece slice(it->Value());
980 if (!DecodeBool(&slice, &auto_increment) || !slice.empty()) 1440 if (!DecodeBool(&slice, &auto_increment) || !slice.empty())
981 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1441 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
982 } 1442 }
983 1443
984 it->Next(); // Is evicatble. 1444 it->Next(); // Is evictable.
985 if (!CheckObjectStoreAndMetaDataType(it.get(), 1445 if (!CheckObjectStoreAndMetaDataType(it.get(),
986 stop_key, 1446 stop_key,
987 object_store_id, 1447 object_store_id,
988 ObjectStoreMetaDataKey::EVICTABLE)) { 1448 ObjectStoreMetaDataKey::EVICTABLE)) {
989 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES); 1449 INTERNAL_CONSISTENCY_ERROR(GET_OBJECT_STORES);
990 break; 1450 break;
991 } 1451 }
992 1452
993 it->Next(); // Last version. 1453 it->Next(); // Last version.
994 if (!CheckObjectStoreAndMetaDataType( 1454 if (!CheckObjectStoreAndMetaDataType(
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 &found); 1623 &found);
1164 if (!ok) { 1624 if (!ok) {
1165 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE); 1625 INTERNAL_READ_ERROR(DELETE_OBJECT_STORE);
1166 return false; 1626 return false;
1167 } 1627 }
1168 if (!found) { 1628 if (!found) {
1169 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE); 1629 INTERNAL_CONSISTENCY_ERROR(DELETE_OBJECT_STORE);
1170 return false; 1630 return false;
1171 } 1631 }
1172 1632
1173 DeleteRange( 1633 DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1634 DeleteRangeHelper(
1174 leveldb_transaction, 1635 leveldb_transaction,
1175 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0), 1636 ObjectStoreMetaDataKey::Encode(database_id, object_store_id, 0),
1176 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1637 ObjectStoreMetaDataKey::EncodeMaxKey(database_id, object_store_id));
1177 1638
1178 leveldb_transaction->Remove( 1639 leveldb_transaction->Remove(
1179 ObjectStoreNamesKey::Encode(database_id, object_store_name)); 1640 ObjectStoreNamesKey::Encode(database_id, object_store_name));
1180 1641
1181 DeleteRange(leveldb_transaction, 1642 DeleteRangeHelper(
1182 IndexFreeListKey::Encode(database_id, object_store_id, 0), 1643 leveldb_transaction,
1183 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id)); 1644 IndexFreeListKey::Encode(database_id, object_store_id, 0),
1184 DeleteRange(leveldb_transaction, 1645 IndexFreeListKey::EncodeMaxKey(database_id, object_store_id));
1185 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0), 1646 DeleteRangeHelper(
1186 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id)); 1647 leveldb_transaction,
1648 IndexMetaDataKey::Encode(database_id, object_store_id, 0, 0),
1649 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id));
1187 1650
1188 return ClearObjectStore(transaction, database_id, object_store_id); 1651 return ClearObjectStore(transaction, database_id, object_store_id);
1189 } 1652 }
1190 1653
1191 bool IndexedDBBackingStore::GetRecord( 1654 bool IndexedDBBackingStore::GetRecord(
1192 IndexedDBBackingStore::Transaction* transaction, 1655 IndexedDBBackingStore::Transaction* transaction,
1193 int64 database_id, 1656 int64 database_id,
1194 int64 object_store_id, 1657 int64 object_store_id,
1195 const IndexedDBKey& key, 1658 const IndexedDBKey& key,
1196 std::string* record) { 1659 IndexedDBValue* record) {
1197 IDB_TRACE("IndexedDBBackingStore::GetRecord"); 1660 IDB_TRACE("IndexedDBBackingStore::GetRecord");
1198 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1661 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1199 return false; 1662 return false;
1200 LevelDBTransaction* leveldb_transaction = 1663 LevelDBTransaction* leveldb_transaction =
1201 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 1664 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1202 1665
1203 const std::string leveldb_key = 1666 const std::string leveldb_key =
1204 ObjectStoreDataKey::Encode(database_id, object_store_id, key); 1667 ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1205 std::string data; 1668 std::string data;
1206 1669
(...skipping 12 matching lines...) Expand all
1219 return false; 1682 return false;
1220 } 1683 }
1221 1684
1222 int64 version; 1685 int64 version;
1223 StringPiece slice(data); 1686 StringPiece slice(data);
1224 if (!DecodeVarInt(&slice, &version)) { 1687 if (!DecodeVarInt(&slice, &version)) {
1225 INTERNAL_READ_ERROR(GET_RECORD); 1688 INTERNAL_READ_ERROR(GET_RECORD);
1226 return false; 1689 return false;
1227 } 1690 }
1228 1691
1229 *record = slice.as_string(); 1692 record->bits = slice.as_string();
1230 return true; 1693 return GetBlobInfoForRecord(
1694 this, leveldb_transaction, database_id, leveldb_key, record);
1231 } 1695 }
1232 1696
1233 WARN_UNUSED_RESULT static bool GetNewVersionNumber( 1697 WARN_UNUSED_RESULT static bool GetNewVersionNumber(
1234 LevelDBTransaction* transaction, 1698 LevelDBTransaction* transaction,
1235 int64 database_id, 1699 int64 database_id,
1236 int64 object_store_id, 1700 int64 object_store_id,
1237 int64* new_version_number) { 1701 int64* new_version_number) {
1238 const std::string last_version_key = ObjectStoreMetaDataKey::Encode( 1702 const std::string last_version_key = ObjectStoreMetaDataKey::Encode(
1239 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION); 1703 database_id, object_store_id, ObjectStoreMetaDataKey::LAST_VERSION);
1240 1704
(...skipping 18 matching lines...) Expand all
1259 1723
1260 *new_version_number = version; 1724 *new_version_number = version;
1261 return true; 1725 return true;
1262 } 1726 }
1263 1727
1264 bool IndexedDBBackingStore::PutRecord( 1728 bool IndexedDBBackingStore::PutRecord(
1265 IndexedDBBackingStore::Transaction* transaction, 1729 IndexedDBBackingStore::Transaction* transaction,
1266 int64 database_id, 1730 int64 database_id,
1267 int64 object_store_id, 1731 int64 object_store_id,
1268 const IndexedDBKey& key, 1732 const IndexedDBKey& key,
1269 const std::string& value, 1733 IndexedDBValue& value,
1270 RecordIdentifier* record_identifier) { 1734 RecordIdentifier* record_identifier) {
1271 IDB_TRACE("IndexedDBBackingStore::PutRecord"); 1735 IDB_TRACE("IndexedDBBackingStore::PutRecord");
1736 fprintf(stderr, "ERICU: PutRecord.\n");
1272 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1737 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1273 return false; 1738 return false;
1274 DCHECK(key.IsValid()); 1739 DCHECK(key.IsValid());
1275 1740
1276 LevelDBTransaction* leveldb_transaction = 1741 LevelDBTransaction* leveldb_transaction =
1277 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 1742 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1278 int64 version = -1; 1743 int64 version = -1;
1279 bool ok = GetNewVersionNumber( 1744 bool ok = GetNewVersionNumber(
1280 leveldb_transaction, database_id, object_store_id, &version); 1745 leveldb_transaction, database_id, object_store_id, &version);
1281 if (!ok) 1746 if (!ok)
1282 return false; 1747 return false;
1283 DCHECK_GE(version, 0); 1748 DCHECK_GE(version, 0);
1284 const std::string object_storedata_key = 1749 const std::string object_store_data_key =
1285 ObjectStoreDataKey::Encode(database_id, object_store_id, key); 1750 ObjectStoreDataKey::Encode(database_id, object_store_id, key);
1286 1751
1287 std::string v; 1752 std::string v;
1288 EncodeVarInt(version, &v); 1753 EncodeVarInt(version, &v);
1289 v.append(value); 1754 v.append(value.bits);
1290 1755
1291 leveldb_transaction->Put(object_storedata_key, &v); 1756 leveldb_transaction->Put(object_store_data_key, &v);
1757 transaction->PutBlobInfo(database_id, object_store_id, object_store_data_key,
1758 &value.blob_info);
1292 1759
1293 const std::string exists_entry_key = 1760 const std::string exists_entry_key =
1294 ExistsEntryKey::Encode(database_id, object_store_id, key); 1761 ExistsEntryKey::Encode(database_id, object_store_id, key);
1295 std::string version_encoded; 1762 std::string version_encoded;
1296 EncodeInt(version, &version_encoded); 1763 EncodeInt(version, &version_encoded);
1297 leveldb_transaction->Put(exists_entry_key, &version_encoded); 1764 leveldb_transaction->Put(exists_entry_key, &version_encoded);
1298 1765
1299 std::string key_encoded; 1766 std::string key_encoded;
1300 EncodeIDBKey(key, &key_encoded); 1767 EncodeIDBKey(key, &key_encoded);
1301 record_identifier->Reset(key_encoded, version); 1768 record_identifier->Reset(key_encoded, version);
1302 return true; 1769 return true;
1303 } 1770 }
1304 1771
1305 bool IndexedDBBackingStore::ClearObjectStore( 1772 bool IndexedDBBackingStore::ClearObjectStore(
1306 IndexedDBBackingStore::Transaction* transaction, 1773 IndexedDBBackingStore::Transaction* transaction,
1307 int64 database_id, 1774 int64 database_id,
1308 int64 object_store_id) { 1775 int64 object_store_id) {
1309 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore"); 1776 IDB_TRACE("IndexedDBBackingStore::ClearObjectStore");
1310 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1777 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1311 return false; 1778 return false;
1312 LevelDBTransaction* leveldb_transaction = 1779 LevelDBTransaction* leveldb_transaction =
1313 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 1780 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1314 const std::string start_key = 1781 const std::string start_key =
1315 KeyPrefix(database_id, object_store_id).Encode(); 1782 KeyPrefix(database_id, object_store_id).Encode();
1316 const std::string stop_key = 1783 const std::string stop_key =
1317 KeyPrefix(database_id, object_store_id + 1).Encode(); 1784 KeyPrefix(database_id, object_store_id + 1).Encode();
1318 1785
1319 DeleteRange(leveldb_transaction, start_key, stop_key); 1786 DeleteRangeHelper(leveldb_transaction, start_key, stop_key);
1787 DeleteBlobsInObjectStore(transaction, database_id, object_store_id);
1320 return true; 1788 return true;
1321 } 1789 }
1322 1790
1323 bool IndexedDBBackingStore::DeleteRecord( 1791 bool IndexedDBBackingStore::DeleteRecord(
1324 IndexedDBBackingStore::Transaction* transaction, 1792 IndexedDBBackingStore::Transaction* transaction,
1325 int64 database_id, 1793 int64 database_id,
1326 int64 object_store_id, 1794 int64 object_store_id,
1327 const RecordIdentifier& record_identifier) { 1795 const RecordIdentifier& record_identifier) {
1796 fprintf(stderr, "ERICU: DeleteRecord.\n");
1328 IDB_TRACE("IndexedDBBackingStore::DeleteRecord"); 1797 IDB_TRACE("IndexedDBBackingStore::DeleteRecord");
1329 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1798 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1330 return false; 1799 return false;
1331 LevelDBTransaction* leveldb_transaction = 1800 LevelDBTransaction* leveldb_transaction =
1332 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 1801 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1333 1802
1334 const std::string object_store_data_key = ObjectStoreDataKey::Encode( 1803 const std::string object_store_data_key = ObjectStoreDataKey::Encode(
1335 database_id, object_store_id, record_identifier.primary_key()); 1804 database_id, object_store_id, record_identifier.primary_key());
1336 leveldb_transaction->Remove(object_store_data_key); 1805 leveldb_transaction->Remove(object_store_data_key);
1806 transaction->PutBlobInfo(database_id, object_store_id, object_store_data_key,
1807 NULL);
1337 1808
1338 const std::string exists_entry_key = ExistsEntryKey::Encode( 1809 const std::string exists_entry_key = ExistsEntryKey::Encode(
1339 database_id, object_store_id, record_identifier.primary_key()); 1810 database_id, object_store_id, record_identifier.primary_key());
1340 leveldb_transaction->Remove(exists_entry_key); 1811 leveldb_transaction->Remove(exists_entry_key);
1341 return true; 1812 return true;
1342 } 1813 }
1343 1814
1815 bool IndexedDBBackingStore::DeleteRange(
1816 IndexedDBBackingStore::Transaction* transaction,
1817 int64 database_id,
1818 int64 object_store_id,
1819 const IndexedDBKeyRange& key_range) {
1820 fprintf(stderr, "ERICU: DeleteRange.\n");
1821 scoped_ptr<IndexedDBBackingStore::Cursor> backing_store_cursor =
1822 OpenObjectStoreCursor(transaction, database_id, object_store_id,
1823 key_range, indexed_db::CURSOR_NEXT);
1824 if (backing_store_cursor) {
1825 do {
1826 if (!DeleteRecord(
1827 transaction, database_id, object_store_id,
1828 backing_store_cursor->record_identifier()))
1829 return false;
1830 } while (backing_store_cursor->Continue());
1831 }
1832
1833 std::string blob_lower =
1834 BlobEntryKey::Encode(database_id, object_store_id,
1835 key_range.lower());
1836 std::string blob_upper =
1837 BlobEntryKey::Encode(database_id, object_store_id,
1838 key_range.upper());
1839 LevelDBTransaction* leveldb_transaction =
1840 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1841 scoped_ptr<LevelDBIterator> it = leveldb_transaction->CreateIterator();
1842 it->Seek(blob_lower);
1843 while (it->IsValid() &&
1844 ((key_range.lowerOpen() &&
1845 CompareKeys(it->Key(), blob_lower) <= 0) ||
1846 (!key_range.lowerOpen() &&
1847 CompareKeys(it->Key(), blob_lower) < 0)))
jsbell 2013/09/13 00:12:21 Given it->Seek(blob_lower), can CompareKeys(it->Ke
ericu 2013/11/20 23:05:39 Nope; fixed.
1848 it->Next();
1849
1850 while (it->IsValid() &&
1851 ((key_range.upperOpen() &&
1852 CompareKeys(it->Key(), blob_upper) < 0) ||
1853 (!key_range.upperOpen() &&
1854 CompareKeys(it->Key(), blob_upper) <= 0))) {
1855 StringPiece key_piece(it->Key());
1856 std::string object_store_data_key =
1857 BlobEntryKey::EncodeToObjectStoreDataKey(&key_piece);
1858 if (!object_store_data_key.size())
1859 return false;
1860 transaction->PutBlobInfo(database_id, object_store_id,
1861 object_store_data_key, NULL);
1862 it->Next();
1863 }
1864
1865 return true;
1866 }
1867
1344 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber( 1868 bool IndexedDBBackingStore::GetKeyGeneratorCurrentNumber(
1345 IndexedDBBackingStore::Transaction* transaction, 1869 IndexedDBBackingStore::Transaction* transaction,
1346 int64 database_id, 1870 int64 database_id,
1347 int64 object_store_id, 1871 int64 object_store_id,
1348 int64* key_generator_current_number) { 1872 int64* key_generator_current_number) {
1349 if (!KeyPrefix::ValidIds(database_id, object_store_id)) 1873 if (!KeyPrefix::ValidIds(database_id, object_store_id))
1350 return false; 1874 return false;
1351 LevelDBTransaction* leveldb_transaction = 1875 LevelDBTransaction* leveldb_transaction =
1352 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 1876 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1353 1877
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 StringPiece slice(data); 1997 StringPiece slice(data);
1474 if (!DecodeVarInt(&slice, &version)) 1998 if (!DecodeVarInt(&slice, &version))
1475 return false; 1999 return false;
1476 2000
1477 std::string encoded_key; 2001 std::string encoded_key;
1478 EncodeIDBKey(key, &encoded_key); 2002 EncodeIDBKey(key, &encoded_key);
1479 found_record_identifier->Reset(encoded_key, version); 2003 found_record_identifier->Reset(encoded_key, version);
1480 return true; 2004 return true;
1481 } 2005 }
1482 2006
2007 class IndexedDBBackingStore::Transaction::ChainedBlobWriter : public
2008 base::RefCounted<IndexedDBBackingStore::Transaction::ChainedBlobWriter> {
2009 public:
2010 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
2011 WriteDescriptorVec;
2012 ChainedBlobWriter(
2013 int64 database_id,
2014 IndexedDBBackingStore* backingStore,
2015 WriteDescriptorVec& blobs,
2016 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
2017 : waiting_for_callback_(false),
2018 database_id_(database_id),
2019 backing_store_(backingStore),
2020 callback_(callback),
2021 aborted_(false) {
2022 blobs_.swap(blobs);
2023 iter_ = blobs_.begin();
2024 WriteNextFile();
2025 }
2026
2027 void set_delegate(scoped_ptr<FileWriterDelegate> delegate) {
2028 delegate_.reset(delegate.release());
2029 }
2030
2031 void ReportWriteCompletion(bool succeeded, int64 bytes_written) {
2032 // TODO(ericu): Is there any need to check bytes_written against what we
2033 // know, if we know it?
2034 DCHECK(waiting_for_callback_);
2035 DCHECK(bytes_written >= 0);
2036 waiting_for_callback_ = false;
2037 content::BrowserThread::DeleteSoon(
2038 content::BrowserThread::IO, FROM_HERE,
2039 delegate_.release());
2040 if (aborted_) {
2041 self_ref_ = NULL;
2042 return;
2043 }
2044 if (succeeded)
2045 WriteNextFile();
2046 else
2047 callback_->didFail();
2048 }
2049
2050 void Abort() {
2051 if (!waiting_for_callback_)
2052 return;
2053 self_ref_ = this;
2054 aborted_ = true;
2055 }
2056
2057 private:
2058 void WriteNextFile() {
2059 DCHECK(!waiting_for_callback_);
2060 DCHECK(!aborted_);
2061 if (iter_ == blobs_.end()) {
2062 callback_->didSucceed();
2063 self_ref_ = NULL;
2064 } else {
2065 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
2066 callback_->didFail();
2067 return;
2068 }
2069 waiting_for_callback_ = true;
2070 ++iter_;
2071 }
2072 }
2073
2074 bool waiting_for_callback_;
2075 scoped_refptr<ChainedBlobWriter> self_ref_;
2076 WriteDescriptorVec blobs_;
2077 WriteDescriptorVec::const_iterator iter_;
2078 int64 database_id_;
2079 IndexedDBBackingStore* backing_store_;
2080 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
2081 scoped_ptr<FileWriterDelegate> delegate_;
2082 bool aborted_;
2083 };
2084
2085 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
2086 public base::RefCounted<LocalWriteClosure> {
2087 public:
2088 LocalWriteClosure(
2089 IndexedDBBackingStore::Transaction::ChainedBlobWriter*
2090 chained_blob_writer_,
2091 base::TaskRunner* task_runner)
2092 : chained_blob_writer_(chained_blob_writer_),
2093 task_runner_(task_runner),
2094 bytes_written_(-1) {
2095 }
2096
2097 void Run(
2098 base::PlatformFileError rv,
2099 int64 bytes,
2100 FileWriterDelegate::WriteProgressStatus write_status) {
2101 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
2102 return; // We don't care about progress events.
2103 if (rv == base::PLATFORM_FILE_OK) {
2104 DCHECK(bytes >= 0);
2105 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED);
2106 bytes_written_ = bytes;
2107 } else {
2108 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
2109 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
2110 }
2111 task_runner_->PostTask(
2112 FROM_HERE,
2113 base::Bind(
2114 &LocalWriteClosure::callBlobCallbackOnIDBTaskRunner, this,
2115 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
2116 }
2117
2118 void writeBlobToFileOnIOThread(
2119 const FilePath& file_path, const GURL& blob_url,
2120 net::URLRequestContext* request_context) {
2121 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
2122 scoped_ptr<fileapi::FileStreamWriter> writer(
2123 new fileapi::LocalFileStreamWriter(
2124 task_runner_, file_path, 0, false));
2125 scoped_ptr<FileWriterDelegate> delegate(
2126 new FileWriterDelegate(writer.Pass()));
2127
2128 DCHECK(blob_url.is_valid());
2129 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
2130 blob_url, delegate.get()));
2131
2132 delegate->Start(blob_request.Pass(),
2133 base::Bind(&LocalWriteClosure::Run, this));
2134 chained_blob_writer_->set_delegate(delegate.Pass());
2135 }
2136
2137 private:
2138 void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
2139 DCHECK(task_runner_->RunsTasksOnCurrentThread());
2140 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
2141 }
2142
2143 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
2144 base::TaskRunner* task_runner_;
2145 int64 bytes_written_;
2146 };
2147
2148 bool IndexedDBBackingStore::WriteBlobFile(
2149 int64 database_id,
2150 const Transaction::WriteDescriptor& descriptor,
2151 Transaction::ChainedBlobWriter* chained_blob_writer) {
2152
2153 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
2154 return false;
2155
2156 FilePath path = GetIDBBlobFileName(database_id, descriptor.key());
2157
2158 if (descriptor.is_file()) {
2159 // TODO: Should we validate the snapshot date here?
2160 DCHECK(!descriptor.file_path().empty());
2161 if (!base::CopyFile(descriptor.file_path(), path))
2162 return false;
2163
2164 base::PlatformFileInfo info;
2165 if (file_util::GetFileInfo(descriptor.file_path(), &info)) {
2166 if (!file_util::TouchFile(path, info.last_accessed, info.last_modified))
2167 ; // TODO: Complain quietly; timestamp's probably not vital.
2168 } else {
2169 ; // TODO: Complain quietly; timestamp's probably not vital.
2170 }
2171
2172 task_runner_->PostTask(
2173 FROM_HERE,
2174 base::Bind(
2175 &Transaction::ChainedBlobWriter::ReportWriteCompletion,
2176 chained_blob_writer, true, info.size));
2177 } else {
2178 DCHECK(descriptor.url().is_valid());
2179 scoped_refptr<LocalWriteClosure> write_closure(
2180 new LocalWriteClosure(chained_blob_writer, task_runner_));
2181 content::BrowserThread::PostTask(
2182 content::BrowserThread::IO, FROM_HERE,
2183 base::Bind(
2184 &LocalWriteClosure::writeBlobToFileOnIOThread, write_closure.get(),
2185 path, descriptor.url(), request_context_));
2186 }
2187 return true;
2188 }
2189
2190 void IndexedDBBackingStore::ReportBlobUnused(
2191 int64 database_id,
2192 int64 blob_key) {
2193 fprintf(stderr, "ERICU: ReportBlobUnused(%ld, %ld).\n", database_id,
2194 blob_key);
2195 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
2196 bool all_blobs = blob_key == DatabaseMetaDataKey::kAllBlobsKey;
2197 DCHECK(all_blobs || DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2198 scoped_refptr<LevelDBTransaction> transaction =
2199 new LevelDBTransaction(db_.get());
2200
2201 std::string secondary_key = LiveBlobJournalKey::Encode();
2202 IndexedDBBackingStore::Transaction::BlobJournalType secondary_journal;
2203 if (!GetBlobJournal(secondary_key, transaction.get(), secondary_journal))
2204 return;
2205 DCHECK(secondary_journal.size());
2206
2207 std::string primary_key = BlobJournalKey::Encode();
2208 IndexedDBBackingStore::Transaction::BlobJournalType primary_journal;
2209 if (!GetBlobJournal(primary_key, transaction.get(), primary_journal))
2210 return;
2211
2212 IndexedDBBackingStore::Transaction::BlobJournalType::iterator journal_iter;
2213 // There are several cases to handle. If blob_key is kAllBlobsKey, we want to
2214 // remove all entries with database_id from the secondary journal and add only
2215 // kAllBlobsKey to the primary journal. Otherwise if IsValidBlobKey(blob_key)
2216 // and we hit kAllBlobsKey for the right database_id in the journal, we leave
2217 // the kAllBlobsKey entry in the secondary journal but add the specific blob
2218 // to the primary. Otherwise if IsValidBlobKey(blob_key) and we find a
2219 // matching (database_id, blob_key) tuple, we should move it to the primary
2220 // journal.
2221 fprintf(stderr, "ERICU: journal sizes are: %ld, %ld.\n",
2222 primary_journal.size(), secondary_journal.size());
2223 IndexedDBBackingStore::Transaction::BlobJournalType new_secondary_journal;
2224 for (journal_iter = secondary_journal.begin();
2225 journal_iter != secondary_journal.end(); ++journal_iter) {
2226 int64 current_database_id = journal_iter->first;
2227 int64 current_blob_key = journal_iter->second;
2228 bool current_all_blobs =
2229 current_blob_key == DatabaseMetaDataKey::kAllBlobsKey;
2230 DCHECK(KeyPrefix::IsValidDatabaseId(current_database_id) ||
2231 current_all_blobs);
2232 if (current_database_id == database_id && (all_blobs ||
2233 current_all_blobs || blob_key == current_blob_key)) {
2234 if (!all_blobs) {
2235 fprintf(stderr, "ERICU: moving to primary: %ld, %ld.\n", database_id,
2236 blob_key);
2237 primary_journal.push_back(
2238 std::make_pair(database_id, current_blob_key));
2239 if (current_all_blobs)
2240 new_secondary_journal.push_back(*journal_iter);
2241 new_secondary_journal.insert(new_secondary_journal.end(),
2242 ++journal_iter, secondary_journal.end()); // All the rest.
2243 break;
2244 } else {
2245 fprintf(stderr, "ERICU: was all_blobs\n");
2246 }
2247 } else {
2248 fprintf(stderr, "ERICU: leaving in secondary: %ld, %ld.\n", database_id,
2249 blob_key);
2250 new_secondary_journal.push_back(*journal_iter);
2251 }
2252 }
2253 if (all_blobs) {
2254 primary_journal.push_back(std::make_pair(
2255 database_id, DatabaseMetaDataKey::kAllBlobsKey));
2256 }
2257 fprintf(stderr, "ERICU: journal sizes are now: %ld, %ld.\n",
2258 primary_journal.size(), new_secondary_journal.size());
2259 UpdatePrimaryJournalWithBlobList(transaction.get(), primary_journal);
2260 UpdateSecondaryJournalWithBlobList(transaction.get(), new_secondary_journal);
2261 transaction->Commit();
2262 fprintf(stderr, "ERICU: committed journal updates. Cleaning in 5 sec.\n");
2263 // We could just do the deletions/cleaning here, but if there are a lot of
2264 // blobs about to be garbage collected, it'd be better to wait and do them all
2265 // at once.
2266 journal_cleaning_timer_.Start(
2267 FROM_HERE, base::TimeDelta::FromSeconds(5), this,
jsbell 2013/09/13 00:12:21 I just landed a change which tweaks the lifetime r
ericu 2013/11/20 23:05:39 OK, we should talk about what the right thing to d
ericu 2013/12/02 23:35:19 Addressed in patch set 57.
2268 &IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn);
2269 }
2270
2271 // This assumes a file path of dbId/3rd-byte-of-counter/counter.
2272 FilePath IndexedDBBackingStore::GetIDBBlobFileName(
2273 int64 database_id, int64 key) {
2274 FilePath path = GetIDBBlobDirectoryNameForKey(blob_path_, database_id, key);
2275 path = path.AppendASCII(base::StringPrintf("%lx", key));
2276 return path;
2277 }
2278
1483 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, 2279 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
1484 const std::string& stop_key, 2280 const std::string& stop_key,
1485 int64 index_id, 2281 int64 index_id,
1486 unsigned char meta_data_type) { 2282 unsigned char meta_data_type) {
1487 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 2283 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1488 return false; 2284 return false;
1489 2285
1490 StringPiece slice(it->Key()); 2286 StringPiece slice(it->Key());
1491 IndexMetaDataKey meta_data_key; 2287 IndexMetaDataKey meta_data_key;
1492 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 2288 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 2371
1576 it->Next(); 2372 it->Next();
1577 } 2373 }
1578 2374
1579 (*indexes)[index_id] = IndexedDBIndexMetadata( 2375 (*indexes)[index_id] = IndexedDBIndexMetadata(
1580 index_name, index_id, key_path, index_unique, index_multi_entry); 2376 index_name, index_id, key_path, index_unique, index_multi_entry);
1581 } 2377 }
1582 return true; 2378 return true;
1583 } 2379 }
1584 2380
2381 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
2382 FilePath fileName = GetIDBBlobFileName(database_id, key);
2383 return base::DeleteFile(fileName, false);
2384 }
2385
2386 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
2387 FilePath dirName = GetIDBBlobDirectoryName(blob_path_, database_id);
2388 return base::DeleteFile(dirName, true);
2389 }
2390
2391 bool IndexedDBBackingStore::CleanUpBlobJournal(
2392 const std::string& level_db_key) {
2393 scoped_refptr<LevelDBTransaction> journal_transaction =
2394 new LevelDBTransaction(db_.get());
2395 IndexedDBBackingStore::Transaction::BlobJournalType journal;
2396 if (!GetBlobJournal(level_db_key, journal_transaction.get(),
2397 journal)) {
2398 return false;
2399 }
2400 if (!journal.size()) {
2401 return true;
2402 }
2403 if (journal.size()) {
2404 IndexedDBBackingStore::Transaction::BlobJournalType::iterator journal_iter;
2405 for (journal_iter = journal.begin(); journal_iter != journal.end();
2406 ++journal_iter) {
2407 int64 database_id = journal_iter->first;
2408 int64 blob_key = journal_iter->second;
2409 DCHECK(KeyPrefix::IsValidDatabaseId(database_id));
2410 if (blob_key == DatabaseMetaDataKey::kAllBlobsKey) {
2411 RemoveBlobDirectory(database_id);
2412 } else {
2413 DCHECK(DatabaseMetaDataKey::IsValidBlobKey(blob_key));
2414 RemoveBlobFile(database_id, blob_key);
2415 }
2416 }
2417 }
2418 ClearBlobJournal(journal_transaction.get(), level_db_key);
2419 return journal_transaction->Commit();
2420 }
2421
2422 void IndexedDBBackingStore::CleanPrimaryJournalIgnoreReturn() {
2423 fprintf(stderr, "ERICU: Cleaning primary journal.\n");
2424 CleanUpBlobJournal(BlobJournalKey::Encode());
2425 }
2426
1585 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction, 2427 WARN_UNUSED_RESULT static bool SetMaxIndexId(LevelDBTransaction* transaction,
1586 int64 database_id, 2428 int64 database_id,
1587 int64 object_store_id, 2429 int64 object_store_id,
1588 int64 index_id) { 2430 int64 index_id) {
1589 int64 max_index_id = -1; 2431 int64 max_index_id = -1;
1590 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 2432 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1591 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 2433 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1592 bool found = false; 2434 bool found = false;
1593 bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found); 2435 bool ok = GetInt(transaction, max_index_id_key, &max_index_id, &found);
1594 if (!ok) { 2436 if (!ok) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1649 IDB_TRACE("IndexedDBBackingStore::DeleteIndex"); 2491 IDB_TRACE("IndexedDBBackingStore::DeleteIndex");
1650 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id)) 2492 if (!KeyPrefix::ValidIds(database_id, object_store_id, index_id))
1651 return false; 2493 return false;
1652 LevelDBTransaction* leveldb_transaction = 2494 LevelDBTransaction* leveldb_transaction =
1653 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 2495 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
1654 2496
1655 const std::string index_meta_data_start = 2497 const std::string index_meta_data_start =
1656 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0); 2498 IndexMetaDataKey::Encode(database_id, object_store_id, index_id, 0);
1657 const std::string index_meta_data_end = 2499 const std::string index_meta_data_end =
1658 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2500 IndexMetaDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
1659 DeleteRange(leveldb_transaction, index_meta_data_start, index_meta_data_end); 2501 DeleteRangeHelper(leveldb_transaction, index_meta_data_start,
2502 index_meta_data_end);
1660 2503
1661 const std::string index_data_start = 2504 const std::string index_data_start =
1662 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id); 2505 IndexDataKey::EncodeMinKey(database_id, object_store_id, index_id);
1663 const std::string index_data_end = 2506 const std::string index_data_end =
1664 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id); 2507 IndexDataKey::EncodeMaxKey(database_id, object_store_id, index_id);
1665 DeleteRange(leveldb_transaction, index_data_start, index_data_end); 2508 DeleteRangeHelper(leveldb_transaction, index_data_start, index_data_end);
1666 return true; 2509 return true;
1667 } 2510 }
1668 2511
1669 bool IndexedDBBackingStore::PutIndexDataForRecord( 2512 bool IndexedDBBackingStore::PutIndexDataForRecord(
1670 IndexedDBBackingStore::Transaction* transaction, 2513 IndexedDBBackingStore::Transaction* transaction,
1671 int64 database_id, 2514 int64 database_id,
1672 int64 object_store_id, 2515 int64 object_store_id,
1673 int64 index_id, 2516 int64 index_id,
1674 const IndexedDBKey& key, 2517 const IndexedDBKey& key,
1675 const RecordIdentifier& record_identifier) { 2518 const RecordIdentifier& record_identifier) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1876 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX); 2719 INTERNAL_READ_ERROR(KEY_EXISTS_IN_INDEX);
1877 return false; 2720 return false;
1878 } 2721 }
1879 2722
1880 StringPiece slice(found_encoded_primary_key); 2723 StringPiece slice(found_encoded_primary_key);
1881 return DecodeIDBKey(&slice, found_primary_key) && slice.empty(); 2724 return DecodeIDBKey(&slice, found_primary_key) && slice.empty();
1882 } 2725 }
1883 2726
1884 IndexedDBBackingStore::Cursor::Cursor( 2727 IndexedDBBackingStore::Cursor::Cursor(
1885 const IndexedDBBackingStore::Cursor* other) 2728 const IndexedDBBackingStore::Cursor* other)
1886 : transaction_(other->transaction_), 2729 : backing_store_(other->backing_store_),
2730 transaction_(other->transaction_),
2731 database_id_(other->database_id_),
1887 cursor_options_(other->cursor_options_), 2732 cursor_options_(other->cursor_options_),
1888 current_key_(new IndexedDBKey(*other->current_key_)) { 2733 current_key_(new IndexedDBKey(*other->current_key_)) {
1889 if (other->iterator_) { 2734 if (other->iterator_) {
1890 iterator_ = transaction_->CreateIterator(); 2735 iterator_ = transaction_->CreateIterator();
1891 2736
1892 if (other->iterator_->IsValid()) { 2737 if (other->iterator_->IsValid()) {
1893 iterator_->Seek(other->iterator_->Key()); 2738 iterator_->Seek(other->iterator_->Key());
1894 DCHECK(iterator_->IsValid()); 2739 DCHECK(iterator_->IsValid());
1895 } 2740 }
1896 } 2741 }
1897 } 2742 }
1898 2743
1899 IndexedDBBackingStore::Cursor::Cursor(LevelDBTransaction* transaction, 2744 IndexedDBBackingStore::Cursor::Cursor(
1900 const CursorOptions& cursor_options) 2745 scoped_refptr<IndexedDBBackingStore> backing_store,
1901 : transaction_(transaction), cursor_options_(cursor_options) {} 2746 LevelDBTransaction* transaction,
2747 int64 database_id,
2748 const CursorOptions& cursor_options)
2749 : backing_store_(backing_store),
2750 transaction_(transaction),
2751 database_id_(database_id),
2752 cursor_options_(cursor_options) {
2753 }
1902 IndexedDBBackingStore::Cursor::~Cursor() {} 2754 IndexedDBBackingStore::Cursor::~Cursor() {}
1903 2755
1904 bool IndexedDBBackingStore::Cursor::FirstSeek() { 2756 bool IndexedDBBackingStore::Cursor::FirstSeek() {
1905 iterator_ = transaction_->CreateIterator(); 2757 iterator_ = transaction_->CreateIterator();
1906 if (cursor_options_.forward) 2758 if (cursor_options_.forward)
1907 iterator_->Seek(cursor_options_.low_key); 2759 iterator_->Seek(cursor_options_.low_key);
1908 else 2760 else
1909 iterator_->Seek(cursor_options_.high_key); 2761 iterator_->Seek(cursor_options_.high_key);
1910 2762
1911 return Continue(0, READY); 2763 return Continue(0, READY);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2055 } 2907 }
2056 2908
2057 const IndexedDBBackingStore::RecordIdentifier& 2909 const IndexedDBBackingStore::RecordIdentifier&
2058 IndexedDBBackingStore::Cursor::record_identifier() const { 2910 IndexedDBBackingStore::Cursor::record_identifier() const {
2059 return record_identifier_; 2911 return record_identifier_;
2060 } 2912 }
2061 2913
2062 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor { 2914 class ObjectStoreKeyCursorImpl : public IndexedDBBackingStore::Cursor {
2063 public: 2915 public:
2064 ObjectStoreKeyCursorImpl( 2916 ObjectStoreKeyCursorImpl(
2917 scoped_refptr<IndexedDBBackingStore> backing_store,
2065 LevelDBTransaction* transaction, 2918 LevelDBTransaction* transaction,
2919 int64 database_id,
2066 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 2920 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2067 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 2921 : IndexedDBBackingStore::Cursor(
2922 backing_store, transaction, database_id, cursor_options) {}
2068 2923
2069 virtual Cursor* Clone() OVERRIDE { 2924 virtual Cursor* Clone() OVERRIDE {
2070 return new ObjectStoreKeyCursorImpl(this); 2925 return new ObjectStoreKeyCursorImpl(this);
2071 } 2926 }
2072 2927
2073 // IndexedDBBackingStore::Cursor 2928 // IndexedDBBackingStore::Cursor
2074 virtual std::string* Value() OVERRIDE { 2929 virtual IndexedDBValue* Value() OVERRIDE {
2075 NOTREACHED(); 2930 NOTREACHED();
2076 return NULL; 2931 return NULL;
2077 } 2932 }
2078 virtual bool LoadCurrentRow() OVERRIDE; 2933 virtual bool LoadCurrentRow() OVERRIDE;
2079 2934
2080 protected: 2935 protected:
2081 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 2936 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2082 return ObjectStoreDataKey::Encode( 2937 return ObjectStoreDataKey::Encode(
2083 cursor_options_.database_id, cursor_options_.object_store_id, key); 2938 cursor_options_.database_id, cursor_options_.object_store_id, key);
2084 } 2939 }
(...skipping 24 matching lines...) Expand all
2109 std::string encoded_key; 2964 std::string encoded_key;
2110 EncodeIDBKey(*current_key_, &encoded_key); 2965 EncodeIDBKey(*current_key_, &encoded_key);
2111 record_identifier_.Reset(encoded_key, version); 2966 record_identifier_.Reset(encoded_key, version);
2112 2967
2113 return true; 2968 return true;
2114 } 2969 }
2115 2970
2116 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor { 2971 class ObjectStoreCursorImpl : public IndexedDBBackingStore::Cursor {
2117 public: 2972 public:
2118 ObjectStoreCursorImpl( 2973 ObjectStoreCursorImpl(
2974 scoped_refptr<IndexedDBBackingStore> backing_store,
2119 LevelDBTransaction* transaction, 2975 LevelDBTransaction* transaction,
2976 int64 database_id,
2120 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 2977 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2121 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 2978 : IndexedDBBackingStore::Cursor(
2979 backing_store, transaction, database_id, cursor_options) {}
2122 2980
2123 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); } 2981 virtual Cursor* Clone() OVERRIDE { return new ObjectStoreCursorImpl(this); }
2124 2982
2125 // IndexedDBBackingStore::Cursor 2983 // IndexedDBBackingStore::Cursor
2126 virtual std::string* Value() OVERRIDE { return &current_value_; } 2984 virtual IndexedDBValue* Value() OVERRIDE { return &current_value_; }
2127 virtual bool LoadCurrentRow() OVERRIDE; 2985 virtual bool LoadCurrentRow() OVERRIDE;
2128 2986
2129 protected: 2987 protected:
2130 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 2988 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2131 return ObjectStoreDataKey::Encode( 2989 return ObjectStoreDataKey::Encode(
2132 cursor_options_.database_id, cursor_options_.object_store_id, key); 2990 cursor_options_.database_id, cursor_options_.object_store_id, key);
2133 } 2991 }
2134 2992
2135 private: 2993 private:
2136 explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other) 2994 explicit ObjectStoreCursorImpl(const ObjectStoreCursorImpl* other)
2137 : IndexedDBBackingStore::Cursor(other), 2995 : IndexedDBBackingStore::Cursor(other),
2138 current_value_(other->current_value_) {} 2996 current_value_(other->current_value_) {}
2139 2997
2140 std::string current_value_; 2998 IndexedDBValue current_value_;
2141 }; 2999 };
2142 3000
2143 bool ObjectStoreCursorImpl::LoadCurrentRow() { 3001 bool ObjectStoreCursorImpl::LoadCurrentRow() {
2144 StringPiece slice(iterator_->Key()); 3002 StringPiece key_slice(iterator_->Key());
2145 ObjectStoreDataKey object_store_data_key; 3003 ObjectStoreDataKey object_store_data_key;
2146 if (!ObjectStoreDataKey::Decode(&slice, &object_store_data_key)) { 3004 if (!ObjectStoreDataKey::Decode(&key_slice, &object_store_data_key)) {
2147 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3005 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2148 return false; 3006 return false;
2149 } 3007 }
2150 3008
2151 current_key_ = object_store_data_key.user_key(); 3009 current_key_ = object_store_data_key.user_key();
2152 3010
2153 int64 version; 3011 int64 version;
2154 slice = StringPiece(iterator_->Value()); 3012 StringPiece value_slice = StringPiece(iterator_->Value());
2155 if (!DecodeVarInt(&slice, &version)) { 3013 if (!DecodeVarInt(&value_slice, &version)) {
2156 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3014 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2157 return false; 3015 return false;
2158 } 3016 }
2159 3017
2160 // TODO(jsbell): This re-encodes what was just decoded; try and optimize. 3018 // TODO(jsbell): This re-encodes what was just decoded; try and optimize.
2161 std::string encoded_key; 3019 std::string encoded_key;
2162 EncodeIDBKey(*current_key_, &encoded_key); 3020 EncodeIDBKey(*current_key_, &encoded_key);
2163 record_identifier_.Reset(encoded_key, version); 3021 record_identifier_.Reset(encoded_key, version);
2164 3022
2165 current_value_ = slice.as_string(); 3023 // TODO(ericu): Don't set bits until we know we've succeeded?
2166 return true; 3024 current_value_.bits = value_slice.as_string();
3025 return GetBlobInfoForRecord(backing_store_, transaction_, database_id_,
3026 iterator_->Key().as_string(), &current_value_);
2167 } 3027 }
2168 3028
2169 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor { 3029 class IndexKeyCursorImpl : public IndexedDBBackingStore::Cursor {
2170 public: 3030 public:
2171 IndexKeyCursorImpl( 3031 IndexKeyCursorImpl(
3032 scoped_refptr<IndexedDBBackingStore> backing_store,
2172 LevelDBTransaction* transaction, 3033 LevelDBTransaction* transaction,
3034 int64 database_id,
2173 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3035 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2174 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3036 : IndexedDBBackingStore::Cursor(
3037 backing_store, transaction, database_id, cursor_options) {}
2175 3038
2176 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); } 3039 virtual Cursor* Clone() OVERRIDE { return new IndexKeyCursorImpl(this); }
2177 3040
2178 // IndexedDBBackingStore::Cursor 3041 // IndexedDBBackingStore::Cursor
2179 virtual std::string* Value() OVERRIDE { 3042 virtual IndexedDBValue* Value() OVERRIDE {
2180 NOTREACHED(); 3043 NOTREACHED();
2181 return NULL; 3044 return NULL;
2182 } 3045 }
2183 virtual const IndexedDBKey& primary_key() const OVERRIDE { 3046 virtual const IndexedDBKey& primary_key() const OVERRIDE {
2184 return *primary_key_; 3047 return *primary_key_;
2185 } 3048 }
2186 virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() 3049 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
2187 const { 3050 const OVERRIDE {
2188 NOTREACHED(); 3051 NOTREACHED();
2189 return record_identifier_; 3052 return record_identifier_;
2190 } 3053 }
2191 virtual bool LoadCurrentRow() OVERRIDE; 3054 virtual bool LoadCurrentRow() OVERRIDE;
2192 3055
2193 protected: 3056 protected:
2194 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 3057 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2195 return IndexDataKey::Encode(cursor_options_.database_id, 3058 return IndexDataKey::Encode(cursor_options_.database_id,
2196 cursor_options_.object_store_id, 3059 cursor_options_.object_store_id,
2197 cursor_options_.index_id, 3060 cursor_options_.index_id,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2261 transaction_->Remove(iterator_->Key()); 3124 transaction_->Remove(iterator_->Key());
2262 return false; 3125 return false;
2263 } 3126 }
2264 3127
2265 return true; 3128 return true;
2266 } 3129 }
2267 3130
2268 class IndexCursorImpl : public IndexedDBBackingStore::Cursor { 3131 class IndexCursorImpl : public IndexedDBBackingStore::Cursor {
2269 public: 3132 public:
2270 IndexCursorImpl( 3133 IndexCursorImpl(
3134 scoped_refptr<IndexedDBBackingStore> backing_store,
2271 LevelDBTransaction* transaction, 3135 LevelDBTransaction* transaction,
3136 int64 database_id,
2272 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options) 3137 const IndexedDBBackingStore::Cursor::CursorOptions& cursor_options)
2273 : IndexedDBBackingStore::Cursor(transaction, cursor_options) {} 3138 : IndexedDBBackingStore::Cursor(
3139 backing_store, transaction, database_id, cursor_options) {}
2274 3140
2275 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); } 3141 virtual Cursor* Clone() OVERRIDE { return new IndexCursorImpl(this); }
2276 3142
2277 // IndexedDBBackingStore::Cursor 3143 // IndexedDBBackingStore::Cursor
2278 virtual std::string* Value() OVERRIDE { return &current_value_; } 3144 virtual IndexedDBValue* Value() OVERRIDE { return &current_value_; }
2279 virtual const IndexedDBKey& primary_key() const OVERRIDE { 3145 virtual const IndexedDBKey& primary_key() const OVERRIDE {
2280 return *primary_key_; 3146 return *primary_key_;
2281 } 3147 }
2282 virtual const IndexedDBBackingStore::RecordIdentifier& RecordIdentifier() 3148 virtual const IndexedDBBackingStore::RecordIdentifier& record_identifier()
2283 const { 3149 const OVERRIDE {
2284 NOTREACHED(); 3150 NOTREACHED();
2285 return record_identifier_; 3151 return record_identifier_;
2286 } 3152 }
2287 virtual bool LoadCurrentRow() OVERRIDE; 3153 virtual bool LoadCurrentRow() OVERRIDE;
2288 3154
2289 protected: 3155 protected:
2290 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE { 3156 virtual std::string EncodeKey(const IndexedDBKey& key) OVERRIDE {
2291 return IndexDataKey::Encode(cursor_options_.database_id, 3157 return IndexDataKey::Encode(cursor_options_.database_id,
2292 cursor_options_.object_store_id, 3158 cursor_options_.object_store_id,
2293 cursor_options_.index_id, 3159 cursor_options_.index_id,
2294 key); 3160 key);
2295 } 3161 }
2296 3162
2297 private: 3163 private:
2298 explicit IndexCursorImpl(const IndexCursorImpl* other) 3164 explicit IndexCursorImpl(const IndexCursorImpl* other)
2299 : IndexedDBBackingStore::Cursor(other), 3165 : IndexedDBBackingStore::Cursor(other),
2300 primary_key_(new IndexedDBKey(*other->primary_key_)), 3166 primary_key_(new IndexedDBKey(*other->primary_key_)),
2301 current_value_(other->current_value_), 3167 current_value_(other->current_value_),
2302 primary_leveldb_key_(other->primary_leveldb_key_) {} 3168 primary_leveldb_key_(other->primary_leveldb_key_) {}
2303 3169
2304 scoped_ptr<IndexedDBKey> primary_key_; 3170 scoped_ptr<IndexedDBKey> primary_key_;
2305 std::string current_value_; 3171 IndexedDBValue current_value_;
2306 std::string primary_leveldb_key_; 3172 std::string primary_leveldb_key_;
2307 }; 3173 };
2308 3174
2309 bool IndexCursorImpl::LoadCurrentRow() { 3175 bool IndexCursorImpl::LoadCurrentRow() {
2310 StringPiece slice(iterator_->Key()); 3176 StringPiece slice(iterator_->Key());
2311 IndexDataKey index_data_key; 3177 IndexDataKey index_data_key;
2312 if (!IndexDataKey::Decode(&slice, &index_data_key)) { 3178 if (!IndexDataKey::Decode(&slice, &index_data_key)) {
2313 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3179 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2314 return false; 3180 return false;
2315 } 3181 }
2316 3182
2317 current_key_ = index_data_key.user_key(); 3183 current_key_ = index_data_key.user_key();
2318 DCHECK(current_key_); 3184 DCHECK(current_key_);
2319 3185
2320 slice = StringPiece(iterator_->Value()); 3186 slice = StringPiece(iterator_->Value());
2321 int64 index_data_version; 3187 int64 index_data_version;
2322 if (!DecodeVarInt(&slice, &index_data_version)) { 3188 if (!DecodeVarInt(&slice, &index_data_version)) {
2323 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3189 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2324 return false; 3190 return false;
2325 } 3191 }
2326 if (!DecodeIDBKey(&slice, &primary_key_)) { 3192 if (!DecodeIDBKey(&slice, &primary_key_)) {
2327 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3193 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2328 return false; 3194 return false;
2329 } 3195 }
2330 3196
3197 DCHECK_EQ(index_data_key.DatabaseId(), database_id_);
2331 primary_leveldb_key_ = 3198 primary_leveldb_key_ =
2332 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(), 3199 ObjectStoreDataKey::Encode(index_data_key.DatabaseId(),
2333 index_data_key.ObjectStoreId(), 3200 index_data_key.ObjectStoreId(),
2334 *primary_key_); 3201 *primary_key_);
2335 3202
2336 std::string result; 3203 std::string result;
2337 bool found = false; 3204 bool found = false;
2338 bool ok = transaction_->Get(primary_leveldb_key_, &result, &found); 3205 bool ok = transaction_->Get(primary_leveldb_key_, &result, &found);
2339 if (!ok) { 3206 if (!ok) {
2340 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3207 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
(...skipping 13 matching lines...) Expand all
2354 if (!DecodeVarInt(&slice, &object_store_data_version)) { 3221 if (!DecodeVarInt(&slice, &object_store_data_version)) {
2355 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW); 3222 INTERNAL_READ_ERROR(LOAD_CURRENT_ROW);
2356 return false; 3223 return false;
2357 } 3224 }
2358 3225
2359 if (object_store_data_version != index_data_version) { 3226 if (object_store_data_version != index_data_version) {
2360 transaction_->Remove(iterator_->Key()); 3227 transaction_->Remove(iterator_->Key());
2361 return false; 3228 return false;
2362 } 3229 }
2363 3230
2364 current_value_ = slice.as_string(); 3231 current_value_.bits = slice.as_string();
2365 return true; 3232 return GetBlobInfoForRecord(backing_store_, transaction_, database_id_,
3233 primary_leveldb_key_, &current_value_);
2366 } 3234 }
2367 3235
2368 bool ObjectStoreCursorOptions( 3236 bool ObjectStoreCursorOptions(
2369 LevelDBTransaction* transaction, 3237 LevelDBTransaction* transaction,
2370 int64 database_id, 3238 int64 database_id,
2371 int64 object_store_id, 3239 int64 object_store_id,
2372 const IndexedDBKeyRange& range, 3240 const IndexedDBKeyRange& range,
2373 indexed_db::CursorDirection direction, 3241 indexed_db::CursorDirection direction,
2374 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) { 3242 IndexedDBBackingStore::Cursor::CursorOptions* cursor_options) {
2375 cursor_options->database_id = database_id; 3243 cursor_options->database_id = database_id;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2513 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 3381 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
2514 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3382 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2515 if (!ObjectStoreCursorOptions(leveldb_transaction, 3383 if (!ObjectStoreCursorOptions(leveldb_transaction,
2516 database_id, 3384 database_id,
2517 object_store_id, 3385 object_store_id,
2518 range, 3386 range,
2519 direction, 3387 direction,
2520 &cursor_options)) 3388 &cursor_options))
2521 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3389 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2522 scoped_ptr<ObjectStoreCursorImpl> cursor( 3390 scoped_ptr<ObjectStoreCursorImpl> cursor(
2523 new ObjectStoreCursorImpl(leveldb_transaction, cursor_options)); 3391 new ObjectStoreCursorImpl(
3392 this, leveldb_transaction, database_id, cursor_options));
2524 if (!cursor->FirstSeek()) 3393 if (!cursor->FirstSeek())
2525 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3394 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2526 3395
2527 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3396 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2528 } 3397 }
2529 3398
2530 scoped_ptr<IndexedDBBackingStore::Cursor> 3399 scoped_ptr<IndexedDBBackingStore::Cursor>
2531 IndexedDBBackingStore::OpenObjectStoreKeyCursor( 3400 IndexedDBBackingStore::OpenObjectStoreKeyCursor(
2532 IndexedDBBackingStore::Transaction* transaction, 3401 IndexedDBBackingStore::Transaction* transaction,
2533 int64 database_id, 3402 int64 database_id,
2534 int64 object_store_id, 3403 int64 object_store_id,
2535 const IndexedDBKeyRange& range, 3404 const IndexedDBKeyRange& range,
2536 indexed_db::CursorDirection direction) { 3405 indexed_db::CursorDirection direction) {
2537 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor"); 3406 IDB_TRACE("IndexedDBBackingStore::OpenObjectStoreKeyCursor");
2538 LevelDBTransaction* leveldb_transaction = 3407 LevelDBTransaction* leveldb_transaction =
2539 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 3408 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
2540 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3409 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2541 if (!ObjectStoreCursorOptions(leveldb_transaction, 3410 if (!ObjectStoreCursorOptions(leveldb_transaction,
2542 database_id, 3411 database_id,
2543 object_store_id, 3412 object_store_id,
2544 range, 3413 range,
2545 direction, 3414 direction,
2546 &cursor_options)) 3415 &cursor_options))
2547 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3416 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2548 scoped_ptr<ObjectStoreKeyCursorImpl> cursor( 3417 scoped_ptr<ObjectStoreKeyCursorImpl> cursor(
2549 new ObjectStoreKeyCursorImpl(leveldb_transaction, cursor_options)); 3418 new ObjectStoreKeyCursorImpl(
3419 this, leveldb_transaction, database_id, cursor_options));
2550 if (!cursor->FirstSeek()) 3420 if (!cursor->FirstSeek())
2551 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3421 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2552 3422
2553 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3423 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2554 } 3424 }
2555 3425
2556 scoped_ptr<IndexedDBBackingStore::Cursor> 3426 scoped_ptr<IndexedDBBackingStore::Cursor>
2557 IndexedDBBackingStore::OpenIndexKeyCursor( 3427 IndexedDBBackingStore::OpenIndexKeyCursor(
2558 IndexedDBBackingStore::Transaction* transaction, 3428 IndexedDBBackingStore::Transaction* transaction,
2559 int64 database_id, 3429 int64 database_id,
2560 int64 object_store_id, 3430 int64 object_store_id,
2561 int64 index_id, 3431 int64 index_id,
2562 const IndexedDBKeyRange& range, 3432 const IndexedDBKeyRange& range,
2563 indexed_db::CursorDirection direction) { 3433 indexed_db::CursorDirection direction) {
2564 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor"); 3434 IDB_TRACE("IndexedDBBackingStore::OpenIndexKeyCursor");
2565 LevelDBTransaction* leveldb_transaction = 3435 LevelDBTransaction* leveldb_transaction =
2566 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 3436 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
2567 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3437 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2568 if (!IndexCursorOptions(leveldb_transaction, 3438 if (!IndexCursorOptions(leveldb_transaction,
2569 database_id, 3439 database_id,
2570 object_store_id, 3440 object_store_id,
2571 index_id, 3441 index_id,
2572 range, 3442 range,
2573 direction, 3443 direction,
2574 &cursor_options)) 3444 &cursor_options))
2575 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3445 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2576 scoped_ptr<IndexKeyCursorImpl> cursor( 3446 scoped_ptr<IndexKeyCursorImpl> cursor(
2577 new IndexKeyCursorImpl(leveldb_transaction, cursor_options)); 3447 new IndexKeyCursorImpl(
3448 this, leveldb_transaction, database_id, cursor_options));
2578 if (!cursor->FirstSeek()) 3449 if (!cursor->FirstSeek())
2579 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3450 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2580 3451
2581 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3452 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2582 } 3453 }
2583 3454
2584 scoped_ptr<IndexedDBBackingStore::Cursor> 3455 scoped_ptr<IndexedDBBackingStore::Cursor>
2585 IndexedDBBackingStore::OpenIndexCursor( 3456 IndexedDBBackingStore::OpenIndexCursor(
2586 IndexedDBBackingStore::Transaction* transaction, 3457 IndexedDBBackingStore::Transaction* transaction,
2587 int64 database_id, 3458 int64 database_id,
2588 int64 object_store_id, 3459 int64 object_store_id,
2589 int64 index_id, 3460 int64 index_id,
2590 const IndexedDBKeyRange& range, 3461 const IndexedDBKeyRange& range,
2591 indexed_db::CursorDirection direction) { 3462 indexed_db::CursorDirection direction) {
2592 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor"); 3463 IDB_TRACE("IndexedDBBackingStore::OpenIndexCursor");
2593 LevelDBTransaction* leveldb_transaction = 3464 LevelDBTransaction* leveldb_transaction =
2594 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction); 3465 IndexedDBBackingStore::Transaction::LevelDBTransactionFrom(transaction);
2595 IndexedDBBackingStore::Cursor::CursorOptions cursor_options; 3466 IndexedDBBackingStore::Cursor::CursorOptions cursor_options;
2596 if (!IndexCursorOptions(leveldb_transaction, 3467 if (!IndexCursorOptions(leveldb_transaction,
2597 database_id, 3468 database_id,
2598 object_store_id, 3469 object_store_id,
2599 index_id, 3470 index_id,
2600 range, 3471 range,
2601 direction, 3472 direction,
2602 &cursor_options)) 3473 &cursor_options))
2603 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3474 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2604 scoped_ptr<IndexCursorImpl> cursor( 3475 scoped_ptr<IndexCursorImpl> cursor(
2605 new IndexCursorImpl(leveldb_transaction, cursor_options)); 3476 new IndexCursorImpl(
3477 this, leveldb_transaction, database_id, cursor_options));
2606 if (!cursor->FirstSeek()) 3478 if (!cursor->FirstSeek())
2607 return scoped_ptr<IndexedDBBackingStore::Cursor>(); 3479 return scoped_ptr<IndexedDBBackingStore::Cursor>();
2608 3480
2609 return cursor.PassAs<IndexedDBBackingStore::Cursor>(); 3481 return cursor.PassAs<IndexedDBBackingStore::Cursor>();
2610 } 3482 }
2611 3483
2612 IndexedDBBackingStore::Transaction::Transaction( 3484 IndexedDBBackingStore::Transaction::Transaction(
2613 IndexedDBBackingStore* backing_store) 3485 IndexedDBBackingStore* backing_store)
2614 : backing_store_(backing_store) {} 3486 : backing_store_(backing_store),
3487 database_id_(-1) {
3488 blob_info_tree_.abstractor().comparator_ = backing_store->comparator();
3489 }
2615 3490
2616 IndexedDBBackingStore::Transaction::~Transaction() {} 3491 IndexedDBBackingStore::Transaction::~Transaction() {}
2617 3492
2618 void IndexedDBBackingStore::Transaction::Begin() { 3493 void IndexedDBBackingStore::Transaction::Begin() {
2619 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin"); 3494 IDB_TRACE("IndexedDBBackingStore::Transaction::Begin");
2620 DCHECK(!transaction_.get()); 3495 DCHECK(!transaction_.get());
2621 transaction_ = new LevelDBTransaction(backing_store_->db_.get()); 3496 transaction_ = new LevelDBTransaction(backing_store_->db_.get());
2622 } 3497 fprintf(stderr, "ERICU: %p::Begin(%p).\n", this, transaction_.get());
2623 3498 }
2624 bool IndexedDBBackingStore::Transaction::Commit() { 3499
2625 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3500 bool IndexedDBBackingStore::Transaction::HandleBlobPreTransaction(
2626 DCHECK(transaction_.get()); 3501 BlobEntryKeyValuePairVec* new_blob_entries,
3502 WriteDescriptorVec* new_files_to_write) {
3503 TreeType::Iterator iter;
3504 iter.StartIterLeast(&blob_info_tree_);
3505 new_blob_entries->clear();
3506 new_files_to_write->clear();
3507 if (*iter) {
3508 // Create LevelDBTransaction for the name generator seed and add-journal.
3509 scoped_refptr<LevelDBTransaction> pre_transaction =
3510 new LevelDBTransaction(backing_store_->db_.get());
3511 BlobJournalType journal;
3512 for (; *iter; ++iter) {
3513 std::vector<IndexedDBBlobInfo>::iterator info_iter;
3514 std::vector<IndexedDBBlobInfo*> new_blob_keys;
3515 for (info_iter = (*iter)->blob_info.begin();
3516 info_iter != (*iter)->blob_info.end(); ++info_iter) {
3517 int64 next_blob_key = -1;
3518 bool result = GetBlobKeyGeneratorCurrentNumber(
3519 pre_transaction.get(), database_id_, next_blob_key);
3520 if (!result || next_blob_key < 0)
3521 return false;
3522 BlobJournalEntryType journal_entry =
3523 std::make_pair(database_id_, next_blob_key);
3524 journal.push_back(journal_entry);
3525 if (info_iter->is_file()) {
3526 new_files_to_write->push_back(
3527 WriteDescriptor(info_iter->file_path(), next_blob_key));
3528 } else {
3529 new_files_to_write->push_back(
3530 WriteDescriptor(info_iter->url(), next_blob_key));
3531 }
3532 info_iter->set_key(next_blob_key);
3533 new_blob_keys.push_back(&*info_iter);
3534 result = UpdateBlobKeyGeneratorCurrentNumber(
3535 pre_transaction.get(), database_id_, next_blob_key + 1);
3536 if (!result)
3537 return result;
3538 }
3539 BlobEntryKey blob_entry_key;
3540 StringPiece key_piece((*iter)->key);
3541 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3542 NOTREACHED();
3543 return false;
3544 }
3545 new_blob_entries->push_back(std::make_pair(blob_entry_key,
3546 EncodeBlobData(new_blob_keys)));
3547 }
3548 UpdatePrimaryJournalWithBlobList(pre_transaction.get(), journal);
3549 if (!pre_transaction->Commit())
3550 return false;
3551 }
3552 return true;
3553 }
3554
3555 bool IndexedDBBackingStore::Transaction::CollectBlobFilesToRemove() {
3556 TreeType::Iterator iter;
3557 iter.StartIterLeast(&blob_info_tree_);
3558 // Look up all old files to remove as part of the transaction, store their
3559 // names in blobs_to_remove_, and remove their old blob data entries.
3560 if (*iter) {
3561 scoped_ptr<LevelDBIterator> db_iter = transaction_->CreateIterator();
3562 for (; *iter; ++iter) {
3563 BlobEntryKey blob_entry_key;
3564 StringPiece key_piece((*iter)->key);
3565 if (!BlobEntryKey::FromObjectStoreDataKey(&key_piece, &blob_entry_key)) {
3566 NOTREACHED();
3567 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3568 transaction_ = NULL;
3569 return false;
3570 }
3571 if (database_id_ < 0)
3572 database_id_ = blob_entry_key.database_id();
3573 else
3574 DCHECK_EQ(database_id_, blob_entry_key.database_id());
3575 std::string blob_entry_key_bytes = blob_entry_key.Encode();
3576 db_iter->Seek(blob_entry_key_bytes);
3577 if (db_iter->IsValid()) {
3578 std::vector<IndexedDBBlobInfo> blob_info;
3579 if (!DecodeBlobData(db_iter->Value().as_string(), &blob_info)) {
3580 INTERNAL_READ_ERROR(TRANSACTION_COMMIT_METHOD);
3581 transaction_ = NULL;
3582 return false;
3583 }
3584 std::vector<IndexedDBBlobInfo>::iterator blob_info_iter;
3585 for (blob_info_iter = blob_info.begin();
3586 blob_info_iter != blob_info.end(); ++blob_info_iter)
3587 blobs_to_remove_.push_back(
3588 std::make_pair(database_id_, blob_info_iter->key()));
3589 transaction_->Remove(blob_entry_key_bytes);
3590 } else {
3591 fprintf(stderr, "ERICU: db_iter wasn't valid.\n");
3592 }
3593 }
3594 }
3595 return true;
3596 }
3597
3598 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
3599 BlobEntryKeyValuePairVec& new_blob_entries,
3600 WriteDescriptorVec& new_files_to_write,
3601 scoped_refptr<BlobWriteCallback> callback) {
3602 DCHECK_GT(new_files_to_write.size(), 0UL);
3603 DCHECK_GT(database_id_, 0);
3604 BlobEntryKeyValuePairVec::iterator blob_entry_iter;
3605 for (blob_entry_iter = new_blob_entries.begin();
3606 blob_entry_iter != new_blob_entries.end(); ++blob_entry_iter) {
3607 // Add the new blob-table entry for each blob to the main transaction, or
3608 // remove any entry that may exist if there's no new one.
3609 if (!blob_entry_iter->second.size())
3610 transaction_->Remove(blob_entry_iter->first.Encode());
3611 else
3612 transaction_->Put(blob_entry_iter->first.Encode(),
3613 &blob_entry_iter->second);
3614 }
3615 // Creating the writer will start it going asynchronously.
3616 chained_blob_writer_ = new ChainedBlobWriter(database_id_, backing_store_,
3617 new_files_to_write, callback);
3618 }
3619
3620 bool IndexedDBBackingStore::Transaction::SortBlobsToRemove() {
3621 IndexedDBActiveBlobRegistry* registry =
3622 backing_store_->active_blob_registry();
3623 BlobJournalType::iterator iter;
3624 BlobJournalType primary_journal, secondary_journal;
3625 for (iter = blobs_to_remove_.begin(); iter != blobs_to_remove_.end();
3626 ++iter) {
3627 if (registry->MarkDeletedCheckIfUsed(iter->first, iter->second))
3628 secondary_journal.push_back(*iter);
3629 else
3630 primary_journal.push_back(*iter);
3631 }
3632 fprintf(stderr, "ERICU: Updating primary journal.\n");
3633 UpdatePrimaryJournalWithBlobList(transaction_.get(), primary_journal);
3634 fprintf(stderr, "ERICU: Updating secondary journal.\n");
3635 if (!MergeBlobsIntoSecondaryJournal(transaction_.get(), secondary_journal)) {
3636 fprintf(stderr, "ERICU: Updating secondary journal FAILED!\n");
3637 return false;
3638 }
3639 // To signal how many blobs need attention right now.
3640 blobs_to_remove_.swap(primary_journal);
3641 return true;
3642 }
3643
3644 bool IndexedDBBackingStore::Transaction::CommitPhaseOne(
3645 scoped_refptr<BlobWriteCallback> callback) {
3646 IDB_TRACE("IndexedDBBackingStore::Transaction::commit");
3647 DCHECK(transaction_);
3648 DCHECK(backing_store_->task_runner()->RunsTasksOnCurrentThread());
3649
3650 if (!backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode())) {
3651 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3652 transaction_ = NULL;
3653 return false;
3654 }
3655
3656 BlobEntryKeyValuePairVec new_blob_entries;
3657 WriteDescriptorVec new_files_to_write;
3658 // This commits the journal of blob files we're about to add, if any.
3659 if (!HandleBlobPreTransaction(&new_blob_entries, &new_files_to_write)) {
3660 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3661 transaction_ = NULL;
3662 return false;
3663 }
3664
3665 DCHECK(!new_files_to_write.size() ||
3666 KeyPrefix::IsValidDatabaseId(database_id_));
3667 fprintf(stderr, "ERICU: Calling CollectBlobFilesToRemove.\n");
3668 if (!CollectBlobFilesToRemove()) {
3669 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3670 transaction_ = NULL;
3671 return false;
3672 }
3673
3674 if (new_files_to_write.size()) {
3675 // This kicks off the writes of the new blobs, if any.
3676 // This call will zero out new_blob_entries and new_files_to_write.
3677 WriteNewBlobs(new_blob_entries, new_files_to_write, callback);
3678 // Remove the add journal, if any; once the blobs are written, and we
3679 // commit, this will do the cleanup.
3680 ClearBlobJournal(transaction_.get(), BlobJournalKey::Encode());
3681 } else {
3682 callback->didSucceed();
3683 }
3684
3685 return true;
3686 }
3687
3688 bool IndexedDBBackingStore::Transaction::CommitPhaseTwo() {
3689 fprintf(stderr, "ERICU: In CommitPhaseTwo; blobs_to_remove_.size() is %lu.\n",
3690 blobs_to_remove_.size());
3691 if (blobs_to_remove_.size())
3692 if (!SortBlobsToRemove()) {
3693 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3694 transaction_ = NULL;
3695 return false;
3696 }
3697
3698 fprintf(stderr, "ERICU: committing transaction_.\n");
2627 bool result = transaction_->Commit(); 3699 bool result = transaction_->Commit();
2628 transaction_ = NULL; 3700 transaction_ = NULL;
3701
2629 if (!result) 3702 if (!result)
2630 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD); 3703 INTERNAL_WRITE_ERROR(TRANSACTION_COMMIT_METHOD);
3704 else if (blobs_to_remove_.size())
3705 backing_store_->CleanUpBlobJournal(BlobJournalKey::Encode());
3706
2631 return result; 3707 return result;
2632 } 3708 }
2633 3709
2634 void IndexedDBBackingStore::Transaction::Rollback() { 3710 void IndexedDBBackingStore::Transaction::Rollback() {
2635 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 3711 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2636 DCHECK(transaction_.get()); 3712 DCHECK(transaction_.get());
3713 if (chained_blob_writer_)
3714 chained_blob_writer_->Abort();
2637 transaction_->Rollback(); 3715 transaction_->Rollback();
2638 transaction_ = NULL; 3716 transaction_ = NULL;
2639 } 3717 }
2640 3718
3719 // This is storing an info, even if empty, even if the previous key had no blob
3720 // info that we know of. It duplicates a bunch of information stored in the
3721 // leveldb transaction, but only w.r.t. the user keys altered--we don't keep the
3722 // changes to exists or index keys here.
3723 void IndexedDBBackingStore::Transaction::PutBlobInfo(
3724 int64 database_id,
3725 int64 object_store_id,
3726 const std::string&key,
3727 std::vector<IndexedDBBlobInfo>* blob_info) {
3728 fprintf(stderr, "ERICU: PutBlobInfo ; blob_info is %p.\n", blob_info);
3729 DCHECK_GT(key.size(), 0UL);
3730 if (database_id_ < 0)
3731 database_id_ = database_id;
3732 DCHECK_EQ(database_id_, database_id);
3733 AVLTreeNode* node = blob_info_tree_.Search(key);
3734 if (!node) {
3735 node = new AVLTreeNode;
3736 node->key.insert(node->key.end(), key.begin(), key.end());
3737 blob_info_tree_.Insert(node);
3738 node->object_store_id = object_store_id;
3739 }
3740 DCHECK_EQ(node->object_store_id, object_store_id);
3741 node->blob_info.clear();
3742 if (blob_info)
3743 node->blob_info.swap(*blob_info);
3744 }
3745
3746 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3747 const GURL& url, int64_t key)
3748 : is_file_(false),
3749 url_(url),
3750 key_(key)
3751 {
3752 }
3753
3754 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3755 const FilePath& file_path, int64_t key)
3756 : is_file_(true),
3757 file_path_(file_path),
3758 key_(key)
3759 {
3760 }
3761
2641 } // namespace content 3762 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698