Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(350)

Unified Diff: sync/engine/process_commit_response_command.cc

Issue 10210009: sync: Loop committing items without downloading updates (v2) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactor loop again, add comments + more Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sync/engine/process_commit_response_command.cc
diff --git a/sync/engine/process_commit_response_command.cc b/sync/engine/process_commit_response_command.cc
index b82ff6d5246dac3c908b4060444a7c390d9d3dcf..f2e5edc3c0608d137a8d2cc55a7ac7ff5e9e4456 100644
--- a/sync/engine/process_commit_response_command.cc
+++ b/sync/engine/process_commit_response_command.cc
@@ -48,7 +48,15 @@ using sessions::StatusController;
using sessions::SyncSession;
using sessions::ConflictProgress;
-ProcessCommitResponseCommand::ProcessCommitResponseCommand() {}
+ProcessCommitResponseCommand::ProcessCommitResponseCommand(
+ const sessions::OrderedCommitSet& commit_set,
+ const ClientToServerMessage& commit_message,
+ const ClientToServerResponse& commit_response)
+ : commit_set_(commit_set),
+ commit_message_(commit_message),
+ commit_response_(commit_response) {
+}
+
ProcessCommitResponseCommand::~ProcessCommitResponseCommand() {}
std::set<ModelSafeGroup> ProcessCommitResponseCommand::GetGroupsToChange(
@@ -57,10 +65,9 @@ std::set<ModelSafeGroup> ProcessCommitResponseCommand::GetGroupsToChange(
syncable::Directory* dir = session.context()->directory();
syncable::ReadTransaction trans(FROM_HERE, dir);
- const StatusController& status = session.status_controller();
- for (size_t i = 0; i < status.commit_ids().size(); ++i) {
+ for (size_t i = 0; i < commit_set_.Size(); ++i) {
groups_with_commits.insert(
- GetGroupForModelType(status.GetUnrestrictedCommitModelTypeAt(i),
+ GetGroupForModelType(commit_set_.GetModelTypeAt(i),
session.routing_info()));
}
@@ -68,19 +75,18 @@ std::set<ModelSafeGroup> ProcessCommitResponseCommand::GetGroupsToChange(
}
SyncerError ProcessCommitResponseCommand::ModelNeutralExecuteImpl(
- sessions::SyncSession* session) {
- const StatusController& status = session->status_controller();
- const ClientToServerResponse& response(status.commit_response());
- const vector<syncable::Id>& commit_ids(status.commit_ids());
+ SyncSession* session) {
+ syncable::Directory* dir = session->context()->directory();
+ const vector<syncable::Id>& commit_ids = commit_set_.GetAllCommitIds();
- if (!response.has_commit()) {
- // TODO(sync): What if we didn't try to commit anything?
+ if (!commit_response_.has_commit()) {
LOG(WARNING) << "Commit response has no commit body!";
+ ClearSyncingBits(dir, commit_ids);
return SERVER_RESPONSE_VALIDATION_FAILED;
}
- const CommitResponse& cr = response.commit();
- int commit_count = commit_ids.size();
+ const CommitResponse& cr = commit_response_.commit();
+ int commit_count = commit_set_.Size();
if (cr.entryresponse_size() != commit_count) {
LOG(ERROR) << "Commit response has wrong number of entries! Expected:" <<
commit_count << " Got:" << cr.entryresponse_size();
@@ -90,6 +96,7 @@ SyncerError ProcessCommitResponseCommand::ModelNeutralExecuteImpl(
if (cr.entryresponse(i).has_error_message())
LOG(ERROR) << " " << cr.entryresponse(i).error_message();
}
+ ClearSyncingBits(dir, commit_ids);
return SERVER_RESPONSE_VALIDATION_FAILED;
}
return SYNCER_OK;
@@ -99,60 +106,60 @@ SyncerError ProcessCommitResponseCommand::ModelChangingExecuteImpl(
SyncSession* session) {
SyncerError result = ProcessCommitResponse(session);
ExtensionsActivityMonitor* monitor = session->context()->extensions_monitor();
- if (session->status_controller().HasBookmarkCommitActivity() &&
- session->status_controller().syncer_status()
+
+ // This is to be run on one model only: the bookmark model.
+ if (session->status_controller().HasBookmarkCommitActivity()) {
+ // If the commit failed, return the data to the ExtensionsActivityMonitor.
+ if (session->status_controller().syncer_status()
.num_successful_bookmark_commits == 0) {
- monitor->PutRecords(session->extensions_activity());
+ monitor->PutRecords(session->extensions_activity());
+ }
+ // Clear our cached data in either case.
session->mutable_extensions_activity()->clear();
}
+
return result;
}
SyncerError ProcessCommitResponseCommand::ProcessCommitResponse(
SyncSession* session) {
syncable::Directory* dir = session->context()->directory();
-
StatusController* status = session->mutable_status_controller();
- const ClientToServerResponse& response(status->commit_response());
- const CommitResponse& cr = response.commit();
- const sync_pb::CommitMessage& commit_message =
- status->commit_message().commit();
-
- // If we try to commit a parent and child together and the parent conflicts
- // the child will have a bad parent causing an error. As this is not a
- // critical error, we trap it and don't LOG(ERROR). To enable this we keep
- // a map of conflicting new folders.
+ const CommitResponse& cr = commit_response_.commit();
+ const sync_pb::CommitMessage& commit_message = commit_message_.commit();
+
int transient_error_commits = 0;
int conflicting_commits = 0;
int error_commits = 0;
int successes = 0;
- set<syncable::Id> conflicting_new_folder_ids;
+
set<syncable::Id> deleted_folders;
ConflictProgress* conflict_progress = status->mutable_conflict_progress();
- OrderedCommitSet::Projection proj = status->commit_id_projection();
+ OrderedCommitSet::Projection proj = status->commit_id_projection(
+ commit_set_);
+
if (!proj.empty()) { // Scope for WriteTransaction.
WriteTransaction trans(FROM_HERE, SYNCER, dir);
for (size_t i = 0; i < proj.size(); i++) {
- CommitResponse::ResponseType response_type =
- ProcessSingleCommitResponse(&trans, cr.entryresponse(proj[i]),
- commit_message.entries(proj[i]),
- status->GetCommitIdAt(proj[i]),
- &conflicting_new_folder_ids,
- &deleted_folders);
+ CommitResponse::ResponseType response_type = ProcessSingleCommitResponse(
+ &trans,
+ cr.entryresponse(proj[i]),
+ commit_message.entries(proj[i]),
+ commit_set_.GetCommitIdAt(proj[i]),
+ &deleted_folders);
switch (response_type) {
case CommitResponse::INVALID_MESSAGE:
++error_commits;
break;
case CommitResponse::CONFLICT:
++conflicting_commits;
- // Only server CONFLICT responses will activate conflict resolution.
conflict_progress->AddServerConflictingItemById(
- status->GetCommitIdAt(proj[i]));
+ commit_set_.GetCommitIdAt(proj[i]));
break;
case CommitResponse::SUCCESS:
// TODO(sync): worry about sync_rate_ rate calc?
++successes;
- if (status->GetCommitModelTypeAt(proj[i]) == syncable::BOOKMARKS)
+ if (commit_set_.GetModelTypeAt(proj[i]) == syncable::BOOKMARKS)
status->increment_num_successful_bookmark_commits();
status->increment_num_successful_commits();
break;
@@ -171,16 +178,25 @@ SyncerError ProcessCommitResponseCommand::ProcessCommitResponse(
SyncerUtil::MarkDeletedChildrenSynced(dir, &deleted_folders);
int commit_count = static_cast<int>(proj.size());
- if (commit_count == (successes + conflicting_commits)) {
- // We consider conflicting commits as a success because things will work out
- // on their own when we receive them. Flags will be set so that
- // HasMoreToSync() will cause SyncScheduler to enter another sync cycle to
- // handle this condition.
+ if (commit_count == successes) {
return SYNCER_OK;
} else if (error_commits > 0) {
return SERVER_RETURN_UNKNOWN_ERROR;
} else if (transient_error_commits > 0) {
return SERVER_RETURN_TRANSIENT_ERROR;
+ } else if (conflicting_commits > 0) {
+ // This means that the server already has an item with this version, but
+ // we haven't seen that update yet. The correct response is to go back
+ // to the download upates phase and try to fetch the conflicting update
+ // so we can resolve it.
+ //
+ // The easiest and safest way to handle this is to treat it as a transient
+ // error. This will cause us to abort this sync cycle, wait a little while,
+ // then try again starting with a GetUpdate.
+ //
+ // TODO: Remove this option when the CONFLICT return value is fully
tim (not reviewing) 2012/05/15 22:25:00 Despite my earlier rant about defensive sounding c
+ // deprecated.
+ return SERVER_RETURN_TRANSIENT_ERROR;
} else {
LOG(FATAL) << "Inconsistent counts when processing commit response";
return SYNCER_OK;
@@ -200,7 +216,6 @@ ProcessCommitResponseCommand::ProcessSingleCommitResponse(
const sync_pb::CommitResponse_EntryResponse& pb_server_entry,
const sync_pb::SyncEntity& commit_request_entry,
const syncable::Id& pre_commit_id,
- std::set<syncable::Id>* conflicting_new_folder_ids,
set<syncable::Id>* deleted_folders) {
const CommitResponse_EntryResponse& server_entry =
@@ -229,10 +244,6 @@ ProcessCommitResponseCommand::ProcessSingleCommitResponse(
}
if (CommitResponse::CONFLICT == response) {
DVLOG(1) << "Conflict Committing: " << local_entry;
- // TODO(nick): conflicting_new_folder_ids is a purposeless anachronism.
- if (!pre_commit_id.ServerKnows() && local_entry.Get(IS_DIR)) {
- conflicting_new_folder_ids->insert(pre_commit_id);
- }
return response;
}
if (CommitResponse::RETRY == response) {
@@ -479,4 +490,22 @@ void ProcessCommitResponseCommand::ProcessSuccessfulCommitResponse(
}
}
+void ProcessCommitResponseCommand::ClearSyncingBits(
+ syncable::Directory *dir,
+ const vector<syncable::Id>& commit_ids) {
+ // This is part of the cleanup in the case of a failed commit. Normally we
+ // would unset the SYNCING bit when processing the commit response. In the
+ // failure case we don't process the response, so we need to clear those bits
+ // here.
+ syncable::WriteTransaction trans(FROM_HERE, syncable::SYNCER, dir);
+ for (size_t i = 0; i < commit_ids.size(); i++) {
+ syncable::MutableEntry entry(&trans, syncable::GET_BY_ID, commit_ids[i]);
+ if (entry.good()) {
+ entry.Put(syncable::SYNCING, false);
+ } else {
+ LOG(WARNING) << "Id: " << commit_ids[i] << " disappeared";
+ }
+ }
+}
+
} // namespace browser_sync

Powered by Google App Engine
This is Rietveld 408576698