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 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |