5 #include <zypp-core/zyppng/io/IODevice> 7 #include <zypp-core/base/DtorReset> 9 #include <zypp-media/MediaException> 10 #include <zypp-media/FileCheckException> 11 #include <zypp-media/CDTools> 23 , _workDir(
std::move(workDir) )
32 MIL <<
"Provider workdir is: " <<
_workDir << std::endl;
41 std::string_view reasonStr;
44 reasonStr =
"ProvideStart";
47 reasonStr =
"QueueIdle";
50 reasonStr =
"EnqueueItem";
53 reasonStr =
"EnqueueReq";
56 reasonStr =
"FinishReq";
59 reasonStr =
"RestartAttach";
62 DBG <<
"Triggering the schedule timer (" << reasonStr <<
")" << std::endl;
73 MIL <<
"Provider is not started, NOT scheduling" << std::endl;
78 DBG_PRV <<
"Scheduling triggered during scheduling, returning immediately." << std::endl;
83 #ifdef _SC_NPROCESSORS_ONLN 84 sysconf(_SC_NPROCESSORS_ONLN) * 2;
90 constexpr
auto findLaziestWorker = [](
const auto &workerQueues,
const auto &idleNames ) {
91 auto candidate = workerQueues.end();
95 for (
const auto &name : idleNames ) {
96 auto thisElem = workerQueues.find(name);
97 if ( thisElem == workerQueues.end() )
100 const auto idleS = thisElem->second->idleSince();
102 && ( candidate == workerQueues.end() || *idleS < candidateIdleSince ) ) {
103 candidateIdleSince = *idleS;
104 candidate = thisElem;
108 if ( candidate != workerQueues.end() )
109 MIL_PRV <<
"Found idle worker:" << candidate->first <<
" idle since: " << candidateIdleSince.time_since_epoch().count() << std::endl;
117 if ( (*iMedia)->refCount() > 1 ) {
118 MIL_PRV <<
"Not releasing media " << (*iMedia)->_name <<
" refcount is not zero" << std::endl;
124 if ( (*iMedia)->_idleSince && std::chrono::steady_clock::now() - (*iMedia)->_idleSince.value() >= std::chrono::hours(1) ) {
125 MIL <<
"Detaching medium " << (*iMedia)->_name <<
" for baseUrl " << (*iMedia)->_attachedUrl << std::endl;
129 MIL_PRV <<
"Not releasing media " << (*iMedia)->_name <<
" downloading worker and not timed out yet." << std::endl;
133 auto bQueue = (*iMedia)->_backingQueue.lock();
140 MIL <<
"Detaching medium " << (*iMedia)->_name <<
" for baseUrl " << (*iMedia)->_attachedUrl << std::endl;
141 bQueue->enqueue ( *req );
145 ERR <<
"Could not send detach request, creating the request failed" << std::endl;
148 ERR <<
"Could not send detach request since no backing queue was defined" << std::endl;
157 const auto schedStart = std::chrono::steady_clock::now();
158 MIL_PRV <<
"Start scheduling" << std::endl;
161 const auto dur = std::chrono::steady_clock::now() - schedStart;
162 MIL_PRV <<
"Exit scheduling after:" << std::chrono::duration_cast<std::chrono::milliseconds>( dur ).count () << std::endl;
166 for (
auto it =
_items.begin (); it !=
_items.end(); ) {
182 for(
auto queueIter =
_queues.begin(); queueIter !=
_queues.end(); queueIter ++ ) {
184 const auto &scheme = queueIter->_schemeName;
185 auto &queue = queueIter->_requests;
192 MIL_PRV <<
"Start scheduling for scheme:" << scheme <<
" queue size is: " << queue.size() << std::endl;
196 ERR <<
"Scheme: " << scheme <<
" failed to return a valid configuration." << std::endl;
198 while( queue.size() ) {
199 auto item = std::move( queue.front() );
209 const auto &config = configOpt.get();
213 for(
auto i = queue.begin (); i != queue.end(); ) {
217 while ( i != queue.end() && !(*i) ) {
221 if ( i == queue.end() )
224 ProvideRequestRef item = *i;
231 item->owner()->finishReq(
nullptr, item,
ZYPP_EXCPT_PTR(
zypp::Exception(
"Downloading Queues do not support ProvideMessage::Code::Attach requests") ) );
235 MIL_PRV <<
"Trying to schedule request: " << item->urls().front() << std::endl;
238 int existingTypeWorkers = 0;
241 int existingConnections = 0;
244 std::vector< std::pair<zypp::Url, ProvideQueue*> > possibleHostWorkers;
247 std::vector<std::string> idleWorkers;
250 std::vector<zypp::Url> mirrsWithoutWorker;
251 for (
const auto &url : item->urls() ) {
254 MIL <<
"Mirror URL " << url <<
" is incompatible with current scheme: " << scheme <<
", ignoring." << std::endl;
258 if( item->owner()->canRedirectTo( item, url ) )
259 mirrsWithoutWorker.push_back( url );
261 MIL_PRV <<
"URL was rejected" << url << std::endl;
266 if( mirrsWithoutWorker.size() == 0 ) {
267 MIL <<
"Request has NO usable URLs" << std::endl;
279 existingTypeWorkers ++;
280 existingConnections += workerQueue->activeRequests();
282 if ( workerQueue->isIdle() )
288 for (
auto i = mirrsWithoutWorker.begin (); i != mirrsWithoutWorker.end(); ) {
290 if ( u.getHost() == workerQueue->hostname() ) {
292 possibleHostWorkers.push_back( {u, workerQueue.get()} );
293 i = mirrsWithoutWorker.erase( i );
302 MIL <<
"Current stats: " << std::endl;
303 MIL <<
"Existing type workers: " << existingTypeWorkers << std::endl;
304 MIL <<
"Existing active connections: " << existingConnections << std::endl;
305 MIL <<
"Possible host workers: "<< possibleHostWorkers.size() << std::endl;
306 MIL <<
"Mirrors without worker: " << mirrsWithoutWorker.size() << std::endl;
311 MIL_PRV <<
"Reached maximum nr of connections, break" << std::endl;
318 && mirrsWithoutWorker.size() ) {
320 MIL_PRV <<
"Free worker slots and available mirror URLs, starting a new worker" << std::endl;
324 for(
const auto &url : mirrsWithoutWorker ) {
327 if ( !item->owner()->safeRedirectTo ( item, url ) )
330 ProvideQueueRef q = std::make_shared<ProvideQueue>( *this );
331 if ( !q->startup( scheme,
_workDir / scheme / url.getHost(), url.getHost() ) ) {
335 MIL_PRV <<
"Started worker for " << url.getHost() <<
" enqueing request" << std::endl;
337 item->setActiveUrl(url);
354 if ( possibleHostWorkers.size() ) {
356 MIL_PRV <<
"No free worker slots, looking for the best existing worker" << std::endl;
358 while( possibleHostWorkers.size () ) {
359 std::vector< std::pair<zypp::Url, ProvideQueue *> >::iterator candidate = possibleHostWorkers.begin();
360 for (
auto i = candidate+1; i != possibleHostWorkers.end(); i++ ) {
361 if ( i->second->activeRequests () < candidate->second->activeRequests () )
365 if ( !item->owner()->safeRedirectTo( item, candidate->first ) ) {
366 possibleHostWorkers.erase( candidate );
370 MIL_PRV <<
"Using existing worker " << candidate->first.getHost() <<
" to download request" << std::endl;
373 item->setActiveUrl( candidate->first );
374 candidate->second->enqueue( item );
386 if ( idleWorkers.size() && mirrsWithoutWorker.size() ) {
388 MIL_PRV <<
"No free worker slots, no slots in existing queues, trying to decomission idle queues." << std::endl;
390 auto candidate = findLaziestWorker(
_workerQueues, idleWorkers );
399 for(
const auto &url : mirrsWithoutWorker ) {
401 if ( !item->owner()->safeRedirectTo ( item, url ) )
404 ProvideQueueRef q = std::make_shared<ProvideQueue>( *this );
405 if ( !q->startup( scheme,
_workDir / scheme / url.getHost(), url.getHost() ) ) {
409 MIL_PRV <<
"Replaced worker for " << url.getHost() <<
", enqueing request" << std::endl;
411 item->setActiveUrl(url);
428 MIL_PRV <<
"End of line, deferring request for next try." << std::endl;
434 for(
auto i = queue.begin (); i != queue.end(); ) {
438 while ( i != queue.end() && !(*i) ) {
442 if ( i == queue.end() )
446 ProvideRequestRef item = *i;
452 if ( item->owner () )
453 item->owner()->finishReq(
nullptr, item,
ZYPP_EXCPT_PTR(
zypp::Exception(
"CPU bound Queues do not support ProvideAttachSpecRef requests") ) );
457 MIL_PRV <<
"Trying to schedule request: " << item->urls().front() << std::endl;
460 int existingTypeWorkers = 0;
461 int existingSchemeWorkers = 0;
464 std::vector< ProvideQueue* > possibleWorkers;
467 std::vector<std::string> idleWorkers;
473 for (
const auto &tmpurl : item->urls() ) {
475 MIL <<
"Mirror URL " << tmpurl <<
" is incompatible with current scheme: " << scheme <<
", ignoring." << std::endl;
484 MIL <<
"Request has NO usable URLs" << std::endl;
498 existingTypeWorkers ++;
500 existingSchemeWorkers++;
501 if ( workerQueue->canScheduleMore() )
502 possibleWorkers.push_back(workerQueue.get());
505 if ( workerQueue->isIdle() )
510 MIL <<
"Current stats: " << std::endl;
511 MIL <<
"Existing type workers: " << existingTypeWorkers << std::endl;
512 MIL <<
"Possible CPU workers: "<< possibleWorkers.size() << std::endl;
516 if ( possibleWorkers.size() ) {
518 for (
auto &w : possibleWorkers ) {
520 MIL_PRV <<
"Using existing idle worker to provide request" << std::endl;
522 item->owner()->redirectTo ( item, url );
523 item->setActiveUrl( url );
535 if ( existingTypeWorkers < cpuLimit ) {
537 MIL_PRV <<
"Free CPU slots, starting a new worker" << std::endl;
540 item->owner()->redirectTo ( item, url );
542 ProvideQueueRef q = std::make_shared<ProvideQueue>( *this );
543 if ( q->startup( scheme,
_workDir / scheme ) ) {
545 item->setActiveUrl(url);
562 if ( possibleWorkers.size() ) {
563 MIL_PRV <<
"No free CPU slots, looking for the best existing worker" << std::endl;
565 if( possibleWorkers.size () ) {
566 std::vector<ProvideQueue *>::iterator candidate = possibleWorkers.begin();
567 for (
auto i = candidate+1; i != possibleWorkers.end(); i++ ) {
568 if ( (*i)->activeRequests () < (*candidate)->activeRequests () )
573 item->owner()->redirectTo ( item, url );
575 MIL_PRV <<
"Using existing worker to provide request" << std::endl;
576 item->setActiveUrl( url );
577 (*candidate)->enqueue( item );
585 if ( idleWorkers.size() ) {
587 MIL_PRV <<
"No free CPU slots, no slots in existing queues, trying to decomission idle queues." << std::endl;
589 auto candidate = findLaziestWorker(
_workerQueues, idleWorkers );
595 item->owner()->redirectTo ( item, url );
597 ProvideQueueRef q = std::make_shared<ProvideQueue>( *this );
598 if ( q->startup( scheme,
_workDir / scheme ) ) {
600 MIL_PRV <<
"Replaced worker, enqueing request" << std::endl;
602 item->setActiveUrl(url);
618 MIL_PRV <<
"No idle workers and no free CPU spots, wait for the next schedule run" << std::endl;
623 MIL_PRV <<
"End of line, deferring request for next try." << std::endl;
630 for(
auto i = queue.begin (); i != queue.end(); ) {
634 while ( i != queue.end() && !(*i) ) {
638 if ( i == queue.end() )
642 ProvideRequestRef item = *i;
643 MIL_PRV <<
"Trying to schedule request: " << item->urls().front() << std::endl;
648 for (
const auto &tmpurl : item->urls() ) {
650 MIL <<
"Mirror URL " << tmpurl <<
" is incompatible with current scheme: " << scheme <<
", ignoring." << std::endl;
659 MIL <<
"Request has NO usable URLs" << std::endl;
669 ProvideQueueRef q = std::make_shared<ProvideQueue>( *this );
670 if ( !q->startup( scheme,
_workDir / scheme ) ) {
671 ERR <<
"Worker startup failed!" << std::endl;
680 MIL_PRV <<
"Started worker, enqueing request" << std::endl;
684 MIL_PRV <<
"Found worker, enqueing request" << std::endl;
689 item->owner()->redirectTo ( item, url );
691 item->setActiveUrl(url);
717 return expected<ProvideQueue::Config>::success(i->second);
725 return expected<ProvideQueue::Config>::success(newItem.first->second);
731 const auto &key = downloadedFile.
asString();
741 i.first->second._deathTimer.reset();
742 return i.first->second._file;
746 return i.first->second._file;
751 const auto &key = downloadedFile.
asString();
763 auto elem = std::find_if(
_items.begin(),
_items.end(), [item](
const auto &i){
return i.get() == item; } );
764 if ( elem !=
_items.end() ) {
785 MIL_PRV <<
"Registered new media attachment with ID: " << medium->name() <<
" with mountPoint: (" << medium->_localMountPoint.value_or(
zypp::Pathname()) <<
")" << std::endl;
794 auto existingQ = std::find_if(
_queues.begin (),
_queues.end(), [&schemeName](
const auto &qItem) {
795 return (qItem._schemeName == schemeName);
797 if ( existingQ !=
_queues.end() ) {
798 existingQ->_requests.push_back(req);
809 auto queue = req->currentQueue ();
811 queue->cancel( req.get(), error );
816 auto elem = std::find( q._requests.begin(), q._requests.end(), req );
817 if ( elem != q._requests.end() ) {
818 q._requests.erase(elem);
821 req->owner()->finishReq(
nullptr, req, error );
837 if ( v.second.get() == &q )
859 DBG_PRV <<
"Pulse timeout" << std::endl;
861 auto now = std::chrono::steady_clock::now();
867 auto &cacheItem = i->second;
868 if ( cacheItem._file.unique() ) {
869 if ( cacheItem._deathTimer ) {
870 if ( now - *cacheItem._deathTimer < std::chrono::seconds(20) ) {
871 MIL <<
"Releasing file " << *i->second._file <<
" from cache, death timeout." << std::endl;
877 cacheItem._deathTimer = std::chrono::steady_clock::now();
902 auto i = std::find(
_items.begin(),
_items.end(), itemRef );
903 if ( i ==
_items.end() ) {
904 ERR <<
"State of unknown Item changed, ignoring" << std::endl;
923 : _parent( parent.weak_this<
Provide>() )
924 , _mediaRef(
std::move(mediaInfoRef) )
948 return invalidHandle;
954 static std::optional<zypp::Pathname> invalidHandle;
956 return invalidHandle;
974 return ProvideRef(
new Provide(workDir) );
979 return attachMedia ( std::vector<zypp::Url>{url}, request );
986 if ( urls.empty() ) {
991 std::vector<zypp::Url> usableMirrs;
992 std::optional<ProvideQueue::Config> scheme;
994 for (
auto mirrIt = urls.begin() ; mirrIt != urls.end(); mirrIt++ ) {
995 const auto &s = d->schemeConfig( d->effectiveScheme( mirrIt->getScheme() ) );
997 WAR <<
"URL: " << *mirrIt <<
" is not supported, ignoring!" << std::endl;
1002 usableMirrs.push_back ( *mirrIt );
1004 if ( scheme->worker_type () == s->worker_type () ) {
1005 usableMirrs.push_back( *mirrIt );
1007 WAR <<
"URL: " << *mirrIt <<
" has different worker type than the primary URL: "<< usableMirrs.front() <<
", ignoring!" << std::endl;
1012 if ( !scheme || usableMirrs.empty() ) {
1017 auto &attachedMedia = d->attachedMediaInfos ();
1018 for (
auto &medium : attachedMedia ) {
1019 if ( medium->isSameMedium ( usableMirrs, request ) ) {
1020 return makeReadyResult( expected<Provide::MediaHandle>::success(
Provide::MediaHandle( *
this, medium ) ));
1026 return op->promise();
1034 return op->promise();
1039 return provide( std::vector<zypp::Url>{ url }, request );
1045 const auto i = std::find( d->_attachedMediaInfos.begin(), d->_attachedMediaInfos.end(), attachHandle.
mediaInfo() );
1046 if ( i == d->_attachedMediaInfos.end() ) {
1068 return op->promise();
1079 if ( chksumRes.headers().contains(algorithm) ) {
1081 return expected<zypp::CheckSum>::success(
zypp::CheckSum( algorithm, chksumRes.headers().value(algorithm).asString() ) );
1083 return expected<zypp::CheckSum>::error( std::current_exception() );
1099 return expected<zypp::ManagedFile>::success( copyRes.asManagedFile() );
1108 auto fName = source.file();
1110 | [ resSave = std::move(source) ] (
auto &&result ) {
1120 d->_isRunning =
true;
1121 d->_pulseTimer->start( 5000 );
1123 if ( d->_log ) d->_log->provideStart();
1128 d_func()->_workerPath = path;
1133 if ( !queueRef.empty() ) {
1141 d_func()->_log = tracker;
1146 return d_func()->_workDir;
1152 return d->_credManagerOptions;
1157 d_func()->_credManagerOptions = opt;
1162 return d_func()->_sigIdle;
1165 SignalProxy<Provide::MediaChangeAction ( const std::string &queueRef, const std::string &, const int32_t, const std::vector<std::string> &,
const std::optional<std::string> &)>
Provide::sigMediaChangeRequested()
1167 return d_func()->_sigMediaChange;
1170 SignalProxy< std::optional<zypp::media::AuthData> (
const zypp::Url &reqUrl,
const std::string &triedUsername,
const std::map<std::string, std::string> &extraValues ) >
Provide::sigAuthRequired()
1172 return d_func()->_sigAuthRequired;
1178 : _provider( parent )
1192 if ( sTime > sTime.min() && fTime >= sTime ) {
1193 auto duration = std::chrono::duration_cast<std::chrono::seconds>( item.
finishedTime() - item.
startTime() );
1194 if ( duration.count() )
1203 MIL <<
"Item failed" << std::endl;
1222 for (
const auto &i : prov->d_func()->items() ) {
1236 const auto &
stats = i->currentStats();
1237 const auto & prevStats = i->previousStats();
1238 if ( !
stats || !prevStats ) {
1239 ERR <<
"Bug! Stats should be initialized by now" << std::endl;
1247 tmpPartialBytes +=
stats->_bytesProvided;
1254 const auto now = std::chrono::steady_clock::now();
1255 const auto sinceLast = std::chrono::duration_cast<std::chrono::seconds>( now -
_stats.
_lastPulseTime );
1256 const auto lastFinB = lastPartialBytes + lastFinishedBytes;
1259 const auto diff = currFinB - lastFinB;
1263 if ( sinceLast >= std::chrono::seconds(1) )
1267 if ( sinceStart.count() ) {
std::string getScheme() const
Returns the scheme name of the URL.
constexpr auto DEFAULT_MAX_DYNAMIC_WORKERS
SignalProxy< void()> sigIdle()
const zypp::Pathname & providerWorkdir() const
zypp::ByteCount _finishedBytes
static ProvideFileItemRef create(const std::vector< zypp::Url > &urls, const ProvideFileSpec &request, ProvidePrivate &parent)
std::optional< zypp::ManagedFile > addToFileCache(const zypp::Pathname &downloadedFile)
bool queueRequest(ProvideRequestRef req)
Pathname realpath() const
Returns this path as the absolute canonical pathname.
AsyncOpRef< expected< ProvideRes > > provide(const std::vector< zypp::Url > &urls, const ProvideFileSpec &request)
const zypp::media::CredManagerOptions & credManangerOptions() const
ProvideStatus(ProvideRef parent)
std::list< ProvideItemRef > _items
void appendPathName(const Pathname &path_r, EEncoding eflag_r=zypp::url::E_DECODED)
Extend the path name.
Store and operate with byte count.
A ProvideRes object is a reference counted ownership of a resource in the cache provided by a Provide...
const zypp::Pathname & workerPath() const
AsyncOpRef< expected< zypp::CheckSum > > checksumForFile(const zypp::Pathname &p, const std::string &algorithm)
virtual void itemFailed(ProvideItem &item)
std::string nextMediaId() const
std::string stripSuffix(const C_Str &str_r, const C_Str &suffix_r)
Strip a suffix_r from str_r and return the resulting string.
String related utilities and Regular expression matching.
void enqueue(ProvideRequestRef request)
bool provideDebugEnabled()
const std::string & asString(const std::string &t)
Global asString() that works with std::string too.
std::unordered_map< std::string, ProvideQueue::Config > _schemeConfigs
zypp::Pathname _workerPath
std::chrono::time_point< std::chrono::steady_clock > TimePoint
static ProvideRef create(const zypp::Pathname &workDir="")
Timer::Ptr _scheduleTrigger
#define L_ENV_CONSTR_DEFINE_FUNC(ENV)
zypp::ByteCount _perSecond
std::chrono::steady_clock::time_point _lastPulseTime
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
void setAuthority(const std::string &authority)
Set the authority component in the URL.
std::vector< AttachedMediaInfo_Ptr > & attachedMediaInfos()
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
void setCredManagerOptions(const zypp::media::CredManagerOptions &opt)
Assign a vaiable a certain value when going out of scope.
bool isInCache(const zypp::Pathname &downloadedFile) const
bool empty() const
Test for an empty path.
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
expected< ProvideQueue::Config > schemeConfig(const std::string &scheme)
ProvidePrivate(zypp::Pathname &&workDir, Provide &pub)
std::deque< QueueItem > _queues
void onItemStateChanged(ProvideItem &item)
std::list< ProvideItemRef > & items()
SignalProxy< MediaChangeAction(const std::string &queueRef, const std::string &label, const int32_t mediaNr, const std::vector< std::string > &devices, const std::optional< std::string > &desc)> sigMediaChangeRequested()
void setScheme(const std::string &scheme)
Set the scheme name in the URL.
int unlink(const Pathname &path)
Like 'unlink'.
const std::string & asString() const
String representation.
const Config & workerConfig() const
zypp::ByteCount _expectedBytes
virtual void itemDone(ProvideItem &item)
bool ejectDevice(const std::string &queueRef, const std::string &device)
void setWorkerPath(const zypp::Pathname &path)
void onPulseTimeout(Timer &)
const std::optional< ItemStats > & currentStats() const
bool startsWith(const C_Str &str_r, const C_Str &prefix_r)
alias for hasPrefix
ProvideMediaHandle MediaHandle
std::vector< AttachedMediaInfo_Ptr > _attachedMediaInfos
void schedule(ScheduleReason reason)
virtual void provideStart()
constexpr auto DEFAULT_CPU_WORKERS
zypp::ByteCount _partialBytes
bool isValid() const
Verifies the Url.
constexpr auto DEFAULT_ACTIVE_CONN_PER_HOST
const std::string queueName(ProvideQueue &q) const
void dequeueItem(ProvideItem *item)
Provide(const zypp::Pathname &workDir)
zypp::media::CredManagerOptions _credManagerOptions
bool startup(const std::string &workerScheme, const zypp::Pathname &workDir, const std::string &hostname="")
constexpr std::string_view DEFAULT_PROVIDE_WORKER_PATH
std::unordered_map< std::string, FileCacheItem > _fileCache
bool dequeueRequest(ProvideRequestRef req, std::exception_ptr error)
AsyncOpRef< expected< MediaHandle > > attachMedia(const std::vector< zypp::Url > &urls, const ProvideMediaSpec &request)
Base class for Exception.
constexpr auto DEFAULT_ACTIVE_CONN
void queueItem(ProvideItemRef item)
reference value() const
Reference to the Tp object.
zypp::media::CredManagerOptions & credManagerOptions()
static expected< ProvideRequestRef > createDetach(const zypp::Url &url)
zypp::ByteCount _perSecondSinceLastPulse
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
void setStatusTracker(ProvideStatusRef tracker)
std::unordered_map< std::string, std::string > _workerAlias
std::chrono::steady_clock::time_point _startTime
const Stats & stats() const
AsyncOpRef< expected< zypp::ManagedFile > > copyFile(const zypp::Pathname &source, const zypp::Pathname &target)
Wrapper class for ::stat/::lstat.
constexpr std::string_view device("device")
ZYPP_IMPL_PRIVATE(NetworkRequestError)
AttachedMediaInfo_Ptr addMedium(AttachedMediaInfo_Ptr &&medium)
Easy-to use interface to the ZYPP dependency resolver.
std::unordered_map< std::string, ProvideQueueRef > _workerQueues
std::string effectiveScheme(const std::string &scheme) const
virtual std::chrono::steady_clock::time_point startTime() const
constexpr std::string_view ATTACHED_MEDIA_SUFFIX
virtual std::chrono::steady_clock::time_point finishedTime() const
SignalProxy< std::optional< zypp::media::AuthData > const zypp::Url &reqUrl, const std::string &triedUsername, const std::map< std::string, std::string > &extraValues) > sigAuthRequired()