Commit 0696650a authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

fs: Get rid of static device cache/listers

Let the FS factory handle device creation, be it from a cache or not
parent 0d18ec76
......@@ -53,6 +53,12 @@ namespace factory
///
virtual std::shared_ptr<fs::IDevice> createDevice( const std::string& uuid ) = 0;
///
/// \brief createDeviceFromPath creates a representation of a device
/// \param path A path.
/// \return A representation of the device.
///
virtual std::shared_ptr<fs::IDevice> createDeviceFromPath( const std::string& path ) = 0;
///
/// \brief refresh Will cause any FS cache to be refreshed.
///
virtual void refresh() = 0;
......
......@@ -40,6 +40,9 @@
# error No filesystem implementation for this architecture
#endif
#include "medialibrary/IDeviceLister.h"
#include "compat/Mutex.h"
namespace medialibrary
{
......@@ -47,8 +50,8 @@ namespace factory
{
FileSystemFactory::FileSystemFactory( DeviceListerPtr lister )
: m_deviceLister( lister )
{
fs::Device::setDeviceLister( lister );
}
std::shared_ptr<fs::IDirectory> FileSystemFactory::createDirectory( const std::string& path )
......@@ -59,7 +62,7 @@ std::shared_ptr<fs::IDirectory> FileSystemFactory::createDirectory( const std::s
return it->second;
try
{
auto dir = std::make_shared<fs::Directory>( path );
auto dir = std::make_shared<fs::Directory>( path, *this );
m_dirs[path] = dir;
return dir;
}
......@@ -72,13 +75,47 @@ std::shared_ptr<fs::IDirectory> FileSystemFactory::createDirectory( const std::s
std::shared_ptr<fs::IDevice> FileSystemFactory::createDevice( const std::string& uuid )
{
return fs::Device::fromUuid( uuid );
auto lock = m_deviceCache.lock();
auto it = m_deviceCache.get().find( uuid );
if ( it != end( m_deviceCache.get() ) )
return it->second;
return nullptr;
}
std::shared_ptr<fs::IDevice> FileSystemFactory::createDeviceFromPath( const std::string& path )
{
auto lock = m_deviceCache.lock();
std::shared_ptr<fs::IDevice> res;
for ( const auto& p : m_deviceCache.get() )
{
if ( path.find( p.second->mountpoint() ) == 0 )
{
if ( res == nullptr || res->mountpoint().length() < p.second->mountpoint().length() )
res = p.second;
}
}
return res;
}
void FileSystemFactory::refresh()
{
std::lock_guard<compat::Mutex> lock( m_mutex );
m_dirs.clear();
{
std::lock_guard<compat::Mutex> lock( m_mutex );
m_dirs.clear();
}
auto lock = m_deviceCache.lock();
if ( m_deviceCache.isCached() == false )
m_deviceCache = DeviceCacheMap{};
m_deviceCache.get().clear();
auto devices = m_deviceLister->devices();
for ( const auto& d : devices )
{
const auto& uuid = std::get<0>( d );
const auto& mountpoint = std::get<1>( d );
const auto removable = std::get<2>( d );
m_deviceCache.get().emplace( uuid, std::make_shared<fs::Device>( uuid, mountpoint, removable ) );
}
}
}
......
......@@ -25,6 +25,7 @@
#include "compat/Mutex.h"
#include "factory/IFileSystem.h"
#include "medialibrary/Types.h"
#include "utils/Cache.h"
#include <string>
#include <unordered_map>
......@@ -36,15 +37,22 @@ namespace factory
{
class FileSystemFactory : public IFileSystem
{
// UUID -> Device instance map
using DeviceCacheMap = std::unordered_map<std::string, std::shared_ptr<fs::IDevice>>;
public:
FileSystemFactory( DeviceListerPtr lister );
virtual std::shared_ptr<fs::IDirectory> createDirectory( const std::string& path ) override;
virtual std::shared_ptr<fs::IDevice> createDevice( const std::string& uuid ) override;
virtual std::shared_ptr<fs::IDevice> createDeviceFromPath( const std::string& path ) override;
virtual void refresh() override;
private:
std::unordered_map<std::string, std::shared_ptr<fs::IDirectory>> m_dirs;
compat::Mutex m_mutex;
DeviceListerPtr m_deviceLister;
Cache<DeviceCacheMap> m_deviceCache;
};
}
......
......@@ -25,7 +25,7 @@
#endif
#include "CommonDirectory.h"
#include "factory/IFileSystem.h"
#include "utils/Filename.h"
#include <dirent.h>
#include <cerrno>
......@@ -36,8 +36,10 @@ namespace medialibrary
namespace fs
{
medialibrary::fs::CommonDirectory::CommonDirectory(const std::string& path)
medialibrary::fs::CommonDirectory::CommonDirectory( const std::string& path,
factory::IFileSystem& fsFactory )
: m_path( path )
, m_fsFactory( fsFactory )
{
if ( *m_path.crbegin() != '/' )
m_path += '/';
......@@ -62,6 +64,15 @@ const std::vector<std::shared_ptr<IDirectory>>& CommonDirectory::dirs() const
return m_dirs;
}
std::shared_ptr<IDevice> CommonDirectory::device() const
{
auto lock = m_device.lock();
if ( m_device.isCached() == false )
m_device = m_fsFactory.createDeviceFromPath( m_path );
return m_device.get();
}
std::string CommonDirectory::toAbsolute( const std::string& path )
{
char abs[PATH_MAX];
......
......@@ -27,16 +27,20 @@
namespace medialibrary
{
namespace factory { class IFileSystem; }
namespace fs
{
class CommonDirectory : public IDirectory
{
public:
CommonDirectory( const std::string& path );
CommonDirectory( const std::string& path, factory::IFileSystem& fsFactory );
virtual const std::string& path() const override;
virtual const std::vector<std::shared_ptr<IFile>>& files() const override;
virtual const std::vector<std::shared_ptr<IDirectory>>& dirs() const override;
virtual std::shared_ptr<IDevice> device() const override;
protected:
virtual void read() const = 0;
......@@ -47,6 +51,7 @@ protected:
mutable std::vector<std::shared_ptr<IFile>> m_files;
mutable std::vector<std::shared_ptr<IDirectory>> m_dirs;
mutable Cache<std::shared_ptr<IDevice>> m_device;
factory::IFileSystem& m_fsFactory;
};
}
......
......@@ -27,17 +27,6 @@
#include "Device.h"
#include "Directory.h"
#include "logging/Logger.h"
#include "medialibrary/IDeviceLister.h"
namespace
{
// Allow private ctors to be used from make_shared
struct DeviceBuilder : public medialibrary::fs::Device
{
template <typename... Args>
DeviceBuilder( Args&&... args ) : Device( std::forward<Args>( args )... ) {}
};
}
namespace medialibrary
{
......@@ -45,9 +34,6 @@ namespace medialibrary
namespace fs
{
Cache<Device::DeviceCacheMap> Device::DeviceCache;
DeviceListerPtr Device::DeviceLister;
Device::Device( const std::string& uuid, const std::string& mountpoint, bool isRemovable )
: m_uuid( uuid )
, m_mountpoint( mountpoint )
......@@ -78,59 +64,6 @@ const std::string&Device::mountpoint() const
return m_mountpoint;
}
std::shared_ptr<IDevice> Device::fromPath( const std::string& path )
{
auto lock = DeviceCache.lock();
std::shared_ptr<IDevice> res;
for ( const auto& p : DeviceCache.get() )
{
if ( path.find( p.second->mountpoint() ) == 0 )
{
if ( res == nullptr || res->mountpoint().length() < p.second->mountpoint().length() )
res = p.second;
}
}
return res;
}
std::shared_ptr<IDevice> Device::fromUuid( const std::string& uuid )
{
auto lock = DeviceCache.lock();
auto it = DeviceCache.get().find( uuid );
if ( it != end( DeviceCache.get() ) )
return it->second;
return nullptr;
}
void Device::setDeviceLister( DeviceListerPtr lister )
{
auto lock = DeviceCache.lock();
DeviceLister = lister;
refreshDeviceCacheLocked();
}
void Device::refreshDeviceCache()
{
auto lock = DeviceCache.lock();
refreshDeviceCacheLocked();
}
void Device::refreshDeviceCacheLocked()
{
if ( DeviceCache.isCached() == false )
DeviceCache = DeviceCacheMap{};
DeviceCache.get().clear();
auto devices = DeviceLister->devices();
for ( const auto& d : devices )
{
const auto& uuid = std::get<0>( d );
const auto& mountpoint = std::get<1>( d );
const auto removable = std::get<2>( d );
DeviceCache.get().emplace( uuid, std::make_shared<DeviceBuilder>( uuid, mountpoint, removable ) );
}
}
}
}
......@@ -24,7 +24,6 @@
#include "filesystem/IDevice.h"
#include "medialibrary/Types.h"
#include "utils/Cache.h"
#include <memory>
#include <unordered_map>
......@@ -37,34 +36,13 @@ namespace fs
class Device : public IDevice
{
// UUID -> Device instance map
using DeviceCacheMap = std::unordered_map<std::string, std::shared_ptr<IDevice>>;
public:
Device( const std::string& uuid, const std::string& mountpoint, bool isRemovable );
virtual const std::string& uuid() const override;
virtual bool isRemovable() const override;
virtual bool isPresent() const override;
virtual const std::string& mountpoint() const override;
///
/// \brief fromPath Returns the device that contains the given path
///
static std::shared_ptr<IDevice> fromPath( const std::string& path );
static std::shared_ptr<IDevice> fromUuid( const std::string& uuid );
static void setDeviceLister( DeviceListerPtr lister );
static void refreshDeviceCache();
protected:
Device( const std::string& uuid, const std::string& mountpoint, bool isRemovable );
private:
static void refreshDeviceCacheLocked();
private:
static Cache<DeviceCacheMap> DeviceCache;
static DeviceListerPtr DeviceLister;
private:
std::string m_uuid;
std::string m_mountpoint;
......
......@@ -42,19 +42,11 @@ namespace medialibrary
namespace fs
{
Directory::Directory( const std::string& path )
: CommonDirectory( toAbsolute( path ) )
Directory::Directory( const std::string& path, factory::IFileSystem& fsFactory )
: CommonDirectory( toAbsolute( path ), fsFactory )
{
}
std::shared_ptr<IDevice> Directory::device() const
{
auto lock = m_device.lock();
if ( m_device.isCached() == false )
m_device = Device::fromPath( m_path );
return m_device.get();
}
void Directory::read() const
{
std::unique_ptr<DIR, int(*)(DIR*)> dir( opendir( m_path.c_str() ), closedir );
......@@ -97,7 +89,7 @@ void Directory::read() const
if ( *dirPath.crbegin() != '/' )
dirPath += '/';
//FIXME: This will use toAbsolute again in the constructor.
m_dirs.emplace_back( std::make_shared<Directory>( dirPath ) );
m_dirs.emplace_back( std::make_shared<Directory>( dirPath, m_fsFactory ) );
}
else
{
......
......@@ -27,14 +27,15 @@
namespace medialibrary
{
namespace factory { class IFileSystem; }
namespace fs
{
class Directory : public CommonDirectory
{
public:
Directory( const std::string& path );
virtual std::shared_ptr<IDevice> device() const override;
Directory( const std::string& path, factory::IFileSystem& fsFactory );
private:
virtual void read() const override;
......
......@@ -191,6 +191,11 @@ struct FileSystemFactory : public factory::IFileSystem
return ret;
}
virtual std::shared_ptr<fs::IDevice> createDeviceFromPath( const std::string& path ) override
{
return device( path );
}
std::vector<std::shared_ptr<Device>> devices;
};
......@@ -305,6 +310,11 @@ public:
return nullptr;
}
virtual std::shared_ptr<fs::IDevice> createDeviceFromPath( const std::string& ) override
{
return nullptr;
}
virtual void refresh() override
{
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment