use of com.liulishuo.filedownloader.model.ConnectionModel in project FileDownloader by lingochamp.
the class DownloadLaunchRunnable method realDownloadWithMultiConnectionFromBeginning.
private void realDownloadWithMultiConnectionFromBeginning(final long totalLength, final int connectionCount) throws InterruptedException {
long startOffset = 0;
final long eachRegion = totalLength / connectionCount;
final int id = model.getId();
final List<ConnectionModel> connectionModelList = new ArrayList<>();
for (int i = 0; i < connectionCount; i++) {
final long endOffset;
if (i == connectionCount - 1) {
// avoid float precision error
endOffset = ConnectionProfile.RANGE_INFINITE;
} else {
// [startOffset, endOffset)
endOffset = startOffset + eachRegion - 1;
}
final ConnectionModel connectionModel = new ConnectionModel();
connectionModel.setId(id);
connectionModel.setIndex(i);
connectionModel.setStartOffset(startOffset);
connectionModel.setCurrentOffset(startOffset);
connectionModel.setEndOffset(endOffset);
connectionModelList.add(connectionModel);
database.insertConnectionModel(connectionModel);
startOffset += eachRegion;
}
model.setConnectionCount(connectionCount);
database.updateConnectionCount(id, connectionCount);
fetchWithMultipleConnection(connectionModelList, totalLength);
}
use of com.liulishuo.filedownloader.model.ConnectionModel in project FileDownloader by lingochamp.
the class DownloadLaunchRunnable method fetchWithMultipleConnection.
private void fetchWithMultipleConnection(final List<ConnectionModel> connectionModelList, final long totalLength) throws InterruptedException {
final int id = model.getId();
final String etag = model.getETag();
final String url = redirectedUrl != null ? redirectedUrl : model.getUrl();
final String path = model.getTempFilePath();
if (FileDownloadLog.NEED_LOG) {
FileDownloadLog.d(this, "fetch data with multiple connection(count: [%d]) for task[%d] totalLength[%d]", connectionModelList.size(), id, totalLength);
}
long totalOffset = 0;
// why not with etag when not resume from the database? because do this can avoid
// precondition failed on separate downloading.
final boolean withEtag = isResumeAvailableOnDB;
for (ConnectionModel connectionModel : connectionModelList) {
final long contentLength;
if (connectionModel.getEndOffset() == ConnectionProfile.RANGE_INFINITE) {
// must be the last one
contentLength = totalLength - connectionModel.getCurrentOffset();
} else {
contentLength = connectionModel.getEndOffset() - connectionModel.getCurrentOffset() + 1;
}
totalOffset += (connectionModel.getCurrentOffset() - connectionModel.getStartOffset());
if (contentLength == 0) {
// it has already done, so pass.
if (FileDownloadLog.NEED_LOG) {
FileDownloadLog.d(this, "pass connection[%d-%d], because it has been completed", connectionModel.getId(), connectionModel.getIndex());
}
continue;
}
final DownloadRunnable.Builder builder = new DownloadRunnable.Builder();
final ConnectionProfile connectionProfile = ConnectionProfile.ConnectionProfileBuild.buildConnectionProfile(connectionModel.getStartOffset(), connectionModel.getCurrentOffset(), connectionModel.getEndOffset(), contentLength);
final DownloadRunnable runnable = builder.setId(id).setConnectionIndex(connectionModel.getIndex()).setCallback(this).setUrl(url).setEtag(withEtag ? etag : null).setHeader(userRequestHeader).setWifiRequired(isWifiRequired).setConnectionModel(connectionProfile).setPath(path).build();
if (FileDownloadLog.NEED_LOG) {
FileDownloadLog.d(this, "enable multiple connection: %s", connectionModel);
}
if (runnable == null) {
throw new IllegalArgumentException("the download runnable must not be null!");
}
downloadRunnableList.add(runnable);
}
if (totalOffset != model.getSoFar()) {
FileDownloadLog.w(this, "correct the sofar[%d] from connection table[%d]", model.getSoFar(), totalOffset);
model.setSoFar(totalOffset);
}
List<Callable<Object>> subTasks = new ArrayList<>(downloadRunnableList.size());
for (DownloadRunnable runnable : downloadRunnableList) {
if (paused) {
runnable.pause();
continue;
}
subTasks.add(Executors.callable(runnable));
}
if (paused) {
model.setStatus(FileDownloadStatus.paused);
return;
}
List<Future<Object>> subTaskFutures = DOWNLOAD_EXECUTOR.invokeAll(subTasks);
if (FileDownloadLog.NEED_LOG) {
for (Future<Object> future : subTaskFutures) {
FileDownloadLog.d(this, "finish sub-task for [%d] %B %B", id, future.isDone(), future.isCancelled());
}
}
}
Aggregations