RepoProvideFile.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015 #include <set>
00016 
00017 #include "zypp/base/Gettext.h"
00018 #include "zypp/base/Logger.h"
00019 #include "zypp/base/String.h"
00020 #include "zypp/base/UserRequestException.h"
00021 #include "zypp/repo/RepoProvideFile.h"
00022 #include "zypp/ZYppCallbacks.h"
00023 #include "zypp/MediaSetAccess.h"
00024 #include "zypp/ZConfig.h"
00025 #include "zypp/repo/SUSEMediaVerifier.h"
00026 #include "zypp/repo/RepoException.h"
00027 
00028 #include "zypp/repo/SUSEMediaVerifier.h"
00029 #include "zypp/repo/RepoException.h"
00030 #include "zypp/FileChecker.h"
00031 
00032 using std::endl;
00033 using std::set;
00034 
00036 namespace zypp
00037 { 
00038 
00039   namespace repo
00040   { 
00041 
00043     //
00044     //  provideFile
00045     //
00047 
00049     namespace
00050     { 
00051 
00056       struct DownloadFileReportHack : public callback::ReceiveReport<repo::RepoReport>
00057       {
00058         virtual bool progress( const ProgressData &progress )
00059         {
00060           if ( _redirect )
00061             return _redirect( progress.val() );
00062           return true;
00063         }
00064         function<bool ( int )> _redirect;
00065       };
00066 
00068     } // namespace
00070 
00071     ManagedFile provideFile( Repository repo_r,
00072                              const OnMediaLocation & loc_r,
00073                              const ProvideFilePolicy & policy_r )
00074     {
00075       RepoMediaAccess access;
00076       return access.provideFile(repo_r, loc_r, policy_r );
00077     }
00078 
00079     class RepoMediaAccess::Impl
00080     {
00081     public:
00082       Impl( const ProvideFilePolicy & defaultPolicy_r )
00083         : _defaultPolicy( defaultPolicy_r )
00084       {}
00085 
00086       ~Impl()
00087       {
00088         std::map<Url, shared_ptr<MediaSetAccess> >::iterator it;
00089         for ( it = _medias.begin();
00090               it != _medias.end();
00091               ++it )
00092         {
00093           it->second->release();
00094         }
00095       }
00096 
00097       shared_ptr<MediaSetAccess> mediaAccessForUrl( const Url &url )
00098       {
00099         std::map<Url, shared_ptr<MediaSetAccess> >::const_iterator it;
00100         it = _medias.find(url);
00101         shared_ptr<MediaSetAccess> media;
00102         if ( it != _medias.end() )
00103         {
00104           media = it->second;
00105         }
00106         else
00107         {
00108           media.reset( new MediaSetAccess(url) );
00109           _medias[url] = media;
00110         }
00111         return media;
00112       }
00113 
00114       void setVerifierForRepo( Repository repo, shared_ptr<MediaSetAccess> media )
00115       {
00116         RepoInfo info = repo.info();
00117         // set a verifier if the repository has it
00118          
00119         Pathname mediafile = info.metadataPath() + "/media.1/media";
00120         if ( ! info.metadataPath().empty() )
00121         {
00122           if ( PathInfo(mediafile).isExist() )
00123           {
00124             std::map<shared_ptr<MediaSetAccess>, Repository>::const_iterator it;
00125             it = _verifier.find(media);
00126             if ( it != _verifier.end() )
00127             {
00128               if ( it->second == repo )
00129               {
00130                 // this media is already using this repo verifier
00131                 return;
00132               }
00133             }
00134 
00135             std::ifstream str(mediafile.asString().c_str());
00136             std::string vendor;
00137             std::string mediaid;
00138             std::string buffer;
00139             if ( str )
00140             {
00141               getline(str, vendor);
00142               getline(str, mediaid);
00143               getline(str, buffer);
00144 
00145               unsigned media_nr = str::strtonum<unsigned>(buffer);
00146               MIL << "Repository '" << info.alias() << "' has " << media_nr << " medias"<< endl;
00147 
00148               for ( unsigned i=1; i <= media_nr; ++i )
00149               {
00150                 media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( vendor, mediaid, i ) );
00151 
00152                 media->setVerifier( i, verifier);
00153               }
00154               _verifier[media] = repo;
00155             }
00156             else
00157             {
00158               ZYPP_THROW(RepoMetadataException(info));
00159             }
00160           }
00161           else
00162           {
00163             WAR << "No media verifier for repo '" << info.alias() << "' media/media.1 does not exist in '" << info.metadataPath() << "'" << endl;
00164           }
00165         }
00166         else
00167         {
00168           WAR << "'" << info.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl;
00169         }
00170       }
00171 
00172       std::map<shared_ptr<MediaSetAccess>, Repository> _verifier;
00173       std::map<Url, shared_ptr<MediaSetAccess> > _medias;
00174       ProvideFilePolicy _defaultPolicy;
00175     };
00176 
00177 
00178 
00179     RepoMediaAccess::RepoMediaAccess( const ProvideFilePolicy & defaultPolicy_r )
00180       : _impl( new Impl( defaultPolicy_r ) )
00181     {}
00182 
00183     RepoMediaAccess::~RepoMediaAccess()
00184     {}
00185 
00186     void RepoMediaAccess::setDefaultPolicy( const ProvideFilePolicy & policy_r )
00187     { _impl->_defaultPolicy = policy_r; }
00188 
00189     const ProvideFilePolicy & RepoMediaAccess::defaultPolicy() const
00190     { return _impl->_defaultPolicy; }
00191 
00192     ManagedFile RepoMediaAccess::provideFile( Repository repo_r,
00193                                               const OnMediaLocation & loc_r,
00194                                               const ProvideFilePolicy & policy_r )
00195     {
00196       MIL << loc_r << endl;
00197       // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport
00198       // and redirect download progress triggers to call the ProvideFilePolicy
00199       // callback.
00200       DownloadFileReportHack dumb;
00201       dumb._redirect = bind( mem_fun_ref( &ProvideFilePolicy::progress ),
00202                              ref( policy_r ), _1 );
00203       callback::TempConnect<repo::RepoReport> temp( dumb );
00204 
00205       Url url;
00206       RepoInfo info = repo_r.info();
00207       
00208       RepoException repo_excpt(str::form(_("Can't provide file %s from repository %s"),
00209                                loc_r.filename().c_str(),
00210                                info.alias().c_str() ) );
00211       
00212       if ( info.baseUrlsEmpty() )
00213       {
00214         repo_excpt.remember(RepoException(_("No url in repository.")));
00215         ZYPP_THROW(repo_excpt);
00216       }
00217       
00218       for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin();
00219             it != info.baseUrlsEnd();
00220             /* incremented in the loop */ )
00221       {
00222         url = *it;
00223         ++it;
00224         try
00225         {
00226           MIL << "Providing file of repo '" << info.alias()
00227               << "' from " << url << endl;
00228           shared_ptr<MediaSetAccess> access = _impl->mediaAccessForUrl(url);
00229           _impl->setVerifierForRepo(repo_r, access);
00230 
00231           ManagedFile ret( access->provideFile(loc_r) );
00232 
00233           std::string scheme( url.getScheme() );
00234           if ( scheme == "http" || scheme == "https" || scheme == "ftp" )
00235           {
00236             ret.setDispose( filesystem::unlink );
00237           }
00238 
00239           if ( loc_r.checksum().empty() )
00240           {
00241             // no checksum in metadata
00242             WAR << "No checksum in metadata " << loc_r << endl;
00243           }
00244           else
00245           {
00246             std::ifstream input( ret->asString().c_str() );
00247             CheckSum retChecksum( loc_r.checksum().type(), input );
00248             input.close();
00249 
00250             if ( loc_r.checksum() != retChecksum )
00251             {
00252               // failed integity check
00253               std::ostringstream err;
00254               err << "File " << ret << " fails integrity check. Expected: [" << loc_r.checksum() << "] Got: [";
00255               if ( retChecksum.empty() )
00256                 err << "Failed to compute checksum";
00257               else
00258                 err << retChecksum;
00259               err << "]";
00260 
00261               if ( policy_r.failOnChecksumError() )
00262                 ZYPP_THROW( FileCheckException( err.str() ) );
00263               else
00264                 WAR << "NO failOnChecksumError: " << err.str() << endl;
00265             }
00266           }
00267 
00268           MIL << "provideFile at " << ret << endl;
00269           return ret;
00270         }
00271         catch ( const SkipRequestException &e )
00272         {
00273           ZYPP_CAUGHT( e );
00274           ZYPP_RETHROW(e);
00275         }
00276         catch ( const AbortRequestException &e )
00277         {
00278           ZYPP_CAUGHT( e );
00279           ZYPP_RETHROW(e);
00280         }
00281         catch ( const Exception &e )
00282         {
00283           ZYPP_CAUGHT( e );
00284           
00285           repo_excpt.remember(e);
00286           
00287           WAR << "Trying next url" << endl;
00288           continue;
00289         }
00290       } // iteration over urls
00291 
00292       ZYPP_THROW(repo_excpt);
00293       return ManagedFile(); // not reached
00294     }
00295 
00297   } // namespace repo
00300 } // namespace zypp

Generated on Tue Sep 25 19:23:05 2007 for libzypp by  doxygen 1.5.3