diff --git a/src/main/java/com/skcraft/launcher/install/HttpDownloader.java b/src/main/java/com/skcraft/launcher/install/HttpDownloader.java index 0f8c1ee..fd38d96 100644 --- a/src/main/java/com/skcraft/launcher/install/HttpDownloader.java +++ b/src/main/java/com/skcraft/launcher/install/HttpDownloader.java @@ -34,6 +34,7 @@ @Log public class HttpDownloader implements Downloader { + private final Random random = new Random(); private final HashFunction hf = Hashing.sha1(); private final File tempDir; @@ -45,10 +46,10 @@ private final Set usedKeys = new HashSet(); private final List running = new ArrayList(); + private final List failed = new ArrayList(); private long downloaded = 0; private long total = 0; private int left = 0; - private boolean hasError = false; /** * Create a new downloader using the given executor. @@ -132,8 +133,10 @@ throw new IOException("Something went wrong", e); } - if (hasError) { - throw new IOException("Some files could not be downloaded"); + synchronized (this) { + if (failed.size() > 0) { + throw new IOException(failed.size() + "files could not be downloaded"); + } } } finally { executor.shutdownNow(); @@ -155,15 +158,20 @@ @Override public synchronized String getStatus() { + String failMessage = _("downloader.failedCount", failed.size()); if (running.size() == 1) { - return _("downloader.downloadingItem", running.get(0).getName()) + "\n" + running.get(0).getStatus(); + return _("downloader.downloadingItem", running.get(0).getName()) + + "\n" + running.get(0).getStatus() + + "\n" + failMessage; } else if (running.size() > 0) { StringBuilder builder = new StringBuilder(); for (HttpDownloadJob job : running) { builder.append("\n"); builder.append(job.getStatus()); } - return _("downloader.downloadingList", queue.size(), left) + builder.toString(); + return _("downloader.downloadingList", queue.size(), left, failed.size()) + + builder.toString() + + "\n" + failMessage; } else { return _("downloader.noDownloads"); } @@ -191,13 +199,19 @@ } download(); + + synchronized (HttpDownloader.this) { + downloaded += size; + } } catch (IOException e) { - hasError = true; + synchronized (HttpDownloader.this) { + failed.add(this); + } } catch (InterruptedException e) { log.info("Download of " + destFile + " was interrupted"); } finally { synchronized (HttpDownloader.this) { - downloaded += size; + left--; running.remove(this); } } @@ -228,14 +242,13 @@ for (URL url : urls) { // Sleep between each trial if (!first) { - Thread.sleep(retryDelay); + Thread.sleep((long) (retryDelay / 2 + (random.nextDouble() * retryDelay))); } first = false; try { request = HttpRequest.get(url); request.execute().expectResponseCode(200).saveContent(file); - left--; return; } catch (IOException e) { lastException = e; diff --git a/src/main/resources/com/skcraft/launcher/lang/Launcher.properties b/src/main/resources/com/skcraft/launcher/lang/Launcher.properties index ba0e749..a13d101 100644 --- a/src/main/resources/com/skcraft/launcher/lang/Launcher.properties +++ b/src/main/resources/com/skcraft/launcher/lang/Launcher.properties @@ -121,10 +121,11 @@ console.confirmKillTitle=Are you sure? downloader.downloadingItem=Downloading {0}... -downloader.downloadingList=Downloading {0} files... ({1} remaining) +downloader.downloadingList=Downloading {0} files... ({1} remaining, {2} failed) downloader.jobProgress={1,number}%\t{0} downloader.jobPending=...\t{0} downloader.noDownloads=No pending downloads. +downloader.failedCount=({0} have failed) progress.defaultStatus=Working... progress.percentTitle=({0}%) {1} @@ -145,7 +146,6 @@ instanceLoader.loadingLocal=Loading local instances from disk... instanceLoader.checkingRemote=Checking for new modpacks... instanceLauncher.preparing=Preparing for launch... -instanceLauncher.preparingAssets=Preparing {0} assets for game... instanceLauncher.collectingArgs=Collecting arguments... instanceLauncher.startingJava=Starting java...