diff options
4 files changed, 50 insertions, 6 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorRequest.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorRequest.java index 021f843be..3cca98864 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorRequest.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorRequest.java @@ -130,7 +130,25 @@ public class MirrorRequest extends ArtifactRequest { return destinationDescriptor; } + /** + * Keep retrying the source repository until it reports back that it will be impossible + * to get the artifact from it. + * @param destinationDescriptor + * @param sourceDescriptor + * @param monitor + * @return the status of the transfer operation + */ private IStatus transfer(IArtifactDescriptor destinationDescriptor, IArtifactDescriptor sourceDescriptor, IProgressMonitor monitor) { + IStatus status = Status.OK_STATUS; + // go until we get one (OK), there are no more mirrors to consider or the operation is cancelled. + // TODO this needs to be redone with a much better mirror management scheme. + do { + status = transferSingle(destinationDescriptor, sourceDescriptor, monitor); + } while (status.getSeverity() == IStatus.ERROR && status.getCode() == IArtifactRepository.CODE_RETRY); + return status; + } + + private IStatus transferSingle(IArtifactDescriptor destinationDescriptor, IArtifactDescriptor sourceDescriptor, IProgressMonitor monitor) { OutputStream destination; try { destination = target.getOutputStream(destinationDescriptor); diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorSelector.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorSelector.java index a155d709f..d72daab92 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorSelector.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/MirrorSelector.java @@ -232,6 +232,16 @@ public class MirrorSelector { } } + /** + * Return whether or not all the mirrors for this selector have proven to be invalid + * @return whether or not there is a vaild mirror in this selector. + */ + public synchronized boolean hasValidMirror() { + // return true if there is a mirror and it has not failed. Since the mirrors + // list is sorted with failures last, we only have to test the first element for failure. + return mirrors != null && mirrors.length > 0 && mirrors[0].failureCount == 0; + } + /** * Selects a mirror from the given list of mirrors. Returns null if a mirror * could not be found. diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java index f7f0c1e69..215c3b09f 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java @@ -421,14 +421,17 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme IStatus result = getTransport().download(mirrorLocation, destination, monitor); if (mirrors != null) mirrors.reportResult(mirrorLocation, result); - if (result.getSeverity() == IStatus.CANCEL) + if (result.isOK() || result.getSeverity() == IStatus.CANCEL) return result; if (monitor.isCanceled()) return Status.CANCEL_STATUS; - if (result.isOK() || baseLocation.equals(mirrorLocation)) - return result; - //maybe we hit a bad mirror - try the base location - return getTransport().download(baseLocation, destination, monitor); + // If there are more valid mirrors then return an error with a special code that tells the caller + // to keep trying. Note that the message in the status is largely irrelevant but the child + // status tells the story of why we failed on this try. + // TODO find a better way of doing this. + if (mirrors != null && mirrors.hasValidMirror()) + return new MultiStatus(Activator.ID, CODE_RETRY, new IStatus[] {result}, "Retry another mirror", null); //$NON-NLS-1$ + return result; } /** @@ -466,7 +469,13 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme return status; status = downloadArtifact(descriptor, destination, monitor); - return reportStatus(descriptor, destination, status); + IStatus result = reportStatus(descriptor, destination, status); + // if the original status was RETRY then ensure that we return that status. It is + // however important to call reportStatus() either way as it updates information + // in addition to collecting status. + // TODO we should remove this when there is more time for testing. + return status.getCode() == CODE_RETRY ? status : result; + } public synchronized IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) { diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java index cbcec403e..2da166ee2 100644 --- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java @@ -27,6 +27,13 @@ import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.Abstr * </p> */ public interface IArtifactRepository extends IRepository { + + /** + * The return code to use when a client could/should retry a failed getArtifact() operation. + * For example, the repository may have additional mirrors that could be consulted. + */ + public static int CODE_RETRY = 13; + /** * Add the given descriptor to the set of descriptors in this repository. This is * a relatively low-level operation that should be used only when the actual related |