Imported Upstream version 17.13.0
[platform/upstream/libzypp.git] / zypp / media / MediaManager.cc
index 2aac698..28202ac 100644 (file)
@@ -9,22 +9,20 @@
 /** \file zypp/media/MediaManager.cc
  *
 */
-#include <zypp/media/MediaException.h>
-#include <zypp/media/MediaManager.h>
-#include <zypp/media/MediaHandler.h>
-#include <zypp/media/Mount.h>
-#include <zypp/thread/Mutex.h>
-#include <zypp/thread/MutexLock.h>
-
-#include <zypp/base/String.h>
-#include <zypp/base/Logger.h>
-#include <zypp/Pathname.h>
-#include <zypp/PathInfo.h>
-
 #include <map>
 #include <list>
 #include <iostream>
+#include <typeinfo>
+
+#include "zypp/media/MediaException.h"
+#include "zypp/media/MediaManager.h"
+#include "zypp/media/MediaHandler.h"
+#include "zypp/media/Mount.h"
 
+#include "zypp/base/String.h"
+#include "zypp/base/Logger.h"
+#include "zypp/Pathname.h"
+#include "zypp/PathInfo.h"
 
 //////////////////////////////////////////////////////////////////////
 namespace zypp
@@ -34,19 +32,10 @@ namespace zypp
   namespace media
   { //////////////////////////////////////////////////////////////////
 
-    using zypp::thread::Mutex;
-    using zypp::thread::MutexLock;
-
     //////////////////////////////////////////////////////////////////
     namespace // anonymous
     { ////////////////////////////////////////////////////////////////
 
-
-      // -------------------------------------------------------------
-      // STATIC
-      static Mutex  g_Mutex;
-
-
       // -------------------------------------------------------------
       struct ManagedMedia
       {
@@ -82,30 +71,29 @@ namespace zypp
           }
         }
 
-        inline void
-        checkDesired(MediaAccessId id)
+        inline void checkDesired( MediaAccessId id )
         {
-          checkAttached(id);
+          checkAttached( id );
 
-          if( !desired)
+          if ( !desired )
           {
             try {
               desired = verifier->isDesiredMedia(handler);
-            }
-            catch(const zypp::Exception &e) {
-              ZYPP_CAUGHT(e);
-              desired = false;
+            } catch ( const zypp::Exception &e ) {
+                ZYPP_CAUGHT( e );
+
+                media::MediaNotDesiredException newEx ( handler->url() );
+                newEx.remember( e );
+                ZYPP_THROW( newEx );
             }
 
-            if( !desired)
+            if( !desired )
             {
-              DBG << "checkDesired(" << id << "): not desired" << std::endl;
-              ZYPP_THROW(MediaNotDesiredException(
-                handler->url()
-              ));
+              DBG << "checkDesired(" << id << "): not desired (report by " << verifier->info() << ")" << std::endl;
+              ZYPP_THROW( MediaNotDesiredException( handler->url() ) );
             }
 
-            DBG << "checkDesired(" << id << "): desired (report)" << std::endl;
+            DBG << "checkDesired(" << id << "): desired (report by " << verifier->info() << ")" << std::endl;
           } else {
             DBG << "checkDesired(" << id << "): desired (cached)" << std::endl;
           }
@@ -120,20 +108,35 @@ namespace zypp
       // -------------------------------------------------------------
       typedef std::map<MediaAccessId, ManagedMedia> ManagedMediaMap;
 
-
       ////////////////////////////////////////////////////////////////
     } // anonymous
     //////////////////////////////////////////////////////////////////
 
 
     //////////////////////////////////////////////////////////////////
+    std::string
+    MediaVerifierBase::info() const
+    {
+      return std::string(typeid((*this)).name());
+    }
+
+
+    //////////////////////////////////////////////////////////////////
+    std::string
+    NoVerifier::info() const
+    {
+      return std::string("zypp::media::NoVerifier");
+    }
+
+
+    //////////////////////////////////////////////////////////////////
     class MediaManager_Impl
     {
     private:
       friend class MediaManager;
 
-      MediaAccessId   last_accessid;
-      ManagedMediaMap mediaMap;
+      MediaAccessId       last_accessid;
+      ManagedMediaMap     mediaMap;
 
       MediaManager_Impl()
         : last_accessid(0)
@@ -142,8 +145,6 @@ namespace zypp
     public:
       ~MediaManager_Impl()
       {
-        MutexLock glock(g_Mutex);
-
         try
         {
           // remove depending (iso) handlers first
@@ -152,7 +153,7 @@ namespace zypp
           do
           {
             found = false;
-            for(it = mediaMap.begin(); it != mediaMap.end(); ++it)
+            for(it = mediaMap.begin(); it != mediaMap.end(); /**/)
             {
               if( it->second.handler->dependsOnParent())
               {
@@ -160,7 +161,9 @@ namespace zypp
                 // let it forget its parent, we will
                 // destroy it later (in clear())...
                 it->second.handler->resetParentId();
-                mediaMap.erase(it);
+                mediaMap.erase( it++ ); // postfix! Incrementing before erase
+              } else {
+                ++it;
               }
             }
           } while(found);
@@ -200,13 +203,19 @@ namespace zypp
       static inline time_t
       getMountTableMTime()
       {
-        return zypp::PathInfo("/etc/mtab").mtime();
+        time_t mtime = zypp::PathInfo("/etc/mtab").mtime();
+        if( mtime <= 0)
+        {
+          WAR << "Failed to retrieve modification time of '/etc/mtab'"
+              << std::endl;
+        }
+        return mtime;
       }
 
       static inline MountEntries
       getMountEntries()
       {
-        return Mount::getEntries("/etc/mtab");
+        return Mount::getEntries();
       }
 
     };
@@ -214,13 +223,12 @@ namespace zypp
 
     //////////////////////////////////////////////////////////////////
     // STATIC
-    zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl(NULL);
+    zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl;
 
 
     //////////////////////////////////////////////////////////////////
     MediaManager::MediaManager()
     {
-      MutexLock glock(g_Mutex);
       if( !m_impl)
       {
         m_impl.reset( new MediaManager_Impl());
@@ -236,8 +244,6 @@ namespace zypp
     MediaAccessId
     MediaManager::open(const Url &url, const Pathname &preferred_attach_point)
     {
-      MutexLock glock(g_Mutex);
-
       // create new access handler for it
       MediaAccessRef handler( new MediaAccess());
       MediaVerifierRef verifier( new NoVerifier());
@@ -258,8 +264,6 @@ namespace zypp
     void
     MediaManager::close(MediaAccessId accessId)
     {
-      MutexLock glock(g_Mutex);
-
       //
       // The MediaISO handler internally requests an accessId
       // of a "parent" handler providing the iso file.
@@ -294,8 +298,6 @@ namespace zypp
     bool
     MediaManager::isOpen(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMediaMap::iterator it( m_impl->mediaMap.find(accessId));
       return it != m_impl->mediaMap.end() &&
              it->second.handler->isOpen();
@@ -305,8 +307,6 @@ namespace zypp
     std::string
     MediaManager::protocol(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       return ref.handler->protocol();
@@ -316,27 +316,15 @@ namespace zypp
          bool
     MediaManager::downloads(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       return ref.handler->downloads();
     }
 
     // ---------------------------------------------------------------
-    // STATIC
-    bool
-    MediaManager::downloads(const Url &url)
-    {
-      return MediaAccess::downloads( url);
-    }
-
-    // ---------------------------------------------------------------
     Url
     MediaManager::url(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       return ref.handler->url();
@@ -347,62 +335,118 @@ namespace zypp
     MediaManager::addVerifier(MediaAccessId           accessId,
                               const MediaVerifierRef &verifier)
     {
-      MutexLock glock(g_Mutex);
-
       if( !verifier)
         ZYPP_THROW(MediaException("Invalid verifier reference"));
 
       ManagedMedia &ref( m_impl->findMM(accessId));
 
-      MediaVerifierRef(verifier).swap(ref.verifier);
       ref.desired = false;
+      MediaVerifierRef(verifier).swap(ref.verifier);
+
+      DBG << "MediaVerifier change: id=" << accessId << ", verifier="
+          << verifier->info() << std::endl;
     }
 
     // ---------------------------------------------------------------
     void
     MediaManager::delVerifier(MediaAccessId accessId)
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       MediaVerifierRef verifier( new NoVerifier());
-      ref.verifier.swap(verifier);
       ref.desired  = false;
+      ref.verifier.swap(verifier);
+
+      DBG << "MediaVerifier change: id=" << accessId << ", verifier="
+          << verifier->info() << std::endl;
     }
 
     // ---------------------------------------------------------------
     bool
     MediaManager::setAttachPrefix(const Pathname &attach_prefix)
     {
-      MutexLock glock(g_Mutex);
-
       return MediaHandler::setAttachPrefix(attach_prefix);
     }
 
     // ---------------------------------------------------------------
-    void
-    MediaManager::attach(MediaAccessId accessId, bool next)
+    void MediaManager::attach(MediaAccessId accessId)
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       DBG << "attach(id=" << accessId << ")" << std::endl;
-      return ref.handler->attach(next);
+
+      // try first mountable/mounted device
+      ref.handler->attach(false);
+      try
+      {
+        ref.checkDesired(accessId);
+        return;
+      }
+      catch (const MediaException & ex)
+      {
+        ZYPP_CAUGHT(ex);
+
+        if (!ref.handler->hasMoreDevices())
+          ZYPP_RETHROW(ex);
+
+        if (ref.handler->isAttached())
+          ref.handler->release();
+      }
+
+      MIL << "checkDesired(" << accessId << ") of first device failed,"
+        " going to try others with attach(true)" << std::endl;
+
+      while (ref.handler->hasMoreDevices())
+      {
+        try
+        {
+          // try to attach next device
+          ref.handler->attach(true);
+          ref.checkDesired(accessId);
+          return;
+        }
+        catch (const MediaNotDesiredException & ex)
+        {
+          ZYPP_CAUGHT(ex);
+
+          if (!ref.handler->hasMoreDevices())
+          {
+            MIL << "No desired media found after trying all detected devices." << std::endl;
+            ZYPP_RETHROW(ex);
+          }
+
+          AttachedMedia media(ref.handler->attachedMedia());
+          DBG << "Skipping " << media.mediaSource->asString() << ": not desired media." << std::endl;
+
+          ref.handler->release();
+        }
+        catch (const MediaException & ex)
+        {
+          ZYPP_CAUGHT(ex);
+
+          if (!ref.handler->hasMoreDevices())
+            ZYPP_RETHROW(ex);
+
+          AttachedMedia media(ref.handler->attachedMedia());
+          DBG << "Skipping " << media.mediaSource->asString() << " because of exception thrown by attach(true)" << std::endl;
+
+          if (ref.handler->isAttached()) ref.handler->release();
+        }
+      }
     }
 
     // ---------------------------------------------------------------
     void
-    MediaManager::release(MediaAccessId accessId, bool eject)
+    MediaManager::release(MediaAccessId accessId, const std::string & ejectDev)
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
-      DBG << "release(id=" << accessId
-          << (eject ? ", eject)" : ")") << std::endl;
-      if( eject)
+      DBG << "release(id=" << accessId;
+      if (!ejectDev.empty())
+        DBG << ", " << ejectDev;
+      DBG << ")" << std::endl;
+
+      if(!ejectDev.empty())
       {
         //
         // release MediaISO handlers, that are using the one
@@ -419,8 +463,8 @@ namespace zypp
             {
               DBG << "Forcing release of handler depending on access id "
                   << accessId << std::endl;
-              m->second.handler->release(!eject);
               m->second.desired  = false;
+              m->second.handler->release();
             }
             catch(const MediaException &e)
             {
@@ -429,16 +473,49 @@ namespace zypp
           }
         }
       }
-      ref.handler->release(eject);
       ref.desired  = false;
+      ref.handler->release(ejectDev);
     }
 
     // ---------------------------------------------------------------
     void
-    MediaManager::disconnect(MediaAccessId accessId)
+    MediaManager::releaseAll()
     {
-      MutexLock glock(g_Mutex);
+      MIL << "Releasing all attached media" << std::endl;
 
+      ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
+      for( ; m != m_impl->mediaMap.end(); ++m)
+      {
+        if( m->second.handler->dependsOnParent())
+          continue;
+
+        try
+        {
+          if(m->second.handler->isAttached())
+          {
+            DBG << "Releasing media id " << m->first << std::endl;
+            m->second.desired  = false;
+            m->second.handler->release();
+          }
+          else
+          {
+            DBG << "Media id " << m->first << " not attached " << std::endl;
+          }
+        }
+        catch(const MediaException & e)
+        {
+          ZYPP_CAUGHT(e);
+          ERR << "Failed to release media id " << m->first << std::endl;
+        }
+      }
+
+      MIL << "Exit" << std::endl;
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::disconnect(MediaAccessId accessId)
+    {
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.handler->disconnect();
@@ -448,8 +525,6 @@ namespace zypp
     bool
     MediaManager::isAttached(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       return ref.handler->isAttached();
@@ -458,8 +533,6 @@ namespace zypp
     // ---------------------------------------------------------------
     bool MediaManager::isSharedMedia(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       return ref.handler->isSharedMedia();
@@ -469,8 +542,6 @@ namespace zypp
     bool
     MediaManager::isDesiredMedia(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       if( !ref.handler->isAttached())
@@ -487,6 +558,10 @@ namespace zypp
           ref.desired = false;
         }
       }
+      DBG << "isDesiredMedia(" << accessId << "): "
+          << (ref.desired ? "" : "not ")
+          << "desired (report by "
+          << ref.verifier->info() << ")" << std::endl;
       return ref.desired;
     }
 
@@ -495,8 +570,6 @@ namespace zypp
     MediaManager::isDesiredMedia(MediaAccessId           accessId,
                                  const MediaVerifierRef &verifier) const
     {
-      MutexLock glock(g_Mutex);
-
       MediaVerifierRef v(verifier);
       if( !v)
         ZYPP_THROW(MediaException("Invalid verifier reference"));
@@ -514,15 +587,24 @@ namespace zypp
           desired = false;
         }
       }
+      DBG << "isDesiredMedia(" << accessId << "): "
+          << (desired ? "" : "not ")
+          << "desired (report by "
+          << v->info() << ")" << std::endl;
       return desired;
     }
 
     // ---------------------------------------------------------------
+    bool
+    MediaManager::isChangeable(MediaAccessId accessId)
+    {
+      return url(accessId).getScheme() == "cd" || url(accessId).getScheme() == "dvd";
+    }
+
+    // ---------------------------------------------------------------
     Pathname
     MediaManager::localRoot(MediaAccessId accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       Pathname path;
@@ -535,8 +617,6 @@ namespace zypp
     MediaManager::localPath(MediaAccessId accessId,
                             const Pathname & pathname) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       Pathname path;
@@ -544,20 +624,36 @@ namespace zypp
       return path;
     }
 
-    // ---------------------------------------------------------------
     void
     MediaManager::provideFile(MediaAccessId   accessId,
                               const Pathname &filename,
-                              bool            cached,
-                              bool            checkonly) const
+                              const ByteCount &expectedFileSize ) const
+    {
+      ManagedMedia &ref( m_impl->findMM(accessId));
+
+      ref.checkDesired(accessId);
+
+      ref.handler->provideFile(filename, expectedFileSize);
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::provideFile(MediaAccessId   accessId,
+                              const Pathname &filename ) const
     {
-      MutexLock glock(g_Mutex);
+      provideFile( accessId, filename, 0);
+    }
 
+    // ---------------------------------------------------------------
+    void
+    MediaManager::setDeltafile(MediaAccessId   accessId,
+                              const Pathname &filename ) const
+    {
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.checkDesired(accessId);
 
-      ref.handler->provideFile(filename, cached, checkonly);
+      ref.handler->setDeltafile(filename);
     }
 
     // ---------------------------------------------------------------
@@ -565,8 +661,6 @@ namespace zypp
     MediaManager::provideDir(MediaAccessId   accessId,
                              const Pathname &dirname) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.checkDesired(accessId);
@@ -579,8 +673,6 @@ namespace zypp
     MediaManager::provideDirTree(MediaAccessId   accessId,
                                  const Pathname &dirname) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.checkDesired(accessId);
@@ -593,8 +685,6 @@ namespace zypp
     MediaManager::releaseFile(MediaAccessId   accessId,
                               const Pathname &filename) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.checkAttached(accessId);
@@ -607,8 +697,6 @@ namespace zypp
     MediaManager::releaseDir(MediaAccessId   accessId,
                              const Pathname &dirname) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.checkAttached(accessId);
@@ -622,8 +710,6 @@ namespace zypp
     MediaManager::releasePath(MediaAccessId   accessId,
                               const Pathname &pathname) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       ref.checkAttached(accessId);
@@ -638,8 +724,6 @@ namespace zypp
                           const Pathname         &dirname,
                           bool                    dots) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       // FIXME: ref.checkDesired(accessId); ???
@@ -655,8 +739,6 @@ namespace zypp
                           const Pathname         &dirname,
                           bool                    dots) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       // FIXME: ref.checkDesired(accessId); ???
@@ -666,11 +748,32 @@ namespace zypp
     }
 
     // ---------------------------------------------------------------
+    bool
+    MediaManager::doesFileExist(MediaAccessId  accessId, const Pathname & filename ) const
+    {
+      ManagedMedia &ref( m_impl->findMM(accessId));
+
+      // FIXME: ref.checkDesired(accessId); ???
+      ref.checkAttached(accessId);
+
+      return ref.handler->doesFileExist(filename);
+    }
+
+    // ---------------------------------------------------------------
+    void
+    MediaManager::getDetectedDevices(MediaAccessId accessId,
+                                     std::vector<std::string> & devices,
+                                     unsigned int & index) const
+    {
+      ManagedMedia &ref( m_impl->findMM(accessId));
+      return ref.handler->getDetectedDevices(devices, index);
+    }
+
+    // ---------------------------------------------------------------
     // STATIC
     time_t
     MediaManager::getMountTableMTime()
     {
-      MutexLock glock(g_Mutex);
       return MediaManager_Impl::getMountTableMTime();
     }
 
@@ -679,20 +782,17 @@ namespace zypp
     MountEntries
     MediaManager::getMountEntries()
     {
-      MutexLock glock(g_Mutex);
-
       return MediaManager_Impl::getMountEntries();
     }
 
     // ---------------------------------------------------------------
     bool
-    MediaManager::isUseableAttachPoint(const Pathname &path) const
+    MediaManager::isUseableAttachPoint(const Pathname &path,
+                                       bool            mtab) const
     {
       if( path.empty() || path == "/" || !PathInfo(path).isDir())
         return false;
 
-      MutexLock glock(g_Mutex);
-
       //
       // check against our current attach points
       //
@@ -722,6 +822,9 @@ namespace zypp
         }
       }
 
+      if( !mtab)
+        return true;
+
       //
       // check against system mount entries
       //
@@ -747,6 +850,7 @@ namespace zypp
           return false;
         }
       }
+
       return true;
     }
 
@@ -754,8 +858,6 @@ namespace zypp
     AttachedMedia
     MediaManager::getAttachedMedia(MediaAccessId &accessId) const
     {
-      MutexLock glock(g_Mutex);
-
       ManagedMedia &ref( m_impl->findMM(accessId));
 
       return ref.handler->attachedMedia();
@@ -765,8 +867,6 @@ namespace zypp
     AttachedMedia
     MediaManager::findAttachedMedia(const MediaSourceRef &media) const
     {
-      MutexLock glock(g_Mutex);
-
       if( !media || media->type.empty())
         return AttachedMedia();
 
@@ -787,8 +887,6 @@ namespace zypp
     void
     MediaManager::forceReleaseShared(const MediaSourceRef &media)
     {
-      MutexLock glock(g_Mutex);
-
       if( !media || media->type.empty())
         return;
 
@@ -801,7 +899,7 @@ namespace zypp
         AttachedMedia ret = m->second.handler->attachedMedia();
         if( ret.mediaSource && ret.mediaSource->equals( *media))
         {
-          m->second.handler->release(false);
+          m->second.handler->release();
           m->second.desired  = false;
         }
       }