Skip to content

Commit

Permalink
[FIXED JENKINS-10094] Retry uploads on bad connections
Browse files Browse the repository at this point in the history
Moved "Verbose output in console" to new advanced section
Swtiched some of the checkboxes from entry/@title to checkbox/@title to prevent longer descriptions from reformatting the view too much
  • Loading branch information
bap2000 committed Jul 7, 2011
1 parent a48ba48 commit 6e3bef7
Show file tree
Hide file tree
Showing 11 changed files with 539 additions and 57 deletions.
41 changes: 30 additions & 11 deletions src/main/java/jenkins/plugins/publish_over/BPTransfer.java
Expand Up @@ -151,18 +151,27 @@ private void assertBaseDirectoryExists(final BPBuildInfo buildInfo) throws Excep
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public int transfer(final BPBuildInfo buildInfo, final BPClient client) throws Exception {
assertBaseDirectoryExists(buildInfo);
final DirectoryMaker dirMaker = new DirectoryMaker(buildInfo, client);
if (cleanRemote) {
dirMaker.resetToSubDirectory();
client.deleteTree();
}
int transferred = 0;
for (FilePath filePath : getSourceFiles(buildInfo)) {
dirMaker.changeAndMakeDirs(filePath);
transferFile(client, filePath);
transferred++;
return transfer(buildInfo, client, new TransferState(getSourceFiles(buildInfo)));
}

@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public int transfer(final BPBuildInfo buildInfo, final BPClient client, final TransferState state) {
try {
final DirectoryMaker dirMaker = new DirectoryMaker(buildInfo, client);
if (cleanRemote && !state.doneCleaning) {
dirMaker.resetToSubDirectory();
client.deleteTree();
state.doneCleaning = true;
}
while(state.transferred < state.sourceFiles.length) {
dirMaker.changeAndMakeDirs(state.sourceFiles[state.transferred]);
transferFile(client, state.sourceFiles[state.transferred]);
state.transferred++;
}
} catch (Exception e) {
throw new BapTransferException(e, state);
}
return transferred;
return state.transferred;
}

@SuppressWarnings("PMD.SignatureDeclareThrowsException")
Expand Down Expand Up @@ -328,4 +337,14 @@ public String toString() {
return addToToString(new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)).toString();
}

public static class TransferState {
private FilePath[] sourceFiles;
private int transferred;
private boolean doneCleaning;
private TransferState(final FilePath[] sourceFiles) {
this.sourceFiles = sourceFiles;
}
protected TransferState() { }
}

}
127 changes: 102 additions & 25 deletions src/main/java/jenkins/plugins/publish_over/BapPublisher.java
Expand Up @@ -33,32 +33,33 @@
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

// serializable + only actually 4 "real" methods in here all rest accessors and boiler str/has/eq
@SuppressWarnings({ "PMD.LooseCoupling", "PMD.TooManyMethods" })
public class BapPublisher<TRANSFER extends BPTransfer> implements Serializable {

private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(BapPublisher.class.getName());

private String configName;
private boolean verbose;
private ArrayList<TRANSFER> transfers;
private boolean useWorkspaceInPromotion;
private boolean usePromotionTimestamp;
private Retry retry;

public BapPublisher() { }

public BapPublisher(final String configName, final boolean verbose, final ArrayList<TRANSFER> transfers) {
this(configName, verbose, transfers, false, false);
}

public BapPublisher(final String configName, final boolean verbose, final ArrayList<TRANSFER> transfers,
final boolean useWorkspaceInPromotion, final boolean usePromotionTimestamp) {
final boolean useWorkspaceInPromotion, final boolean usePromotionTimestamp, final Retry retry) {
this.configName = configName;
this.verbose = verbose;
setTransfers(transfers);
this.useWorkspaceInPromotion = useWorkspaceInPromotion;
this.usePromotionTimestamp = usePromotionTimestamp;
this.retry = retry;
}

public String getConfigName() {
Expand Down Expand Up @@ -100,6 +101,10 @@ public final void setTransfers(final ArrayList<TRANSFER> transfers) {
}
}

public Retry getRetry() {
return retry;
}

private int sumTransfers(final List<Integer> transferred) {
int total = 0;
for (int tx : transferred) {
Expand Down Expand Up @@ -136,44 +141,32 @@ public void setEffectiveEnvironmentInBuildInfo(final BPBuildInfo buildInfo) {

@SuppressWarnings("PMD.SignatureDeclareThrowsException")
public void perform(final BPHostConfiguration hostConfig, final BPBuildInfo buildInfo) throws Exception {
buildInfo.println(Messages.console_connecting(configName));
final BPClient client = hostConfig.createClient(buildInfo);
final List<Integer> transferred = new ArrayList<Integer>();
try {
for (TRANSFER transfer : transfers) {
client.beginTransfers(transfer);
if (transfer.hasConfiguredSourceFiles())
transferred.add(transfer.transfer(buildInfo, client));
else
transferred.add(0);
client.endTransfers(transfer);
}
printNumberOfFilesTransferred(buildInfo, transferred);
} finally {
buildInfo.println(Messages.console_disconnecting(configName));
client.disconnectQuietly();
}
final Performer performer = new Performer(hostConfig, buildInfo);
printNumberOfFilesTransferred(buildInfo, performer.perform());
}

protected HashCodeBuilder addToHashCode(final HashCodeBuilder builder) {
return builder.append(configName).append(verbose).append(transfers)
.append(useWorkspaceInPromotion).append(usePromotionTimestamp);
.append(useWorkspaceInPromotion).append(usePromotionTimestamp)
.append(retry);
}

protected EqualsBuilder addToEquals(final EqualsBuilder builder, final BapPublisher that) {
return builder.append(configName, that.configName)
.append(verbose, that.verbose)
.append(transfers, that.transfers)
.append(useWorkspaceInPromotion, that.useWorkspaceInPromotion)
.append(usePromotionTimestamp, that.usePromotionTimestamp);
.append(usePromotionTimestamp, that.usePromotionTimestamp)
.append(retry, that.retry);
}

protected ToStringBuilder addToToString(final ToStringBuilder builder) {
return builder.append("configName", configName)
.append("verbose", verbose)
.append("transfers", transfers)
.append("useWorkspaceInPromotion", useWorkspaceInPromotion)
.append("usePromotionTimestamp", usePromotionTimestamp);
.append("usePromotionTimestamp", usePromotionTimestamp)
.append("retry", retry);
}

public boolean equals(final Object that) {
Expand All @@ -191,4 +184,88 @@ public String toString() {
return addToToString(new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)).toString();
}

private class Performer {

private final BPHostConfiguration hostConfig;
private final BPBuildInfo buildInfo;
private BPClient client;
private int remainingTries;
private ArrayList<TRANSFER> remainingTransfers = new ArrayList<TRANSFER>();
final List<Integer> transferred = new ArrayList<Integer>();
private boolean transferComplete;
private BPTransfer.TransferState transferState;
private Exception exception;

private Performer(final BPHostConfiguration hostConfig, final BPBuildInfo buildInfo) {
this.hostConfig = hostConfig;
this.buildInfo = buildInfo;
remainingTries = retry == null ? 0 : retry.getRetries();
remainingTransfers.addAll(transfers);
}

private List<Integer> perform() throws Exception {
do {
try {
buildInfo.println(Messages.console_connecting(configName));
client = hostConfig.createClient(buildInfo);
while (!remainingTransfers.isEmpty()) {
beginTransfers();
transfer();
endTransfers();
}
return transferred;
} catch (BapTransferException bte) {
transferState = bte.getState();
exception = (Exception) bte.getCause();
} catch (Exception e) {
exception = e;
} finally {
if (client != null) {
buildInfo.println(Messages.console_disconnecting(configName));
client.disconnectQuietly();
}
}
} while (remainingTries-- > 0 && delay());
throw exception;
}

private boolean delay() {
LOGGER.log(Level.WARNING, Messages.log_exceptionCaught_retrying(), exception);
buildInfo.println(Messages.console_retryDelay(exception.getLocalizedMessage(), retry.getRetryDelay()));
try {
Thread.sleep(retry.getRetryDelay());
} catch (InterruptedException ie) {
throw new BapPublisherException(Messages.exception_retryDelayInterrupted(), ie);
}
return true;
}

private void beginTransfers() {
client.beginTransfers(remainingTransfers.get(0));
}

private void transfer() throws Exception {
if (transferComplete) return;
final BPTransfer transfer = remainingTransfers.get(0);
if (!transfer.hasConfiguredSourceFiles()) {
transferred.add(0);
transferComplete = true;
return;
}
if (transferState == null)
transferred.add(transfer.transfer(buildInfo, client));
else
transferred.add(transfer.transfer(buildInfo, client, transferState));
transferComplete = true;
}

private void endTransfers() {
client.endTransfers(remainingTransfers.get(0));
remainingTransfers.remove(0);
transferState = null;
transferComplete = false;
}

}

}
Expand Up @@ -46,4 +46,8 @@ public BapPublisherException(final String message, final Throwable throwable) {
super(message, throwable);
}

public BapPublisherException(final Throwable throwable) {
super(throwable);
}

}
@@ -0,0 +1,44 @@
/*
* The MIT License
*
* Copyright (C) 2010-2011 by Anthony Robinson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.plugins.publish_over;

public class BapTransferException extends BapPublisherException {

private BPTransfer.TransferState state;

public BapTransferException(final Throwable throwable) {
this(throwable, null);
}

public BapTransferException(final Throwable throwable, final BPTransfer.TransferState state) {
super(throwable);
this.state = state;
}

public BPTransfer.TransferState getState() {
return state;
}

}
13 changes: 13 additions & 0 deletions src/main/java/jenkins/plugins/publish_over/JellySupport.java
Expand Up @@ -24,18 +24,31 @@

package jenkins.plugins.publish_over;

import hudson.model.Hudson;
import hudson.util.VersionNumber;

import java.util.regex.Pattern;

public class JellySupport {

public static final int MINIMUM_MINIMUM_HEIGHT = 1;
public static final int DEFAULT_MINIMUM_HEIGHT = 5;
private static final Pattern LINE_END = Pattern.compile("\r?\n");
private static final VersionNumber BOX_GETS_TITLE = new VersionNumber("1.389");
private static final VersionNumber BOX_GETS_CSS_SPACE = new VersionNumber("1.406");

public static final int textAreaHeight(final int minimum, final String content) {
final int min = Math.max(minimum, MINIMUM_MINIMUM_HEIGHT);
if (content == null) return min;
return Math.max(min, LINE_END.split(content).length);
}

public static final boolean boxMissingTitle() {
return Hudson.getVersion().isOlderThan(BOX_GETS_TITLE);
}

public static final boolean boxNeedsSpace() {
return Hudson.getVersion().isOlderThan(BOX_GETS_CSS_SPACE);
}

}

0 comments on commit 6e3bef7

Please sign in to comment.