MediaSetAccess.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00009 
00010 #include <iostream>
00011 #include <fstream>
00012 
00013 #include "zypp/base/LogTools.h"
00014 #include "zypp/ZYppCallbacks.h"
00015 #include "zypp/MediaSetAccess.h"
00016 #include "zypp/PathInfo.h"
00017 //#include "zypp/source/MediaSetAccessReportReceivers.h"
00018 
00019 using namespace std;
00020 
00022 namespace zypp
00023 { 
00024 
00025 
00026   ChecksumFileChecker::ChecksumFileChecker( const CheckSum &checksum )
00027     : _checksum(checksum)
00028   {
00029   }
00030 
00031   bool ChecksumFileChecker::operator()( const Pathname &file )
00032   {
00033     // FIXME probably this funcionality should be in CheckSum itself
00034     CheckSum real_checksum( _checksum.type(), filesystem::checksum( file, _checksum.type() ));
00035     if ( real_checksum == _checksum )
00036     {
00037       return true;
00038     }
00039     else
00040     {
00041       ERR << "Got " << real_checksum << ", expected " << _checksum << std::endl;
00042       return false;
00043     }
00044   }
00045 
00046   bool NullFileChecker::operator()(const Pathname &file )
00047   {
00048     return true;
00049   }
00050 
00051   MediaSetAccess::MediaSetAccess(  const Url &url, const Pathname &path )
00052       : _url(url),
00053         _path(path)
00054   {
00055     MIL << "initializing.." << std::endl;
00056     //std::vector<media::MediaVerifierRef> single_media;
00057     //single_media[0] = media::MediaVerifierRef(new media::NoVerifier());
00058     //_verifiers = single_media;
00059   }
00060   
00061   MediaSetAccess::~MediaSetAccess()
00062   {
00063   }
00064 
00065   void MediaSetAccess::setVerifiers( const std::vector<media::MediaVerifierRef> &verifiers )
00066   {
00067     _verifiers = verifiers;
00068   }
00069 
00070 //       callback::SendReport<source::DownloadFileReport> report;
00071 //       DownloadProgressFileReceiver download_report( report );
00072 //       SourceFactory source_factory;
00073 //       Url file_url( url().asString() + file_r.asString() );
00074 //       report->start( source_factory.createFrom(this), file_url );
00075 //       callback::TempConnect<media::DownloadProgressReport> tmp_download( download_report );
00076 //       Pathname file = provideJustFile( file_r, media_nr, cached, checkonly );
00077 //       report->finish( file_url, source::DownloadFileReport::NO_ERROR, "" );
00078 //       return file;
00079 
00080 
00081   void MediaSetAccess::providePossiblyCachedMetadataFile( const Pathname &file_to_download, unsigned medianr, const Pathname &destination, const Pathname &cached_file, const CheckSum &checksum )
00082   {
00083     Url file_url( _url.asString() + file_to_download.asString() );
00084     // if we have a cached file and its the same
00085     if ( PathInfo(cached_file).isExist() && (! checksum.empty()) && is_checksum( cached_file, checksum ) )
00086     {
00087       MIL << "file " << file_url << " found in previous cache. Using cached copy." << std::endl;
00088       // checksum is already checked.
00089       // we could later implement double failover and try to download if file copy fails.
00090       if ( filesystem::copy(cached_file, destination) != 0 )
00091         ZYPP_THROW(Exception("Can't copy " + cached_file.asString() + " to " + destination.asString()));
00092     }
00093     else
00094     {
00095       // we dont have it or its not the same, download it.
00096       Pathname downloaded_file = provideFile( file_to_download, medianr, ChecksumFileChecker(checksum) );
00097       
00098       if ( filesystem::copy(downloaded_file, destination) != 0 )
00099         ZYPP_THROW(Exception("Can't copy " + downloaded_file.asString() + " to " + destination.asString()));      
00100     }
00101   }
00102 
00103   Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
00104   {
00105     return provideFileInternal( file, media_nr, false, false);
00106   }
00107 
00108   Pathname  MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, FileChecker checker )
00109   {
00110     Pathname p = provideFileInternal( file, media_nr, false, false);
00111     
00112     if ( ! checker(p) )
00113     {
00114       ZYPP_THROW(Exception("Error checker"));
00115     }
00116     return p;
00117   }
00118 
00119   Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
00120   {
00121     callback::SendReport<media::MediaChangeReport> report;
00122     media::MediaManager media_mgr;
00123     // get the mediaId, but don't try to attach it here
00124     media::MediaAccessId media = getMediaAccessId( media_nr);
00125       
00126     do
00127     {
00128       try
00129       {
00130         DBG << "Going to try provide file " << file << " from " << media_nr << endl;        
00131         // try to attach the media
00132         if ( ! media_mgr.isAttached(media) )
00133         media_mgr.attach(media);
00134         media_mgr.provideFile (media, file, false, false);
00135         break;
00136       }
00137       catch ( Exception & excp )
00138       {
00139         ZYPP_CAUGHT(excp);
00140         media::MediaChangeReport::Action user;
00141         do
00142         {
00143           DBG << "Media couldn't provide file " << file << " , releasing." << endl;
00144           try
00145           {
00146             media_mgr.release (media, false);
00147           }
00148           catch (const Exception & excpt_r)
00149           {
00150               ZYPP_CAUGHT(excpt_r);
00151               MIL << "Failed to release media " << media << endl;
00152           }
00153           
00154           MIL << "Releasing all medias of all sources" << endl;
00155           try
00156           {
00157             //zypp::SourceManager::sourceManager()->releaseAllSources();
00158           }
00159           catch (const zypp::Exception& excpt_r)
00160           {
00161               ZYPP_CAUGHT(excpt_r);
00162               ERR << "Failed to release all sources" << endl;
00163           }
00164 
00165           // set up the reason
00166           media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00167           
00168           if( typeid(excp) == typeid( media::MediaFileNotFoundException )  ||
00169               typeid(excp) == typeid( media::MediaNotAFileException ) )
00170           {
00171             reason = media::MediaChangeReport::NOT_FOUND;
00172           } 
00173           else if( typeid(excp) == typeid( media::MediaNotDesiredException)  ||
00174               typeid(excp) == typeid( media::MediaNotAttachedException) )
00175           {
00176             reason = media::MediaChangeReport::WRONG;
00177           }
00178 
00179           user  = checkonly ? media::MediaChangeReport::ABORT :
00180             report->requestMedia (
00181               Source_Ref::noSource,
00182               media_nr,
00183               reason,
00184               excp.asUserString()
00185             );
00186 
00187           DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00188 
00189           if( user == media::MediaChangeReport::ABORT )
00190           {
00191             DBG << "Aborting" << endl;
00192             ZYPP_RETHROW ( excp );
00193           }
00194           else if ( user == media::MediaChangeReport::IGNORE )
00195           {
00196             DBG << "Skipping" << endl;
00197             ZYPP_THROW ( source::SkipRequestedException("User-requested skipping of a file") );
00198           }
00199           else if ( user == media::MediaChangeReport::EJECT )
00200           {
00201             DBG << "Eject: try to release" << endl;
00202             try
00203             {
00204               //zypp::SourceManager::sourceManager()->releaseAllSources();
00205             }
00206             catch (const zypp::Exception& excpt_r)
00207             {
00208               ZYPP_CAUGHT(excpt_r);
00209               ERR << "Failed to release all sources" << endl;
00210             }
00211             media_mgr.release (media, true); // one more release needed for eject
00212             // FIXME: this will not work, probably
00213           }
00214           else if ( user == media::MediaChangeReport::RETRY  ||
00215             user == media::MediaChangeReport::CHANGE_URL )
00216           {
00217             // retry
00218             DBG << "Going to try again" << endl;
00219 
00220             // not attaching, media set will do that for us
00221             // this could generate uncaught exception (#158620)
00222             break;
00223           }
00224           else
00225           {
00226             DBG << "Don't know, let's ABORT" << endl;
00227             ZYPP_RETHROW ( excp );
00228           }
00229         } while( user == media::MediaChangeReport::EJECT );
00230       }
00231 
00232       // retry or change URL
00233     } while( true );
00234 
00235     return media_mgr.localPath( media, file );
00236   }
00237 
00238   media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
00239   {
00240     media::MediaManager media_mgr;
00241 
00242     if (medias.find(medianr) != medias.end())
00243     {
00244       media::MediaAccessId id = medias[medianr];
00245       //if (! noattach && ! media_mgr.isAttached(id))
00246       //media_mgr.attach(id);
00247       return id;
00248     }
00249     Url url;
00250     url = rewriteUrl (_url, medianr);
00251     media::MediaAccessId id = media_mgr.open(url, _path);
00252     //try {
00253     //  MIL << "Adding media verifier" << endl;
00254     //  media_mgr.delVerifier(id);
00255     //  media_mgr.addVerifier(id, _source.verifier(medianr));
00256     //}
00257     //catch (const Exception & excpt_r)
00258     //{
00259     //  ZYPP_CAUGHT(excpt_r);
00260     //  WAR << "Verifier not found" << endl;
00261     //}
00262     medias[medianr] = id;
00263     
00264     //if (! noattach)
00265     //  media_mgr.attach(id);
00266 
00267     return id;
00268   }
00269 
00270   Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
00271   {
00272     std::string scheme = url_r.getScheme();
00273     if (scheme == "cd" || scheme == "dvd")
00274     return url_r;
00275 
00276     DBG << "Rewriting url " << url_r << endl;
00277 
00278     if( scheme == "iso")
00279     {
00280       std::string isofile = url_r.getQueryParam("iso");
00281       boost::regex e("^(.*(cd|dvd))([0-9]+)(\\.iso)$", boost::regex::icase);
00282       boost::smatch what;
00283       if(boost::regex_match(isofile, what, e, boost::match_extra))
00284       {
00285         Url url( url_r);
00286         isofile = what[1] + str::numstring(medianr) + what[4];
00287         url.setQueryParam("iso", isofile);
00288         DBG << "Url rewrite result: " << url << endl;
00289         return url;
00290       }
00291     }
00292     else
00293     {
00294       std::string pathname = url_r.getPathName();
00295       boost::regex e("^(.*(cd|dvd))([0-9]+)(/?)$", boost::regex::icase);
00296       boost::smatch what;
00297       if(boost::regex_match(pathname, what, e, boost::match_extra))
00298       {
00299         Url url( url_r);
00300         pathname = what[1] + str::numstring(medianr) + what[4];
00301         url.setPathName(pathname);
00302         DBG << "Url rewrite result: " << url << endl;
00303         return url;
00304       }
00305     }
00306     return url_r;
00307   }
00308 
00309   std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
00310   {
00311     return str;
00312   }
00313 
00314 //     media::MediaVerifierRef MediaSetAccess::verifier(unsigned media_nr)
00315 //     { return media::MediaVerifierRef(new media::NoVerifier()); }
00316 
00317   MediaVerifier::MediaVerifier(const std::string & vendor_r, const std::string & id_r, const media::MediaNr media_nr)
00318     : _media_vendor(vendor_r)
00319       , _media_id(id_r)
00320       , _media_nr(media_nr)
00321   {}
00322 
00323   bool MediaVerifier::isDesiredMedia(const media::MediaAccessRef &ref)
00324   {
00325     if (_media_vendor.empty() || _media_id.empty())
00326       return true;
00327 
00328       Pathname media_file = "/media." + str::numstring(_media_nr) + "/media";
00329       ref->provideFile (media_file);
00330       media_file = ref->localPath(media_file);
00331       std::ifstream str(media_file.asString().c_str());
00332       std::string vendor;
00333       std::string id;
00334 
00335 #warning check the stream status
00336       getline(str, vendor);
00337       getline(str, id);
00338 
00339       return (vendor == _media_vendor && id == _media_id );
00340   }
00341 
00342 
00344 } // namespace source

Generated on Tue Nov 28 16:49:29 2006 for zypp by  doxygen 1.5.0