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