1 // Copyright (c) 2011 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 // Utility functions manipulating syncable::Entries, intended for use by the 6 // syncer. 7 8 #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_UTIL_H_ 9 #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_UTIL_H_ 10 #pragma once 11 12 #include <set> 13 #include <string> 14 #include <vector> 15 16 #include "build/build_config.h" 17 #include "chrome/browser/sync/engine/syncer.h" 18 #include "chrome/browser/sync/engine/syncer_types.h" 19 #include "chrome/browser/sync/syncable/syncable.h" 20 #include "chrome/browser/sync/syncable/syncable_id.h" 21 22 namespace browser_sync { 23 24 class Cryptographer; 25 class SyncEntity; 26 27 class SyncerUtil { 28 public: 29 static void ChangeEntryIDAndUpdateChildren( 30 syncable::WriteTransaction* trans, 31 syncable::MutableEntry* entry, 32 const syncable::Id& new_id, 33 syncable::Directory::ChildHandles* children); 34 35 // Returns the number of unsynced entries. 36 static int GetUnsyncedEntries(syncable::BaseTransaction* trans, 37 std::vector<int64> *handles); 38 39 static void ChangeEntryIDAndUpdateChildren(syncable::WriteTransaction* trans, 40 syncable::MutableEntry* entry, 41 const syncable::Id& new_id); 42 43 // If the server sent down a client-tagged entry, or an entry whose 44 // commit response was lost, it is necessary to update a local entry 45 // with an ID that doesn't match the ID of the update. Here, we 46 // find the ID of such an entry, if it exists. This function may 47 // determine that |server_entry| should be dropped; if so, it returns 48 // the null ID -- callers must handle this case. When update application 49 // should proceed normally with a new local entry, this function will 50 // return server_entry.id(); the caller must create an entry with that 51 // ID. This function does not alter the database. 52 static syncable::Id FindLocalIdToUpdate( 53 syncable::BaseTransaction* trans, 54 const SyncEntity& server_entry); 55 56 static UpdateAttemptResponse AttemptToUpdateEntry( 57 syncable::WriteTransaction* const trans, 58 syncable::MutableEntry* const entry, 59 ConflictResolver* resolver, 60 Cryptographer* cryptographer); 61 62 // Pass in name to avoid redundant UTF8 conversion. 63 static void UpdateServerFieldsFromUpdate( 64 syncable::MutableEntry* local_entry, 65 const SyncEntity& server_entry, 66 const std::string& name); 67 68 // Creates a new Entry iff no Entry exists with the given id. 69 static void CreateNewEntry(syncable::WriteTransaction *trans, 70 const syncable::Id& id); 71 72 static bool ServerAndLocalEntriesMatch(syncable::Entry* entry); 73 74 static void SplitServerInformationIntoNewEntry( 75 syncable::WriteTransaction* trans, 76 syncable::MutableEntry* entry); 77 78 // This function is called on an entry when we can update the user-facing data 79 // from the server data. 80 static void UpdateLocalDataFromServerData(syncable::WriteTransaction* trans, 81 syncable::MutableEntry* entry); 82 83 static VerifyCommitResult ValidateCommitEntry(syncable::Entry* entry); 84 85 static VerifyResult VerifyNewEntry(const SyncEntity& update, 86 syncable::Entry* target, 87 const bool deleted); 88 89 // Assumes we have an existing entry; check here for updates that break 90 // consistency rules. 91 static VerifyResult VerifyUpdateConsistency(syncable::WriteTransaction* trans, 92 const SyncEntity& update, 93 syncable::MutableEntry* target, 94 const bool deleted, 95 const bool is_directory, 96 syncable::ModelType model_type); 97 98 // Assumes we have an existing entry; verify an update that seems to be 99 // expressing an 'undelete' 100 static VerifyResult VerifyUndelete(syncable::WriteTransaction* trans, 101 const SyncEntity& update, 102 syncable::MutableEntry* target); 103 104 // Append |item|, followed by a chain of its predecessors selected by 105 // |inclusion_filter|, to the |commit_ids| vector and tag them as included by 106 // storing in the set |inserted_items|. |inclusion_filter| (typically one of 107 // IS_UNAPPLIED_UPDATE or IS_UNSYNCED) selects which type of predecessors to 108 // include. Returns true if |item| was added, and false if it was already in 109 // the list. 110 // 111 // Use AddPredecessorsThenItem instead of this method if you want the 112 // item to be the last, rather than first, item appended. 113 static bool AddItemThenPredecessors( 114 syncable::BaseTransaction* trans, 115 syncable::Entry* item, 116 syncable::IndexedBitField inclusion_filter, 117 syncable::MetahandleSet* inserted_items, 118 std::vector<syncable::Id>* commit_ids); 119 120 // Exactly like AddItemThenPredecessors, except items are appended in the 121 // reverse (and generally more useful) order: a chain of predecessors from 122 // far to near, and finally the item. 123 static void AddPredecessorsThenItem( 124 syncable::BaseTransaction* trans, 125 syncable::Entry* item, 126 syncable::IndexedBitField inclusion_filter, 127 syncable::MetahandleSet* inserted_items, 128 std::vector<syncable::Id>* commit_ids); 129 130 static void MarkDeletedChildrenSynced( 131 const syncable::ScopedDirLookup &dir, 132 std::set<syncable::Id>* deleted_folders); 133 134 // Examine the up-to-date predecessors of this item according to the server 135 // position, and then again according to the local position. Return true 136 // if they match. For an up-to-date item, this should be the case. 137 static bool ServerAndLocalOrdersMatch(syncable::Entry* entry); 138 139 private: 140 DISALLOW_IMPLICIT_CONSTRUCTORS(SyncerUtil); 141 }; 142 143 #ifndef OS_WIN 144 145 // time.h on Linux and Mac both return seconds since the epoch, this should 146 // be converted to milliseconds. 147 inline int64 ServerTimeToClientTime(int64 server_time) { 148 return server_time / GG_LONGLONG(1000); 149 } 150 151 inline int64 ClientTimeToServerTime(int64 client_time) { 152 return client_time * GG_LONGLONG(1000); 153 } 154 155 // As we truncate server times on the client for posix and on the server for 156 // windows we need two ClientAndServerTimeMatch fucntions. 157 inline bool ClientAndServerTimeMatch(int64 client_time, int64 server_time) { 158 // Compare at the coarser timescale (client) 159 return client_time == ServerTimeToClientTime(server_time); 160 } 161 #else 162 // The sync server uses Java Times (ms since 1970) 163 // and the client uses FILETIMEs (ns since 1601) so we need to convert 164 // between the timescales. 165 // TODO(sync): Fix this. No need to use two timescales. 166 inline int64 ServerTimeToClientTime(int64 server_time) { 167 return server_time * GG_LONGLONG(10000) + GG_LONGLONG(116444736000000000); 168 } 169 170 inline int64 ClientTimeToServerTime(int64 client_time) { 171 return (client_time - GG_LONGLONG(116444736000000000)) / GG_LONGLONG(10000); 172 } 173 174 inline bool ClientAndServerTimeMatch(int64 client_time, int64 server_time) { 175 // Compare at the coarser timescale (server) 176 return ClientTimeToServerTime(client_time) == server_time; 177 } 178 #endif 179 180 } // namespace browser_sync 181 182 #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_UTIL_H_ 183