1731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/get_commit_ids_command.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <utility> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_util.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/syncable.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::set; 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::vector; 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::OrderedCommitSet; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::SyncSession; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing sessions::StatusController; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGetCommitIdsCommand::GetCommitIdsCommand(int commit_batch_size) 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : requested_commit_batch_size_(commit_batch_size) {} 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGetCommitIdsCommand::~GetCommitIdsCommand() {} 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetCommitIdsCommand::ExecuteImpl(SyncSession* session) { 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Gather the full set of unsynced items and store it in the session. They 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // are not in the correct order for commit. 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Directory::UnsyncedMetaHandles all_unsynced_handles; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncerUtil::GetUnsyncedEntries(session->write_transaction(), 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &all_unsynced_handles); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StatusController* status = session->status_controller(); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->set_unsynced_handles(all_unsynced_handles); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BuildCommitIds(status->unsynced_handles(), session->write_transaction(), 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch session->routing_info()); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const vector<syncable::Id>& verified_commit_ids = 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->GetAllCommitIds(); 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < verified_commit_ids.size(); i++) 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Debug commit batch result:" << verified_commit_ids[i]; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch status->set_commit_set(*ordered_commit_set_.get()); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetCommitIdsCommand::AddUncommittedParentsAndTheirPredecessors( 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans, 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id parent_id, 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ModelSafeRoutingInfo& routes) { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch using namespace syncable; 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OrderedCommitSet item_dependencies(routes); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Climb the tree adding entries leaf -> root. 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!parent_id.ServerKnows()) { 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Entry parent(trans, GET_BY_ID, parent_id); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(parent.good()) << "Bad user-only parent in item path."; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 handle = parent.Get(META_HANDLE); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ordered_commit_set_->HaveCommitItem(handle) || 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item_dependencies.HaveCommitItem(handle)) { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!AddItemThenPredecessors(trans, &parent, IS_UNSYNCED, 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &item_dependencies)) { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; // Parent was already present in the set. 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent_id = parent.Get(PARENT_ID); 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Reverse what we added to get the correct order. 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->AppendReverse(item_dependencies); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCommitIdsCommand::AddItem(syncable::Entry* item, 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OrderedCommitSet* result) { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 item_handle = item->Get(syncable::META_HANDLE); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (result->HaveCommitItem(item_handle) || 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->HaveCommitItem(item_handle)) { 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->AddCommitItem(item_handle, item->Get(syncable::ID), 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch item->GetModelType()); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCommitIdsCommand::AddItemThenPredecessors( 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans, 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry* item, 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::IndexedBitField inclusion_filter, 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OrderedCommitSet* result) { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!AddItem(item, result)) 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (item->Get(syncable::IS_DEL)) 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; // Deleted items have no predecessors. 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id prev_id = item->Get(syncable::PREV_ID); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!prev_id.IsRoot()) { 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry prev(trans, syncable::GET_BY_ID, prev_id); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(prev.good()) << "Bad id when walking predecessors."; 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!prev.Get(inclusion_filter)) 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!AddItem(&prev, result)) 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prev_id = prev.Get(syncable::PREV_ID); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetCommitIdsCommand::AddPredecessorsThenItem( 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans, 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry* item, 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::IndexedBitField inclusion_filter, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ModelSafeRoutingInfo& routes) { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OrderedCommitSet item_dependencies(routes); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddItemThenPredecessors(trans, item, inclusion_filter, &item_dependencies); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Reverse what we added to get the correct order. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->AppendReverse(item_dependencies); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetCommitIdsCommand::IsCommitBatchFull() { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ordered_commit_set_->Size() >= requested_commit_batch_size_; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetCommitIdsCommand::AddCreatesAndMoves( 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const vector<int64>& unsynced_handles, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::WriteTransaction* write_transaction, 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ModelSafeRoutingInfo& routes) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add moves and creates, and prepend their uncommitted parents. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (CommitMetahandleIterator iterator(unsynced_handles, write_transaction, 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_.get()); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !IsCommitBatchFull() && iterator.Valid(); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator.Increment()) { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 metahandle = iterator.Current(); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry entry(write_transaction, 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::GET_BY_HANDLE, 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metahandle); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry.Get(syncable::IS_DEL)) { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddUncommittedParentsAndTheirPredecessors(write_transaction, 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.Get(syncable::PARENT_ID), routes); 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddPredecessorsThenItem(write_transaction, &entry, 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::IS_UNSYNCED, routes); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It's possible that we overcommitted while trying to expand dependent 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // items. If so, truncate the set down to the allowed size. 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->Truncate(requested_commit_batch_size_); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetCommitIdsCommand::AddDeletes(const vector<int64>& unsynced_handles, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::WriteTransaction* write_transaction) { 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch set<syncable::Id> legal_delete_parents; 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (CommitMetahandleIterator iterator(unsynced_handles, write_transaction, 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_.get()); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !IsCommitBatchFull() && iterator.Valid(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator.Increment()) { 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 metahandle = iterator.Current(); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry entry(write_transaction, syncable::GET_BY_HANDLE, 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metahandle); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry.Get(syncable::IS_DEL)) { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry parent(write_transaction, syncable::GET_BY_ID, 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.Get(syncable::PARENT_ID)); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the parent is deleted and unsynced, then any children of that 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // parent don't need to be added to the delete queue. 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: the parent could be synced if there was an update deleting a 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // folder when we had a deleted all items in it. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We may get more updates, or we may want to delete the entry. 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (parent.good() && 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent.Get(syncable::IS_DEL) && 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch parent.Get(syncable::IS_UNSYNCED)) { 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // However, if an entry is moved, these rules can apply differently. 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the entry was moved, then the destination parent was deleted, 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // then we'll miss it in the roll up. We have to add it in manually. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(chron): Unit test for move / delete cases: 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Case 1: Locally moved, then parent deleted 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Case 2: Server moved, then locally issue recursive delete. 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry.Get(syncable::ID).ServerKnows() && 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.Get(syncable::PARENT_ID) != 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.Get(syncable::SERVER_PARENT_ID)) { 189731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Inserting moved and deleted entry, will be missed by " 190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick "delete roll." << entry.Get(syncable::ID); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->AddCommitItem(metahandle, 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.Get(syncable::ID), 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.GetModelType()); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Skip this entry since it's a child of a parent that will be 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // deleted. The server will unroll the delete and delete the 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // child as well. 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch legal_delete_parents.insert(entry.Get(syncable::PARENT_ID)); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We could store all the potential entries with a particular parent during 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the above scan, but instead we rescan here. This is less efficient, but 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // we're dropping memory alloc/dealloc in favor of linear scans of recently 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // examined entries. 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Scan through the UnsyncedMetaHandles again. If we have a deleted 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // entry, then check if the parent is in legal_delete_parents. 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parent being in legal_delete_parents means for the child: 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a recursive delete is not currently happening (no recent deletes in same 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // folder) 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // parent did expect at least one old deleted child 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // parent was not deleted 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (CommitMetahandleIterator iterator(unsynced_handles, write_transaction, 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_.get()); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !IsCommitBatchFull() && iterator.Valid(); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iterator.Increment()) { 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 metahandle = iterator.Current(); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MutableEntry entry(write_transaction, syncable::GET_BY_HANDLE, 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metahandle); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry.Get(syncable::IS_DEL)) { 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id parent_id = entry.Get(syncable::PARENT_ID); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (legal_delete_parents.count(parent_id)) { 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_->AddCommitItem(metahandle, entry.Get(syncable::ID), 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry.GetModelType()); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetCommitIdsCommand::BuildCommitIds(const vector<int64>& unsynced_handles, 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::WriteTransaction* write_transaction, 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ModelSafeRoutingInfo& routes) { 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ordered_commit_set_.reset(new OrderedCommitSet(routes)); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Commits follow these rules: 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 1. Moves or creates are preceded by needed folder creates, from 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // root to leaf. For folders whose contents are ordered, moves 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and creates appear in order. 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2. Moves/Creates before deletes. 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 3. Deletes, collapsed. 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We commit deleted moves under deleted items as moves when collapsing 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // delete trees. 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add moves and creates, and prepend their uncommitted parents. 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddCreatesAndMoves(unsynced_handles, write_transaction, routes); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add all deletes. 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddDeletes(unsynced_handles, write_transaction); 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 259