1 // Copyright 2014 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/non_blocking_type_commit_contribution.h"
6
7 #include "sync/engine/non_blocking_sync_common.h"
8 #include "sync/engine/non_blocking_type_processor_core.h"
9 #include "sync/protocol/proto_value_conversions.h"
10
11 namespace syncer {
12
NonBlockingTypeCommitContribution(const sync_pb::DataTypeContext & context,const google::protobuf::RepeatedPtrField<sync_pb::SyncEntity> & entities,const std::vector<int64> & sequence_numbers,NonBlockingTypeProcessorCore * processor_core)13 NonBlockingTypeCommitContribution::NonBlockingTypeCommitContribution(
14 const sync_pb::DataTypeContext& context,
15 const google::protobuf::RepeatedPtrField<sync_pb::SyncEntity>& entities,
16 const std::vector<int64>& sequence_numbers,
17 NonBlockingTypeProcessorCore* processor_core)
18 : processor_core_(processor_core),
19 context_(context),
20 entities_(entities),
21 sequence_numbers_(sequence_numbers),
22 cleaned_up_(false) {
23 }
24
~NonBlockingTypeCommitContribution()25 NonBlockingTypeCommitContribution::~NonBlockingTypeCommitContribution() {
26 DCHECK(cleaned_up_);
27 }
28
AddToCommitMessage(sync_pb::ClientToServerMessage * msg)29 void NonBlockingTypeCommitContribution::AddToCommitMessage(
30 sync_pb::ClientToServerMessage* msg) {
31 sync_pb::CommitMessage* commit_message = msg->mutable_commit();
32 entries_start_index_ = commit_message->entries_size();
33
34 std::copy(entities_.begin(),
35 entities_.end(),
36 RepeatedPtrFieldBackInserter(commit_message->mutable_entries()));
37 if (!context_.context().empty())
38 commit_message->add_client_contexts()->CopyFrom(context_);
39 }
40
ProcessCommitResponse(const sync_pb::ClientToServerResponse & response,sessions::StatusController * status)41 SyncerError NonBlockingTypeCommitContribution::ProcessCommitResponse(
42 const sync_pb::ClientToServerResponse& response,
43 sessions::StatusController* status) {
44 const sync_pb::CommitResponse& commit_response = response.commit();
45
46 bool transient_error = false;
47 bool commit_conflict = false;
48 bool unknown_error = false;
49
50 CommitResponseDataList response_list;
51
52 for (size_t i = 0; i < sequence_numbers_.size(); ++i) {
53 const sync_pb::CommitResponse_EntryResponse& entry_response =
54 commit_response.entryresponse(entries_start_index_ + i);
55
56 switch (entry_response.response_type()) {
57 case sync_pb::CommitResponse::INVALID_MESSAGE:
58 LOG(ERROR) << "Server reports commit message is invalid.";
59 DLOG(ERROR) << "Message was: " << SyncEntityToValue(entities_.Get(i),
60 false);
61 unknown_error = true;
62 break;
63 case sync_pb::CommitResponse::CONFLICT:
64 DVLOG(1) << "Server reports conflict for commit message.";
65 DVLOG(1) << "Message was: " << SyncEntityToValue(entities_.Get(i),
66 false);
67 commit_conflict = true;
68 break;
69 case sync_pb::CommitResponse::SUCCESS: {
70 CommitResponseData response_data;
71 response_data.id = entry_response.id_string();
72 response_data.client_tag_hash =
73 entities_.Get(i).client_defined_unique_tag();
74 response_data.sequence_number = sequence_numbers_[i];
75 response_data.response_version = entry_response.version();
76 response_list.push_back(response_data);
77 break;
78 }
79 case sync_pb::CommitResponse::OVER_QUOTA:
80 case sync_pb::CommitResponse::RETRY:
81 case sync_pb::CommitResponse::TRANSIENT_ERROR:
82 DLOG(WARNING) << "Entity commit blocked by transient error.";
83 transient_error = true;
84 break;
85 default:
86 LOG(ERROR) << "Bad return from ProcessSingleCommitResponse.";
87 unknown_error = true;
88 }
89 }
90
91 // Send whatever successful responses we did get back to our parent.
92 // It's the schedulers job to handle the failures.
93 processor_core_->OnCommitResponse(response_list);
94
95 // Let the scheduler know about the failures.
96 if (unknown_error) {
97 return SERVER_RETURN_UNKNOWN_ERROR;
98 } else if (transient_error) {
99 return SERVER_RETURN_TRANSIENT_ERROR;
100 } else if (commit_conflict) {
101 return SERVER_RETURN_CONFLICT;
102 } else {
103 return SYNCER_OK;
104 }
105 }
106
CleanUp()107 void NonBlockingTypeCommitContribution::CleanUp() {
108 cleaned_up_ = true;
109
110 // We could inform our parent NonBlockingCommitContributor that a commit is
111 // no longer in progress. The current implementation doesn't really care
112 // either way, so we don't bother sending the signal.
113 }
114
GetNumEntries() const115 size_t NonBlockingTypeCommitContribution::GetNumEntries() const {
116 return sequence_numbers_.size();
117 }
118
119 } // namespace syncer
120