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

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

Issue 337037: Make some improvements to sync model associator:... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month 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
« no previous file with comments | « no previous file | chrome/browser/sync/profile_sync_service_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2009 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 #if defined(BROWSER_SYNC) 5 #if defined(BROWSER_SYNC)
6 6
7 #include "chrome/browser/sync/glue/model_associator.h" 7 #include "chrome/browser/sync/glue/model_associator.h"
8 8
9 #include <stack> 9 #include <stack>
10 10
11 #include "base/hash_tables.h"
11 #include "base/message_loop.h" 12 #include "base/message_loop.h"
12 #include "base/task.h" 13 #include "base/task.h"
13 #include "chrome/browser/bookmarks/bookmark_model.h" 14 #include "chrome/browser/bookmarks/bookmark_model.h"
14 #include "chrome/browser/sync/engine/syncapi.h" 15 #include "chrome/browser/sync/engine/syncapi.h"
15 #include "chrome/browser/sync/profile_sync_service.h" 16 #include "chrome/browser/sync/profile_sync_service.h"
16 17
17 namespace browser_sync { 18 namespace browser_sync {
18 19
19 // The sync protocol identifies top-level entities by means of well-known tags, 20 // The sync protocol identifies top-level entities by means of well-known tags,
20 // which should not be confused with titles. Each tag corresponds to a 21 // which should not be confused with titles. Each tag corresponds to a
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 BookmarkNodesSet::iterator iter = child_nodes_.find(&temp_node); 106 BookmarkNodesSet::iterator iter = child_nodes_.find(&temp_node);
106 if (iter != child_nodes_.end()) { 107 if (iter != child_nodes_.end()) {
107 result = *iter; 108 result = *iter;
108 // Remove the matched node so we don't match with it again. 109 // Remove the matched node so we don't match with it again.
109 child_nodes_.erase(iter); 110 child_nodes_.erase(iter);
110 } 111 }
111 112
112 return result; 113 return result;
113 } 114 }
114 115
116 // Helper class to build an index of bookmark nodes by their IDs.
117 class BookmarkNodeIdIndex {
118 public:
119 BookmarkNodeIdIndex() { }
120 ~BookmarkNodeIdIndex() { }
121
122 // Adds the given bookmark node and all its descendants to the ID index.
123 // Does nothing if node is NULL.
124 void AddAll(const BookmarkNode* node);
125
126 // Finds the bookmark node with the given ID.
127 // Returns NULL if none exists with the given id.
128 const BookmarkNode* Find(int64 id) const;
129
130 // Returns the count of nodes in the index.
131 size_t count() const { return node_index_.size(); }
132
133 private:
134 typedef base::hash_map<int64, const BookmarkNode*> BookmarkIdMap;
135 // Map that holds nodes indexed by their ids.
136 BookmarkIdMap node_index_;
137
138 DISALLOW_COPY_AND_ASSIGN(BookmarkNodeIdIndex);
139 };
140
141 void BookmarkNodeIdIndex::AddAll(const BookmarkNode* node) {
142 if (!node)
143 return;
144
145 node_index_[node->id()] = node;
146
147 if (!node->is_folder())
148 return;
149
150 for (int i = 0; i < node->GetChildCount(); ++i)
151 AddAll(node->GetChild(i));
152 }
153
154 const BookmarkNode* BookmarkNodeIdIndex::Find(int64 id) const {
155 BookmarkIdMap::const_iterator iter = node_index_.find(id);
156 return iter == node_index_.end() ? NULL : iter->second;
157 }
158
115 ModelAssociator::ModelAssociator(ProfileSyncService* sync_service) 159 ModelAssociator::ModelAssociator(ProfileSyncService* sync_service)
116 : sync_service_(sync_service), 160 : sync_service_(sync_service),
117 task_pending_(false) { 161 task_pending_(false) {
118 DCHECK(sync_service_); 162 DCHECK(sync_service_);
119 } 163 }
120 164
121 void ModelAssociator::ClearAll() { 165 void ModelAssociator::ClearAll() {
122 id_map_.clear(); 166 id_map_.clear();
123 id_map_inverse_.clear(); 167 id_map_inverse_.clear();
124 dirty_associations_sync_ids_.clear(); 168 dirty_associations_sync_ids_.clear();
(...skipping 24 matching lines...) Expand all
149 return false; 193 return false;
150 DCHECK(sync_node->GetId() == sync_id); 194 DCHECK(sync_node->GetId() == sync_id);
151 return true; 195 return true;
152 } 196 }
153 197
154 const BookmarkNode* ModelAssociator::GetBookmarkNodeFromSyncId(int64 sync_id) { 198 const BookmarkNode* ModelAssociator::GetBookmarkNodeFromSyncId(int64 sync_id) {
155 int64 node_id; 199 int64 node_id;
156 if (!GetBookmarkIdFromSyncId(sync_id, &node_id)) 200 if (!GetBookmarkIdFromSyncId(sync_id, &node_id))
157 return false; 201 return false;
158 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel(); 202 BookmarkModel* model = sync_service_->profile()->GetBookmarkModel();
203 // TODO(munjal): Fix issue 26141.
159 return model->GetNodeByID(node_id); 204 return model->GetNodeByID(node_id);
160 } 205 }
161 206
162 void ModelAssociator::AssociateIds(int64 node_id, int64 sync_id) { 207 void ModelAssociator::AssociateIds(int64 node_id, int64 sync_id) {
163 DCHECK_NE(sync_id, sync_api::kInvalidId); 208 DCHECK_NE(sync_id, sync_api::kInvalidId);
164 DCHECK(id_map_.find(node_id) == id_map_.end()); 209 DCHECK(id_map_.find(node_id) == id_map_.end());
165 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); 210 DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end());
166 id_map_[node_id] = sync_id; 211 id_map_[node_id] = sync_id;
167 id_map_inverse_[sync_id] = node_id; 212 id_map_inverse_[sync_id] = node_id;
168 dirty_associations_sync_ids_.insert(sync_id); 213 dirty_associations_sync_ids_.insert(sync_id);
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 // create the tagged nodes on demand, and the order in which we probe for 491 // create the tagged nodes on demand, and the order in which we probe for
447 // them here will impact their positional ordering in that case. 492 // them here will impact their positional ordering in that case.
448 int64 bookmark_bar_id; 493 int64 bookmark_bar_id;
449 if (!GetSyncIdForTaggedNode(WideToUTF16(kBookmarkBarTag), &bookmark_bar_id)) { 494 if (!GetSyncIdForTaggedNode(WideToUTF16(kBookmarkBarTag), &bookmark_bar_id)) {
450 // We should always be able to find the permanent nodes. 495 // We should always be able to find the permanent nodes.
451 sync_service_->OnUnrecoverableError(); 496 sync_service_->OnUnrecoverableError();
452 return false; 497 return false;
453 } 498 }
454 int64 other_bookmarks_id; 499 int64 other_bookmarks_id;
455 if (!GetSyncIdForTaggedNode(WideToUTF16(kOtherBookmarksTag), 500 if (!GetSyncIdForTaggedNode(WideToUTF16(kOtherBookmarksTag),
456 &other_bookmarks_id)) { 501 &other_bookmarks_id)) {
457 // We should always be able to find the permanent nodes. 502 // We should always be able to find the permanent nodes.
458 sync_service_->OnUnrecoverableError(); 503 sync_service_->OnUnrecoverableError();
459 return false; 504 return false;
460 } 505 }
461 506
507 // Build a bookmark node ID index since we are going to repeatedly search for
508 // bookmark nodes by their IDs.
509 BookmarkNodeIdIndex id_index;
510 id_index.AddAll(model->GetBookmarkBarNode());
511 id_index.AddAll(model->other_node());
512
462 std::stack<int64> dfs_stack; 513 std::stack<int64> dfs_stack;
463 dfs_stack.push(other_bookmarks_id); 514 dfs_stack.push(other_bookmarks_id);
464 dfs_stack.push(bookmark_bar_id); 515 dfs_stack.push(bookmark_bar_id);
465 516
466 sync_api::ReadTransaction trans( 517 sync_api::ReadTransaction trans(
467 sync_service_->backend()->GetUserShareHandle()); 518 sync_service_->backend()->GetUserShareHandle());
468 519
520 // Count total number of nodes in sync model so that we can compare that
521 // with the total number of nodes in the bookmark model.
522 int64 sync_node_count = 0;
469 while (!dfs_stack.empty()) { 523 while (!dfs_stack.empty()) {
470 int64 parent_id = dfs_stack.top(); 524 int64 parent_id = dfs_stack.top();
471 dfs_stack.pop(); 525 dfs_stack.pop();
526 ++sync_node_count;
472 sync_api::ReadNode sync_parent(&trans); 527 sync_api::ReadNode sync_parent(&trans);
473 if (!sync_parent.InitByIdLookup(parent_id)) { 528 if (!sync_parent.InitByIdLookup(parent_id)) {
474 sync_service_->OnUnrecoverableError(); 529 sync_service_->OnUnrecoverableError();
475 return false; 530 return false;
476 } 531 }
477 532
478 int64 external_id = sync_parent.GetExternalId(); 533 int64 external_id = sync_parent.GetExternalId();
479 if (external_id == 0) 534 if (external_id == 0)
480 return false; 535 return false;
481 536
482 const BookmarkNode* node = model->GetNodeByID(external_id); 537 const BookmarkNode* node = id_index.Find(external_id);
483 if (!node) 538 if (!node)
484 return false; 539 return false;
485 540
486 // Don't try to call NodesMatch on permanent nodes like bookmark bar and 541 // Don't try to call NodesMatch on permanent nodes like bookmark bar and
487 // other bookmarks. They are not expected to match. 542 // other bookmarks. They are not expected to match.
488 if (node != model->GetBookmarkBarNode() && 543 if (node != model->GetBookmarkBarNode() &&
489 node != model->other_node() && 544 node != model->other_node() &&
490 !NodesMatch(node, &sync_parent)) 545 !NodesMatch(node, &sync_parent))
491 return false; 546 return false;
492 547
493 AssociateIds(external_id, sync_parent.GetId()); 548 AssociateIds(external_id, sync_parent.GetId());
494 549
495 // Add all children of the current node to the stack. 550 // Add all children of the current node to the stack.
496 int64 child_id = sync_parent.GetFirstChildId(); 551 int64 child_id = sync_parent.GetFirstChildId();
497 while (child_id != sync_api::kInvalidId) { 552 while (child_id != sync_api::kInvalidId) {
498 dfs_stack.push(child_id); 553 dfs_stack.push(child_id);
499 sync_api::ReadNode child_node(&trans); 554 sync_api::ReadNode child_node(&trans);
500 if (!child_node.InitByIdLookup(child_id)) { 555 if (!child_node.InitByIdLookup(child_id)) {
501 sync_service_->OnUnrecoverableError(); 556 sync_service_->OnUnrecoverableError();
502 return false; 557 return false;
503 } 558 }
504 child_id = child_node.GetSuccessorId(); 559 child_id = child_node.GetSuccessorId();
505 } 560 }
506 } 561 }
507 DCHECK(dfs_stack.empty()); 562 DCHECK(dfs_stack.empty());
508 return true; 563
564 // It's possible that the number of nodes in the bookmark model is not the
565 // same as number of nodes in the sync model. This can happen when the sync
566 // model doesn't get a chance to persist its changes, for example when
567 // Chrome does not shut down gracefully. In such cases we can't trust the
568 // loaded associations.
569 return sync_node_count == id_index.count();
509 } 570 }
510 571
511 } // namespace browser_sync 572 } // namespace browser_sync
512 573
513 #endif // defined(BROWSER_SYNC) 574 #endif // defined(BROWSER_SYNC)
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/sync/profile_sync_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698