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.
ServerTimeToClientTime(int64 server_time)147 inline int64 ServerTimeToClientTime(int64 server_time) {
148 return server_time / GG_LONGLONG(1000);
149 }
150
ClientTimeToServerTime(int64 client_time)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.
ClientAndServerTimeMatch(int64 client_time,int64 server_time)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.
ServerTimeToClientTime(int64 server_time)166 inline int64 ServerTimeToClientTime(int64 server_time) {
167 return server_time * GG_LONGLONG(10000) + GG_LONGLONG(116444736000000000);
168 }
169
ClientTimeToServerTime(int64 client_time)170 inline int64 ClientTimeToServerTime(int64 client_time) {
171 return (client_time - GG_LONGLONG(116444736000000000)) / GG_LONGLONG(10000);
172 }
173
ClientAndServerTimeMatch(int64 client_time,int64 server_time)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