Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: chrome/browser/sync/engine/build_commit_command.cc

Issue 9699057: [Sync] Move 'sync' target to sync/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Tim's comments Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 #include "chrome/browser/sync/engine/build_commit_command.h"
6
7 #include <limits>
8 #include <set>
9 #include <string>
10 #include <vector>
11
12 #include "base/string_util.h"
13 #include "chrome/browser/sync/engine/syncer_proto_util.h"
14 #include "chrome/browser/sync/sessions/sync_session.h"
15 #include "chrome/browser/sync/syncable/syncable.h"
16 #include "chrome/browser/sync/syncable/syncable_changes_version.h"
17 #include "chrome/browser/sync/util/time.h"
18 #include "sync/protocol/bookmark_specifics.pb.h"
19
20 using std::set;
21 using std::string;
22 using std::vector;
23 using syncable::Entry;
24 using syncable::IS_DEL;
25 using syncable::SERVER_POSITION_IN_PARENT;
26 using syncable::IS_UNAPPLIED_UPDATE;
27 using syncable::IS_UNSYNCED;
28 using syncable::Id;
29 using syncable::MutableEntry;
30 using syncable::SPECIFICS;
31 using syncable::UNSPECIFIED;
32
33 namespace browser_sync {
34
35 using sessions::SyncSession;
36
37 // static
38 int64 BuildCommitCommand::GetFirstPosition() {
39 return std::numeric_limits<int64>::min();
40 }
41
42 // static
43 int64 BuildCommitCommand::GetLastPosition() {
44 return std::numeric_limits<int64>::max();
45 }
46
47 // static
48 int64 BuildCommitCommand::GetGap() {
49 return 1LL << 20;
50 }
51
52 BuildCommitCommand::BuildCommitCommand() {}
53 BuildCommitCommand::~BuildCommitCommand() {}
54
55 void BuildCommitCommand::AddExtensionsActivityToMessage(
56 SyncSession* session, CommitMessage* message) {
57 // We only send ExtensionsActivity to the server if bookmarks are being
58 // committed.
59 ExtensionsActivityMonitor* monitor = session->context()->extensions_monitor();
60 if (!session->status_controller().HasBookmarkCommitActivity()) {
61 // Return the records to the activity monitor.
62 monitor->PutRecords(session->extensions_activity());
63 session->mutable_extensions_activity()->clear();
64 return;
65 }
66 const ExtensionsActivityMonitor::Records& records =
67 session->extensions_activity();
68 for (ExtensionsActivityMonitor::Records::const_iterator it = records.begin();
69 it != records.end(); ++it) {
70 sync_pb::ChromiumExtensionsActivity* activity_message =
71 message->add_extensions_activity();
72 activity_message->set_extension_id(it->second.extension_id);
73 activity_message->set_bookmark_writes_since_last_commit(
74 it->second.bookmark_write_count);
75 }
76 }
77
78 namespace {
79 void SetEntrySpecifics(MutableEntry* meta_entry, SyncEntity* sync_entry) {
80 // Add the new style extension and the folder bit.
81 sync_entry->mutable_specifics()->CopyFrom(meta_entry->Get(SPECIFICS));
82 sync_entry->set_folder(meta_entry->Get(syncable::IS_DIR));
83
84 DCHECK(meta_entry->GetModelType() == sync_entry->GetModelType());
85 }
86 } // namespace
87
88 SyncerError BuildCommitCommand::ExecuteImpl(SyncSession* session) {
89 ClientToServerMessage message;
90 message.set_share(session->context()->account_name());
91 message.set_message_contents(ClientToServerMessage::COMMIT);
92
93 CommitMessage* commit_message = message.mutable_commit();
94 commit_message->set_cache_guid(
95 session->write_transaction()->directory()->cache_guid());
96 AddExtensionsActivityToMessage(session, commit_message);
97 SyncerProtoUtil::AddRequestBirthday(
98 session->write_transaction()->directory(), &message);
99
100 // Cache previously computed position values. Because |commit_ids|
101 // is already in sibling order, we should always hit this map after
102 // the first sibling in a consecutive run of commit items. The
103 // entries in this map are (low, high) values describing the
104 // space of positions that are immediate successors of the item
105 // whose ID is the map's key.
106 std::map<Id, std::pair<int64, int64> > position_map;
107
108 const vector<Id>& commit_ids = session->status_controller().commit_ids();
109 for (size_t i = 0; i < commit_ids.size(); i++) {
110 Id id = commit_ids[i];
111 SyncEntity* sync_entry =
112 static_cast<SyncEntity*>(commit_message->add_entries());
113 sync_entry->set_id(id);
114 MutableEntry meta_entry(session->write_transaction(),
115 syncable::GET_BY_ID,
116 id);
117 CHECK(meta_entry.good());
118 // This is the only change we make to the entry in this function.
119 meta_entry.Put(syncable::SYNCING, true);
120
121 DCHECK(0 != session->routing_info().count(meta_entry.GetModelType()))
122 << "Committing change to datatype that's not actively enabled.";
123
124 string name = meta_entry.Get(syncable::NON_UNIQUE_NAME);
125 CHECK(!name.empty()); // Make sure this isn't an update.
126 TruncateUTF8ToByteSize(name, 255, &name);
127 sync_entry->set_name(name);
128
129 // Set the non_unique_name. If we do, the server ignores
130 // the |name| value (using |non_unique_name| instead), and will return
131 // in the CommitResponse a unique name if one is generated.
132 // We send both because it may aid in logging.
133 sync_entry->set_non_unique_name(name);
134
135 if (!meta_entry.Get(syncable::UNIQUE_CLIENT_TAG).empty()) {
136 sync_entry->set_client_defined_unique_tag(
137 meta_entry.Get(syncable::UNIQUE_CLIENT_TAG));
138 }
139
140 // Deleted items with server-unknown parent ids can be a problem so we set
141 // the parent to 0. (TODO(sync): Still true in protocol?).
142 Id new_parent_id;
143 if (meta_entry.Get(syncable::IS_DEL) &&
144 !meta_entry.Get(syncable::PARENT_ID).ServerKnows()) {
145 new_parent_id = session->write_transaction()->root_id();
146 } else {
147 new_parent_id = meta_entry.Get(syncable::PARENT_ID);
148 }
149 sync_entry->set_parent_id(new_parent_id);
150
151 // If our parent has changed, send up the old one so the server
152 // can correctly deal with multiple parents.
153 // TODO(nick): With the server keeping track of the primary sync parent,
154 // it should not be necessary to provide the old_parent_id: the version
155 // number should suffice.
156 if (new_parent_id != meta_entry.Get(syncable::SERVER_PARENT_ID) &&
157 0 != meta_entry.Get(syncable::BASE_VERSION) &&
158 syncable::CHANGES_VERSION != meta_entry.Get(syncable::BASE_VERSION)) {
159 sync_entry->set_old_parent_id(meta_entry.Get(syncable::SERVER_PARENT_ID));
160 }
161
162 int64 version = meta_entry.Get(syncable::BASE_VERSION);
163 if (syncable::CHANGES_VERSION == version || 0 == version) {
164 // Undeletions are only supported for items that have a client tag.
165 DCHECK(!id.ServerKnows() ||
166 !meta_entry.Get(syncable::UNIQUE_CLIENT_TAG).empty())
167 << meta_entry;
168
169 // Version 0 means to create or undelete an object.
170 sync_entry->set_version(0);
171 } else {
172 DCHECK(id.ServerKnows()) << meta_entry;
173 sync_entry->set_version(meta_entry.Get(syncable::BASE_VERSION));
174 }
175 sync_entry->set_ctime(TimeToProtoTime(meta_entry.Get(syncable::CTIME)));
176 sync_entry->set_mtime(TimeToProtoTime(meta_entry.Get(syncable::MTIME)));
177
178 // Deletion is final on the server, let's move things and then delete them.
179 if (meta_entry.Get(IS_DEL)) {
180 sync_entry->set_deleted(true);
181 } else {
182 if (meta_entry.Get(SPECIFICS).has_bookmark()) {
183 // Common data in both new and old protocol.
184 const Id& prev_id = meta_entry.Get(syncable::PREV_ID);
185 string prev_id_string =
186 prev_id.IsRoot() ? string() : prev_id.GetServerId();
187 sync_entry->set_insert_after_item_id(prev_id_string);
188
189 // Compute a numeric position based on what we know locally.
190 std::pair<int64, int64> position_block(
191 GetFirstPosition(), GetLastPosition());
192 std::map<Id, std::pair<int64, int64> >::iterator prev_pos =
193 position_map.find(prev_id);
194 if (prev_pos != position_map.end()) {
195 position_block = prev_pos->second;
196 position_map.erase(prev_pos);
197 } else {
198 position_block = std::make_pair(
199 FindAnchorPosition(syncable::PREV_ID, meta_entry),
200 FindAnchorPosition(syncable::NEXT_ID, meta_entry));
201 }
202 position_block.first = InterpolatePosition(position_block.first,
203 position_block.second);
204
205 position_map[id] = position_block;
206 sync_entry->set_position_in_parent(position_block.first);
207 }
208 SetEntrySpecifics(&meta_entry, sync_entry);
209 }
210 }
211 session->mutable_status_controller()->
212 mutable_commit_message()->CopyFrom(message);
213
214 return SYNCER_OK;
215 }
216
217 int64 BuildCommitCommand::FindAnchorPosition(syncable::IdField direction,
218 const syncable::Entry& entry) {
219 Id next_id = entry.Get(direction);
220 while (!next_id.IsRoot()) {
221 Entry next_entry(entry.trans(),
222 syncable::GET_BY_ID,
223 next_id);
224 if (!next_entry.Get(IS_UNSYNCED) && !next_entry.Get(IS_UNAPPLIED_UPDATE)) {
225 return next_entry.Get(SERVER_POSITION_IN_PARENT);
226 }
227 next_id = next_entry.Get(direction);
228 }
229 return
230 direction == syncable::PREV_ID ?
231 GetFirstPosition() : GetLastPosition();
232 }
233
234 int64 BuildCommitCommand::InterpolatePosition(const int64 lo,
235 const int64 hi) {
236 DCHECK_LE(lo, hi);
237
238 // The first item to be added under a parent gets a position of zero.
239 if (lo == GetFirstPosition() && hi == GetLastPosition())
240 return 0;
241
242 // For small gaps, we do linear interpolation. For larger gaps,
243 // we use an additive offset of |GetGap()|. We are careful to avoid
244 // signed integer overflow.
245 uint64 delta = static_cast<uint64>(hi) - static_cast<uint64>(lo);
246 if (delta <= static_cast<uint64>(GetGap()*2))
247 return lo + (static_cast<int64>(delta) + 7) / 8; // Interpolate.
248 else if (lo == GetFirstPosition())
249 return hi - GetGap(); // Extend range just before successor.
250 else
251 return lo + GetGap(); // Use or extend range just after predecessor.
252 }
253
254
255 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/engine/build_commit_command.h ('k') | chrome/browser/sync/engine/build_commit_command_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698