修复ftp上传完成后,删除服务器端的文件,无法重新下载的问题

This commit is contained in:
laoyuyu
2020-01-06 19:59:17 +08:00
parent e14928e260
commit 8158c58d6e
29 changed files with 290 additions and 74 deletions

View File

@@ -53,7 +53,7 @@ public class DownloadGroupEntity extends AbsGroupEntity {
getSubEntities().get(0).getUrl())) {
return ITaskWrapper.ERROR;
}
return getSubEntities().get(0).getUrl().startsWith("ftp") ? ITaskWrapper.D_FTP_DIR
return (groupHash.startsWith("ftp") || groupHash.startsWith("sftp")) ? ITaskWrapper.D_FTP_DIR
: ITaskWrapper.DG_HTTP;
}

View File

@@ -267,7 +267,8 @@ public abstract class AbsGroupLoader implements ILoaderVisitor, ILoader {
Looper looper = Looper.myLooper();
initState(looper);
getState().setSubSize(getWrapper().getSubTaskWrapper().size());
if (getState().getCompleteNum() == getState().getSubSize()) {
if (getState().getCompleteNum() != 0
&& getState().getCompleteNum() == getState().getSubSize()) {
mListener.onComplete();
return;
}

View File

@@ -16,6 +16,7 @@
package com.arialyy.aria.core.group;
import android.os.Handler;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.IUtil;
@@ -81,6 +82,10 @@ public abstract class AbsSubDLoadUtil implements IUtil, Runnable {
return mWrapper.getEntity();
}
public TaskRecord getRecord(){
return getLoader().getRecord();
}
@Override public void run() {
if (isStop || isCancel) {
return;

View File

@@ -23,7 +23,7 @@ import java.util.Set;
/**
* 组合任务执行中的状态信息
*/
public class GroupRunState {
public final class GroupRunState {
/**
* 子任务数
*/

View File

@@ -22,7 +22,7 @@ import com.arialyy.aria.core.task.AbsGroupTask;
* Created by lyy on 2017/9/8.
* 任务组参数传递
*/
public class GroupSendParams<GROUP_TASK extends AbsGroupTask, ENTITY extends AbsNormalEntity> {
public final class GroupSendParams<GROUP_TASK extends AbsGroupTask, ENTITY extends AbsNormalEntity> {
public GROUP_TASK groupTask;
public ENTITY entity;

View File

@@ -20,21 +20,20 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.config.Configuration;
import com.arialyy.aria.core.inf.IThreadStateManager;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.manager.ThreadTaskManager;
import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.NetUtils;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.io.File;
/**
* 组合任务子任务调度器,用于调度任务的开始、停止、失败、完成等情况
* 该调度器生命周期和{@link AbsGroupLoaderUtil}生命周期一致
*/
class SimpleSchedulers implements Handler.Callback {
final class SimpleSchedulers implements Handler.Callback {
private static final String TAG = "SimpleSchedulers";
private SimpleSubQueue mQueue;
private GroupRunState mGState;
@@ -86,7 +85,8 @@ class SimpleSchedulers implements Handler.Callback {
ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName);
break;
case IThreadStateManager.STATE_FAIL:
handleFail(loaderUtil);
boolean needRetry = b.getBoolean(IThreadStateManager.DATA_RETRY, false);
handleFail(loaderUtil, needRetry);
ThreadTaskManager.getInstance().removeSingleTaskThread(mKey, threadName);
break;
}
@@ -98,18 +98,19 @@ class SimpleSchedulers implements Handler.Callback {
* 1、子任务失败次数大于等于配置的重试次数才能认为子任务停止
* 2、stopNum + failNum + completeNum + cacheNum == subSize则认为组合任务停止
* 3、failNum == subSize只有全部的子任务都失败了才能任务组合任务失败
*
* @param needRetry true 需要重试false 不需要重试
*/
private synchronized void handleFail(final AbsSubDLoadUtil loaderUtil) {
private synchronized void handleFail(final AbsSubDLoadUtil loaderUtil, boolean needRetry) {
Configuration config = Configuration.getInstance();
long interval = config.dGroupCfg.getSubReTryInterval();
int num = config.dGroupCfg.getSubReTryNum();
boolean isNotNetRetry = config.appCfg.isNotNetRetry();
final int reTryNum = num;
if ((!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry)
if (!needRetry
|| (!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry)
|| loaderUtil.getLoader() == null // 如果获取不到文件信息loader为空
|| loaderUtil.getEntity().getFailNum() > reTryNum) {
|| loaderUtil.getEntity().getFailNum() > num) {
mQueue.removeTaskFromExecQ(loaderUtil);
mGState.listener.onSubFail(loaderUtil.getEntity(), new TaskException(TAG,
String.format("任务组子任务【%s】下载失败下载地址【%s】", loaderUtil.getEntity().getFileName(),
@@ -127,20 +128,7 @@ class SimpleSchedulers implements Handler.Callback {
}
return;
}
// 如果获取不到文件信息loader为空
final ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1);
timer.schedule(new Runnable() {
@Override public void run() {
AbsEntity entity = loaderUtil.getEntity();
if (entity.getFailNum() <= reTryNum) {
ALog.d(TAG, String.format("任务【%s】开始重试", loaderUtil.getEntity().getFileName()));
loaderUtil.reStart();
} else {
startNext();
}
}
}, interval, TimeUnit.MILLISECONDS);
SimpleSubRetryQueue.getInstance().offer(loaderUtil);
}
/**
@@ -175,6 +163,11 @@ class SimpleSchedulers implements Handler.Callback {
*/
private synchronized void handleComplete(AbsSubDLoadUtil loader) {
ALog.d(TAG, String.format("子任务【%s】完成", loader.getEntity().getFileName()));
if (loader.getRecord().isBlock) {
File partFile =
new File(String.format(IRecordHandler.SUB_PATH, loader.getRecord().filePath, 0));
partFile.renameTo(new File(loader.getRecord().filePath));
}
ThreadTaskManager.getInstance().removeTaskThread(loader.getKey());
mGState.listener.onSubComplete(loader.getEntity());
mQueue.removeTaskFromExecQ(loader);

View File

@@ -29,7 +29,7 @@ import java.util.Set;
/**
* 组合任务队列,该队列生命周期和{@link AbsGroupLoaderUtil}生命周期一致
*/
class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
final class SimpleSubQueue implements ISubQueue<AbsSubDLoadUtil> {
private final String TAG = CommonUtil.getClassName(getClass());
/**
* 缓存下载器

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.group;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 子任务重试队列
*/
final class SimpleSubRetryQueue {
private volatile static SimpleSubRetryQueue INSTANCE = null;
private ExecutorService pool = new ThreadPoolExecutor(5, 100,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
public synchronized static SimpleSubRetryQueue getInstance() {
if (INSTANCE == null) {
synchronized (SimpleSubRetryQueue.class) {
INSTANCE = new SimpleSubRetryQueue();
}
}
return INSTANCE;
}
private SimpleSubRetryQueue() {
}
void offer(AbsSubDLoadUtil subDLoadUtil) {
pool.submit(subDLoadUtil.getLoader());
}
}

View File

@@ -1,6 +1,8 @@
package com.arialyy.aria.core.loader;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.AbsNormalEntity;
@@ -133,7 +135,16 @@ public abstract class AbsNormalTTBuilder implements IThreadTaskBuilder {
if (tr.isComplete) {//该线程已经完成
currentProgress += endL - startL;
ALog.d(TAG, String.format("任务【%s】线程__%s__已完成", mWrapper.getKey(), i));
mStateHandler.obtainMessage(IThreadStateManager.STATE_COMPLETE).sendToTarget();
Message msg = mStateHandler.obtainMessage();
msg.what = IThreadStateManager.STATE_COMPLETE;
Bundle b = msg.getData();
if (b == null){
b = new Bundle();
}
b.putString(IThreadStateManager.DATA_THREAD_NAME,
CommonUtil.getThreadName(getEntity().getUrl(), tr.threadId));
msg.setData(b);
msg.sendToTarget();
continue;
}

View File

@@ -48,6 +48,7 @@ public final class SubLoader implements ILoader, ILoaderVisitor {
private IRecordHandler recordHandler;
private IThreadTask threadTask;
private String parentKey;
private TaskRecord record;
public SubLoader(AbsTaskWrapper wrapper, Handler schedulers) {
this.wrapper = wrapper;
@@ -92,7 +93,7 @@ public final class SubLoader implements ILoader, ILoaderVisitor {
}
private void handlerTask() {
TaskRecord record = recordHandler.getRecord(wrapper.getEntity().getFileSize());
record = recordHandler.getRecord(wrapper.getEntity().getFileSize());
if (record.threadRecords != null
&& !TextUtils.isEmpty(record.filePath)
&& new File(record.filePath).exists()
@@ -123,6 +124,10 @@ public final class SubLoader implements ILoader, ILoaderVisitor {
}
}
public TaskRecord getRecord(){
return record;
}
public void setParentKey(String parentKey) {
this.parentKey = parentKey;
}

View File

@@ -86,11 +86,17 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
mEntity = mTaskWrapper.getEntity();
mLastSaveTime = System.currentTimeMillis();
mConfigThreadPool = Executors.newCachedThreadPool();
isNotNetRetry = AriaConfig.getInstance().getAConfig().isNotNetRetry();
mRangeProgress = mRecord.startLocation;
mLastRangeProgress = mRangeProgress;
updateInterval = config.updateInterval;
checkFileExist();
}
private void checkFileExist() {
if (!getConfig().tempFile.exists()) {
FileUtil.createFile(getConfig().tempFile);
}
}
/**

View File

@@ -98,7 +98,7 @@ class DelegateFind extends AbsDelegate {
*/
<T extends AbsDbWrapper> List<T> findRelationData(SQLiteDatabase db, Class<T> clazz,
String... expression) {
return exeRelationSql(db, clazz, -1, -1, expression);
return exeRelationSql(db, clazz, 1, 10, expression);
}
/**
@@ -111,6 +111,7 @@ class DelegateFind extends AbsDelegate {
<T extends AbsDbWrapper> List<T> findRelationData(SQLiteDatabase db, Class<T> clazz,
int page, int num, String... expression) {
if (page < 1 || num < 1) {
ALog.w(TAG, "pagenum 小于1");
return null;
}
return exeRelationSql(db, clazz, page, num, expression);
@@ -345,6 +346,7 @@ class DelegateFind extends AbsDelegate {
<T extends DbEntity> List<T> findData(SQLiteDatabase db, Class<T> clazz, int page, int num,
String... expression) {
if (page < 1 || num < 1) {
ALog.w(TAG, "page, bum 小于1");
return null;
}
db = checkDb(db);
@@ -390,6 +392,7 @@ class DelegateFind extends AbsDelegate {
<T extends DbEntity> List<T> findDataByFuzzy(SQLiteDatabase db, Class<T> clazz,
int page, int num, String conditions) {
if (page < 1 || num < 1) {
ALog.w(TAG, "page, bum 小于1");
return null;
}
db = checkDb(db);

View File

@@ -65,6 +65,15 @@ public class RecordUtil {
return;
}
DownloadGroupEntity groupEntity = DbDataHelper.getDGEntityByPath(dirPath);
// 处理组任务存在,而子任务为空的情况
if (groupEntity == null) {
groupEntity = DbEntity.findFirst(DownloadGroupEntity.class, "dirPath=?", dirPath);
if (groupEntity != null) {
groupEntity.deleteData();
DbEntity.deleteData(DownloadEntity.class, "groupHash=?", groupEntity.getGroupHash());
}
return;
}
delGroupTaskRecord(groupEntity, removeFile, true);
}