OLD | NEW |
---|---|
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 |
OLD | NEW |