/** * Given a file and a source this will start a worker-less file downloading. * * @param nF * @param bestSource */ private void startFileDownloading(DownloadFile nF, DownloadSource bestSource) { // first ensure that the file is not already complete on disk: if (downloadFileCompleteOnDisk(nF)) { Logger.warn("Complete download: " + nF + " was in the queue. Issueing completion."); nF.downloadComplete(); // issue completion wereCompleteItemsInQueue = true; return; } // Create a new info container for the file (if it has never been started before, or if for some // reason there are no chunks in it (corrupt for some reason? broken code in the past probably)) if (nF.active == null) { if (nF.getSize() == 0) { // zero byte files do not need downloading. (and indeed they will fail to dispatch correctly // as they will never have any incomplete chunks) try { nF.getFile().createNewFile(); nF.downloadComplete(); wereCompleteItemsInQueue = true; return; } catch (IOException e) { Logger.severe( "Empty file: " + nF.getFile().getPath() + " couldn't be created on disk: " + e); } } nF.active = new DownloadInfo(nF); } else { if (nF.active.isComplete()) { Logger.warn("Complete download: " + nF + " was in the queue. Issueing completion."); nF.downloadComplete(); wereCompleteItemsInQueue = true; return; } else if (nF.active.chunks.size() == 0) { Logger.warn( "Active download '" + nF + "' in queue with no chunks. Restarting download from the beginning."); nF.active = new DownloadInfo(nF); } } try { // Create the new worker: DownloadWorker w = DownloadWorker.getDownloadWorker(this, nF.active); nF.active.worker = w; workers.add(w); // Start one of the download chunks present in the info: for (DownloadChunk c : w.getIncompleteInactiveChunks()) { w.downloadChunk(c, bestSource, downloadThreadPool); break; } } catch (IOException e) { Logger.severe("Unable to dispatch a download: " + e); Logger.log(e); } }
/** * Finds a file that is not being serviced by a download worker and starts to download it. * * @return true iff there was a file in the queue to consider, false otherwise. */ private synchronized boolean dispatchFile() { // 1) establish the active directory: DownloadFile nF = controller.q.getInactiveDownloadFile(); if (nF != null) { // Logger.log("attempting to dispatch: "+nF); // start it downloading... // 1) find a source for the download: Map<String, DownloadSource> sources = controller.ssvr.getIndexNodeCommunicator().getSourcesForFile(nF.hash); if (sources.isEmpty()) { nF.notifyNoSources(); } else { startFileDownloading(nF, controller.peerstats.getBestSource(sources)); } return true; } else { // Logger.log("Nothing to dispatch."); return false; } }
/** * Checks if the downloadFile specified has been completed already. This returns true iff: ) file * exists ) is expected size ) hashes to the same fs2 hash. * * @param f * @return */ private boolean downloadFileCompleteOnDisk(DownloadFile f) { try { File onDisk = f.getFile(); if (!onDisk.isFile()) return false; if (onDisk.length() != f.size) return false; if (!ThrottledFileDigester.fs2DigestFile(onDisk, null).equals(f.hash)) return false; } catch (Exception e) { Logger.warn("Couldn't test for file completion on disk: " + e); Logger.log(e); return false; } return true; // it's already complete! }