libzypp  13.10.6
PackageProvider.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <sstream>
14 #include "zypp/repo/PackageDelta.h"
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/Gettext.h"
18 #include "zypp/base/NonCopyable.h"
21 #include "zypp/repo/PackageDelta.h"
22 
23 #include "zypp/TmpPath.h"
24 #include "zypp/ZConfig.h"
25 #include "zypp/RepoInfo.h"
26 
27 using std::endl;
28 
30 namespace zypp
31 {
33  namespace repo
34  {
36  // class PackageProviderPolicy
38 
39  bool PackageProviderPolicy::queryInstalled( const std::string & name_r,
40  const Edition & ed_r,
41  const Arch & arch_r ) const
42  {
43  if ( _queryInstalledCB )
44  return _queryInstalledCB( name_r, ed_r, arch_r );
45  return false;
46  }
47 
48 
54  {
55  public:
57  Impl( RepoMediaAccess & access_r,
58  const Package::constPtr & package_r,
59  const DeltaCandidates & deltas_r,
60  const PackageProviderPolicy & policy_r )
61  : _policy( policy_r )
62  , _package( package_r )
63  , _deltas( deltas_r )
64  , _access( access_r )
65  , _retry(false)
66  {}
67 
68  virtual ~Impl() {}
69 
74  static Impl * factoryMake( RepoMediaAccess & access_r,
75  const Package::constPtr & package_r,
76  const DeltaCandidates & deltas_r,
77  const PackageProviderPolicy & policy_r );
78 
79  public:
85 
88  {
90  if ( ! ( ret->empty() || _package->repoInfo().keepPackages() ) )
92  return ret;
93  }
94 
96  bool isCached() const
97  { return ! doProvidePackageFromCache()->empty(); }
98 
99  protected:
102 
113  virtual ManagedFile doProvidePackageFromCache() const = 0;
114 
132  virtual ManagedFile doProvidePackage() const = 0;
133 
134  protected:
136  Report & report() const
137  { return *_report; }
138 
140  bool progressPackageDownload( int value ) const
141  { return report()->progress( value, _package ); }
142 
144  bool failOnChecksumError() const
145  {
146  std::string package_str = _package->name() + "-" + _package->edition().asString();
147 
148  // TranslatorExplanation %s = package being checked for integrity
149  switch ( report()->problem( _package, repo::DownloadResolvableReport::INVALID, str::form(_("Package %s seems to be corrupted during transfer. Do you want to retry retrieval?"), package_str.c_str() ) ) )
150  {
152  _retry = true;
153  break;
155  ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
156  break;
158  ZYPP_THROW(AbortRequestException("User requested to abort"));
159  break;
160  default:
161  break;
162  }
163  return true; // anyway a failure
164  }
165 
166  protected:
171 
172  private:
173  typedef shared_ptr<void> ScopedGuard;
174 
176  {
177  _report.reset( new Report );
178  // Use a custom deleter calling _report.reset() when guard goes out of
179  // scope (cast required as reset is overloaded). We want report to end
180  // when leaving providePackage and not wait for *this going out of scope.
181  return shared_ptr<void>( static_cast<void*>(0),
182  bind( mem_fun_ref( static_cast<void (shared_ptr<Report>::*)()>(&shared_ptr<Report>::reset) ),
183  ref(_report) ) );
184  }
185 
186  mutable bool _retry;
187  mutable shared_ptr<Report> _report;
188  };
190 
193  { return ManagedFile(); }
194 
197  {
198  ManagedFile ret;
199  OnMediaLocation loc = _package->location();
200 
201  ProvideFilePolicy policy;
202  policy.progressCB( bind( &Base::progressPackageDownload, this, _1 ) );
203  policy.failOnChecksumErrorCB( bind( &Base::failOnChecksumError, this ) );
204  return _access.provideFile( _package->repoInfo(), loc, policy );
205  }
206 
208 
210  {
211  // check for cache hit:
213  if ( ! ret->empty() )
214  {
215  MIL << "provided Package from cache " << _package << " at " << ret << endl;
216  return ret; // <-- cache hit
217  }
218 
219  // HERE: cache misss, do download:
220  Url url;
221  RepoInfo info = _package->repoInfo();
222  // FIXME we only support the first url for now.
223  if ( info.baseUrlsEmpty() )
224  ZYPP_THROW(Exception("No url in repository."));
225  else
226  url = * info.baseUrlsBegin();
227 
228  MIL << "provide Package " << _package << endl;
229  ScopedGuard guardReport( newReport() );
230  do {
231  _retry = false;
232  report()->start( _package, url );
233  try // ELIMINATE try/catch by providing a log-guard
234  {
235  ret = doProvidePackage();
236  }
237  catch ( const UserRequestException & excpt )
238  {
239  // UserRequestException e.g. from failOnChecksumError was already reported.
240  ERR << "Failed to provide Package " << _package << endl;
241  if ( ! _retry )
242  {
243  ZYPP_RETHROW( excpt );
244  }
245  }
246  catch ( const Exception & excpt )
247  {
248  ERR << "Failed to provide Package " << _package << endl;
249  if ( ! _retry )
250  {
251  // Aything else gets reported
252  std::string package_str = _package->name() + "-" + _package->edition().asString();
253 
254  // TranslatorExplanation %s = name of the package being processed.
255  std::string detail_str( str::form(_("Failed to provide Package %s. Do you want to retry retrieval?"), package_str.c_str() ) );
256  detail_str += str::form( "\n\n%s", excpt.asUserHistory().c_str() );
257 
258  switch ( report()->problem( _package, repo::DownloadResolvableReport::IO, detail_str.c_str() ) )
259  {
261  _retry = true;
262  break;
264  ZYPP_THROW(SkipRequestException("User requested skip of corrupted file", excpt));
265  break;
267  ZYPP_THROW(AbortRequestException("User requested to abort", excpt));
268  break;
269  default:
270  ZYPP_RETHROW( excpt );
271  break;
272  }
273  }
274  }
275  } while ( _retry );
276 
277  report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() );
278  MIL << "provided Package " << _package << " at " << ret << endl;
279  return ret;
280  }
281 
282 
288  {
289  public:
291  const Package::constPtr & package_r,
292  const DeltaCandidates & deltas_r,
293  const PackageProviderPolicy & policy_r )
294  : PackageProvider::Impl( access_r, package_r, deltas_r, policy_r )
295  {}
296 
297  protected:
298  virtual ManagedFile doProvidePackageFromCache() const;
299 
300  virtual ManagedFile doProvidePackage() const;
301 
302  private:
304 
305  ManagedFile tryDelta( const DeltaRpm & delta_r ) const;
306 
307  bool progressDeltaDownload( int value ) const
308  { return report()->progressDeltaDownload( value ); }
309 
310  void progressDeltaApply( int value ) const
311  { return report()->progressDeltaApply( value ); }
312 
313  bool queryInstalled( const Edition & ed_r = Edition() ) const
314  { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
315  };
317 
319  {
320  return ManagedFile( _package->cachedLocation() );
321  }
322 
324  {
325  Url url;
326  RepoInfo info = _package->repoInfo();
327  // FIXME we only support the first url for now.
328  if ( info.baseUrlsEmpty() )
329  ZYPP_THROW(Exception("No url in repository."));
330  else
331  url = * info.baseUrlsBegin();
332 
333  // check whether to process patch/delta rpms
334  if ( ZConfig::instance().download_use_deltarpm()
336  {
337  std::list<DeltaRpm> deltaRpms;
338  _deltas.deltaRpms( _package ).swap( deltaRpms );
339 
340  if ( ! deltaRpms.empty() && queryInstalled() && applydeltarpm::haveApplydeltarpm() )
341  {
342  for_( it, deltaRpms.begin(), deltaRpms.end())
343  {
344  DBG << "tryDelta " << *it << endl;
345  ManagedFile ret( tryDelta( *it ) );
346  if ( ! ret->empty() )
347  return ret;
348  }
349  }
350  }
351 
352  // no patch/delta -> provide full package
353  return Base::doProvidePackage();
354  }
355 
357  {
358  if ( delta_r.baseversion().edition() != Edition::noedition
359  && ! queryInstalled( delta_r.baseversion().edition() ) )
360  return ManagedFile();
361 
362  if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) )
363  return ManagedFile();
364 
365  report()->startDeltaDownload( delta_r.location().filename(),
366  delta_r.location().downloadSize() );
367  ManagedFile delta;
368  try
369  {
370  ProvideFilePolicy policy;
371  policy.progressCB( bind( &RpmPackageProvider::progressDeltaDownload, this, _1 ) );
372  delta = _access.provideFile( delta_r.repository().info(), delta_r.location(), policy );
373  }
374  catch ( const Exception & excpt )
375  {
376  report()->problemDeltaDownload( excpt.asUserHistory() );
377  return ManagedFile();
378  }
379  report()->finishDeltaDownload();
380 
381  report()->startDeltaApply( delta );
382  if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) )
383  {
384  report()->problemDeltaApply( _("applydeltarpm check failed.") );
385  return ManagedFile();
386  }
387 
388  // build the package and put it into the cache
389  Pathname destination( _package->repoInfo().packagesPath() / _package->location().filename() );
390 
391  if ( ! applydeltarpm::provide( delta, destination,
392  bind( &RpmPackageProvider::progressDeltaApply, this, _1 ) ) )
393  {
394  report()->problemDeltaApply( _("applydeltarpm failed.") );
395  return ManagedFile();
396  }
397  report()->finishDeltaApply();
398 
399  return ManagedFile( destination, filesystem::unlink );
400  }
401 
402 #if 0
403  class PluginPackageProvider : public PackageProvider::Impl
411  {
412  public:
413  PluginPackageProvider( const std::string & stem_r,
414  RepoMediaAccess & access_r,
415  const Package::constPtr & package_r,
416  const DeltaCandidates & deltas_r,
417  const PackageProviderPolicy & policy_r )
418  : Base( access_r, package_r, deltas_r, policy_r )
419  {}
420 
421  protected:
422  virtual ManagedFile doProvidePackageFromCache() const
423  {
424  return Base::doProvidePackageFromCache();
425  }
426 
427  virtual ManagedFile doProvidePackage() const
428  {
429  return Base::doProvidePackage();
430  }
431  };
433 #endif
434 
436  // class PackageProvider
438 
440  const Package::constPtr & package_r,
441  const DeltaCandidates & deltas_r,
442  const PackageProviderPolicy & policy_r )
443  {
444  return new RpmPackageProvider( access_r, package_r, deltas_r, policy_r );
445  }
446 
448  const Package::constPtr & package_r,
449  const DeltaCandidates & deltas_r,
450  const PackageProviderPolicy & policy_r )
451  : _pimpl( Impl::factoryMake( access_r, package_r, deltas_r, policy_r ) )
452  {}
453 
455  {}
456 
458  { return _pimpl->providePackage(); }
459 
461  { return _pimpl->providePackageFromCache(); }
462 
464  { return _pimpl->isCached(); }
465 
466  } // namespace repo
468 } // namespace zypp
Candidate delta and patches for a package.
RepoInfo info() const
Return any associated RepoInfo.
Definition: Repository.cc:201
Interface to gettext.
#define MIL
Definition: Logger.h:47
bool failOnChecksumError() const
Redirect ProvideFilePolicy failOnChecksumError to this if needed.
virtual ManagedFile doProvidePackageFromCache() const
Lookup the final rpm in cache.
const Repository & repository() const
Definition: PackageDelta.h:70
PackageProvider implementation.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:320
Describes a path on a certain media amongs as the information required to download it...
static ZConfig & instance()
Singleton ctor.
Definition: ZConfig.cc:655
const BaseVersion & baseversion() const
Definition: PackageDelta.h:69
ManagedFile providePackage() const
Provide the package.
bool isCached() const
Whether the package is cached.
Architecture.
Definition: Arch.h:36
ManagedFile tryDelta(const DeltaRpm &delta_r) const
urls_const_iterator baseUrlsBegin() const
iterator that points at begin of repository urls
Definition: RepoInfo.cc:252
callback::SendReport< repo::DownloadResolvableReport > Report
bool isCached() const
Whether the package is cached.
Policies and options for PackageProvider.
bool haveApplydeltarpm()
Test whether an execuatble applydeltarpm program is available.
What is known about a repository.
Definition: RepoInfo.h:66
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
Definition: ManagedFile.h:27
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
Edition represents [epoch:]version[-release]
Definition: Edition.h:60
void progressDeltaApply(int value) const
Report & report() const
Access to the DownloadResolvableReport.
#define ERR
Definition: Logger.h:49
bool queryInstalled(const Edition &ed_r=Edition()) const
ManagedFile providePackageFromCache() const
Provide the package if it is cached.
Policy for provideFile.
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
Definition: Exception.h:328
RW_pointer< Impl > _pimpl
Implementation class.
PackageProvider(RepoMediaAccess &access, const Package::constPtr &package, const DeltaCandidates &deltas, const PackageProviderPolicy &policy_r=PackageProviderPolicy())
Ctor taking the Package to provide.
packagedelta::DeltaRpm DeltaRpm
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
int unlink(const Pathname &path)
Like &#39;unlink&#39;.
Definition: PathInfo.cc:660
ManagedFile providePackageFromCache() const
Provide the package if it is cached.
zypp::Url url
Definition: MediaCurl.cc:193
bool progressPackageDownload(int value) const
Redirect ProvideFilePolicy package download progress to this.
RpmPackageProvider(RepoMediaAccess &access_r, const Package::constPtr &package_r, const DeltaCandidates &deltas_r, const PackageProviderPolicy &policy_r)
#define _(MSG)
Return translated text.
Definition: Gettext.h:21
const OnMediaLocation & location() const
Definition: PackageDelta.h:68
virtual ManagedFile doProvidePackage() const
Actually provide the final rpm.
Provides files from different repos.
void setDispose(const Dispose &dispose_r)
Set a new dispose function.
Definition: AutoDispose.h:158
bool baseUrlsEmpty() const
whether repository urls are available
Definition: RepoInfo.cc:269
ProvideFilePolicy & failOnChecksumErrorCB(FailOnChecksumErrorCB failOnChecksumErrorCB_r)
Set callback.
std::string form(const char *format,...)
Printf style construction of std::string.
Definition: String.cc:34
const std::string & sequenceinfo() const
Definition: PackageDelta.h:46
virtual ManagedFile doProvidePackageFromCache() const =0
Lookup the final rpm in cache.
Base class for Exception.
Definition: Exception.h:143
ProvideFilePolicy & progressCB(ProgressCB progressCB_r)
Set callback.
Provide a package from a Repo.
Impl(RepoMediaAccess &access_r, const Package::constPtr &package_r, const DeltaCandidates &deltas_r, const PackageProviderPolicy &policy_r)
Ctor taking the Package to provide.
callback::SendReport< DownloadProgressReport > * report
Definition: MediaCurl.cc:178
const Pathname & filename() const
The path to the resource relatve to the url and path.
ManagedFile providePackage() const
Provide the package.
Reference counted access to a _Tp object calling a custom Dispose function when the last AutoDispose ...
Definition: AutoDispose.h:92
RPM PackageProvider implementation.
std::string asUserHistory() const
A single (multiline) string composed of asUserString and historyAsString.
Definition: Exception.cc:75
bool quickcheck(const std::string &sequenceinfo_r)
Quick via check sequence info.
Definition: Applydeltarpm.h:48
bool check(const std::string &sequenceinfo_r, bool quick_r)
Check via sequence info.
virtual ManagedFile doProvidePackage() const =0
Actually provide the final rpm.
bool queryInstalled(const std::string &name_r, const Edition &ed_r, const Arch &arch_r) const
Evaluate callback.
bool progressDeltaDownload(int value) const
Base for exceptions caused by explicit user request.
static bool schemeIsDownloading(const std::string &scheme_r)
http https ftp sftp tftp
Definition: Url.cc:474
const ByteCount & downloadSize() const
The size of the resource on the server.
bool provide(const Pathname &delta_r, const Pathname &new_r, const Progress &report_r)
Apply a binary delta to on-disk data to re-create a new rpm.
Url manipulation class.
Definition: Url.h:87
TraitsType::constPtrType constPtr
Definition: Package.h:38
bool download_use_deltarpm_always() const
Whether to consider using a deltarpm even when rpm is local.
Definition: ZConfig.cc:839
#define DBG
Definition: Logger.h:46
static const Edition noedition
Value representing noedition (&quot;&quot;) This is in fact a valid Edition.
Definition: Edition.h:73
static Impl * factoryMake(RepoMediaAccess &access_r, const Package::constPtr &package_r, const DeltaCandidates &deltas_r, const PackageProviderPolicy &policy_r)
Factory method providing the appropriate implementation.