parent
6b8c051b30
commit
c06b1fd5fb
@ -1,221 +0,0 @@ |
|||||||
/* |
|
||||||
* 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.dua.group; |
|
||||||
|
|
||||||
import com.arialyy.aria.core.common.AbsEntity; |
|
||||||
import com.arialyy.aria.core.common.CompleteInfo; |
|
||||||
import com.arialyy.aria.core.download.DGTaskWrapper; |
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper; |
|
||||||
import com.arialyy.aria.core.download.DownloadEntity; |
|
||||||
import com.arialyy.aria.core.loader.IInfoTask; |
|
||||||
import com.arialyy.aria.core.loader.ILoaderVisitor; |
|
||||||
import com.arialyy.aria.exception.AriaException; |
|
||||||
import com.arialyy.aria.exception.AriaHTTPException; |
|
||||||
import com.arialyy.aria.http.HttpTaskOption; |
|
||||||
import com.arialyy.aria.util.ALog; |
|
||||||
import com.arialyy.aria.util.CommonUtil; |
|
||||||
import java.util.concurrent.ExecutorService; |
|
||||||
import java.util.concurrent.Executors; |
|
||||||
import java.util.concurrent.atomic.AtomicInteger; |
|
||||||
|
|
||||||
/** |
|
||||||
* 组合任务文件信息,用于获取长度未知时,组合任务的长度 |
|
||||||
*/ |
|
||||||
public final class HttpDGInfoTask implements IInfoTask { |
|
||||||
private String TAG = CommonUtil.getClassName(this); |
|
||||||
private Callback callback; |
|
||||||
private DGTaskWrapper wrapper; |
|
||||||
private final Object LOCK = new Object(); |
|
||||||
private ExecutorService mPool = null; |
|
||||||
private boolean getLenComplete = false; |
|
||||||
private AtomicInteger count = new AtomicInteger(); |
|
||||||
private AtomicInteger failCount = new AtomicInteger(); |
|
||||||
private boolean isStop = false, isCancel = false; |
|
||||||
|
|
||||||
public interface DGInfoCallback extends Callback { |
|
||||||
|
|
||||||
/** |
|
||||||
* 子任务失败 |
|
||||||
*/ |
|
||||||
void onSubFail(DownloadEntity subEntity, AriaHTTPException e, boolean needRetry); |
|
||||||
|
|
||||||
/** |
|
||||||
* 组合任务停止 |
|
||||||
*/ |
|
||||||
void onStop(long len); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 子任务回调 |
|
||||||
*/ |
|
||||||
private Callback subCallback = new Callback() { |
|
||||||
@Override public void onSucceed(String url, CompleteInfo info) { |
|
||||||
count.getAndIncrement(); |
|
||||||
checkGetSizeComplete(count.get(), failCount.get()); |
|
||||||
ALog.d(TAG, "获取子任务信息完成"); |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void onFail(AbsEntity entity, AriaException e, boolean needRetry) { |
|
||||||
ALog.e(TAG, String.format("获取文件信息失败,url:%s", ((DownloadEntity) entity).getUrl())); |
|
||||||
count.getAndIncrement(); |
|
||||||
failCount.getAndIncrement(); |
|
||||||
((DGInfoCallback) callback).onSubFail((DownloadEntity) entity, new AriaHTTPException( |
|
||||||
String.format("子任务获取文件长度失败,url:%s", ((DownloadEntity) entity).getUrl())), needRetry); |
|
||||||
checkGetSizeComplete(count.get(), failCount.get()); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
HttpDGInfoTask(DGTaskWrapper wrapper) { |
|
||||||
this.wrapper = wrapper; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 停止 |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void stop() { |
|
||||||
isStop = true; |
|
||||||
if (mPool != null) { |
|
||||||
mPool.shutdown(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void cancel() { |
|
||||||
isCancel = true; |
|
||||||
if (mPool != null) { |
|
||||||
mPool.shutdown(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void run() { |
|
||||||
// 如果是isUnknownSize()标志,并且获取大小没有完成,则直接回调onStop
|
|
||||||
if (mPool != null && !getLenComplete) { |
|
||||||
ALog.d(TAG, "获取长度未完成的情况下,停止组合任务"); |
|
||||||
mPool.shutdown(); |
|
||||||
((DGInfoCallback)callback).onStop(0); |
|
||||||
return; |
|
||||||
} |
|
||||||
// 处理组合任务大小未知的情况
|
|
||||||
if (wrapper.isUnknownSize()) { |
|
||||||
mPool = Executors.newCachedThreadPool(); |
|
||||||
getGroupSize(); |
|
||||||
try { |
|
||||||
synchronized (LOCK) { |
|
||||||
LOCK.wait(); |
|
||||||
} |
|
||||||
} catch (InterruptedException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
if (!mPool.isShutdown()) { |
|
||||||
mPool.shutdown(); |
|
||||||
} |
|
||||||
} else { |
|
||||||
for (DTaskWrapper wrapper : wrapper.getSubTaskWrapper()) { |
|
||||||
cloneHeader(wrapper); |
|
||||||
} |
|
||||||
callback.onSucceed(wrapper.getKey(), new CompleteInfo()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* 获取组合任务大小,使用该方式获取到的组合任务大小,子任务不需要再重新获取文件大小 |
|
||||||
*/ |
|
||||||
private void getGroupSize() { |
|
||||||
new Thread(new Runnable() { |
|
||||||
@Override public void run() { |
|
||||||
for (DTaskWrapper dTaskWrapper : wrapper.getSubTaskWrapper()) { |
|
||||||
DownloadEntity subEntity = dTaskWrapper.getEntity(); |
|
||||||
if (subEntity.getFileSize() > 0) { |
|
||||||
count.getAndIncrement(); |
|
||||||
if (subEntity.getCurrentProgress() < subEntity.getFileSize()) { |
|
||||||
// 如果没有完成需要拷贝一份数据
|
|
||||||
cloneHeader(dTaskWrapper); |
|
||||||
} |
|
||||||
checkGetSizeComplete(count.get(), failCount.get()); |
|
||||||
continue; |
|
||||||
} |
|
||||||
cloneHeader(dTaskWrapper); |
|
||||||
HttpDFileInfoTask infoTask = new HttpDFileInfoTask(dTaskWrapper); |
|
||||||
infoTask.setCallback(subCallback); |
|
||||||
mPool.execute(infoTask); |
|
||||||
} |
|
||||||
} |
|
||||||
}).start(); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 检查组合任务大小是否获取完成,获取完成后取消阻塞,并设置组合任务大小 |
|
||||||
*/ |
|
||||||
private void checkGetSizeComplete(int count, int failCount) { |
|
||||||
if (isStop || isCancel) { |
|
||||||
ALog.w(TAG, "任务已停止或已取消,isStop = " + isStop + ", isCancel = " + isCancel); |
|
||||||
notifyLock(); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (failCount == wrapper.getSubTaskWrapper().size()) { |
|
||||||
callback.onFail(wrapper.getEntity(), new AriaHTTPException("获取子任务长度失败"), false); |
|
||||||
notifyLock(); |
|
||||||
return; |
|
||||||
} |
|
||||||
if (count == wrapper.getSubTaskWrapper().size()) { |
|
||||||
long size = 0; |
|
||||||
for (DTaskWrapper wrapper : wrapper.getSubTaskWrapper()) { |
|
||||||
size += wrapper.getEntity().getFileSize(); |
|
||||||
} |
|
||||||
wrapper.getEntity().setConvertFileSize(CommonUtil.formatFileSize(size)); |
|
||||||
wrapper.getEntity().setFileSize(size); |
|
||||||
wrapper.getEntity().update(); |
|
||||||
getLenComplete = true; |
|
||||||
ALog.d(TAG, String.format("获取组合任务长度完成,组合任务总长度:%s,失败的子任务数:%s", size, failCount)); |
|
||||||
callback.onSucceed(wrapper.getKey(), new CompleteInfo()); |
|
||||||
notifyLock(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private void notifyLock() { |
|
||||||
synchronized (LOCK) { |
|
||||||
LOCK.notifyAll(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* 子任务使用父包裹器的属性 |
|
||||||
*/ |
|
||||||
private void cloneHeader(DTaskWrapper taskWrapper) { |
|
||||||
HttpTaskOption groupOption = (HttpTaskOption) wrapper.getTaskOption(); |
|
||||||
HttpTaskOption subOption = new HttpTaskOption(); |
|
||||||
|
|
||||||
// 设置属性
|
|
||||||
subOption.setFileLenAdapter(groupOption.getFileLenAdapter()); |
|
||||||
subOption.setFileNameAdapter(groupOption.getFileNameAdapter()); |
|
||||||
subOption.setUseServerFileName(groupOption.isUseServerFileName()); |
|
||||||
|
|
||||||
subOption.setFileNameAdapter(groupOption.getFileNameAdapter()); |
|
||||||
subOption.setRequestEnum(groupOption.getRequestEnum()); |
|
||||||
subOption.setHeaders(groupOption.getHeaders()); |
|
||||||
subOption.setProxy(groupOption.getProxy()); |
|
||||||
subOption.setParams(groupOption.getParams()); |
|
||||||
taskWrapper.setTaskOption(subOption); |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void setCallback(Callback callback) { |
|
||||||
this.callback = callback; |
|
||||||
} |
|
||||||
|
|
||||||
@Override public void accept(ILoaderVisitor visitor) { |
|
||||||
visitor.addComponent(this); |
|
||||||
} |
|
||||||
} |
|
@ -1,59 +0,0 @@ |
|||||||
/* |
|
||||||
* 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.dua.group; |
|
||||||
|
|
||||||
import android.os.Handler; |
|
||||||
import com.arialyy.aria.core.download.DTaskWrapper; |
|
||||||
import com.arialyy.aria.core.group.AbsSubDLoadAdapter; |
|
||||||
import com.arialyy.aria.core.group.SubRecordHandler; |
|
||||||
import com.arialyy.aria.core.loader.GroupSubThreadStateManager; |
|
||||||
import com.arialyy.aria.core.loader.LoaderStructure; |
|
||||||
import com.arialyy.aria.core.loader.NormalTTBuilder; |
|
||||||
import com.arialyy.aria.core.loader.SubLoader; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author lyy |
|
||||||
* Date: 2019-09-28 |
|
||||||
*/ |
|
||||||
final class HttpSubDLoaderAdapter extends AbsSubDLoadAdapter { |
|
||||||
/** |
|
||||||
* @param schedulers 调度器 |
|
||||||
* @param needGetInfo {@code true} 需要获取文件信息。{@code false} 不需要获取文件信息 |
|
||||||
*/ |
|
||||||
HttpSubDLoaderAdapter( Handler schedulers, boolean needGetInfo, String parentKey) { |
|
||||||
super(schedulers, needGetInfo, parentKey); |
|
||||||
} |
|
||||||
|
|
||||||
@Override protected SubLoader getLoader() { |
|
||||||
if (mDLoader == null) { |
|
||||||
mDLoader = new SubLoader(getWrapper(), getSchedulers()); |
|
||||||
mDLoader.setNeedGetInfo(isNeedGetInfo()); |
|
||||||
mDLoader.setParentKey(getParentKey()); |
|
||||||
} |
|
||||||
return mDLoader; |
|
||||||
} |
|
||||||
|
|
||||||
@Override protected LoaderStructure buildLoaderStructure() { |
|
||||||
LoaderStructure structure = new LoaderStructure(); |
|
||||||
structure.addComponent(new SubRecordHandler(getWrapper())) |
|
||||||
.addComponent(new GroupSubThreadStateManager(getSchedulers(),getKey())) |
|
||||||
.addComponent(new NormalTTBuilder(getWrapper(), new HttpDTTBuilderAdapter())) |
|
||||||
.addComponent(new HttpDFileInfoTask(getWrapper())); |
|
||||||
structure.accept(getLoader()); |
|
||||||
return structure; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
Loading…
Reference in new issue