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/base/Regex.h"
00015 #include "zypp/base/UserRequestException.h"
00016 #include "zypp/ZYppCallbacks.h"
00017 #include "zypp/MediaSetAccess.h"
00018 #include "zypp/PathInfo.h"
00019 //#include "zypp/source/MediaSetAccessReportReceivers.h"
00020 
00021 using namespace std;
00022 
00024 namespace zypp
00025 { 
00026 
00027 IMPL_PTR_TYPE(MediaSetAccess);
00028 
00030 
00031   MediaSetAccess::MediaSetAccess(const Url &url,
00032                                  const Pathname & prefered_attach_point)
00033       : _url(url),
00034         _prefAttachPoint(prefered_attach_point)
00035   {
00036     MIL << "initializing.." << std::endl;
00037     //std::vector<media::MediaVerifierRef> single_media;
00038     //single_media[0] = media::MediaVerifierRef(new media::NoVerifier());
00039     //_verifiers = single_media;
00040   }
00041 
00042 
00043   MediaSetAccess::~MediaSetAccess()
00044   {
00045     release();
00046   }
00047 
00048 
00049   void MediaSetAccess::setVerifier( unsigned media_nr, media::MediaVerifierRef verifier )
00050   {
00051     if (_medias.find(media_nr) != _medias.end())
00052     {
00053       // the media already exists, set theverifier
00054       media::MediaAccessId id = _medias[media_nr];
00055       media::MediaManager media_mgr;
00056       media_mgr.addVerifier( id, verifier );
00057       // remove any saved verifier for this media
00058       _verifiers.erase(media_nr);
00059       //if (! noattach && ! media_mgr.isAttached(id))
00060       //media_mgr.attach(id);
00061     }
00062     else
00063     {
00064       // save the verifier in the map, and set it when
00065       // the media number is first attached
00066       _verifiers[media_nr] = verifier;
00067     }
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   Pathname MediaSetAccess::provideFile( const OnMediaLocation & on_media_file )
00082   {
00083     return provideFile( on_media_file.filename(), on_media_file.medianr() );
00084   }
00085 
00086 
00087   Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
00088   {
00089     return provideFileInternal( file, media_nr, false, false);
00090   }
00091 
00092   bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
00093   {
00094     callback::SendReport<media::MediaChangeReport> report;
00095     media::MediaManager media_mgr;
00096 
00097     bool exists = false;
00098 
00099     do
00100     {
00101       // get the mediaId, but don't try to attach it here
00102       media::MediaAccessId media = getMediaAccessId( media_nr);
00103 
00104       try
00105       {
00106         DBG << "Cheking if file " << file
00107             << " from media number " << media_nr << " exists." << endl;
00108         // try to attach the media
00109         if ( ! media_mgr.isAttached(media) )
00110           media_mgr.attachDesiredMedia(media);
00111         exists = media_mgr.doesFileExist(media, file);
00112         break;
00113       }
00114       catch ( media::MediaException & excp )
00115       {
00116         ZYPP_CAUGHT(excp);
00117         media::MediaChangeReport::Action user;
00118         do
00119         {
00120           DBG << "Media couldn't provide file " << file << " , releasing." << endl;
00121           try
00122           {
00123             media_mgr.release (media, false);
00124           }
00125           catch (const Exception & excpt_r)
00126           {
00127               ZYPP_CAUGHT(excpt_r);
00128               MIL << "Failed to release media " << media << endl;
00129           }
00130 
00131           // set up the reason
00132           media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00133 
00134           if( typeid(excp) == typeid( media::MediaFileNotFoundException )  ||
00135               typeid(excp) == typeid( media::MediaNotAFileException ) )
00136           {
00137             reason = media::MediaChangeReport::NOT_FOUND;
00138           }
00139           else if( typeid(excp) == typeid( media::MediaNotDesiredException)  ||
00140               typeid(excp) == typeid( media::MediaNotAttachedException) )
00141           {
00142             reason = media::MediaChangeReport::WRONG;
00143           }
00144 
00145           user = report->requestMedia (
00146               _url,
00147               media_nr,
00148               reason,
00149               excp.asUserString()
00150             );
00151 
00152           DBG << "doesFileExist exception caught, callback answer: " << user << endl;
00153 
00154           if( user == media::MediaChangeReport::ABORT )
00155           {
00156             DBG << "Aborting" << endl;
00157             ZYPP_RETHROW ( excp );
00158           }
00159           else if ( user == media::MediaChangeReport::IGNORE )
00160           {
00161             DBG << "Skipping" << endl;
00162             SkipRequestException nexcp("User-requested skipping of a file");
00163             nexcp.remember(excp);
00164             ZYPP_THROW(nexcp);
00165           }
00166           else if ( user == media::MediaChangeReport::EJECT )
00167           {
00168             DBG << "Eject: try to release" << endl;
00169             media_mgr.releaseAll();
00170             media_mgr.release (media, true); // one more release needed for eject
00171           }
00172           else if ( user == media::MediaChangeReport::RETRY  ||
00173             user == media::MediaChangeReport::CHANGE_URL )
00174           {
00175             // retry
00176             DBG << "Going to try again" << endl;
00177             // invalidate current media access id
00178             media_mgr.close(media);
00179             _medias.erase(media_nr);
00180 
00181             // not attaching, media set will do that for us
00182             // this could generate uncaught exception (#158620)
00183             break;
00184           }
00185           else
00186           {
00187             DBG << "Don't know, let's ABORT" << endl;
00188             ZYPP_RETHROW ( excp );
00189           }
00190         } while( user == media::MediaChangeReport::EJECT );
00191       }
00192 
00193       // retry or change URL
00194     } while( true );
00195 
00196     return exists;
00197   }
00198 
00199   Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
00200   {
00201     callback::SendReport<media::MediaChangeReport> report;
00202     media::MediaManager media_mgr;
00203 
00204     media::MediaAccessId media;
00205 
00206     do
00207     {
00208       // get the mediaId, but don't try to attach it here
00209       media = getMediaAccessId( media_nr);
00210 
00211       try
00212       {
00213         DBG << "Going to try to provide file " << file
00214             << " from media number " << media_nr << endl;
00215         // try to attach the media
00216         if ( ! media_mgr.isAttached(media) )
00217           media_mgr.attachDesiredMedia(media);
00218         media_mgr.provideFile (media, file, false, false);
00219         break;
00220       }
00221       catch ( media::MediaException & excp )
00222       {
00223         ZYPP_CAUGHT(excp);
00224         media::MediaChangeReport::Action user;
00225         do
00226         {
00227           DBG << "Media couldn't provide file " << file << " , releasing." << endl;
00228           try
00229           {
00230             media_mgr.release (media, false);
00231           }
00232           catch (const Exception & excpt_r)
00233           {
00234               ZYPP_CAUGHT(excpt_r);
00235               MIL << "Failed to release media " << media << endl;
00236           }
00237 
00238           // set up the reason
00239           media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00240 
00241           if( typeid(excp) == typeid( media::MediaFileNotFoundException )  ||
00242               typeid(excp) == typeid( media::MediaNotAFileException ) )
00243           {
00244             reason = media::MediaChangeReport::NOT_FOUND;
00245           }
00246           else if( typeid(excp) == typeid( media::MediaNotDesiredException)  ||
00247               typeid(excp) == typeid( media::MediaNotAttachedException) )
00248           {
00249             reason = media::MediaChangeReport::WRONG;
00250           }
00251 
00252           user  = checkonly ? media::MediaChangeReport::ABORT :
00253             report->requestMedia (
00254               _url,
00255               media_nr,
00256               reason,
00257               excp.asUserString()
00258             );
00259 
00260           DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00261 
00262           if( user == media::MediaChangeReport::ABORT )
00263           {
00264             DBG << "Aborting" << endl;
00265             ZYPP_RETHROW ( excp );
00266           }
00267           else if ( user == media::MediaChangeReport::IGNORE )
00268           {
00269             DBG << "Skipping" << endl;
00270             SkipRequestException nexcp("User-requested skipping of a file");
00271             nexcp.remember(excp);
00272             ZYPP_THROW(nexcp);
00273           }
00274           else if ( user == media::MediaChangeReport::EJECT )
00275           {
00276             DBG << "Eject: try to release" << endl;
00277             media_mgr.releaseAll();
00278             media_mgr.release (media, true); // one more release needed for eject
00279           }
00280           else if ( user == media::MediaChangeReport::RETRY  ||
00281             user == media::MediaChangeReport::CHANGE_URL )
00282           {
00283             // retry
00284             DBG << "Going to try again" << endl;
00285             // invalidate current media access id
00286             media_mgr.close(media);
00287             _medias.erase(media_nr);
00288 
00289             // not attaching, media set will do that for us
00290             // this could generate uncaught exception (#158620)
00291             break;
00292           }
00293           else
00294           {
00295             DBG << "Don't know, let's ABORT" << endl;
00296             ZYPP_RETHROW ( excp );
00297           }
00298         } while( user == media::MediaChangeReport::EJECT );
00299       }
00300 
00301       // retry or change URL
00302     } while( true );
00303 
00304     return media_mgr.localPath( media, file );
00305   }
00306 
00307 
00308   Pathname MediaSetAccess::provideDir(const Pathname & dir,
00309                                       bool recursive,
00310                                       unsigned media_nr)
00311   {
00312     callback::SendReport<media::MediaChangeReport> report;
00313     media::MediaManager media_mgr;
00314     media::MediaAccessId _media;
00315 
00316     do
00317     {
00318       // get the mediaId, but don't try to attach it here
00319       _media = getMediaAccessId(media_nr);
00320 
00321       try
00322       {
00323         DBG << "Going to try provide direcotry " << dir
00324             << (recursive ? " (recursively)" : "")
00325             << " from media nr. " << media_nr << endl;
00326 
00327         // try to attach the media
00328         if (!media_mgr.isAttached(_media))
00329           media_mgr.attachDesiredMedia(_media);
00330 
00331         _media = getMediaAccessId(media_nr); // in case of redirect
00332 
00333         if (recursive)
00334           media_mgr.provideDirTree(_media, dir);
00335         else
00336           media_mgr.provideDir(_media, dir);
00337 
00338         break; // quit the retry loop
00339       }
00340       catch (media::MediaException & excp)
00341       {
00342         ZYPP_CAUGHT(excp);
00343         media::MediaChangeReport::Action user;
00344 
00345         do
00346         {
00347           DBG << "Media couldn't provide dir " << dir << ", releasing." << endl;
00348           try
00349           {
00350             media_mgr.release (_media, false);
00351           }
00352           catch (const Exception & excpt_r)
00353           {
00354             ZYPP_CAUGHT(excpt_r);
00355             ERR << "Failed to release media " << _media << endl;
00356           }
00357 
00358           //MIL << "Releasing all medias of all sources" << endl;
00359           try
00360           {
00362             //zypp::SourceManager::sourceManager()->releaseAllSources();
00363           }
00364           catch (const zypp::Exception& excpt_r)
00365           {
00366             ZYPP_CAUGHT(excpt_r);
00367             ERR << "Failed to release all sources" << endl;
00368           }
00369 
00370           // set up the reason
00371           media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
00372 
00373           if (typeid(excp) == typeid(media::MediaFileNotFoundException)
00374               || typeid(excp) == typeid(media::MediaNotAFileException))
00375           {
00376             reason = media::MediaChangeReport::NOT_FOUND;
00377           }
00378           else if (typeid(excp) == typeid( media::MediaNotDesiredException)
00379               || typeid(excp) == typeid(media::MediaNotAttachedException))
00380           {
00381             reason = media::MediaChangeReport::WRONG;
00382           }
00383 
00384           user = report->requestMedia(_url,
00385                                       media_nr,
00386                                       reason,
00387                                       excp.asUserString());
00388 
00389           DBG << "ProvideFile exception caught, callback answer: " << user << endl;
00390 
00391           if (user == media::MediaChangeReport::ABORT)
00392           {
00393             DBG << "Aborting" << endl;
00394             ZYPP_RETHROW ( excp );
00395           }
00396           else if (user == media::MediaChangeReport::EJECT)
00397           {
00398             DBG << "Eject: try to release" << endl;
00399             media_mgr.releaseAll();
00400             media_mgr.release (_media, true); // one more release needed for eject
00401           }
00402           else if (user == media::MediaChangeReport::RETRY ||
00403               user == media::MediaChangeReport::CHANGE_URL)
00404           {
00405             // retry
00406             DBG << "Going to try again" << endl;
00407             // invalidate current media access id
00408             media_mgr.close(_media);
00409             _medias.erase(media_nr);
00410 
00411             // not attaching, media set will do that for us
00412             // this could generate uncaught exception (#158620)
00413 
00414             break;
00415           }
00416           else
00417           {
00418             DBG << "Don't know, let's ABORT" << endl;
00419 
00420             ZYPP_RETHROW (excp);
00421           }
00422         }
00423         while (user == media::MediaChangeReport::EJECT);
00424       }
00425       // retry or change URL
00426     }
00427     while (true);
00428 
00429     return media_mgr.localPath(_media, dir);
00430   }
00431 
00432   media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
00433   {
00434     media::MediaManager media_mgr;
00435 
00436     if (_medias.find(medianr) != _medias.end())
00437     {
00438       media::MediaAccessId id = _medias[medianr];
00439       //if (! noattach && ! media_mgr.isAttached(id))
00440       //media_mgr.attach(id);
00441       return id;
00442     }
00443     Url url;
00444     url = rewriteUrl (_url, medianr);
00445     media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
00446     _medias[medianr] = id;
00447 
00448     try
00449     {
00450       if (_verifiers.find(medianr) != _verifiers.end())
00451       {
00452         // a verifier is set for this media
00453         // FIXME check the case where the verifier exists
00454         // but we have no access id for the media
00455         media::MediaAccessId id = _medias[medianr];
00456         media::MediaManager media_mgr;
00457         media_mgr.delVerifier(id);
00458         media_mgr.addVerifier( id, _verifiers[medianr] );
00459         // remove any saved verifier for this media
00460         _verifiers.erase(medianr);
00461       }
00462     }
00463     catch ( const Exception &e )
00464     {
00465       ZYPP_CAUGHT(e);
00466       WAR << "Verifier not found" << endl;
00467     }
00468 
00469     return id;
00470   }
00471 
00472 
00473   Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
00474   {
00475     std::string scheme = url_r.getScheme();
00476     if (scheme == "cd" || scheme == "dvd")
00477       return url_r;
00478 
00479     DBG << "Rewriting url " << url_r << endl;
00480 
00481     if( scheme == "iso")
00482     {
00483       // TODO the iso parameter will not be required in the future, this
00484       // code has to be adapted together with the MediaISO change.
00485       // maybe some MediaISOURL interface should be used.
00486       std::string isofile = url_r.getQueryParam("iso");
00487       str::regex e("^(.*)(cd|dvd)[0-9]+\\.iso$", str::regex::icase);
00488 
00489       str::smatch what;
00490       if(str::regex_match(isofile, what, e))
00491       {
00492         Url url( url_r);
00493         isofile = what[1] + what[2] + str::numstring(medianr) + ".iso";
00494         url.setQueryParam("iso", isofile);
00495         DBG << "Url rewrite result: " << url << endl;
00496         return url;
00497       }
00498     }
00499     else
00500     {
00501       std::string pathname = url_r.getPathName();
00502       str::regex e("^(.*)(cd|dvd)[0-9]+(/)?$", str::regex::icase);
00503       str::smatch what;
00504       if(str::regex_match(pathname, what, e))
00505       {
00506         Url url( url_r);
00507         pathname = what[1] + what[2] + str::numstring(medianr) + what[3];
00508         url.setPathName(pathname);
00509         DBG << "Url rewrite result: " << url << endl;
00510         return url;
00511       }
00512     }
00513     return url_r;
00514   }
00515 
00516   void MediaSetAccess::release()
00517   {
00518     DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
00519     media::MediaManager manager;
00520     for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
00521       manager.release(m->second);
00522   }
00523 
00524   std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
00525   {
00526     str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
00527     return str;
00528   }
00529 
00530 //     media::MediaVerifierRef MediaSetAccess::verifier(unsigned media_nr)
00531 //     { return media::MediaVerifierRef(new media::NoVerifier()); }
00532 
00534 } // namespace zypp

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