| 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 webkit_database { | |
| 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 webkit_database | |
| OLD | NEW |