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/model_type_sync_worker_impl.h" 8 #include "sync/internal_api/public/non_blocking_sync_common.h" 9 #include "sync/protocol/proto_value_conversions.h" 10 11 namespace syncer { 12 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 ModelTypeSyncWorkerImpl* worker) 18 : worker_(worker), 19 context_(context), 20 entities_(entities), 21 sequence_numbers_(sequence_numbers), 22 cleaned_up_(false) { 23 } 24 25 NonBlockingTypeCommitContribution::~NonBlockingTypeCommitContribution() { 26 DCHECK(cleaned_up_); 27 } 28 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 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 worker_->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 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 115 size_t NonBlockingTypeCommitContribution::GetNumEntries() const { 116 return sequence_numbers_.size(); 117 } 118 119 } // namespace syncer 120