OLD | NEW |
| (Empty) |
1 // Copyright 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 "sync/engine/commit.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include "base/metrics/sparse_histogram.h" | |
10 #include "base/trace_event/trace_event.h" | |
11 #include "sync/engine/commit_contribution.h" | |
12 #include "sync/engine/commit_processor.h" | |
13 #include "sync/engine/commit_util.h" | |
14 #include "sync/engine/syncer.h" | |
15 #include "sync/engine/syncer_proto_util.h" | |
16 #include "sync/internal_api/public/events/commit_request_event.h" | |
17 #include "sync/internal_api/public/events/commit_response_event.h" | |
18 #include "sync/sessions/sync_session.h" | |
19 #include "sync/util/data_type_histogram.h" | |
20 | |
21 namespace syncer { | |
22 | |
23 Commit::Commit(ContributionMap contributions, | |
24 const sync_pb::ClientToServerMessage& message, | |
25 ExtensionsActivity::Records extensions_activity_buffer) | |
26 : contributions_(std::move(contributions)), | |
27 message_(message), | |
28 extensions_activity_buffer_(extensions_activity_buffer), | |
29 cleaned_up_(false) {} | |
30 | |
31 Commit::~Commit() { | |
32 DCHECK(cleaned_up_); | |
33 } | |
34 | |
35 Commit* Commit::Init(ModelTypeSet requested_types, | |
36 ModelTypeSet enabled_types, | |
37 size_t max_entries, | |
38 const std::string& account_name, | |
39 const std::string& cache_guid, | |
40 bool cookie_jar_mismatch, | |
41 bool cookie_jar_empty, | |
42 CommitProcessor* commit_processor, | |
43 ExtensionsActivity* extensions_activity) { | |
44 // Gather per-type contributions. | |
45 ContributionMap contributions; | |
46 commit_processor->GatherCommitContributions(requested_types, max_entries, | |
47 cookie_jar_mismatch, | |
48 cookie_jar_empty, &contributions); | |
49 | |
50 // Give up if no one had anything to commit. | |
51 if (contributions.empty()) | |
52 return NULL; | |
53 | |
54 sync_pb::ClientToServerMessage message; | |
55 message.set_message_contents(sync_pb::ClientToServerMessage::COMMIT); | |
56 message.set_share(account_name); | |
57 | |
58 sync_pb::CommitMessage* commit_message = message.mutable_commit(); | |
59 commit_message->set_cache_guid(cache_guid); | |
60 | |
61 // Set extensions activity if bookmark commits are present. | |
62 ExtensionsActivity::Records extensions_activity_buffer; | |
63 ContributionMap::const_iterator it = contributions.find(syncer::BOOKMARKS); | |
64 if (it != contributions.end() && it->second->GetNumEntries() != 0) { | |
65 commit_util::AddExtensionsActivityToMessage( | |
66 extensions_activity, | |
67 &extensions_activity_buffer, | |
68 commit_message); | |
69 } | |
70 | |
71 // Set the client config params. | |
72 commit_util::AddClientConfigParamsToMessage( | |
73 enabled_types, | |
74 cookie_jar_mismatch, | |
75 commit_message); | |
76 | |
77 int previous_message_size = message.ByteSize(); | |
78 // Finally, serialize all our contributions. | |
79 for (const auto& contribution : contributions) { | |
80 contribution.second->AddToCommitMessage(&message); | |
81 int current_entry_size = message.ByteSize() - previous_message_size; | |
82 previous_message_size = message.ByteSize(); | |
83 int local_integer_model_type = ModelTypeToHistogramInt(contribution.first); | |
84 if (current_entry_size > 0) { | |
85 SyncRecordDatatypeBin("DataUse.Sync.Upload.Bytes", | |
86 local_integer_model_type, current_entry_size); | |
87 } | |
88 UMA_HISTOGRAM_SPARSE_SLOWLY("DataUse.Sync.Upload.Count", | |
89 local_integer_model_type); | |
90 } | |
91 | |
92 // If we made it this far, then we've successfully prepared a commit message. | |
93 return new Commit(std::move(contributions), message, | |
94 extensions_activity_buffer); | |
95 } | |
96 | |
97 SyncerError Commit::PostAndProcessResponse( | |
98 sessions::NudgeTracker* nudge_tracker, | |
99 sessions::SyncSession* session, | |
100 sessions::StatusController* status, | |
101 ExtensionsActivity* extensions_activity) { | |
102 ModelTypeSet request_types; | |
103 for (ContributionMap::const_iterator it = contributions_.begin(); | |
104 it != contributions_.end(); ++it) { | |
105 request_types.Put(it->first); | |
106 } | |
107 session->mutable_status_controller()->set_commit_request_types(request_types); | |
108 | |
109 if (session->context()->debug_info_getter()) { | |
110 sync_pb::DebugInfo* debug_info = message_.mutable_debug_info(); | |
111 session->context()->debug_info_getter()->GetDebugInfo(debug_info); | |
112 } | |
113 | |
114 DVLOG(1) << "Sending commit message."; | |
115 | |
116 CommitRequestEvent request_event( | |
117 base::Time::Now(), | |
118 message_.commit().entries_size(), | |
119 request_types, | |
120 message_); | |
121 session->SendProtocolEvent(request_event); | |
122 | |
123 TRACE_EVENT_BEGIN0("sync", "PostCommit"); | |
124 const SyncerError post_result = SyncerProtoUtil::PostClientToServerMessage( | |
125 &message_, &response_, session, NULL); | |
126 TRACE_EVENT_END0("sync", "PostCommit"); | |
127 | |
128 // TODO(rlarocque): Use result that includes errors captured later? | |
129 CommitResponseEvent response_event( | |
130 base::Time::Now(), | |
131 post_result, | |
132 response_); | |
133 session->SendProtocolEvent(response_event); | |
134 | |
135 if (post_result != SYNCER_OK) { | |
136 LOG(WARNING) << "Post commit failed"; | |
137 return post_result; | |
138 } | |
139 | |
140 if (!response_.has_commit()) { | |
141 LOG(WARNING) << "Commit response has no commit body!"; | |
142 return SERVER_RESPONSE_VALIDATION_FAILED; | |
143 } | |
144 | |
145 size_t message_entries = message_.commit().entries_size(); | |
146 size_t response_entries = response_.commit().entryresponse_size(); | |
147 if (message_entries != response_entries) { | |
148 LOG(ERROR) | |
149 << "Commit response has wrong number of entries! " | |
150 << "Expected: " << message_entries << ", " | |
151 << "Got: " << response_entries; | |
152 return SERVER_RESPONSE_VALIDATION_FAILED; | |
153 } | |
154 | |
155 if (session->context()->debug_info_getter()) { | |
156 // Clear debug info now that we have successfully sent it to the server. | |
157 DVLOG(1) << "Clearing client debug info."; | |
158 session->context()->debug_info_getter()->ClearDebugInfo(); | |
159 } | |
160 | |
161 // Let the contributors process the responses to each of their requests. | |
162 SyncerError processing_result = SYNCER_OK; | |
163 for (ContributionMap::const_iterator it = contributions_.begin(); | |
164 it != contributions_.end(); ++it) { | |
165 TRACE_EVENT1("sync", "ProcessCommitResponse", | |
166 "type", ModelTypeToString(it->first)); | |
167 SyncerError type_result = | |
168 it->second->ProcessCommitResponse(response_, status); | |
169 if (type_result == SERVER_RETURN_CONFLICT) { | |
170 nudge_tracker->RecordCommitConflict(it->first); | |
171 } | |
172 if (processing_result == SYNCER_OK && type_result != SYNCER_OK) { | |
173 processing_result = type_result; | |
174 } | |
175 } | |
176 | |
177 // Handle bookmarks' special extensions activity stats. | |
178 if (session->status_controller(). | |
179 model_neutral_state().num_successful_bookmark_commits == 0) { | |
180 extensions_activity->PutRecords(extensions_activity_buffer_); | |
181 } | |
182 | |
183 return processing_result; | |
184 } | |
185 | |
186 void Commit::CleanUp() { | |
187 for (ContributionMap::const_iterator it = contributions_.begin(); | |
188 it != contributions_.end(); ++it) { | |
189 it->second->CleanUp(); | |
190 } | |
191 cleaned_up_ = true; | |
192 } | |
193 | |
194 } // namespace syncer | |
OLD | NEW |