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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_SYNC_ENGINE_GET_COMMIT_IDS_COMMAND_H_ 6 #define CHROME_BROWSER_SYNC_ENGINE_GET_COMMIT_IDS_COMMAND_H_ 7 #pragma once 8 9 #include <utility> 10 #include <vector> 11 12 #include "chrome/browser/sync/engine/syncer_command.h" 13 #include "chrome/browser/sync/engine/syncer_util.h" 14 #include "chrome/browser/sync/sessions/ordered_commit_set.h" 15 #include "chrome/browser/sync/sessions/sync_session.h" 16 17 using std::pair; 18 using std::vector; 19 20 namespace browser_sync { 21 22 class GetCommitIdsCommand : public SyncerCommand { 23 friend class SyncerTest; 24 25 public: 26 explicit GetCommitIdsCommand(int commit_batch_size); 27 virtual ~GetCommitIdsCommand(); 28 29 // SyncerCommand implementation. 30 virtual void ExecuteImpl(sessions::SyncSession* session); 31 32 // Builds a vector of IDs that should be committed. 33 void BuildCommitIds(const vector<int64>& unsynced_handles, 34 syncable::WriteTransaction* write_transaction, 35 const ModelSafeRoutingInfo& routes); 36 37 // TODO(chron): Remove writes from this iterator. As a warning, this 38 // iterator causes writes to entries and so isn't a pure iterator. 39 // It will do Put(IS_UNSYNCED). Refactor this out later. 40 class CommitMetahandleIterator { 41 public: 42 // TODO(chron): Cache ValidateCommitEntry responses across iterators to save 43 // UTF8 conversion and filename checking CommitMetahandleIterator(const vector<int64> & unsynced_handles,syncable::WriteTransaction * write_transaction,sessions::OrderedCommitSet * commit_set)44 CommitMetahandleIterator(const vector<int64>& unsynced_handles, 45 syncable::WriteTransaction* write_transaction, 46 sessions::OrderedCommitSet* commit_set) 47 : write_transaction_(write_transaction), 48 handle_iterator_(unsynced_handles.begin()), 49 unsynced_handles_end_(unsynced_handles.end()), 50 commit_set_(commit_set) { 51 52 // TODO(chron): Remove writes from this iterator. 53 DCHECK(write_transaction_); 54 55 if (Valid() && !ValidateMetahandleForCommit(*handle_iterator_)) 56 Increment(); 57 } ~CommitMetahandleIterator()58 ~CommitMetahandleIterator() {} 59 Current()60 int64 Current() const { 61 DCHECK(Valid()); 62 return *handle_iterator_; 63 } 64 Increment()65 bool Increment() { 66 if (!Valid()) 67 return false; 68 69 for (++handle_iterator_; 70 handle_iterator_ != unsynced_handles_end_; 71 ++handle_iterator_) { 72 if (ValidateMetahandleForCommit(*handle_iterator_)) 73 return true; 74 } 75 76 return false; 77 } 78 Valid()79 bool Valid() const { 80 return !(handle_iterator_ == unsynced_handles_end_); 81 } 82 83 private: ValidateMetahandleForCommit(int64 metahandle)84 bool ValidateMetahandleForCommit(int64 metahandle) { 85 if (commit_set_->HaveCommitItem(metahandle)) 86 return false; 87 88 // We should really not WRITE in this iterator, but we can fix that 89 // later. We should move that somewhere else later. 90 syncable::MutableEntry entry(write_transaction_, 91 syncable::GET_BY_HANDLE, metahandle); 92 VerifyCommitResult verify_result = 93 SyncerUtil::ValidateCommitEntry(&entry); 94 if (verify_result == VERIFY_UNSYNCABLE) { 95 // Drop unsyncable entries. 96 entry.Put(syncable::IS_UNSYNCED, false); 97 } 98 return verify_result == VERIFY_OK; 99 } 100 101 syncable::WriteTransaction* const write_transaction_; 102 vector<int64>::const_iterator handle_iterator_; 103 vector<int64>::const_iterator unsynced_handles_end_; 104 sessions::OrderedCommitSet* commit_set_; 105 106 DISALLOW_COPY_AND_ASSIGN(CommitMetahandleIterator); 107 }; 108 109 private: 110 void AddUncommittedParentsAndTheirPredecessors( 111 syncable::BaseTransaction* trans, 112 syncable::Id parent_id, 113 const ModelSafeRoutingInfo& routes); 114 115 // OrderedCommitSet helpers for adding predecessors in order. 116 // TODO(ncarter): Refactor these so that the |result| parameter goes away, 117 // and AddItem doesn't need to consider two OrderedCommitSets. 118 bool AddItem(syncable::Entry* item, sessions::OrderedCommitSet* result); 119 bool AddItemThenPredecessors(syncable::BaseTransaction* trans, 120 syncable::Entry* item, 121 syncable::IndexedBitField inclusion_filter, 122 sessions::OrderedCommitSet* result); 123 void AddPredecessorsThenItem(syncable::BaseTransaction* trans, 124 syncable::Entry* item, 125 syncable::IndexedBitField inclusion_filter, 126 const ModelSafeRoutingInfo& routes); 127 128 bool IsCommitBatchFull(); 129 130 void AddCreatesAndMoves(const vector<int64>& unsynced_handles, 131 syncable::WriteTransaction* write_transaction, 132 const ModelSafeRoutingInfo& routes); 133 134 void AddDeletes(const vector<int64>& unsynced_handles, 135 syncable::WriteTransaction* write_transaction); 136 137 scoped_ptr<sessions::OrderedCommitSet> ordered_commit_set_; 138 139 int requested_commit_batch_size_; 140 141 DISALLOW_COPY_AND_ASSIGN(GetCommitIdsCommand); 142 }; 143 144 } // namespace browser_sync 145 146 #endif // CHROME_BROWSER_SYNC_ENGINE_GET_COMMIT_IDS_COMMAND_H_ 147