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

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

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