|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "storage/browser/database/database_connections.h" | 
|  |  | 
|  | #include <ostream> | 
|  |  | 
|  | #include "base/check.h" | 
|  |  | 
|  | namespace storage { | 
|  |  | 
|  | DatabaseConnections::DatabaseConnections() = default; | 
|  |  | 
|  | DatabaseConnections::~DatabaseConnections() { | 
|  | DCHECK(connections_.empty()); | 
|  | } | 
|  |  | 
|  | bool DatabaseConnections::IsEmpty() const { | 
|  | return connections_.empty(); | 
|  | } | 
|  |  | 
|  | bool DatabaseConnections::IsDatabaseOpened( | 
|  | const std::string& origin_identifier, | 
|  | const std::u16string& database_name) const { | 
|  | auto origin_it = connections_.find(origin_identifier); | 
|  | if (origin_it == connections_.end()) | 
|  | return false; | 
|  | const DBConnections& origin_connections = origin_it->second; | 
|  | return (origin_connections.find(database_name) != origin_connections.end()); | 
|  | } | 
|  |  | 
|  | bool DatabaseConnections::IsOriginUsed( | 
|  | const std::string& origin_identifier) const { | 
|  | return (connections_.find(origin_identifier) != connections_.end()); | 
|  | } | 
|  |  | 
|  | bool DatabaseConnections::AddConnection(const std::string& origin_identifier, | 
|  | const std::u16string& database_name) { | 
|  | int& count = connections_[origin_identifier][database_name].first; | 
|  | return ++count == 1; | 
|  | } | 
|  |  | 
|  | bool DatabaseConnections::RemoveConnection( | 
|  | const std::string& origin_identifier, | 
|  | const std::u16string& database_name) { | 
|  | return RemoveConnectionsHelper(origin_identifier, database_name, 1); | 
|  | } | 
|  |  | 
|  | void DatabaseConnections::RemoveAllConnections() { | 
|  | connections_.clear(); | 
|  | } | 
|  |  | 
|  | std::vector<std::pair<std::string, std::u16string>> | 
|  | DatabaseConnections::RemoveConnections(const DatabaseConnections& connections) { | 
|  | std::vector<std::pair<std::string, std::u16string>> closed_dbs; | 
|  | for (const auto& origin_connections_pair : connections.connections_) { | 
|  | const DBConnections& db_connections = origin_connections_pair.second; | 
|  | for (const auto& count_size_pair : db_connections) { | 
|  | if (RemoveConnectionsHelper(origin_connections_pair.first, | 
|  | count_size_pair.first, | 
|  | count_size_pair.second.first)) { | 
|  | closed_dbs.emplace_back(origin_connections_pair.first, | 
|  | count_size_pair.first); | 
|  | } | 
|  | } | 
|  | } | 
|  | return closed_dbs; | 
|  | } | 
|  |  | 
|  | int64_t DatabaseConnections::GetOpenDatabaseSize( | 
|  | const std::string& origin_identifier, | 
|  | const std::u16string& database_name) const { | 
|  | auto origin_it = connections_.find(origin_identifier); | 
|  | DCHECK(origin_it != connections_.end()) << "Database not opened"; | 
|  | auto it = origin_it->second.find(database_name); | 
|  | DCHECK(it != origin_it->second.end()) << "Database not opened"; | 
|  | return it->second.second; | 
|  | } | 
|  |  | 
|  | void DatabaseConnections::SetOpenDatabaseSize( | 
|  | const std::string& origin_identifier, | 
|  | const std::u16string& database_name, | 
|  | int64_t size) { | 
|  | DCHECK(IsDatabaseOpened(origin_identifier, database_name)); | 
|  | connections_[origin_identifier][database_name].second = size; | 
|  | } | 
|  |  | 
|  | std::vector<std::pair<std::string, std::u16string>> | 
|  | DatabaseConnections::ListConnections() const { | 
|  | std::vector<std::pair<std::string, std::u16string>> list; | 
|  | for (const auto& origin_connections_pair : connections_) { | 
|  | const DBConnections& db_connections = origin_connections_pair.second; | 
|  | for (const auto& count_size_pair : db_connections) | 
|  | list.emplace_back(origin_connections_pair.first, count_size_pair.first); | 
|  | } | 
|  | return list; | 
|  | } | 
|  |  | 
|  | bool DatabaseConnections::RemoveConnectionsHelper( | 
|  | const std::string& origin_identifier, | 
|  | const std::u16string& database_name, | 
|  | int num_connections) { | 
|  | auto origin_iterator = connections_.find(origin_identifier); | 
|  | DCHECK(origin_iterator != connections_.end()); | 
|  | DBConnections& db_connections = origin_iterator->second; | 
|  | int& count = db_connections[database_name].first; | 
|  | DCHECK(count >= num_connections); | 
|  | count -= num_connections; | 
|  | if (count) | 
|  | return false; | 
|  | db_connections.erase(database_name); | 
|  | if (db_connections.empty()) | 
|  | connections_.erase(origin_iterator); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | }  // namespace storage |