mirror of https://github.com/aria2/aria2
parent
0465aa5455
commit
6240345fd5
|
@ -74,12 +74,10 @@
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
AbstractCommand::AbstractCommand(
|
AbstractCommand::AbstractCommand(cuid_t cuid,
|
||||||
cuid_t cuid,
|
|
||||||
const std::shared_ptr<Request>& req,
|
const std::shared_ptr<Request>& req,
|
||||||
const std::shared_ptr<FileEntry>& fileEntry,
|
const std::shared_ptr<FileEntry>& fileEntry,
|
||||||
RequestGroup *requestGroup,
|
RequestGroup* requestGroup, DownloadEngine* e,
|
||||||
DownloadEngine *e,
|
|
||||||
const std::shared_ptr<SocketCore>& s,
|
const std::shared_ptr<SocketCore>& s,
|
||||||
const std::shared_ptr<SocketRecvBuffer>& socketRecvBuffer,
|
const std::shared_ptr<SocketRecvBuffer>& socketRecvBuffer,
|
||||||
bool incNumConnection)
|
bool incNumConnection)
|
||||||
|
@ -113,8 +111,7 @@ AbstractCommand::AbstractCommand(
|
||||||
#endif // ENABLE_ASYNC_DNS
|
#endif // ENABLE_ASYNC_DNS
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractCommand::~AbstractCommand()
|
AbstractCommand::~AbstractCommand() {
|
||||||
{
|
|
||||||
disableReadCheckSocket();
|
disableReadCheckSocket();
|
||||||
disableWriteCheckSocket();
|
disableWriteCheckSocket();
|
||||||
#ifdef ENABLE_ASYNC_DNS
|
#ifdef ENABLE_ASYNC_DNS
|
||||||
|
@ -127,8 +124,8 @@ AbstractCommand::~AbstractCommand()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void AbstractCommand::useFasterRequest
|
||||||
AbstractCommand::useFasterRequest(const std::shared_ptr<Request> &fasterRequest)
|
(const std::shared_ptr<Request>& fasterRequest)
|
||||||
{
|
{
|
||||||
A2_LOG_INFO(fmt("CUID#%" PRId64 " - Use faster Request hostname=%s, port=%u",
|
A2_LOG_INFO(fmt("CUID#%" PRId64 " - Use faster Request hostname=%s, port=%u",
|
||||||
getCuid(),
|
getCuid(),
|
||||||
|
@ -137,45 +134,13 @@ AbstractCommand::useFasterRequest(const std::shared_ptr<Request> &fasterRequest)
|
||||||
// Cancel current Request object and use faster one.
|
// Cancel current Request object and use faster one.
|
||||||
fileEntry_->removeRequest(req_);
|
fileEntry_->removeRequest(req_);
|
||||||
e_->setNoWait(true);
|
e_->setNoWait(true);
|
||||||
e_->addCommand(
|
e_->addCommand(InitiateConnectionCommandFactory::
|
||||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand(
|
createInitiateConnectionCommand
|
||||||
getCuid(), fasterRequest, fileEntry_, requestGroup_, e_));
|
(getCuid(), fasterRequest, fileEntry_, requestGroup_, e_));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractCommand::shouldCheck() const
|
bool AbstractCommand::execute() {
|
||||||
{
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - socket: read:%d, write:%d, hup:%d, err:%d",
|
||||||
if (checkSocketIsReadable_) {
|
|
||||||
if (readEventEnabled()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socketRecvBuffer_ && !socketRecvBuffer_->bufferEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkSocketIsWritable_ && writeEventEnabled()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_ASYNC_DNS
|
|
||||||
const auto resolverChecked = asyncNameResolverMan_->resolverChecked();
|
|
||||||
if (resolverChecked && asyncNameResolverMan_->getStatus() != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkSocketIsReadable_ && !checkSocketIsWritable_ && !resolverChecked) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // ENABLE_ASYNC_DNS
|
|
||||||
|
|
||||||
return noCheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AbstractCommand::execute()
|
|
||||||
{
|
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64
|
|
||||||
" - socket: read:%d, write:%d, hup:%d, err:%d",
|
|
||||||
getCuid(),
|
getCuid(),
|
||||||
readEventEnabled(),
|
readEventEnabled(),
|
||||||
writeEventEnabled(),
|
writeEventEnabled(),
|
||||||
|
@ -185,28 +150,20 @@ bool AbstractCommand::execute()
|
||||||
if(requestGroup_->downloadFinished() || requestGroup_->isHaltRequested()) {
|
if(requestGroup_->downloadFinished() || requestGroup_->isHaltRequested()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(req_ && req_->removalRequested()) {
|
if(req_ && req_->removalRequested()) {
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Discard original URI=%s because it is"
|
||||||
" - Discard original URI=%s because it is"
|
|
||||||
" requested.",
|
" requested.",
|
||||||
getCuid(),
|
getCuid(), req_->getUri().c_str()));
|
||||||
req_->getUri().c_str()));
|
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sm = getSegmentMan();
|
|
||||||
|
|
||||||
if(getPieceStorage()) {
|
if(getPieceStorage()) {
|
||||||
segments_.clear();
|
segments_.clear();
|
||||||
sm->getInFlightSegment(segments_, getCuid());
|
getSegmentMan()->getInFlightSegment(segments_, getCuid());
|
||||||
|
|
||||||
if(req_ && segments_.empty()) {
|
if(req_ && segments_.empty()) {
|
||||||
// This command previously has assigned segments, but it is
|
// This command previously has assigned segments, but it is
|
||||||
// canceled. So discard current request chain. Plus, if no
|
// canceled. So discard current request chain. Plus, if no
|
||||||
// segment is available when http pipelining is used.
|
// segment is available when http pipelining is used.
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - It seems previously assigned segments"
|
||||||
" - It seems previously assigned segments"
|
|
||||||
" are canceled. Restart.",
|
" are canceled. Restart.",
|
||||||
getCuid()));
|
getCuid()));
|
||||||
// Request::isPipeliningEnabled() == true means aria2
|
// Request::isPipeliningEnabled() == true means aria2
|
||||||
|
@ -217,12 +174,12 @@ bool AbstractCommand::execute()
|
||||||
}
|
}
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO it is not needed to check other PeerStats every time.
|
// TODO it is not needed to check other PeerStats every time.
|
||||||
// Find faster Request when no segment split is allowed.
|
// Find faster Request when no segment split is allowed.
|
||||||
if(req_ && fileEntry_->countPooledRequest() > 0 &&
|
if(req_ && fileEntry_->countPooledRequest() > 0 &&
|
||||||
requestGroup_->getPendingLength() < calculateMinSplitSize() * 2) {
|
requestGroup_->getTotalLength()-requestGroup_->getCompletedLength()
|
||||||
auto fasterRequest = fileEntry_->findFasterRequest(req_);
|
< calculateMinSplitSize()*2) {
|
||||||
|
std::shared_ptr<Request> fasterRequest = fileEntry_->findFasterRequest(req_);
|
||||||
if(fasterRequest) {
|
if(fasterRequest) {
|
||||||
useFasterRequest(fasterRequest);
|
useFasterRequest(fasterRequest);
|
||||||
return true;
|
return true;
|
||||||
|
@ -239,22 +196,31 @@ bool AbstractCommand::execute()
|
||||||
if(getOption()->getAsBool(PREF_SELECT_LEAST_USED_HOST)) {
|
if(getOption()->getAsBool(PREF_SELECT_LEAST_USED_HOST)) {
|
||||||
getDownloadEngine()->getRequestGroupMan()->getUsedHosts(usedHosts);
|
getDownloadEngine()->getRequestGroupMan()->getUsedHosts(usedHosts);
|
||||||
}
|
}
|
||||||
auto fasterRequest = fileEntry_->findFasterRequest(
|
std::shared_ptr<Request> fasterRequest =
|
||||||
req_, usedHosts, e_->getRequestGroupMan()->getServerStatMan());
|
fileEntry_->findFasterRequest
|
||||||
|
(req_, usedHosts, e_->getRequestGroupMan()->getServerStatMan());
|
||||||
if(fasterRequest) {
|
if(fasterRequest) {
|
||||||
useFasterRequest(fasterRequest);
|
useFasterRequest(fasterRequest);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if((checkSocketIsReadable_ &&
|
||||||
if (shouldCheck()) {
|
(readEventEnabled() ||
|
||||||
|
(socketRecvBuffer_ && !socketRecvBuffer_->bufferEmpty()))) ||
|
||||||
|
(checkSocketIsWritable_ && writeEventEnabled()) ||
|
||||||
|
hupEventEnabled() ||
|
||||||
|
#ifdef ENABLE_ASYNC_DNS
|
||||||
|
(asyncNameResolverMan_->resolverChecked() &&
|
||||||
|
asyncNameResolverMan_->getStatus() != 0) ||
|
||||||
|
#endif // ENABLE_ASYNC_DNS
|
||||||
|
(!checkSocketIsReadable_ && !checkSocketIsWritable_
|
||||||
|
#ifdef ENABLE_ASYNC_DNS
|
||||||
|
&& !asyncNameResolverMan_->resolverChecked()
|
||||||
|
#endif // ENABLE_ASYNC_DNS
|
||||||
|
) || noCheck()) {
|
||||||
checkPoint_ = global::wallclock();
|
checkPoint_ = global::wallclock();
|
||||||
|
if(getPieceStorage()) {
|
||||||
if (!getPieceStorage()) {
|
|
||||||
return executeInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!req_ || req_->getMaxPipelinedRequest() == 1 ||
|
if(!req_ || req_->getMaxPipelinedRequest() == 1 ||
|
||||||
// Why the following condition is necessary? That's because
|
// Why the following condition is necessary? That's because
|
||||||
// For single file download, SegmentMan::getSegment(cuid)
|
// For single file download, SegmentMan::getSegment(cuid)
|
||||||
|
@ -263,55 +229,55 @@ bool AbstractCommand::execute()
|
||||||
size_t maxSegments = req_?req_->getMaxPipelinedRequest():1;
|
size_t maxSegments = req_?req_->getMaxPipelinedRequest():1;
|
||||||
size_t minSplitSize = calculateMinSplitSize();
|
size_t minSplitSize = calculateMinSplitSize();
|
||||||
while(segments_.size() < maxSegments) {
|
while(segments_.size() < maxSegments) {
|
||||||
auto segment = sm->getSegment(getCuid(), minSplitSize);
|
std::shared_ptr<Segment> segment =
|
||||||
|
getSegmentMan()->getSegment(getCuid(), minSplitSize);
|
||||||
if(!segment) {
|
if(!segment) {
|
||||||
break;
|
break;
|
||||||
}
|
} else {
|
||||||
segments_.push_back(segment);
|
segments_.push_back(segment);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(segments_.empty()) {
|
if(segments_.empty()) {
|
||||||
// TODO socket could be pooled here if pipelining is
|
// TODO socket could be pooled here if pipelining is
|
||||||
// enabled... Hmm, I don't think if pipelining is enabled
|
// enabled... Hmm, I don't think if pipelining is enabled
|
||||||
// it does not go here.
|
// it does not go here.
|
||||||
A2_LOG_INFO(fmt(MSG_NO_SEGMENT_AVAILABLE, getCuid()));
|
A2_LOG_INFO(fmt(MSG_NO_SEGMENT_AVAILABLE,
|
||||||
|
getCuid()));
|
||||||
// When all segments are ignored in SegmentMan, there are
|
// When all segments are ignored in SegmentMan, there are
|
||||||
// no URIs available, so don't retry.
|
// no URIs available, so don't retry.
|
||||||
if (sm->allSegmentsIgnored()) {
|
if(getSegmentMan()->allSegmentsIgnored()) {
|
||||||
A2_LOG_DEBUG("All segments are ignored.");
|
A2_LOG_DEBUG("All segments are ignored.");
|
||||||
// This will execute other idle Commands and let them
|
// This will execute other idle Commands and let them
|
||||||
// finish quickly.
|
// finish quickly.
|
||||||
e_->setRefreshInterval(0);
|
e_->setRefreshInterval(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
return prepareForRetry(1);
|
return prepareForRetry(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
// For multi-file downloads
|
// For multi-file downloads
|
||||||
size_t minSplitSize = calculateMinSplitSize();
|
size_t minSplitSize = calculateMinSplitSize();
|
||||||
size_t maxSegments = req_->getMaxPipelinedRequest();
|
size_t maxSegments = req_->getMaxPipelinedRequest();
|
||||||
if(segments_.size() < maxSegments) {
|
if(segments_.size() < maxSegments) {
|
||||||
sm->getSegment(
|
getSegmentMan()->getSegment
|
||||||
segments_, getCuid(), minSplitSize, fileEntry_, maxSegments);
|
(segments_, getCuid(), minSplitSize, fileEntry_, maxSegments);
|
||||||
}
|
}
|
||||||
if(segments_.empty()) {
|
if(segments_.empty()) {
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return executeInternal();
|
return executeInternal();
|
||||||
}
|
} else if(errorEventEnabled()) {
|
||||||
|
throw DL_RETRY_EX(fmt(MSG_NETWORK_PROBLEM,
|
||||||
if (errorEventEnabled()) {
|
socket_->getSocketError().c_str()));
|
||||||
throw DL_RETRY_EX(
|
} else {
|
||||||
fmt(MSG_NETWORK_PROBLEM, socket_->getSocketError().c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(checkPoint_.difference(global::wallclock()) >= timeout_) {
|
if(checkPoint_.difference(global::wallclock()) >= timeout_) {
|
||||||
// timeout triggers ServerStat error state.
|
// timeout triggers ServerStat error state.
|
||||||
auto ss = e_->getRequestGroupMan()->getOrCreateServerStat(
|
std::shared_ptr<ServerStat> ss =
|
||||||
req_->getHost(), req_->getProtocol());
|
e_->getRequestGroupMan()->getOrCreateServerStat(req_->getHost(),
|
||||||
|
req_->getProtocol());
|
||||||
ss->setError();
|
ss->setError();
|
||||||
// When DNS query was timeout, req_->getConnectedAddr() is
|
// When DNS query was timeout, req_->getConnectedAddr() is
|
||||||
// empty.
|
// empty.
|
||||||
|
@ -324,53 +290,56 @@ bool AbstractCommand::execute()
|
||||||
req_->getConnectedAddr(),
|
req_->getConnectedAddr(),
|
||||||
req_->getConnectedPort());
|
req_->getConnectedPort());
|
||||||
}
|
}
|
||||||
if (e_->findCachedIPAddress(req_->getConnectedHostname(),
|
if(e_->findCachedIPAddress
|
||||||
req_->getConnectedPort()).empty()) {
|
(req_->getConnectedHostname(), req_->getConnectedPort()).empty()) {
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - All IP addresses were marked bad."
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - All IP addresses were marked bad."
|
||||||
" Removing Entry.",
|
" Removing Entry.",
|
||||||
getCuid()));
|
getCuid()));
|
||||||
e_->removeCachedIPAddress(req_->getConnectedHostname(),
|
e_->removeCachedIPAddress
|
||||||
req_->getConnectedPort());
|
(req_->getConnectedHostname(), req_->getConnectedPort());
|
||||||
}
|
}
|
||||||
throw DL_RETRY_EX2(EX_TIME_OUT, error_code::TIME_OUT);
|
throw DL_RETRY_EX2(EX_TIME_OUT, error_code::TIME_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommandSelf();
|
addCommandSelf();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch (DlAbortEx &err) {
|
} catch(DlAbortEx& err) {
|
||||||
requestGroup_->setLastErrorCode(err.getErrorCode());
|
requestGroup_->setLastErrorCode(err.getErrorCode());
|
||||||
if(req_) {
|
if(req_) {
|
||||||
A2_LOG_ERROR_EX(
|
A2_LOG_ERROR_EX(fmt(MSG_DOWNLOAD_ABORTED,
|
||||||
fmt(MSG_DOWNLOAD_ABORTED, getCuid(), req_->getUri().c_str()),
|
getCuid(),
|
||||||
DL_ABORT_EX2(fmt("URI=%s", req_->getCurrentUri().c_str()), err));
|
req_->getUri().c_str()),
|
||||||
|
DL_ABORT_EX2(fmt("URI=%s", req_->getCurrentUri().c_str()),
|
||||||
|
err));
|
||||||
fileEntry_->addURIResult(req_->getUri(), err.getErrorCode());
|
fileEntry_->addURIResult(req_->getUri(), err.getErrorCode());
|
||||||
if(err.getErrorCode() == error_code::CANNOT_RESUME) {
|
if(err.getErrorCode() == error_code::CANNOT_RESUME) {
|
||||||
requestGroup_->increaseResumeFailureCount();
|
requestGroup_->increaseResumeFailureCount();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
A2_LOG_DEBUG_EX(EX_EXCEPTION_CAUGHT, err);
|
A2_LOG_DEBUG_EX(EX_EXCEPTION_CAUGHT, err);
|
||||||
}
|
}
|
||||||
onAbort();
|
onAbort();
|
||||||
tryReserved();
|
tryReserved();
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch(DlRetryEx& err) {
|
||||||
catch (DlRetryEx &err) {
|
|
||||||
assert(req_);
|
assert(req_);
|
||||||
A2_LOG_INFO_EX(
|
A2_LOG_INFO_EX(fmt(MSG_RESTARTING_DOWNLOAD,
|
||||||
fmt(MSG_RESTARTING_DOWNLOAD, getCuid(), req_->getUri().c_str()),
|
getCuid(), req_->getUri().c_str()),
|
||||||
DL_RETRY_EX2(fmt("URI=%s", req_->getCurrentUri().c_str()), err));
|
DL_RETRY_EX2(fmt("URI=%s", req_->getCurrentUri().c_str()),
|
||||||
|
err));
|
||||||
req_->addTryCount();
|
req_->addTryCount();
|
||||||
req_->resetRedirectCount();
|
req_->resetRedirectCount();
|
||||||
req_->resetUri();
|
req_->resetUri();
|
||||||
|
|
||||||
const int maxTries = getOption()->getAsInt(PREF_MAX_TRIES);
|
const int maxTries = getOption()->getAsInt(PREF_MAX_TRIES);
|
||||||
bool isAbort = maxTries != 0 && req_->getTryCount() >= maxTries;
|
bool isAbort = maxTries != 0 && req_->getTryCount() >= maxTries;
|
||||||
if(isAbort) {
|
if(isAbort) {
|
||||||
A2_LOG_INFO(fmt(MSG_MAX_TRY, getCuid(), req_->getTryCount()));
|
A2_LOG_INFO(fmt(MSG_MAX_TRY,
|
||||||
A2_LOG_ERROR_EX(
|
getCuid(),
|
||||||
fmt(MSG_DOWNLOAD_ABORTED, getCuid(), req_->getUri().c_str()), err);
|
req_->getTryCount()));
|
||||||
|
A2_LOG_ERROR_EX(fmt(MSG_DOWNLOAD_ABORTED,
|
||||||
|
getCuid(),
|
||||||
|
req_->getUri().c_str()),
|
||||||
|
err);
|
||||||
fileEntry_->addURIResult(req_->getUri(), err.getErrorCode());
|
fileEntry_->addURIResult(req_->getUri(), err.getErrorCode());
|
||||||
requestGroup_->setLastErrorCode(err.getErrorCode());
|
requestGroup_->setLastErrorCode(err.getErrorCode());
|
||||||
if(err.getErrorCode() == error_code::CANNOT_RESUME) {
|
if(err.getErrorCode() == error_code::CANNOT_RESUME) {
|
||||||
|
@ -379,19 +348,20 @@ bool AbstractCommand::execute()
|
||||||
onAbort();
|
onAbort();
|
||||||
tryReserved();
|
tryReserved();
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
Timer wakeTime(global::wallclock());
|
Timer wakeTime(global::wallclock());
|
||||||
wakeTime.advance(getOption()->getAsInt(PREF_RETRY_WAIT));
|
wakeTime.advance(getOption()->getAsInt(PREF_RETRY_WAIT));
|
||||||
req_->setWakeTime(wakeTime);
|
req_->setWakeTime(wakeTime);
|
||||||
return prepareForRetry(0);
|
return prepareForRetry(0);
|
||||||
}
|
}
|
||||||
catch (DownloadFailureException &err) {
|
} catch(DownloadFailureException& err) {
|
||||||
requestGroup_->setLastErrorCode(err.getErrorCode());
|
requestGroup_->setLastErrorCode(err.getErrorCode());
|
||||||
if(req_) {
|
if(req_) {
|
||||||
A2_LOG_ERROR_EX(
|
A2_LOG_ERROR_EX(fmt(MSG_DOWNLOAD_ABORTED,
|
||||||
fmt(MSG_DOWNLOAD_ABORTED, getCuid(), req_->getUri().c_str()),
|
getCuid(),
|
||||||
DL_ABORT_EX2(fmt("URI=%s", req_->getCurrentUri().c_str()), err));
|
req_->getUri().c_str()),
|
||||||
|
DL_ABORT_EX2(fmt("URI=%s", req_->getCurrentUri().c_str()),
|
||||||
|
err));
|
||||||
fileEntry_->addURIResult(req_->getUri(), err.getErrorCode());
|
fileEntry_->addURIResult(req_->getUri(), err.getErrorCode());
|
||||||
} else {
|
} else {
|
||||||
A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, err);
|
A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, err);
|
||||||
|
@ -402,10 +372,10 @@ bool AbstractCommand::execute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCommand::tryReserved()
|
void AbstractCommand::tryReserved() {
|
||||||
{
|
|
||||||
if(getDownloadContext()->getFileEntries().size() == 1) {
|
if(getDownloadContext()->getFileEntries().size() == 1) {
|
||||||
const auto &entry = getDownloadContext()->getFirstFileEntry();
|
const std::shared_ptr<FileEntry>& entry =
|
||||||
|
getDownloadContext()->getFirstFileEntry();
|
||||||
// Don't create new command if currently file length is unknown
|
// Don't create new command if currently file length is unknown
|
||||||
// and there are no URI left. Because file length is unknown, we
|
// and there are no URI left. Because file length is unknown, we
|
||||||
// can assume that there are no in-flight request object.
|
// can assume that there are no in-flight request object.
|
||||||
|
@ -417,16 +387,15 @@ void AbstractCommand::tryReserved()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
A2_LOG_DEBUG(
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Trying reserved/pooled request.",
|
||||||
fmt("CUID#%" PRId64 " - Trying reserved/pooled request.", getCuid()));
|
getCuid()));
|
||||||
std::vector<std::unique_ptr<Command>> commands;
|
std::vector<std::unique_ptr<Command>> commands;
|
||||||
requestGroup_->createNextCommand(commands, e_, 1);
|
requestGroup_->createNextCommand(commands, e_, 1);
|
||||||
e_->setNoWait(true);
|
e_->setNoWait(true);
|
||||||
e_->addCommand(std::move(commands));
|
e_->addCommand(std::move(commands));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractCommand::prepareForRetry(time_t wait)
|
bool AbstractCommand::prepareForRetry(time_t wait) {
|
||||||
{
|
|
||||||
if(getPieceStorage()) {
|
if(getPieceStorage()) {
|
||||||
getSegmentMan()->cancelSegment(getCuid());
|
getSegmentMan()->cancelSegment(getCuid());
|
||||||
}
|
}
|
||||||
|
@ -439,19 +408,17 @@ bool AbstractCommand::prepareForRetry(time_t wait)
|
||||||
|
|
||||||
fileEntry_->poolRequest(req_);
|
fileEntry_->poolRequest(req_);
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Pooling request URI=%s",
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Pooling request URI=%s",
|
||||||
getCuid(),
|
getCuid(), req_->getUri().c_str()));
|
||||||
req_->getUri().c_str()));
|
|
||||||
if(getSegmentMan()) {
|
if(getSegmentMan()) {
|
||||||
getSegmentMan()->recognizeSegmentFor(fileEntry_);
|
getSegmentMan()->recognizeSegmentFor(fileEntry_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto command =
|
auto command = make_unique<CreateRequestCommand>(getCuid(),
|
||||||
make_unique<CreateRequestCommand>(getCuid(), requestGroup_, e_);
|
requestGroup_, e_);
|
||||||
if(wait == 0) {
|
if(wait == 0) {
|
||||||
e_->setNoWait(true);
|
e_->setNoWait(true);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// We don't use wait so that Command can be executed by
|
// We don't use wait so that Command can be executed by
|
||||||
// DownloadEngine::setRefreshInterval(0).
|
// DownloadEngine::setRefreshInterval(0).
|
||||||
command->setStatus(Command::STATUS_INACTIVE);
|
command->setStatus(Command::STATUS_INACTIVE);
|
||||||
|
@ -460,34 +427,26 @@ bool AbstractCommand::prepareForRetry(time_t wait)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCommand::onAbort()
|
void AbstractCommand::onAbort() {
|
||||||
{
|
|
||||||
if(req_) {
|
if(req_) {
|
||||||
fileEntry_->removeIdenticalURI(req_->getUri());
|
fileEntry_->removeIdenticalURI(req_->getUri());
|
||||||
fileEntry_->removeRequest(req_);
|
fileEntry_->removeRequest(req_);
|
||||||
}
|
}
|
||||||
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Aborting download",
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Aborting download", getCuid()));
|
getCuid()));
|
||||||
if (!getPieceStorage()) {
|
if(getPieceStorage()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSegmentMan()->cancelSegment(getCuid());
|
getSegmentMan()->cancelSegment(getCuid());
|
||||||
// Don't do following process if BitTorrent is involved or files
|
// Don't do following process if BitTorrent is involved or files
|
||||||
// in DownloadContext is more than 1. The latter condition is
|
// in DownloadContext is more than 1. The latter condition is
|
||||||
// limitation of current implementation.
|
// limitation of current implementation.
|
||||||
if (getOption()->getAsBool(PREF_ALWAYS_RESUME) || !fileEntry_ ||
|
if(!getOption()->getAsBool(PREF_ALWAYS_RESUME) &&
|
||||||
getDownloadContext()->getNetStat().getSessionDownloadLength() != 0 ||
|
fileEntry_ &&
|
||||||
requestGroup_->p2pInvolved() ||
|
getDownloadContext()->getNetStat().getSessionDownloadLength() == 0 &&
|
||||||
getDownloadContext()->getFileEntries().size() != 1) {
|
!requestGroup_->p2pInvolved() &&
|
||||||
return;
|
getDownloadContext()->getFileEntries().size() == 1) {
|
||||||
}
|
|
||||||
|
|
||||||
const int maxTries = getOption()->getAsInt(PREF_MAX_RESUME_FAILURE_TRIES);
|
const int maxTries = getOption()->getAsInt(PREF_MAX_RESUME_FAILURE_TRIES);
|
||||||
if (!(maxTries > 0 && requestGroup_->getResumeFailureCount() >= maxTries) &&
|
if((maxTries > 0 && requestGroup_->getResumeFailureCount() >= maxTries)||
|
||||||
!fileEntry_->emptyRequestUri()) {
|
fileEntry_->emptyRequestUri()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Local file exists, but given servers(or at least contacted
|
// Local file exists, but given servers(or at least contacted
|
||||||
// ones) doesn't support resume. Let's restart download from
|
// ones) doesn't support resume. Let's restart download from
|
||||||
// scratch.
|
// scratch.
|
||||||
|
@ -502,18 +461,13 @@ void AbstractCommand::onAbort()
|
||||||
getOption()->put(PREF_ALWAYS_RESUME, A2_V_TRUE);
|
getOption()->put(PREF_ALWAYS_RESUME, A2_V_TRUE);
|
||||||
std::deque<URIResult> res;
|
std::deque<URIResult> res;
|
||||||
fileEntry_->extractURIResult(res, error_code::CANNOT_RESUME);
|
fileEntry_->extractURIResult(res, error_code::CANNOT_RESUME);
|
||||||
if (res.empty()) {
|
if(!res.empty()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSegmentMan()->cancelAllSegments();
|
getSegmentMan()->cancelAllSegments();
|
||||||
getSegmentMan()->eraseSegmentWrittenLengthMemo();
|
getSegmentMan()->eraseSegmentWrittenLengthMemo();
|
||||||
getPieceStorage()->markPiecesDone(0);
|
getPieceStorage()->markPiecesDone(0);
|
||||||
std::vector<std::string> uris;
|
std::vector<std::string> uris;
|
||||||
uris.reserve(res.size());
|
uris.reserve(res.size());
|
||||||
std::transform(res.begin(),
|
std::transform(res.begin(), res.end(), std::back_inserter(uris),
|
||||||
res.end(),
|
|
||||||
std::back_inserter(uris),
|
|
||||||
std::mem_fn(&URIResult::getURI));
|
std::mem_fn(&URIResult::getURI));
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - %lu URIs found.",
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - %lu URIs found.",
|
||||||
getCuid(),
|
getCuid(),
|
||||||
|
@ -521,94 +475,84 @@ void AbstractCommand::onAbort()
|
||||||
fileEntry_->addUris(uris.begin(), uris.end());
|
fileEntry_->addUris(uris.begin(), uris.end());
|
||||||
getSegmentMan()->recognizeSegmentFor(fileEntry_);
|
getSegmentMan()->recognizeSegmentFor(fileEntry_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void AbstractCommand::disableReadCheckSocket()
|
}
|
||||||
{
|
}
|
||||||
if (!checkSocketIsReadable_) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbstractCommand::disableReadCheckSocket() {
|
||||||
|
if(checkSocketIsReadable_) {
|
||||||
e_->deleteSocketForReadCheck(readCheckTarget_, this);
|
e_->deleteSocketForReadCheck(readCheckTarget_, this);
|
||||||
checkSocketIsReadable_ = false;
|
checkSocketIsReadable_ = false;
|
||||||
readCheckTarget_.reset();
|
readCheckTarget_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AbstractCommand::setReadCheckSocket(const std::shared_ptr<SocketCore> &socket)
|
|
||||||
{
|
|
||||||
if (!socket->isOpen()) {
|
|
||||||
disableReadCheckSocket();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbstractCommand::setReadCheckSocket
|
||||||
|
(const std::shared_ptr<SocketCore>& socket) {
|
||||||
|
if(!socket->isOpen()) {
|
||||||
|
disableReadCheckSocket();
|
||||||
|
} else {
|
||||||
if(checkSocketIsReadable_) {
|
if(checkSocketIsReadable_) {
|
||||||
if(*readCheckTarget_ != *socket) {
|
if(*readCheckTarget_ != *socket) {
|
||||||
e_->deleteSocketForReadCheck(readCheckTarget_, this);
|
e_->deleteSocketForReadCheck(readCheckTarget_, this);
|
||||||
e_->addSocketForReadCheck(socket, this);
|
e_->addSocketForReadCheck(socket, this);
|
||||||
readCheckTarget_ = socket;
|
readCheckTarget_ = socket;
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
e_->addSocketForReadCheck(socket, this);
|
e_->addSocketForReadCheck(socket, this);
|
||||||
checkSocketIsReadable_ = true;
|
checkSocketIsReadable_ = true;
|
||||||
readCheckTarget_ = socket;
|
readCheckTarget_ = socket;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void AbstractCommand::setReadCheckSocketIf
|
||||||
AbstractCommand::setReadCheckSocketIf(const std::shared_ptr<SocketCore> &socket,
|
(const std::shared_ptr<SocketCore>& socket, bool pred)
|
||||||
bool pred)
|
|
||||||
{
|
{
|
||||||
if(pred) {
|
if(pred) {
|
||||||
setReadCheckSocket(socket);
|
setReadCheckSocket(socket);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
disableReadCheckSocket();
|
disableReadCheckSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCommand::disableWriteCheckSocket()
|
|
||||||
{
|
|
||||||
if (!checkSocketIsWritable_) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbstractCommand::disableWriteCheckSocket() {
|
||||||
|
if(checkSocketIsWritable_) {
|
||||||
e_->deleteSocketForWriteCheck(writeCheckTarget_, this);
|
e_->deleteSocketForWriteCheck(writeCheckTarget_, this);
|
||||||
checkSocketIsWritable_ = false;
|
checkSocketIsWritable_ = false;
|
||||||
writeCheckTarget_.reset();
|
writeCheckTarget_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AbstractCommand::setWriteCheckSocket(const std::shared_ptr<SocketCore> &socket)
|
|
||||||
{
|
|
||||||
if (!socket->isOpen()) {
|
|
||||||
disableWriteCheckSocket();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbstractCommand::setWriteCheckSocket
|
||||||
|
(const std::shared_ptr<SocketCore>& socket) {
|
||||||
|
if(!socket->isOpen()) {
|
||||||
|
disableWriteCheckSocket();
|
||||||
|
} else {
|
||||||
if(checkSocketIsWritable_) {
|
if(checkSocketIsWritable_) {
|
||||||
if(*writeCheckTarget_ != *socket) {
|
if(*writeCheckTarget_ != *socket) {
|
||||||
e_->deleteSocketForWriteCheck(writeCheckTarget_, this);
|
e_->deleteSocketForWriteCheck(writeCheckTarget_, this);
|
||||||
e_->addSocketForWriteCheck(socket, this);
|
e_->addSocketForWriteCheck(socket, this);
|
||||||
writeCheckTarget_ = socket;
|
writeCheckTarget_ = socket;
|
||||||
}
|
}
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
e_->addSocketForWriteCheck(socket, this);
|
e_->addSocketForWriteCheck(socket, this);
|
||||||
checkSocketIsWritable_ = true;
|
checkSocketIsWritable_ = true;
|
||||||
writeCheckTarget_ = socket;
|
writeCheckTarget_ = socket;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AbstractCommand::setWriteCheckSocketIf(
|
void AbstractCommand::setWriteCheckSocketIf
|
||||||
const std::shared_ptr<SocketCore> &socket, bool pred)
|
(const std::shared_ptr<SocketCore>& socket, bool pred)
|
||||||
{
|
{
|
||||||
if(pred) {
|
if(pred) {
|
||||||
setWriteCheckSocket(socket);
|
setWriteCheckSocket(socket);
|
||||||
return;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
disableWriteCheckSocket();
|
disableWriteCheckSocket();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AbstractCommand::swapSocket(std::shared_ptr<SocketCore>& socket)
|
void AbstractCommand::swapSocket(std::shared_ptr<SocketCore>& socket)
|
||||||
{
|
{
|
||||||
|
@ -620,15 +564,14 @@ void AbstractCommand::swapSocket(std::shared_ptr<SocketCore> &socket)
|
||||||
namespace {
|
namespace {
|
||||||
// Constructs proxy URI, merging username and password if they are
|
// Constructs proxy URI, merging username and password if they are
|
||||||
// defined.
|
// defined.
|
||||||
std::string makeProxyUri(PrefPtr proxyPref,
|
std::string makeProxyUri
|
||||||
|
(PrefPtr proxyPref,
|
||||||
PrefPtr proxyUser,
|
PrefPtr proxyUser,
|
||||||
PrefPtr proxyPasswd,
|
PrefPtr proxyPasswd,
|
||||||
const Option* option)
|
const Option* option)
|
||||||
{
|
{
|
||||||
uri::UriStruct us;
|
uri::UriStruct us;
|
||||||
if (!uri::parse(us, option->get(proxyPref))) {
|
if(uri::parse(us, option->get(proxyPref))) {
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if(option->defined(proxyUser)) {
|
if(option->defined(proxyUser)) {
|
||||||
us.username = option->get(proxyUser);
|
us.username = option->get(proxyUser);
|
||||||
}
|
}
|
||||||
|
@ -637,55 +580,60 @@ std::string makeProxyUri(PrefPtr proxyPref,
|
||||||
us.hasPassword = true;
|
us.hasPassword = true;
|
||||||
}
|
}
|
||||||
return uri::construct(us);
|
return uri::construct(us);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Returns proxy option value for the given protocol.
|
// Returns proxy option value for the given protocol.
|
||||||
std::string getProxyOptionFor(PrefPtr proxyPref,
|
std::string getProxyOptionFor
|
||||||
|
(PrefPtr proxyPref,
|
||||||
PrefPtr proxyUser,
|
PrefPtr proxyUser,
|
||||||
PrefPtr proxyPasswd,
|
PrefPtr proxyPasswd,
|
||||||
const Option* option)
|
const Option* option)
|
||||||
{
|
{
|
||||||
std::string uri = makeProxyUri(proxyPref, proxyUser, proxyPasswd, option);
|
std::string uri = makeProxyUri(proxyPref, proxyUser, proxyPasswd, option);
|
||||||
if(uri.empty()) {
|
if(uri.empty()) {
|
||||||
return makeProxyUri(
|
return makeProxyUri(PREF_ALL_PROXY, PREF_ALL_PROXY_USER,
|
||||||
PREF_ALL_PROXY, PREF_ALL_PROXY_USER, PREF_ALL_PROXY_PASSWD, option);
|
PREF_ALL_PROXY_PASSWD, option);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Returns proxy URI for given protocol. If no proxy URI is defined,
|
// Returns proxy URI for given protocol. If no proxy URI is defined,
|
||||||
// then returns an empty string.
|
// then returns an empty string.
|
||||||
std::string getProxyUri(const std::string &protocol, const Option *option)
|
std::string getProxyUri
|
||||||
|
(const std::string& protocol, const Option* option)
|
||||||
{
|
{
|
||||||
if(protocol == "http") {
|
if(protocol == "http") {
|
||||||
return getProxyOptionFor(
|
return getProxyOptionFor(PREF_HTTP_PROXY,
|
||||||
PREF_HTTP_PROXY, PREF_HTTP_PROXY_USER, PREF_HTTP_PROXY_PASSWD, option);
|
PREF_HTTP_PROXY_USER,
|
||||||
}
|
PREF_HTTP_PROXY_PASSWD,
|
||||||
|
option);
|
||||||
if (protocol == "https") {
|
} else if(protocol == "https") {
|
||||||
return getProxyOptionFor(PREF_HTTPS_PROXY,
|
return getProxyOptionFor(PREF_HTTPS_PROXY,
|
||||||
PREF_HTTPS_PROXY_USER,
|
PREF_HTTPS_PROXY_USER,
|
||||||
PREF_HTTPS_PROXY_PASSWD,
|
PREF_HTTPS_PROXY_PASSWD,
|
||||||
option);
|
option);
|
||||||
}
|
} else if(protocol == "ftp") {
|
||||||
|
return getProxyOptionFor(PREF_FTP_PROXY,
|
||||||
if (protocol == "ftp") {
|
PREF_FTP_PROXY_USER,
|
||||||
return getProxyOptionFor(
|
PREF_FTP_PROXY_PASSWD,
|
||||||
PREF_FTP_PROXY, PREF_FTP_PROXY_USER, PREF_FTP_PROXY_PASSWD, option);
|
option);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
return A2STR::NIL;
|
return A2STR::NIL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// Returns true if proxy is defined for the given protocol. Otherwise
|
// Returns true if proxy is defined for the given protocol. Otherwise
|
||||||
// returns false.
|
// returns false.
|
||||||
bool isProxyRequest(const std::string &protocol,
|
bool isProxyRequest
|
||||||
const std::shared_ptr<Option> &option)
|
(const std::string& protocol, const std::shared_ptr<Option>& option)
|
||||||
{
|
{
|
||||||
std::string proxyUri = getProxyUri(protocol, option.get());
|
std::string proxyUri = getProxyUri(protocol, option.get());
|
||||||
return !proxyUri.empty();
|
return !proxyUri.empty();
|
||||||
|
@ -693,36 +641,39 @@ bool isProxyRequest(const std::string &protocol,
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool inNoProxy(const std::shared_ptr<Request> &req, const std::string &noProxy)
|
bool inNoProxy(const std::shared_ptr<Request>& req,
|
||||||
|
const std::string& noProxy)
|
||||||
{
|
{
|
||||||
std::vector<Scip> entries;
|
std::vector<Scip> entries;
|
||||||
util::splitIter(
|
util::splitIter(noProxy.begin(), noProxy.end(), std::back_inserter(entries),
|
||||||
noProxy.begin(), noProxy.end(), std::back_inserter(entries), ',', true);
|
',', true);
|
||||||
if(entries.empty()) {
|
if(entries.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
for(std::vector<Scip>::const_iterator i = entries.begin(),
|
||||||
for (const auto &e : entries) {
|
eoi = entries.end(); i != eoi; ++i) {
|
||||||
const auto slashpos = std::find(e.first, e.second, '/');
|
std::string::const_iterator slashpos =
|
||||||
if (slashpos == e.second) {
|
std::find((*i).first, (*i).second, '/');
|
||||||
if (util::noProxyDomainMatch(req->getHost(),
|
if(slashpos == (*i).second) {
|
||||||
std::string(e.first, e.second))) {
|
if(util::noProxyDomainMatch
|
||||||
|
(req->getHost(), std::string((*i).first, (*i).second))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
// TODO We don't resolve hostname here. More complete
|
// TODO We don't resolve hostname here. More complete
|
||||||
// implementation is that we should first resolve
|
// implementation is that we should first resolve
|
||||||
// hostname(which may result in several IP addresses) and
|
// hostname(which may result in several IP addresses) and
|
||||||
// evaluates against all of them
|
// evaluates against all of them
|
||||||
std::string ip(e.first, slashpos);
|
std::string ip((*i).first, slashpos);
|
||||||
uint32_t bits;
|
uint32_t bits;
|
||||||
if (!util::parseUIntNoThrow(bits, std::string(slashpos + 1, e.second))) {
|
if(!util::parseUIntNoThrow(bits, std::string(slashpos+1, (*i).second))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(util::inSameCidrBlock(ip, req->getHost(), bits)) {
|
if(util::inSameCidrBlock(ip, req->getHost(), bits)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -739,42 +690,30 @@ std::shared_ptr<Request> AbstractCommand::createProxyRequest() const
|
||||||
if(inNoProxy(req_, getOption()->get(PREF_NO_PROXY))) {
|
if(inNoProxy(req_, getOption()->get(PREF_NO_PROXY))) {
|
||||||
return proxyRequest;
|
return proxyRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string proxy = getProxyUri(req_->getProtocol(), getOption().get());
|
std::string proxy = getProxyUri(req_->getProtocol(), getOption().get());
|
||||||
if(!proxy.empty()) {
|
if(!proxy.empty()) {
|
||||||
proxyRequest.reset(new Request());
|
proxyRequest.reset(new Request());
|
||||||
if(proxyRequest->setUri(proxy)) {
|
if(proxyRequest->setUri(proxy)) {
|
||||||
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Using proxy", getCuid()));
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Using proxy", getCuid()));
|
||||||
}
|
} else {
|
||||||
else {
|
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - Failed to parse proxy string",
|
||||||
A2_LOG_DEBUG(
|
getCuid()));
|
||||||
fmt("CUID#%" PRId64 " - Failed to parse proxy string", getCuid()));
|
|
||||||
proxyRequest.reset();
|
proxyRequest.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return proxyRequest;
|
return proxyRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AbstractCommand::resolveHostname(std::vector<std::string> &addrs,
|
std::string AbstractCommand::resolveHostname
|
||||||
const std::string &hostname,
|
(std::vector<std::string>& addrs, const std::string& hostname, uint16_t port)
|
||||||
uint16_t port)
|
|
||||||
{
|
{
|
||||||
if(util::isNumericHost(hostname)) {
|
if(util::isNumericHost(hostname)) {
|
||||||
addrs.push_back(hostname);
|
addrs.push_back(hostname);
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
e_->findAllCachedIPAddresses(std::back_inserter(addrs), hostname, port);
|
e_->findAllCachedIPAddresses(std::back_inserter(addrs), hostname, port);
|
||||||
if (!addrs.empty()) {
|
|
||||||
auto ipaddr = addrs.front();
|
|
||||||
A2_LOG_INFO(fmt(MSG_DNS_CACHE_HIT,
|
|
||||||
getCuid(),
|
|
||||||
hostname.c_str(),
|
|
||||||
strjoin(addrs.begin(), addrs.end(), ", ").c_str()));
|
|
||||||
return ipaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ipaddr;
|
std::string ipaddr;
|
||||||
|
if(addrs.empty()) {
|
||||||
#ifdef ENABLE_ASYNC_DNS
|
#ifdef ENABLE_ASYNC_DNS
|
||||||
if(getOption()->getAsBool(PREF_ASYNC_DNS)) {
|
if(getOption()->getAsBool(PREF_ASYNC_DNS)) {
|
||||||
if(!asyncNameResolverMan_->started()) {
|
if(!asyncNameResolverMan_->started()) {
|
||||||
|
@ -783,31 +722,26 @@ std::string AbstractCommand::resolveHostname(std::vector<std::string> &addrs,
|
||||||
switch(asyncNameResolverMan_->getStatus()) {
|
switch(asyncNameResolverMan_->getStatus()) {
|
||||||
case -1:
|
case -1:
|
||||||
if(!isProxyRequest(req_->getProtocol(), getOption())) {
|
if(!isProxyRequest(req_->getProtocol(), getOption())) {
|
||||||
e_->getRequestGroupMan()
|
e_->getRequestGroupMan()->getOrCreateServerStat
|
||||||
->getOrCreateServerStat(req_->getHost(), req_->getProtocol())
|
(req_->getHost(), req_->getProtocol())->setError();
|
||||||
->setError();
|
|
||||||
}
|
}
|
||||||
throw DL_ABORT_EX2(fmt(MSG_NAME_RESOLUTION_FAILED,
|
throw DL_ABORT_EX2
|
||||||
getCuid(),
|
(fmt(MSG_NAME_RESOLUTION_FAILED, getCuid(), hostname.c_str(),
|
||||||
hostname.c_str(),
|
|
||||||
asyncNameResolverMan_->getLastError().c_str()),
|
asyncNameResolverMan_->getLastError().c_str()),
|
||||||
error_code::NAME_RESOLVE_ERROR);
|
error_code::NAME_RESOLVE_ERROR);
|
||||||
case 0:
|
case 0:
|
||||||
return A2STR::NIL;
|
return A2STR::NIL;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
asyncNameResolverMan_->getResolvedAddress(addrs);
|
asyncNameResolverMan_->getResolvedAddress(addrs);
|
||||||
if(addrs.empty()) {
|
if(addrs.empty()) {
|
||||||
throw DL_ABORT_EX2(fmt(MSG_NAME_RESOLUTION_FAILED,
|
throw DL_ABORT_EX2
|
||||||
getCuid(),
|
(fmt(MSG_NAME_RESOLUTION_FAILED, getCuid(), hostname.c_str(),
|
||||||
hostname.c_str(),
|
|
||||||
"No address returned"),
|
"No address returned"),
|
||||||
error_code::NAME_RESOLVE_ERROR);
|
error_code::NAME_RESOLVE_ERROR);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
#endif // ENABLE_ASYNC_DNS
|
#endif // ENABLE_ASYNC_DNS
|
||||||
{
|
{
|
||||||
NameResolver res;
|
NameResolver res;
|
||||||
|
@ -821,67 +755,74 @@ std::string AbstractCommand::resolveHostname(std::vector<std::string> &addrs,
|
||||||
getCuid(),
|
getCuid(),
|
||||||
hostname.c_str(),
|
hostname.c_str(),
|
||||||
strjoin(addrs.begin(), addrs.end(), ", ").c_str()));
|
strjoin(addrs.begin(), addrs.end(), ", ").c_str()));
|
||||||
for (const auto &addr: addrs) {
|
for(std::vector<std::string>::const_iterator i = addrs.begin(),
|
||||||
e_->cacheIPAddress(hostname, addr, port);
|
eoi = addrs.end(); i != eoi; ++i) {
|
||||||
|
e_->cacheIPAddress(hostname, *i, port);
|
||||||
}
|
}
|
||||||
ipaddr = e_->findCachedIPAddress(hostname, port);
|
ipaddr = e_->findCachedIPAddress(hostname, port);
|
||||||
|
} else {
|
||||||
|
ipaddr = addrs.front();
|
||||||
|
A2_LOG_INFO(fmt(MSG_DNS_CACHE_HIT,
|
||||||
|
getCuid(),
|
||||||
|
hostname.c_str(),
|
||||||
|
strjoin(addrs.begin(), addrs.end(), ", ").c_str()));
|
||||||
|
}
|
||||||
return ipaddr;
|
return ipaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractCommand::prepareForNextAction(
|
void AbstractCommand::prepareForNextAction
|
||||||
std::unique_ptr<CheckIntegrityEntry> checkEntry)
|
(std::unique_ptr<CheckIntegrityEntry> checkEntry)
|
||||||
{
|
{
|
||||||
std::vector<std::unique_ptr<Command>> commands;
|
std::vector<std::unique_ptr<Command>> commands;
|
||||||
requestGroup_->processCheckIntegrityEntry(
|
requestGroup_->processCheckIntegrityEntry(commands, std::move(checkEntry),
|
||||||
commands, std::move(checkEntry), e_);
|
e_);
|
||||||
e_->addCommand(std::move(commands));
|
e_->addCommand(std::move(commands));
|
||||||
e_->setNoWait(true);
|
e_->setNoWait(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractCommand::checkIfConnectionEstablished(
|
bool AbstractCommand::checkIfConnectionEstablished
|
||||||
const std::shared_ptr<SocketCore> &socket,
|
(const std::shared_ptr<SocketCore>& socket,
|
||||||
const std::string& connectedHostname,
|
const std::string& connectedHostname,
|
||||||
const std::string& connectedAddr,
|
const std::string& connectedAddr,
|
||||||
uint16_t connectedPort)
|
uint16_t connectedPort)
|
||||||
{
|
{
|
||||||
std::string error = socket->getSocketError();
|
std::string error = socket->getSocketError();
|
||||||
if (error.empty()) {
|
if(!error.empty()) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See also InitiateConnectionCommand::executeInternal()
|
// See also InitiateConnectionCommand::executeInternal()
|
||||||
e_->markBadIPAddress(connectedHostname, connectedAddr, connectedPort);
|
e_->markBadIPAddress(connectedHostname, connectedAddr, connectedPort);
|
||||||
if (e_->findCachedIPAddress(connectedHostname, connectedPort).empty()) {
|
if(!e_->findCachedIPAddress(connectedHostname, connectedPort).empty()) {
|
||||||
|
A2_LOG_INFO(fmt(MSG_CONNECT_FAILED_AND_RETRY,
|
||||||
|
getCuid(),
|
||||||
|
connectedAddr.c_str(), connectedPort));
|
||||||
|
e_->setNoWait(true);
|
||||||
|
e_->addCommand(InitiateConnectionCommandFactory::
|
||||||
|
createInitiateConnectionCommand
|
||||||
|
(getCuid(), req_, fileEntry_, requestGroup_, e_));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
e_->removeCachedIPAddress(connectedHostname, connectedPort);
|
e_->removeCachedIPAddress(connectedHostname, connectedPort);
|
||||||
// Don't set error if proxy server is used and its method is GET.
|
// Don't set error if proxy server is used and its method is GET.
|
||||||
if(resolveProxyMethod(req_->getProtocol()) != V_GET ||
|
if(resolveProxyMethod(req_->getProtocol()) != V_GET ||
|
||||||
!isProxyRequest(req_->getProtocol(), getOption())) {
|
!isProxyRequest(req_->getProtocol(), getOption())) {
|
||||||
e_->getRequestGroupMan()
|
e_->getRequestGroupMan()->getOrCreateServerStat
|
||||||
->getOrCreateServerStat(req_->getHost(), req_->getProtocol())
|
(req_->getHost(), req_->getProtocol())->setError();
|
||||||
->setError();
|
|
||||||
}
|
}
|
||||||
throw DL_RETRY_EX(fmt(MSG_ESTABLISHING_CONNECTION_FAILED, error.c_str()));
|
throw DL_RETRY_EX
|
||||||
|
(fmt(MSG_ESTABLISHING_CONNECTION_FAILED, error.c_str()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
A2_LOG_INFO(fmt(MSG_CONNECT_FAILED_AND_RETRY,
|
const std::string& AbstractCommand::resolveProxyMethod
|
||||||
getCuid(),
|
(const std::string& protocol) const
|
||||||
connectedAddr.c_str(),
|
|
||||||
connectedPort));
|
|
||||||
e_->setNoWait(true);
|
|
||||||
e_->addCommand(
|
|
||||||
InitiateConnectionCommandFactory::createInitiateConnectionCommand(
|
|
||||||
getCuid(), req_, fileEntry_, requestGroup_, e_));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string&
|
|
||||||
AbstractCommand::resolveProxyMethod(const std::string &protocol) const
|
|
||||||
{
|
{
|
||||||
if (getOption()->get(PREF_PROXY_METHOD) == V_TUNNEL || protocol == "https") {
|
if(getOption()->get(PREF_PROXY_METHOD) == V_TUNNEL ||
|
||||||
|
protocol == "https") {
|
||||||
return V_TUNNEL;
|
return V_TUNNEL;
|
||||||
}
|
} else {
|
||||||
return V_GET;
|
return V_GET;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::shared_ptr<Option>& AbstractCommand::getOption() const
|
const std::shared_ptr<Option>& AbstractCommand::getOption() const
|
||||||
{
|
{
|
||||||
|
@ -897,10 +838,10 @@ int32_t AbstractCommand::calculateMinSplitSize() const
|
||||||
{
|
{
|
||||||
if(req_ && req_->isPipeliningEnabled()) {
|
if(req_ && req_->isPipeliningEnabled()) {
|
||||||
return getDownloadContext()->getPieceLength();
|
return getDownloadContext()->getPieceLength();
|
||||||
}
|
} else {
|
||||||
|
|
||||||
return getOption()->getAsInt(PREF_MIN_SPLIT_SIZE);
|
return getOption()->getAsInt(PREF_MIN_SPLIT_SIZE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AbstractCommand::setRequest(const std::shared_ptr<Request>& request)
|
void AbstractCommand::setRequest(const std::shared_ptr<Request>& request)
|
||||||
{
|
{
|
||||||
|
@ -922,8 +863,7 @@ void AbstractCommand::setSocket(const std::shared_ptr<SocketCore>& s)
|
||||||
socket_ = s;
|
socket_ = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<DownloadContext>&
|
const std::shared_ptr<DownloadContext>& AbstractCommand::getDownloadContext() const
|
||||||
AbstractCommand::getDownloadContext() const
|
|
||||||
{
|
{
|
||||||
return requestGroup_->getDownloadContext();
|
return requestGroup_->getDownloadContext();
|
||||||
}
|
}
|
||||||
|
@ -940,13 +880,11 @@ const std::shared_ptr<PieceStorage>& AbstractCommand::getPieceStorage() const
|
||||||
|
|
||||||
void AbstractCommand::checkSocketRecvBuffer()
|
void AbstractCommand::checkSocketRecvBuffer()
|
||||||
{
|
{
|
||||||
if (socketRecvBuffer_->bufferEmpty()) {
|
if(!socketRecvBuffer_->bufferEmpty()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setStatus(Command::STATUS_ONESHOT_REALTIME);
|
setStatus(Command::STATUS_ONESHOT_REALTIME);
|
||||||
e_->setNoWait(true);
|
e_->setNoWait(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AbstractCommand::addCommandSelf()
|
void AbstractCommand::addCommandSelf()
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,8 +43,7 @@
|
||||||
|
|
||||||
#include "TimerA2.h"
|
#include "TimerA2.h"
|
||||||
|
|
||||||
namespace aria2
|
namespace aria2 {
|
||||||
{
|
|
||||||
|
|
||||||
class FileEntry;
|
class FileEntry;
|
||||||
class RequestGroup;
|
class RequestGroup;
|
||||||
|
@ -63,8 +62,7 @@ class AsyncNameResolver;
|
||||||
class AsyncNameResolverMan;
|
class AsyncNameResolverMan;
|
||||||
#endif // ENABLE_ASYNC_DNS
|
#endif // ENABLE_ASYNC_DNS
|
||||||
|
|
||||||
class AbstractCommand : public Command
|
class AbstractCommand : public Command {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Request> req_;
|
std::shared_ptr<Request> req_;
|
||||||
std::shared_ptr<FileEntry> fileEntry_;
|
std::shared_ptr<FileEntry> fileEntry_;
|
||||||
|
@ -92,11 +90,8 @@ private:
|
||||||
bool incNumConnection_;
|
bool incNumConnection_;
|
||||||
|
|
||||||
int32_t calculateMinSplitSize() const;
|
int32_t calculateMinSplitSize() const;
|
||||||
|
|
||||||
void useFasterRequest(const std::shared_ptr<Request>& fasterRequest);
|
void useFasterRequest(const std::shared_ptr<Request>& fasterRequest);
|
||||||
|
|
||||||
bool shouldCheck() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RequestGroup* getRequestGroup() const
|
RequestGroup* getRequestGroup() const
|
||||||
{
|
{
|
||||||
|
@ -155,32 +150,26 @@ public:
|
||||||
// return empty string. In this case, call this function with same
|
// return empty string. In this case, call this function with same
|
||||||
// arguments until resolved address is returned. Exception is
|
// arguments until resolved address is returned. Exception is
|
||||||
// thrown on error. port is used for retrieving cached addresses.
|
// thrown on error. port is used for retrieving cached addresses.
|
||||||
std::string resolveHostname(std::vector<std::string> &addrs,
|
std::string resolveHostname
|
||||||
const std::string &hostname,
|
(std::vector<std::string>& addrs, const std::string& hostname, uint16_t port);
|
||||||
uint16_t port);
|
|
||||||
|
|
||||||
void tryReserved();
|
void tryReserved();
|
||||||
|
|
||||||
void setReadCheckSocket(const std::shared_ptr<SocketCore>& socket);
|
void setReadCheckSocket(const std::shared_ptr<SocketCore>& socket);
|
||||||
|
|
||||||
void setWriteCheckSocket(const std::shared_ptr<SocketCore>& socket);
|
void setWriteCheckSocket(const std::shared_ptr<SocketCore>& socket);
|
||||||
|
|
||||||
void disableReadCheckSocket();
|
void disableReadCheckSocket();
|
||||||
|
|
||||||
void disableWriteCheckSocket();
|
void disableWriteCheckSocket();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If pred == true, calls setReadCheckSocket(socket). Otherwise, calls
|
* If pred == true, calls setReadCheckSocket(socket). Otherwise, calls
|
||||||
* disableReadCheckSocket().
|
* disableReadCheckSocket().
|
||||||
*/
|
*/
|
||||||
void setReadCheckSocketIf(const std::shared_ptr<SocketCore> &socket,
|
void setReadCheckSocketIf(const std::shared_ptr<SocketCore>& socket, bool pred);
|
||||||
bool pred);
|
|
||||||
/**
|
/**
|
||||||
* If pred == true, calls setWriteCheckSocket(socket). Otherwise, calls
|
* If pred == true, calls setWriteCheckSocket(socket). Otherwise, calls
|
||||||
* disableWriteCheckSocket().
|
* disableWriteCheckSocket().
|
||||||
*/
|
*/
|
||||||
void setWriteCheckSocketIf(const std::shared_ptr<SocketCore> &socket,
|
void setWriteCheckSocketIf(const std::shared_ptr<SocketCore>& socket, bool pred);
|
||||||
bool pred);
|
|
||||||
|
|
||||||
// Swaps socket_ with socket. This disables current read and write
|
// Swaps socket_ with socket. This disables current read and write
|
||||||
// check.
|
// check.
|
||||||
|
@ -191,10 +180,7 @@ public:
|
||||||
return timeout_;
|
return timeout_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTimeout(time_t timeout)
|
void setTimeout(time_t timeout) { timeout_ = timeout; }
|
||||||
{
|
|
||||||
timeout_ = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void prepareForNextAction(std::unique_ptr<CheckIntegrityEntry> checkEntry);
|
void prepareForNextAction(std::unique_ptr<CheckIntegrityEntry> checkEntry);
|
||||||
|
|
||||||
|
@ -203,7 +189,8 @@ public:
|
||||||
// InitiateConnectionCommandFactory and it is pushed to
|
// InitiateConnectionCommandFactory and it is pushed to
|
||||||
// DownloadEngine and returns false. If no addresses left, DlRetryEx
|
// DownloadEngine and returns false. If no addresses left, DlRetryEx
|
||||||
// exception is thrown.
|
// exception is thrown.
|
||||||
bool checkIfConnectionEstablished(const std::shared_ptr<SocketCore> &socket,
|
bool checkIfConnectionEstablished
|
||||||
|
(const std::shared_ptr<SocketCore>& socket,
|
||||||
const std::string& connectedHostname,
|
const std::string& connectedHostname,
|
||||||
const std::string& connectedAddr,
|
const std::string& connectedAddr,
|
||||||
uint16_t connectedPort);
|
uint16_t connectedPort);
|
||||||
|
@ -238,40 +225,33 @@ public:
|
||||||
void checkSocketRecvBuffer();
|
void checkSocketRecvBuffer();
|
||||||
|
|
||||||
void addCommandSelf();
|
void addCommandSelf();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool prepareForRetry(time_t wait);
|
virtual bool prepareForRetry(time_t wait);
|
||||||
|
|
||||||
virtual void onAbort();
|
virtual void onAbort();
|
||||||
|
|
||||||
virtual bool executeInternal() = 0;
|
virtual bool executeInternal() = 0;
|
||||||
|
|
||||||
// Returns true if the derived class wants to execute
|
// Returns true if the derived class wants to execute
|
||||||
// executeInternal() unconditionally
|
// executeInternal() unconditionally
|
||||||
virtual bool noCheck() const
|
virtual bool noCheck()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractCommand(cuid_t cuid,
|
AbstractCommand(cuid_t cuid, const std::shared_ptr<Request>& req,
|
||||||
const std::shared_ptr<Request> &req,
|
|
||||||
const std::shared_ptr<FileEntry>& fileEntry,
|
const std::shared_ptr<FileEntry>& fileEntry,
|
||||||
RequestGroup *requestGroup,
|
RequestGroup* requestGroup, DownloadEngine* e,
|
||||||
DownloadEngine *e,
|
|
||||||
const std::shared_ptr<SocketCore>& s = nullptr,
|
const std::shared_ptr<SocketCore>& s = nullptr,
|
||||||
const std::shared_ptr<SocketRecvBuffer> &socketRecvBuffer =
|
const std::shared_ptr<SocketRecvBuffer>& socketRecvBuffer = nullptr,
|
||||||
nullptr,
|
|
||||||
bool incNumConnection = true);
|
bool incNumConnection = true);
|
||||||
|
|
||||||
virtual ~AbstractCommand();
|
virtual ~AbstractCommand();
|
||||||
|
|
||||||
virtual bool execute() CXX11_OVERRIDE;
|
virtual bool execute() CXX11_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns proxy URI for given protocol. If no proxy URI is defined,
|
// Returns proxy URI for given protocol. If no proxy URI is defined,
|
||||||
// then returns an empty string.
|
// then returns an empty string.
|
||||||
std::string getProxyUri(const std::string &protocol, const Option *option);
|
std::string getProxyUri
|
||||||
|
(const std::string& protocol, const Option* option);
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ bool ConnectCommand::executeInternal()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConnectCommand::noCheck() const
|
bool ConnectCommand::noCheck()
|
||||||
{
|
{
|
||||||
return backupConnectionInfo_ && !backupConnectionInfo_->ipaddr.empty();
|
return backupConnectionInfo_ && !backupConnectionInfo_->ipaddr.empty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ public:
|
||||||
const std::shared_ptr<Request>& getProxyRequest() const;
|
const std::shared_ptr<Request>& getProxyRequest() const;
|
||||||
protected:
|
protected:
|
||||||
virtual bool executeInternal() CXX11_OVERRIDE;
|
virtual bool executeInternal() CXX11_OVERRIDE;
|
||||||
virtual bool noCheck() const CXX11_OVERRIDE;
|
virtual bool noCheck() CXX11_OVERRIDE;
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Request> proxyRequest_;
|
std::shared_ptr<Request> proxyRequest_;
|
||||||
std::shared_ptr<BackupConnectInfo> backupConnectionInfo_;
|
std::shared_ptr<BackupConnectInfo> backupConnectionInfo_;
|
||||||
|
|
|
@ -241,11 +241,6 @@ public:
|
||||||
|
|
||||||
int64_t getCompletedLength() const;
|
int64_t getCompletedLength() const;
|
||||||
|
|
||||||
inline int64_t getPendingLength() const
|
|
||||||
{
|
|
||||||
return getTotalLength() - getCompletedLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares expected filename with specified actualFilename.
|
* Compares expected filename with specified actualFilename.
|
||||||
* The expected filename refers to FileEntry::getBasename() of the first
|
* The expected filename refers to FileEntry::getBasename() of the first
|
||||||
|
|
Loading…
Reference in New Issue