commit.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 "base/debug/trace_event.h"
8#include "sync/engine/commit_processor.h"
9#include "sync/engine/commit_util.h"
10#include "sync/engine/sync_directory_commit_contribution.h"
11#include "sync/engine/syncer.h"
12#include "sync/engine/syncer_proto_util.h"
13#include "sync/sessions/sync_session.h"
14
15namespace syncer {
16
17Commit::Commit(
18    const std::map<ModelType, SyncDirectoryCommitContribution*>& contributions,
19    const sync_pb::ClientToServerMessage& message,
20    ExtensionsActivity::Records extensions_activity_buffer)
21  : contributions_(contributions),
22    deleter_(&contributions_),
23    message_(message),
24    extensions_activity_buffer_(extensions_activity_buffer),
25    cleaned_up_(false) {
26}
27
28Commit::~Commit() {
29  DCHECK(cleaned_up_);
30}
31
32Commit* Commit::Init(
33    ModelTypeSet requested_types,
34    ModelTypeSet enabled_types,
35    size_t max_entries,
36    const std::string& account_name,
37    const std::string& cache_guid,
38    CommitProcessor* commit_processor,
39    ExtensionsActivity* extensions_activity) {
40  // Gather per-type contributions.
41  ContributionMap contributions;
42  commit_processor->GatherCommitContributions(
43      requested_types,
44      max_entries,
45      &contributions);
46
47  // Give up if no one had anything to commit.
48  if (contributions.empty())
49    return NULL;
50
51  sync_pb::ClientToServerMessage message;
52  message.set_message_contents(sync_pb::ClientToServerMessage::COMMIT);
53  message.set_share(account_name);
54
55  sync_pb::CommitMessage* commit_message = message.mutable_commit();
56  commit_message->set_cache_guid(cache_guid);
57
58  // Set extensions activity if bookmark commits are present.
59  ExtensionsActivity::Records extensions_activity_buffer;
60  ContributionMap::iterator it = contributions.find(syncer::BOOKMARKS);
61  if (it != contributions.end() && it->second->GetNumEntries() != 0) {
62    commit_util::AddExtensionsActivityToMessage(
63        extensions_activity,
64        &extensions_activity_buffer,
65        commit_message);
66  }
67
68  // Set the client config params.
69  commit_util::AddClientConfigParamsToMessage(
70      enabled_types,
71      commit_message);
72
73  // Finally, serialize all our contributions.
74  for (std::map<ModelType, SyncDirectoryCommitContribution*>::iterator it =
75           contributions.begin(); it != contributions.end(); ++it) {
76    it->second->AddToCommitMessage(&message);
77  }
78
79  // If we made it this far, then we've successfully prepared a commit message.
80  return new Commit(contributions, message, extensions_activity_buffer);
81}
82
83SyncerError Commit::PostAndProcessResponse(
84    sessions::SyncSession* session,
85    sessions::StatusController* status,
86    ExtensionsActivity* extensions_activity) {
87  ModelTypeSet request_types;
88  for (ContributionMap::const_iterator it = contributions_.begin();
89       it != contributions_.end(); ++it) {
90    request_types.Put(it->first);
91  }
92  session->mutable_status_controller()->set_commit_request_types(request_types);
93
94  if (session->context()->debug_info_getter()) {
95    sync_pb::DebugInfo* debug_info = message_.mutable_debug_info();
96    session->context()->debug_info_getter()->GetDebugInfo(debug_info);
97  }
98
99  DVLOG(1) << "Sending commit message.";
100  TRACE_EVENT_BEGIN0("sync", "PostCommit");
101  const SyncerError post_result = SyncerProtoUtil::PostClientToServerMessage(
102      &message_, &response_, session);
103  TRACE_EVENT_END0("sync", "PostCommit");
104
105  if (post_result != SYNCER_OK) {
106    LOG(WARNING) << "Post commit failed";
107    return post_result;
108  }
109
110  if (!response_.has_commit()) {
111    LOG(WARNING) << "Commit response has no commit body!";
112    return SERVER_RESPONSE_VALIDATION_FAILED;
113  }
114
115  size_t message_entries = message_.commit().entries_size();
116  size_t response_entries = response_.commit().entryresponse_size();
117  if (message_entries != response_entries) {
118    LOG(ERROR)
119       << "Commit response has wrong number of entries! "
120       << "Expected: " << message_entries << ", "
121       << "Got: " << response_entries;
122    return SERVER_RESPONSE_VALIDATION_FAILED;
123  }
124
125  if (session->context()->debug_info_getter()) {
126    // Clear debug info now that we have successfully sent it to the server.
127    DVLOG(1) << "Clearing client debug info.";
128    session->context()->debug_info_getter()->ClearDebugInfo();
129  }
130
131  // Let the contributors process the responses to each of their requests.
132  SyncerError processing_result = SYNCER_OK;
133  for (std::map<ModelType, SyncDirectoryCommitContribution*>::iterator it =
134       contributions_.begin(); it != contributions_.end(); ++it) {
135    TRACE_EVENT1("sync", "ProcessCommitResponse",
136                 "type", ModelTypeToString(it->first));
137    SyncerError type_result =
138        it->second->ProcessCommitResponse(response_, status);
139    if (processing_result == SYNCER_OK && type_result != SYNCER_OK) {
140      processing_result = type_result;
141    }
142  }
143
144  // Handle bookmarks' special extensions activity stats.
145  if (session->status_controller().
146          model_neutral_state().num_successful_bookmark_commits == 0) {
147    extensions_activity->PutRecords(extensions_activity_buffer_);
148  }
149
150  return processing_result;
151}
152
153void Commit::CleanUp() {
154  for (ContributionMap::iterator it = contributions_.begin();
155       it != contributions_.end(); ++it) {
156    it->second->CleanUp();
157  }
158  cleaned_up_ = true;
159}
160
161}  // namespace syncer
162