00001
00002
00003
00004
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
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
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 }
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
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
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
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
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
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
00236
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;
00271 }
00272
00273 bool PackageProvider::queryInstalled( const Edition & ed_r ) const
00274 { return _policy.queryInstalled( _package->name(), ed_r ); }
00275
00276
00278 }
00281 }