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

Generated on Wed Sep 27 01:16:42 2006 for zypp by  doxygen 1.4.6