more progress on fixing horrible broken design:
authorDuncan Mac-Vicar P <dmacvicar@suse.de>
Wed, 5 Jul 2006 16:31:27 +0000 (16:31 +0000)
committerDuncan Mac-Vicar P <dmacvicar@suse.de>
Wed, 5 Jul 2006 16:31:27 +0000 (16:31 +0000)
- 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
zypp/source/SourceMediaAccess.h

index 46cbe84..1a9a436 100644 (file)
@@ -13,6 +13,7 @@
 #include <fstream>
 
 #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<media::MediaVerifierRef> verifiers )
+  SourceMediaAccess::SourceMediaAccess(  const Url &url, const Pathname &path )
       : _url(url),
         _path(path)
   {
-    
+    std::vector<media::MediaVerifierRef> single_media;
+    single_media[0] = media::MediaVerifierRef(new media::NoVerifier());
+    _verifiers = single_media;
   }
   
   SourceMediaAccess::~SourceMediaAccess()
   {
   }
+
+  void SourceMediaAccess::setVerifiers( const std::vector<media::MediaVerifierRef> &verifiers )
+  {
+    _verifiers = verifiers;
+  }
+
+  const Pathname SourceMediaAccess::provideFile(const Pathname & file, const unsigned media_nr )
+  {
+    callback::SendReport<media::MediaChangeReport> 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()); }
index baeb150..709703f 100644 (file)
@@ -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<media::MediaVerifierRef> 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<media::MediaVerifierRef> &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<media::MediaVerifierRef> _verifiers;
+      typedef std::map<media::MediaNr, media::MediaAccessId> MediaMap;
+      /** Mapping between each CD and Media Access ID */
+      MediaMap medias;
     };
     ///////////////////////////////////////////////////////////////////