From 68d3a70db6bf8bc5bdb97fed883c44795c1f09fd Mon Sep 17 00:00:00 2001 From: Duncan Mac-Vicar P Date: Wed, 5 Jul 2006 16:31:27 +0000 Subject: [PATCH] more progress on fixing horrible broken design: - This class (probably will be renamed later) is what media set always should have been. - basically ripping out code from SourceImpl that not belongs there, togeether with code from MediaSet, and making it not coupled with sources, therefore teteable as a unit. --- zypp/source/SourceMediaAccess.cc | 208 ++++++++++++++++++++++++++++++++++++++- zypp/source/SourceMediaAccess.h | 18 +++- 2 files changed, 222 insertions(+), 4 deletions(-) diff --git a/zypp/source/SourceMediaAccess.cc b/zypp/source/SourceMediaAccess.cc index 46cbe84..1a9a436 100644 --- a/zypp/source/SourceMediaAccess.cc +++ b/zypp/source/SourceMediaAccess.cc @@ -13,6 +13,7 @@ #include #include "zypp/base/LogTools.h" +#include "zypp/ZYppCallbacks.h" #include "zypp/source/SourceMediaAccess.h" //#include "zypp/source/SourceMediaAccessReportReceivers.h" @@ -26,18 +27,219 @@ namespace source { ///////////////////////////////////////////////////////////////// - SourceMediaAccess::SourceMediaAccess( const Url &url, const Pathname &path, std::vector verifiers ) + SourceMediaAccess::SourceMediaAccess( const Url &url, const Pathname &path ) : _url(url), _path(path) { - + std::vector single_media; + single_media[0] = media::MediaVerifierRef(new media::NoVerifier()); + _verifiers = single_media; } SourceMediaAccess::~SourceMediaAccess() { } + + void SourceMediaAccess::setVerifiers( const std::vector &verifiers ) + { + _verifiers = verifiers; + } + + const Pathname SourceMediaAccess::provideFile(const Pathname & file, const unsigned media_nr ) + { + callback::SendReport report; + media::MediaManager media_mgr; + bool checkonly = false; + // get the mediaId, but don't try to attach it here + media::MediaAccessId media = getMediaAccessId( media_nr); + + do + { + try + { + DBG << "Going to try provide file " << file << " from " << media_nr << endl; + // try to attach the media + if ( ! media_mgr.isAttached(media) ) + media_mgr.attach(media); + media_mgr.provideFile (media, file, false, false); + break; + } + catch ( Exception & excp ) + { + ZYPP_CAUGHT(excp); + media::MediaChangeReport::Action user; + do + { + DBG << "Media couldn't provide file " << file << " , releasing." << endl; + try + { + media_mgr.release (media, false); + } + catch (const Exception & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + MIL << "Failed to release media " << media << endl; + } + + MIL << "Releasing all medias of all sources" << endl; + try + { + //zypp::SourceManager::sourceManager()->releaseAllSources(); + } + catch (const zypp::Exception& excpt_r) + { + ZYPP_CAUGHT(excpt_r); + ERR << "Failed to release all sources" << endl; + } + + // set up the reason + media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID; + + if( typeid(excp) == typeid( media::MediaFileNotFoundException ) || + typeid(excp) == typeid( media::MediaNotAFileException ) ) + { + reason = media::MediaChangeReport::NOT_FOUND; + } + else if( typeid(excp) == typeid( media::MediaNotDesiredException) || + typeid(excp) == typeid( media::MediaNotAttachedException) ) + { + reason = media::MediaChangeReport::WRONG; + } + + user = checkonly ? media::MediaChangeReport::ABORT : + report->requestMedia ( + Source_Ref::noSource, + media_nr, + reason, + excp.asUserString() + ); + + DBG << "ProvideFile exception caught, callback answer: " << user << endl; + + if( user == media::MediaChangeReport::ABORT ) + { + DBG << "Aborting" << endl; + ZYPP_RETHROW ( excp ); + } + else if ( user == media::MediaChangeReport::IGNORE ) + { + DBG << "Skipping" << endl; + ZYPP_THROW ( SkipRequestedException("User-requested skipping of a file") ); + } + else if ( user == media::MediaChangeReport::EJECT ) + { + DBG << "Eject: try to release" << endl; + try + { + //zypp::SourceManager::sourceManager()->releaseAllSources(); + } + catch (const zypp::Exception& excpt_r) + { + ZYPP_CAUGHT(excpt_r); + ERR << "Failed to release all sources" << endl; + } + media_mgr.release (media, true); // one more release needed for eject + // FIXME: this will not work, probably + } + else if ( user == media::MediaChangeReport::RETRY || + user == media::MediaChangeReport::CHANGE_URL ) + { + // retry + DBG << "Going to try again" << endl; + + // not attaching, media set will do that for us + // this could generate uncaught exception (#158620) + break; + } + else + { + DBG << "Don't know, let's ABORT" << endl; + ZYPP_RETHROW ( excp ); + } + } while( user == media::MediaChangeReport::EJECT ); + } + + // retry or change URL + } while( true ); + + return media_mgr.localPath( media, file ); + } + + media::MediaAccessId SourceMediaAccess::getMediaAccessId (media::MediaNr medianr) + { + media::MediaManager media_mgr; + + if (medias.find(medianr) != medias.end()) + { + media::MediaAccessId id = medias[medianr]; + //if (! noattach && ! media_mgr.isAttached(id)) + //media_mgr.attach(id); + return id; + } + Url url; + url = rewriteUrl (_url, medianr); + media::MediaAccessId id = media_mgr.open(url, _path); + //try { + // MIL << "Adding media verifier" << endl; + // media_mgr.delVerifier(id); + // media_mgr.addVerifier(id, _source.verifier(medianr)); + //} + //catch (const Exception & excpt_r) + //{ + // ZYPP_CAUGHT(excpt_r); + // WAR << "Verifier not found" << endl; + //} + medias[medianr] = id; - + //if (! noattach) + // media_mgr.attach(id); + + return id; + } + + Url SourceMediaAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr) + { + std::string scheme = url_r.getScheme(); + if (scheme == "cd" || scheme == "dvd") + return url_r; + + DBG << "Rewriting url " << url_r << endl; + + if( scheme == "iso") + { + std::string isofile = url_r.getQueryParam("iso"); + boost::regex e("^(.*(cd|dvd))([0-9]+)(\\.iso)$", boost::regex::icase); + boost::smatch what; + if(boost::regex_match(isofile, what, e, boost::match_extra)) + { + Url url( url_r); + isofile = what[1] + str::numstring(medianr) + what[4]; + url.setQueryParam("iso", isofile); + DBG << "Url rewrite result: " << url << endl; + return url; + } + } + else + { + std::string pathname = url_r.getPathName(); + boost::regex e("^(.*(cd|dvd))([0-9]+)(/?)$", boost::regex::icase); + boost::smatch what; + if(boost::regex_match(pathname, what, e, boost::match_extra)) + { + Url url( url_r); + pathname = what[1] + str::numstring(medianr) + what[4]; + url.setPathName(pathname); + DBG << "Url rewrite result: " << url << endl; + return url; + } + } + return url_r; + } + + std::ostream & SourceMediaAccess::dumpOn( std::ostream & str ) const + { + return str; + } // media::MediaVerifierRef SourceMediaAccess::verifier(unsigned media_nr) // { return media::MediaVerifierRef(new media::NoVerifier()); } diff --git a/zypp/source/SourceMediaAccess.h b/zypp/source/SourceMediaAccess.h index baeb150..709703f 100644 --- a/zypp/source/SourceMediaAccess.h +++ b/zypp/source/SourceMediaAccess.h @@ -55,13 +55,29 @@ namespace zypp friend std::ostream & operator<<( std::ostream & str, const SourceMediaAccess & obj ); public: - SourceMediaAccess( const Url &url, const Pathname &path, std::vector verifiers ); + /** + * creates a callback enabled media access for \param url and \param path. + * with only media no verified + */ + SourceMediaAccess( const Url &url, const Pathname &path ); ~SourceMediaAccess(); + /** + * the media change callbacks depend on the verifiers given for each media. + */ + void setVerifiers( const std::vector &verifiers ); + const Pathname provideFile(const Pathname & file, const unsigned media_nr = 1 ); + protected: + Url rewriteUrl (const Url & url_r, const media::MediaNr medianr); + media::MediaAccessId getMediaAccessId (media::MediaNr medianr); virtual std::ostream & dumpOn( std::ostream & str ) const; private: Url _url; Pathname _path; + std::vector _verifiers; + typedef std::map MediaMap; + /** Mapping between each CD and Media Access ID */ + MediaMap medias; }; /////////////////////////////////////////////////////////////////// -- 2.7.4