PackageProvider.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <sstream>
00014 #include "zypp/repo/PackageDelta.h"
00015 #include "zypp/base/Logger.h"
00016 #include "zypp/base/Gettext.h"
00017 #include "zypp/base/UserRequestException.h"
00018 #include "zypp/repo/PackageProvider.h"
00019 #include "zypp/repo/RepoProvideFile.h"
00020 #include "zypp/repo/Applydeltarpm.h"
00021 #include "zypp/repo/PackageDelta.h"
00022
00023 #include "zypp/TmpPath.h"
00024 #include "zypp/ZConfig.h"
00025 #include "zypp/RepoInfo.h"
00026
00027 using std::endl;
00028
00030 namespace zypp
00031 {
00032
00033 namespace repo
00034 {
00035
00037
00038
00039
00041
00042 bool PackageProviderPolicy::queryInstalled( const std::string & name_r,
00043 const Edition & ed_r,
00044 const Arch & arch_r ) const
00045 {
00046 if ( _queryInstalledCB )
00047 return _queryInstalledCB( name_r, ed_r, arch_r );
00048 return false;
00049 }
00050
00052
00053
00054
00056
00058 namespace
00059 {
00060
00061 inline std::string defRpmFileName( const Package::constPtr & package )
00062 {
00063 std::ostringstream ret;
00064 ret << package->name() << '-' << package->edition() << '.' << package->arch() << ".rpm";
00065 return ret.str();
00066 }
00067
00069 }
00071 PackageProvider::PackageProvider( RepoMediaAccess &access,
00072 const Package::constPtr & package,
00073 const DeltaCandidates & deltas,
00074 const PackageProviderPolicy & policy_r )
00075 : _policy( policy_r )
00076 , _package( package )
00077 , _deltas(deltas)
00078 , _access(access)
00079 , _retry(false)
00080 {}
00081
00082 PackageProvider::~PackageProvider()
00083 {}
00084
00085 ManagedFile PackageProvider::providePackage() const
00086 {
00087 Url url;
00088 RepoInfo info = _package->repoInfo();
00089
00090 if ( info.baseUrlsEmpty() )
00091 ZYPP_THROW(Exception("No url in repository."));
00092 else
00093 url = * info.baseUrlsBegin();
00094
00095 {
00096 OnMediaLocation loc( _package->location() );
00097 PathInfo cachepath( info.packagesPath() / loc.filename() );
00098
00099 if ( cachepath.isFile() && ! loc.checksum().empty() )
00100
00101
00102
00103 {
00104 CheckSum cachechecksum( loc.checksum().type(), filesystem::checksum( cachepath.path(), loc.checksum().type() ) );
00105 USR << cachechecksum << endl;
00106 if ( cachechecksum == loc.checksum() )
00107 {
00108 ManagedFile ret( cachepath.path() );
00109 if ( ! info.keepPackages() )
00110 {
00111 ret.setDispose( filesystem::unlink );
00112 }
00113 MIL << "provided Package from cache " << _package << " at " << ret << endl;
00114 return ret;
00115 }
00116 }
00117 }
00118
00119
00120 MIL << "provide Package " << _package << endl;
00121 ScopedGuard guardReport( newReport() );
00122 ManagedFile ret;
00123 do {
00124 _retry = false;
00125 report()->start( _package, url );
00126 try
00127 {
00128 ret = doProvidePackage();
00129 }
00130 catch ( const UserRequestException & excpt )
00131 {
00132
00133 ERR << "Failed to provide Package " << _package << endl;
00134 if ( ! _retry )
00135 {
00136 ZYPP_RETHROW( excpt );
00137 }
00138 }
00139 catch ( const Exception & excpt )
00140 {
00141 ERR << "Failed to provide Package " << _package << endl;
00142 if ( ! _retry )
00143 {
00144
00145 std::string package_str = _package->name() + "-" + _package->edition().asString();
00146
00147
00148 std::string detail_str( str::form(_("Failed to provide Package %s. Do you want to retry retrieval?"), package_str.c_str() ) );
00149 detail_str += str::form( "\n\n%s", excpt.asUserHistory().c_str() );
00150
00151 switch ( report()->problem( _package, repo::DownloadResolvableReport::IO, detail_str.c_str() ) )
00152 {
00153 case repo::DownloadResolvableReport::RETRY:
00154 _retry = true;
00155 break;
00156 case repo::DownloadResolvableReport::IGNORE:
00157 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
00158 break;
00159 case repo::DownloadResolvableReport::ABORT:
00160 ZYPP_THROW(AbortRequestException("User requested to abort"));
00161 break;
00162 default:
00163 ZYPP_RETHROW( excpt );
00164 break;
00165 }
00166 }
00167 }
00168 } while ( _retry );
00169
00170 report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() );
00171 MIL << "provided Package " << _package << " at " << ret << endl;
00172 return ret;
00173 }
00174
00175 ManagedFile PackageProvider::doProvidePackage() const
00176 {
00177 Url url;
00178 RepoInfo info = _package->repoInfo();
00179
00180 if ( info.baseUrlsEmpty() )
00181 ZYPP_THROW(Exception("No url in repository."));
00182 else
00183 url = * info.baseUrlsBegin();
00184
00185
00186 if ( url.schemeIsDownloading() || ZConfig::instance().download_use_deltarpm_always() )
00187 {
00188 std::list<DeltaRpm> deltaRpms;
00189 if ( ZConfig::instance().download_use_deltarpm() )
00190 {
00191 _deltas.deltaRpms( _package ).swap( deltaRpms );
00192 }
00193
00194 if ( ! ( deltaRpms.empty() )
00195 && queryInstalled() )
00196 {
00197 if ( ! deltaRpms.empty() && applydeltarpm::haveApplydeltarpm() )
00198 {
00199 for( std::list<DeltaRpm>::const_iterator it = deltaRpms.begin();
00200 it != deltaRpms.end(); ++it )
00201 {
00202 DBG << "tryDelta " << *it << endl;
00203 ManagedFile ret( tryDelta( *it ) );
00204 if ( ! ret->empty() )
00205 return ret;
00206 }
00207 }
00208 }
00209 }
00210
00211
00212 ManagedFile ret;
00213 OnMediaLocation loc = _package->location();
00214
00215 ProvideFilePolicy policy;
00216 policy.progressCB( bind( &PackageProvider::progressPackageDownload, this, _1 ) );
00217 policy.failOnChecksumErrorCB( bind( &PackageProvider::failOnChecksumError, this ) );
00218 return _access.provideFile( _package->repoInfo(), loc, policy );
00219 }
00220
00221 ManagedFile PackageProvider::tryDelta( const DeltaRpm & delta_r ) const
00222 {
00223 if ( delta_r.baseversion().edition() != Edition::noedition
00224 && ! queryInstalled( delta_r.baseversion().edition() ) )
00225 return ManagedFile();
00226
00227 if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) )
00228 return ManagedFile();
00229
00230 report()->startDeltaDownload( delta_r.location().filename(),
00231 delta_r.location().downloadSize() );
00232 ManagedFile delta;
00233 try
00234 {
00235 ProvideFilePolicy policy;
00236 policy.progressCB( bind( &PackageProvider::progressDeltaDownload, this, _1 ) );
00237 delta = _access.provideFile( delta_r.repository().info(), delta_r.location(), policy );
00238 }
00239 catch ( const Exception & excpt )
00240 {
00241 report()->problemDeltaDownload( excpt.asUserHistory() );
00242 return ManagedFile();
00243 }
00244 report()->finishDeltaDownload();
00245
00246 report()->startDeltaApply( delta );
00247 if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) )
00248 {
00249 report()->problemDeltaApply( _("applydeltarpm check failed.") );
00250 return ManagedFile();
00251 }
00252
00253
00254 Pathname destination( _package->repoInfo().packagesPath() / _package->location().filename() );
00255
00256 if ( ! applydeltarpm::provide( delta, destination,
00257 bind( &PackageProvider::progressDeltaApply, this, _1 ) ) )
00258 {
00259 report()->problemDeltaApply( _("applydeltarpm failed.") );
00260 return ManagedFile();
00261 }
00262 report()->finishDeltaApply();
00263
00264 return ManagedFile( destination, filesystem::unlink );
00265 }
00266
00267 PackageProvider::ScopedGuard PackageProvider::newReport() const
00268 {
00269 _report.reset( new Report );
00270 return shared_ptr<void>( static_cast<void*>(0),
00271
00272
00273 bind( mem_fun_ref( static_cast<void (shared_ptr<Report>::*)()>(&shared_ptr<Report>::reset) ),
00274 ref(_report) ) );
00275 }
00276
00277 PackageProvider::Report & PackageProvider::report() const
00278 { return *_report; }
00279
00280 bool PackageProvider::progressDeltaDownload( int value ) const
00281 { return report()->progressDeltaDownload( value ); }
00282
00283 void PackageProvider::progressDeltaApply( int value ) const
00284 { return report()->progressDeltaApply( value ); }
00285
00286 bool PackageProvider::progressPackageDownload( int value ) const
00287 { return report()->progress( value, _package ); }
00288
00289 bool PackageProvider::failOnChecksumError() const
00290 {
00291 std::string package_str = _package->name() + "-" + _package->edition().asString();
00292
00293
00294 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() ) ) )
00295 {
00296 case repo::DownloadResolvableReport::RETRY:
00297 _retry = true;
00298 break;
00299 case repo::DownloadResolvableReport::IGNORE:
00300 ZYPP_THROW(SkipRequestException("User requested skip of corrupted file"));
00301 break;
00302 case repo::DownloadResolvableReport::ABORT:
00303 ZYPP_THROW(AbortRequestException("User requested to abort"));
00304 break;
00305 default:
00306 break;
00307 }
00308 return true;
00309 }
00310
00311 bool PackageProvider::queryInstalled( const Edition & ed_r ) const
00312 { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); }
00313
00314
00316 }
00319 }