OLD | NEW |
---|---|
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 Loading... | |
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 1347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1593 | 1594 |
1594 size_t IndexedDBDatabase::PendingUpgradeCount() const { | 1595 size_t IndexedDBDatabase::PendingUpgradeCount() const { |
1595 return pending_run_version_change_transaction_call_ ? 1 : 0; | 1596 return pending_run_version_change_transaction_call_ ? 1 : 0; |
1596 } | 1597 } |
1597 | 1598 |
1598 size_t IndexedDBDatabase::RunningUpgradeCount() const { | 1599 size_t IndexedDBDatabase::RunningUpgradeCount() const { |
1599 return pending_second_half_open_ ? 1 : 0; | 1600 return pending_second_half_open_ ? 1 : 0; |
1600 } | 1601 } |
1601 | 1602 |
1602 size_t IndexedDBDatabase::PendingDeleteCount() const { | 1603 size_t IndexedDBDatabase::PendingDeleteCount() const { |
1603 return pending_delete_calls_.size(); | 1604 return pending_delete_calls_.size() + blocked_delete_calls_.size(); |
1604 } | 1605 } |
1605 | 1606 |
1606 void IndexedDBDatabase::ProcessPendingCalls() { | 1607 void IndexedDBDatabase::ProcessPendingCalls() { |
1607 if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) { | 1608 if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) { |
1608 DCHECK(pending_run_version_change_transaction_call_->version() > | 1609 DCHECK(pending_run_version_change_transaction_call_->version() > |
1609 metadata_.version); | 1610 metadata_.version); |
1610 std::unique_ptr<PendingUpgradeCall> pending_call = | 1611 std::unique_ptr<PendingUpgradeCall> pending_call = |
1611 std::move(pending_run_version_change_transaction_call_); | 1612 std::move(pending_run_version_change_transaction_call_); |
1612 RunVersionChangeTransactionFinal(pending_call->callbacks(), | 1613 RunVersionChangeTransactionFinal(pending_call->callbacks(), |
1613 pending_call->ReleaseConnection(), | 1614 pending_call->ReleaseConnection(), |
1614 pending_call->transaction_id(), | 1615 pending_call->transaction_id(), |
1615 pending_call->version()); | 1616 pending_call->version()); |
1616 DCHECK_EQ(1u, ConnectionCount()); | 1617 DCHECK_EQ(1u, ConnectionCount()); |
1617 // Fall through would be a no-op, since transaction must complete | 1618 // Fall through would be a no-op, since transaction must complete |
1618 // asynchronously. | 1619 // asynchronously. |
1620 DCHECK(IsUpgradeRunning()); | |
1619 DCHECK(IsDeleteDatabaseBlocked()); | 1621 DCHECK(IsDeleteDatabaseBlocked()); |
1620 DCHECK(IsOpenConnectionBlocked()); | 1622 DCHECK(IsOpenConnectionBlocked()); |
1621 return; | 1623 return; |
1622 } | 1624 } |
1623 | 1625 |
1624 if (!IsDeleteDatabaseBlocked()) { | 1626 if (IsUpgradeRunning()) { |
1627 DCHECK_EQ(ConnectionCount(), 1UL); | |
1628 return; | |
1629 } | |
1630 | |
1631 // These delete calls were blocked by a running upgrade, and did not even | |
1632 // get as far as broadcasting OnVersionChange (if needed). | |
1633 { | |
1625 PendingDeleteCallList pending_delete_calls; | 1634 PendingDeleteCallList pending_delete_calls; |
1626 pending_delete_calls_.swap(pending_delete_calls); | 1635 pending_delete_calls_.swap(pending_delete_calls); |
1627 while (!pending_delete_calls.empty()) { | 1636 while (!pending_delete_calls.empty()) { |
1637 std::unique_ptr<PendingDeleteCall> pending_delete_call( | |
1638 pending_delete_calls.front()); | |
1639 pending_delete_calls.pop_front(); | |
1640 DeleteDatabase(pending_delete_call->callbacks()); | |
1641 } | |
1642 // DeleteDatabase should never re-queue these calls. | |
1643 DCHECK(pending_delete_calls_.empty()); | |
1644 // Fall through when complete, as pending deletes/opens may be unblocked. | |
1645 } | |
1646 | |
1647 // These delete calls broadcast OnVersionChange (if needed) but were blocked | |
1648 // by open connections. | |
1649 if (!IsDeleteDatabaseBlocked()) { | |
1650 PendingDeleteCallList blocked_delete_calls; | |
1651 blocked_delete_calls_.swap(blocked_delete_calls); | |
1652 while (!blocked_delete_calls.empty()) { | |
1628 // Only the first delete call will delete the database, but each must fire | 1653 // Only the first delete call will delete the database, but each must fire |
1629 // callbacks. | 1654 // callbacks. |
1630 std::unique_ptr<PendingDeleteCall> pending_delete_call( | 1655 std::unique_ptr<PendingDeleteCall> pending_delete_call( |
1631 pending_delete_calls.front()); | 1656 blocked_delete_calls.front()); |
1632 pending_delete_calls.pop_front(); | 1657 blocked_delete_calls.pop_front(); |
1633 DeleteDatabaseFinal(pending_delete_call->callbacks()); | 1658 DeleteDatabaseFinal(pending_delete_call->callbacks()); |
1634 } | 1659 } |
1635 // delete_database_final should never re-queue calls. | 1660 // DeleteDatabaseFinal should never re-queue these calls. |
1636 DCHECK(pending_delete_calls_.empty()); | 1661 DCHECK(blocked_delete_calls_.empty()); |
1637 // Fall through when complete, as pending opens may be unblocked. | 1662 // Fall through when complete, as pending opens may be unblocked. |
1638 } | 1663 } |
1639 | 1664 |
1665 // These open calls were blocked by a pending/running upgrade or a pending | |
1666 // delete. | |
1640 if (!IsOpenConnectionBlocked()) { | 1667 if (!IsOpenConnectionBlocked()) { |
1641 PendingOpenCallList pending_open_calls; | 1668 PendingOpenCallList pending_open_calls; |
1642 pending_open_calls_.swap(pending_open_calls); | 1669 pending_open_calls_.swap(pending_open_calls); |
1643 while (!pending_open_calls.empty()) { | 1670 while (!pending_open_calls.empty()) { |
1671 // This may re-queue open calls if an upgrade is necessary. | |
1644 OpenConnection(pending_open_calls.front()); | 1672 OpenConnection(pending_open_calls.front()); |
1645 pending_open_calls.pop_front(); | 1673 pending_open_calls.pop_front(); |
1646 } | 1674 } |
1647 } | 1675 } |
1648 } | 1676 } |
1649 | 1677 |
1650 void IndexedDBDatabase::CreateTransaction( | 1678 void IndexedDBDatabase::CreateTransaction( |
1651 int64_t transaction_id, | 1679 int64_t transaction_id, |
1652 IndexedDBConnection* connection, | 1680 IndexedDBConnection* connection, |
1653 const std::vector<int64_t>& object_store_ids, | 1681 const std::vector<int64_t>& object_store_ids, |
(...skipping 13 matching lines...) Expand all Loading... | |
1667 TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( | 1695 TransactionCreated(IndexedDBClassFactory::Get()->CreateIndexedDBTransaction( |
1668 transaction_id, connection->callbacks(), | 1696 transaction_id, connection->callbacks(), |
1669 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, | 1697 std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, |
1670 this, new IndexedDBBackingStore::Transaction(backing_store_.get()))); | 1698 this, new IndexedDBBackingStore::Transaction(backing_store_.get()))); |
1671 } | 1699 } |
1672 | 1700 |
1673 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { | 1701 void IndexedDBDatabase::TransactionCreated(IndexedDBTransaction* transaction) { |
1674 transactions_[transaction->id()] = transaction; | 1702 transactions_[transaction->id()] = transaction; |
1675 } | 1703 } |
1676 | 1704 |
1705 bool IndexedDBDatabase::IsUpgradeRunning() const { | |
1706 return transaction_coordinator_.IsRunningVersionChangeTransaction(); | |
1707 } | |
1708 | |
1709 bool IndexedDBDatabase::IsUpgradePendingOrRunning() const { | |
1710 return pending_run_version_change_transaction_call_ || IsUpgradeRunning(); | |
1711 } | |
1712 | |
1677 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { | 1713 bool IndexedDBDatabase::IsOpenConnectionBlocked() const { |
1678 return !pending_delete_calls_.empty() || | 1714 return IsUpgradePendingOrRunning() || !blocked_delete_calls_.empty(); |
cmumford
2016/06/23 21:44:19
nit: blocked_delete_calls_.empty() is constant tim
jsbell
2016/06/23 22:26:50
IsUpgradePendingOrRunning() should be constant tim
| |
1679 transaction_coordinator_.IsRunningVersionChangeTransaction() || | |
1680 pending_run_version_change_transaction_call_; | |
1681 } | 1715 } |
1682 | 1716 |
1683 void IndexedDBDatabase::OpenConnection( | 1717 void IndexedDBDatabase::OpenConnection( |
1684 const IndexedDBPendingConnection& connection) { | 1718 const IndexedDBPendingConnection& connection) { |
1685 DCHECK(backing_store_.get()); | 1719 DCHECK(backing_store_.get()); |
1686 | 1720 |
1687 // TODO(jsbell): Should have a priority queue so that higher version | |
1688 // requests are processed first. http://crbug.com/225850 | |
1689 if (IsOpenConnectionBlocked()) { | 1721 if (IsOpenConnectionBlocked()) { |
1690 // The backing store only detects data loss when it is first opened. The | 1722 // The backing store only detects data loss when it is first opened. The |
1691 // presence of existing connections means we didn't even check for data loss | 1723 // presence of existing connections means we didn't even check for data loss |
1692 // so there'd better not be any. | 1724 // so there'd better not be any. |
1693 DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss()); | 1725 DCHECK_NE(blink::WebIDBDataLossTotal, connection.callbacks->data_loss()); |
1694 pending_open_calls_.push_back(connection); | 1726 pending_open_calls_.push_back(connection); |
1695 return; | 1727 return; |
1696 } | 1728 } |
1697 | 1729 |
1698 if (metadata_.id == kInvalidId) { | 1730 if (metadata_.id == kInvalidId) { |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1805 scoped_refptr<IndexedDBCallbacks> callbacks, | 1837 scoped_refptr<IndexedDBCallbacks> callbacks, |
1806 std::unique_ptr<IndexedDBConnection> connection, | 1838 std::unique_ptr<IndexedDBConnection> connection, |
1807 int64_t transaction_id, | 1839 int64_t transaction_id, |
1808 int64_t requested_version) { | 1840 int64_t requested_version) { |
1809 std::vector<int64_t> object_store_ids; | 1841 std::vector<int64_t> object_store_ids; |
1810 CreateTransaction(transaction_id, | 1842 CreateTransaction(transaction_id, |
1811 connection.get(), | 1843 connection.get(), |
1812 object_store_ids, | 1844 object_store_ids, |
1813 blink::WebIDBTransactionModeVersionChange); | 1845 blink::WebIDBTransactionModeVersionChange); |
1814 | 1846 |
1847 DCHECK(transaction_coordinator_.IsRunningVersionChangeTransaction()); | |
1815 transactions_[transaction_id]->ScheduleTask( | 1848 transactions_[transaction_id]->ScheduleTask( |
1816 base::Bind(&IndexedDBDatabase::VersionChangeOperation, | 1849 base::Bind(&IndexedDBDatabase::VersionChangeOperation, |
1817 this, | 1850 this, |
1818 requested_version, | 1851 requested_version, |
1819 callbacks, | 1852 callbacks, |
1820 base::Passed(&connection))); | 1853 base::Passed(&connection))); |
1821 DCHECK(!pending_second_half_open_); | 1854 DCHECK(!pending_second_half_open_); |
1822 } | 1855 } |
1823 | 1856 |
1824 void IndexedDBDatabase::DeleteDatabase( | 1857 void IndexedDBDatabase::DeleteDatabase( |
1825 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1858 scoped_refptr<IndexedDBCallbacks> callbacks) { |
1859 // If there's a running upgrade, the delete calls should be deferred so that | |
1860 // "versionchange" is seen after "success" fires. | |
1861 if (IsUpgradeRunning()) { | |
1862 pending_delete_calls_.push_back(new PendingDeleteCall(callbacks)); | |
1863 return; | |
1864 } | |
1826 | 1865 |
1827 if (IsDeleteDatabaseBlocked()) { | 1866 if (IsDeleteDatabaseBlocked()) { |
1828 for (const auto* connection : connections_) { | 1867 for (const auto* connection : connections_) { |
1829 // Front end ensures the event is not fired at connections that have | 1868 // Front end ensures the event is not fired at connections that have |
1830 // close_pending set. | 1869 // close_pending set. |
1831 connection->callbacks()->OnVersionChange( | 1870 connection->callbacks()->OnVersionChange( |
1832 metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION); | 1871 metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION); |
1833 } | 1872 } |
1834 // OnBlocked will be fired at the request when one of the other | 1873 // OnBlocked will be fired at the request when one of the other |
1835 // connections acks that the OnVersionChange was ignored. | 1874 // connections acks that the OnVersionChange was ignored. |
1836 | 1875 |
1837 pending_delete_calls_.push_back(new PendingDeleteCall(callbacks)); | 1876 blocked_delete_calls_.push_back(new PendingDeleteCall(callbacks)); |
1838 return; | 1877 return; |
1839 } | 1878 } |
1840 DeleteDatabaseFinal(callbacks); | 1879 DeleteDatabaseFinal(callbacks); |
1841 } | 1880 } |
1842 | 1881 |
1843 bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const { | 1882 bool IndexedDBDatabase::IsDeleteDatabaseBlocked() const { |
1844 return !!ConnectionCount(); | 1883 return IsUpgradePendingOrRunning() || !!ConnectionCount(); |
1845 } | 1884 } |
1846 | 1885 |
1847 void IndexedDBDatabase::DeleteDatabaseFinal( | 1886 void IndexedDBDatabase::DeleteDatabaseFinal( |
1848 scoped_refptr<IndexedDBCallbacks> callbacks) { | 1887 scoped_refptr<IndexedDBCallbacks> callbacks) { |
1849 DCHECK(!IsDeleteDatabaseBlocked()); | 1888 DCHECK(!IsDeleteDatabaseBlocked()); |
1850 DCHECK(backing_store_.get()); | 1889 DCHECK(backing_store_.get()); |
1851 leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name); | 1890 leveldb::Status s = backing_store_->DeleteDatabase(metadata_.name); |
1852 if (!s.ok()) { | 1891 if (!s.ok()) { |
1853 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, | 1892 IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, |
1854 "Internal error deleting database."); | 1893 "Internal error deleting database."); |
(...skipping 18 matching lines...) Expand all Loading... | |
1873 scoped_refptr<IndexedDBDatabase> protect(this); | 1912 scoped_refptr<IndexedDBDatabase> protect(this); |
1874 ConnectionSet::const_iterator it = connections_.begin(); | 1913 ConnectionSet::const_iterator it = connections_.begin(); |
1875 while (it != connections_.end()) { | 1914 while (it != connections_.end()) { |
1876 IndexedDBConnection* connection = *it++; | 1915 IndexedDBConnection* connection = *it++; |
1877 connection->ForceClose(); | 1916 connection->ForceClose(); |
1878 } | 1917 } |
1879 DCHECK(connections_.empty()); | 1918 DCHECK(connections_.empty()); |
1880 } | 1919 } |
1881 | 1920 |
1882 void IndexedDBDatabase::VersionChangeIgnored() { | 1921 void IndexedDBDatabase::VersionChangeIgnored() { |
1883 if (pending_run_version_change_transaction_call_) | 1922 if (pending_run_version_change_transaction_call_) { |
1884 pending_run_version_change_transaction_call_->callbacks()->OnBlocked( | 1923 pending_run_version_change_transaction_call_->callbacks()->OnBlocked( |
1885 metadata_.version); | 1924 metadata_.version); |
1925 } | |
1886 | 1926 |
1887 for (const auto& pending_delete_call : pending_delete_calls_) | 1927 for (const auto& pending_delete_call : blocked_delete_calls_) |
1888 pending_delete_call->callbacks()->OnBlocked(metadata_.version); | 1928 pending_delete_call->callbacks()->OnBlocked(metadata_.version); |
1889 } | 1929 } |
1890 | 1930 |
1891 | |
1892 void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) { | 1931 void IndexedDBDatabase::Close(IndexedDBConnection* connection, bool forced) { |
1893 DCHECK(connections_.count(connection)); | 1932 DCHECK(connections_.count(connection)); |
1894 DCHECK(connection->IsConnected()); | 1933 DCHECK(connection->IsConnected()); |
1895 DCHECK(connection->database() == this); | 1934 DCHECK(connection->database() == this); |
1896 | 1935 |
1897 IDB_TRACE("IndexedDBDatabase::Close"); | 1936 IDB_TRACE("IndexedDBDatabase::Close"); |
1898 | 1937 |
1899 connections_.erase(connection); | 1938 connections_.erase(connection); |
1900 | 1939 |
1901 // Abort outstanding transactions from the closing connection. This | 1940 // Abort outstanding transactions from the closing connection. This |
(...skipping 15 matching lines...) Expand all Loading... | |
1917 pending_second_half_open_->callbacks()->OnError( | 1956 pending_second_half_open_->callbacks()->OnError( |
1918 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, | 1957 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionAbortError, |
1919 "The connection was closed.")); | 1958 "The connection was closed.")); |
1920 pending_second_half_open_.reset(); | 1959 pending_second_half_open_.reset(); |
1921 } | 1960 } |
1922 | 1961 |
1923 ProcessPendingCalls(); | 1962 ProcessPendingCalls(); |
1924 | 1963 |
1925 // TODO(jsbell): Add a test for the pending_open_calls_ cases below. | 1964 // TODO(jsbell): Add a test for the pending_open_calls_ cases below. |
1926 if (!ConnectionCount() && !pending_open_calls_.size() && | 1965 if (!ConnectionCount() && !pending_open_calls_.size() && |
1927 !pending_delete_calls_.size()) { | 1966 !blocked_delete_calls_.size()) { |
cmumford
2016/06/23 21:44:19
Nit: I know you're sticking with existing pattern,
jsbell
2016/06/23 22:26:50
Whoops, yeah, I'll use empty(). That was ported fr
| |
1928 DCHECK(transactions_.empty()); | 1967 DCHECK(transactions_.empty()); |
1929 backing_store_ = NULL; | 1968 backing_store_ = NULL; |
1930 factory_->ReleaseDatabase(identifier_, forced); | 1969 factory_->ReleaseDatabase(identifier_, forced); |
1931 } | 1970 } |
1932 } | 1971 } |
1933 | 1972 |
1934 void IndexedDBDatabase::CreateObjectStoreAbortOperation( | 1973 void IndexedDBDatabase::CreateObjectStoreAbortOperation( |
1935 int64_t object_store_id, | 1974 int64_t object_store_id, |
1936 IndexedDBTransaction* transaction) { | 1975 IndexedDBTransaction* transaction) { |
1937 DCHECK(!transaction); | 1976 DCHECK(!transaction); |
(...skipping 12 matching lines...) Expand all Loading... | |
1950 | 1989 |
1951 void IndexedDBDatabase::VersionChangeAbortOperation( | 1990 void IndexedDBDatabase::VersionChangeAbortOperation( |
1952 int64_t previous_version, | 1991 int64_t previous_version, |
1953 IndexedDBTransaction* transaction) { | 1992 IndexedDBTransaction* transaction) { |
1954 DCHECK(!transaction); | 1993 DCHECK(!transaction); |
1955 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); | 1994 IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation"); |
1956 metadata_.version = previous_version; | 1995 metadata_.version = previous_version; |
1957 } | 1996 } |
1958 | 1997 |
1959 } // namespace content | 1998 } // namespace content |
OLD | NEW |