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

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: Added a 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();
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 if (delegate_.get()) // Only present for Blob, not File.
1763 content::BrowserThread::DeleteSoon(
1764 content::BrowserThread::IO, FROM_HERE, delegate_.release());
1765 if (aborted_) {
1766 self_ref_ = NULL;
1767 return;
1768 }
1769 if (succeeded)
1770 WriteNextFile();
1771 else
1772 callback_->Run(false);
1773 }
1774
1775 void Abort() {
1776 if (!waiting_for_callback_)
1777 return;
1778 self_ref_ = this;
1779 aborted_ = true;
1780 }
1781
1782 private:
1783 void WriteNextFile() {
1784 DCHECK(!waiting_for_callback_);
1785 DCHECK(!aborted_);
1786 if (iter_ == blobs_.end()) {
1787 DCHECK(!self_ref_);
1788 callback_->Run(true);
1789 return;
1790 } else {
1791 if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) {
1792 callback_->Run(false);
1793 return;
1794 }
1795 waiting_for_callback_ = true;
1796 ++iter_;
1797 }
1798 }
1799
1800 bool waiting_for_callback_;
1801 scoped_refptr<ChainedBlobWriterImpl> self_ref_;
1802 WriteDescriptorVec blobs_;
1803 WriteDescriptorVec::const_iterator iter_;
1804 int64 database_id_;
1805 IndexedDBBackingStore* backing_store_;
1806 scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_;
1807 scoped_ptr<FileWriterDelegate> delegate_;
1808 bool aborted_;
1809 };
1810
1811 class LocalWriteClosure : public FileWriterDelegate::DelegateWriteCallback,
1812 public base::RefCounted<LocalWriteClosure> {
1813 public:
1814 LocalWriteClosure(IndexedDBBackingStore::Transaction::ChainedBlobWriter*
1815 chained_blob_writer_,
1816 base::TaskRunner* task_runner)
1817 : chained_blob_writer_(chained_blob_writer_),
1818 task_runner_(task_runner),
1819 bytes_written_(-1) {}
1820
1821 void Run(base::File::Error rv,
1822 int64 bytes,
1823 FileWriterDelegate::WriteProgressStatus write_status) {
1824 if (write_status == FileWriterDelegate::SUCCESS_IO_PENDING)
1825 return; // We don't care about progress events.
1826 if (rv == base::File::FILE_OK) {
1827 DCHECK(bytes >= 0);
1828 DCHECK(write_status == FileWriterDelegate::SUCCESS_COMPLETED);
1829 bytes_written_ = bytes;
1830 } else {
1831 DCHECK(write_status == FileWriterDelegate::ERROR_WRITE_STARTED ||
1832 write_status == FileWriterDelegate::ERROR_WRITE_NOT_STARTED);
1833 }
1834 task_runner_->PostTask(
1835 FROM_HERE,
1836 base::Bind(&LocalWriteClosure::callBlobCallbackOnIDBTaskRunner,
1837 this,
1838 write_status == FileWriterDelegate::SUCCESS_COMPLETED));
1839 }
1840
1841 void writeBlobToFileOnIOThread(const FilePath& file_path,
1842 const GURL& blob_url,
1843 net::URLRequestContext* request_context) {
1844 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
1845 scoped_ptr<fileapi::FileStreamWriter> writer(
1846 fileapi::FileStreamWriter::CreateForLocalFile(
1847 task_runner_, file_path, 0,
1848 fileapi::FileStreamWriter::CREATE_NEW_FILE));
1849 scoped_ptr<FileWriterDelegate> delegate(
1850 new FileWriterDelegate(writer.Pass()));
1851
1852 DCHECK(blob_url.is_valid());
1853 scoped_ptr<net::URLRequest> blob_request(request_context->CreateRequest(
1854 blob_url, net::DEFAULT_PRIORITY, delegate.get(), NULL));
1855
1856 delegate->Start(blob_request.Pass(),
1857 base::Bind(&LocalWriteClosure::Run, this));
1858 chained_blob_writer_->set_delegate(delegate.Pass());
1859 }
1860
1861 private:
1862 void callBlobCallbackOnIDBTaskRunner(bool succeeded) {
1863 DCHECK(task_runner_->RunsTasksOnCurrentThread());
1864 chained_blob_writer_->ReportWriteCompletion(succeeded, bytes_written_);
1865 }
1866
1867 IndexedDBBackingStore::Transaction::ChainedBlobWriter* chained_blob_writer_;
1868 base::TaskRunner* task_runner_;
1869 int64 bytes_written_;
1870 };
1871
1872 bool IndexedDBBackingStore::WriteBlobFile(
1873 int64 database_id,
1874 const Transaction::WriteDescriptor& descriptor,
1875 Transaction::ChainedBlobWriter* chained_blob_writer) {
1876
1877 if (!MakeIDBBlobDirectory(blob_path_, database_id, descriptor.key()))
1878 return false;
1879
1880 FilePath path = GetBlobFileName(database_id, descriptor.key());
1881
1882 if (descriptor.is_file()) {
1883 DCHECK(!descriptor.file_path().empty());
1884 if (!base::CopyFile(descriptor.file_path(), path))
1885 return false;
1886
1887 base::File::Info info;
1888 if (base::GetFileInfo(descriptor.file_path(), &info)) {
1889 // TODO(ericu): Validate the snapshot date here. Expand WriteDescriptor
1890 // to include snapshot date and file size, and check both.
1891 if (!base::TouchFile(path, info.last_accessed, info.last_modified))
1892 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
1893 } else {
1894 ; // TODO(ericu): Complain quietly; timestamp's probably not vital.
1895 }
1896
1897 task_runner_->PostTask(
1898 FROM_HERE,
1899 base::Bind(&Transaction::ChainedBlobWriter::ReportWriteCompletion,
1900 chained_blob_writer,
1901 true,
1902 info.size));
1903 } else {
1904 DCHECK(descriptor.url().is_valid());
1905 scoped_refptr<LocalWriteClosure> write_closure(
1906 new LocalWriteClosure(chained_blob_writer, task_runner_));
1907 content::BrowserThread::PostTask(
1908 content::BrowserThread::IO,
1909 FROM_HERE,
1910 base::Bind(&LocalWriteClosure::writeBlobToFileOnIOThread,
1911 write_closure.get(),
1912 path,
1913 descriptor.url(),
1914 request_context_));
1915 }
1916 return true;
1917 }
1918
1919 // This assumes a file path of dbId/second-to-LSB-of-counter/counter.
jsbell 2014/04/24 00:16:13 Just to keep assumptions together at the top of th
ericu 2014/04/28 17:49:04 Done.
1920 FilePath IndexedDBBackingStore::GetBlobFileName(int64 database_id, int64 key) {
1921 FilePath path = GetBlobDirectoryNameForKey(blob_path_, database_id, key);
1922 path = path.AppendASCII(base::StringPrintf("%lx", key));
1923 return path;
1924 }
1925
1696 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it, 1926 static bool CheckIndexAndMetaDataKey(const LevelDBIterator* it,
1697 const std::string& stop_key, 1927 const std::string& stop_key,
1698 int64 index_id, 1928 int64 index_id,
1699 unsigned char meta_data_type) { 1929 unsigned char meta_data_type) {
1700 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0) 1930 if (!it->IsValid() || CompareKeys(it->Key(), stop_key) >= 0)
1701 return false; 1931 return false;
1702 1932
1703 StringPiece slice(it->Key()); 1933 StringPiece slice(it->Key());
1704 IndexMetaDataKey meta_data_key; 1934 IndexMetaDataKey meta_data_key;
1705 bool ok = IndexMetaDataKey::Decode(&slice, &meta_data_key); 1935 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( 2032 (*indexes)[index_id] = IndexedDBIndexMetadata(
1803 index_name, index_id, key_path, index_unique, index_multi_entry); 2033 index_name, index_id, key_path, index_unique, index_multi_entry);
1804 } 2034 }
1805 2035
1806 if (!s.ok()) 2036 if (!s.ok())
1807 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES); 2037 INTERNAL_READ_ERROR_UNTESTED(GET_INDEXES);
1808 2038
1809 return s; 2039 return s;
1810 } 2040 }
1811 2041
2042 bool IndexedDBBackingStore::RemoveBlobFile(int64 database_id, int64 key) {
2043 FilePath fileName = GetBlobFileName(database_id, key);
2044 return base::DeleteFile(fileName, false);
2045 }
2046
2047 bool IndexedDBBackingStore::RemoveBlobDirectory(int64 database_id) {
2048 FilePath dirName = GetBlobDirectoryName(blob_path_, database_id);
2049 return base::DeleteFile(dirName, true);
2050 }
2051
1812 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId( 2052 WARN_UNUSED_RESULT static leveldb::Status SetMaxIndexId(
1813 LevelDBTransaction* transaction, 2053 LevelDBTransaction* transaction,
1814 int64 database_id, 2054 int64 database_id,
1815 int64 object_store_id, 2055 int64 object_store_id,
1816 int64 index_id) { 2056 int64 index_id) {
1817 int64 max_index_id = -1; 2057 int64 max_index_id = -1;
1818 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode( 2058 const std::string max_index_id_key = ObjectStoreMetaDataKey::Encode(
1819 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID); 2059 database_id, object_store_id, ObjectStoreMetaDataKey::MAX_INDEX_ID);
1820 bool found = false; 2060 bool found = false;
1821 leveldb::Status s = 2061 leveldb::Status s =
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 leveldb::Status IndexedDBBackingStore::Transaction::Commit() { 3179 leveldb::Status IndexedDBBackingStore::Transaction::Commit() {
2940 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit"); 3180 IDB_TRACE("IndexedDBBackingStore::Transaction::Commit");
2941 DCHECK(transaction_.get()); 3181 DCHECK(transaction_.get());
2942 leveldb::Status s = transaction_->Commit(); 3182 leveldb::Status s = transaction_->Commit();
2943 transaction_ = NULL; 3183 transaction_ = NULL;
2944 if (!s.ok()) 3184 if (!s.ok())
2945 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD); 3185 INTERNAL_WRITE_ERROR_UNTESTED(TRANSACTION_COMMIT_METHOD);
2946 return s; 3186 return s;
2947 } 3187 }
2948 3188
3189
3190 class IndexedDBBackingStore::Transaction::BlobWriteCallbackWrapper
3191 : public IndexedDBBackingStore::BlobWriteCallback {
3192 public:
3193 BlobWriteCallbackWrapper(IndexedDBBackingStore::Transaction* transaction,
3194 scoped_refptr<BlobWriteCallback> callback)
3195 : transaction_(transaction), callback_(callback) {}
3196 virtual void Run(bool succeeded) {
3197 callback_->Run(succeeded);
3198 transaction_->chained_blob_writer_ = NULL;
3199 }
3200
3201 private:
3202 IndexedDBBackingStore::Transaction* transaction_;
3203 scoped_refptr<BlobWriteCallback> callback_;
3204 };
3205
3206 void IndexedDBBackingStore::Transaction::WriteNewBlobs(
3207 BlobEntryKeyValuePairVec& new_blob_entries,
3208 WriteDescriptorVec& new_files_to_write,
3209 scoped_refptr<BlobWriteCallback> callback) {
3210 DCHECK_GT(new_files_to_write.size(), 0UL);
3211 DCHECK_GT(database_id_, 0);
3212 BlobEntryKeyValuePairVec::iterator blob_entry_iter;
3213 for (blob_entry_iter = new_blob_entries.begin();
3214 blob_entry_iter != new_blob_entries.end();
3215 ++blob_entry_iter) {
3216 // Add the new blob-table entry for each blob to the main transaction, or
3217 // remove any entry that may exist if there's no new one.
3218 if (!blob_entry_iter->second.size())
3219 transaction_->Remove(blob_entry_iter->first.Encode());
3220 else
3221 transaction_->Put(blob_entry_iter->first.Encode(),
3222 &blob_entry_iter->second);
3223 }
3224 // Creating the writer will start it going asynchronously.
3225 chained_blob_writer_ =
3226 new ChainedBlobWriterImpl(database_id_,
3227 backing_store_,
3228 new_files_to_write,
3229 new BlobWriteCallbackWrapper(this, callback));
3230 }
3231
2949 void IndexedDBBackingStore::Transaction::Rollback() { 3232 void IndexedDBBackingStore::Transaction::Rollback() {
2950 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback"); 3233 IDB_TRACE("IndexedDBBackingStore::Transaction::Rollback");
2951 DCHECK(transaction_.get()); 3234 DCHECK(transaction_.get());
3235 if (chained_blob_writer_) {
3236 chained_blob_writer_->Abort();
3237 chained_blob_writer_ = NULL;
3238 }
2952 transaction_->Rollback(); 3239 transaction_->Rollback();
2953 transaction_ = NULL; 3240 transaction_ = NULL;
2954 } 3241 }
2955 3242
2956 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord( 3243 IndexedDBBackingStore::Transaction::BlobChangeRecord::BlobChangeRecord(
2957 const std::string& key, int64 object_store_id) 3244 const std::string& key, int64 object_store_id)
2958 : key_(key), object_store_id_(object_store_id) { 3245 : key_(key), object_store_id_(object_store_id) {
2959 } 3246 }
2960 3247
2961 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() { 3248 IndexedDBBackingStore::Transaction::BlobChangeRecord::~BlobChangeRecord() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2997 blob_change_map_[key] = record; 3284 blob_change_map_[key] = record;
2998 } else { 3285 } else {
2999 record = it->second; 3286 record = it->second;
3000 } 3287 }
3001 DCHECK_EQ(record->object_store_id(), object_store_id); 3288 DCHECK_EQ(record->object_store_id(), object_store_id);
3002 record->SetBlobInfo(blob_info); 3289 record->SetBlobInfo(blob_info);
3003 record->SetHandles(handles); 3290 record->SetHandles(handles);
3004 DCHECK(!handles || !handles->size()); 3291 DCHECK(!handles || !handles->size());
3005 } 3292 }
3006 3293
3294 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3295 const GURL& url,
3296 int64_t key)
3297 : is_file_(false), url_(url), key_(key) {}
3298
3299 IndexedDBBackingStore::Transaction::WriteDescriptor::WriteDescriptor(
3300 const FilePath& file_path,
3301 int64_t key)
3302 : is_file_(true), file_path_(file_path), key_(key) {}
3303
3007 } // namespace content 3304 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698