• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 webkit_database {
14 
DatabaseConnections()15 DatabaseConnections::DatabaseConnections() {
16 }
17 
~DatabaseConnections()18 DatabaseConnections::~DatabaseConnections() {
19   DCHECK(connections_.empty());
20 }
21 
IsEmpty() const22 bool DatabaseConnections::IsEmpty() const {
23   return connections_.empty();
24 }
25 
IsDatabaseOpened(const std::string & origin_identifier,const base::string16 & database_name) const26 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 
IsOriginUsed(const std::string & origin_identifier) const37 bool DatabaseConnections::IsOriginUsed(
38     const std::string& origin_identifier) const {
39   return (connections_.find(origin_identifier) != connections_.end());
40 }
41 
AddConnection(const std::string & origin_identifier,const base::string16 & database_name)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 
RemoveConnection(const std::string & origin_identifier,const base::string16 & database_name)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 
RemoveAllConnections()55 void DatabaseConnections::RemoveAllConnections() {
56   connections_.clear();
57 }
58 
RemoveConnections(const DatabaseConnections & connections,std::vector<std::pair<std::string,base::string16>> * closed_dbs)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 
GetOpenDatabaseSize(const std::string & origin_identifier,const base::string16 & database_name) const76 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 
SetOpenDatabaseSize(const std::string & origin_identifier,const base::string16 & database_name,int64 size)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 
ListConnections(std::vector<std::pair<std::string,base::string16>> * list) const91 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 
RemoveConnectionsHelper(const std::string & origin_identifier,const base::string16 & database_name,int num_connections)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 
DatabaseConnectionsWrapper()124 DatabaseConnectionsWrapper::DatabaseConnectionsWrapper()
125     : waiting_for_dbs_to_close_(false),
126       main_thread_(base::MessageLoopProxy::current()) {
127 }
128 
~DatabaseConnectionsWrapper()129 DatabaseConnectionsWrapper::~DatabaseConnectionsWrapper() {
130 }
131 
WaitForAllDatabasesToClose()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 
HasOpenConnections()143 bool DatabaseConnectionsWrapper::HasOpenConnections() {
144   DCHECK(main_thread_->BelongsToCurrentThread());
145   base::AutoLock auto_lock(open_connections_lock_);
146   return !open_connections_.IsEmpty();
147 }
148 
AddOpenConnection(const std::string & origin_identifier,const base::string16 & database_name)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 
RemoveOpenConnection(const std::string & origin_identifier,const base::string16 & 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;
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 webkit_database
176