libzypp  17.34.1
basicdownloader_p.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 ----------------------------------------------------------------------*/
9 
14 #include <zypp-core/fs/PathInfo.h>
15 
16 #include <utility>
17 
18 #include "basicdownloader_p.h"
19 
20 namespace zyppng {
21 
23  : MirrorHandlingStateBase( parent )
24  , _request( std::move(req) )
25  { }
26 
28  {
29  if ( _request ) {
30  const auto &spec = stateMachine()._spec;
31  MIL_MEDIA << "Reusing request from previous state" << std::endl;
32  _request->setOptions( Request::Default );
33  _request->setPriority( Request::Normal );
34  _request->resetRequestRanges();
35  _request->setTargetFilePath( spec.targetPath() );
36  _request->setFileOpenMode( Request::WriteExclusive );
37  _request->transferSettings() = spec.settings();
38  startRequest();
39  return;
40  }
41 
42  if ( _fileMirrors.size() ) {
43  const auto res = prepareNextMirror();
44  // for Delayed or OK we can just continue here
46  return;
47  }
49  }
50 
52  {
53  if ( _request ) {
54  _request->disconnectSignals();
55  _request.reset();
56  }
57  }
58 
60  {
61  auto &sm = stateMachine();
62  auto url = sm._spec.url();
63  auto set = sm._spec.settings();
64 
65  auto err = setupMirror( mirror, url, set );
66  if ( err.isError() ) {
67  WAR << "Setting up mirror " << mirror.second->mirrorUrl << " failed with error: " << err.toString() << "(" << err.nativeErrorString() << "), falling back to original URL." << std::endl;
69  }
70  startWithMirror( mirror.second, url, set );
71  }
72 
74  {
76  }
77 
79  {
80  auto &sm = stateMachine();
81  const auto &spec = sm._spec;
82 
83  _request = std::make_shared<Request>( ::internal::clearQueryString(url), spec.targetPath() ) ;
84  _request->_myMirror = std::move(mirror);
85  _request->_originalUrl = url;
86  _request->transferSettings() = set;
87 
88  startRequest();
89  }
90 
92  {
93  auto &sm = stateMachine();
94  const auto &spec = sm._spec;
95 
96  auto url = spec.url();
97  auto set = spec.settings();
98  auto err = sm.safeFillSettingsFromURL( url, set );
99  if ( err.isError() )
100  return failed( std::move(err) );
101  startWithMirror( nullptr, url, set );
102  }
103 
105  {
106  auto &sm = stateMachine();
107 
108  if ( !_request )
109  return failed("Request was not intialized before starting it.");
110 
111  if ( _chksumtype && _chksumVec ) {
112  std::optional<zypp::Digest> fileDigest = zypp::Digest();
113  if ( fileDigest->create( *_chksumtype ) )
114  // to run the checksum for the full file we need to request one big range with open end
115  _request->addRequestRange( 0, 0, std::move(fileDigest), *_chksumVec );
116  }
117 
118  if ( sm._spec.checkExistsOnly() )
119  _request->setOptions( _request->options() | Request::HeadRequest );
120 
121  if ( !initializeRequest( _request ) ) {
122  return failed( "Failed to initialize request" );
123  }
124 
125  if ( stateMachine().previousState() && *stateMachine().previousState() != Download::InitialState ) {
126  //make sure this request will run asap
127  _request->setPriority( sm._defaultSubRequestPriority );
128  }
129 
130  _request->connectSignals( *this );
131  sm._requestDispatcher->enqueue( _request );
132  }
133 
134  bool BasicDownloaderStateBase::initializeRequest( std::shared_ptr<Request> & )
135  {
136  return true;
137  }
138 
140  {
141  _sigFinished.emit();
142  }
143 
144  void BasicDownloaderStateBase::failed( std::string &&str )
145  {
147  }
148 
150  {
151  _error = std::move( err );
152  zypp::filesystem::unlink( stateMachine()._spec.targetPath() );
153 
154  _sigFailed.emit();
155  }
156 
158  {
159  auto &sm = stateMachine();
160  if ( !sm._emittedSigStart ) {
161  sm._emittedSigStart = true;
162  stateMachine()._sigStarted.emit( *stateMachine().z_func() );
163  }
164  if ( _request->_myMirror )
165  _request->_myMirror->startTransfer();
166  }
167 
168  void BasicDownloaderStateBase::handleRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow )
169  {
170  auto &sm = stateMachine();
171  const off_t expFSize = sm._spec.expectedFileSize();
172  if ( expFSize > 0 && expFSize < req.downloadedByteCount() ) {
173  sm._requestDispatcher->cancel( req, NetworkRequestErrorPrivate::customError( NetworkRequestError::ExceededMaxLen ) );
174  return;
175  }
176  return sm._sigProgress.emit( *sm.z_func(), (expFSize > 0 ? expFSize : dltotal), dlnow );
177  }
178 
179  void BasicDownloaderStateBase::onRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow, off_t, off_t )
180  {
181  handleRequestProgress( req, dltotal, dlnow );
182  }
183 
185  {
186  auto lck = stateMachine().z_func()->shared_from_this();
187  auto &sm = stateMachine();
188 
189  if ( _request->_myMirror )
190  _request->_myMirror->finishTransfer( !err.isError() );
191 
192  if ( req.hasError() ) {
193  // if we get authentication failure we try to recover
194  if ( sm.handleRequestAuthError( _request, err ) ) {
195  //make sure this request will run asap
196  _request->setPriority( sm._defaultSubRequestPriority );
197  sm._requestDispatcher->enqueue( _request );
198  return;
199  }
200 
201  MIL << req.nativeHandle() << " " << "Downloading on " << stateMachine()._spec.url() << " failed with error "<< err.toString() << " " << err.nativeErrorString() << std::endl;
202  if ( req.lastRedirectInfo ().size () )
203  MIL << req.nativeHandle() << " Last redirection target was: " << req.lastRedirectInfo () << std::endl;
204 
205  return failed( NetworkRequestError(err) );
206  }
207 
208  gotFinished();
209  }
210 
211 }
BasicDownloaderStateBase(DownloadPrivate &parent)
bool isError() const
isError Will return true if this is a actual error
#define MIL
Definition: Logger.h:98
void * nativeHandle() const
Definition: request.cc:856
void onRequestFinished(NetworkRequest &req, const NetworkRequestError &err)
Compute Message Digests (MD5, SHA1 etc)
Definition: Digest.h:37
DownloadSpec _spec
Definition: base_p.h:98
const std::string & lastRedirectInfo() const
Definition: request.cc:851
virtual void failed(NetworkRequestError &&err)
Holds transfer setting.
void onRequestProgress(NetworkRequest &, off_t dltotal, off_t dlnow, off_t, off_t)
zypp::ByteCount downloadedByteCount() const
Returns the number of already downloaded bytes as reported by the backend.
Definition: request.cc:962
void onRequestStarted(NetworkRequest &)
Url clearQueryString(const Url &url)
Definition: curlhelper.cc:373
std::optional< UByteArray > _chksumVec
std::string toString() const
toString Returns a string representation of the error
String related utilities and Regular expression matching.
Definition: Arch.h:363
std::string nativeErrorString() const
bool hasError() const
Checks if there was a error with the request.
Definition: request.cc:1017
Signal< void(Download &req)> _sigStarted
Definition: base_p.h:108
#define WAR
Definition: Logger.h:99
The NetworkRequestError class Represents a error that occured in.
std::shared_ptr< Request > _request
void mirrorReceived(MirrorControl::MirrorPick mirror) override
virtual void handleRequestProgress(NetworkRequest &req, off_t dltotal, off_t dlnow)
std::pair< std::vector< Url >::const_iterator, MirrorHandle > MirrorPick
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:705
std::optional< std::string > _chksumtype
virtual bool initializeRequest(std::shared_ptr< Request > &r)
NetworkRequestError setupMirror(const MirrorControl::MirrorPick &pick, Url &url, TransferSettings &set)
#define MIL_MEDIA
Definition: mediadebug_p.h:29
std::shared_ptr< Mirror > MirrorHandle
void startWithMirror(MirrorControl::MirrorHandle mirror, const zypp::Url &url, const TransferSettings &set)
static zyppng::NetworkRequestError customError(NetworkRequestError::Type t, std::string &&errorMsg="", std::map< std::string, boost::any > &&extraInfo={})
const Url & url() const
Definition: downloadspec.cc:48
Url manipulation class.
Definition: Url.h:91