14#include <zypp-core/AutoDispose.h>
15#include <zypp-core/fs/PathInfo.h>
28 dlnowMulti += req->downloadedByteCount();
34 stateMachine()._sigProgress.emit( *stateMachine().z_func(),
_fileSize, dlnowMulti );
39 auto lck = stateMachine().z_func()->shared_from_this();
41 return ( r.get() == &req );
53 if ( reqLocked->_myMirror )
54 reqLocked->_myMirror->finishTransfer( !err.
isError() );
65 MIL_MEDIA <<
"Request finished "<<std::endl;
66 const auto &rngs = reqLocked->requestedRanges();
67 std::for_each( rngs.begin(), rngs.end(), [](
const auto &
b ){ DBG <<
"-> Block " << b.start <<
" finished." << std::endl; } );
69 auto restartReqWithBlock = [ this ]( std::shared_ptr<Request> &req, std::vector<Block> &&blocks ) {
70 MIL_MEDIA <<
"Reusing Request to download blocks:"<<std::endl;
81 MIL_MEDIA <<
"Reusing to download blocks: "<<std::endl;
82 if ( !restartReqWithBlock( reqLocked,
getNextBlocks( reqLocked->url().getScheme() ) ) ) {
83 return setFailed(
"Failed to restart request with new blocks." );
92 MIL_MEDIA <<
"Reusing to download failed blocks: "<<std::endl;
93 if ( !restartReqWithBlock( reqLocked, std::move(fblks) ) ) {
94 return setFailed(
"Failed to restart request with previously failed blocks." );
110 auto &parent = stateMachine();
116 retry = parent.handleRequestAuthError( req, err );
120 MIL <<
"Request failed " << req->extendedErrorString() <<
"(" << req->url() <<
")" << std::endl;
124 const auto &fRanges = req->failedRanges();
126 std::transform( fRanges.begin(), fRanges.end(), std::back_inserter(
_failedRanges), [ &req ](
const auto &r ){
127 Block b = std::any_cast<Block>(r.userData);;
128 b._failedWithErr = req->error();
129 if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 )
130 DBG_MEDIA <<
"Adding failed block to failed blocklist: " << b.start <<
" " << b.len <<
" (" << req->error().toString() <<
" [" << req->error().nativeErrorString()<<
"])" << std::endl;
140 WAR <<
"Multipart download failed: " << ex.
asString() << std::endl;
147 req->setPriority( parent._defaultSubRequestPriority );
210 auto &parent = stateMachine();
215 if ( err.isError() ) {
216 WAR <<
"Failure to setup mirror " << myUrl <<
" with error " << err.toString() <<
"("<< err.nativeErrorString() <<
"), dropping it from the list of mirrors." << std::endl;
226 if ( !blocks.size() )
229 if ( !blocks.size() ) {
236 const auto &spec = parent._spec;
239 req->_myMirror = mirror.second;
240 req->_originalUrl = myUrl;
241 req->setPriority( parent._defaultSubRequestPriority );
242 req->transferSettings() = settings;
248 DBG_MEDIA <<
"Creating Request to download blocks:"<<std::endl;
274 bool triggerResched =
false;
277 triggerResched =
true;
281 if ( triggerResched )
282 stateMachine()._requestDispatcher->reschedule();
287 if ( connectSignals )
288 req->connectSignals( *
this );
291 stateMachine()._requestDispatcher->enqueue( req );
293 if ( req->_myMirror )
294 req->_myMirror->startTransfer();
299 const off_t expFSize = stateMachine()._spec.expectedFileSize();
300 if ( expFSize > 0 && expFSize < currentFilesize ) {
312 req->resetRequestRanges();
313 for (
const auto &block : blocks ) {
314 if ( block.chksumVec && block.chksumtype.size() ) {
315 std::shared_ptr<zypp::Digest> dig = std::make_shared<zypp::Digest>();
316 if ( !dig->create( block.chksumtype ) ) {
317 WAR_MEDIA <<
"Trying to create Digest with chksum type " << block.chksumtype <<
" failed " << std::endl;
323 req->addRequestRange( block.start, block.len, dig, *block.chksumVec, std::any( block ), block.chksumCompareLen, block.chksumPad );
327 DBG_MEDIA <<
"Starting block " << block.start <<
" without checksum." << std::endl;
328 req->addRequestRange( block.start, block.len, {}, {}, std::any( block ) );
336 _error = std::move( err );
357 req->disconnectSignals();
359 stateMachine()._requestDispatcher->cancel( *req, err );
360 if ( req->_myMirror )
361 req->_myMirror->cancelTransfer();
367 std::vector<Block> blocks;
369 size_t accumulatedSize = 0;
373 std::optional<size_t> lastBlockEnd;
374 while (
_ranges.size() && accumulatedSize < prefSize ) {
375 const auto &r =
_ranges.front();
377 if ( !canDoRandomBlocks && lastBlockEnd ) {
378 if (
static_cast<const size_t>(r.start) != (*lastBlockEnd)+1 )
382 lastBlockEnd = r.start + r.len - 1;
383 accumulatedSize += r.len;
385 blocks.push_back( std::move(
_ranges.front() ) );
389 DBG_MEDIA <<
"Accumulated " << blocks.size() <<
" blocks with accumulated size of: " << accumulatedSize <<
"." << std::endl;
397 _failedRanges.sort( [](
const auto &
a ,
const auto &
b ){
return a.start <
b.start; } );
401 std::vector<Block> fblks;
402 std::optional<size_t> lastBlockEnd;
403 size_t accumulatedSize = 0;
409 if ( !canDoRandomBlocks && lastBlockEnd ) {
410 if (
static_cast<const size_t>(block.start) != (*lastBlockEnd)+1 )
414 lastBlockEnd = block.start + block.len - 1;
415 accumulatedSize += block.len;
420 fblks.back()._retryCount += 1;
422 if ( accumulatedSize >= prefSize )
432 if ( filesize == 0 )
return 4 * 1024 * 1024;
433 else if ( filesize < 4*1024*1024 )
return filesize;
434 else if ( filesize < 8*1024*1024 )
return 4*1024*1024;
435 else if ( filesize < 16*1024*1024 )
return 8*1024*1024;
436 else if ( filesize < 256*1024*1024 )
return 10*1024*1024;
Store and operate with byte count.
static const Unit K
1024 Byte
static std::string digestVectorToString(const UByteArray &vec)
get hex string representation of the digest vector given as parameter
Base class for Exception.
std::string asString() const
Error message provided by dumpOn as string.
std::pair< std::vector< Url >::const_iterator, MirrorHandle > MirrorPick
static zyppng::NetworkRequestError customError(NetworkRequestError::Type t, std::string &&errorMsg="", std::map< std::string, boost::any > &&extraInfo={})
The NetworkRequestError class Represents a error that occured in.
Type type() const
type Returns the type of the error
bool isError() const
isError Will return true if this is a actual error
zypp::ByteCount downloadedByteCount() const
Returns the number of already downloaded bytes as reported by the backend.
Url clearQueryString(const Url &url)
long ZYPP_MEDIA_CURL_DEBUG()
Long number for setting CURLOPT_DEBUGDATA.
int unlink(const Pathname &path)
Like 'unlink'.
bool hasPrefixCI(const C_Str &str_r, const C_Str &prefix_r)
NetworkRequestError setupMirror(const MirrorControl::MirrorPick &pick, Url &url, TransferSettings &set)
std::vector< Url > _fileMirrors
PrepareResult prepareNextMirror()
NetworkRequestError _error
Signal< void() > _sigFinished
off_t _downloadedMultiByteCount
std::vector< Block > getNextBlocks(const std::string &urlScheme)
zypp::ByteCount _preferredChunkSize
virtual void setFinished()
void onRequestProgress(NetworkRequest &, off_t, off_t, off_t, off_t)
void failedToPrepare() override
std::list< Block > _ranges
bool addBlockRanges(std::shared_ptr< Request > req, std::vector< Block > &&blocks) const
Just initialize the requests ranges from the internal blocklist.
void onRequestFinished(NetworkRequest &req, const NetworkRequestError &err)
void onRequestStarted(NetworkRequest &)
void handleRequestError(std::shared_ptr< Request > req, const zyppng::NetworkRequestError &err)
Signal< void() > _sigFailed
std::vector< std::shared_ptr< Request > > _runningRequests
bool assertExpectedFilesize(off_t currentFilesize)
std::vector< Block > getNextFailedBlocks(const std::string &urlScheme)
std::list< Block > _failedRanges
bool _inEnsureDownloadsRunning
static zypp::ByteCount makeBlksize(size_t filesize)
void mirrorReceived(MirrorControl::MirrorPick mirror) override
void cancelAll(const NetworkRequestError &err)
void addNewRequest(std::shared_ptr< Request > req, const bool connectSignals=true)
void setFailed(NetworkRequestError &&err)
void ensureDownloadsRunning()