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

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

Issue 240003011: Add blob-writing functionality [as yet un-called] to IDB's backend. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Factor out GetBlobFilenameForKey Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_backing_store.h" 5 #include "content/browser/indexed_db/indexed_db_backing_store.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/files/file_path.h" 8 #include "base/files/file_path.h"
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
15 #include "content/browser/child_process_security_policy_impl.h" 16 #include "content/browser/child_process_security_policy_impl.h"
16 #include "content/browser/indexed_db/indexed_db_blob_info.h" 17 #include "content/browser/indexed_db/indexed_db_blob_info.h"
17 #include "content/browser/indexed_db/indexed_db_database_error.h" 18 #include "content/browser/indexed_db/indexed_db_database_error.h"
18 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" 19 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
19 #include "content/browser/indexed_db/indexed_db_metadata.h" 20 #include "content/browser/indexed_db/indexed_db_metadata.h"
20 #include "content/browser/indexed_db/indexed_db_tracing.h" 21 #include "content/browser/indexed_db/indexed_db_tracing.h"
21 #include "content/browser/indexed_db/indexed_db_value.h" 22 #include "content/browser/indexed_db/indexed_db_value.h"
22 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" 23 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
23 #include "content/browser/indexed_db/leveldb/leveldb_database.h" 24 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
24 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" 25 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
25 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 26 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
26 #include "content/common/indexed_db/indexed_db_key.h" 27 #include "content/common/indexed_db/indexed_db_key.h"
27 #include "content/common/indexed_db/indexed_db_key_path.h" 28 #include "content/common/indexed_db/indexed_db_key_path.h"
28 #include "content/common/indexed_db/indexed_db_key_range.h" 29 #include "content/common/indexed_db/indexed_db_key_range.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "net/url_request/url_request_context.h"
29 #include "third_party/WebKit/public/platform/WebIDBTypes.h" 32 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
30 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" 33 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
31 #include "third_party/leveldatabase/env_chromium.h" 34 #include "third_party/leveldatabase/env_chromium.h"
32 #include "webkit/browser/blob/blob_data_handle.h" 35 #include "webkit/browser/blob/blob_data_handle.h"
36 #include "webkit/browser/fileapi/file_stream_writer.h"
37 #include "webkit/browser/fileapi/file_writer_delegate.h"
38 #include "webkit/browser/fileapi/local_file_stream_writer.h"
33 #include "webkit/common/database/database_identifier.h" 39 #include "webkit/common/database/database_identifier.h"
34 40
41 using base::FilePath;
35 using base::StringPiece; 42 using base::StringPiece;
43 using fileapi::FileWriterDelegate;
36 44
37 namespace content { 45 namespace content {
38 46
39 namespace { 47 namespace {
40 48
49 FilePath GetBlobDirectoryName(const FilePath& pathBase, int64 database_id) {
50 return pathBase.AppendASCII(base::StringPrintf("%lx", database_id));
51 }
52
53 FilePath GetBlobDirectoryNameForKey(const FilePath& pathBase,
54 int64 database_id,
55 int64 key) {
56 FilePath path = GetBlobDirectoryName(pathBase, database_id);
57 path = path.AppendASCII(base::StringPrintf(
58 "%02x", static_cast<int>(key & 0x000000000000ff00) >> 8));
59 return path;
60 }
61
62 FilePath GetBlobFileNameForKey(const FilePath& pathBase,
63 int64 database_id,
64 int64 key) {
65 FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
66 path = path.AppendASCII(base::StringPrintf("%lx", key));
67 return path;
68 }
69
70 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
71 bool MakeIDBBlobDirectory(const FilePath& pathBase,
72 int64 database_id,
73 int64 key) {
74 FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
75 return base::CreateDirectory(path);
76 }
77
41 static std::string ComputeOriginIdentifier(const GURL& origin_url) { 78 static std::string ComputeOriginIdentifier(const GURL& origin_url) {
42 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; 79 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
43 } 80 }
44 81
45 static base::FilePath ComputeFileName(const GURL& origin_url) { 82 static base::FilePath ComputeFileName(const GURL& origin_url) {
46 return base::FilePath() 83 return base::FilePath()
47 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) 84 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
48 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); 85 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
49 } 86 }
50 87
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) 471 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
435 OVERRIDE { 472 OVERRIDE {
436 return LevelDBDatabase::Destroy(file_name); 473 return LevelDBDatabase::Destroy(file_name);
437 } 474 }
438 }; 475 };
439 476
440 IndexedDBBackingStore::IndexedDBBackingStore( 477 IndexedDBBackingStore::IndexedDBBackingStore(
441 IndexedDBFactory* indexed_db_factory, 478 IndexedDBFactory* indexed_db_factory,
442 const GURL& origin_url, 479 const GURL& origin_url,
443 const base::FilePath& blob_path, 480 const base::FilePath& blob_path,
481 net::URLRequestContext* request_context,
444 scoped_ptr<LevelDBDatabase> db, 482 scoped_ptr<LevelDBDatabase> db,
445 scoped_ptr<LevelDBComparator> comparator, 483 scoped_ptr<LevelDBComparator> comparator,
446 base::TaskRunner* task_runner) 484 base::TaskRunner* task_runner)
447 : indexed_db_factory_(indexed_db_factory), 485 : indexed_db_factory_(indexed_db_factory),
448 origin_url_(origin_url), 486 origin_url_(origin_url),
449 blob_path_(blob_path), 487 blob_path_(blob_path),
450 origin_identifier_(ComputeOriginIdentifier(origin_url)), 488 origin_identifier_(ComputeOriginIdentifier(origin_url)),
489 request_context_(request_context),
451 task_runner_(task_runner), 490 task_runner_(task_runner),
452 db_(db.Pass()), 491 db_(db.Pass()),
453 comparator_(comparator.Pass()), 492 comparator_(comparator.Pass()),
454 active_blob_registry_(this) {} 493 active_blob_registry_(this) {}
455 494
456 IndexedDBBackingStore::~IndexedDBBackingStore() { 495 IndexedDBBackingStore::~IndexedDBBackingStore() {
457 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) { 496 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
458 ChildProcessSecurityPolicyImpl* policy = 497 ChildProcessSecurityPolicyImpl* policy =
459 ChildProcessSecurityPolicyImpl::GetInstance(); 498 ChildProcessSecurityPolicyImpl::GetInstance();
460 std::set<int>::const_iterator iter; 499 std::set<int>::const_iterator iter;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY, 538 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
500 INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION, 539 INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
501 INDEXED_DB_BACKING_STORE_OPEN_MAX, 540 INDEXED_DB_BACKING_STORE_OPEN_MAX,
502 }; 541 };
503 542
504 // static 543 // static
505 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 544 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
506 IndexedDBFactory* indexed_db_factory, 545 IndexedDBFactory* indexed_db_factory,
507 const GURL& origin_url, 546 const GURL& origin_url,
508 const base::FilePath& path_base, 547 const base::FilePath& path_base,
548 net::URLRequestContext* request_context,
509 blink::WebIDBDataLoss* data_loss, 549 blink::WebIDBDataLoss* data_loss,
510 std::string* data_loss_message, 550 std::string* data_loss_message,
511 bool* disk_full, 551 bool* disk_full,
512 base::TaskRunner* task_runner) { 552 base::TaskRunner* task_runner) {
513 *data_loss = blink::WebIDBDataLossNone; 553 *data_loss = blink::WebIDBDataLossNone;
514 DefaultLevelDBFactory leveldb_factory; 554 DefaultLevelDBFactory leveldb_factory;
515 return IndexedDBBackingStore::Open(indexed_db_factory, 555 return IndexedDBBackingStore::Open(indexed_db_factory,
516 origin_url, 556 origin_url,
517 path_base, 557 path_base,
558 request_context,
518 data_loss, 559 data_loss,
519 data_loss_message, 560 data_loss_message,
520 disk_full, 561 disk_full,
521 &leveldb_factory, 562 &leveldb_factory,
522 task_runner); 563 task_runner);
523 } 564 }
524 565
525 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) { 566 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
526 if (origin_url.host() == "docs.google.com") 567 if (origin_url.host() == "docs.google.com")
527 return ".Docs"; 568 return ".Docs";
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 return false; 689 return false;
649 int written = file.Write(0, output_js.c_str(), output_js.length()); 690 int written = file.Write(0, output_js.c_str(), output_js.length());
650 return size_t(written) == output_js.length(); 691 return size_t(written) == output_js.length();
651 } 692 }
652 693
653 // static 694 // static
654 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 695 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
655 IndexedDBFactory* indexed_db_factory, 696 IndexedDBFactory* indexed_db_factory,
656 const GURL& origin_url, 697 const GURL& origin_url,
657 const base::FilePath& path_base, 698 const base::FilePath& path_base,
699 net::URLRequestContext* request_context,
658 blink::WebIDBDataLoss* data_loss, 700 blink::WebIDBDataLoss* data_loss,
659 std::string* data_loss_message, 701 std::string* data_loss_message,
660 bool* is_disk_full, 702 bool* is_disk_full,
661 LevelDBFactory* leveldb_factory, 703 LevelDBFactory* leveldb_factory,
662 base::TaskRunner* task_runner) { 704 base::TaskRunner* task_runner) {
663 IDB_TRACE("IndexedDBBackingStore::Open"); 705 IDB_TRACE("IndexedDBBackingStore::Open");
664 DCHECK(!path_base.empty()); 706 DCHECK(!path_base.empty());
665 *data_loss = blink::WebIDBDataLossNone; 707 *data_loss = blink::WebIDBDataLossNone;
666 *data_loss_message = ""; 708 *data_loss_message = "";
667 *is_disk_full = false; 709 *is_disk_full = false;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 if (!db) { 815 if (!db) {
774 NOTREACHED(); 816 NOTREACHED();
775 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, 817 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
776 origin_url); 818 origin_url);
777 return scoped_refptr<IndexedDBBackingStore>(); 819 return scoped_refptr<IndexedDBBackingStore>();
778 } 820 }
779 821
780 return Create(indexed_db_factory, 822 return Create(indexed_db_factory,
781 origin_url, 823 origin_url,
782 blob_path, 824 blob_path,
825 request_context,
783 db.Pass(), 826 db.Pass(),
784 comparator.Pass(), 827 comparator.Pass(),
785 task_runner); 828 task_runner);
786 } 829 }
787 830
788 // static 831 // static
789 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 832 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
790 const GURL& origin_url, 833 const GURL& origin_url,
791 base::TaskRunner* task_runner) { 834 base::TaskRunner* task_runner) {
792 DefaultLevelDBFactory leveldb_factory; 835 DefaultLevelDBFactory leveldb_factory;
(...skipping 15 matching lines...) Expand all
808 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; 851 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
809 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, 852 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
810 origin_url); 853 origin_url);
811 return scoped_refptr<IndexedDBBackingStore>(); 854 return scoped_refptr<IndexedDBBackingStore>();
812 } 855 }
813 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); 856 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
814 857
815 return Create(NULL /* indexed_db_factory */, 858 return Create(NULL /* indexed_db_factory */,
816 origin_url, 859 origin_url,
817 base::FilePath(), 860 base::FilePath(),
861 NULL /* request_context */,
818 db.Pass(), 862 db.Pass(),
819 comparator.Pass(), 863 comparator.Pass(),
820 task_runner); 864 task_runner);
821 } 865 }
822 866
823 // static 867 // static
824 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( 868 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
825 IndexedDBFactory* indexed_db_factory, 869 IndexedDBFactory* indexed_db_factory,
826 const GURL& origin_url, 870 const GURL& origin_url,
827 const base::FilePath& blob_path, 871 const base::FilePath& blob_path,
872 net::URLRequestContext* request_context,
828 scoped_ptr<LevelDBDatabase> db, 873 scoped_ptr<LevelDBDatabase> db,
829 scoped_ptr<LevelDBComparator> comparator, 874 scoped_ptr<LevelDBComparator> comparator,
830 base::TaskRunner* task_runner) { 875 base::TaskRunner* task_runner) {
831 // TODO(jsbell): Handle comparator name changes. 876 // TODO(jsbell): Handle comparator name changes.
832
833 scoped_refptr<IndexedDBBackingStore> backing_store( 877 scoped_refptr<IndexedDBBackingStore> backing_store(
834 new IndexedDBBackingStore(indexed_db_factory, 878 new IndexedDBBackingStore(indexed_db_factory,
835 origin_url, 879 origin_url,
836 blob_path, 880 blob_path,
881 request_context,
837 db.Pass(), 882 db.Pass(),
838 comparator.Pass(), 883 comparator.Pass(),
839 task_runner)); 884 task_runner));
840 if (!SetUpMetadata(backing_store->db_.get(), 885 if (!SetUpMetadata(backing_store->db_.get(),
841 backing_store->origin_identifier_)) 886 backing_store->origin_identifier_))
842 return scoped_refptr<IndexedDBBackingStore>(); 887 return scoped_refptr<IndexedDBBackingStore>();
843 888
844 return backing_store; 889 return backing_store;
845 } 890 }
846 891
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 StringPiece slice(data); 1731 StringPiece slice(data);
1687 if (!DecodeVarInt(&slice, &version)) 1732 if (!DecodeVarInt(&slice, &version))
1688 return InternalInconsistencyStatus(); 1733 return InternalInconsistencyStatus();
1689 1734
1690 std::string encoded_key; 1735 std::string encoded_key;
1691 EncodeIDBKey(key, &encoded_key); 1736 EncodeIDBKey(key, &encoded_key);
1692 found_record_identifier->Reset(encoded_key, version); 1737 found_record_identifier->Reset(encoded_key, version);
1693 return s; 1738 return s;
1694 } 1739 }
1695 1740
1741 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
1742 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter {
1743 public:
1744 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
1745 WriteDescriptorVec;
1746 ChainedBlobWriterImpl(
1747 int64 database_id,
1748 IndexedDBBackingStore* backingStore,
1749 WriteDescriptorVec& blobs,
1750 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
1751 : waiting_for_callback_(false),
1752 database_id_(database_id),
1753 backing_store_(backingStore),
1754 callback_(callback),
1755 aborted_(false) {
1756 blobs_.swap(blobs);
1757 iter_ = blobs_.begin();
1758 WriteNextFile();
1759 }
1760
1761 void set_delegate(scoped_ptr<FileWriterDelegate> delegate) {
1762 delegate_.reset(delegate.release());
1763 }
1764
1765 void ReportWriteCompletion(bool succeeded, int64 bytes_written) {
1766 // TODO(ericu): Check bytes_written against the blob's snapshot value.
1767 DCHECK(waiting_for_callback_);
1768 DCHECK(!succeeded || bytes_written >= 0);
1769 waiting_for_callback_ = false;
1770 if (delegate_.get()) // Only present for Blob, not File.
1771 content::BrowserThread::DeleteSoon(
1772 content::BrowserThread::IO, FROM_HERE, delegate_.release());
1773 if (aborted_) {
1774 self_ref_ = NULL;
1775 return;
1776 }
1777 if (succeeded)
1778 WriteNextFile();
1779 else
1780 callback_->Run(false);
1781 }
1782
1783 void Abort() {
1784 if (!waiting_for_callback_)
1785 return;
1786 self_ref_ = this;
1787 aborted_ = true;
1788 }
1789
1790 private:
1791 void WriteNextFile() {
1792 DCHECK(!waiting_for_callback_);
1793 DCHECK(!aborted_);
1794 if (iter_ == blobs_.end()) {
1795 DCHECK(!self_ref_);
1796 callback_->Run(true);
1797 return;
1798 } else {
1799 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
1800 callback_->Run(false);
1801 return;
1802 }
1803 waiting_for_callback_ = true;
1804 ++iter_;
1805 }
1806 }
1807
1808 bool waiting_for_callback_;
1809 scoped_refptr<ChainedBlobWriterImpl> self_ref_;
1810 WriteDescriptorVec blobs_;
1811 WriteDescriptorVec::const_iterator iter_;
1812 int64 database_id_;
1813 IndexedDBBackingStore* backing_store_;
1814 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
1815 scoped_ptr<FileWriterDelegate> delegate_;
1816 bool aborted_;
1817 };
1818
1819 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
1820 public base::RefCounted<LocalWriteClosure> {
1821 public:
1822 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
1823 chained_blob_writer_,
1824 base::TaskRunner* task_runner)
1825 : chained_blob_writer_(chained_blob_writer_),
1826 task_runner_(task_runner),
1827 bytes_written_(-1) {}
1828
1829 void Run(base::File::Error rv,
1830 int64 bytes,
1831 FileWriterDelegate::WriteProgressStatus write_status) {
1832 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
1833 return; // We don't care about progress events.
1834 if (rv == base::File::FILE_OK) {
1835 DCHECK(bytes >= 0);
1836 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED);
1837 bytes_written_ = bytes;
1838 } else {
1839 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
1840 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
1841 }
1842 task_runner_->PostTask(
1843 FROM_HERE,
1844 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner,
1845 this,
1846 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
1847 }
1848
1849 void writeBlobToFileOnIOThread(const FilePath& file_path,
1850 const GURL& blob_url,
1851 net::URLRequestContext* request_context) {
1852 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1853 scoped_ptr<fileapi::FileStreamWriter> writer(
1854 fileapi::FileStreamWriter::CreateForLocalFile(
1855 task_runner_, file_path, 0,
1856 fileapi::FileStreamWriter::CREATE_NEW_FILE));
1857 scoped_ptr<FileWriterDelegate> delegate(
1858 new FileWriterDelegate(writer.Pass()));
1859
1860 DCHECK(blob_url.is_valid());
1861 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
1862 blob_url, net::DEFAULT_PRIORITY, delegate.get(), NULL));
1863
1864 delegate->Start(blob_request.Pass(),
1865 base::Bind(&LocalWriteClosure::Run, this));
1866 chained_blob_writer_->set_delegate(delegate.Pass());
1867 }
1868
1869 private:
1870 void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
1871 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1872 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
1873 }
1874
1875 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
1876 base::TaskRunner* task_runner_;
1877 int64 bytes_written_;
1878 };
1879
1880 bool IndexedDBBackingStore::WriteBlobFile(
1881 int64 database_id,
1882 const Transaction::WriteDescriptor& descriptor,
1883 Transaction::ChainedBlobWriter* chained_blob_writer) {
1884
1885 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
1886 return false;
1887
1888 FilePath path = GetBlobFileName(database_id, descriptor.key());
1889
1890 if (descriptor.is_file()) {
1891 DCHECK(!descriptor.file_path().empty());
1892 if (!base::CopyFile(descriptor.file_path(), path))
1893 return false;
1894
1895 base::File::Info info;
1896 if (base::GetFileInfo(descriptor.file_path(), &info)) {
1897 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor
1898 // to include snapshot date and file size, and check both.
1899 if (!base::TouchFile(path, info.last_accessed, info.last_modified))
1900 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
1901 } else {
1902 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
1903 }
1904
1905 task_runner_->PostTask(
1906 FROM_HERE,
1907 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
1908 chained_blob_writer,
1909 true,
1910 info.size));
1911 } else {
1912 DCHECK(descriptor.url().is_valid());
1913 scoped_refptr<LocalWriteClosure> write_closure(
1914 new LocalWriteClosure(chained_blob_writer, task_runner_));
1915 content::BrowserThread::PostTask(
1916 content::BrowserThread::IO,
1917 FROM_HERE,
1918 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread,
1919 write_closure.get(),
1920 path,
1921 descriptor.url(),
1922 request_context_));
1923 }
1924 return true;
1925 }
1926
1927 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
jsbell 2014/04/28 18:04:20 Nit: This comment could be moved/removed now.
1928 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) {
1929 return GetBlobFileNameForKey(blob_path_, database_id, key);
1930 }
1931
1696 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, 1932 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
1697 const std::string& stop_key, 1933 const std::string& stop_key,
1698 int64 index_id, 1934 int64 index_id,
1699 unsigned char meta_data_type) { 1935 unsigned char meta_data_type) {
1700 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1936 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1701 return false; 1937 return false;
1702 1938
1703 StringPiece slice(it->Key()); 1939 StringPiece slice(it->Key());
1704 IndexMetaDataKey meta_data_key; 1940 IndexMetaDataKey meta_data_key;
1705 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 1941 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1802 (*indexes)[index_id] = IndexedDBIndexMetadata( 2038 (*indexes)[index_id] = IndexedDBIndexMetadata(
1803 index_name, index_id, key_path, index_unique, index_multi_entry); 2039 index_name, index_id, key_path, index_unique, index_multi_entry);
1804 } 2040 }
1805 2041
1806 if (!s.ok()) 2042 if (!s.ok())
1807 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES); 2043 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES);
1808 2044
1809 return s; 2045 return s;
1810 } 2046 }
1811 2047
2048 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
2049 FilePath fileName = GetBlobFileName(database_id, key);
2050 return base::DeleteFile(fileName, false);
2051 }
2052
2053 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
2054 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id);
2055 return base::DeleteFile(dirName, true);
2056 }
2057
1812 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( 2058 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
1813 LevelDBTransaction* transaction, 2059 LevelDBTransaction* transaction,
1814 int64 database_id, 2060 int64 database_id,
1815 int64 object_store_id, 2061 int64 object_store_id,
1816 int64 index_id) { 2062 int64 index_id) {
1817 int64 max_index_id = -1; 2063 int64 max_index_id = -1;
1818 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 2064 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1819 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 2065 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1820 bool found = false; 2066 bool found = false;
1821 leveldb::Status s = 2067 leveldb::Status s =
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 3185 leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
2940 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3186 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit");
2941 DCHECK(transaction_.get()); 3187 DCHECK(transaction_.get());
2942 leveldb::Status s = transaction_->Commit(); 3188 leveldb::Status s = transaction_->Commit();
2943 transaction_ = NULL; 3189 transaction_ = NULL;
2944 if (!s.ok()) 3190 if (!s.ok())
2945 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); 3191 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
2946 return s; 3192 return s;
2947 } 3193 }
2948 3194
3195
3196 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
3197 : public IndexedDBBackingStore::BlobWriteCallback {
3198 public:
3199 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
3200 scoped_refptr<BlobWriteCallback> callback)
3201 : transaction_(transaction), callback_(callback) {}
3202 virtual void Run(bool succeeded) {
3203 callback_->Run(succeeded);
3204 transaction_->chained_blob_writer_ = NULL;
3205 }
3206
3207 private:
3208 IndexedDBBackingStore::Transaction* transaction_;
3209 scoped_refptr<BlobWriteCallback> callback_;
3210 };
3211
3212 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
3213 BlobEntryKeyValuePairVec& new_blob_entries,
3214 WriteDescriptorVec& new_files_to_write,
3215 scoped_refptr<BlobWriteCallback> callback) {
3216 DCHECK_GT(new_files_to_write.size(), 0UL);
3217 DCHECK_GT(database_id_, 0);
3218 BlobEntryKeyValuePairVec::iterator blob_entry_iter;
3219 for (blob_entry_iter = new_blob_entries.begin();
3220 blob_entry_iter != new_blob_entries.end();
3221 ++blob_entry_iter) {
3222 // Add the new blob-table entry for each blob to the main transaction, or
3223 // remove any entry that may exist if there's no new one.
3224 if (!blob_entry_iter->second.size())
3225 transaction_->Remove(blob_entry_iter->first.Encode());
3226 else
3227 transaction_->Put(blob_entry_iter->first.Encode(),
3228 &blob_entry_iter->second);
3229 }
3230 // Creating the writer will start it going asynchronously.
3231 chained_blob_writer_ =
3232 new ChainedBlobWriterImpl(database_id_,
3233 backing_store_,
3234 new_files_to_write,
3235 new BlobWriteCallbackWrapper(this, callback));
3236 }
3237
2949 void IndexedDBBackingStore::Transaction::Rollback() { 3238 void IndexedDBBackingStore::Transaction::Rollback() {
2950 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 3239 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2951 DCHECK(transaction_.get()); 3240 DCHECK(transaction_.get());
3241 if (chained_blob_writer_) {
3242 chained_blob_writer_->Abort();
3243 chained_blob_writer_ = NULL;
3244 }
2952 transaction_->Rollback(); 3245 transaction_->Rollback();
2953 transaction_ = NULL; 3246 transaction_ = NULL;
2954 } 3247 }
2955 3248
2956 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord( 3249 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord(
2957 const std::string& key, int64 object_store_id) 3250 const std::string& key, int64 object_store_id)
2958 : key_(key), object_store_id_(object_store_id) { 3251 : key_(key), object_store_id_(object_store_id) {
2959 } 3252 }
2960 3253
2961 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() { 3254 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 blob_change_map_[key] = record; 3290 blob_change_map_[key] = record;
2998 } else { 3291 } else {
2999 record = it->second; 3292 record = it->second;
3000 } 3293 }
3001 DCHECK_EQ(record->object_store_id(), object_store_id); 3294 DCHECK_EQ(record->object_store_id(), object_store_id);
3002 record->SetBlobInfo(blob_info); 3295 record->SetBlobInfo(blob_info);
3003 record->SetHandles(handles); 3296 record->SetHandles(handles);
3004 DCHECK(!handles || !handles->size()); 3297 DCHECK(!handles || !handles->size());
3005 } 3298 }
3006 3299
3300 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3301 const GURL& url,
3302 int64_t key)
3303 : is_file_(false), url_(url), key_(key) {}
3304
3305 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3306 const FilePath& file_path,
3307 int64_t key)
3308 : is_file_(true), file_path_(file_path), key_(key) {}
3309
3007 } // namespace content 3310 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698