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

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: Cleaned branch 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/format_macros.h"
9 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
10 #include "base/json/json_writer.h" 11 #include "base/json/json_writer.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
13 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h" 16 #include "base/strings/utf_string_conversions.h"
15 #include "content/browser/child_process_security_policy_impl.h" 17 #include "content/browser/child_process_security_policy_impl.h"
16 #include "content/browser/indexed_db/indexed_db_blob_info.h" 18 #include "content/browser/indexed_db/indexed_db_blob_info.h"
17 #include "content/browser/indexed_db/indexed_db_database_error.h" 19 #include "content/browser/indexed_db/indexed_db_database_error.h"
18 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" 20 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
19 #include "content/browser/indexed_db/indexed_db_metadata.h" 21 #include "content/browser/indexed_db/indexed_db_metadata.h"
20 #include "content/browser/indexed_db/indexed_db_tracing.h" 22 #include "content/browser/indexed_db/indexed_db_tracing.h"
21 #include "content/browser/indexed_db/indexed_db_value.h" 23 #include "content/browser/indexed_db/indexed_db_value.h"
22 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h" 24 #include "content/browser/indexed_db/leveldb/leveldb_comparator.h"
23 #include "content/browser/indexed_db/leveldb/leveldb_database.h" 25 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
24 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h" 26 #include "content/browser/indexed_db/leveldb/leveldb_iterator.h"
25 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" 27 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
26 #include "content/common/indexed_db/indexed_db_key.h" 28 #include "content/common/indexed_db/indexed_db_key.h"
27 #include "content/common/indexed_db/indexed_db_key_path.h" 29 #include "content/common/indexed_db/indexed_db_key_path.h"
28 #include "content/common/indexed_db/indexed_db_key_range.h" 30 #include "content/common/indexed_db/indexed_db_key_range.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "net/url_request/url_request_context.h"
29 #include "third_party/WebKit/public/platform/WebIDBTypes.h" 33 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
30 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h" 34 #include "third_party/WebKit/public/web/WebSerializedScriptValueVersion.h"
31 #include "third_party/leveldatabase/env_chromium.h" 35 #include "third_party/leveldatabase/env_chromium.h"
32 #include "webkit/browser/blob/blob_data_handle.h" 36 #include "webkit/browser/blob/blob_data_handle.h"
37 #include "webkit/browser/fileapi/file_stream_writer.h"
38 #include "webkit/browser/fileapi/file_writer_delegate.h"
39 #include "webkit/browser/fileapi/local_file_stream_writer.h"
33 #include "webkit/common/database/database_identifier.h" 40 #include "webkit/common/database/database_identifier.h"
34 41
42 using base::FilePath;
35 using base::StringPiece; 43 using base::StringPiece;
44 using fileapi::FileWriterDelegate;
36 45
37 namespace content { 46 namespace content {
38 47
39 namespace { 48 namespace {
40 49
50 FilePath GetBlobDirectoryName(const FilePath& pathBase, int64 database_id) {
51 return pathBase.AppendASCII(base::StringPrintf("%" PRIx64, database_id));
52 }
53
54 FilePath GetBlobDirectoryNameForKey(const FilePath& pathBase,
55 int64 database_id,
56 int64 key) {
57 FilePath path = GetBlobDirectoryName(pathBase, database_id);
58 path = path.AppendASCII(base::StringPrintf(
59 "%02x", static_cast<int>(key & 0x000000000000ff00) >> 8));
60 return path;
61 }
62
63 FilePath GetBlobFileNameForKey(const FilePath& pathBase,
64 int64 database_id,
65 int64 key) {
66 FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
67 path = path.AppendASCII(base::StringPrintf("%" PRIx64, key));
68 return path;
69 }
70
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 virtual void set_delegate(scoped_ptr<FileWriterDelegate> delegate) OVERRIDE {
1762 delegate_.reset(delegate.release());
1763 }
1764
1765 virtual void ReportWriteCompletion(bool succeeded,
1766 int64 bytes_written) OVERRIDE {
1767 // TODO(ericu): Check bytes_written against the blob's snapshot value.
1768 DCHECK(waiting_for_callback_);
1769 DCHECK(!succeeded || bytes_written >= 0);
1770 waiting_for_callback_ = false;
1771 if (delegate_.get()) // Only present for Blob, not File.
1772 content::BrowserThread::DeleteSoon(
1773 content::BrowserThread::IO, FROM_HERE, delegate_.release());
1774 if (aborted_) {
1775 self_ref_ = NULL;
1776 return;
1777 }
1778 if (succeeded)
1779 WriteNextFile();
1780 else
1781 callback_->Run(false);
1782 }
1783
1784 virtual void Abort() OVERRIDE {
1785 if (!waiting_for_callback_)
1786 return;
1787 self_ref_ = this;
1788 aborted_ = true;
1789 }
1790
1791 private:
1792 virtual ~ChainedBlobWriterImpl() {}
1793
1794 void WriteNextFile() {
1795 DCHECK(!waiting_for_callback_);
1796 DCHECK(!aborted_);
1797 if (iter_ == blobs_.end()) {
1798 DCHECK(!self_ref_);
1799 callback_->Run(true);
1800 return;
1801 } else {
1802 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
1803 callback_->Run(false);
1804 return;
1805 }
1806 waiting_for_callback_ = true;
1807 ++iter_;
1808 }
1809 }
1810
1811 bool waiting_for_callback_;
1812 scoped_refptr<ChainedBlobWriterImpl> self_ref_;
1813 WriteDescriptorVec blobs_;
1814 WriteDescriptorVec::const_iterator iter_;
1815 int64 database_id_;
1816 IndexedDBBackingStore* backing_store_;
1817 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
1818 scoped_ptr<FileWriterDelegate> delegate_;
1819 bool aborted_;
1820 };
1821
1822 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
1823 public base::RefCounted<LocalWriteClosure> {
1824 public:
1825 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
1826 chained_blob_writer_,
1827 base::TaskRunner* task_runner)
1828 : chained_blob_writer_(chained_blob_writer_),
1829 task_runner_(task_runner),
1830 bytes_written_(-1) {}
1831
1832 void Run(base::File::Error rv,
1833 int64 bytes,
1834 FileWriterDelegate::WriteProgressStatus write_status) {
1835 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
1836 return; // We don't care about progress events.
1837 if (rv == base::File::FILE_OK) {
1838 DCHECK(bytes >= 0);
1839 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED);
1840 bytes_written_ = bytes;
1841 } else {
1842 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
1843 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
1844 }
1845 task_runner_->PostTask(
1846 FROM_HERE,
1847 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner,
1848 this,
1849 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
1850 }
1851
1852 void writeBlobToFileOnIOThread(const FilePath& file_path,
1853 const GURL& blob_url,
1854 net::URLRequestContext* request_context) {
1855 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1856 scoped_ptr<fileapi::FileStreamWriter> writer(
1857 fileapi::FileStreamWriter::CreateForLocalFile(
1858 task_runner_, file_path, 0,
1859 fileapi::FileStreamWriter::CREATE_NEW_FILE));
1860 scoped_ptr<FileWriterDelegate> delegate(
1861 new FileWriterDelegate(writer.Pass()));
1862
1863 DCHECK(blob_url.is_valid());
1864 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
1865 blob_url, net::DEFAULT_PRIORITY, delegate.get(), NULL));
1866
1867 delegate->Start(blob_request.Pass(),
1868 base::Bind(&LocalWriteClosure::Run, this));
1869 chained_blob_writer_->set_delegate(delegate.Pass());
1870 }
1871
1872 private:
1873 virtual ~LocalWriteClosure() {}
1874 friend class base::RefCounted<LocalWriteClosure>;
1875
1876 void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
1877 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1878 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
1879 }
1880
1881 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
1882 base::TaskRunner* task_runner_;
1883 int64 bytes_written_;
1884 };
1885
1886 bool IndexedDBBackingStore::WriteBlobFile(
1887 int64 database_id,
1888 const Transaction::WriteDescriptor& descriptor,
1889 Transaction::ChainedBlobWriter* chained_blob_writer) {
1890
1891 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
1892 return false;
1893
1894 FilePath path = GetBlobFileName(database_id, descriptor.key());
1895
1896 if (descriptor.is_file()) {
1897 DCHECK(!descriptor.file_path().empty());
1898 if (!base::CopyFile(descriptor.file_path(), path))
1899 return false;
1900
1901 base::File::Info info;
1902 if (base::GetFileInfo(descriptor.file_path(), &info)) {
1903 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor
1904 // to include snapshot date and file size, and check both.
1905 if (!base::TouchFile(path, info.last_accessed, info.last_modified)) {
1906 // TODO(ericu): Complain quietly; timestamp's probably not vital.
1907 }
1908 } else {
1909 // TODO(ericu): Complain quietly; timestamp's probably not vital.
1910 }
1911
1912 task_runner_->PostTask(
1913 FROM_HERE,
1914 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
1915 chained_blob_writer,
1916 true,
1917 info.size));
1918 } else {
1919 DCHECK(descriptor.url().is_valid());
1920 scoped_refptr<LocalWriteClosure> write_closure(
1921 new LocalWriteClosure(chained_blob_writer, task_runner_));
1922 content::BrowserThread::PostTask(
1923 content::BrowserThread::IO,
1924 FROM_HERE,
1925 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread,
1926 write_closure.get(),
1927 path,
1928 descriptor.url(),
1929 request_context_));
1930 }
1931 return true;
1932 }
1933
1934 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
1935 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) {
1936 return GetBlobFileNameForKey(blob_path_, database_id, key);
1937 }
1938
1696 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, 1939 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
1697 const std::string& stop_key, 1940 const std::string& stop_key,
1698 int64 index_id, 1941 int64 index_id,
1699 unsigned char meta_data_type) { 1942 unsigned char meta_data_type) {
1700 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1943 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1701 return false; 1944 return false;
1702 1945
1703 StringPiece slice(it->Key()); 1946 StringPiece slice(it->Key());
1704 IndexMetaDataKey meta_data_key; 1947 IndexMetaDataKey meta_data_key;
1705 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 1948 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( 2045 (*indexes)[index_id] = IndexedDBIndexMetadata(
1803 index_name, index_id, key_path, index_unique, index_multi_entry); 2046 index_name, index_id, key_path, index_unique, index_multi_entry);
1804 } 2047 }
1805 2048
1806 if (!s.ok()) 2049 if (!s.ok())
1807 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES); 2050 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES);
1808 2051
1809 return s; 2052 return s;
1810 } 2053 }
1811 2054
2055 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
2056 FilePath fileName = GetBlobFileName(database_id, key);
2057 return base::DeleteFile(fileName, false);
2058 }
2059
2060 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
2061 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id);
2062 return base::DeleteFile(dirName, true);
2063 }
2064
1812 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( 2065 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
1813 LevelDBTransaction* transaction, 2066 LevelDBTransaction* transaction,
1814 int64 database_id, 2067 int64 database_id,
1815 int64 object_store_id, 2068 int64 object_store_id,
1816 int64 index_id) { 2069 int64 index_id) {
1817 int64 max_index_id = -1; 2070 int64 max_index_id = -1;
1818 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 2071 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1819 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 2072 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1820 bool found = false; 2073 bool found = false;
1821 leveldb::Status s = 2074 leveldb::Status s =
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 3192 leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
2940 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3193 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit");
2941 DCHECK(transaction_.get()); 3194 DCHECK(transaction_.get());
2942 leveldb::Status s = transaction_->Commit(); 3195 leveldb::Status s = transaction_->Commit();
2943 transaction_ = NULL; 3196 transaction_ = NULL;
2944 if (!s.ok()) 3197 if (!s.ok())
2945 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); 3198 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
2946 return s; 3199 return s;
2947 } 3200 }
2948 3201
3202
3203 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
3204 : public IndexedDBBackingStore::BlobWriteCallback {
3205 public:
3206 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
3207 scoped_refptr<BlobWriteCallback> callback)
3208 : transaction_(transaction), callback_(callback) {}
3209 virtual void Run(bool succeeded) OVERRIDE {
3210 callback_->Run(succeeded);
3211 transaction_->chained_blob_writer_ = NULL;
3212 }
3213
3214 private:
3215 virtual ~BlobWriteCallbackWrapper() {}
3216 friend class base::RefCounted<IndexedDBBackingStore::BlobWriteCallback>;
3217
3218 IndexedDBBackingStore::Transaction* transaction_;
3219 scoped_refptr<BlobWriteCallback> callback_;
3220 };
3221
3222 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
3223 BlobEntryKeyValuePairVec& new_blob_entries,
3224 WriteDescriptorVec& new_files_to_write,
3225 scoped_refptr<BlobWriteCallback> callback) {
3226 DCHECK_GT(new_files_to_write.size(), 0UL);
3227 DCHECK_GT(database_id_, 0);
3228 BlobEntryKeyValuePairVec::iterator blob_entry_iter;
3229 for (blob_entry_iter = new_blob_entries.begin();
3230 blob_entry_iter != new_blob_entries.end();
3231 ++blob_entry_iter) {
3232 // Add the new blob-table entry for each blob to the main transaction, or
3233 // remove any entry that may exist if there's no new one.
3234 if (!blob_entry_iter->second.size())
3235 transaction_->Remove(blob_entry_iter->first.Encode());
3236 else
3237 transaction_->Put(blob_entry_iter->first.Encode(),
3238 &blob_entry_iter->second);
3239 }
3240 // Creating the writer will start it going asynchronously.
3241 chained_blob_writer_ =
3242 new ChainedBlobWriterImpl(database_id_,
3243 backing_store_,
3244 new_files_to_write,
3245 new BlobWriteCallbackWrapper(this, callback));
3246 }
3247
2949 void IndexedDBBackingStore::Transaction::Rollback() { 3248 void IndexedDBBackingStore::Transaction::Rollback() {
2950 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 3249 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2951 DCHECK(transaction_.get()); 3250 DCHECK(transaction_.get());
3251 if (chained_blob_writer_) {
3252 chained_blob_writer_->Abort();
3253 chained_blob_writer_ = NULL;
3254 }
2952 transaction_->Rollback(); 3255 transaction_->Rollback();
2953 transaction_ = NULL; 3256 transaction_ = NULL;
2954 } 3257 }
2955 3258
2956 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord( 3259 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord(
2957 const std::string& key, int64 object_store_id) 3260 const std::string& key, int64 object_store_id)
2958 : key_(key), object_store_id_(object_store_id) { 3261 : key_(key), object_store_id_(object_store_id) {
2959 } 3262 }
2960 3263
2961 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() { 3264 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 blob_change_map_[key] = record; 3300 blob_change_map_[key] = record;
2998 } else { 3301 } else {
2999 record = it->second; 3302 record = it->second;
3000 } 3303 }
3001 DCHECK_EQ(record->object_store_id(), object_store_id); 3304 DCHECK_EQ(record->object_store_id(), object_store_id);
3002 record->SetBlobInfo(blob_info); 3305 record->SetBlobInfo(blob_info);
3003 record->SetHandles(handles); 3306 record->SetHandles(handles);
3004 DCHECK(!handles || !handles->size()); 3307 DCHECK(!handles || !handles->size());
3005 } 3308 }
3006 3309
3310 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3311 const GURL& url,
3312 int64_t key)
3313 : is_file_(false), url_(url), key_(key) {}
3314
3315 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3316 const FilePath& file_path,
3317 int64_t key)
3318 : is_file_(true), file_path_(file_path), key_(key) {}
3319
3007 } // namespace content 3320 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698