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

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

Issue 2084053004: IndexedDB: Defer delete calls when there is a running upgrade (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased, made delete lists contain unique_ptrs Created 4 years, 5 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
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_database.h" 5 #include "content/browser/indexed_db/indexed_db_database.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include <limits> 9 #include <limits>
10 #include <memory> 10 #include <memory>
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 &metadata_.object_stores); 226 &metadata_.object_stores);
227 227
228 return backing_store_->CreateIDBDatabaseMetaData( 228 return backing_store_->CreateIDBDatabaseMetaData(
229 metadata_.name, metadata_.version, &metadata_.id); 229 metadata_.name, metadata_.version, &metadata_.id);
230 } 230 }
231 231
232 IndexedDBDatabase::~IndexedDBDatabase() { 232 IndexedDBDatabase::~IndexedDBDatabase() {
233 DCHECK(transactions_.empty()); 233 DCHECK(transactions_.empty());
234 DCHECK(pending_open_calls_.empty()); 234 DCHECK(pending_open_calls_.empty());
235 DCHECK(pending_delete_calls_.empty()); 235 DCHECK(pending_delete_calls_.empty());
236 DCHECK(blocked_delete_calls_.empty());
236 } 237 }
237 238
238 size_t IndexedDBDatabase::GetMaxMessageSizeInBytes() const { 239 size_t IndexedDBDatabase::GetMaxMessageSizeInBytes() const {
239 return kMaxIDBMessageSizeInBytes; 240 return kMaxIDBMessageSizeInBytes;
240 } 241 }
241 242
242 std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection( 243 std::unique_ptr<IndexedDBConnection> IndexedDBDatabase::CreateConnection(
243 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks, 244 scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
244 int child_process_id) { 245 int child_process_id) {
245 std::unique_ptr<IndexedDBConnection> connection( 246 std::unique_ptr<IndexedDBConnection> connection(
(...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 metadata_.version); 1630 metadata_.version);
1630 std::unique_ptr<PendingUpgradeCall> pending_call = 1631 std::unique_ptr<PendingUpgradeCall> pending_call =
1631 std::move(pending_run_version_change_transaction_call_); 1632 std::move(pending_run_version_change_transaction_call_);
1632 RunVersionChangeTransactionFinal(pending_call->callbacks(), 1633 RunVersionChangeTransactionFinal(pending_call->callbacks(),
1633 pending_call->ReleaseConnection(), 1634 pending_call->ReleaseConnection(),
1634 pending_call->transaction_id(), 1635 pending_call->transaction_id(),
1635 pending_call->version()); 1636 pending_call->version());
1636 DCHECK_EQ(1u, ConnectionCount()); 1637 DCHECK_EQ(1u, ConnectionCount());
1637 // Fall through would be a no-op, since transaction must complete 1638 // Fall through would be a no-op, since transaction must complete
1638 // asynchronously. 1639 // asynchronously.
1640 DCHECK(IsUpgradeRunning());
1639 DCHECK(IsDeleteDatabaseBlocked()); 1641 DCHECK(IsDeleteDatabaseBlocked());
1640 DCHECK(IsOpenConnectionBlocked()); 1642 DCHECK(IsOpenConnectionBlocked());
1641 return; 1643 return;
1642 } 1644 }
1643 1645
1644 if (!IsDeleteDatabaseBlocked()) { 1646 if (IsUpgradeRunning()) {
1645 std::list<PendingDeleteCall*> pending_delete_calls; 1647 DCHECK_EQ(ConnectionCount(), 1UL);
1648 return;
1649 }
1650
1651 // These delete calls were blocked by a running upgrade, and did not even
1652 // get as far as broadcasting OnVersionChange (if needed).
1653 {
1654 std::list<std::unique_ptr<PendingDeleteCall>> pending_delete_calls;
1646 pending_delete_calls_.swap(pending_delete_calls); 1655 pending_delete_calls_.swap(pending_delete_calls);
1647 while (!pending_delete_calls.empty()) { 1656 while (!pending_delete_calls.empty()) {
1657 std::unique_ptr<PendingDeleteCall> pending_delete_call(
1658 std::move(pending_delete_calls.front()));
1659 pending_delete_calls.pop_front();
1660 DeleteDatabase(pending_delete_call->callbacks());
1661 }
1662 // DeleteDatabase should never re-queue these calls.
1663 DCHECK(pending_delete_calls_.empty());
1664 // Fall through when complete, as pending deletes/opens may be unblocked.
1665 }
1666
1667 // These delete calls broadcast OnVersionChange (if needed) but were blocked
1668 // by open connections.
1669 if (!IsDeleteDatabaseBlocked()) {
1670 std::list<std::unique_ptr<PendingDeleteCall>> blocked_delete_calls;
1671 blocked_delete_calls_.swap(blocked_delete_calls);
1672 while (!blocked_delete_calls.empty()) {
1648 // Only the first delete call will delete the database, but each must fire 1673 // Only the first delete call will delete the database, but each must fire
1649 // callbacks. 1674 // callbacks.
1650 std::unique_ptr<PendingDeleteCall> pending_delete_call( 1675 std::unique_ptr<PendingDeleteCall> pending_delete_call(
1651 pending_delete_calls.front()); 1676 std::move(blocked_delete_calls.front()));
1652 pending_delete_calls.pop_front(); 1677 blocked_delete_calls.pop_front();
1653 DeleteDatabaseFinal(pending_delete_call->callbacks()); 1678 DeleteDatabaseFinal(pending_delete_call->callbacks());
1654 } 1679 }
1655 // delete_database_final should never re-queue calls. 1680 // DeleteDatabaseFinal should never re-queue these calls.
1656 DCHECK(pending_delete_calls_.empty()); 1681 DCHECK(blocked_delete_calls_.empty());
1657 // Fall through when complete, as pending opens may be unblocked. 1682 // Fall through when complete, as pending opens may be unblocked.
1658 } 1683 }
1659 1684
1685 // These open calls were blocked by a pending/running upgrade or a pending
1686 // delete.
1660 if (!IsOpenConnectionBlocked()) { 1687 if (!IsOpenConnectionBlocked()) {
1661 std::queue<IndexedDBPendingConnection> pending_open_calls; 1688 std::queue<IndexedDBPendingConnection> pending_open_calls;
1662 pending_open_calls_.swap(pending_open_calls); 1689 pending_open_calls_.swap(pending_open_calls);
1663 while (!pending_open_calls.empty()) { 1690 while (!pending_open_calls.empty()) {
1691 // This may re-queue open calls if an upgrade is necessary.
1664 OpenConnection(pending_open_calls.front()); 1692 OpenConnection(pending_open_calls.front());
1665 pending_open_calls.pop(); 1693 pending_open_calls.pop();
1666 } 1694 }
1667 } 1695 }
1668 } 1696 }
1669 1697
1670 void IndexedDBDatabase::CreateTransaction( 1698 void IndexedDBDatabase::CreateTransaction(
1671 int64_t transaction_id, 1699 int64_t transaction_id,
1672 IndexedDBConnection* connection, 1700 IndexedDBConnection* connection,
1673 const std::vector<int64_t>& object_store_ids, 1701 const std::vector<int64_t>& object_store_ids,
(...skipping 13 matching lines...) Expand all
1687 TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( 1715 TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction(
1688 transaction_id, connection->GetWeakPtr(), 1716 transaction_id, connection->GetWeakPtr(),
1689 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, 1717 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode,
1690 new IndexedDBBackingStore::Transaction(backing_store_.get()))); 1718 new IndexedDBBackingStore::Transaction(backing_store_.get())));
1691 } 1719 }
1692 1720
1693 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { 1721 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) {
1694 transactions_[transaction->id()] = transaction; 1722 transactions_[transaction->id()] = transaction;
1695 } 1723 }
1696 1724
1725 bool IndexedDBDatabase::IsUpgradeRunning() const {
1726 return transaction_coordinator_.IsRunningVersionChangeTransaction();
1727 }
1728
1729 bool IndexedDBDatabase::IsUpgradePendingOrRunning() const {
1730 return pending_run_version_change_transaction_call_ || IsUpgradeRunning();
1731 }
1732
1697 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { 1733 bool IndexedDBDatabase::IsOpenConnectionBlocked() const {
1698 return !pending_delete_calls_.empty() || 1734 return IsUpgradePendingOrRunning() || !blocked_delete_calls_.empty();
1699 transaction_coordinator_.IsRunningVersionChangeTransaction() ||
1700 pending_run_version_change_transaction_call_;
1701 } 1735 }
1702 1736
1703 void IndexedDBDatabase::OpenConnection( 1737 void IndexedDBDatabase::OpenConnection(
1704 const IndexedDBPendingConnection& connection) { 1738 const IndexedDBPendingConnection& connection) {
1705 DCHECK(backing_store_.get()); 1739 DCHECK(backing_store_.get());
1706 1740
1707 // TODO(jsbell): Should have a priority queue so that higher version
1708 // requests are processed first. http://crbug.com/225850
1709 if (IsOpenConnectionBlocked()) { 1741 if (IsOpenConnectionBlocked()) {
1710 // The backing store only detects data loss when it is first opened. The 1742 // The backing store only detects data loss when it is first opened. The
1711 // presence of existing connections means we didn't even check for data loss 1743 // presence of existing connections means we didn't even check for data loss
1712 // so there'd better not be any. 1744 // so there'd better not be any.
1713 DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss()); 1745 DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss());
1714 pending_open_calls_.push(connection); 1746 pending_open_calls_.push(connection);
1715 return; 1747 return;
1716 } 1748 }
1717 1749
1718 if (metadata_.id == kInvalidId) { 1750 if (metadata_.id == kInvalidId) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 scoped_refptr<IndexedDBCallbacks> callbacks, 1857 scoped_refptr<IndexedDBCallbacks> callbacks,
1826 std::unique_ptr<IndexedDBConnection> connection, 1858 std::unique_ptr<IndexedDBConnection> connection,
1827 int64_t transaction_id, 1859 int64_t transaction_id,
1828 int64_t requested_version) { 1860 int64_t requested_version) {
1829 std::vector<int64_t> object_store_ids; 1861 std::vector<int64_t> object_store_ids;
1830 CreateTransaction(transaction_id, 1862 CreateTransaction(transaction_id,
1831 connection.get(), 1863 connection.get(),
1832 object_store_ids, 1864 object_store_ids,
1833 blink::WebIDBTransactionModeVersionChange); 1865 blink::WebIDBTransactionModeVersionChange);
1834 1866
1867 DCHECK(transaction_coordinator_.IsRunningVersionChangeTransaction());
1835 transactions_[transaction_id]->ScheduleTask( 1868 transactions_[transaction_id]->ScheduleTask(
1836 base::Bind(&IndexedDBDatabase::VersionChangeOperation, 1869 base::Bind(&IndexedDBDatabase::VersionChangeOperation,
1837 this, 1870 this,
1838 requested_version, 1871 requested_version,
1839 callbacks, 1872 callbacks,
1840 base::Passed(&connection))); 1873 base::Passed(&connection)));
1841 DCHECK(!pending_second_half_open_); 1874 DCHECK(!pending_second_half_open_);
1842 } 1875 }
1843 1876
1844 void IndexedDBDatabase::DeleteDatabase( 1877 void IndexedDBDatabase::DeleteDatabase(
1845 scoped_refptr<IndexedDBCallbacks> callbacks) { 1878 scoped_refptr<IndexedDBCallbacks> callbacks) {
1879 // If there's a running upgrade, the delete calls should be deferred so that
1880 // "versionchange" is seen after "success" fires.
1881 if (IsUpgradeRunning()) {
1882 pending_delete_calls_.push_back(
1883 std::unique_ptr<PendingDeleteCall>(new PendingDeleteCall(callbacks)));
1884 return;
1885 }
1846 1886
1847 if (IsDeleteDatabaseBlocked()) { 1887 if (IsDeleteDatabaseBlocked()) {
1848 for (const auto* connection : connections_) { 1888 for (const auto* connection : connections_) {
1849 // Front end ensures the event is not fired at connections that have 1889 // Front end ensures the event is not fired at connections that have
1850 // close_pending set. 1890 // close_pending set.
1851 connection->callbacks()->OnVersionChange( 1891 connection->callbacks()->OnVersionChange(
1852 metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION); 1892 metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION);
1853 } 1893 }
1854 // OnBlocked will be fired at the request when one of the other 1894 // OnBlocked will be fired at the request when one of the other
1855 // connections acks that the OnVersionChange was ignored. 1895 // connections acks that the OnVersionChange was ignored.
1856 1896
1857 pending_delete_calls_.push_back(new PendingDeleteCall(callbacks)); 1897 blocked_delete_calls_.push_back(
1898 std::unique_ptr<PendingDeleteCall>(new PendingDeleteCall(callbacks)));
1858 return; 1899 return;
1859 } 1900 }
1860 DeleteDatabaseFinal(callbacks); 1901 DeleteDatabaseFinal(callbacks);
1861 } 1902 }
1862 1903
1863 bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const { 1904 bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const {
1864 return !!ConnectionCount(); 1905 return IsUpgradePendingOrRunning() || !!ConnectionCount();
1865 } 1906 }
1866 1907
1867 void IndexedDBDatabase::DeleteDatabaseFinal( 1908 void IndexedDBDatabase::DeleteDatabaseFinal(
1868 scoped_refptr<IndexedDBCallbacks> callbacks) { 1909 scoped_refptr<IndexedDBCallbacks> callbacks) {
1869 DCHECK(!IsDeleteDatabaseBlocked()); 1910 DCHECK(!IsDeleteDatabaseBlocked());
1870 DCHECK(backing_store_.get()); 1911 DCHECK(backing_store_.get());
1871 leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name); 1912 leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name);
1872 if (!s.ok()) { 1913 if (!s.ok()) {
1873 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, 1914 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError,
1874 "Internal error deleting database."); 1915 "Internal error deleting database.");
(...skipping 18 matching lines...) Expand all
1893 scoped_refptr<IndexedDBDatabase> protect(this); 1934 scoped_refptr<IndexedDBDatabase> protect(this);
1894 ConnectionSet::const_iterator it = connections_.begin(); 1935 ConnectionSet::const_iterator it = connections_.begin();
1895 while (it != connections_.end()) { 1936 while (it != connections_.end()) {
1896 IndexedDBConnection* connection = *it++; 1937 IndexedDBConnection* connection = *it++;
1897 connection->ForceClose(); 1938 connection->ForceClose();
1898 } 1939 }
1899 DCHECK(connections_.empty()); 1940 DCHECK(connections_.empty());
1900 } 1941 }
1901 1942
1902 void IndexedDBDatabase::VersionChangeIgnored() { 1943 void IndexedDBDatabase::VersionChangeIgnored() {
1903 if (pending_run_version_change_transaction_call_) 1944 if (pending_run_version_change_transaction_call_) {
1904 pending_run_version_change_transaction_call_->callbacks()->OnBlocked( 1945 pending_run_version_change_transaction_call_->callbacks()->OnBlocked(
1905 metadata_.version); 1946 metadata_.version);
1947 }
1906 1948
1907 for (const auto& pending_delete_call : pending_delete_calls_) 1949 for (const auto& pending_delete_call : blocked_delete_calls_)
1908 pending_delete_call->callbacks()->OnBlocked(metadata_.version); 1950 pending_delete_call->callbacks()->OnBlocked(metadata_.version);
1909 } 1951 }
1910 1952
1911
1912 void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) { 1953 void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) {
1913 DCHECK(connections_.count(connection)); 1954 DCHECK(connections_.count(connection));
1914 DCHECK(connection->IsConnected()); 1955 DCHECK(connection->IsConnected());
1915 DCHECK(connection->database() == this); 1956 DCHECK(connection->database() == this);
1916 1957
1917 IDB_TRACE("IndexedDBDatabase::Close"); 1958 IDB_TRACE("IndexedDBDatabase::Close");
1918 1959
1919 connections_.erase(connection); 1960 connections_.erase(connection);
1920 1961
1921 // Abort outstanding transactions from the closing connection. This 1962 // Abort outstanding transactions from the closing connection. This
(...skipping 15 matching lines...) Expand all
1937 pending_second_half_open_->callbacks()->OnError( 1978 pending_second_half_open_->callbacks()->OnError(
1938 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, 1979 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError,
1939 "The connection was closed.")); 1980 "The connection was closed."));
1940 pending_second_half_open_.reset(); 1981 pending_second_half_open_.reset();
1941 } 1982 }
1942 1983
1943 ProcessPendingCalls(); 1984 ProcessPendingCalls();
1944 1985
1945 // TODO(jsbell): Add a test for the pending_open_calls_ cases below. 1986 // TODO(jsbell): Add a test for the pending_open_calls_ cases below.
1946 if (!ConnectionCount() && pending_open_calls_.empty() && 1987 if (!ConnectionCount() && pending_open_calls_.empty() &&
1947 pending_delete_calls_.empty()) { 1988 blocked_delete_calls_.empty()) {
1948 DCHECK(transactions_.empty()); 1989 DCHECK(transactions_.empty());
1949 backing_store_ = NULL; 1990 backing_store_ = NULL;
1950 factory_->ReleaseDatabase(identifier_, forced); 1991 factory_->ReleaseDatabase(identifier_, forced);
1951 } 1992 }
1952 } 1993 }
1953 1994
1954 void IndexedDBDatabase::CreateObjectStoreAbortOperation( 1995 void IndexedDBDatabase::CreateObjectStoreAbortOperation(
1955 int64_t object_store_id, 1996 int64_t object_store_id,
1956 IndexedDBTransaction* transaction) { 1997 IndexedDBTransaction* transaction) {
1957 DCHECK(!transaction); 1998 DCHECK(!transaction);
(...skipping 12 matching lines...) Expand all
1970 2011
1971 void IndexedDBDatabase::VersionChangeAbortOperation( 2012 void IndexedDBDatabase::VersionChangeAbortOperation(
1972 int64_t previous_version, 2013 int64_t previous_version,
1973 IndexedDBTransaction* transaction) { 2014 IndexedDBTransaction* transaction) {
1974 DCHECK(!transaction); 2015 DCHECK(!transaction);
1975 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); 2016 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
1976 metadata_.version = previous_version; 2017 metadata_.version = previous_version;
1977 } 2018 }
1978 2019
1979 } // namespace content 2020 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698