Chromium Code Reviews| 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 <algorithm> | |
| 8 #include <vector> | |
| 9 | |
| 7 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| 8 #include "base/logging.h" | 11 #include "base/logging.h" |
| 9 #include "base/stringprintf.h" | 12 #include "base/stringprintf.h" |
| 10 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 11 #include "chrome/browser/sync/profile_sync_service.h" | 14 #include "chrome/browser/sync/profile_sync_service.h" |
| 12 #include "sync/internal_api/public/base/model_type.h" | 15 #include "sync/internal_api/public/base/model_type.h" |
| 13 #include "sync/internal_api/public/read_node.h" | 16 #include "sync/internal_api/public/read_node.h" |
| 14 #include "sync/internal_api/public/write_node.h" | 17 #include "sync/internal_api/public/write_node.h" |
| 15 #include "sync/internal_api/public/write_transaction.h" | 18 #include "sync/internal_api/public/write_transaction.h" |
| 16 | 19 |
| 17 namespace browser_sync { | 20 namespace browser_sync { |
| 18 | 21 |
| 19 static const char kNoSessionsFolderError[] = | 22 static const char kNoSessionsFolderError[] = |
| 20 "Server did not create the top-level sessions node. We " | 23 "Server did not create the top-level sessions node. We " |
| 21 "might be running against an out-of-date server."; | 24 "might be running against an out-of-date server."; |
| 22 | 25 |
| 23 TabNodePool::TabNodePool( | 26 TabNodePool::TabNodePool(ProfileSyncService* sync_service) |
| 24 ProfileSyncService* sync_service) | 27 : max_used_tab_node_id_(-1), |
| 25 : tab_pool_fp_(-1), | 28 tab_pool_fp_(-1), |
| 26 sync_service_(sync_service) { | 29 sync_service_(sync_service) {} |
| 27 } | |
| 28 | 30 |
| 29 TabNodePool::~TabNodePool() {} | 31 TabNodePool::~TabNodePool() {} |
| 30 | 32 |
| 31 // Static | 33 // Static |
| 32 std::string TabNodePool::TabIdToTag( | 34 std::string TabNodePool::TabIdToTag(const std::string machine_tag, |
| 33 const std::string machine_tag, | 35 int32 tab_node_id) { |
| 34 size_t tab_node_id) { | 36 return base::StringPrintf("%s %" PRId32 "", machine_tag.c_str(), tab_node_id); |
| 35 return base::StringPrintf("%s %" PRIuS "", machine_tag.c_str(), tab_node_id); | |
| 36 } | 37 } |
| 37 | 38 |
| 38 void TabNodePool::AddTabNode(int64 sync_id) { | 39 int64 TabNodePool::GetOldSyncNode(const int64 sync_id) { |
| 39 tab_syncid_pool_.resize(tab_syncid_pool_.size() + 1); | 40 if (sync_id > 0) { |
| 40 tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id; | 41 std::vector<int64>::iterator sync_node_iter = |
| 42 std::lower_bound(old_sync_ids.begin(), old_sync_ids.end(), sync_id); | |
| 43 if (sync_node_iter != old_sync_ids.end() && sync_id == *sync_node_iter) { | |
| 44 old_sync_ids.erase(sync_node_iter); | |
| 45 return sync_id; | |
| 46 } | |
| 47 } | |
| 48 return -1; | |
| 49 } | |
| 50 | |
| 51 void TabNodePool::AddTabNode(int64 sync_id, int32 tab_node_id) { | |
| 52 DCHECK_GE(sync_id, 0); | |
| 53 if (max_used_tab_node_id_ < tab_node_id) { | |
| 54 max_used_tab_node_id_ = tab_node_id; | |
| 55 } | |
| 56 | |
| 57 old_sync_ids.push_back(sync_id); | |
| 58 std::sort(old_sync_ids.begin(), old_sync_ids.end()); | |
| 59 } | |
| 60 | |
| 61 void TabNodePool::PurgeOldSyncNodes(std::vector<int64>& used_sync_ids) { | |
| 62 std::sort(used_sync_ids.begin(), used_sync_ids.end()); | |
| 63 std::vector<int64> remaining; | |
| 64 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | |
| 65 for (std::vector<int64>::iterator i = old_sync_ids.begin(); | |
| 66 i != old_sync_ids.end(); | |
| 67 ++i) { | |
| 68 if (std::lower_bound(used_sync_ids.begin(), used_sync_ids.end(), *i) == | |
| 69 used_sync_ids.end()) { | |
| 70 // Delete the node. | |
| 71 syncer::WriteNode tab_node(&trans); | |
| 72 if (tab_node.InitByIdLookup(*i) == syncer::BaseNode::INIT_OK) { | |
| 73 tab_node.Tombstone(); | |
|
Nicolas Zea
2013/05/16 22:59:03
shouldn't these nodes be added to the tab_syncid_p
shashi
2013/05/17 00:29:16
Yes, they should be returned to the free tab pool.
| |
| 74 } | |
| 75 } else { | |
| 76 remaining.push_back(*i); | |
| 77 } | |
| 78 } | |
| 79 old_sync_ids.clear(); | |
| 80 old_sync_ids.swap(remaining); | |
| 41 } | 81 } |
| 42 | 82 |
| 43 int64 TabNodePool::GetFreeTabNode() { | 83 int64 TabNodePool::GetFreeTabNode() { |
| 44 DCHECK_GT(machine_tag_.length(), 0U); | 84 DCHECK_GT(machine_tag_.length(), 0U); |
| 45 if (tab_pool_fp_ == -1) { | 85 if (tab_pool_fp_ == -1) { |
| 46 // Tab pool has no free nodes, allocate new one. | 86 // Tab pool has no free nodes, allocate new one. |
| 47 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); | 87 syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare()); |
| 48 syncer::ReadNode root(&trans); | 88 syncer::ReadNode root(&trans); |
| 49 if (root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS)) != | 89 if (root.InitByTagLookup(syncer::ModelTypeToRootTag(syncer::SESSIONS)) != |
| 50 syncer::BaseNode::INIT_OK) { | 90 syncer::BaseNode::INIT_OK) { |
| 51 LOG(ERROR) << kNoSessionsFolderError; | 91 LOG(ERROR) << kNoSessionsFolderError; |
| 52 return syncer::kInvalidId; | 92 return syncer::kInvalidId; |
| 53 } | 93 } |
| 54 size_t tab_node_id = tab_syncid_pool_.size(); | 94 int32 tab_node_id = ++max_used_tab_node_id_; |
| 55 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); | 95 std::string tab_node_tag = TabIdToTag(machine_tag_, tab_node_id); |
| 56 syncer::WriteNode tab_node(&trans); | 96 syncer::WriteNode tab_node(&trans); |
| 57 syncer::WriteNode::InitUniqueByCreationResult result = | 97 syncer::WriteNode::InitUniqueByCreationResult result = |
| 58 tab_node.InitUniqueByCreation(syncer::SESSIONS, root, tab_node_tag); | 98 tab_node.InitUniqueByCreation(syncer::SESSIONS, root, tab_node_tag); |
| 59 if (result != syncer::WriteNode::INIT_SUCCESS) { | 99 if (result != syncer::WriteNode::INIT_SUCCESS) { |
| 60 LOG(ERROR) << "Could not create new node with tag " | 100 LOG(ERROR) << "Could not create new node with tag " |
| 61 << tab_node_tag << "!"; | 101 << tab_node_tag << "!"; |
| 62 return syncer::kInvalidId; | 102 return syncer::kInvalidId; |
| 63 } | 103 } |
| 64 // We fill the new node with just enough data so that in case of a crash/bug | 104 // 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. | 105 // we can identify the node as our own on re-association and reuse it. |
| 66 tab_node.SetTitle(UTF8ToWide(tab_node_tag)); | 106 tab_node.SetTitle(UTF8ToWide(tab_node_tag)); |
| 67 sync_pb::SessionSpecifics specifics; | 107 sync_pb::SessionSpecifics specifics; |
| 68 specifics.set_session_tag(machine_tag_); | 108 specifics.set_session_tag(machine_tag_); |
| 69 specifics.set_tab_node_id(tab_node_id); | 109 specifics.set_tab_node_id(tab_node_id); |
| 70 tab_node.SetSessionSpecifics(specifics); | 110 tab_node.SetSessionSpecifics(specifics); |
| 71 | 111 |
| 72 // Grow the pool by 1 since we created a new node. We don't actually need | 112 // Grow the pool by 1 since we created a new node. We don't actually need |
| 73 // to put the node's id in the pool now, since the pool is still empty. | 113 // to put the node's id in the pool now, since the pool is still empty. |
| 74 // The id will be added when that tab is closed and the node is freed. | 114 // The id will be added when that tab is closed and the node is freed. |
| 75 tab_syncid_pool_.resize(tab_node_id + 1); | 115 tab_syncid_pool_.resize(tab_syncid_pool_.size() + 1); |
| 76 DVLOG(1) << "Adding sync node " | 116 DVLOG(1) << "Adding sync node " << tab_node.GetId() |
| 77 << tab_node.GetId() << " to tab syncid pool"; | 117 << " to tab syncid pool"; |
| 78 return tab_node.GetId(); | 118 return tab_node.GetId(); |
| 79 } else { | 119 } else { |
| 80 // There are nodes available, grab next free and decrement free pointer. | 120 // There are nodes available, grab next free and decrement free pointer. |
| 81 return tab_syncid_pool_[static_cast<size_t>(tab_pool_fp_--)]; | 121 return tab_syncid_pool_[tab_pool_fp_--]; |
| 82 } | 122 } |
| 83 } | 123 } |
| 84 | 124 |
| 85 void TabNodePool::FreeTabNode(int64 sync_id) { | 125 void TabNodePool::FreeTabNode(int64 sync_id) { |
| 86 // Pool size should always match # of free tab nodes. | 126 // Pool size should always match # of free tab nodes. |
| 87 DCHECK_LT(tab_pool_fp_, static_cast<int64>(tab_syncid_pool_.size())); | 127 DCHECK_LT(tab_pool_fp_, static_cast<int64>(tab_syncid_pool_.size())); |
| 128 DCHECK_GE(max_used_tab_node_id_ + 1, | |
| 129 static_cast<int32>(tab_syncid_pool_.size())); | |
| 88 tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id; | 130 tab_syncid_pool_[static_cast<size_t>(++tab_pool_fp_)] = sync_id; |
| 131 | |
| 89 } | 132 } |
| 90 | 133 |
| 91 } // namespace browser_sync | 134 } // namespace browser_sync |
| OLD | NEW |