libzypp  17.31.31
provideitem.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
9 
10 #include "private/providedbg_p.h"
11 #include "private/provideitem_p.h"
12 #include "private/provide_p.h"
14 #include "private/provideres_p.h"
15 #include "provide-configvars.h"
16 #include <zypp-media/MediaException>
17 #include <zypp-core/base/UserRequestException>
18 #include "mediaverifier.h"
19 #include <zypp-core/fs/PathInfo.h>
20 
21 using namespace std::literals;
22 
23 namespace zyppng {
24 
25  static constexpr std::string_view DEFAULT_MEDIA_VERIFIER("SuseMediaV1");
26 
27  expected<ProvideRequestRef> ProvideRequest::create(ProvideItem &owner, const std::vector<zypp::Url> &urls, const std::string &id, ProvideMediaSpec &spec )
28  {
29  if ( urls.empty() )
30  return expected<ProvideRequestRef>::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("List of URLs can not be empty") ) );
31 
32  auto m = ProvideMessage::createAttach( ProvideQueue::InvalidId, urls.front(), id, spec.label() );
33  if ( !spec.mediaFile().empty() ) {
34  m.setValue( AttachMsgFields::VerifyType, std::string(DEFAULT_MEDIA_VERIFIER.data()) );
35  m.setValue( AttachMsgFields::VerifyData, spec.mediaFile().asString() );
36  m.setValue( AttachMsgFields::MediaNr, int32_t(spec.medianr()) );
37  }
38 
39  const auto &cHeaders = spec.customHeaders();
40  for ( auto i = cHeaders.beginList (); i != cHeaders.endList(); i++) {
41  for ( const auto &val : i->second )
42  m.addValue( i->first, val );
43  }
44 
45  return expected<ProvideRequestRef>::success( ProvideRequestRef( new ProvideRequest(&owner, urls, std::move(m))) );
46  }
47 
48  expected<ProvideRequestRef> ProvideRequest::create( ProvideItem &owner, const std::vector<zypp::Url> &urls, ProvideFileSpec &spec )
49  {
50  if ( urls.empty() )
51  return expected<ProvideRequestRef>::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("List of URLs can not be empty") ) );
52 
53  auto m = ProvideMessage::createProvide ( ProvideQueue::InvalidId, urls.front() );
54  const auto &destFile = spec.destFilenameHint();
55  const auto &deltaFile = spec.deltafile();
56  const int64_t fSize = spec.downloadSize();;
57 
58  if ( !destFile.empty() )
59  m.setValue( ProvideMsgFields::Filename, destFile.asString() );
60  if ( !deltaFile.empty() )
61  m.setValue( ProvideMsgFields::DeltaFile, deltaFile.asString() );
62  if ( fSize )
63  m.setValue( ProvideMsgFields::ExpectedFilesize, fSize );
65 
66  const auto &cHeaders = spec.customHeaders();
67  for ( auto i = cHeaders.beginList (); i != cHeaders.endList(); i++) {
68  for ( const auto &val : i->second )
69  m.addValue( i->first, val );
70  }
71 
72  return expected<ProvideRequestRef>::success( ProvideRequestRef( new ProvideRequest(&owner, urls, std::move(m)) ) );
73  }
74 
75  expected<ProvideRequestRef> ProvideRequest::createDetach( const zypp::Url &url )
76  {
77  auto m = ProvideMessage::createDetach ( ProvideQueue::InvalidId , url );
78  return expected<ProvideRequestRef>::success( ProvideRequestRef( new ProvideRequest( nullptr, { url }, std::move(m) ) ) );
79  }
80 
82 
83  ProvideItem::ProvideItem( ProvidePrivate &parent )
84  : Base( *new ProvideItemPrivate( parent, *this ) )
85  { }
86 
88  { }
89 
91  {
92  return d_func()->_parent;
93  }
94 
95  bool ProvideItem::safeRedirectTo( ProvideRequestRef startedReq, const zypp::Url &url )
96  {
97  if ( !canRedirectTo( startedReq, url ) )
98  return false;
99 
100  redirectTo( startedReq, url );
101  return true;
102  }
103 
104  void ProvideItem::redirectTo( ProvideRequestRef startedReq, const zypp::Url &url )
105  {
106  //@TODO strip irrelevant stuff from URL
107  startedReq->_pastRedirects.push_back ( url );
108  }
109 
110  bool ProvideItem::canRedirectTo( ProvideRequestRef startedReq, const zypp::Url &url )
111  {
112  // make sure there is no redirect loop
113  if ( !startedReq->_pastRedirects.size() )
114  return true;
115 
116  if ( std::find( startedReq->_pastRedirects.begin(), startedReq->_pastRedirects.end(), url ) != startedReq->_pastRedirects.end() )
117  return false;
118 
119  return true;
120  }
121 
122  const std::optional<ProvideItem::ItemStats> &ProvideItem::currentStats() const
123  {
124  return d_func()->_currStats;
125  }
126 
127  const std::optional<ProvideItem::ItemStats> &ProvideItem::previousStats() const
128  {
129  return d_func()->_prevStats;
130  }
131 
132  std::chrono::steady_clock::time_point ProvideItem::startTime() const
133  {
134  return d_func()->_itemStarted;
135  }
136 
137  std::chrono::steady_clock::time_point ProvideItem::finishedTime() const {
138  return d_func()->_itemFinished;
139  }
140 
142  {
143  Z_D();
144  if ( d->_currStats )
145  d->_prevStats = d->_currStats;
146 
147  d->_currStats = makeStats();
148 
149  // once the item is finished the pulse time is always the finish time
150  if ( d->_itemState == Finished )
151  d->_currStats->_pulseTime = d->_itemFinished;
152  }
153 
155  {
156  return 0;
157  }
158 
160  {
161  return ItemStats {
162  ._pulseTime = std::chrono::steady_clock::now(),
163  ._runningRequests = _runningReq ? (uint)1 : (uint)0
164  };
165  }
166 
167  void ProvideItem::informalMessage ( ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg )
168  {
169  if ( req != _runningReq ) {
170  WAR << "Received event for unknown request, ignoring" << std::endl;
171  return;
172  }
173 
174  if ( msg.code() == ProvideMessage::Code::ProvideStarted ) {
175  MIL << "Request: "<< req->url() << " was started" << std::endl;
176  }
177 
178  }
179 
180  void ProvideItem::cacheMiss( ProvideRequestRef req )
181  {
182  if ( req != _runningReq ) {
183  WAR << "Received event for unknown request, ignoring" << std::endl;
184  return;
185  }
186 
187  MIL << "Request: "<< req->url() << " CACHE MISS, request will be restarted by queue." << std::endl;
188  }
189 
190  void ProvideItem::finishReq(ProvideQueue &, ProvideRequestRef finishedReq, const ProvideMessage &msg )
191  {
192  if ( finishedReq != _runningReq ) {
193  WAR << "Received event for unknown request, ignoring" << std::endl;
194  return;
195  }
196 
197  auto log = provider().log();
198 
199  // explicitely handled codes
200  const auto code = msg.code();
201  if ( code == ProvideMessage::Code::Redirect ) {
202 
203  // remove the old request
204  _runningReq.reset();
205 
206  try {
207 
208  MIL << "Request finished with redirect." << std::endl;
209 
211  if ( !safeRedirectTo( finishedReq, newUrl ) ) {
213  return;
214  }
215 
216  MIL << "Request redirected to: " << newUrl << std::endl;
217 
218  if ( log ) log->requestRedirect( *this, msg.requestId(), newUrl );
219 
220  finishedReq->setUrl( newUrl );
221 
222  if ( !enqueueRequest( finishedReq ) ) {
223  cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) );
224  }
225  } catch ( ... ) {
226  cancelWithError( std::current_exception() );
227  return;
228  }
229  return;
230 
231  } else if ( code == ProvideMessage::Code::Metalink ) {
232 
233  // remove the old request
234  _runningReq.reset();
235 
236  MIL << "Request finished with mirrorlist from server." << std::endl;
237 
238  //@TODO do we need to merge this with the mirrorlist we got from the user?
239  // or does a mirrorlist from d.o.o invalidate that?
240 
241  std::vector<zypp::Url> urls;
242  const auto &mirrors = msg.values( MetalinkRedirectMsgFields::NewUrl );
243  for( auto i = mirrors.cbegin(); i != mirrors.cend(); i++ ) {
244  try {
245  zypp::Url newUrl( i->asString() );
246  if ( !canRedirectTo( finishedReq, newUrl ) )
247  continue;
248  urls.push_back ( newUrl );
249  } catch ( ... ) {
250  if ( i->isString() )
251  WAR << "Received invalid URL from worker: " << i->asString() << " ignoring!" << std::endl;
252  else
253  WAR << "Received invalid value for newUrl from worker ignoring!" << std::endl;
254  }
255  }
256 
257  if ( urls.size () == 0 ) {
258  cancelWithError( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No mirrors left to redirect to.")) );
259  return;
260  }
261 
262  MIL << "Found usable nr of mirrors: " << urls.size () << std::endl;
263  finishedReq->setUrls( urls );
264 
265  // disable metalink
266  finishedReq->provideMessage().setValue( ProvideMsgFields::MetalinkEnabled, false );
267 
268  if ( log ) log->requestDone( *this, msg.requestId() );
269 
270  if ( !enqueueRequest( finishedReq ) ) {
271  cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) );
272  }
273 
274  MIL << "End of mirrorlist handling"<< std::endl;
275  return;
276 
277  } else if ( code >= ProvideMessage::Code::FirstClientErrCode && code <= ProvideMessage::Code::LastSrvErrCode ) {
278 
279  // remove the old request
280  _runningReq.reset();
281 
282  std::exception_ptr errPtr;
283  try {
284  const auto reqUrl = finishedReq->activeUrl().value();
285  const auto reason = msg.value( ErrMsgFields::Reason ).asString();
286  switch ( code ) {
287  case ProvideMessage::Code::BadRequest:
288  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException (zypp::str::Str() << "Bad request for URL: " << reqUrl << " " << reason ) );
289  break;
290  case ProvideMessage::Code::PeerCertificateInvalid:
291  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException(zypp::str::Str() << "PeerCertificateInvalid Error for URL: " << reqUrl << " " << reason) );
292  break;
293  case ProvideMessage::Code::ConnectionFailed:
294  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException(zypp::str::Str() << "ConnectionFailed Error for URL: " << reqUrl << " " << reason ) );
295  break;
296  case ProvideMessage::Code::ExpectedSizeExceeded: {
297 
298  std::optional<int64_t> filesize;
299  finishedReq->provideMessage ().forEachVal( [&]( const std::string &key, const auto &val ){
300  if ( key == ProvideMsgFields::ExpectedFilesize && val.valid() )
301  filesize = val.asInt64();
302  return true;
303  });
304 
305  if ( !filesize ) {
306  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "ExceededExpectedSize Error for URL: " << reqUrl << " " << reason ) );
307  } else {
308  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaFileSizeExceededException(reqUrl, *filesize ) );
309  }
310  break;
311  }
312  case ProvideMessage::Code::Cancelled:
313  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Request was cancelled: " << reqUrl << " " << reason ) );
314  break;
315  case ProvideMessage::Code::InvalidChecksum:
316  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "InvalidChecksum Error for URL: " << reqUrl << " " << reason ) );
317  break;
320  break;
321  case ProvideMessage::Code::NotFound:
323  break;
324  case ProvideMessage::Code::Forbidden:
325  case ProvideMessage::Code::Unauthorized: {
326 
327  const auto &hintVal = msg.value( "authHint"sv );
328  std::string hint;
329  if ( hintVal.valid() && hintVal.isString() ) {
330  hint = hintVal.asString();
331  }
332 
333  //@TODO retry here with timestamp from cred store check
334  // we let the request fail after it checked the store
335 
337  reqUrl, reason, "", hint
338  ));
339  break;
340 
341  }
342  case ProvideMessage::Code::MountFailed:
343  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "MountFailed Error for URL: " << reqUrl << " " << reason ) );
344  break;
345  case ProvideMessage::Code::Jammed:
347  break;
348  case ProvideMessage::Code::MediaChangeSkip:
349  errPtr = ZYPP_EXCPT_PTR( zypp::SkipRequestException ( zypp::str::Str() << "User-requested skipping for URL: " << reqUrl << " " << reason ) );
350  break;
351  case ProvideMessage::Code::MediaChangeAbort:
352  errPtr = ZYPP_EXCPT_PTR( zypp::AbortRequestException( zypp::str::Str() <<"Aborting requested by user for URL: " << reqUrl << " " << reason ) );
353  break;
354  case ProvideMessage::Code::InternalError:
355  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "WorkerSpecific Error for URL: " << reqUrl << " " << reason ) );
356  break;
357  case ProvideMessage::Code::NotAFile:
358  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaNotAFileException(reqUrl, "") );
359  break;
360  case ProvideMessage::Code::MediumNotDesired:
362  break;
363  default:
364  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Unknown Error for URL: " << reqUrl << " " << reason ) );
365  break;
366  }
367  } catch (...) {
368  errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Invalid error message received for URL: " << *finishedReq->activeUrl() << " code: " << code ) );
369  }
370 
371  if ( log ) log->requestFailed( *this, msg.requestId(), errPtr );
372  // finish the request
373  cancelWithError( errPtr );
374  return;
375  }
376 
377  // if we reach here we don't know how to handle the message
378  _runningReq.reset();
379  cancelWithError( ZYPP_EXCPT_PTR (zypp::media::MediaException("Unhandled message received for ProvideFileItem")) );
380  }
381 
382  void ProvideItem::finishReq(ProvideQueue *, ProvideRequestRef finishedReq , const std::exception_ptr excpt)
383  {
384  if ( finishedReq != _runningReq ) {
385  WAR << "Received event for unknown request, ignoring" << std::endl;
386  return;
387  }
388 
389  if ( _runningReq ) {
390  auto log = provider().log();
391  if ( log ) log->requestFailed( *this, finishedReq->provideMessage().requestId(), excpt );
392  }
393 
394  _runningReq.reset();
395  cancelWithError(excpt);
396  }
397 
398  expected<zypp::media::AuthData> ProvideItem::authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map<std::string, std::string> &extraFields )
399  {
400 
401  if ( req != _runningReq ) {
402  WAR << "Received authenticationRequired for unknown request, rejecting" << std::endl;
403  return expected<zypp::media::AuthData>::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unknown request in authenticationRequired, this is a bug.") ) );
404  }
405 
406  try {
407  zypp::media::CredentialManager mgr ( provider().credManagerOptions() );
408 
409  MIL << "Looking for existing auth data for " << effectiveUrl << "more recent then " << lastTimestamp << std::endl;
410 
411  auto credPtr = mgr.getCred( effectiveUrl );
412  if ( credPtr && credPtr->lastDatabaseUpdate() > lastTimestamp ) {
413  MIL << "Found existing auth data for " << effectiveUrl << "ts: " << credPtr->lastDatabaseUpdate() << std::endl;
414  return expected<zypp::media::AuthData>::success( *credPtr );
415  }
416 
417  if ( credPtr ) MIL << "Found existing auth data for " << effectiveUrl << "but too old ts: " << credPtr->lastDatabaseUpdate() << std::endl;
418 
419  std::string username;
420  if ( auto i = extraFields.find( std::string(AuthDataRequestMsgFields::LastUser) ); i != extraFields.end() ) {
421  username = i->second;
422  }
423 
424 
425  MIL << "NO Auth data found, asking user. Last tried username was: " << username << std::endl;
426 
427  auto userAuth = provider()._sigAuthRequired.emit( effectiveUrl, username, extraFields );
428  if ( !userAuth || !userAuth->valid() ) {
429  MIL << "User rejected to give auth" << std::endl;
430  return expected<zypp::media::AuthData>::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("No auth given by user." ) ) );
431  }
432 
433  mgr.addCred( *userAuth );
434  mgr.save();
435 
436  // rather ugly, but update the timestamp to the last mtime of the cred database our URL belongs to
437  // otherwise we'd need to reload the cred database
438  userAuth->setLastDatabaseUpdate( mgr.timestampForCredDatabase( effectiveUrl ) );
439 
440  return expected<zypp::media::AuthData>::success(*userAuth);
441  } catch ( const zypp::Exception &e ) {
442  ZYPP_CAUGHT(e);
443  return expected<zypp::media::AuthData>::error( std::current_exception() );
444  }
445  }
446 
447  bool ProvideItem::enqueueRequest( ProvideRequestRef request )
448  {
449  // base item just supports one running request at a time
450  if ( _runningReq )
451  return ( _runningReq == request );
452 
453  _runningReq = request;
454  return d_func()->_parent.queueRequest( request );
455  }
456 
457  void ProvideItem::updateState( const State newState )
458  {
459  Z_D();
460  if ( d->_itemState != newState ) {
461 
462  bool started = ( d->_itemState == Uninitialized && ( newState != Finished ));
463  auto log = provider().log();
464 
465  const auto oldState = d->_itemState;
466  d->_itemState = newState;
467  d->_sigStateChanged( *this, oldState, d->_itemState );
468 
469  if ( started ) {
470  d->_itemStarted = std::chrono::steady_clock::now();
471  pulse();
472  if ( log ) log->itemStart( *this );
473  }
474 
475  if ( newState == Finished ) {
476  d->_itemFinished = std::chrono::steady_clock::now();
477  pulse();
478  if ( log) log->itemDone( *this );
479  d->_parent.dequeueItem(this);
480  }
481  // CAREFUL, 'this' might be invalid from here on
482  }
483  }
484 
486  {
487  if ( state() == Finished || state() == Finalizing )
488  return;
489 
490  MIL << "Item Cleanup due to released Promise in state:" << state() << std::endl;
492  }
493 
495  {
496  return d_func()->_itemState;
497  }
498 
499  void ProvideRequest::setCurrentQueue( ProvideQueueRef ref )
500  {
501  _myQueue = ref;
502  }
503 
505  {
506  return _myQueue.lock();
507  }
508 
509  const std::optional<zypp::Url> ProvideRequest::activeUrl() const
510  {
512  switch ( this->_message.code () ) {
513  case ProvideMessage::Code::Attach:
515  break;
516  case ProvideMessage::Code::Detach:
518  break;
519  case ProvideMessage::Code::Provide:
521  break;
522  default:
523  // should never happen because we guard the constructor
524  throw std::logic_error("Invalid message type in ProvideRequest");
525  }
526  if ( !url.valid() ) {
527  return {};
528  }
529 
530  try {
531  auto u = zypp::Url( url.asString() );
532  return u;
533  } catch ( const zypp::Exception &e ) {
534  ZYPP_CAUGHT(e);
535  }
536 
537  return {};
538  }
539 
540  void ProvideRequest::setActiveUrl(const zypp::Url &urlToUse) {
541 
542  switch ( this->_message.code () ) {
543  case ProvideMessage::Code::Attach:
545  break;
546  case ProvideMessage::Code::Detach:
548  break;
549  case ProvideMessage::Code::Provide:
551  break;
552  default:
553  // should never happen because we guard the constructor
554  throw std::logic_error("Invalid message type in ProvideRequest");
555  }
556  }
557 
558  ProvideFileItem::ProvideFileItem(const std::vector<zypp::Url> &urls, const ProvideFileSpec &request, ProvidePrivate &parent)
559  : ProvideItem( parent )
560  , _mirrorList ( urls )
561  , _initialSpec ( request )
562  { }
563 
564  ProvideFileItemRef ProvideFileItem::create(const std::vector<zypp::Url> &urls, const ProvideFileSpec &request, ProvidePrivate &parent )
565  {
566  return ProvideFileItemRef( new ProvideFileItem( urls, request, parent ) );
567  }
568 
570  {
571  if ( state() != Uninitialized || _runningReq ) {
572  WAR << "Double init of ProvideFileItem!" << std::endl;
573  return;
574  }
575 
576  auto req = ProvideRequest::create( *this, _mirrorList, _initialSpec );
577  if ( !req ){
578  cancelWithError( req.error() );
579  return ;
580  }
581 
582  if ( enqueueRequest( *req ) ) {
584  updateState( Pending );
585  } else {
586  cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) );
587  return ;
588  }
589  }
590 
592  {
593  if ( !_promiseCreated ) {
594  _promiseCreated = true;
595  auto promiseRef = std::make_shared<ProvidePromise<ProvideRes>>( shared_this<ProvideItem>() );
596  _promise = promiseRef;
597  return promiseRef;
598  }
599  return _promise.lock();
600  }
601 
603  {
604  _handleRef = std::move(hdl);
605  }
606 
608  {
609  return _handleRef;
610  }
611 
612  void ProvideFileItem::informalMessage ( ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg )
613  {
614  if ( req != _runningReq ) {
615  WAR << "Received event for unknown request, ignoring" << std::endl;
616  return;
617  }
618 
619  if ( msg.code() == ProvideMessage::Code::ProvideStarted ) {
620  MIL << "Provide File Request: "<< req->url() << " was started" << std::endl;
621  auto log = provider().log();
622 
623  auto locPath = msg.value( ProvideStartedMsgFields::LocalFilename, std::string() ).asString();
624  if ( !locPath.empty() )
625  _targetFile = zypp::Pathname(locPath);
626 
627  locPath = msg.value( ProvideStartedMsgFields::StagingFilename, std::string() ).asString();
628  if ( !locPath.empty() )
629  _stagingFile = zypp::Pathname(locPath);
630 
631  if ( log ) {
632  auto effUrl = req->activeUrl().value_or( zypp::Url() );
633  try {
635  } catch( const zypp::Exception &e ) {
636  ZYPP_CAUGHT(e);
637  }
638 
639  AnyMap m;
640  m["spec"] = _initialSpec;
641  if ( log ) log->requestStart( *this, msg.requestId(), effUrl, m );
643  }
644  }
645  }
646 
647  void zyppng::ProvideFileItem::ProvideFileItem::finishReq( zyppng::ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg )
648  {
649  if ( finishedReq != _runningReq ) {
650  WAR << "Received event for unknown request, ignoring" << std::endl;
651  return;
652  }
653 
654  if ( msg.code () == ProvideMessage::Code::ProvideFinished ) {
655 
656  auto log = provider().log();
657  if ( log ) {
658  AnyMap m;
659  m["spec"] = _initialSpec;
660  if ( log ) log->requestDone( *this, msg.requestId(), m );
661  }
662 
663  MIL << "Request was successfully finished!" << std::endl;
664  // request is def done
665  _runningReq.reset();
666 
667  try {
668 
669  const auto locFilename = msg.value( ProvideFinishedMsgFields::LocalFilename ).asString();
670  const auto cacheHit = msg.value( ProvideFinishedMsgFields::CacheHit ).asBool();
671  const auto &wConf = queue.workerConfig();
672 
673  const bool doesDownload = wConf.worker_type() == ProvideQueue::Config::Downloading;
674  const bool fileNeedsCleanup = doesDownload || ( wConf.worker_type() == ProvideQueue::Config::CPUBound && wConf.cfg_flags() & ProvideQueue::Config::FileArtifacts );
675 
676  std::optional<zypp::ManagedFile> resFile;
677 
678  if ( doesDownload ) {
679 
680  resFile = provider().addToFileCache ( locFilename );
681  if ( !resFile ) {
682  if ( cacheHit ) {
683  MIL << "CACHE MISS, file " << locFilename << " was already removed, queueing again" << std::endl;
684  cacheMiss ( finishedReq );
685  finishedReq->clearForRestart();
686  enqueueRequest( finishedReq );
687  return;
688  } else {
689  // if we reach here it seems that a new file, that was not in cache before, vanished between
690  // providing it and receiving the finished message.
691  // unlikely this can happen but better be safe than sorry
692  cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("File vanished between downloading and adding it to cache.")) );
693  return;
694  }
695  }
696 
697  } else {
698  resFile = zypp::ManagedFile( zypp::filesystem::Pathname(locFilename) );
699  if ( fileNeedsCleanup )
700  resFile->setDispose( zypp::filesystem::unlink );
701  else
702  resFile->resetDispose();
703  }
704 
705  _targetFile = locFilename;
706 
707  // keep the media handle around as long as the file is used by the code
708  auto resObj = std::make_shared<ProvideResourceData>();
709  resObj->_mediaHandle = this->_handleRef;
710  resObj->_myFile = *resFile;
711  resObj->_resourceUrl = *(finishedReq->activeUrl());
712  resObj->_responseHeaders = msg.headers();
713 
714  auto p = promise();
715  if ( p ) {
716  try {
717  p->setReady( expected<ProvideRes>::success( ProvideRes( resObj )) );
718  } catch( const zypp::Exception &e ) {
719  ZYPP_CAUGHT(e);
720  }
721  }
722 
723  updateState( Finished );
724 
725  } catch ( const zypp::Exception &e ) {
726  ZYPP_CAUGHT(e);
727  cancelWithError( std::current_exception() );
728  } catch ( ...) {
729  cancelWithError( std::current_exception() );
730  }
731 
732  } else {
733  ProvideItem::finishReq ( queue, finishedReq, msg );
734  }
735  }
736 
737 
738  void zyppng::ProvideFileItem::cancelWithError( std::exception_ptr error )
739  {
740  if ( _runningReq ) {
741  auto weakThis = weak_from_this ();
742  provider().dequeueRequest ( _runningReq, error );
743  if ( weakThis.expired () )
744  return;
745  }
746 
747  // if we reach this place for some reason finishReq was not called, lets clean up manually
748  _runningReq.reset();
749  auto p = promise();
750  if ( p ) {
751  try {
752  p->setReady( expected<ProvideRes>::error( error ) );
753  } catch( const zypp::Exception &e ) {
754  ZYPP_CAUGHT(e);
755  }
756  }
757  updateState( Finished );
758  }
759 
760  expected<zypp::media::AuthData> ProvideFileItem::authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map<std::string, std::string> &extraFields )
761  {
762  zypp::Url urlToUse = effectiveUrl;
763  if ( _handleRef.isValid() ) {
764  // if we have a attached medium this overrules the URL we are going to ask the user about... this is how the old media backend did handle this
765  // i guess there were never password protected repositories that have different credentials on the redirection targets
766  auto &attachedMedia = provider().attachedMediaInfos();
767  auto i = std::find_if( attachedMedia.begin(), attachedMedia.end(), [&]( const auto &m ) { return m._name == _handleRef.handle(); } );
768  if ( i == attachedMedia.end() )
769  return expected<zypp::media::AuthData>::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("Attachment handle vanished during request.") ) );
770 
771  urlToUse = i->_attachedUrl;
772  }
773  return ProvideItem::authenticationRequired( queue, req, urlToUse, lastTimestamp, extraFields );
774  }
775 
777  {
778  zypp::ByteCount providedByNow;
779 
780  bool checkStaging = false;
781  if ( !_targetFile.empty() ) {
783  if ( inf.isExist() && inf.isFile() )
784  providedByNow = zypp::ByteCount( inf.size() );
785  else
786  checkStaging = true;
787  }
788 
789  if ( checkStaging && !_stagingFile.empty() ) {
791  if ( inf.isExist() && inf.isFile() )
792  providedByNow = zypp::ByteCount( inf.size() );
793  }
794 
795  auto baseStats = ProvideItem::makeStats();
796  baseStats._bytesExpected = bytesExpected();
797  baseStats._bytesProvided = providedByNow;
798  return baseStats;
799  }
800 
802  {
804  }
805 
806  AttachMediaItem::AttachMediaItem( const std::vector<zypp::Url> &urls, const ProvideMediaSpec &request, ProvidePrivate &parent )
807  : ProvideItem ( parent )
808  , _mirrorList ( urls )
809  , _initialSpec ( request )
810  { }
811 
813  {
814  MIL << "Killing the AttachMediaItem" << std::endl;
815  }
816 
818  {
819  if ( !_promiseCreated ) {
820  _promiseCreated = true;
821  auto promiseRef = std::make_shared<ProvidePromise<Provide::MediaHandle>>( shared_this<ProvideItem>() );
822  _promise = promiseRef;
823  return promiseRef;
824  }
825  return _promise.lock();
826  }
827 
829  {
830  if ( state() != Uninitialized ) {
831  WAR << "Double init of AttachMediaItem!" << std::endl;
832  return;
833  }
835 
836  if ( _mirrorList.empty() ) {
837  cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("No usable mirrors in mirrorlist.")) );
838  return;
839  }
840 
841  // shortcut to the provider instance
842  auto &prov= provider();
843 
844  // sanitize the mirrors to contain only URLs that have same worker types
845  std::vector<zypp::Url> usableMirrs;
846  std::optional<ProvideQueue::Config> scheme;
847 
848  for ( auto mirrIt = _mirrorList.begin() ; mirrIt != _mirrorList.end(); mirrIt++ ) {
849  const auto &s = prov.schemeConfig( prov.effectiveScheme( mirrIt->getScheme() ) );
850  if ( !s ) {
851  WAR << "URL: " << *mirrIt << " is not supported, ignoring!" << std::endl;
852  continue;
853  }
854  if ( !scheme ) {
855  scheme = *s;
856  usableMirrs.push_back ( *mirrIt );
857  } else {
858  if ( scheme->worker_type () == s->worker_type () ) {
859  usableMirrs.push_back( *mirrIt );
860  } else {
861  WAR << "URL: " << *mirrIt << " has different worker type than the primary URL: "<< usableMirrs.front() <<", ignoring!" << std::endl;
862  }
863  }
864  }
865 
866  // save the sanitized mirrors
867  _mirrorList = usableMirrs;
868 
869  if ( !scheme || _mirrorList.empty() ) {
870  auto prom = promise();
871  if ( prom ) {
872  try {
873  prom->setReady( expected<Provide::MediaHandle>::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No valid mirrors available") )) );
874  } catch( const zypp::Exception &e ) {
875  ZYPP_CAUGHT(e);
876  }
877  }
879  return;
880  }
881 
882  // first check if there is a already attached medium we can use as well
883  auto &attachedMedia = prov.attachedMediaInfos ();
884 
885  for ( auto &medium : attachedMedia ) {
886  if ( medium.isSameMedium ( _mirrorList, _initialSpec ) ) {
887  finishWithSuccess ( medium );
888  return;
889  }
890  }
891 
892  for ( auto &otherItem : prov.items() ) {
893  auto attachIt = std::dynamic_pointer_cast<AttachMediaItem>(otherItem);
894  if ( !attachIt // not the right type
895  || attachIt.get() == this // do not attach to ourselves
896  || attachIt->state () == Uninitialized // item was not initialized
897  || attachIt->state () == Finalizing // item cleaning up
898  || attachIt->state () == Finished ) // item done
899  continue;
900 
901  // does this Item attach the same medium?
902  const auto sameMedium = attachIt->_initialSpec.isSameMedium( _initialSpec);
903  if ( zypp::indeterminate(sameMedium) ) {
904  // check the primary URLs ( should we do a full list compare? )
905  if ( attachIt->_mirrorList.front() != _mirrorList.front() )
906  continue;
907  }
908  else if ( !(bool)sameMedium )
909  continue;
910 
911  MIL << "Found item providing the same medium, attaching to finished signal and waiting for it to be finished" << std::endl;
912 
913  // it does, connect to its ready signal and just wait
915  return;
916  }
917 
918  _workerType = scheme->worker_type();
919 
920  switch( _workerType ) {
921  case ProvideQueue::Config::Downloading: {
922 
923  // if the media file is empty in the spec we can not do anything
924  // simply pretend attach worked
925  if( _initialSpec.mediaFile().empty() ) {
926  finishWithSuccess( prov.addMedium( _workerType, _mirrorList.front(), _initialSpec ) );
927  return;
928  }
929 
930  // prepare the verifier with the data
931  auto smvDataLocal = MediaDataVerifier::createVerifier("SuseMediaV1");
932  if ( !smvDataLocal ) {
933  cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, no verifier instance was returned.")) );
934  return;
935  }
936 
937  if ( !smvDataLocal->load( _initialSpec.mediaFile() ) ) {
938  cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, unable to load local verify data.")) );
939  return;
940  }
941 
942  _verifier = smvDataLocal;
943 
944  std::vector<zypp::Url> urls;
945  urls.reserve( _mirrorList.size () );
946 
947  for ( zypp::Url url : _mirrorList ) {
948  url.appendPathName ( ( zypp::str::Format("/media.%d/media") % _initialSpec.medianr() ).asString() );
949  urls.push_back(url);
950  }
951 
952  // for downloading schemes we ask for the /media.x/media file and check the data manually
953  ProvideFileSpec spec;
955 
956  // disable metalink
957  spec.customHeaders().set( std::string(NETWORK_METALINK_ENABLED), false );
958 
959  auto req = ProvideRequest::create( *this, urls, spec );
960  if ( !req ) {
961  cancelWithError( req.error() );
962  return;
963  }
964  if ( !enqueueRequest( *req ) ) {
965  cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) );
966  return;
967  }
969  break;
970  }
971  case ProvideQueue::Config::VolatileMount:
972  case ProvideQueue::Config::SimpleMount: {
973 
974  const auto &newId = provider().nextMediaId();
975  auto req = ProvideRequest::create( *this, _mirrorList, newId, _initialSpec );
976  if ( !req ) {
977  cancelWithError( req.error() );
978  return;
979  }
980  if ( !enqueueRequest( *req ) ) {
981  ERR << "Failed to queue request" << std::endl;
982  cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) );
983  return;
984  }
985  break;
986  }
987  default: {
988  auto prom = promise();
989  if ( prom ) {
990  try {
991  prom->setReady( expected<Provide::MediaHandle>::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("URL scheme does not support attaching.") )) );
992  } catch( const zypp::Exception &e ) {
993  ZYPP_CAUGHT(e);
994  }
995  }
997  return;
998  }
999  }
1000  }
1001 
1003  {
1004 
1006 
1007  // aquire a ref to keep the medium around until we notified all dependant attach operations
1008  // currently not really required because only the next schedule run will clean up attached medias
1009  // but in case that ever changes the code is safe already
1010  medium.ref();
1011  zypp::OnScopeExit autoUnref([&]{
1012  medium.unref();
1013  });
1014 
1015  auto prom = promise();
1016  try {
1017  if ( prom ) {
1018  // the ref for the result we are giving out
1019  medium.ref();
1020  try {
1021  prom->setReady( expected<Provide::MediaHandle>::success( Provide::MediaHandle( *static_cast<Provide*>( provider().z_func() ), medium._name) ) );
1022  } catch( const zypp::Exception &e ) {
1023  ZYPP_CAUGHT(e);
1024  }
1025  }
1026  } catch ( const std::exception &e ) {
1027  ERR << "WTF " << e.what () << std::endl;
1028  } catch ( ... ) {
1029  ERR << "WTF " << std::endl;
1030  }
1031 
1032  // tell others as well
1033  _sigReady.emit( zyppng::expected<AttachedMediaInfo *>::success(&medium) );
1034 
1035  prom->isReady ();
1036 
1037  MIL << "Before setFinished" << std::endl;
1038  updateState( Finished );
1039  return;
1040  }
1041 
1042  void AttachMediaItem::cancelWithError( std::exception_ptr error )
1043  {
1044  MIL << "Cancelling Item with error" << std::endl;
1046 
1047  // tell children
1048  _sigReady.emit( expected<AttachedMediaInfo *>::error(error) );
1049 
1050  if ( _runningReq ) {
1051  // we might get deleted when calling dequeueRequest
1052  auto weakThis = weak_from_this ();
1053  provider().dequeueRequest ( _runningReq, error );
1054  if ( weakThis.expired () )
1055  return;
1056  }
1057 
1058  // if we reach this place we had no runningReq, clean up manually
1059  _runningReq.reset();
1060  _masterItemConn.disconnect();
1061 
1062  auto p = promise();
1063  if ( p ) {
1064  try {
1065  p->setReady( expected<zyppng::Provide::MediaHandle>::error( error ) );
1066  } catch( const zypp::Exception &e ) {
1067  ZYPP_CAUGHT(e);
1068  }
1069  }
1070  updateState( Finished );
1071  }
1072 
1073  void AttachMediaItem::onMasterItemReady( const zyppng::expected<AttachedMediaInfo *> &result )
1074  {
1075 
1076  _masterItemConn.disconnect();
1077 
1078  if ( result ) {
1079  AttachedMediaInfo &medium = *result.get();
1080  finishWithSuccess(medium);
1081  } else {
1082  try {
1083  std::rethrow_exception ( result.error() );
1084  } catch ( const zypp::media::MediaRequestCancelledException & e) {
1085  // in case a item was cancelled, we revert to Pending state and trigger the scheduler.
1086  // This will make sure that all our sibilings that also depend on the master
1087  // can revert to pending state and we only get one new master in the next schedule run
1088  MIL_PRV << "Master item was cancelled, reverting to Uninitialized state and waiting for scheduler to run again" << std::endl;
1091 
1092  } catch ( ... ) {
1093  cancelWithError( std::current_exception() );
1094  }
1095  }
1096  }
1097 
1098  AttachMediaItemRef AttachMediaItem::create( const std::vector<zypp::Url> &urls, const ProvideMediaSpec &request, ProvidePrivate &parent )
1099  {
1100  return AttachMediaItemRef( new AttachMediaItem(urls, request, parent) );
1101  }
1102 
1103  SignalProxy<void (const zyppng::expected<AttachedMediaInfo *> &)> AttachMediaItem::sigReady()
1104  {
1105  return _sigReady;
1106  }
1107 
1108  void AttachMediaItem::finishReq ( ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg )
1109  {
1110  if ( finishedReq != _runningReq ) {
1111  WAR << "Received event for unknown request, ignoring" << std::endl;
1112  return;
1113  }
1114 
1115  if( _workerType == ProvideQueue::Config::Downloading ) {
1116  // success
1117  if ( msg.code() == ProvideMessage::Code::ProvideFinished ) {
1118 
1120 
1121  zypp::Url baseUrl = *finishedReq->activeUrl();
1122  // remove /media.n/media
1123  baseUrl.setPathName( zypp::Pathname(baseUrl.getPathName()).dirname().dirname() );
1124 
1125  // we got the file, lets parse it
1126  auto smvDataRemote = MediaDataVerifier::createVerifier("SuseMediaV1");
1127  if ( !smvDataRemote ) {
1128  return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, no verifier instance was returned.")) );
1129  }
1130 
1131  if ( !smvDataRemote->load( msg.value( ProvideFinishedMsgFields::LocalFilename ).asString() ) ) {
1132  return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, unable to load remote verify data.")) );
1133  }
1134 
1135  // check if we got a valid media file
1136  if ( !smvDataRemote->valid () ) {
1137  return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, unable to load local verify data.")) );
1138  }
1139 
1140  // check if the received file matches with the one we have in the spec
1141  if (! _verifier->matches( smvDataRemote ) ) {
1142  DBG << "expect: " << _verifier << " medium " << _initialSpec.medianr() << std::endl;
1143  DBG << "remote: " << smvDataRemote << std::endl;
1144  return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaNotDesiredException( *finishedReq->activeUrl() ) ) );
1145  }
1146 
1147  // all good, register the medium and tell all child items
1148  _runningReq.reset();
1149  return finishWithSuccess( provider().addMedium( _workerType, baseUrl, _initialSpec ) );
1150 
1151  } else if ( msg.code() == ProvideMessage::Code::NotFound ) {
1152 
1153  // simple downloading attachment we need to check the media file contents
1154  // in case of a error we might tolerate a file not found error in certain situations
1155  if ( _verifier->totalMedia () == 1 ) {
1156  // relaxed , tolerate a vanished media file
1157  _runningReq.reset();
1158  return finishWithSuccess( provider().addMedium( _workerType, _mirrorList.front(), _initialSpec) );
1159  } else {
1160  return ProvideItem::finishReq ( queue, finishedReq, msg );
1161  }
1162  } else {
1163  return ProvideItem::finishReq ( queue, finishedReq, msg );
1164  }
1165  } else {
1166  // real device attach
1167  if ( msg.code() == ProvideMessage::Code::AttachFinished ) {
1168  _runningReq.reset();
1169  return finishWithSuccess( provider().addMedium( _workerType
1170  , queue.weak_this<ProvideQueue>()
1171  , finishedReq->provideMessage().value( AttachMsgFields::AttachId ).asString()
1172  , *finishedReq->activeUrl()
1173  , _initialSpec ) );
1174  }
1175  }
1176 
1177  // unhandled message , let the base impl do it
1178  return ProvideItem::finishReq ( queue, finishedReq, msg );
1179  }
1180 
1181  expected<zypp::media::AuthData> AttachMediaItem::authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map<std::string, std::string> &extraFields )
1182  {
1183  zypp::Url baseUrl = effectiveUrl;
1184  if( _workerType == ProvideQueue::Config::Downloading ) {
1185  // remove /media.n/media
1186  baseUrl.setPathName( zypp::Pathname(baseUrl.getPathName()).dirname().dirname() );
1187  }
1188  return ProvideItem::authenticationRequired( queue, req, baseUrl, lastTimestamp, extraFields );
1189  }
1190 
1191 }
std::vector< zypp::Url > _mirrorList
bool safeRedirectTo(ProvideRequestRef startedReq, const zypp::Url &url)
Definition: provideitem.cc:95
expected< zypp::media::AuthData > authenticationRequired(ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map< std::string, std::string > &extraFields) override
#define MIL
Definition: Logger.h:96
virtual bool enqueueRequest(ProvideRequestRef request)
Definition: provideitem.cc:447
constexpr std::string_view Url("url")
constexpr std::string_view LocalFilename("local_filename")
const std::string & asString() const
static ProvideFileItemRef create(const std::vector< zypp::Url > &urls, const ProvideFileSpec &request, ProvidePrivate &parent)
Definition: provideitem.cc:564
constexpr std::string_view AttachId("attach_id")
ProvideQueue::Config::WorkerType _workerType
ProvidePromiseWeakRef< Provide::MediaHandle > _promise
static constexpr std::string_view DEFAULT_MEDIA_VERIFIER("SuseMediaV1")
AttachMediaItem(const std::vector< zypp::Url > &urls, const ProvideMediaSpec &request, ProvidePrivate &parent)
Definition: provideitem.cc:806
constexpr std::string_view NETWORK_METALINK_ENABLED("zypp-nw-metalink-enabled")
constexpr std::string_view VerifyData("verify_data")
expected< zypp::media::AuthData > authenticationRequired(ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map< std::string, std::string > &extraFields) override
Definition: provideitem.cc:760
ProvideQueueWeakRef _myQueue
Definition: provideitem_p.h:87
constexpr std::string_view Filename("filename")
Signal< std::optional< zypp::media::AuthData > const zypp::Url &reqUrl, const std::string &triedUsername, const std::map< std::string, std::string > &extraValues) > _sigAuthRequired
Definition: provide_p.h:105
Store and operate with byte count.
Definition: ByteCount.h:30
HeaderValueMap headers() const
virtual void cacheMiss(ProvideRequestRef req)
Definition: provideitem.cc:180
ProvidePromiseRef< ProvideRes > promise()
Definition: provideitem.cc:591
void initialize() override
Definition: provideitem.cc:828
void save()
Saves any unsaved credentials added via addUserCred() or addGlobalCred() methods. ...
std::string nextMediaId() const
Definition: provide.cc:771
MediaDataVerifierRef _verifier
virtual void finishReq(ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg)
Definition: provideitem.cc:190
std::shared_ptr< ProvidePromise< T > > ProvidePromiseRef
Definition: providefwd_p.h:31
const zypp::Pathname & deltafile() const
The existing deltafile that can be used to reduce download size ( zchunk or metalink ) ...
Definition: providespec.cc:240
Signal< void(const zyppng::expected< AttachedMediaInfo * > &)> _sigReady
virtual ItemStats makeStats()
Definition: provideitem.cc:159
void onMasterItemReady(const zyppng::expected< AttachedMediaInfo *> &result)
AuthData_Ptr getCred(const Url &url)
Get credentials for the specified url.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
void set(const std::string &key, const Value &val)
const std::string & label() const
Definition: providespec.cc:95
std::chrono::steady_clock::time_point _pulseTime
Definition: provideitem.h:46
Convenient building of std::string with boost::format.
Definition: String.h:252
constexpr std::string_view VerifyType("verify_type")
void initialize() override
Definition: provideitem.cc:569
#define ZYPP_EXCPT_PTR(EXCPT)
Drops a logline and returns Exception as a std::exception_ptr.
Definition: Exception.h:432
State state() const
Definition: provideitem.cc:494
ProvideMessage _message
Definition: provideitem_p.h:83
time_t timestampForCredDatabase(const zypp::Url &url)
#define ERR
Definition: Logger.h:98
void finishWithSuccess(AttachedMediaInfo &medium)
const std::optional< zypp::Url > activeUrl() const
Definition: provideitem.cc:509
void updateState(const State newState)
Definition: provideitem.cc:457
constexpr std::string_view CheckExistOnly("check_existance_only")
std::string asString(TInt val, char zero='0', char one='1')
For printing bits.
Definition: Bit.h:57
constexpr std::string_view NewUrl("new_url")
bool empty() const
Test for an empty path.
Definition: Pathname.h:114
ProvideFileSpec _initialSpec
void setPathName(const std::string &path, EEncoding eflag=zypp::url::E_DECODED)
Set the path name.
Definition: Url.cc:764
std::vector< AttachedMediaInfo > & attachedMediaInfos()
Definition: provide.cc:707
std::string asString() const
Returns a default string representation of the Url object.
Definition: Url.cc:497
constexpr std::string_view LocalFilename("local_filename")
FieldVal value(const std::string_view &str, const FieldVal &defaultVal=FieldVal()) const
void redirectTo(ProvideRequestRef startedReq, const zypp::Url &url)
Definition: provideitem.cc:104
Convenient building of std::string via std::ostringstream Basically a std::ostringstream autoconverti...
Definition: String.h:211
unsigned medianr() const
Definition: providespec.cc:104
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:700
std::vector< FieldVal > values(const std::string_view &str) const
zypp::Pathname mediaFile() const
Definition: providespec.cc:113
const std::string & asString() const
String representation.
Definition: Pathname.h:91
const Config & workerConfig() const
bool isExist() const
Return whether valid stat info exists.
Definition: PathInfo.h:281
Just inherits Exception to separate media exceptions.
virtual void informalMessage(ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg)
Definition: provideitem.cc:167
Pathname dirname() const
Return all but the last component od this path.
Definition: Pathname.h:124
zypp::Url url() const
Definition: provideitem_p.h:66
#define WAR
Definition: Logger.h:97
std::string asCompleteString() const
Returns a complete string representation of the Url object.
Definition: Url.cc:505
void informalMessage(ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg) override
Definition: provideitem.cc:612
const std::optional< ItemStats > & currentStats() const
Definition: provideitem.cc:122
zypp::TriBool isSameMedium(const ProvideMediaSpec &other)
Definition: providespec.cc:140
ProvideStatusRef log()
Definition: provide_p.h:98
void cancelWithError(std::exception_ptr error) override
Definition: provideitem.cc:738
ItemStats makeStats() override
Definition: provideitem.cc:776
void schedule(ScheduleReason reason)
Definition: provide.cc:38
ProvideFileItem(const std::vector< zypp::Url > &urls, const ProvideFileSpec &request, ProvidePrivate &parent)
Definition: provideitem.cc:558
static expected< ProvideRequestRef > create(ProvideItem &owner, const std::vector< zypp::Url > &urls, const std::string &id, ProvideMediaSpec &spec)
Definition: provideitem.cc:27
zypp::ByteCount bytesExpected() const override
Definition: provideitem.cc:801
const zypp::ByteCount & downloadSize() const
The size of the resource on the server.
Definition: providespec.cc:204
constexpr std::string_view Reason("reason")
void cancelWithError(std::exception_ptr error) override
SignalProxy< void(const zyppng::expected< AttachedMediaInfo * > &) > sigReady()
const zypp::Pathname & destFilenameHint() const
Definition: providespec.cc:186
ProvidePrivate & provider()
Definition: provideitem.cc:90
constexpr std::string_view NewUrl("new_url")
void setCurrentQueue(ProvideQueueRef ref)
Definition: provideitem.cc:499
void setValue(const std::string &name, const FieldVal &value)
constexpr std::string_view DeltaFile("delta_file")
#define MIL_PRV
Definition: providedbg_p.h:35
static MediaDataVerifierRef createVerifier(const std::string &verifierType)
virtual bool canRedirectTo(ProvideRequestRef startedReq, const zypp::Url &url)
Definition: provideitem.cc:110
zypp::Pathname _targetFile
#define ZYPP_CAUGHT(EXCPT)
Drops a logline telling the Exception was caught (in order to handle it).
Definition: Exception.h:436
ZYPP_IMPL_PRIVATE(ProvideItem)
bool dequeueRequest(ProvideRequestRef req, std::exception_ptr error)
Definition: provide.cc:808
void finishReq(ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg) override
Base class for Exception.
Definition: Exception.h:145
HeaderValueMap & customHeaders()
Definition: providespec.cc:122
static AttachMediaItemRef create(const std::vector< zypp::Url > &urls, const ProvideMediaSpec &request, ProvidePrivate &parent)
void setActiveUrl(const zypp::Url &urlToUse)
Definition: provideitem.cc:540
constexpr std::string_view Url("url")
virtual expected< zypp::media::AuthData > authenticationRequired(ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map< std::string, std::string > &extraFields)
Definition: provideitem.cc:398
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:604
constexpr std::string_view Url("url")
ProvidePromiseRef< Provide::MediaHandle > promise()
Definition: provideitem.cc:817
zypp::ByteCount _expectedBytes
virtual void released()
Definition: provideitem.cc:485
ProvideQueueRef currentQueue()
Definition: provideitem.cc:504
constexpr std::string_view MetalinkEnabled("metalink_enabled")
Wrapper class for ::stat/::lstat.
Definition: PathInfo.h:220
Provide::MediaHandle _handleRef
virtual void cancelWithError(std::exception_ptr error)=0
constexpr std::string_view StagingFilename("staging_filename")
Provide::MediaHandle & mediaRef()
Definition: provideitem.cc:607
std::vector< zypp::Url > _mirrorList
constexpr std::string_view Url("url")
std::string handle() const
Definition: provide.cc:951
std::unordered_map< std::string, boost::any > AnyMap
Definition: provide.h:41
virtual zypp::ByteCount bytesExpected() const
Definition: provideitem.cc:154
void addCred(const AuthData &cred)
Add new credentials with user callbacks.
ProvideMediaSpec _initialSpec
void setMediaRef(Provide::MediaHandle &&hdl)
Definition: provideitem.cc:602
const std::optional< ItemStats > & previousStats() const
Definition: provideitem.cc:127
ProvidePromiseWeakRef< ProvideRes > _promise
HeaderValueMap & customHeaders()
Definition: providespec.cc:246
constexpr std::string_view CacheHit("cacheHit")
virtual std::chrono::steady_clock::time_point startTime() const
Definition: provideitem.cc:132
constexpr std::string_view LastUser("username")
zypp::Pathname _stagingFile
Url manipulation class.
Definition: Url.h:91
virtual std::chrono::steady_clock::time_point finishedTime() const
Definition: provideitem.cc:137
bool checkExistsOnly() const
Definition: providespec.cc:192
unsigned int MediaNr
Definition: MediaManager.h:30
#define DBG
Definition: Logger.h:95
ProvideRequestRef _runningReq
Definition: provideitem.h:189
constexpr std::string_view ExpectedFilesize("expected_filesize")