blob: 273760bc6ed35d76bfe0e5c19dd82ab5d80f5b9b [file] [log] [blame]
/*
* Copyright (C) 2016, Google Inc. and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.internal.ketch;
import java.util.Collection;
import java.util.Map;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceiveCommand;
/**
* A push request sending objects to a replica, and its result.
* <p>
* Implementors of {@link org.eclipse.jgit.internal.ketch.KetchReplica} must
* populate the command result fields, {@link #setRefs(Map)}, and call one of
* {@link #setException(Repository, Throwable)} or {@link #done(Repository)} to
* finish processing.
*/
public class ReplicaPushRequest {
private final KetchReplica replica;
private final Collection<ReceiveCommand> commands;
private Map<String, Ref> refs;
private Throwable exception;
private boolean notified;
/**
* Construct a new push request for a replica.
*
* @param replica
* the replica being pushed to.
* @param commands
* commands to be executed.
*/
public ReplicaPushRequest(KetchReplica replica,
Collection<ReceiveCommand> commands) {
this.replica = replica;
this.commands = commands;
}
/**
* Get commands to be executed, and their results.
*
* @return commands to be executed, and their results.
*/
public Collection<ReceiveCommand> getCommands() {
return commands;
}
/**
* Get remote references, usually from the advertisement.
*
* @return remote references, usually from the advertisement.
*/
@Nullable
public Map<String, Ref> getRefs() {
return refs;
}
/**
* Set references observed from the replica.
*
* @param refs
* references observed from the replica.
*/
public void setRefs(Map<String, Ref> refs) {
this.refs = refs;
}
/**
* Get exception thrown, if any.
*
* @return exception thrown, if any.
*/
@Nullable
public Throwable getException() {
return exception;
}
/**
* Mark the request as crashing with a communication error.
* <p>
* This method may take significant time acquiring the leader lock and
* updating the Ketch state machine with the failure.
*
* @param repo
* local repository reference used by the push attempt.
* @param err
* exception thrown during communication.
*/
public void setException(@Nullable Repository repo, Throwable err) {
if (KetchReplica.log.isErrorEnabled()) {
KetchReplica.log.error(describe("failed"), err); //$NON-NLS-1$
}
if (!notified) {
notified = true;
exception = err;
replica.afterPush(repo, this);
}
}
/**
* Mark the request as completed without exception.
* <p>
* This method may take significant time acquiring the leader lock and
* updating the Ketch state machine with results from this replica.
*
* @param repo
* local repository reference used by the push attempt.
*/
public void done(Repository repo) {
if (KetchReplica.log.isDebugEnabled()) {
KetchReplica.log.debug(describe("completed")); //$NON-NLS-1$
}
if (!notified) {
notified = true;
replica.afterPush(repo, this);
}
}
private String describe(String heading) {
StringBuilder b = new StringBuilder();
b.append("push to "); //$NON-NLS-1$
b.append(replica.describeForLog());
b.append(' ').append(heading).append(":\n"); //$NON-NLS-1$
for (ReceiveCommand cmd : commands) {
b.append(String.format(
" %-12s %-12s %s %s", //$NON-NLS-1$
LeaderSnapshot.str(cmd.getOldId()),
LeaderSnapshot.str(cmd.getNewId()),
cmd.getRefName(),
cmd.getResult()));
if (cmd.getMessage() != null) {
b.append(' ').append(cmd.getMessage());
}
b.append('\n');
}
return b.toString();
}
}