libzypp  17.31.31
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 "basicdownloader_p.h"
17 
18 namespace zyppng {
19 
21  : MirrorHandlingStateBase( parent )
22  , _request( std::move(req) )
23  { }
24 
26  {
27  if ( _request ) {
28  const auto &spec = stateMachine()._spec;
29  MIL_MEDIA << "Reusing request from previous state" << std::endl;
30  _request->setOptions( Request::Default );
31  _request->setPriority( Request::Normal );
32  _request->resetRequestRanges();
33  _request->setTargetFilePath( spec.targetPath() );
34  _request->setFileOpenMode( Request::WriteExclusive );
35  _request->transferSettings() = spec.settings();
36  startRequest();
37  return;
38  }
39 
40  if ( _fileMirrors.size() ) {
41  const auto res = prepareNextMirror();
42  // for Delayed or OK we can just continue here
44  return;
45  }
47  }
48 
50  {
51  if ( _request ) {
52  _request->disconnectSignals();
53  _request.reset();
54  }
55  }
56 
58  {
59  auto &sm = stateMachine();
60  auto url = sm._spec.url();
61  auto set = sm._spec.settings();
62 
63  auto err = setupMirror( mirror, url, set );
64  if ( err.isError() ) {
65  WAR << "Setting up mirror " << mirror.second->mirrorUrl << " failed with error: " << err.toString() << "(" << err.nativeErrorString() << "), falling back to original URL." << std::endl;
67  }
68  startWithMirror( mirror.second, url, set );
69  }
70 
72  {
74  }
75 
77  {
78  auto &sm = stateMachine();
79  const auto &spec = sm._spec;
80 
81  _request = std::make_shared<Request>( ::internal::clearQueryString(url), spec.targetPath() ) ;
82  _request->_myMirror = mirror;
83  _request->_originalUrl = url;
84  _request->transferSettings() = set;
85 
86  startRequest();
87  }
88 
90  {
91  auto &sm = stateMachine();
92  const auto &spec = sm._spec;
93 
94  auto url = spec.url();
95  auto set = spec.settings();
96  auto err = sm.safeFillSettingsFromURL( url, set );
97  if ( err.isError() )
98  return failed( std::move(err) );
99  startWithMirror( nullptr, url, set );
100  }
101 
103  {
104  auto &sm = stateMachine();
105 
106  if ( !_request )
107  return failed("Request was not intialized before starting it.");
108 
109  if ( _chksumtype && _chksumVec ) {
110  std::optional<zypp::Digest> fileDigest = zypp::Digest();
111  if ( fileDigest->create( *_chksumtype ) )
112  // to run the checksum for the full file we need to request one big range with open end
113  _request->addRequestRange( 0, 0, std::move(fileDigest), *_chksumVec );
114  }
115 
116  if ( sm._spec.checkExistsOnly() )
117  _request->setOptions( _request->options() | Request::HeadRequest );
118 
119  if ( !initializeRequest( _request ) ) {
120  return failed( "Failed to initialize request" );
121  }
122 
123  if ( stateMachine().previousState() && *stateMachine().previousState() != Download::InitialState ) {
124  //make sure this request will run asap
125  _request->setPriority( sm._defaultSubRequestPriority );
126  }
127 
128  _request->connectSignals( *this );
129  sm._requestDispatcher->enqueue( _request );
130  }
131 
132  bool BasicDownloaderStateBase::initializeRequest( std::shared_ptr<Request> & )
133  {
134  return true;
135  }
136 
138  {
139  _sigFinished.emit();
140  }
141 
142  void BasicDownloaderStateBase::failed( std::string &&str )
143  {
145  }
146 
148  {
149  _error = std::move( err );
150  zypp::filesystem::unlink( stateMachine()._spec.targetPath() );
151 
152  _sigFailed.emit();
153  }
154 
156  {
157  auto &sm = stateMachine();
158  if ( !sm._emittedSigStart ) {
159  sm._emittedSigStart = true;
160  stateMachine()._sigStarted.emit( *stateMachine().z_func() );
161  }
162  if ( _request->_myMirror )
163  _request->_myMirror->startTransfer();
164  }
165 
166  void BasicDownloaderStateBase::handleRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow )
167  {
168  auto &sm = stateMachine();
169  const off_t expFSize = sm._spec.expectedFileSize();
170  if ( expFSize > 0 && expFSize < req.downloadedByteCount() ) {
171  sm._requestDispatcher->cancel( req, NetworkRequestErrorPrivate::customError( NetworkRequestError::ExceededMaxLen ) );
172  return;
173  }
174  return sm._sigProgress.emit( *sm.z_func(), (expFSize > 0 ? expFSize : dltotal), dlnow );
175  }
176 
177  void BasicDownloaderStateBase::onRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow, off_t, off_t )
178  {
179  handleRequestProgress( req, dltotal, dlnow );
180  }
181 
183  {
184  auto lck = stateMachine().z_func()->shared_from_this();
185  auto &sm = stateMachine();
186 
187  if ( _request->_myMirror )
188  _request->_myMirror->finishTransfer( !err.isError() );
189 
190  if ( req.hasError() ) {
191  // if we get authentication failure we try to recover
192  if ( sm.handleRequestAuthError( _request, err ) ) {
193  //make sure this request will run asap
194  _request->setPriority( sm._defaultSubRequestPriority );
195  sm._requestDispatcher->enqueue( _request );
196  return;
197  }
198 
199  MIL << req.nativeHandle() << " " << "Downloading on " << stateMachine()._spec.url() << " failed with error "<< err.toString() << " " << err.nativeErrorString() << std::endl;
200  if ( req.lastRedirectInfo ().size () )
201  MIL << req.nativeHandle() << " Last redirection target was: " << req.lastRedirectInfo () << std::endl;
202 
203  return failed( NetworkRequestError(err) );
204  }
205 
206  gotFinished();
207  }
208 
209 }
BasicDownloaderStateBase(DownloadPrivate &parent)
bool isError() const
isError Will return true if this is a actual error
#define MIL
Definition: Logger.h:96
void * nativeHandle() const
Definition: request.cc:840
void onRequestFinished(NetworkRequest &req, const NetworkRequestError &err)
Compute Message Digests (MD5, SHA1 etc)
Definition: Digest.h:37
const std::string & lastRedirectInfo() const
Definition: request.cc:835
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:946
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:1001
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:700
#define WAR
Definition: Logger.h:97
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
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={})
Url manipulation class.
Definition: Url.h:91