Home | History | Annotate | Download | only in engine
      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