Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / storage / common / database / database_connections.cc
blobb0b55de57eb7c973570746b58c564fe13201f6b7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "storage/common/database/database_connections.h"
7 #include "base/auto_reset.h"
8 #include "base/bind.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/thread_task_runner_handle.h"
13 namespace storage {
15 DatabaseConnections::DatabaseConnections() {
18 DatabaseConnections::~DatabaseConnections() {
19 DCHECK(connections_.empty());
22 bool DatabaseConnections::IsEmpty() const {
23 return connections_.empty();
26 bool DatabaseConnections::IsDatabaseOpened(
27 const std::string& origin_identifier,
28 const base::string16& database_name) const {
29 OriginConnections::const_iterator origin_it =
30 connections_.find(origin_identifier);
31 if (origin_it == connections_.end())
32 return false;
33 const DBConnections& origin_connections = origin_it->second;
34 return (origin_connections.find(database_name) != origin_connections.end());
37 bool DatabaseConnections::IsOriginUsed(
38 const std::string& origin_identifier) const {
39 return (connections_.find(origin_identifier) != connections_.end());
42 bool DatabaseConnections::AddConnection(
43 const std::string& origin_identifier,
44 const base::string16& database_name) {
45 int& count = connections_[origin_identifier][database_name].first;
46 return ++count == 1;
49 bool DatabaseConnections::RemoveConnection(
50 const std::string& origin_identifier,
51 const base::string16& database_name) {
52 return RemoveConnectionsHelper(origin_identifier, database_name, 1);
55 void DatabaseConnections::RemoveAllConnections() {
56 connections_.clear();
59 void DatabaseConnections::RemoveConnections(
60 const DatabaseConnections& connections,
61 std::vector<std::pair<std::string, base::string16> >* closed_dbs) {
62 for (OriginConnections::const_iterator origin_it =
63 connections.connections_.begin();
64 origin_it != connections.connections_.end();
65 origin_it++) {
66 const DBConnections& db_connections = origin_it->second;
67 for (DBConnections::const_iterator db_it = db_connections.begin();
68 db_it != db_connections.end(); db_it++) {
69 if (RemoveConnectionsHelper(origin_it->first, db_it->first,
70 db_it->second.first))
71 closed_dbs->push_back(std::make_pair(origin_it->first, db_it->first));
76 int64 DatabaseConnections::GetOpenDatabaseSize(
77 const std::string& origin_identifier,
78 const base::string16& database_name) const {
79 DCHECK(IsDatabaseOpened(origin_identifier, database_name));
80 return connections_[origin_identifier][database_name].second;
83 void DatabaseConnections::SetOpenDatabaseSize(
84 const std::string& origin_identifier,
85 const base::string16& database_name,
86 int64 size) {
87 DCHECK(IsDatabaseOpened(origin_identifier, database_name));
88 connections_[origin_identifier][database_name].second = size;
91 void DatabaseConnections::ListConnections(
92 std::vector<std::pair<std::string, base::string16> > *list) const {
93 for (OriginConnections::const_iterator origin_it =
94 connections_.begin();
95 origin_it != connections_.end();
96 origin_it++) {
97 const DBConnections& db_connections = origin_it->second;
98 for (DBConnections::const_iterator db_it = db_connections.begin();
99 db_it != db_connections.end(); db_it++) {
100 list->push_back(std::make_pair(origin_it->first, db_it->first));
105 bool DatabaseConnections::RemoveConnectionsHelper(
106 const std::string& origin_identifier,
107 const base::string16& database_name,
108 int num_connections) {
109 OriginConnections::iterator origin_iterator =
110 connections_.find(origin_identifier);
111 DCHECK(origin_iterator != connections_.end());
112 DBConnections& db_connections = origin_iterator->second;
113 int& count = db_connections[database_name].first;
114 DCHECK(count >= num_connections);
115 count -= num_connections;
116 if (count)
117 return false;
118 db_connections.erase(database_name);
119 if (db_connections.empty())
120 connections_.erase(origin_iterator);
121 return true;
124 DatabaseConnectionsWrapper::DatabaseConnectionsWrapper()
125 : waiting_for_dbs_to_close_(false),
126 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
129 DatabaseConnectionsWrapper::~DatabaseConnectionsWrapper() {
132 void DatabaseConnectionsWrapper::WaitForAllDatabasesToClose() {
133 // We assume that new databases won't be open while we're waiting.
134 DCHECK(main_thread_->BelongsToCurrentThread());
135 if (HasOpenConnections()) {
136 base::AutoReset<bool> auto_reset(&waiting_for_dbs_to_close_, true);
137 base::MessageLoop::ScopedNestableTaskAllower allow(
138 base::MessageLoop::current());
139 base::MessageLoop::current()->Run();
143 bool DatabaseConnectionsWrapper::HasOpenConnections() {
144 DCHECK(main_thread_->BelongsToCurrentThread());
145 base::AutoLock auto_lock(open_connections_lock_);
146 return !open_connections_.IsEmpty();
149 void DatabaseConnectionsWrapper::AddOpenConnection(
150 const std::string& origin_identifier,
151 const base::string16& database_name) {
152 // We add to the collection immediately on any thread.
153 base::AutoLock auto_lock(open_connections_lock_);
154 open_connections_.AddConnection(origin_identifier, database_name);
157 void DatabaseConnectionsWrapper::RemoveOpenConnection(
158 const std::string& origin_identifier,
159 const base::string16& database_name) {
160 // But only remove from the collection on the main thread
161 // so we can handle the waiting_for_dbs_to_close_ case.
162 if (!main_thread_->BelongsToCurrentThread()) {
163 main_thread_->PostTask(
164 FROM_HERE,
165 base::Bind(&DatabaseConnectionsWrapper::RemoveOpenConnection, this,
166 origin_identifier, database_name));
167 return;
169 base::AutoLock auto_lock(open_connections_lock_);
170 open_connections_.RemoveConnection(origin_identifier, database_name);
171 if (waiting_for_dbs_to_close_ && open_connections_.IsEmpty())
172 base::MessageLoop::current()->Quit();
175 } // namespace storage