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