PackageProvider.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <sstream>
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Gettext.h"
00016 
00017 #include "zypp/ZConfig.h"
00018 #include "zypp/Source.h"
00019 #include "zypp/source/PackageProvider.h"
00020 #include "zypp/source/SourceProvideFile.h"
00021 #include "zypp/source/Applydeltarpm.h"
00022 #include "zypp/source/PackageDelta.h"
00023 #include "zypp/detail/ImplConnect.h"
00024 
00025 using std::endl;
00026 
00028 namespace zypp
00029 { 
00030 
00031   namespace source
00032   { 
00033 
00035     //
00036     //  CLASS NAME : PackageProviderPolicy
00037     //
00039 
00040     bool PackageProviderPolicy::queryInstalled( const std::string & name_r,
00041                                                 const Edition &     ed_r,
00042                                                 const Arch &        arch_r ) const
00043     {
00044       if ( _queryInstalledCB )
00045         return _queryInstalledCB( name_r, ed_r, arch_r );
00046       return false;
00047     }
00048 
00050     //
00051     //  CLASS NAME : PackageProvider
00052     //
00054 
00056     namespace
00057     { 
00058 
00059       inline std::string defRpmFileName( const Package::constPtr & package )
00060       {
00061         std::ostringstream ret;
00062         ret << package->name() << '-' << package->edition() << '.' << package->arch() << ".rpm";
00063         return ret.str();
00064       }
00065 
00067     } // namespace source
00069     PackageProvider::PackageProvider( const Package::constPtr & package,
00070                                       const PackageProviderPolicy & policy_r )
00071     : _policy( policy_r )
00072     , _package( package )
00073     , _implPtr( detail::ImplConnect::resimpl( _package ) )
00074     {}
00075 
00076     PackageProvider::~PackageProvider()
00077     {}
00078 
00079     ManagedFile PackageProvider::providePackage() const
00080     {
00081       MIL << "provide Package " << _package << endl;
00082       ScopedGuard guardReport( newReport() );
00083       ManagedFile ret;
00084       do {
00085         _retry = false;
00086         report()->start( _package, _package->source().url() );
00087         try  // ELIMINATE try/catch by providing a log-guard
00088           {
00089             ret = doProvidePackage();
00090           }
00091         catch ( const Exception & excpt )
00092           {
00093             ERR << "Failed to provide Package " << _package << endl;
00094             if ( ! _retry )
00095               {
00096                 ZYPP_RETHROW( excpt );
00097               }
00098           }
00099       } while ( _retry );
00100 
00101       report()->finish( _package, source::DownloadResolvableReport::NO_ERROR, std::string() );
00102       MIL << "provided Package " << _package << " at " << ret << endl;
00103       return ret;
00104     }
00105 
00106     ManagedFile PackageProvider::doProvidePackage() const
00107     {
00108       // check whether to process patch/delta rpms
00109       if ( _package->source().remote() )
00110         {
00111           std::list<DeltaRpm> deltaRpms;
00112           if ( ZConfig::instance().download_use_deltarpm() )
00113           {
00114             _implPtr->deltaRpms().swap( deltaRpms );
00115           }
00116 
00117           std::list<PatchRpm> patchRpms;
00118           if ( ZConfig::instance().download_use_patchrpm() )
00119           {
00120             _implPtr->patchRpms().swap( patchRpms );
00121           }
00122 
00123           if ( ! ( deltaRpms.empty() && patchRpms.empty() )
00124                && queryInstalled() )
00125             {
00126               if ( ! deltaRpms.empty() && applydeltarpm::haveApplydeltarpm() )
00127                 {
00128                   for( std::list<DeltaRpm>::const_iterator it = deltaRpms.begin();
00129                        it != deltaRpms.end(); ++it )
00130                     {
00131                       DBG << "tryDelta " << *it << endl;
00132                       ManagedFile ret( tryDelta( *it ) );
00133                       if ( ! ret->empty() )
00134                         return ret;
00135                     }
00136                 }
00137 
00138               if ( ! patchRpms.empty() )
00139                 {
00140                   for( std::list<PatchRpm>::const_iterator it = patchRpms.begin();
00141                        it != patchRpms.end(); ++it )
00142                     {
00143                       DBG << "tryPatch " << *it << endl;
00144                       ManagedFile ret( tryPatch( *it ) );
00145                       if ( ! ret->empty() )
00146                         return ret;
00147                     }
00148                 }
00149             }
00150         }
00151       else
00152         {
00153           // allow patch rpm from local source
00154           std::list<PatchRpm> patchRpms;
00155           if ( ZConfig::instance().download_use_patchrpm() )
00156           {
00157             _implPtr->patchRpms().swap( patchRpms );
00158           }
00159 
00160           if ( ! patchRpms.empty() && queryInstalled() )
00161             {
00162               for( std::list<PatchRpm>::const_iterator it = patchRpms.begin();
00163                    it != patchRpms.end(); ++it )
00164                 {
00165                   DBG << "tryPatch " << *it << endl;
00166                   ManagedFile ret( tryPatch( *it ) );
00167                   if ( ! ret->empty() )
00168                     return ret;
00169                 }
00170             }
00171         }
00172 
00173       // no patch/delta -> provide full package
00174       ManagedFile ret;
00175       source::OnMediaLocation loc;
00176       loc.medianr( _package->sourceMediaNr() )
00177       .filename( _package->location() )
00178       .checksum( _package->checksum() )
00179       .downloadsize( _package->archivesize() );
00180 
00181       source::ProvideFilePolicy policy;
00182       policy.progressCB( bind( &PackageProvider::progressPackageDownload, this, _1 ) );
00183       policy.failOnChecksumErrorCB( bind( &PackageProvider::failOnChecksumError, this ) );
00184 
00185       return source::provideFile( _package->source(), loc, policy );
00186     }
00187 
00188     ManagedFile PackageProvider::tryDelta( const DeltaRpm & delta_r ) const
00189     {
00190       if ( delta_r.baseversion().edition() != Edition::noedition
00191            && ! queryInstalled( delta_r.baseversion().edition() ) )
00192         return ManagedFile();
00193 
00194       if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) )
00195         return ManagedFile();
00196 
00197       report()->startDeltaDownload( delta_r.location().filename(),
00198                                     delta_r.location().downloadsize() );
00199       ManagedFile delta;
00200       try
00201         {
00202           source::ProvideFilePolicy policy;
00203           policy.progressCB( bind( &PackageProvider::progressDeltaDownload, this, _1 ) );
00204           delta = source::provideFile( _package->source(), delta_r.location(), policy );
00205         }
00206       catch ( const Exception & excpt )
00207         {
00208           report()->problemDeltaDownload( excpt.asUserString() );
00209           return ManagedFile();
00210         }
00211       report()->finishDeltaDownload();
00212 
00213       report()->startDeltaApply( delta );
00214       if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) )
00215         {
00216           report()->problemDeltaApply( _("applydeltarpm check failed.") );
00217           return ManagedFile();
00218         }
00219 
00220       Pathname destination( Pathname::dirname( delta ) / defRpmFileName( _package ) );
00221       /* just to ease testing with non remote sources */
00222       if ( ! _package->source().remote() )
00223         destination = Pathname("/tmp") / defRpmFileName( _package );
00224       
00225 
00226       if ( ! applydeltarpm::provide( delta, destination,
00227                                      bind( &PackageProvider::progressDeltaApply, this, _1 ) ) )
00228         {
00229           report()->problemDeltaApply( _("applydeltarpm failed.") );
00230           return ManagedFile();
00231         }
00232       report()->finishDeltaApply();
00233 
00234       return ManagedFile( destination, filesystem::unlink );
00235     }
00236 
00237     ManagedFile PackageProvider::tryPatch( const PatchRpm & patch_r ) const
00238     {
00239       // installed edition is in baseversions?
00240       const PatchRpm::BaseVersions & baseversions( patch_r.baseversions() );
00241 
00242       if ( std::find_if( baseversions.begin(), baseversions.end(),
00243                          bind( &PackageProvider::queryInstalled, this, _1 ) )
00244            == baseversions.end() )
00245         return ManagedFile();
00246 
00247       report()->startPatchDownload( patch_r.location().filename(),
00248                                     patch_r.location().downloadsize() );
00249       ManagedFile patch;
00250       try
00251         {
00252           source::ProvideFilePolicy policy;
00253           policy.progressCB( bind( &PackageProvider::progressPatchDownload, this, _1 ) );
00254           patch = source::provideFile( _package->source(), patch_r.location(), policy );
00255         }
00256       catch ( const Exception & excpt )
00257         {
00258           report()->problemPatchDownload( excpt.asUserString() );
00259           return ManagedFile();
00260         }
00261       report()->finishPatchDownload();
00262 
00263       return patch;
00264     }
00265 
00266     PackageProvider::ScopedGuard PackageProvider::newReport() const
00267     {
00268       _report.reset( new Report );
00269       return shared_ptr<void>( static_cast<void*>(0),
00270                                // custom deleter calling _report.reset()
00271                                // (cast required as reset is overloaded)
00272                                bind( mem_fun_ref( static_cast<void (shared_ptr<Report>::*)()>(&shared_ptr<Report>::reset) ),
00273                                      ref(_report) ) );
00274     }
00275 
00276     PackageProvider::Report & PackageProvider::report() const
00277     { return *_report; }
00278 
00279     bool PackageProvider::progressDeltaDownload( int value ) const
00280     { return report()->progressDeltaDownload( value ); }
00281 
00282     void PackageProvider::progressDeltaApply( int value ) const
00283     { return report()->progressDeltaApply( value ); }
00284 
00285     bool PackageProvider::progressPatchDownload( int value ) const
00286     { return report()->progressPatchDownload( value ); }
00287 
00288     bool PackageProvider::progressPackageDownload( int value ) const
00289     { return report()->progress( value, _package ); }
00290 
00291     bool PackageProvider::failOnChecksumError() const
00292     {
00293       std::string package_str = _package->name() + "-" + _package->edition().asString();
00294 
00295       // TranslatorExplanation %s = package being checked for integrity
00296       switch ( report()->problem( _package, source::DownloadResolvableReport::INVALID, str::form(_("Package %s fails integrity check. Do you want to retry downloading it?"), package_str.c_str() ) ) )
00297         {
00298         case source::DownloadResolvableReport::RETRY:
00299           _retry = true;
00300           break;
00301           case source::DownloadResolvableReport::IGNORE:
00302           ZYPP_THROW(source::SkipRequestedException("User requested skip of corrupted file"));
00303           break;
00304         default:
00305           break;
00306         }
00307       return true; // anyway a failure
00308     }
00309 
00310     bool PackageProvider::queryInstalled( const Edition & ed_r ) const
00311     { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
00312 
00313 
00315   } // namespace source
00318 } // namespace zypp

Generated on Thu Apr 24 02:24:54 2008 for zypp by  doxygen 1.4.6