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 << req.
nativeHandle() <<
" " <<
"Request finished successfully."<<std::endl;
66 const auto &rngs = reqLocked->requestedRanges();
67 std::for_each( rngs.begin(), rngs.end(), [&req](
const auto &
b ){ DBG_MEDIA << req.nativeHandle() <<
" " <<
"-> Block " << b.start <<
" finished." << std::endl; } );
69 auto restartReqWithBlock = [ this ]( std::shared_ptr<Request> &req, std::vector<Block> &&blocks ) {
70 MIL << req->
nativeHandle() <<
" " <<
"Reusing Request to download blocks:"<<std::endl;
81 MIL << req.
nativeHandle() <<
" " <<
"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 << req.
nativeHandle() <<
" " <<
"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 << req->nativeHandle() <<
" " <<
"Request failed " << req->extendedErrorString() <<
"(" << req->url() <<
")" << std::endl;
121 if ( req->lastRedirectInfo ().size () )
122 MIL << req->nativeHandle() <<
" Last redirection target was: " << req->lastRedirectInfo () << std::endl;
126 const auto &fRanges = req->failedRanges();
128 std::transform( fRanges.begin(), fRanges.end(), std::back_inserter(
_failedRanges), [ &req ](
const auto &r ){
129 Block b = std::any_cast<Block>(r.userData);;
130 b._failedWithErr = req->error();
131 if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 )
132 DBG_MEDIA <<
"Adding failed block to failed blocklist: " << b.start <<
" " << b.len <<
" (" << req->error().toString() <<
" [" << req->error().nativeErrorString()<<
"])" << std::endl;
142 WAR <<
"Multipart download failed: " << ex.
asString() << std::endl;
149 req->setPriority( parent._defaultSubRequestPriority );
212 auto &parent = stateMachine();
217 if ( err.isError() ) {
218 WAR <<
"Failure to setup mirror " << myUrl <<
" with error " << err.toString() <<
"("<< err.nativeErrorString() <<
"), dropping it from the list of mirrors." << std::endl;
228 if ( !blocks.size() )
231 if ( !blocks.size() ) {
238 const auto &spec = parent._spec;
241 req->_myMirror = mirror.second;
242 req->_originalUrl = myUrl;
243 req->setPriority( parent._defaultSubRequestPriority );
244 req->transferSettings() = settings;
250 MIL <<
"Creating Request to download blocks via mirror: " << myUrl << std::endl;
276 bool triggerResched =
false;
279 triggerResched =
true;
283 if ( triggerResched )
284 stateMachine()._requestDispatcher->reschedule();
289 if ( connectSignals )
290 req->connectSignals( *
this );
293 stateMachine()._requestDispatcher->enqueue( req );
295 if ( req->_myMirror )
296 req->_myMirror->startTransfer();
301 const off_t expFSize = stateMachine()._spec.expectedFileSize();
302 if ( expFSize > 0 && expFSize < currentFilesize ) {
314 req->resetRequestRanges();
315 for (
const auto &block : blocks ) {
316 if ( block.chksumVec && block.chksumtype.size() ) {
317 std::shared_ptr<zypp::Digest> dig = std::make_shared<zypp::Digest>();
318 if ( !dig->create( block.chksumtype ) ) {
319 WAR_MEDIA <<
"Trying to create Digest with chksum type " << block.chksumtype <<
" failed " << std::endl;
325 req->addRequestRange( block.start, block.len, dig, *block.chksumVec, std::any( block ), block.chksumCompareLen, block.chksumPad );
329 DBG_MEDIA <<
"Starting block " << block.start <<
" without checksum." << std::endl;
330 req->addRequestRange( block.start, block.len, {}, {}, std::any( block ) );
338 _error = std::move( err );
359 req->disconnectSignals();
361 stateMachine()._requestDispatcher->cancel( *req, err );
362 if ( req->_myMirror )
363 req->_myMirror->cancelTransfer();
369 std::vector<Block> blocks;
371 size_t accumulatedSize = 0;
375 std::optional<size_t> lastBlockEnd;
376 while (
_ranges.size() && accumulatedSize < prefSize ) {
377 const auto &r =
_ranges.front();
379 if ( !canDoRandomBlocks && lastBlockEnd ) {
380 if (
static_cast<const size_t>(r.start) != (*lastBlockEnd)+1 )
384 lastBlockEnd = r.start + r.len - 1;
385 accumulatedSize += r.len;
387 blocks.push_back( std::move(
_ranges.front() ) );
391 DBG_MEDIA <<
"Accumulated " << blocks.size() <<
" blocks with accumulated size of: " << accumulatedSize <<
"." << std::endl;
399 _failedRanges.sort( [](
const auto &
a ,
const auto &
b ){
return a.start <
b.start; } );
403 std::vector<Block> fblks;
404 std::optional<size_t> lastBlockEnd;
405 size_t accumulatedSize = 0;
411 if ( !canDoRandomBlocks && lastBlockEnd ) {
412 if (
static_cast<const size_t>(block.start) != (*lastBlockEnd)+1 )
416 lastBlockEnd = block.start + block.len - 1;
417 accumulatedSize += block.len;
422 fblks.back()._retryCount += 1;
424 if ( accumulatedSize >= prefSize )
434 if ( filesize == 0 )
return 4 * 1024 * 1024;
435 else if ( filesize < 4*1024*1024 )
return filesize;
436 else if ( filesize < 8*1024*1024 )
return 4*1024*1024;
437 else if ( filesize < 16*1024*1024 )
return 8*1024*1024;
438 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.
void * nativeHandle() const
Url clearQueryString(const Url &url)
const long & ZYPP_MEDIA_CURL_DEBUG()
const long& for setting CURLOPT_DEBUGDATA Returns a reference to a static variable,...
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()