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