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

Side by Side Diff: chrome/browser/sync/glue/tab_node_pool.cc

Issue 16421003: [Sync] Add logic to reassociate tab nodes after restart. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix win compile, rename uint -> size_t. Created 7 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "chrome/browser/sync/glue/tab_node_pool.h" 5 #include "chrome/browser/sync/glue/tab_node_pool.h"
6 6
7 #include "base/format_macros.h" 7 #include "base/format_macros.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/stringprintf.h" 9 #include "base/stringprintf.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/sync/profile_sync_service.h" 11 #include "chrome/browser/sync/profile_sync_service.h"
12 #include "sync/internal_api/public/base/model_type.h" 12 #include "sync/internal_api/public/base/model_type.h"
13 #include "sync/internal_api/public/read_node.h" 13 #include "sync/internal_api/public/read_node.h"
14 #include "sync/internal_api/public/write_node.h" 14 #include "sync/internal_api/public/write_node.h"
15 #include "sync/internal_api/public/write_transaction.h" 15 #include "sync/internal_api/public/write_transaction.h"
16 16
17 namespace browser_sync { 17 namespace browser_sync {
18 18
19 static const char kNoSessionsFolderError[] = 19 static const char kNoSessionsFolderError[] =
20 "Server did not create the top-level sessions node. We " 20 "Server did not create the top-level sessions node. We "
21 "might be running against an out-of-date server."; 21 "might be running against an out-of-date server.";
22 22
23 TabNodePool::TabNodePool( 23 static const size_t kMaxNumberOfFreeNodes = 25;
24 ProfileSyncService* sync_service) 24
25 : tab_pool_fp_(-1), 25 TabNodePool::TabNodePool(ProfileSyncService* sync_service)
26 sync_service_(sync_service) { 26 : max_used_tab_node_id_(0), sync_service_(sync_service) {}
27 }
28 27
29 TabNodePool::~TabNodePool() {} 28 TabNodePool::~TabNodePool() {}
30 29
31 // Static 30 // Static
32 std::string TabNodePool::TabIdToTag( 31 std::string TabNodePool::TabIdToTag(
33 const std::string machine_tag, 32 const std::string machine_tag,
34 size_t tab_node_id) { 33 size_t tab_node_id) {
35 return base::StringPrintf("%s %" PRIuS "", machine_tag.c_str(), tab_node_id); 34 return base::StringPrintf("%s %" PRIuS "", machine_tag.c_str(), tab_node_id);
36 } 35 }
37 36
38 void TabNodePool::AddTabNode(int64 sync_id) { 37 void TabNodePool::AddTabNode(int64 sync_id,
39 tab_syncid_pool_.resize(tab_syncid_pool_.size() + 1); 38 const SessionID& tab_id,
40 tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id; 39 size_t tab_node_id) {
40 DCHECK_GT(sync_id, 0);
Nicolas Zea 2013/06/19 21:35:33 DCHECK_GT(sync_id, syncer::kInvalidId); also DCHE
shashi 2013/06/20 00:49:32 Done.
41 DCHECK(tab_syncid_tab_id_map_.find(sync_id) == tab_syncid_tab_id_map_.end());
42 tab_syncid_tab_id_map_[sync_id] = tab_id.id();
43 if (max_used_tab_node_id_ < tab_node_id)
44 max_used_tab_node_id_ = tab_node_id;
45 }
46
47 void TabNodePool::AssociateTabNode(int64 sync_id, SessionID::id_type tab_id) {
48 DCHECK_GT(sync_id, 0);
49 // Remove node from free node pool and associate it with tab.
50 std::set<int64>::iterator it = free_nodes_pool_.find(sync_id);
51 DCHECK(it != free_nodes_pool_.end());
52 if (it != free_nodes_pool_.end()) {
Nicolas Zea 2013/06/19 21:35:33 nit: don't handle DCHECK's. Remove the if statemen
shashi 2013/06/20 00:49:32 Done.
53 free_nodes_pool_.erase(it);
54 }
55 DCHECK(tab_syncid_tab_id_map_.find(sync_id) == tab_syncid_tab_id_map_.end());
56 tab_syncid_tab_id_map_[sync_id] = tab_id;
41 } 57 }
42 58
43 int64 TabNodePool::GetFreeTabNode() { 59 int64 TabNodePool::GetFreeTabNode() {
44 DCHECK_GT(machine_tag_.length(), 0U); 60 DCHECK_GT(machine_tag_.length(), 0U);
45 if (tab_pool_fp_ == -1) { 61 if (free_nodes_pool_.empty()) {
46 // Tab pool has no free nodes, allocate new one. 62 // Tab pool has no free nodes, allocate new one.
47 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); 63 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
48 syncer::ReadNode root(&trans); 64 syncer::ReadNode root(&trans);
49 if (root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS)) != 65 if (root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS)) !=
50 syncer::BaseNode::INIT_OK) { 66 syncer::BaseNode::INIT_OK) {
51 LOG(ERROR) << kNoSessionsFolderError; 67 LOG(ERROR) << kNoSessionsFolderError;
52 return syncer::kInvalidId; 68 return syncer::kInvalidId;
53 } 69 }
54 size_t tab_node_id = tab_syncid_pool_.size(); 70 size_t tab_node_id = ++max_used_tab_node_id_;
55 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); 71 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id);
56 syncer::WriteNode tab_node(&trans); 72 syncer::WriteNode tab_node(&trans);
57 syncer::WriteNode::InitUniqueByCreationResult result = 73 syncer::WriteNode::InitUniqueByCreationResult result =
58 tab_node.InitUniqueByCreation(syncer::SESSIONS, root, tab_node_tag); 74 tab_node.InitUniqueByCreation(syncer::SESSIONS, root, tab_node_tag);
59 if (result != syncer::WriteNode::INIT_SUCCESS) { 75 if (result != syncer::WriteNode::INIT_SUCCESS) {
60 LOG(ERROR) << "Could not create new node with tag " 76 LOG(ERROR) << "Could not create new node with tag "
61 << tab_node_tag << "!"; 77 << tab_node_tag << "!";
62 return syncer::kInvalidId; 78 return syncer::kInvalidId;
63 } 79 }
64 // We fill the new node with just enough data so that in case of a crash/bug 80 // We fill the new node with just enough data so that in case of a crash/bug
65 // we can identify the node as our own on re-association and reuse it. 81 // we can identify the node as our own on re-association and reuse it.
66 tab_node.SetTitle(UTF8ToWide(tab_node_tag)); 82 tab_node.SetTitle(UTF8ToWide(tab_node_tag));
67 sync_pb::SessionSpecifics specifics; 83 sync_pb::SessionSpecifics specifics;
68 specifics.set_session_tag(machine_tag_); 84 specifics.set_session_tag(machine_tag_);
69 specifics.set_tab_node_id(tab_node_id); 85 specifics.set_tab_node_id(tab_node_id);
70 tab_node.SetSessionSpecifics(specifics); 86 tab_node.SetSessionSpecifics(specifics);
71 87
72 // Grow the pool by 1 since we created a new node. We don't actually need 88 // Grow the pool by 1 since we created a new node.
73 // to put the node's id in the pool now, since the pool is still empty. 89 DVLOG(1) << "Adding sync node " << tab_node.GetId()
74 // The id will be added when that tab is closed and the node is freed. 90 << " to tab syncid pool";
75 tab_syncid_pool_.resize(tab_node_id + 1); 91 free_nodes_pool_.insert(tab_node.GetId());
76 DVLOG(1) << "Adding sync node "
77 << tab_node.GetId() << " to tab syncid pool";
78 return tab_node.GetId(); 92 return tab_node.GetId();
79 } else { 93 } else {
80 // There are nodes available, grab next free and decrement free pointer. 94 // Return the next free node.
81 return tab_syncid_pool_[static_cast<size_t>(tab_pool_fp_--)]; 95 return *free_nodes_pool_.begin();
82 } 96 }
83 } 97 }
84 98
85 void TabNodePool::FreeTabNode(int64 sync_id) { 99 void TabNodePool::FreeTabNode(int64 sync_id) {
86 // Pool size should always match # of free tab nodes. 100 SyncIDToTabIDMap::iterator it = tab_syncid_tab_id_map_.find(sync_id);
87 DCHECK_LT(tab_pool_fp_, static_cast<int64>(tab_syncid_pool_.size())); 101 DCHECK(it != tab_syncid_tab_id_map_.end());
88 tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id; 102 if (it != tab_syncid_tab_id_map_.end()) {
Nicolas Zea 2013/06/19 21:35:33 here too
shashi 2013/06/20 00:49:32 Done.
103 tab_syncid_tab_id_map_.erase(it);
104 }
105 // If number of free nodes exceed number of maximum allowed free nodes,
106 // delete the sync node.
107 if (free_nodes_pool_.size() < kMaxNumberOfFreeNodes) {
108 free_nodes_pool_.insert(sync_id);
109 } else {
110 if (free_nodes_pool_.find(sync_id) == free_nodes_pool_.end()) {
Nicolas Zea 2013/06/19 21:35:33 This also seems like it should just be DCHECK'd. D
shashi 2013/06/20 00:49:32 Done, moved the DCHECK about since this constraint
111 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
112 syncer::WriteNode tab_node(&trans);
113 if (tab_node.InitByIdLookup(sync_id) != syncer::BaseNode::INIT_OK) {
114 LOG(ERROR) << "Could not find sync node with id: " << sync_id;
115 return;
116 }
117 tab_node.Tombstone();
118 }
119 }
120 }
121
122 bool TabNodePool::ReassociateTabNode(int64 sync_id, SessionID::id_type tab_id) {
123 SyncIDToTabIDMap::iterator it = tab_syncid_tab_id_map_.find(sync_id);
124 if (it != tab_syncid_tab_id_map_.end()) {
125 tab_syncid_tab_id_map_[sync_id] = tab_id;
126 return true;
127 }
128 return false;
129 }
130
131 SessionID::id_type TabNodePool::TabIDForSyncID(int64 sync_id) const {
132 SyncIDToTabIDMap::const_iterator it = tab_syncid_tab_id_map_.find(sync_id);
133 if (it != tab_syncid_tab_id_map_.end()) {
134 return it->second;
135 }
136 return kInvalidTabID;
137 }
138
139 void TabNodePool::FreeUnusedTabNodes(const std::set<int64>& used_sync_ids) {
Nicolas Zea 2013/06/19 21:35:33 Is this method still necessary? Can't the caller j
shashi 2013/06/20 00:49:32 This method is needed so that we delete nodes for
140 for (SyncIDToTabIDMap::iterator it = tab_syncid_tab_id_map_.begin();
141 it != tab_syncid_tab_id_map_.end();) {
142 if (used_sync_ids.find(it->first) == used_sync_ids.end()) {
143 // This sync node is not used, return it to free node pool.
144 int64 sync_id = it->first;
145 ++it;
146 FreeTabNode(sync_id);
147 } else {
148 ++it;
149 }
150 }
89 } 151 }
90 152
91 } // namespace browser_sync 153 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698