blob: 603288ebcbd3162516a7dccebb6133d7da9fe36c [file] [log] [blame]
/*
* Copyright (C) 2016, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
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();
}
}