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

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

Issue 194065: Initial commit of sync engine code to browser/sync.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Fixes to gtest include path, reverted syncapi. Created 11 years, 3 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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/syncer_proto_util.h"
6
7 #include "chrome/browser/sync/engine/net/server_connection_manager.h"
8 #include "chrome/browser/sync/engine/syncer.h"
9 #include "chrome/browser/sync/engine/syncer_util.h"
10 #include "chrome/browser/sync/protocol/service_constants.h"
11 #include "chrome/browser/sync/syncable/directory_manager.h"
12 #include "chrome/browser/sync/syncable/syncable-inl.h"
13 #include "chrome/browser/sync/syncable/syncable.h"
14 #include "chrome/browser/sync/util/character_set_converters.h"
15
16 using std::string;
17 using std::stringstream;
18 using syncable::BASE_VERSION;
19 using syncable::CTIME;
20 using syncable::ID;
21 using syncable::IS_DEL;
22 using syncable::IS_DIR;
23 using syncable::IS_UNSYNCED;
24 using syncable::MTIME;
25 using syncable::PARENT_ID;
26 using syncable::ScopedDirLookup;
27 using syncable::SyncName;
28
29 namespace browser_sync {
30
31 namespace {
32
33 // Time to backoff syncing after receiving a throttled response.
34 static const int kSyncDelayAfterThrottled = 2 * 60 * 60; // 2 hours
35
36 // Verifies the store birthday, alerting/resetting as appropriate if there's a
37 // mismatch.
38 bool VerifyResponseBirthday(const ScopedDirLookup& dir,
39 const ClientToServerResponse* response) {
40 // Process store birthday.
41 if (!response->has_store_birthday())
42 return true;
43 string birthday = dir->store_birthday();
44 if (response->store_birthday() == birthday)
45 return true;
46 LOG(INFO) << "New store birthday: " << response->store_birthday();
47 if (!birthday.empty()) {
48 LOG(ERROR) << "Birthday changed, showing syncer stuck";
49 return false;
50 }
51 dir->set_store_birthday(response->store_birthday());
52 return true;
53 }
54
55 void LogResponseProfilingData(const ClientToServerResponse& response) {
56 if (response.has_profiling_data()) {
57 stringstream response_trace;
58 response_trace << "Server response trace:";
59
60 if (response.profiling_data().has_user_lookup_time()) {
61 response_trace << " " << "user lookup: " <<
62 response.profiling_data().user_lookup_time() << "ms";
63 }
64
65 if (response.profiling_data().has_meta_data_write_time()) {
66 response_trace << " " << "meta write: " <<
67 response.profiling_data().meta_data_write_time() << "ms";
68 }
69
70 if (response.profiling_data().has_meta_data_read_time()) {
71 response_trace << " " << "meta read: " <<
72 response.profiling_data().meta_data_read_time() << "ms";
73 }
74
75 if (response.profiling_data().has_file_data_write_time()) {
76 response_trace << " " << "file write: " <<
77 response.profiling_data().file_data_write_time() << "ms";
78 }
79
80 if (response.profiling_data().has_file_data_read_time()) {
81 response_trace << " " << "file read: " <<
82 response.profiling_data().file_data_read_time() << "ms";
83 }
84
85 if (response.profiling_data().has_total_request_time()) {
86 response_trace << " " << "total time: " <<
87 response.profiling_data().total_request_time() << "ms";
88 }
89 LOG(INFO) << response_trace.str();
90 }
91 }
92
93 } // namespace
94
95 // static
96 bool SyncerProtoUtil::PostClientToServerMessage(
97 ClientToServerMessage* msg,
98 ClientToServerResponse* response,
99 SyncerSession *session) {
idana 2009/09/10 05:44:37 Same old "SyncerSession *session"...
100
101 bool rv = false;
102 string tx, rx;
103 CHECK(response);
104
105 ScopedDirLookup dir(session->dirman(), session->account_name());
106 if (!dir.good())
107 return false;
108 string birthday = dir->store_birthday();
109 if (!birthday.empty()) {
110 msg->set_store_birthday(birthday);
111 } else {
112 LOG(INFO) << "no birthday set";
113 }
114
115 msg->SerializeToString(&tx);
116 HttpResponse http_response;
117 ServerConnectionManager::PostBufferParams params = {
118 tx, &rx, &http_response
119 };
120
121 if (!session->connection_manager()->PostBufferWithCachedAuth(&params)) {
122 LOG(WARNING) << "Error posting from syncer:" << http_response;
123 } else {
124 rv = response->ParseFromString(rx);
125 }
126 SyncerStatus status(session);
127 if (rv) {
128 if (!VerifyResponseBirthday(dir, response)) {
129 // TODO(ncarter): Add a unit test for the case where the syncer
130 // becomes stuck due to a bad birthday.
131 status.set_syncer_stuck(true);
132 return false;
133 }
134
135 // We use an exponential moving average to determine the rate of errors.
136 // It's more reactive to recent situations and uses no extra storage.
137 status.ForgetOldError();
138 // If we're decaying send out an update.
139 status.CheckErrorRateTooHigh();
140
141 switch (response->error_code()) {
142 case ClientToServerResponse::SUCCESS:
143 if (!response->has_store_birthday() && birthday.empty()) {
144 LOG(ERROR) <<
145 "Server didn't provide birthday in proto buffer response.";
146 rv = false;
147 }
148 LogResponseProfilingData(*response);
149 break;
150 case ClientToServerResponse::USER_NOT_ACTIVATED:
151 case ClientToServerResponse::AUTH_INVALID:
152 case ClientToServerResponse::ACCESS_DENIED:
153 LOG(INFO) << "Authentication expired, re-requesting";
154 LOG(INFO) << "Not implemented in syncer yet!!!";
155 status.AuthFailed();
156 rv = false;
157 break;
158 case ClientToServerResponse::NOT_MY_BIRTHDAY:
159 LOG(WARNING) << "Not my birthday return.";
160 rv = false;
161 break;
162 case ClientToServerResponse::THROTTLED:
163 LOG(WARNING) << "Client silenced by server.";
164 session->set_silenced_until(time(0) + kSyncDelayAfterThrottled);
165 rv = false;
166 break;
167 }
168
169 } else if (session->connection_manager()->IsServerReachable()) {
170 status.TallyNewError();
171 }
172 return rv;
173 }
174
175 // static
176 bool SyncerProtoUtil::Compare(const syncable::Entry& local_entry,
177 const SyncEntity& server_entry) {
178 SyncName name = NameFromSyncEntity(server_entry);
179
180 CHECK(local_entry.Get(ID) == server_entry.id()) <<
181 " SyncerProtoUtil::Compare precondition not met.";
182 CHECK(server_entry.version() == local_entry.Get(BASE_VERSION)) <<
183 " SyncerProtoUtil::Compare precondition not met.";
184 CHECK(!local_entry.Get(IS_UNSYNCED)) <<
185 " SyncerProtoUtil::Compare precondition not met.";
186
187 if (local_entry.Get(IS_DEL) && server_entry.deleted())
188 return true;
189 if (!ClientAndServerTimeMatch(local_entry.Get(CTIME), server_entry.ctime())) {
190 LOG(WARNING) << "ctime mismatch";
191 return false;
192 }
193
194 // These checks are somewhat prolix, but they're easier to debug than
195 // a big boolean statement.
196 SyncName client_name = local_entry.GetName();
197 if (client_name != name) {
198 LOG(WARNING) << "Client name mismatch";
199 return false;
200 }
201 if (local_entry.Get(PARENT_ID) != server_entry.parent_id()) {
202 LOG(WARNING) << "Parent ID mismatch";
203 return false;
204 }
205 if (local_entry.Get(IS_DIR) != server_entry.IsFolder()) {
206 LOG(WARNING) << "Dir field mismatch";
207 return false;
208 }
209 if (local_entry.Get(IS_DEL) != server_entry.deleted()) {
210 LOG(WARNING) << "Deletion mismatch";
211 return false;
212 }
213 if (!local_entry.Get(IS_DIR) &&
214 !ClientAndServerTimeMatch(local_entry.Get(MTIME),
215 server_entry.mtime())) {
216 LOG(WARNING) << "mtime mismatch";
217 return false;
218 }
219
220 return true;
221 }
222
223 // static
224 void SyncerProtoUtil::CopyProtoBytesIntoBlob(const std::string& proto_bytes,
225 syncable::Blob* blob) {
226 syncable::Blob proto_blob(proto_bytes.begin(), proto_bytes.end());
227 blob->swap(proto_blob);
228 }
229
230 // static
231 bool SyncerProtoUtil::ProtoBytesEqualsBlob(const std::string& proto_bytes,
232 const syncable::Blob& blob) {
233 if (proto_bytes.size() != blob.size())
234 return false;
235 return std::equal(proto_bytes.begin(), proto_bytes.end(), blob.begin());
236 }
237
238 // static
239 void SyncerProtoUtil::CopyBlobIntoProtoBytes(const syncable::Blob& blob,
240 std::string* proto_bytes) {
241 std::string blob_string(blob.begin(), blob.end());
242 proto_bytes->swap(blob_string);
243 }
244
245 // static
246 syncable::SyncName SyncerProtoUtil::NameFromSyncEntity(
247 const SyncEntity &entry) {
248 SyncName result(PSTR(""));
249
250 AppendUTF8ToPathString(entry.name(), &result.value());
251 if (entry.has_non_unique_name()) {
252 AppendUTF8ToPathString(entry.non_unique_name(),
253 &result.non_unique_value());
254 } else {
255 result.non_unique_value() = result.value();
256 }
257 return result;
258 }
259
260 // static
261 syncable::SyncName SyncerProtoUtil::NameFromCommitEntryResponse(
262 const CommitResponse_EntryResponse& entry) {
263 SyncName result(PSTR(""));
264
265 AppendUTF8ToPathString(entry.name(), &result.value());
266 if (entry.has_non_unique_name()) {
267 AppendUTF8ToPathString(entry.non_unique_name(),
268 &result.non_unique_value());
269 } else {
270 result.non_unique_value() = result.value();
271 }
272 return result;
273 }
274
idana 2009/09/10 05:44:37 Remove extra blank line.
275
276 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698