Permalink
Browse files

修复分块文件长度错误的bug

  • Loading branch information...
AriaLyy committed Nov 22, 2018
1 parent 5c6770b commit 3786a91ae2d8ca5e6d8d8550e402029312e6ef85
@@ -391,16 +391,20 @@ private void handleBlockRecord() {
"startLocation = %s; endLocation = %s; block = %s; tempLen = %s; i = %s",
tr.startLocation, tr.endLocation, blockLen, temp.length(), i));
if (tr.endLocation == realLocation) {
ALog.d(TAG, String.format("分块【%s】已完成,更新记录", temp.getPath()));
ALog.i(TAG, String.format("分块【%s】已完成,更新记录", temp.getPath()));
tr.startLocation = realLocation;
tr.isComplete = true;
mCompleteThreadNum++;
} else {
tr.isComplete = false;
if (realLocation != tr.startLocation) {
if (realLocation == tr.startLocation) {
i++;
continue;
}
if (realLocation > tr.startLocation) {
ALog.i(TAG, String.format("修正分块【%s】的进度记录为:%s", temp.getPath(), realLocation));
tr.startLocation = realLocation;
} else if (realLocation > tr.endLocation) {
} else {
ALog.i(TAG, String.format("分块【%s】错误,将重新开始该分块", temp.getPath()));
temp.delete();
tr.startLocation = i * blockLen;
@@ -415,7 +419,7 @@ private void handleBlockRecord() {
}
/**
* convertDb 为兼容性代码
* convertDb 是兼容性代码
* 从3.4.1开始,线程配置信息将存储在数据库中。
* 将配置文件的内容复制到数据库中,并将配置文件删除
*/
@@ -548,13 +552,9 @@ private AbsThreadTask createSingThreadTask(int i, long startL, long endL, long f
private void handleBreakpoint() {
long fileLength = mEntity.getFileSize();
long blockSize = fileLength / mTotalThreadNum;
int[] threadId = new int[mTotalThreadNum];
int rl = 0;
Set<Integer> threads = new HashSet<>();
mRecord.fileLength = fileLength;
for (int i = 0; i < mTotalThreadNum; i++) {
threadId[i] = -1;
}
if (mTaskEntity.isNewTask() && !handleNewTask()) {
return;
}
@@ -572,7 +572,7 @@ private void handleBreakpoint() {
}
if (tr.blockLen == 0) {
tr.blockLen = i == mTotalThreadNum - 1 ? (fileLength - i * blockSize) : blockSize;
tr.blockLen = CommonUtil.getBlockLen(fileLength, i, mTotalThreadNum);
}
if (tr.isComplete) {//该线程已经完成
@@ -605,22 +605,21 @@ private void handleBreakpoint() {
AbsThreadTask task = createSingThreadTask(i, startL, endL, fileLength, tr);
if (task == null) return;
mTask.put(i, task);
threadId[rl] = i;
rl++;
threads.add(i);
}
if (mConstance.CURRENT_LOCATION != 0
&& mConstance.CURRENT_LOCATION != mEntity.getCurrentProgress()) {
ALog.d(TAG, String.format("进度修正,当前进度:%s", mConstance.CURRENT_LOCATION));
mEntity.setCurrentProgress(mConstance.CURRENT_LOCATION);
}
saveRecord();
startThreadTask(threadId);
startThreadTask(threads);
}
/**
* 启动单线程任务
*/
private void startThreadTask(int[] recordL) {
private void startThreadTask(Set<Integer> recordL) {
if (isBreak()) {
return;
}
@@ -49,7 +49,7 @@
private final String TAG = "AbsThreadTask";
/**
* 当前子线程的下载位置
* 当前子线程相对于总长度的位置
*/
protected long mChildCurrentLocation = 0;
protected int mBufSize;
@@ -236,23 +236,59 @@ protected boolean mergeFile() {
f.delete();
}
}
File targetFile = new File(STATE.TASK_RECORD.filePath);
if (targetFile.exists() && targetFile.length() > mEntity.getFileSize()) {
ALog.e(TAG, String.format("任务【%s】分块文件合并失败,下载长度超出文件真实长度,downloadLen: %s,fileSize: %s",
mConfig.TEMP_FILE.getName(), targetFile.length(), mEntity.getFileSize()));
return false;
}
return true;
} else {
return false;
}
}
/**
* 检查下载完成的分块大小,如果下载完成的分块大小大于或小于分配的大小,则需要重新下载该分块
* 如果是非分块任务,直接返回{@code true}
*
* @return {@code true} 分块分大小正常,{@code false} 分块大小错误
*/
protected boolean checkBlock() {
if (!getTaskRecord().isBlock) {
return true;
}
ThreadRecord tr = getThreadRecord();
File blockFile = getBockFile();
if (!blockFile.exists() || blockFile.length() != tr.blockLen) {
ALog.i(TAG, String.format("分块【%s】下载错误,即将重新下载该分块,开始位置:%s,结束位置:%s", blockFile.getName(),
tr.startLocation, tr.endLocation));
retryThis(isBreak());
return false;
}
return true;
}
/**
* 停止任务
*/
public void stop() {
synchronized (AriaManager.LOCK) {
if (mConfig.SUPPORT_BP) {
final long currentTemp = mChildCurrentLocation;
final long stopLocation;
if (getTaskRecord().isBlock) {
File blockFile = getBockFile();
ThreadRecord tr = getThreadRecord();
long block = mEntity.getFileSize() / getTaskRecord().threadRecords.size();
stopLocation =
blockFile.exists() ? (tr.threadId * block + blockFile.length()) : tr.threadId * block;
} else {
stopLocation = mChildCurrentLocation;
}
STATE.STOP_NUM++;
ALog.d(TAG, String.format("任务【%s】thread__%s__停止【停止位置:%s】", mConfig.TEMP_FILE.getName(),
mConfig.THREAD_ID, currentTemp));
writeConfig(false, currentTemp);
ALog.d(TAG, String.format("任务【%s】thread__%s__停止【当前线程停止位置:%s】", mConfig.TEMP_FILE.getName(),
mConfig.THREAD_ID, stopLocation));
writeConfig(false, stopLocation);
if (STATE.isStop()) {
ALog.i(TAG, String.format("任务【%s】已停止", mConfig.TEMP_FILE.getName()));
STATE.isRunning = false;
@@ -273,7 +309,8 @@ protected void progress(long len) {
synchronized (AriaManager.LOCK) {
if (STATE.CURRENT_LOCATION > mEntity.getFileSize()) {
String errorMsg =
String.format("下载失败,下载长度超出文件大;currentLocation=%s, fileSize=%s", STATE.CURRENT_LOCATION,
String.format("下载失败,下载长度超出文件真实长度;currentLocation=%s, fileSize=%s",
STATE.CURRENT_LOCATION,
mEntity.getFileSize());
taskBreak = true;
fail(mChildCurrentLocation, new FileException(TAG, errorMsg), false);
@@ -376,31 +413,42 @@ private void handleRetryRecord() {
if (getTaskRecord().isBlock) {
ThreadRecord tr = getThreadRecord();
long block = mEntity.getFileSize() / getTaskRecord().threadRecords.size();
File file = mConfig.TEMP_FILE;
if (file.length() > tr.endLocation) {
ALog.i(TAG, String.format("分块【%s】错误,将重新下载该分块", file.getPath()));
boolean b = file.delete();
ALog.w(TAG, "删除:" + b);
File blockFile = getBockFile();
if (blockFile.length() > tr.blockLen) {
ALog.i(TAG, String.format("分块【%s】错误,将重新下载该分块", blockFile.getPath()));
blockFile.delete();
tr.startLocation = block * tr.threadId;
tr.isComplete = false;
mConfig.START_LOCATION = tr.startLocation;
} else if (file.length() == tr.endLocation) {
STATE.COMPLETE_THREAD_NUM++;
tr.isComplete = true;
} else {
tr.startLocation = block * tr.threadId + file.length();
mConfig.START_LOCATION = tr.startLocation;
} else if (blockFile.length() < tr.blockLen) {
tr.startLocation = block * tr.threadId + blockFile.length();
tr.isComplete = false;
mConfig.START_LOCATION = tr.startLocation;
STATE.CURRENT_LOCATION = getBlockRealTotalSize();
ALog.i(TAG, String.format("修正分块【%s】进度,开始位置:%s,当前进度:%s", file.getPath(), tr.startLocation,
ALog.i(TAG, String.format("修正分块【%s】,开始位置:%s,当前进度:%s", blockFile.getPath(), tr.startLocation,
STATE.CURRENT_LOCATION));
} else {
STATE.COMPLETE_THREAD_NUM++;
tr.isComplete = true;
}
tr.update();
} else {
mConfig.START_LOCATION = mChildCurrentLocation == 0 ? mConfig.START_LOCATION
: mConfig.THREAD_RECORD.startLocation;
}
}
/**
* 获取分块文件
*
* @return 分块文件
*/
private File getBockFile() {
return new File(String.format(AbsFileer.SUB_PATH, STATE.TASK_RECORD.filePath,
getThreadRecord().threadId));
}
/**
* 获取分块任务真实的进度
*
@@ -448,7 +496,9 @@ protected void writeConfig(boolean isComplete, final long record) {
ThreadRecord tr = getThreadRecord();
if (tr != null) {
tr.isComplete = isComplete;
if (getTaskRecord().isBlock || getTaskRecord().isOpenDynamicFile) {
if (getTaskRecord().isBlock) {
tr.startLocation = record;
} else if (getTaskRecord().isOpenDynamicFile) {
tr.startLocation = mConfig.TEMP_FILE.length();
} else {
if (0 < record && record < mConfig.END_LOCATION) {
@@ -133,6 +133,9 @@ private void handleComplete() {
if (isBreak()) {
return;
}
if (!checkBlock()) {
return;
}
ALog.i(TAG,
String.format("任务【%s】线程__%s__下载完毕", mConfig.TEMP_FILE.getName(), mConfig.THREAD_ID));
writeConfig(true, mConfig.END_LOCATION);
@@ -247,6 +247,9 @@ private void handleComplete() {
if (isBreak()) {
return;
}
if (!checkBlock()){
return;
}
if (mChildCurrentLocation == mConfig.END_LOCATION) {
//支持断点的处理
@@ -22,6 +22,8 @@
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DownloadSharePool;
import com.arialyy.aria.core.queue.pool.UploadSharePool;
import com.arialyy.aria.util.ALog;
import java.util.Map;
import java.util.Set;
@@ -32,18 +34,29 @@
*/
abstract class AbsTaskQueue<TASK extends AbsTask, TASK_ENTITY extends AbsTaskEntity>
implements ITaskQueue<TASK, TASK_ENTITY> {
protected final int TYPE_D_QUEUE = 1;
protected final int TYPE_DG_QUEUE = 2;
protected final int TYPE_U_QUEUE = 3;
private final String TAG = "AbsTaskQueue";
BaseCachePool<TASK> mCachePool;
BaseExecutePool<TASK> mExecutePool;
AbsTaskQueue() {
mCachePool = setCachePool();
mExecutePool = setExecutePool();
switch (getQueueType()) {
case TYPE_D_QUEUE:
case TYPE_DG_QUEUE:
mCachePool = DownloadSharePool.getInstance().cachePool;
mExecutePool = DownloadSharePool.getInstance().executePool;
break;
case TYPE_U_QUEUE:
mCachePool = UploadSharePool.getInstance().cachePool;
mExecutePool = UploadSharePool.getInstance().executePool;
break;
}
}
abstract BaseCachePool<TASK> setCachePool();
abstract BaseExecutePool<TASK> setExecutePool();
abstract int getQueueType();
@Override public boolean taskIsRunning(String key) {
return mExecutePool.getTask(key) != null;
@@ -19,9 +19,6 @@
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadGroupTask;
import com.arialyy.aria.core.download.DownloadGroupTaskEntity;
import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DownloadSharePool;
import com.arialyy.aria.core.scheduler.DownloadGroupSchedulers;
import com.arialyy.aria.util.ALog;
@@ -47,12 +44,8 @@ public static DownloadGroupTaskQueue getInstance() {
private DownloadGroupTaskQueue() {
}
@Override BaseCachePool<DownloadGroupTask> setCachePool() {
return DownloadSharePool.getInstance().cachePool;
}
@Override BaseExecutePool<DownloadGroupTask> setExecutePool() {
return DownloadSharePool.getInstance().executePool;
@Override int getQueueType() {
return TYPE_DG_QUEUE;
}
@Override public int getMaxTaskNum() {
@@ -19,11 +19,7 @@
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.TaskSchedulerType;
import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.DownloadSharePool;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.util.ALog;
import java.util.LinkedHashSet;
@@ -50,12 +46,8 @@ public static DownloadTaskQueue getInstance() {
private DownloadTaskQueue() {
}
@Override BaseCachePool<DownloadTask> setCachePool() {
return DownloadSharePool.getInstance().cachePool;
}
@Override BaseExecutePool<DownloadTask> setExecutePool() {
return DownloadSharePool.getInstance().executePool;
@Override int getQueueType() {
return TYPE_D_QUEUE;
}
@Override public int getConfigMaxNum() {
@@ -17,9 +17,6 @@
package com.arialyy.aria.core.queue;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.queue.pool.BaseCachePool;
import com.arialyy.aria.core.queue.pool.BaseExecutePool;
import com.arialyy.aria.core.queue.pool.UploadSharePool;
import com.arialyy.aria.core.scheduler.UploadSchedulers;
import com.arialyy.aria.core.upload.UploadTask;
import com.arialyy.aria.core.upload.UploadTaskEntity;
@@ -45,12 +42,8 @@ public static UploadTaskQueue getInstance() {
private UploadTaskQueue() {
}
@Override BaseCachePool<UploadTask> setCachePool() {
return UploadSharePool.getInstance().cachePool;
}
@Override BaseExecutePool<UploadTask> setExecutePool() {
return UploadSharePool.getInstance().executePool;
@Override int getQueueType() {
return TYPE_U_QUEUE;
}
@Override public int getConfigMaxNum() {
Oops, something went wrong.

0 comments on commit 3786a91

Please sign in to comment.