OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "webkit/common/database/database_connections.h" | |
6 | |
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/message_loop/message_loop_proxy.h" | |
12 | |
13 namespace storage { | |
14 | |
15 DatabaseConnections::DatabaseConnections() { | |
16 } | |
17 | |
18 DatabaseConnections::~DatabaseConnections() { | |
19 DCHECK(connections_.empty()); | |
20 } | |
21 | |
22 bool DatabaseConnections::IsEmpty() const { | |
23 return connections_.empty(); | |
24 } | |
25 | |
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()); | |
35 } | |
36 | |
37 bool DatabaseConnections::IsOriginUsed( | |
38 const std::string& origin_identifier) const { | |
39 return (connections_.find(origin_identifier) != connections_.end()); | |
40 } | |
41 | |
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; | |
47 } | |
48 | |
49 bool DatabaseConnections::RemoveConnection( | |
50 const std::string& origin_identifier, | |
51 const base::string16& database_name) { | |
52 return RemoveConnectionsHelper(origin_identifier, database_name, 1); | |
53 } | |
54 | |
55 void DatabaseConnections::RemoveAllConnections() { | |
56 connections_.clear(); | |
57 } | |
58 | |
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)); | |
72 } | |
73 } | |
74 } | |
75 | |
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; | |
81 } | |
82 | |
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; | |
89 } | |
90 | |
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)); | |
101 } | |
102 } | |
103 } | |
104 | |
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; | |
122 } | |
123 | |
124 DatabaseConnectionsWrapper::DatabaseConnectionsWrapper() | |
125 : waiting_for_dbs_to_close_(false), | |
126 main_thread_(base::MessageLoopProxy::current()) { | |
127 } | |
128 | |
129 DatabaseConnectionsWrapper::~DatabaseConnectionsWrapper() { | |
130 } | |
131 | |
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(); | |
140 } | |
141 } | |
142 | |
143 bool DatabaseConnectionsWrapper::HasOpenConnections() { | |
144 DCHECK(main_thread_->BelongsToCurrentThread()); | |
145 base::AutoLock auto_lock(open_connections_lock_); | |
146 return !open_connections_.IsEmpty(); | |
147 } | |
148 | |
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); | |
155 } | |
156 | |
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; | |
168 } | |
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(); | |
173 } | |
174 | |
175 } // namespace storage | |
OLD | NEW |