Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(279)

Side by Side Diff: components/sync_sessions/tab_node_pool.cc

Issue 2712743006: Reland v5 of Sessions Refactor (Closed)
Patch Set: Fix typo Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/sync_sessions/tab_node_pool.h" 5 #include "components/sync_sessions/tab_node_pool.h"
6 6
7 #include "base/format_macros.h" 7 #include <algorithm>
8
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "components/sync/base/model_type.h" 10 #include "components/sync/base/model_type.h"
11 #include "components/sync/model/sync_change.h"
12 #include "components/sync/model/sync_data.h"
13 #include "components/sync/protocol/session_specifics.pb.h" 11 #include "components/sync/protocol/session_specifics.pb.h"
14 #include "components/sync/protocol/sync.pb.h" 12 #include "components/sync/protocol/sync.pb.h"
15 13
16 namespace sync_sessions { 14 namespace sync_sessions {
17 15
18 const size_t TabNodePool::kFreeNodesLowWatermark = 25; 16 const size_t TabNodePool::kFreeNodesLowWatermark = 25;
19 const size_t TabNodePool::kFreeNodesHighWatermark = 100; 17 const size_t TabNodePool::kFreeNodesHighWatermark = 100;
20 18
21 TabNodePool::TabNodePool() : max_used_tab_node_id_(kInvalidTabNodeID) {} 19 TabNodePool::TabNodePool() : max_used_tab_node_id_(kInvalidTabNodeID) {}
22 20
23 // static 21 // static
24 // We start vending tab node IDs at 0. 22 // We start vending tab node IDs at 0.
25 const int TabNodePool::kInvalidTabNodeID = -1; 23 const int TabNodePool::kInvalidTabNodeID = -1;
26 24
27 TabNodePool::~TabNodePool() {} 25 TabNodePool::~TabNodePool() {}
28 26
29 // Static
30 std::string TabNodePool::TabIdToTag(const std::string& machine_tag,
31 int tab_node_id) {
32 return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id);
33 }
34
35 void TabNodePool::AddTabNode(int tab_node_id) { 27 void TabNodePool::AddTabNode(int tab_node_id) {
36 DCHECK_GT(tab_node_id, kInvalidTabNodeID); 28 DCHECK_GT(tab_node_id, kInvalidTabNodeID);
37 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end()); 29 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end());
38 unassociated_nodes_.insert(tab_node_id); 30 DVLOG(1) << "Adding tab node " << tab_node_id << " to pool.";
39 if (max_used_tab_node_id_ < tab_node_id) 31 max_used_tab_node_id_ = std::max(max_used_tab_node_id_, tab_node_id);
40 max_used_tab_node_id_ = tab_node_id; 32 free_nodes_pool_.insert(tab_node_id);
41 } 33 }
42 34
43 void TabNodePool::AssociateTabNode(int tab_node_id, SessionID::id_type tab_id) { 35 void TabNodePool::AssociateTabNode(int tab_node_id, SessionID::id_type tab_id) {
44 DCHECK_GT(tab_node_id, kInvalidTabNodeID); 36 DCHECK_GT(tab_node_id, kInvalidTabNodeID);
45 // Remove sync node if it is in unassociated nodes pool. 37 DCHECK_GT(tab_id, kInvalidTabID);
46 std::set<int>::iterator u_it = unassociated_nodes_.find(tab_node_id); 38
47 if (u_it != unassociated_nodes_.end()) { 39 // This is a new node association, the sync node should be free.
48 unassociated_nodes_.erase(u_it); 40 // Remove node from free node pool and then associate it with the tab.
49 } else { 41 std::set<int>::iterator it = free_nodes_pool_.find(tab_node_id);
50 // This is a new node association, the sync node should be free. 42 DCHECK(it != free_nodes_pool_.end());
51 // Remove node from free node pool and then associate it with the tab. 43 free_nodes_pool_.erase(it);
52 std::set<int>::iterator it = free_nodes_pool_.find(tab_node_id); 44
53 DCHECK(it != free_nodes_pool_.end());
54 free_nodes_pool_.erase(it);
55 }
56 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end()); 45 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end());
46 DVLOG(1) << "Associating tab node " << tab_node_id << " with tab " << tab_id;
57 nodeid_tabid_map_[tab_node_id] = tab_id; 47 nodeid_tabid_map_[tab_node_id] = tab_id;
48 tabid_nodeid_map_[tab_id] = tab_node_id;
58 } 49 }
59 50
60 int TabNodePool::GetFreeTabNode(syncer::SyncChangeList* append_changes) { 51 bool TabNodePool::GetTabNodeForTab(SessionID::id_type tab_id,
61 DCHECK_GT(machine_tag_.length(), 0U); 52 int* tab_node_id) {
62 DCHECK(append_changes); 53 if (tabid_nodeid_map_.find(tab_id) != tabid_nodeid_map_.end()) {
54 *tab_node_id = tabid_nodeid_map_[tab_id];
55 return true;
56 }
57
63 if (free_nodes_pool_.empty()) { 58 if (free_nodes_pool_.empty()) {
64 // Tab pool has no free nodes, allocate new one. 59 // Tab pool has no free nodes, allocate new one.
65 int tab_node_id = ++max_used_tab_node_id_; 60 *tab_node_id = ++max_used_tab_node_id_;
66 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); 61 AddTabNode(*tab_node_id);
67 62
68 // We fill the new node with just enough data so that in case of a crash/bug 63 AssociateTabNode(*tab_node_id, tab_id);
69 // we can identify the node as our own on re-association and reuse it. 64 return false;
70 sync_pb::EntitySpecifics entity;
71 sync_pb::SessionSpecifics* specifics = entity.mutable_session();
72 specifics->set_session_tag(machine_tag_);
73 specifics->set_tab_node_id(tab_node_id);
74 append_changes->push_back(syncer::SyncChange(
75 FROM_HERE, syncer::SyncChange::ACTION_ADD,
76 syncer::SyncData::CreateLocalData(tab_node_tag, tab_node_tag, entity)));
77
78 // Grow the pool by 1 since we created a new node.
79 DVLOG(1) << "Adding sync node " << tab_node_id << " to tab node id pool";
80 free_nodes_pool_.insert(tab_node_id);
81 return tab_node_id;
82 } else { 65 } else {
83 // Return the next free node. 66 // Return the next free node.
84 return *free_nodes_pool_.begin(); 67 *tab_node_id = *free_nodes_pool_.begin();
68 AssociateTabNode(*tab_node_id, tab_id);
69 return true;
85 } 70 }
86 } 71 }
87 72
88 void TabNodePool::FreeTabNode(int tab_node_id, 73 void TabNodePool::FreeTab(int tab_id) {
89 syncer::SyncChangeList* append_changes) { 74 DCHECK_GT(tab_id, kInvalidTabID);
90 DCHECK(append_changes); 75 TabIDToTabNodeIDMap::iterator it = tabid_nodeid_map_.find(tab_id);
91 TabNodeIDToTabIDMap::iterator it = nodeid_tabid_map_.find(tab_node_id); 76 if (it == tabid_nodeid_map_.end()) {
92 DCHECK(it != nodeid_tabid_map_.end()); 77 return; // Already freed.
93 nodeid_tabid_map_.erase(it); 78 }
94 FreeTabNodeInternal(tab_node_id, append_changes);
95 }
96 79
97 void TabNodePool::FreeTabNodeInternal(int tab_node_id, 80 int tab_node_id = it->second;
98 syncer::SyncChangeList* append_changes) { 81 DVLOG(1) << "Freeing tab " << tab_id << " at node " << tab_node_id;
99 DCHECK(free_nodes_pool_.find(tab_node_id) == free_nodes_pool_.end()); 82 nodeid_tabid_map_.erase(nodeid_tabid_map_.find(tab_node_id));
100 DCHECK(append_changes); 83 tabid_nodeid_map_.erase(it);
101 free_nodes_pool_.insert(tab_node_id); 84 free_nodes_pool_.insert(tab_node_id);
102
103 // If number of free nodes exceed kFreeNodesHighWatermark,
104 // delete sync nodes till number reaches kFreeNodesLowWatermark.
105 // Note: This logic is to mitigate temporary disassociation issues with old
106 // clients: http://crbug.com/259918. Newer versions do not need this.
107 if (free_nodes_pool_.size() > kFreeNodesHighWatermark) {
108 for (std::set<int>::iterator free_it = free_nodes_pool_.begin();
109 free_it != free_nodes_pool_.end();) {
110 const std::string tab_node_tag = TabIdToTag(machine_tag_, *free_it);
111 append_changes->push_back(syncer::SyncChange(
112 FROM_HERE, syncer::SyncChange::ACTION_DELETE,
113 syncer::SyncData::CreateLocalDelete(tab_node_tag, syncer::SESSIONS)));
114 free_nodes_pool_.erase(free_it++);
115 if (free_nodes_pool_.size() <= kFreeNodesLowWatermark) {
116 return;
117 }
118 }
119 }
120 }
121
122 bool TabNodePool::IsUnassociatedTabNode(int tab_node_id) {
123 return unassociated_nodes_.find(tab_node_id) != unassociated_nodes_.end();
124 } 85 }
125 86
126 void TabNodePool::ReassociateTabNode(int tab_node_id, 87 void TabNodePool::ReassociateTabNode(int tab_node_id,
127 SessionID::id_type tab_id) { 88 SessionID::id_type tab_id) {
128 // Remove from list of unassociated sync_nodes if present. 89 DCHECK_GT(tab_node_id, kInvalidTabNodeID);
129 std::set<int>::iterator it = unassociated_nodes_.find(tab_node_id); 90 DCHECK_GT(tab_id, kInvalidTabID);
130 if (it != unassociated_nodes_.end()) { 91
131 unassociated_nodes_.erase(it); 92 auto tabid_it = tabid_nodeid_map_.find(tab_id);
93 if (tabid_it != tabid_nodeid_map_.end()) {
94 if (tabid_it->second == tab_node_id) {
95 return; // Already associated properly.
96 } else {
97 // Another node is already associated with this tab. Free it.
98 FreeTab(tab_id);
99 }
100 }
101
102 auto nodeid_it = nodeid_tabid_map_.find(tab_node_id);
103 if (nodeid_it != nodeid_tabid_map_.end()) {
104 // This node was already associated with another tab. Free it.
105 FreeTab(nodeid_it->second);
132 } else { 106 } else {
133 // tab_node_id must be an already associated node. 107 // This is a new tab node. Add it before association.
134 DCHECK(nodeid_tabid_map_.find(tab_node_id) != nodeid_tabid_map_.end()); 108 AddTabNode(tab_node_id);
135 } 109 }
136 nodeid_tabid_map_[tab_node_id] = tab_id; 110
111 AssociateTabNode(tab_node_id, tab_id);
137 } 112 }
138 113
139 SessionID::id_type TabNodePool::GetTabIdFromTabNodeId(int tab_node_id) const { 114 SessionID::id_type TabNodePool::GetTabIdFromTabNodeId(int tab_node_id) const {
140 TabNodeIDToTabIDMap::const_iterator it = nodeid_tabid_map_.find(tab_node_id); 115 TabNodeIDToTabIDMap::const_iterator it = nodeid_tabid_map_.find(tab_node_id);
141 if (it != nodeid_tabid_map_.end()) { 116 if (it != nodeid_tabid_map_.end()) {
142 return it->second; 117 return it->second;
143 } 118 }
144 return kInvalidTabID; 119 return kInvalidTabID;
145 } 120 }
146 121
147 void TabNodePool::DeleteUnassociatedTabNodes( 122 void TabNodePool::CleanupTabNodes(std::set<int>* deleted_node_ids) {
148 syncer::SyncChangeList* append_changes) { 123 // If number of free nodes exceed kFreeNodesHighWatermark,
149 for (std::set<int>::iterator it = unassociated_nodes_.begin(); 124 // delete sync nodes till number reaches kFreeNodesLowWatermark.
150 it != unassociated_nodes_.end();) { 125 // Note: This logic is to mitigate temporary disassociation issues with old
151 FreeTabNodeInternal(*it, append_changes); 126 // clients: http://crbug.com/259918. Newer versions do not need this.
152 unassociated_nodes_.erase(it++); 127 if (free_nodes_pool_.size() > kFreeNodesHighWatermark) {
128 for (std::set<int>::iterator free_it = free_nodes_pool_.begin();
129 free_it != free_nodes_pool_.end();) {
130 deleted_node_ids->insert(*free_it);
131 free_nodes_pool_.erase(free_it++);
132 if (free_nodes_pool_.size() <= kFreeNodesLowWatermark) {
133 return;
134 }
135 }
153 } 136 }
154 DCHECK(unassociated_nodes_.empty());
155 } 137 }
156 138
157 // Clear tab pool. 139 // Clear tab pool.
158 void TabNodePool::Clear() { 140 void TabNodePool::Clear() {
159 unassociated_nodes_.clear();
160 free_nodes_pool_.clear(); 141 free_nodes_pool_.clear();
161 nodeid_tabid_map_.clear(); 142 nodeid_tabid_map_.clear();
143 tabid_nodeid_map_.clear();
162 max_used_tab_node_id_ = kInvalidTabNodeID; 144 max_used_tab_node_id_ = kInvalidTabNodeID;
163 } 145 }
164 146
165 size_t TabNodePool::Capacity() const { 147 size_t TabNodePool::Capacity() const {
166 return nodeid_tabid_map_.size() + unassociated_nodes_.size() + 148 return nodeid_tabid_map_.size() + free_nodes_pool_.size();
167 free_nodes_pool_.size();
168 } 149 }
169 150
170 bool TabNodePool::Empty() const { 151 bool TabNodePool::Empty() const {
171 return free_nodes_pool_.empty(); 152 return free_nodes_pool_.empty();
172 } 153 }
173 154
174 bool TabNodePool::Full() { 155 bool TabNodePool::Full() {
175 return nodeid_tabid_map_.empty(); 156 return nodeid_tabid_map_.empty();
176 } 157 }
177 158
178 void TabNodePool::SetMachineTag(const std::string& machine_tag) {
179 machine_tag_ = machine_tag;
180 }
181
182 } // namespace sync_sessions 159 } // namespace sync_sessions
OLDNEW
« no previous file with comments | « components/sync_sessions/tab_node_pool.h ('k') | components/sync_sessions/tab_node_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698