// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // // Utility functions manipulating syncable::Entries, intended for use by the // syncer. #ifndef CHROME_BROWSER_SYNC_ENGINE_SYNCER_UTIL_H_ #define CHROME_BROWSER_SYNC_ENGINE_SYNCER_UTIL_H_ #pragma once #include <set> #include <string> #include <vector> #include "build/build_config.h" #include "chrome/browser/sync/engine/syncer.h" #include "chrome/browser/sync/engine/syncer_types.h" #include "chrome/browser/sync/syncable/syncable.h" #include "chrome/browser/sync/syncable/syncable_id.h" namespace browser_sync { class Cryptographer; class SyncEntity; class SyncerUtil { public: static void ChangeEntryIDAndUpdateChildren( syncable::WriteTransaction* trans, syncable::MutableEntry* entry, const syncable::Id& new_id, syncable::Directory::ChildHandles* children); // Returns the number of unsynced entries. static int GetUnsyncedEntries(syncable::BaseTransaction* trans, std::vector<int64> *handles); static void ChangeEntryIDAndUpdateChildren(syncable::WriteTransaction* trans, syncable::MutableEntry* entry, const syncable::Id& new_id); // If the server sent down a client-tagged entry, or an entry whose // commit response was lost, it is necessary to update a local entry // with an ID that doesn't match the ID of the update. Here, we // find the ID of such an entry, if it exists. This function may // determine that |server_entry| should be dropped; if so, it returns // the null ID -- callers must handle this case. When update application // should proceed normally with a new local entry, this function will // return server_entry.id(); the caller must create an entry with that // ID. This function does not alter the database. static syncable::Id FindLocalIdToUpdate( syncable::BaseTransaction* trans, const SyncEntity& server_entry); static UpdateAttemptResponse AttemptToUpdateEntry( syncable::WriteTransaction* const trans, syncable::MutableEntry* const entry, ConflictResolver* resolver, Cryptographer* cryptographer); // Pass in name to avoid redundant UTF8 conversion. static void UpdateServerFieldsFromUpdate( syncable::MutableEntry* local_entry, const SyncEntity& server_entry, const std::string& name); // Creates a new Entry iff no Entry exists with the given id. static void CreateNewEntry(syncable::WriteTransaction *trans, const syncable::Id& id); static bool ServerAndLocalEntriesMatch(syncable::Entry* entry); static void SplitServerInformationIntoNewEntry( syncable::WriteTransaction* trans, syncable::MutableEntry* entry); // This function is called on an entry when we can update the user-facing data // from the server data. static void UpdateLocalDataFromServerData(syncable::WriteTransaction* trans, syncable::MutableEntry* entry); static VerifyCommitResult ValidateCommitEntry(syncable::Entry* entry); static VerifyResult VerifyNewEntry(const SyncEntity& update, syncable::Entry* target, const bool deleted); // Assumes we have an existing entry; check here for updates that break // consistency rules. static VerifyResult VerifyUpdateConsistency(syncable::WriteTransaction* trans, const SyncEntity& update, syncable::MutableEntry* target, const bool deleted, const bool is_directory, syncable::ModelType model_type); // Assumes we have an existing entry; verify an update that seems to be // expressing an 'undelete' static VerifyResult VerifyUndelete(syncable::WriteTransaction* trans, const SyncEntity& update, syncable::MutableEntry* target); // Append |item|, followed by a chain of its predecessors selected by // |inclusion_filter|, to the |commit_ids| vector and tag them as included by // storing in the set |inserted_items|. |inclusion_filter| (typically one of // IS_UNAPPLIED_UPDATE or IS_UNSYNCED) selects which type of predecessors to // include. Returns true if |item| was added, and false if it was already in // the list. // // Use AddPredecessorsThenItem instead of this method if you want the // item to be the last, rather than first, item appended. static bool AddItemThenPredecessors( syncable::BaseTransaction* trans, syncable::Entry* item, syncable::IndexedBitField inclusion_filter, syncable::MetahandleSet* inserted_items, std::vector<syncable::Id>* commit_ids); // Exactly like AddItemThenPredecessors, except items are appended in the // reverse (and generally more useful) order: a chain of predecessors from // far to near, and finally the item. static void AddPredecessorsThenItem( syncable::BaseTransaction* trans, syncable::Entry* item, syncable::IndexedBitField inclusion_filter, syncable::MetahandleSet* inserted_items, std::vector<syncable::Id>* commit_ids); static void MarkDeletedChildrenSynced( const syncable::ScopedDirLookup &dir, std::set<syncable::Id>* deleted_folders); // Examine the up-to-date predecessors of this item according to the server // position, and then again according to the local position. Return true // if they match. For an up-to-date item, this should be the case. static bool ServerAndLocalOrdersMatch(syncable::Entry* entry); private: DISALLOW_IMPLICIT_CONSTRUCTORS(SyncerUtil); }; #ifndef OS_WIN // time.h on Linux and Mac both return seconds since the epoch, this should // be converted to milliseconds. inline int64 ServerTimeToClientTime(int64 server_time) { return server_time / GG_LONGLONG(1000); } inline int64 ClientTimeToServerTime(int64 client_time) { return client_time * GG_LONGLONG(1000); } // As we truncate server times on the client for posix and on the server for // windows we need two ClientAndServerTimeMatch fucntions. inline bool ClientAndServerTimeMatch(int64 client_time, int64 server_time) { // Compare at the coarser timescale (client) return client_time == ServerTimeToClientTime(server_time); } #else // The sync server uses Java Times (ms since 1970) // and the client uses FILETIMEs (ns since 1601) so we need to convert // between the timescales. // TODO(sync): Fix this. No need to use two timescales. inline int64 ServerTimeToClientTime(int64 server_time) { return server_time * GG_LONGLONG(10000) + GG_LONGLONG(116444736000000000); } inline int64 ClientTimeToServerTime(int64 client_time) { return (client_time - GG_LONGLONG(116444736000000000)) / GG_LONGLONG(10000); } inline bool ClientAndServerTimeMatch(int64 client_time, int64 server_time) { // Compare at the coarser timescale (server) return ClientTimeToServerTime(client_time) == server_time; } #endif } // namespace browser_sync #endif // CHROME_BROWSER_SYNC_ENGINE_SYNCER_UTIL_H_