Search in sources :

Example 6 with ConnectionModel

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);
}
Also used : ArrayList(java.util.ArrayList) ConnectionModel(com.liulishuo.filedownloader.model.ConnectionModel)

Example 7 with ConnectionModel

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());
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Callable(java.util.concurrent.Callable) Future(java.util.concurrent.Future) ConnectionModel(com.liulishuo.filedownloader.model.ConnectionModel)

Aggregations

ConnectionModel (com.liulishuo.filedownloader.model.ConnectionModel)7 FileDownloadModel (com.liulishuo.filedownloader.model.FileDownloadModel)3 ArrayList (java.util.ArrayList)3 Cursor (android.database.Cursor)1 DownloadLaunchRunnable (com.liulishuo.filedownloader.download.DownloadLaunchRunnable)1 Callable (java.util.concurrent.Callable)1 Future (java.util.concurrent.Future)1