/** \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/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"
//////////////////////////////////////////////////////////////////////
namespace zypp
{}
inline void
- checkAttached()
+ checkAttached(MediaAccessId id)
{
if( !handler->isAttached())
{
+ DBG << "checkAttached(" << id << ") not attached" << std::endl;
desired = false;
ZYPP_THROW(MediaNotAttachedException(
handler->url()
}
inline void
- checkDesired()
+ checkDesired(MediaAccessId id)
{
- checkAttached();
+ checkAttached(id);
if( !desired)
{
if( !desired)
{
+ DBG << "checkDesired(" << id << "): not desired (report by "
+ << verifier->info() << ")" << std::endl;
ZYPP_THROW(MediaNotDesiredException(
handler->url()
));
}
- DBG << "checkDesired(): desired (report)" << std::endl;
+ DBG << "checkDesired(" << id << "): desired (report by "
+ << verifier->info() << ")" << std::endl;
} else {
- DBG << "checkDesired(): desired (cached)" << std::endl;
+ DBG << "checkDesired(" << id << "): desired (cached)" << std::endl;
}
}
// -------------------------------------------------------------
typedef std::map<MediaAccessId, ManagedMedia> ManagedMediaMap;
-
////////////////////////////////////////////////////////////////
} // anonymous
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
- class MediaManager::Impl
+ 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:
- MediaAccessId last_accessid;
+ friend class MediaManager;
- public:
- ManagedMediaMap mediaMap;
+ MediaAccessId last_accessid;
+ ManagedMediaMap mediaMap;
- Impl()
+ MediaManager_Impl()
: last_accessid(0)
{}
- ~Impl()
+ public:
+ ~MediaManager_Impl()
{
+ MutexLock glock(g_Mutex);
+
try
{
+ // remove depending (iso) handlers first
+ ManagedMediaMap::iterator it;
+ bool found;
+ do
+ {
+ found = false;
+ for(it = mediaMap.begin(); it != mediaMap.end(); /**/)
+ {
+ if( it->second.handler->dependsOnParent())
+ {
+ found = true;
+ // let it forget its parent, we will
+ // destroy it later (in clear())...
+ it->second.handler->resetParentId();
+ mediaMap.erase( it++ ); // postfix! Incrementing before erase
+ } else {
+ ++it;
+ }
+ }
+ } while(found);
+
+ // remove all other handlers
mediaMap.clear();
}
catch( ... )
return it->second;
}
- inline time_t
- getMountTableMTime() const
+ 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;
}
- inline MountEntries
+ static inline MountEntries
getMountEntries()
{
- return Mount::getEntries("/etc/mtab");
+ return Mount::getEntries();
}
};
//////////////////////////////////////////////////////////////////
// STATIC
- zypp::RW_pointer<MediaManager::Impl> MediaManager::m_impl(NULL);
+ zypp::RW_pointer<MediaManager_Impl> MediaManager::m_impl;
//////////////////////////////////////////////////////////////////
MutexLock glock(g_Mutex);
if( !m_impl)
{
- m_impl.reset( new MediaManager::Impl());
+ m_impl.reset( new MediaManager_Impl());
}
}
{
MutexLock glock(g_Mutex);
- ManagedMedia &ref( m_impl->findMM(accessId));
+ //
+ // The MediaISO handler internally requests an accessId
+ // of a "parent" handler providing the iso file.
+ // The parent handler accessId is private to MediaISO,
+ // but the attached media source may be shared reference.
+ // This means, that if the accessId exactly matches the
+ // parent handler id, close was used on uninitialized
+ // accessId variable (or the accessId was guessed) and
+ // the close request to this id will be rejected here.
+ //
+ ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
+ for( ; m != m_impl->mediaMap.end(); ++m)
+ {
+ if( m->second.handler->dependsOnParent(accessId, true))
+ {
+ ZYPP_THROW(MediaIsSharedException(
+ m->second.handler->url().asString()
+ ));
+ }
+ }
+
+ DBG << "Close to access handler using id "
+ << accessId << " requested" << std::endl;
+ ManagedMedia &ref( m_impl->findMM(accessId));
ref.handler->close();
+
m_impl->mediaMap.erase(accessId);
}
}
// ---------------------------------------------------------------
- // STATIC
- bool
- MediaManager::downloads(const Url &url)
- {
- return MediaAccess::downloads( url);
- }
-
- // ---------------------------------------------------------------
Url
MediaManager::url(MediaAccessId accessId) const
{
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;
}
// ---------------------------------------------------------------
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;
}
// ---------------------------------------------------------------
}
// ---------------------------------------------------------------
- void
- MediaManager::attach(MediaAccessId accessId, bool next)
+ void MediaManager::attach(MediaAccessId accessId)
{
MutexLock glock(g_Mutex);
ManagedMedia &ref( m_impl->findMM(accessId));
- return ref.handler->attach(next);
- }
+ DBG << "attach(id=" << accessId << ")" << std::endl;
- // ---------------------------------------------------------------
- void
- MediaManager::reattach(MediaAccessId accessId,
- const Pathname &attach_point,
- bool temporary)
- {
- MutexLock glock(g_Mutex);
+ // try first mountable/mounted device
+ ref.handler->attach(false);
+ try
+ {
+ ref.checkDesired(accessId);
+ return;
+ }
+ catch (const MediaException & ex)
+ {
+ ZYPP_CAUGHT(ex);
- ManagedMedia &ref( m_impl->findMM(accessId));
+ if (!ref.handler->hasMoreDevices())
+ ZYPP_RETHROW(ex);
- ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
- for( ; m != m_impl->mediaMap.end(); ++m)
+ 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())
{
- // don't allow a reattach if it is the
- // source for an loop mounted ISO file
- if( m->second.handler->dependsOnParent(accessId))
+ try
{
- ZYPP_THROW(MediaIsSharedException(
- m->second.handler->url().asString()
- ));
+ // 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();
}
}
- return ref.handler->reattach(attach_point, temporary);
}
// ---------------------------------------------------------------
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));
- 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
+ // specified with accessId, because it provides the
+ // iso file and it will disappear now (forced release
+ // with eject).
+ //
ManagedMediaMap::iterator m(m_impl->mediaMap.begin());
for( ; m != m_impl->mediaMap.end(); ++m)
{
- if( m->second.handler->dependsOnParent(accessId))
+ if( m->second.handler->dependsOnParent(accessId, false))
{
try
{
- m->second.handler->release(!eject);
+ DBG << "Forcing release of handler depending on access id "
+ << accessId << std::endl;
m->second.desired = false;
+ m->second.handler->release();
}
catch(const MediaException &e)
{
}
}
}
- ref.handler->release(eject);
ref.desired = false;
+ ref.handler->release(ejectDev);
+ }
+
+ // ---------------------------------------------------------------
+ void
+ 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;
}
// ---------------------------------------------------------------
ref.desired = false;
}
}
+ DBG << "isDesiredMedia(" << accessId << "): "
+ << (ref.desired ? "" : "not ")
+ << "desired (report by "
+ << ref.verifier->info() << ")" << std::endl;
return ref.desired;
}
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
{
// ---------------------------------------------------------------
void
MediaManager::provideFile(MediaAccessId accessId,
- const Pathname &filename,
- bool cached,
- bool checkonly) const
+ const Pathname &filename ) const
+ {
+ MutexLock glock(g_Mutex);
+
+ ManagedMedia &ref( m_impl->findMM(accessId));
+
+ ref.checkDesired(accessId);
+
+ ref.handler->provideFile(filename);
+ }
+
+ // ---------------------------------------------------------------
+ void
+ MediaManager::setDeltafile(MediaAccessId accessId,
+ const Pathname &filename ) const
{
MutexLock glock(g_Mutex);
ManagedMedia &ref( m_impl->findMM(accessId));
- ref.checkDesired();
+ ref.checkDesired(accessId);
- ref.handler->provideFile(filename, cached, checkonly);
+ ref.handler->setDeltafile(filename);
}
// ---------------------------------------------------------------
ManagedMedia &ref( m_impl->findMM(accessId));
- ref.checkDesired();
+ ref.checkDesired(accessId);
ref.handler->provideDir(dirname);
}
ManagedMedia &ref( m_impl->findMM(accessId));
- ref.checkDesired();
+ ref.checkDesired(accessId);
ref.handler->provideDirTree(dirname);
}
ManagedMedia &ref( m_impl->findMM(accessId));
- ref.checkAttached();
+ ref.checkAttached(accessId);
ref.handler->releaseFile(filename);
}
ManagedMedia &ref( m_impl->findMM(accessId));
- ref.checkAttached();
+ ref.checkAttached(accessId);
ref.handler->releaseDir(dirname);
}
ManagedMedia &ref( m_impl->findMM(accessId));
- ref.checkAttached();
+ ref.checkAttached(accessId);
ref.handler->releasePath(pathname);
}
ManagedMedia &ref( m_impl->findMM(accessId));
- // FIXME: ref.checkDesired(); ???
- ref.checkAttached();
+ // FIXME: ref.checkDesired(accessId); ???
+ ref.checkAttached(accessId);
ref.handler->dirInfo(retlist, dirname, dots);
}
ManagedMedia &ref( m_impl->findMM(accessId));
- // FIXME: ref.checkDesired(); ???
- ref.checkAttached();
+ // FIXME: ref.checkDesired(accessId); ???
+ ref.checkAttached(accessId);
ref.handler->dirInfo(retlist, dirname, dots);
}
// ---------------------------------------------------------------
- time_t
- MediaManager::getMountTableMTime() const
+ bool
+ MediaManager::doesFileExist(MediaAccessId accessId, const Pathname & filename ) const
+ {
+ MutexLock glock(g_Mutex);
+ 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
{
MutexLock glock(g_Mutex);
+ ManagedMedia &ref( m_impl->findMM(accessId));
+ return ref.handler->getDetectedDevices(devices, index);
+ }
- return m_impl->getMountTableMTime();
+ // ---------------------------------------------------------------
+ // STATIC
+ time_t
+ MediaManager::getMountTableMTime()
+ {
+ MutexLock glock(g_Mutex);
+ return MediaManager_Impl::getMountTableMTime();
}
// ---------------------------------------------------------------
+ // STATIC
MountEntries
- MediaManager::getMountEntries() const
+ MediaManager::getMountEntries()
{
MutexLock glock(g_Mutex);
- return m_impl->getMountEntries();
+ 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;
}
}
+ if( !mtab)
+ return true;
+
//
// check against system mount entries
//
return false;
}
}
+
return true;
}
// ---------------------------------------------------------------
void
- MediaManager::forceMediaRelease(const MediaSourceRef &media)
+ MediaManager::forceReleaseShared(const MediaSourceRef &media)
{
MutexLock glock(g_Mutex);
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;
}
}