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

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: Remove todo Created 6 years, 8 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 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
63 bool MakeIDBBlobDirectory(const FilePath& pathBase,
64 int64 database_id,
65 int64 key) {
66 FilePath path = GetBlobDirectoryNameForKey(pathBase, database_id, key);
67 return base::CreateDirectory(path);
68 }
69
41 static std::string ComputeOriginIdentifier(const GURL& origin_url) { 70 static std::string ComputeOriginIdentifier(const GURL& origin_url) {
42 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1"; 71 return webkit_database::GetIdentifierFromOrigin(origin_url) + "@1";
43 } 72 }
44 73
45 static base::FilePath ComputeFileName(const GURL& origin_url) { 74 static base::FilePath ComputeFileName(const GURL& origin_url) {
46 return base::FilePath() 75 return base::FilePath()
47 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url)) 76 .AppendASCII(webkit_database::GetIdentifierFromOrigin(origin_url))
48 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb")); 77 .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
49 } 78 }
50 79
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name) 463 virtual leveldb::Status DestroyLevelDB(const base::FilePath& file_name)
435 OVERRIDE { 464 OVERRIDE {
436 return LevelDBDatabase::Destroy(file_name); 465 return LevelDBDatabase::Destroy(file_name);
437 } 466 }
438 }; 467 };
439 468
440 IndexedDBBackingStore::IndexedDBBackingStore( 469 IndexedDBBackingStore::IndexedDBBackingStore(
441 IndexedDBFactory* indexed_db_factory, 470 IndexedDBFactory* indexed_db_factory,
442 const GURL& origin_url, 471 const GURL& origin_url,
443 const base::FilePath& blob_path, 472 const base::FilePath& blob_path,
473 net::URLRequestContext* request_context,
444 scoped_ptr<LevelDBDatabase> db, 474 scoped_ptr<LevelDBDatabase> db,
445 scoped_ptr<LevelDBComparator> comparator, 475 scoped_ptr<LevelDBComparator> comparator,
446 base::TaskRunner* task_runner) 476 base::TaskRunner* task_runner)
447 : indexed_db_factory_(indexed_db_factory), 477 : indexed_db_factory_(indexed_db_factory),
448 origin_url_(origin_url), 478 origin_url_(origin_url),
449 blob_path_(blob_path), 479 blob_path_(blob_path),
450 origin_identifier_(ComputeOriginIdentifier(origin_url)), 480 origin_identifier_(ComputeOriginIdentifier(origin_url)),
481 request_context_(request_context),
451 task_runner_(task_runner), 482 task_runner_(task_runner),
452 db_(db.Pass()), 483 db_(db.Pass()),
453 comparator_(comparator.Pass()), 484 comparator_(comparator.Pass()),
454 active_blob_registry_(this) {} 485 active_blob_registry_(this) {}
455 486
456 IndexedDBBackingStore::~IndexedDBBackingStore() { 487 IndexedDBBackingStore::~IndexedDBBackingStore() {
457 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) { 488 if (!blob_path_.empty() && !child_process_ids_granted_.empty()) {
458 ChildProcessSecurityPolicyImpl* policy = 489 ChildProcessSecurityPolicyImpl* policy =
459 ChildProcessSecurityPolicyImpl::GetInstance(); 490 ChildProcessSecurityPolicyImpl::GetInstance();
460 std::set<int>::const_iterator iter; 491 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, 530 INDEXED_DB_BACKING_STORE_OPEN_NO_RECOVERY,
500 INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION, 531 INDEXED_DB_BACKING_STORE_OPEN_FAILED_PRIOR_CORRUPTION,
501 INDEXED_DB_BACKING_STORE_OPEN_MAX, 532 INDEXED_DB_BACKING_STORE_OPEN_MAX,
502 }; 533 };
503 534
504 // static 535 // static
505 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 536 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
506 IndexedDBFactory* indexed_db_factory, 537 IndexedDBFactory* indexed_db_factory,
507 const GURL& origin_url, 538 const GURL& origin_url,
508 const base::FilePath& path_base, 539 const base::FilePath& path_base,
540 net::URLRequestContext* request_context,
509 blink::WebIDBDataLoss* data_loss, 541 blink::WebIDBDataLoss* data_loss,
510 std::string* data_loss_message, 542 std::string* data_loss_message,
511 bool* disk_full, 543 bool* disk_full,
512 base::TaskRunner* task_runner) { 544 base::TaskRunner* task_runner) {
513 *data_loss = blink::WebIDBDataLossNone; 545 *data_loss = blink::WebIDBDataLossNone;
514 DefaultLevelDBFactory leveldb_factory; 546 DefaultLevelDBFactory leveldb_factory;
515 return IndexedDBBackingStore::Open(indexed_db_factory, 547 return IndexedDBBackingStore::Open(indexed_db_factory,
516 origin_url, 548 origin_url,
517 path_base, 549 path_base,
550 request_context,
518 data_loss, 551 data_loss,
519 data_loss_message, 552 data_loss_message,
520 disk_full, 553 disk_full,
521 &leveldb_factory, 554 &leveldb_factory,
522 task_runner); 555 task_runner);
523 } 556 }
524 557
525 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) { 558 static std::string OriginToCustomHistogramSuffix(const GURL& origin_url) {
526 if (origin_url.host() == "docs.google.com") 559 if (origin_url.host() == "docs.google.com")
527 return ".Docs"; 560 return ".Docs";
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 return false; 681 return false;
649 int written = file.Write(0, output_js.c_str(), output_js.length()); 682 int written = file.Write(0, output_js.c_str(), output_js.length());
650 return size_t(written) == output_js.length(); 683 return size_t(written) == output_js.length();
651 } 684 }
652 685
653 // static 686 // static
654 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open( 687 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
655 IndexedDBFactory* indexed_db_factory, 688 IndexedDBFactory* indexed_db_factory,
656 const GURL& origin_url, 689 const GURL& origin_url,
657 const base::FilePath& path_base, 690 const base::FilePath& path_base,
691 net::URLRequestContext* request_context,
658 blink::WebIDBDataLoss* data_loss, 692 blink::WebIDBDataLoss* data_loss,
659 std::string* data_loss_message, 693 std::string* data_loss_message,
660 bool* is_disk_full, 694 bool* is_disk_full,
661 LevelDBFactory* leveldb_factory, 695 LevelDBFactory* leveldb_factory,
662 base::TaskRunner* task_runner) { 696 base::TaskRunner* task_runner) {
663 IDB_TRACE("IndexedDBBackingStore::Open"); 697 IDB_TRACE("IndexedDBBackingStore::Open");
664 DCHECK(!path_base.empty()); 698 DCHECK(!path_base.empty());
665 *data_loss = blink::WebIDBDataLossNone; 699 *data_loss = blink::WebIDBDataLossNone;
666 *data_loss_message = ""; 700 *data_loss_message = "";
667 *is_disk_full = false; 701 *is_disk_full = false;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 if (!db) { 807 if (!db) {
774 NOTREACHED(); 808 NOTREACHED();
775 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR, 809 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_FAILED_UNKNOWN_ERR,
776 origin_url); 810 origin_url);
777 return scoped_refptr<IndexedDBBackingStore>(); 811 return scoped_refptr<IndexedDBBackingStore>();
778 } 812 }
779 813
780 return Create(indexed_db_factory, 814 return Create(indexed_db_factory,
781 origin_url, 815 origin_url,
782 blob_path, 816 blob_path,
817 request_context,
783 db.Pass(), 818 db.Pass(),
784 comparator.Pass(), 819 comparator.Pass(),
785 task_runner); 820 task_runner);
786 } 821 }
787 822
788 // static 823 // static
789 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory( 824 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
790 const GURL& origin_url, 825 const GURL& origin_url,
791 base::TaskRunner* task_runner) { 826 base::TaskRunner* task_runner) {
792 DefaultLevelDBFactory leveldb_factory; 827 DefaultLevelDBFactory leveldb_factory;
(...skipping 15 matching lines...) Expand all
808 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed."; 843 LOG(ERROR) << "LevelDBDatabase::OpenInMemory failed.";
809 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED, 844 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_FAILED,
810 origin_url); 845 origin_url);
811 return scoped_refptr<IndexedDBBackingStore>(); 846 return scoped_refptr<IndexedDBBackingStore>();
812 } 847 }
813 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url); 848 HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
814 849
815 return Create(NULL /* indexed_db_factory */, 850 return Create(NULL /* indexed_db_factory */,
816 origin_url, 851 origin_url,
817 base::FilePath(), 852 base::FilePath(),
853 NULL /* request_context */,
818 db.Pass(), 854 db.Pass(),
819 comparator.Pass(), 855 comparator.Pass(),
820 task_runner); 856 task_runner);
821 } 857 }
822 858
823 // static 859 // static
824 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create( 860 scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Create(
825 IndexedDBFactory* indexed_db_factory, 861 IndexedDBFactory* indexed_db_factory,
826 const GURL& origin_url, 862 const GURL& origin_url,
827 const base::FilePath& blob_path, 863 const base::FilePath& blob_path,
864 net::URLRequestContext* request_context,
828 scoped_ptr<LevelDBDatabase> db, 865 scoped_ptr<LevelDBDatabase> db,
829 scoped_ptr<LevelDBComparator> comparator, 866 scoped_ptr<LevelDBComparator> comparator,
830 base::TaskRunner* task_runner) { 867 base::TaskRunner* task_runner) {
831 // TODO(jsbell): Handle comparator name changes. 868 // TODO(jsbell): Handle comparator name changes.
832
833 scoped_refptr<IndexedDBBackingStore> backing_store( 869 scoped_refptr<IndexedDBBackingStore> backing_store(
834 new IndexedDBBackingStore(indexed_db_factory, 870 new IndexedDBBackingStore(indexed_db_factory,
835 origin_url, 871 origin_url,
836 blob_path, 872 blob_path,
873 request_context,
837 db.Pass(), 874 db.Pass(),
838 comparator.Pass(), 875 comparator.Pass(),
839 task_runner)); 876 task_runner));
840 if (!SetUpMetadata(backing_store->db_.get(), 877 if (!SetUpMetadata(backing_store->db_.get(),
841 backing_store->origin_identifier_)) 878 backing_store->origin_identifier_))
842 return scoped_refptr<IndexedDBBackingStore>(); 879 return scoped_refptr<IndexedDBBackingStore>();
843 880
844 return backing_store; 881 return backing_store;
845 } 882 }
846 883
(...skipping 839 matching lines...) Expand 10 before | Expand all | Expand 10 after
1686 StringPiece slice(data); 1723 StringPiece slice(data);
1687 if (!DecodeVarInt(&slice, &version)) 1724 if (!DecodeVarInt(&slice, &version))
1688 return InternalInconsistencyStatus(); 1725 return InternalInconsistencyStatus();
1689 1726
1690 std::string encoded_key; 1727 std::string encoded_key;
1691 EncodeIDBKey(key, &encoded_key); 1728 EncodeIDBKey(key, &encoded_key);
1692 found_record_identifier->Reset(encoded_key, version); 1729 found_record_identifier->Reset(encoded_key, version);
1693 return s; 1730 return s;
1694 } 1731 }
1695 1732
1733 class IndexedDBBackingStore::Transaction::ChainedBlobWriterImpl
1734 : public IndexedDBBackingStore::Transaction::ChainedBlobWriter {
1735 public:
1736 typedef IndexedDBBackingStore::Transaction::WriteDescriptorVec
1737 WriteDescriptorVec;
1738 ChainedBlobWriterImpl(
1739 int64 database_id,
1740 IndexedDBBackingStore* backingStore,
1741 WriteDescriptorVec& blobs,
1742 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback)
1743 : waiting_for_callback_(false),
1744 database_id_(database_id),
1745 backing_store_(backingStore),
1746 callback_(callback),
1747 aborted_(false) {
1748 blobs_.swap(blobs);
1749 iter_ = blobs_.begin();
1750 WriteNextFile();
cmumford 2014/04/18 17:19:06 By writing the first file in the constructor do yo
ericu 2014/04/21 20:54:19 No, the delegate gets set in writeBlobToFileOnIOTh
1751 }
1752
1753 void set_delegate(scoped_ptr<FileWriterDelegate> delegate) {
1754 delegate_.reset(delegate.release());
1755 }
1756
1757 void ReportWriteCompletion(bool succeeded, int64 bytes_written) {
1758 // TODO(ericu): Check bytes_written against the blob's snapshot value.
1759 DCHECK(waiting_for_callback_);
1760 DCHECK(!succeeded || bytes_written >= 0);
1761 waiting_for_callback_ = false;
1762 content::BrowserThread::DeleteSoon(
1763 content::BrowserThread::IO, FROM_HERE, delegate_.release());
1764 if (aborted_) {
1765 self_ref_ = NULL;
1766 return;
1767 }
1768 if (succeeded)
1769 WriteNextFile();
1770 else
1771 callback_->DidFail();
1772 }
1773
1774 void Abort() {
1775 if (!waiting_for_callback_)
1776 return;
1777 self_ref_ = this;
1778 aborted_ = true;
1779 }
1780
1781 private:
1782 void WriteNextFile() {
1783 DCHECK(!waiting_for_callback_);
1784 DCHECK(!aborted_);
1785 if (iter_ == blobs_.end()) {
1786 DCHECK(!self_ref_);
1787 callback_->DidSucceed();
1788 return;
1789 } else {
1790 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
1791 callback_->DidFail();
1792 return;
1793 }
1794 waiting_for_callback_ = true;
1795 ++iter_;
1796 }
1797 }
1798
1799 bool waiting_for_callback_;
1800 scoped_refptr<ChainedBlobWriterImpl> self_ref_;
cmumford 2014/04/18 17:19:06 having a self reference seems like a scary way to
ericu 2014/04/21 20:54:19 It's safe for us to outlive the backing store. Th
1801 WriteDescriptorVec blobs_;
1802 WriteDescriptorVec::const_iterator iter_;
1803 int64 database_id_;
1804 IndexedDBBackingStore* backing_store_;
1805 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
1806 scoped_ptr<FileWriterDelegate> delegate_;
1807 bool aborted_;
1808 };
1809
1810 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
1811 public base::RefCounted<LocalWriteClosure> {
1812 public:
1813 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
1814 chained_blob_writer_,
1815 base::TaskRunner* task_runner)
1816 : chained_blob_writer_(chained_blob_writer_),
1817 task_runner_(task_runner),
1818 bytes_written_(-1) {}
1819
1820 void Run(base::File::Error rv,
1821 int64 bytes,
1822 FileWriterDelegate::WriteProgressStatus write_status) {
1823 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
1824 return; // We don't care about progress events.
1825 if (rv == base::File::FILE_OK) {
1826 DCHECK(bytes >= 0);
1827 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED);
1828 bytes_written_ = bytes;
1829 } else {
1830 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
1831 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
1832 }
1833 task_runner_->PostTask(
1834 FROM_HERE,
1835 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner,
1836 this,
1837 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
1838 }
1839
1840 void writeBlobToFileOnIOThread(const FilePath& file_path,
1841 const GURL& blob_url,
1842 net::URLRequestContext* request_context) {
1843 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1844 scoped_ptr<fileapi::FileStreamWriter> writer(
1845 fileapi::FileStreamWriter::CreateForLocalFile(
1846 task_runner_, file_path, 0,
1847 fileapi::FileStreamWriter::CREATE_NEW_FILE));
1848 scoped_ptr<FileWriterDelegate> delegate(
1849 new FileWriterDelegate(writer.Pass()));
1850
1851 DCHECK(blob_url.is_valid());
1852 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
1853 blob_url, net::DEFAULT_PRIORITY, delegate.get(), NULL));
1854
1855 delegate->Start(blob_request.Pass(),
1856 base::Bind(&LocalWriteClosure::Run, this));
1857 chained_blob_writer_->set_delegate(delegate.Pass());
1858 }
1859
1860 private:
1861 void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
1862 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1863 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
1864 }
1865
1866 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
1867 base::TaskRunner* task_runner_;
1868 int64 bytes_written_;
1869 };
1870
1871 bool IndexedDBBackingStore::WriteBlobFile(
1872 int64 database_id,
1873 const Transaction::WriteDescriptor& descriptor,
1874 Transaction::ChainedBlobWriter* chained_blob_writer) {
1875
1876 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
1877 return false;
cmumford 2014/04/18 17:19:06 If we can't create the dir (or copy the file below
ericu 2014/04/21 20:54:19 We return false, and WriteNextFile [our only calle
1878
1879 FilePath path = GetBlobFileName(database_id, descriptor.key());
1880
1881 if (descriptor.is_file()) {
1882 DCHECK(!descriptor.file_path().empty());
1883 if (!base::CopyFile(descriptor.file_path(), path))
1884 return false;
1885
1886 base::File::Info info;
1887 if (base::GetFileInfo(descriptor.file_path(), &info)) {
1888 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor
1889 // to include snapshot date and file size, and check both.
1890 if (!base::TouchFile(path, info.last_accessed, info.last_modified))
1891 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
1892 } else {
1893 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
1894 }
1895
1896 task_runner_->PostTask(
1897 FROM_HERE,
1898 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
1899 chained_blob_writer,
1900 true,
1901 info.size));
1902 } else {
1903 DCHECK(descriptor.url().is_valid());
1904 scoped_refptr<LocalWriteClosure> write_closure(
1905 new LocalWriteClosure(chained_blob_writer, task_runner_));
1906 content::BrowserThread::PostTask(
1907 content::BrowserThread::IO,
1908 FROM_HERE,
1909 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread,
1910 write_closure.get(),
1911 path,
1912 descriptor.url(),
1913 request_context_));
1914 }
1915 return true;
1916 }
1917
1918 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
1919 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) {
1920 FilePath path = GetBlobDirectoryNameForKey(blob_path_, database_id, key);
1921 path = path.AppendASCII(base::StringPrintf("%lx", key));
1922 return path;
1923 }
1924
1696 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, 1925 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
1697 const std::string& stop_key, 1926 const std::string& stop_key,
1698 int64 index_id, 1927 int64 index_id,
1699 unsigned char meta_data_type) { 1928 unsigned char meta_data_type) {
1700 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1929 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1701 return false; 1930 return false;
1702 1931
1703 StringPiece slice(it->Key()); 1932 StringPiece slice(it->Key());
1704 IndexMetaDataKey meta_data_key; 1933 IndexMetaDataKey meta_data_key;
1705 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 1934 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( 2031 (*indexes)[index_id] = IndexedDBIndexMetadata(
1803 index_name, index_id, key_path, index_unique, index_multi_entry); 2032 index_name, index_id, key_path, index_unique, index_multi_entry);
1804 } 2033 }
1805 2034
1806 if (!s.ok()) 2035 if (!s.ok())
1807 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES); 2036 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES);
1808 2037
1809 return s; 2038 return s;
1810 } 2039 }
1811 2040
2041 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
2042 FilePath fileName = GetBlobFileName(database_id, key);
2043 return base::DeleteFile(fileName, false);
2044 }
2045
2046 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
2047 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id);
2048 return base::DeleteFile(dirName, true);
2049 }
2050
1812 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( 2051 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
1813 LevelDBTransaction* transaction, 2052 LevelDBTransaction* transaction,
1814 int64 database_id, 2053 int64 database_id,
1815 int64 object_store_id, 2054 int64 object_store_id,
1816 int64 index_id) { 2055 int64 index_id) {
1817 int64 max_index_id = -1; 2056 int64 max_index_id = -1;
1818 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 2057 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1819 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 2058 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1820 bool found = false; 2059 bool found = false;
1821 leveldb::Status s = 2060 leveldb::Status s =
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 3178 leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
2940 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3179 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit");
2941 DCHECK(transaction_.get()); 3180 DCHECK(transaction_.get());
2942 leveldb::Status s = transaction_->Commit(); 3181 leveldb::Status s = transaction_->Commit();
2943 transaction_ = NULL; 3182 transaction_ = NULL;
2944 if (!s.ok()) 3183 if (!s.ok())
2945 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); 3184 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
2946 return s; 3185 return s;
2947 } 3186 }
2948 3187
3188
3189 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
3190 : public IndexedDBBackingStore::BlobWriteCallback {
3191 public:
3192 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
3193 scoped_refptr<BlobWriteCallback> callback)
3194 : transaction_(transaction), callback_(callback) {}
3195 virtual void DidSucceed() {
3196 callback_->DidSucceed();
3197 transaction_->chained_blob_writer_ = NULL;
3198 }
3199 virtual void DidFail() {
3200 callback_->DidFail();
3201 transaction_->chained_blob_writer_ = NULL;
3202 }
3203
3204 private:
3205 IndexedDBBackingStore::Transaction* transaction_;
3206 scoped_refptr<BlobWriteCallback> callback_;
3207 };
3208
3209 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
3210 BlobEntryKeyValuePairVec& new_blob_entries,
3211 WriteDescriptorVec& new_files_to_write,
3212 scoped_refptr<BlobWriteCallback> callback) {
3213 DCHECK_GT(new_files_to_write.size(), 0UL);
3214 DCHECK_GT(database_id_, 0);
3215 BlobEntryKeyValuePairVec::iterator blob_entry_iter;
3216 for (blob_entry_iter = new_blob_entries.begin();
3217 blob_entry_iter != new_blob_entries.end();
3218 ++blob_entry_iter) {
3219 // Add the new blob-table entry for each blob to the main transaction, or
3220 // remove any entry that may exist if there's no new one.
3221 if (!blob_entry_iter->second.size())
3222 transaction_->Remove(blob_entry_iter->first.Encode());
3223 else
3224 transaction_->Put(blob_entry_iter->first.Encode(),
3225 &blob_entry_iter->second);
3226 }
3227 // Creating the writer will start it going asynchronously.
3228 chained_blob_writer_ =
3229 new ChainedBlobWriterImpl(database_id_,
3230 backing_store_,
3231 new_files_to_write,
3232 new BlobWriteCallbackWrapper(this, callback));
3233 }
3234
2949 void IndexedDBBackingStore::Transaction::Rollback() { 3235 void IndexedDBBackingStore::Transaction::Rollback() {
2950 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 3236 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2951 DCHECK(transaction_.get()); 3237 DCHECK(transaction_.get());
3238 if (chained_blob_writer_) {
3239 chained_blob_writer_->Abort();
3240 chained_blob_writer_ = NULL;
3241 }
2952 transaction_->Rollback(); 3242 transaction_->Rollback();
2953 transaction_ = NULL; 3243 transaction_ = NULL;
2954 } 3244 }
2955 3245
2956 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord( 3246 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord(
2957 const std::string& key, int64 object_store_id) 3247 const std::string& key, int64 object_store_id)
2958 : key_(key), object_store_id_(object_store_id) { 3248 : key_(key), object_store_id_(object_store_id) {
2959 } 3249 }
2960 3250
2961 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() { 3251 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 blob_change_map_[key] = record; 3287 blob_change_map_[key] = record;
2998 } else { 3288 } else {
2999 record = it->second; 3289 record = it->second;
3000 } 3290 }
3001 DCHECK_EQ(record->object_store_id(), object_store_id); 3291 DCHECK_EQ(record->object_store_id(), object_store_id);
3002 record->SetBlobInfo(blob_info); 3292 record->SetBlobInfo(blob_info);
3003 record->SetHandles(handles); 3293 record->SetHandles(handles);
3004 DCHECK(!handles || !handles->size()); 3294 DCHECK(!handles || !handles->size());
3005 } 3295 }
3006 3296
3297 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3298 const GURL& url,
3299 int64_t key)
3300 : is_file_(false), url_(url), key_(key) {}
3301
3302 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3303 const FilePath& file_path,
3304 int64_t key)
3305 : is_file_(true), file_path_(file_path), key_(key) {}
3306
3007 } // namespace content 3307 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698