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

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

Issue 2499083004: Reland of [Sync] Put session tracker in charge of maintaining local state. (Closed)
Patch Set: Self review Created 4 years 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"
8 #include "base/logging.h" 7 #include "base/logging.h"
9 #include "base/strings/stringprintf.h"
10 #include "components/sync/base/model_type.h" 8 #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" 9 #include "components/sync/protocol/session_specifics.pb.h"
14 #include "components/sync/protocol/sync.pb.h" 10 #include "components/sync/protocol/sync.pb.h"
15 11
16 namespace sync_sessions { 12 namespace sync_sessions {
17 13
18 const size_t TabNodePool::kFreeNodesLowWatermark = 25; 14 const size_t TabNodePool::kFreeNodesLowWatermark = 25;
19 const size_t TabNodePool::kFreeNodesHighWatermark = 100; 15 const size_t TabNodePool::kFreeNodesHighWatermark = 100;
20 16
21 TabNodePool::TabNodePool() : max_used_tab_node_id_(kInvalidTabNodeID) {} 17 TabNodePool::TabNodePool() : max_used_tab_node_id_(kInvalidTabNodeID) {}
22 18
23 // static 19 // static
24 // We start vending tab node IDs at 0. 20 // We start vending tab node IDs at 0.
25 const int TabNodePool::kInvalidTabNodeID = -1; 21 const int TabNodePool::kInvalidTabNodeID = -1;
26 22
27 TabNodePool::~TabNodePool() {} 23 TabNodePool::~TabNodePool() {}
28 24
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) { 25 void TabNodePool::AddTabNode(int tab_node_id) {
36 DCHECK_GT(tab_node_id, kInvalidTabNodeID); 26 DCHECK_GT(tab_node_id, kInvalidTabNodeID);
37 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end()); 27 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end());
38 unassociated_nodes_.insert(tab_node_id); 28 DVLOG(1) << "Adding tab node " << tab_node_id << " to pool.";
39 if (max_used_tab_node_id_ < tab_node_id) 29 if (max_used_tab_node_id_ < tab_node_id)
skym 2016/12/03 01:20:46 do you think std::max would be more clear? max_us
Nicolas Zea 2016/12/06 01:32:55 Done.
40 max_used_tab_node_id_ = tab_node_id; 30 max_used_tab_node_id_ = tab_node_id;
31 free_nodes_pool_.insert(tab_node_id);
41 } 32 }
42 33
43 void TabNodePool::AssociateTabNode(int tab_node_id, SessionID::id_type tab_id) { 34 void TabNodePool::AssociateTabNode(int tab_node_id, SessionID::id_type tab_id) {
44 DCHECK_GT(tab_node_id, kInvalidTabNodeID); 35 DCHECK_GT(tab_node_id, kInvalidTabNodeID);
45 // Remove sync node if it is in unassociated nodes pool. 36 DCHECK_GT(tab_id, kInvalidTabID);
46 std::set<int>::iterator u_it = unassociated_nodes_.find(tab_node_id); 37
47 if (u_it != unassociated_nodes_.end()) { 38 // This is a new node association, the sync node should be free.
48 unassociated_nodes_.erase(u_it); 39 // Remove node from free node pool and then associate it with the tab.
49 } else { 40 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. 41 DCHECK(it != free_nodes_pool_.end());
51 // Remove node from free node pool and then associate it with the tab. 42 free_nodes_pool_.erase(it);
52 std::set<int>::iterator it = free_nodes_pool_.find(tab_node_id); 43
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()); 44 DCHECK(nodeid_tabid_map_.find(tab_node_id) == nodeid_tabid_map_.end());
45 DVLOG(1) << "Associating tab node " << tab_node_id << " with tab " << tab_id;
57 nodeid_tabid_map_[tab_node_id] = tab_id; 46 nodeid_tabid_map_[tab_node_id] = tab_id;
47 tabid_nodeid_map_[tab_id] = tab_node_id;
58 } 48 }
59 49
60 int TabNodePool::GetFreeTabNode(syncer::SyncChangeList* append_changes) { 50 bool TabNodePool::GetTabNodeForTab(SessionID::id_type tab_id,
61 DCHECK_GT(machine_tag_.length(), 0U); 51 int* tab_node_id) {
62 DCHECK(append_changes); 52 if (tabid_nodeid_map_.find(tab_id) != tabid_nodeid_map_.end()) {
53 *tab_node_id = tabid_nodeid_map_[tab_id];
54 return true;
55 }
56
63 if (free_nodes_pool_.empty()) { 57 if (free_nodes_pool_.empty()) {
64 // Tab pool has no free nodes, allocate new one. 58 // Tab pool has no free nodes, allocate new one.
65 int tab_node_id = ++max_used_tab_node_id_; 59 *tab_node_id = ++max_used_tab_node_id_;
66 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id);
67
68 // We fill the new node with just enough data so that in case of a crash/bug
69 // we can identify the node as our own on re-association and reuse it.
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 60
78 // Grow the pool by 1 since we created a new node. 61 // 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"; 62 DVLOG(1) << "Adding tab node " << *tab_node_id << " to pool";
80 free_nodes_pool_.insert(tab_node_id); 63 free_nodes_pool_.insert(*tab_node_id);
skym 2016/12/03 01:20:46 This is kind of odd that you put it in free_nodes
Nicolas Zea 2016/12/06 01:32:55 It allows for consistency. AssociateTabNode assume
81 return tab_node_id; 64
65 AssociateTabNode(*tab_node_id, tab_id);
66 return false;
82 } else { 67 } else {
83 // Return the next free node. 68 // Return the next free node.
84 return *free_nodes_pool_.begin(); 69 *tab_node_id = *free_nodes_pool_.begin();
70 AssociateTabNode(*tab_node_id, tab_id);
71 return true;
85 } 72 }
86 } 73 }
87 74
88 void TabNodePool::FreeTabNode(int tab_node_id, 75 void TabNodePool::FreeTab(int tab_id) {
89 syncer::SyncChangeList* append_changes) { 76 DCHECK_GT(tab_id, kInvalidTabID);
90 DCHECK(append_changes); 77 TabIDToTabNodeIDMap::iterator it = tabid_nodeid_map_.find(tab_id);
91 TabNodeIDToTabIDMap::iterator it = nodeid_tabid_map_.find(tab_node_id); 78 if (it == tabid_nodeid_map_.end()) {
92 DCHECK(it != nodeid_tabid_map_.end()); 79 return; // Already freed.
93 nodeid_tabid_map_.erase(it); 80 }
94 FreeTabNodeInternal(tab_node_id, append_changes);
95 }
96 81
97 void TabNodePool::FreeTabNodeInternal(int tab_node_id, 82 int tab_node_id = it->second;
98 syncer::SyncChangeList* append_changes) { 83 DVLOG(1) << "Freeing tab " << tab_id << " at node " << tab_node_id;
99 DCHECK(free_nodes_pool_.find(tab_node_id) == free_nodes_pool_.end()); 84 nodeid_tabid_map_.erase(nodeid_tabid_map_.find(tab_node_id));
100 DCHECK(append_changes); 85 tabid_nodeid_map_.erase(it);
101 free_nodes_pool_.insert(tab_node_id); 86 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 } 87 }
125 88
126 void TabNodePool::ReassociateTabNode(int tab_node_id, 89 void TabNodePool::ReassociateTabNode(int tab_node_id,
127 SessionID::id_type tab_id) { 90 SessionID::id_type tab_id) {
128 // Remove from list of unassociated sync_nodes if present. 91 DCHECK_GT(tab_node_id, kInvalidTabNodeID);
129 std::set<int>::iterator it = unassociated_nodes_.find(tab_node_id); 92 DCHECK_GT(tab_id, kInvalidTabID);
130 if (it != unassociated_nodes_.end()) { 93
131 unassociated_nodes_.erase(it); 94 auto tabid_it = tabid_nodeid_map_.find(tab_id);
95 if (tabid_it != tabid_nodeid_map_.end()) {
96 if (tabid_it->second == tab_node_id) {
97 return; // Already associated properly.
98 } else {
99 // Another node is already associated with this tab. Free it.
100 FreeTab(tab_id);
101 }
102 }
103
104 auto nodeid_it = nodeid_tabid_map_.find(tab_node_id);
105 if (nodeid_it != nodeid_tabid_map_.end()) {
106 // This node was already associated with another tab. Free it.
107 FreeTab(nodeid_it->second);
132 } else { 108 } else {
133 // tab_node_id must be an already associated node. 109 // This is a new tab node. Add it before association.
134 DCHECK(nodeid_tabid_map_.find(tab_node_id) != nodeid_tabid_map_.end()); 110 AddTabNode(tab_node_id);
135 } 111 }
136 nodeid_tabid_map_[tab_node_id] = tab_id; 112
113 AssociateTabNode(tab_node_id, tab_id);
137 } 114 }
138 115
139 SessionID::id_type TabNodePool::GetTabIdFromTabNodeId(int tab_node_id) const { 116 SessionID::id_type TabNodePool::GetTabIdFromTabNodeId(int tab_node_id) const {
140 TabNodeIDToTabIDMap::const_iterator it = nodeid_tabid_map_.find(tab_node_id); 117 TabNodeIDToTabIDMap::const_iterator it = nodeid_tabid_map_.find(tab_node_id);
141 if (it != nodeid_tabid_map_.end()) { 118 if (it != nodeid_tabid_map_.end()) {
142 return it->second; 119 return it->second;
143 } 120 }
144 return kInvalidTabID; 121 return kInvalidTabID;
145 } 122 }
146 123
147 void TabNodePool::DeleteUnassociatedTabNodes( 124 void TabNodePool::CleanupTabNodes(std::set<int>* deleted_node_ids) {
148 syncer::SyncChangeList* append_changes) { 125 // If number of free nodes exceed kFreeNodesHighWatermark,
149 for (std::set<int>::iterator it = unassociated_nodes_.begin(); 126 // delete sync nodes till number reaches kFreeNodesLowWatermark.
150 it != unassociated_nodes_.end();) { 127 // Note: This logic is to mitigate temporary disassociation issues with old
151 FreeTabNodeInternal(*it, append_changes); 128 // clients: http://crbug.com/259918. Newer versions do not need this.
152 unassociated_nodes_.erase(it++); 129 if (free_nodes_pool_.size() > kFreeNodesHighWatermark) {
130 for (std::set<int>::iterator free_it = free_nodes_pool_.begin();
131 free_it != free_nodes_pool_.end();) {
132 deleted_node_ids->insert(*free_it);
133 free_nodes_pool_.erase(free_it++);
134 if (free_nodes_pool_.size() <= kFreeNodesLowWatermark) {
135 return;
136 }
137 }
153 } 138 }
154 DCHECK(unassociated_nodes_.empty());
155 } 139 }
156 140
157 // Clear tab pool. 141 // Clear tab pool.
158 void TabNodePool::Clear() { 142 void TabNodePool::Clear() {
159 unassociated_nodes_.clear();
160 free_nodes_pool_.clear(); 143 free_nodes_pool_.clear();
161 nodeid_tabid_map_.clear(); 144 nodeid_tabid_map_.clear();
145 tabid_nodeid_map_.clear();
162 max_used_tab_node_id_ = kInvalidTabNodeID; 146 max_used_tab_node_id_ = kInvalidTabNodeID;
163 } 147 }
164 148
165 size_t TabNodePool::Capacity() const { 149 size_t TabNodePool::Capacity() const {
166 return nodeid_tabid_map_.size() + unassociated_nodes_.size() + 150 return nodeid_tabid_map_.size() + free_nodes_pool_.size();
167 free_nodes_pool_.size();
168 } 151 }
169 152
170 bool TabNodePool::Empty() const { 153 bool TabNodePool::Empty() const {
171 return free_nodes_pool_.empty(); 154 return free_nodes_pool_.empty();
172 } 155 }
173 156
174 bool TabNodePool::Full() { 157 bool TabNodePool::Full() {
175 return nodeid_tabid_map_.empty(); 158 return nodeid_tabid_map_.empty();
176 } 159 }
177 160
178 void TabNodePool::SetMachineTag(const std::string& machine_tag) {
179 machine_tag_ = machine_tag;
180 }
181
182 } // namespace sync_sessions 161 } // namespace sync_sessions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698