/** * Why pause? not stop? because invoke this method(pause) will clear all data about this task in * memory, and stop the total processing about this task. but when you start the paused task, it * would be continue downloading from the breakpoint as default. * * @return If true, successful pause this task by status of pause, otherwise this task has already * in over status before invoke this method(Maybe occur high concurrent situation). * @see FileDownloader#pause(int) * @see FileDownloader#pause(FileDownloadListener) * @see FileDownloader#pauseAll() */ public boolean pause() { if (FileDownloadStatus.isOver(getStatus())) { if (FileDownloadLog.NEED_LOG) { /** * The over-status call-backed and set the over-status to this task between here area and * remove from the {@link FileDownloadList}. * * <p>High concurrent cause. */ FileDownloadLog.d( this, "High concurrent cause, Already is over, can't pause " + "again, %d %d", getStatus(), getId()); } return false; } setStatus(FileDownloadStatus.paused); _pauseExecute(); calcAverageSpeed(this.soFarBytes); // For make sure already added event listener for receive paused event FileDownloadList.getImpl().add(this); FileDownloadList.getImpl().remove(this, MessageSnapshotTaker.catchPause(this)); return true; }
/** * Reuse this task withhold request params: path、url、header、isForceReDownloader、etc. * * @return Successful reuse or not. */ public boolean reuse() { if (isRunning()) { FileDownloadLog.w( this, "This task is running %d, if you want start the same task," + " please create a new one by FileDownloader.create", getId()); return false; } this.using = false; this.etag = null; this.resuming = false; this.retryingTimes = 0; this.isReusedOldFile = false; this.ex = null; resetSpeed(); clearMarkAdded2List(); setStatus(FileDownloadStatus.INVALID_STATUS); this.soFarBytes = 0; this.totalBytes = 0; messenger.reAppointment(this); return true; }
/** * start download * * <p>用于启动一个单独任务 * * @return Download id */ public int start() { if (FileDownloadMonitor.isValid()) { FileDownloadMonitor.getMonitor().onRequestStart(this); } if (FileDownloadLog.NEED_LOG) { FileDownloadLog.v( this, "call start " + "url[%s], setPath[%s] listener[%s], tag[%s]", url, path, listener, tag); } boolean ready = true; try { _adjust(); _checkFile(path); } catch (Throwable e) { ready = false; setStatus(FileDownloadStatus.error); setEx(e); FileDownloadList.getImpl().add(this); FileDownloadList.getImpl().removeByError(this); } if (ready) { FileDownloadEventPool.getImpl().send2Service(new DownloadTaskEvent(this).requestStart()); } return getDownloadId(); }
/** * Pause task * * <p>停止任务, 对于线程而言会直接关闭,清理所有相关数据,不会hold住任何东西 * * <p>如果重新启动,默认会断点续传,所以为pause */ public boolean pause() { setStatus(FileDownloadStatus.paused); final boolean result = _pauseExecute(); // For make sure already added event listener for receive paused event FileDownloadList.getImpl().add(this); if (result) { FileDownloadList.getImpl().removeByPaused(this); } else { FileDownloadLog.w(this, "paused false %s", toString()); // 一直依赖不在下载进程队列中 // 只有可能是 串行 还没有执行到 or 并行还没来得及加入进的 FileDownloadList.getImpl().removeByPaused(this); } return result; }
private void update(final MessageSnapshot snapshot) { setStatus(snapshot.getStatus()); this.isLargeFile = snapshot.isLargeFile(); switch (snapshot.getStatus()) { case FileDownloadStatus.pending: this.soFarBytes = snapshot.getLargeSofarBytes(); this.totalBytes = snapshot.getLargeTotalBytes(); // notify getMessenger().notifyPending(snapshot); break; case FileDownloadStatus.started: // notify getMessenger().notifyStarted(snapshot); break; case FileDownloadStatus.connected: this.totalBytes = snapshot.getLargeTotalBytes(); this.resuming = snapshot.isResuming(); this.etag = snapshot.getEtag(); markStartDownload(); // notify getMessenger().notifyConnected(snapshot); break; case FileDownloadStatus.progress: this.soFarBytes = snapshot.getLargeSofarBytes(); calcSpeed(snapshot.getLargeSofarBytes()); // notify getMessenger().notifyProgress(snapshot); break; // case FileDownloadStatus.blockComplete: /** Handled by {@link FileDownloadList#removeByCompleted(BaseDownloadTask)} */ // break; case FileDownloadStatus.retry: this.soFarBytes = snapshot.getLargeSofarBytes(); this.ex = snapshot.getThrowable(); _setRetryingTimes(snapshot.getRetryingTimes()); resetSpeed(); // notify getMessenger().notifyRetry(snapshot); break; case FileDownloadStatus.error: this.ex = snapshot.getThrowable(); this.soFarBytes = snapshot.getLargeSofarBytes(); calcAverageSpeed(this.soFarBytes); // to FileDownloadList FileDownloadList.getImpl().remove(this, snapshot); break; case FileDownloadStatus.paused: /** Handled by {@link #pause()} */ break; case FileDownloadStatus.completed: this.isReusedOldFile = snapshot.isReusedDownloadedFile(); if (snapshot.isReusedDownloadedFile()) { this.etag = snapshot.getEtag(); } // only carry total data back this.soFarBytes = snapshot.getLargeTotalBytes(); this.totalBytes = snapshot.getLargeTotalBytes(); calcAverageSpeed(this.soFarBytes); // to FileDownloadList FileDownloadList.getImpl().remove(this, snapshot); break; case FileDownloadStatus.warn: resetSpeed(); final int count = FileDownloadList.getImpl().count(getId()); if (count <= 1) { // 1. this progress kill by sys and relive, // for add at least one listener // or 2. pre downloading task has already completed/error/paused // request status final int currentStatus = _getStatusFromServer(downloadId); FileDownloadLog.w( this, "warn, but no listener to receive progress, " + "switch to pending %d %d", getId(), currentStatus); //noinspection StatementWithEmptyBody if (FileDownloadStatus.isIng(currentStatus)) { // ing, has callbacks // keep and wait callback setStatus(FileDownloadStatus.pending); this.totalBytes = snapshot.getLargeTotalBytes(); this.soFarBytes = snapshot.getLargeSofarBytes(); markStartDownload(); ((MessageSnapshot.IWarnMessageSnapshot) snapshot).turnToPending(); getMessenger().notifyPending(snapshot); break; } else { // already over and no callback } } // to FileDownloadList FileDownloadList.getImpl().remove(this, snapshot); break; } }
MessageSnapshot catchException(Throwable ex) { setStatus(FileDownloadStatus.error); this.ex = ex; return MessageSnapshotTaker.catchException(this); }
/** @param transfer In order to optimize some of the data in some cases is not back */ void update(final FileDownloadTransferModel transfer) { switch (transfer.getStatus()) { case FileDownloadStatus.pending: if (getStatus() == FileDownloadStatus.pending) { FileDownloadLog.w(this, "already pending %d", getDownloadId()); break; } this.setStatus(transfer.getStatus()); this.setSoFarBytes(transfer.getSoFarBytes()); this.setTotalBytes(transfer.getTotalBytes()); // notify getDriver().notifyPending(); break; case FileDownloadStatus.connected: if (getStatus() == FileDownloadStatus.connected) { FileDownloadLog.w(this, "already connected %d", getDownloadId()); break; } setStatus(transfer.getStatus()); setTotalBytes(transfer.getTotalBytes()); setSoFarBytes(transfer.getSoFarBytes()); this.isContinue = transfer.isContinue(); this.etag = transfer.getEtag(); // notify getDriver().notifyConnected(); break; case FileDownloadStatus.progress: if (getStatus() == FileDownloadStatus.progress && transfer.getSoFarBytes() == getLargeFileSoFarBytes()) { FileDownloadLog.w(this, "%d unused values! by process callback", getDownloadId()); break; } setStatus(transfer.getStatus()); setSoFarBytes(transfer.getSoFarBytes()); // notify getDriver().notifyProgress(); break; case FileDownloadStatus.blockComplete: /** Handled by {@link FileDownloadList#removeByCompleted(BaseDownloadTask)} */ break; case FileDownloadStatus.retry: if (getStatus() == FileDownloadStatus.retry && getRetryingTimes() == transfer.getRetryingTimes()) { FileDownloadLog.w( this, "%d already retry! %d %d %s", getDownloadId(), getRetryingTimes(), getAutoRetryTimes(), transfer.getThrowable()); break; } setStatus(transfer.getStatus()); setSoFarBytes(transfer.getSoFarBytes()); setEx(transfer.getThrowable()); _setRetryingTimes(transfer.getRetryingTimes()); // notify getDriver().notifyRetry(); break; case FileDownloadStatus.error: if (getStatus() == FileDownloadStatus.error) { FileDownloadLog.w( this, "%d already err(%s) , callback by other status same transfer", getDownloadId(), getEx()); break; } setStatus(transfer.getStatus()); setEx(transfer.getThrowable()); setSoFarBytes(transfer.getSoFarBytes()); // to FileDownloadList FileDownloadList.getImpl().removeByError(this); break; case FileDownloadStatus.paused: /** Handled by {@link #pause()} */ break; case FileDownloadStatus.completed: if (getStatus() == FileDownloadStatus.completed) { FileDownloadLog.w( this, "%d already completed , callback by process with same transfer", getDownloadId()); break; } this.isReusedOldFile = transfer.isUseOldFile(); setStatus(transfer.getStatus()); // only carry total data back setSoFarBytes(transfer.getTotalBytes()); setTotalBytes(transfer.getTotalBytes()); // to FileDownloadList FileDownloadList.getImpl().removeByCompleted(this); break; case FileDownloadStatus.warn: if (getStatus() == FileDownloadStatus.warn) { FileDownloadLog.w( this, "%d already warn , callback by process with same transfer", getDownloadId()); break; } final int count = FileDownloadList.getImpl().count(getDownloadId()); if (count <= 1) { // 1. this progress kill by sys and relive, // for add at least one listener // or 2. pre downloading task has already completed/error/paused // request status final int currentStatus = _getStatusFromServer(downloadId); FileDownloadLog.w( this, "warn, but no listener to receive progress, " + "switch to pending %d %d", getDownloadId(), currentStatus); if (FileDownloadStatus.isIng(currentStatus)) { // ing, has callbacks // keep and wait callback setStatus(FileDownloadStatus.pending); getDriver().notifyPending(); break; } else { // already over and no callback } } setStatus(transfer.getStatus()); // to FileDownloadList FileDownloadList.getImpl().removeByWarn(this); break; } }