Commit 4337c8a6 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Always use MRLs

parent e5af542e
......@@ -308,7 +308,7 @@ samples_SOURCES = \
samples_CPPFLAGS = \
$(MEDIALIB_CPPFLAGS) \
-DSRC_DIR=\"$(top_srcdir)\" \
-DSRC_DIR=\"$(abs_srcdir)\" \
-I$(top_srcdir)/test \
-I$(top_srcdir)/googletest/include \
$(SQLITE_CFLAGS) \
......
......@@ -57,7 +57,7 @@ namespace factory
/// \param path A path.
/// \return A representation of the device.
///
virtual std::shared_ptr<fs::IDevice> createDeviceFromPath( const std::string& path ) = 0;
virtual std::shared_ptr<fs::IDevice> createDeviceFromMrl( const std::string& path ) = 0;
///
/// \brief refresh Will cause any FS cache to be refreshed.
///
......@@ -67,7 +67,7 @@ namespace factory
/// \param path The path to probe for support
/// \return True if supported, false otherwise
///
virtual bool isPathSupported( const std::string& path ) const = 0;
virtual bool isMrlSupported( const std::string& path ) const = 0;
///
/// \brief isNetworkFileSystem Returns true if this FS factory handles network file systems
///
......
......@@ -39,7 +39,7 @@ namespace fs
public:
virtual ~IDirectory() = default;
// Returns the absolute path to this directory
virtual const std::string& path() const = 0;
virtual const std::string& mrl() const = 0;
/// Returns a list of absolute files path
virtual const std::vector<std::shared_ptr<IFile>>& files() const = 0;
/// Returns a list of absolute path to this folder subdirectories
......
......@@ -35,10 +35,8 @@ namespace fs
virtual ~IFile() = default;
/// Returns the filename, including extension
virtual const std::string& name() const = 0;
/// Returns the path containing the file
virtual const std::string& path() const = 0;
/// Returns the entire path, plus filename
virtual const std::string& fullPath() const = 0;
/// Returns the mrl of this file
virtual const std::string& mrl() const = 0;
virtual const std::string& extension() const = 0;
virtual unsigned int lastModificationDate() const = 0;
virtual unsigned int size() const = 0;
......
......@@ -33,13 +33,13 @@ public:
virtual ~IFolder() = default;
virtual int64_t id() const = 0;
/**
* @brief path Returns the full path for this folder.
* @brief mrl Returns the full mrl for this folder.
* Caller is responsible for checking isPresent() beforehand, as we
* can't compute a path for a folder that is/was present on a removable storage
* that has been unplugged
* @return The folder's full path
* can't compute an for a folder that is/was present on a removable storage
* or network share that has been unplugged
* @return The folder's mrl
*/
virtual const std::string& path() const = 0;
virtual const std::string& mrl() const = 0;
virtual bool isPresent() const = 0;
};
......
......@@ -38,16 +38,18 @@ Device::Device( MediaLibraryPtr ml, sqlite::Row& row )
{
row >> m_id
>> m_uuid
>> m_scheme
>> m_isRemovable
>> m_isPresent;
//FIXME: It's probably a bad idea to load "isPresent" for DB. This field should
//only be here for sqlite triggering purposes
}
Device::Device( MediaLibraryPtr ml, const std::string& uuid, bool isRemovable )
Device::Device( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable )
: m_ml( ml )
, m_id( 0 )
, m_uuid( uuid )
, m_scheme( scheme )
, m_isRemovable( isRemovable )
// Assume we can't add an absent device
, m_isPresent( true )
......@@ -83,12 +85,17 @@ void Device::setPresent(bool value)
m_isPresent = value;
}
std::shared_ptr<Device> Device::create( MediaLibraryPtr ml, const std::string& uuid, bool isRemovable )
const std::string& Device::scheme() const
{
return m_scheme;
}
std::shared_ptr<Device> Device::create( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable )
{
static const std::string req = "INSERT INTO " + policy::DeviceTable::Name
+ "(uuid, is_removable, is_present) VALUES(?, ?, ?)";
auto self = std::make_shared<Device>( ml, uuid, isRemovable );
if ( insert( ml, self, req, uuid, isRemovable, self->isPresent() ) == false )
+ "(uuid, scheme, is_removable, is_present) VALUES(?, ?, ?, ?)";
auto self = std::make_shared<Device>( ml, uuid, scheme, isRemovable );
if ( insert( ml, self, req, uuid, scheme, isRemovable, self->isPresent() ) == false )
return nullptr;
return self;
}
......@@ -98,6 +105,7 @@ bool Device::createTable(DBConnection connection)
const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::DeviceTable::Name + "("
"id_device INTEGER PRIMARY KEY AUTOINCREMENT,"
"uuid TEXT UNIQUE ON CONFLICT FAIL,"
"scheme TEXT,"
"is_removable BOOLEAN,"
"is_present BOOLEAN"
")";
......
......@@ -43,15 +43,22 @@ struct DeviceTable
class Device : public DatabaseHelpers<Device, policy::DeviceTable>
{
public:
Device( MediaLibraryPtr ml, const std::string& uuid, bool isRemovable );
Device( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable );
Device( MediaLibraryPtr ml, sqlite::Row& row );
int64_t id() const;
const std::string& uuid() const;
bool isRemovable() const;
bool isPresent() const;
void setPresent( bool value );
///
/// \brief scheme returns the scheme that was used for this device when it was
/// originally created. This allows to use the apropriate IFileSystemFactory to find the
/// recreate a IDevice based on its id or UUID
/// \return
///
const std::string& scheme() const;
static std::shared_ptr<Device> create( MediaLibraryPtr ml, const std::string& uuid, bool isRemovable );
static std::shared_ptr<Device> create( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable );
static bool createTable( DBConnection connection );
static std::shared_ptr<Device> fromUuid( MediaLibraryPtr ml, const std::string& uuid );
......@@ -62,6 +69,7 @@ private:
// This is a unique ID on the system side, in the /dev/disk/by-uuid sense.
// It can be a name or what not, depending on the OS.
std::string m_uuid;
std::string m_scheme;
bool m_isRemovable;
bool m_isPresent;
......
......@@ -56,7 +56,7 @@ File::File( MediaLibraryPtr ml, int64_t mediaId, Type type, const fs::IFile& fil
: m_ml( ml )
, m_id( 0 )
, m_mediaId( mediaId )
, m_mrl( isRemovable == true ? file.name() : file.fullPath() )
, m_mrl( isRemovable == true ? file.name() : file.mrl() )
, m_type( type )
, m_lastModificationDate( file.lastModificationDate() )
, m_size( file.size() )
......@@ -101,7 +101,7 @@ const std::string& File::mrl() const
auto folder = Folder::fetch( m_ml, m_folderId );
if ( folder == nullptr )
return m_mrl;
m_fullPath = folder->path() + m_mrl;
m_fullPath = folder->mrl() + m_mrl;
return m_fullPath;
}
......@@ -200,7 +200,7 @@ std::shared_ptr<File> File::create( MediaLibraryPtr ml, int64_t mediaId, Type ty
if ( insert( ml, self, req, mediaId, self->m_mrl, type, sqlite::ForeignKey( folderId ),
self->m_lastModificationDate, self->m_size, isRemovable ) == false )
return nullptr;
self->m_fullPath = fileFs.fullPath();
self->m_fullPath = fileFs.mrl();
return self;
}
......@@ -223,10 +223,10 @@ std::shared_ptr<File> File::create( MediaLibraryPtr ml, int64_t mediaId, IFile::
return self;
}
std::shared_ptr<File> File::fromPath( MediaLibraryPtr ml, const std::string& path )
std::shared_ptr<File> File::fromMrl( MediaLibraryPtr ml, const std::string& mrl )
{
static const std::string req = "SELECT * FROM " + policy::FileTable::Name + " WHERE mrl = ? AND folder_id IS NOT NULL";
auto file = fetch( ml, req, path );
auto file = fetch( ml, req, mrl );
if ( file == nullptr )
return nullptr;
// safety checks: since this only works for files on non removable devices, isPresent must be true
......@@ -247,7 +247,7 @@ std::shared_ptr<File> File::fromFileName( MediaLibraryPtr ml, const std::string&
return file;
}
std::shared_ptr<File> File::fromMrl( MediaLibraryPtr ml, const std::string& mrl )
std::shared_ptr<File> File::fromExternalMrl( MediaLibraryPtr ml, const std::string& mrl )
{
static const std::string req = "SELECT * FROM " + policy::FileTable::Name + " WHERE mrl = ? "
"AND folder_id IS NULL";
......
......@@ -85,12 +85,12 @@ public:
const fs::IFile& file, int64_t folderId, bool isRemovable );
static std::shared_ptr<File> create( MediaLibraryPtr ml, int64_t mediaId, Type type, const std::string& mrl );
/**
* @brief fromPath Attempts to fetch a file using its full path
* @brief fromPath Attempts to fetch a file using its mrl
* This will only work if the file was stored on a non removable device
* @param path The full path to the wanted file
* @param path The wanted file mrl
* @return A pointer to the wanted file, or nullptr if it wasn't found
*/
static std::shared_ptr<File> fromPath( MediaLibraryPtr ml, const std::string& path );
static std::shared_ptr<File> fromMrl( MediaLibraryPtr ml, const std::string& mrl );
/**
* @brief fromFileName Attemps to fetch a file based on its filename and folder id
* @param ml
......@@ -106,7 +106,7 @@ public:
* This implies the folder_id is null
* @return
*/
static std::shared_ptr<File> fromMrl( MediaLibraryPtr ml, const std::string& mrl );
static std::shared_ptr<File> fromExternalMrl( MediaLibraryPtr ml, const std::string& mrl );
private:
......@@ -114,6 +114,8 @@ private:
int64_t m_id;
int64_t m_mediaId;
// Contains the path relative to the containing folder for files contained in a removable folder
// or the full file MRL for non removable ones
std::string m_mrl;
Type m_type;
unsigned int m_lastModificationDate;
......@@ -124,6 +126,7 @@ private:
bool m_isRemovable;
bool m_isExternal;
// Contains the full path as a MRL
mutable Cache<std::string> m_fullPath;
mutable Cache<std::weak_ptr<Media>> m_media;
......
......@@ -96,14 +96,14 @@ bool Folder::createTable( DBConnection connection)
sqlite::Tools::executeRequest( connection, triggerReq );
}
std::shared_ptr<Folder> Folder::create( MediaLibraryPtr ml, const std::string& fullPath,
std::shared_ptr<Folder> Folder::create( MediaLibraryPtr ml, const std::string& mrl,
int64_t parentId, Device& device, fs::IDevice& deviceFs )
{
std::string path;
if ( device.isRemovable() == true )
path = utils::file::removePath( fullPath, deviceFs.mountpoint() );
path = utils::file::removePath( mrl, deviceFs.mountpoint() );
else
path = fullPath;
path = mrl;
auto self = std::make_shared<Folder>( ml, path, parentId, device.id(), device.isRemovable() );
static const std::string req = "INSERT INTO " + policy::FolderTable::Name +
"(path, parent_id, device_id, is_removable) VALUES(?, ?, ?, ?)";
......@@ -117,12 +117,12 @@ std::shared_ptr<Folder> Folder::create( MediaLibraryPtr ml, const std::string& f
return self;
}
bool Folder::blacklist( MediaLibraryPtr ml, const std::string& fullPath )
bool Folder::blacklist( MediaLibraryPtr ml, const std::string& mrl )
{
// Ensure we delete the existing folder if any & blacklist the folder in an "atomic" way
auto t = ml->getConn()->newTransaction();
auto f = fromPath( ml, fullPath, BannedType::Any );
auto f = fromMrl( ml, mrl, BannedType::Any );
if ( f != nullptr )
{
// No need to blacklist a folder twice
......@@ -131,21 +131,21 @@ bool Folder::blacklist( MediaLibraryPtr ml, const std::string& fullPath )
// Let the foreign key destroy everything beneath this folder
destroy( ml, f->id() );
}
auto fsFactory = ml->fsFactoryForPath( fullPath );
auto fsFactory = ml->fsFactoryForMrl( mrl );
if ( fsFactory == nullptr )
return false;
auto folderFs = fsFactory->createDirectory( fullPath );
auto folderFs = fsFactory->createDirectory( mrl );
if ( folderFs == nullptr )
return false;
auto deviceFs = folderFs->device();
auto device = Device::fromUuid( ml, deviceFs->uuid() );
if ( device == nullptr )
device = Device::create( ml, deviceFs->uuid(), deviceFs->isRemovable() );
device = Device::create( ml, deviceFs->uuid(), utils::file::scheme( mrl ), deviceFs->isRemovable() );
std::string path;
if ( deviceFs->isRemovable() == true )
path = utils::file::removePath( fullPath, deviceFs->mountpoint() );
path = utils::file::removePath( mrl, deviceFs->mountpoint() );
else
path = fullPath;
path = mrl;
static const std::string req = "INSERT INTO " + policy::FolderTable::Name +
"(path, parent_id, is_blacklisted, device_id, is_removable) VALUES(?, ?, ?, ?, ?)";
auto res = sqlite::Tools::executeInsert( ml->getConn(), req, path, nullptr, true, device->id(), deviceFs->isRemovable() ) != 0;
......@@ -153,44 +153,44 @@ bool Folder::blacklist( MediaLibraryPtr ml, const std::string& fullPath )
return res;
}
std::shared_ptr<Folder> Folder::fromPath( MediaLibraryPtr ml, const std::string& fullPath )
std::shared_ptr<Folder> Folder::fromMrl( MediaLibraryPtr ml, const std::string& mrl )
{
return fromPath( ml, fullPath, BannedType::No );
return fromMrl( ml, mrl, BannedType::No );
}
std::shared_ptr<Folder> Folder::blacklistedFolder( MediaLibraryPtr ml, const std::string& fullPath )
std::shared_ptr<Folder> Folder::blacklistedFolder( MediaLibraryPtr ml, const std::string& mrl )
{
return fromPath( ml, fullPath, BannedType::Yes );
return fromMrl( ml, mrl, BannedType::Yes );
}
std::shared_ptr<Folder> Folder::fromPath( MediaLibraryPtr ml, const std::string& fullPath, BannedType bannedType )
std::shared_ptr<Folder> Folder::fromMrl( MediaLibraryPtr ml, const std::string& mrl, BannedType bannedType )
{
auto fsFactory = ml->fsFactoryForPath( fullPath );
auto fsFactory = ml->fsFactoryForMrl( mrl );
if ( fsFactory == nullptr )
return nullptr;
auto folderFs = fsFactory->createDirectory( fullPath );
auto folderFs = fsFactory->createDirectory( mrl );
if ( folderFs == nullptr )
return nullptr;
auto deviceFs = folderFs->device();
if ( deviceFs == nullptr )
{
LOG_ERROR( "Failed to get device containing an existing folder: ", folderFs->path() );
LOG_ERROR( "Failed to get device containing an existing folder: ", folderFs->mrl() );
return nullptr;
}
if ( deviceFs->isRemovable() == false )
{
std::string req = "SELECT * FROM " + policy::FolderTable::Name + " WHERE path = ? AND is_removable = 0";
if ( bannedType == BannedType::Any )
return fetch( ml, req, folderFs->path() );
return fetch( ml, req, folderFs->mrl() );
req += " AND is_blacklisted = ?";
return fetch( ml, req, folderFs->path(), bannedType == BannedType::Yes ? true : false );
return fetch( ml, req, folderFs->mrl(), bannedType == BannedType::Yes ? true : false );
}
auto device = Device::fromUuid( ml, deviceFs->uuid() );
// We are trying to find a folder. If we don't know the device it's on, we don't know the folder.
if ( device == nullptr )
return nullptr;
auto path = utils::file::removePath( folderFs->path(), deviceFs->mountpoint() );
auto path = utils::file::removePath( folderFs->mrl(), deviceFs->mountpoint() );
std::string req = "SELECT * FROM " + policy::FolderTable::Name + " WHERE path = ? AND device_id = ?";
std::shared_ptr<Folder> folder;
if ( bannedType == BannedType::Any )
......@@ -214,7 +214,7 @@ int64_t Folder::id() const
return m_id;
}
const std::string& Folder::path() const
const std::string& Folder::mrl() const
{
if ( m_isRemovable == false )
return m_path;
......@@ -227,7 +227,7 @@ const std::string& Folder::path() const
return m_fullPath;
auto device = Device::fetch( m_ml, m_deviceId );
auto fsFactory = m_ml->fsFactoryForPath( m_fullPath );
auto fsFactory = m_ml->fsFactoryForMrl( device->scheme() );
assert( fsFactory != nullptr );
auto deviceFs = fsFactory->createDevice( device->uuid() );
m_deviceMountpoint = deviceFs->mountpoint();
......
......@@ -61,15 +61,15 @@ public:
Folder(MediaLibraryPtr ml, const std::string& path, int64_t parent , int64_t deviceId , bool isRemovable );
static bool createTable( DBConnection connection );
static std::shared_ptr<Folder> create( MediaLibraryPtr ml, const std::string& path, int64_t parentId, Device& device, fs::IDevice& deviceFs );
static bool blacklist( MediaLibraryPtr ml, const std::string& fullPath );
static std::shared_ptr<Folder> create( MediaLibraryPtr ml, const std::string& mrl, int64_t parentId, Device& device, fs::IDevice& deviceFs );
static bool blacklist( MediaLibraryPtr ml, const std::string& mrl );
static std::vector<std::shared_ptr<Folder>> fetchRootFolders( MediaLibraryPtr ml );
static std::shared_ptr<Folder> fromPath(MediaLibraryPtr ml, const std::string& fullPath );
static std::shared_ptr<Folder> blacklistedFolder(MediaLibraryPtr ml, const std::string& fullPath );
static std::shared_ptr<Folder> fromMrl(MediaLibraryPtr ml, const std::string& mrl );
static std::shared_ptr<Folder> blacklistedFolder(MediaLibraryPtr ml, const std::string& mrl );
virtual int64_t id() const override;
virtual const std::string& path() const override;
virtual const std::string& mrl() const override;
std::vector<std::shared_ptr<File>> files();
std::vector<std::shared_ptr<Folder>> folders();
std::shared_ptr<Folder> parent();
......@@ -85,13 +85,14 @@ private:
Any, //< Well... any of the above.
};
static std::shared_ptr<Folder> fromPath( MediaLibraryPtr ml, const std::string& fullPath, BannedType bannedType );
static std::shared_ptr<Folder> fromMrl( MediaLibraryPtr ml, const std::string& mrl, BannedType bannedType );
private:
MediaLibraryPtr m_ml;
int64_t m_id;
// This contains the path relative to the device mountpoint (ie. excluding it)
// or the full path (including mrl scheme) for folders on non removable devices
std::string m_path;
int64_t m_parent;
bool m_isBlacklisted;
......@@ -100,7 +101,8 @@ private:
bool m_isRemovable;
mutable Cache<std::string> m_deviceMountpoint;
// This contains the full path, including device mountpoint.
// This contains the full path, including device mountpoint (and mrl scheme,
// as its part of the mountpoint
mutable std::string m_fullPath;
friend struct policy::FolderTable;
......
......@@ -272,29 +272,29 @@ MediaPtr MediaLibrary::media( int64_t mediaId ) const
MediaPtr MediaLibrary::media( const std::string& mrl ) const
{
LOG_INFO( "Fetching media from mrl: ", mrl );
auto file = File::fromMrl( this, mrl );
auto file = File::fromExternalMrl( this, mrl );
if ( file != nullptr )
{
LOG_INFO( "Found external media: ", mrl );
return file->media();
}
auto fsFactory = fsFactoryForPath( mrl );
auto fsFactory = fsFactoryForMrl( mrl );
if ( fsFactory == nullptr )
{
LOG_WARN( "Failed to create FS factory for path ", mrl );
return nullptr;
}
auto device = fsFactory->createDeviceFromPath( mrl );
auto device = fsFactory->createDeviceFromMrl( mrl );
if ( device == nullptr )
{
LOG_WARN( "Failed to create a device associated with mrl ", mrl );
return nullptr;
}
if ( device->isRemovable() == false )
file = File::fromPath( this, mrl );
file = File::fromMrl( this, mrl );
else
{
auto folder = Folder::fromPath( this, utils::file::directory( mrl ) );
auto folder = Folder::fromMrl( this, utils::file::directory( mrl ) );
if ( folder == nullptr )
{
LOG_WARN( "Failed to find folder containing ", mrl );
......@@ -351,22 +351,22 @@ std::shared_ptr<Media> MediaLibrary::addFile( const fs::IFile& fileFs, Folder& p
std::find_if( begin( supportedAudioExtensions ), end( supportedAudioExtensions ),
predicate ) == end( supportedAudioExtensions ) )
{
LOG_INFO( "Rejecting file ", fileFs.fullPath(), " due to its extension" );
LOG_INFO( "Rejecting file ", fileFs.mrl(), " due to its extension" );
return nullptr;
}
LOG_INFO( "Adding ", fileFs.fullPath() );
LOG_INFO( "Adding ", fileFs.mrl() );
auto mptr = Media::create( this, type, fileFs.name() );
if ( mptr == nullptr )
{
LOG_ERROR( "Failed to add media ", fileFs.fullPath(), " to the media library" );
LOG_ERROR( "Failed to add media ", fileFs.mrl(), " to the media library" );
return nullptr;
}
// For now, assume all media are made of a single file
auto file = mptr->addFile( fileFs, parentFolder, parentFolderFs, File::Type::Main );
if ( file == nullptr )
{
LOG_ERROR( "Failed to add file ", fileFs.fullPath(), " to media #", mptr->id() );
LOG_ERROR( "Failed to add file ", fileFs.mrl(), " to media #", mptr->id() );
Media::destroy( this, mptr->id() );
return nullptr;
}
......@@ -686,11 +686,11 @@ IDeviceListerCb* MediaLibrary::setDeviceLister( DeviceListerPtr lister )
return static_cast<IDeviceListerCb*>( this );
}
std::shared_ptr<factory::IFileSystem> MediaLibrary::fsFactoryForPath( const std::string& path ) const
std::shared_ptr<factory::IFileSystem> MediaLibrary::fsFactoryForMrl( const std::string& mrl ) const
{
for ( const auto& f : m_fsFactories )
{
if ( f->isPathSupported( path ) )
if ( f->isMrlSupported( mrl ) )
return f;
}
return nullptr;
......@@ -729,7 +729,7 @@ std::vector<FolderPtr> MediaLibrary::entryPoints() const
bool MediaLibrary::removeEntryPoint( const std::string& entryPoint )
{
auto folder = Folder::fromPath( this, entryPoint );
auto folder = Folder::fromMrl( this, entryPoint );
if ( folder == nullptr )
{
LOG_WARN( "Can't remove unknown entrypoint: ", entryPoint );
......@@ -789,7 +789,7 @@ void MediaLibrary::onDevicePlugged( const std::string& uuid, const std::string&
LOG_INFO( "Device ", uuid, " was plugged and mounted on ", mountpoint );
for ( const auto& fsFactory : m_fsFactories )
{
if ( fsFactory->isPathSupported( "file://" ) )
if ( fsFactory->isMrlSupported( "file://" ) )
{
fsFactory->refreshDevices();
break;
......@@ -802,7 +802,7 @@ void MediaLibrary::onDeviceUnplugged( const std::string& uuid )
LOG_INFO( "Device ", uuid, " was unplugged" );
for ( const auto& fsFactory : m_fsFactories )
{
if ( fsFactory->isPathSupported( "file://" ) )
if ( fsFactory->isMrlSupported( "file://" ) )
{
fsFactory->refreshDevices();
break;
......
......@@ -134,7 +134,7 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb
std::shared_ptr<ModificationNotifier> getNotifier() const;
virtual IDeviceListerCb* setDeviceLister( DeviceListerPtr lister ) override;
std::shared_ptr<factory::IFileSystem> fsFactoryForPath( const std::string& path ) const;
std::shared_ptr<factory::IFileSystem> fsFactoryForMrl( const std::string& path ) const;
public:
static const uint32_t DbModelVersion;
......
......@@ -52,9 +52,8 @@ FsDiscoverer::FsDiscoverer( std::shared_ptr<factory::IFileSystem> fsFactory, Med
bool FsDiscoverer::discover( const std::string &entryPoint )
{
LOG_INFO( "Adding to discovery list: ", entryPoint );
// Assume :// denotes a scheme that isn't a file path, and refuse to discover it.
if ( m_fsFactory->isPathSupported( entryPoint ) == false )
if ( m_fsFactory->isMrlSupported( entryPoint ) == false )
return false;
std::shared_ptr<fs::IDirectory> fsDir = m_fsFactory->createDirectory( entryPoint );
......@@ -64,7 +63,7 @@ bool FsDiscoverer::discover( const std::string &entryPoint )
LOG_ERROR("Failed to create an IDirectory for ", entryPoint );
return false;
}
auto f = Folder::fromPath( m_ml, fsDir->path() );
auto f = Folder::fromMrl( m_ml, fsDir->mrl() );
// If the folder exists, we assume it will be handled by reload()
if ( f != nullptr )
return true;
......@@ -93,10 +92,10 @@ bool FsDiscoverer::reload()
auto rootFolders = Folder::fetchRootFolders( m_ml );
for ( const auto& f : rootFolders )
{
auto folder = m_fsFactory->createDirectory( f->path() );
auto folder = m_fsFactory->createDirectory( f->mrl() );
if ( folder == nullptr )
{
LOG_INFO( "Removing folder ", f->path() );
LOG_INFO( "Removing folder ", f->mrl() );
m_ml->deleteFolder( *f );
continue;
}
......@@ -107,7 +106,7 @@ bool FsDiscoverer::reload()
bool FsDiscoverer::reload( const std::string& entryPoint )
{
if ( m_fsFactory->isPathSupported( entryPoint ) == false )
if ( m_fsFactory->isMrlSupported( entryPoint ) == false )
return false;
LOG_INFO( "Reloading folder ", entryPoint );
// Start by checking if previously known devices have been plugged/unplugged
......@@ -116,16 +115,16 @@ bool FsDiscoverer::reload( const std::string& entryPoint )
LOG_ERROR( "Refusing to reloading files with no storage device" );
return false;
}
auto folder = Folder::fromPath( m_ml, entryPoint );
auto folder = Folder::fromMrl( m_ml, entryPoint );
if ( folder == nullptr )
{
LOG_ERROR( "Can't reload ", entryPoint, ": folder wasn't found in database" );
return false;
}
auto folderFs = m_fsFactory->createDirectory( folder->path() );
auto folderFs = m_fsFactory->createDirectory( folder->mrl() );
if ( folderFs == nullptr )
{
LOG_ERROR(" Failed to create a fs::IDirectory representing ", folder->path() );
LOG_ERROR(" Failed to create a fs::IDirectory representing ", folder->mrl() );
return false;
}
checkFolder( *folderFs, *folder, false );
......@@ -160,13 +159,13 @@ void FsDiscoverer::checkFolder( fs::IDirectory& currentFolderFs, Folder& current
// In this case, simply delete the folder.
if ( hasDotNoMediaFile( currentFolderFs ) )
{
LOG_INFO( "Deleting folder ", currentFolderFs.path(), " due to a .nomedia file" );
LOG_INFO( "Deleting folder ", currentFolderFs.mrl(), " due to a .nomedia file" );
m_ml->deleteFolder( currentFolder );
return;
}
m_cb->onDiscoveryProgress( currentFolderFs.path() );
m_cb->onDiscoveryProgress( currentFolderFs.mrl() );
// Load the folders we already know of:
LOG_INFO( "Checking for modifications in ", currentFolderFs.path() );
LOG_INFO( "Checking for modifications in ", currentFolderFs.mrl() );
// Don't try to fetch any potential sub folders if the folder was freshly added
std::vector<std::shared_ptr<Folder>> subFoldersInDB;
if ( newFolder == false )
......@@ -174,7 +173,7 @@ void FsDiscoverer::checkFolder( fs::IDirectory& currentFolderFs, Folder& current
for ( const auto& subFolder : currentFolderFs.dirs() )
{
auto it = std::find_if( begin( subFoldersInDB ), end( subFoldersInDB ), [&subFolder](const std::shared_ptr<Folder>& f) {
return f->path() == subFolder->path();
return f->mrl() == subFolder->mrl();
});
// We don't know this folder, it's a new one
if ( it == end( subFoldersInDB ) )
......@@ -184,7 +183,7 @@ void FsDiscoverer::checkFolder( fs::IDirectory& currentFolderFs, Folder& current
LOG_INFO( "Ignoring folder with a .nomedia file" );
continue;
}
LOG_INFO( "New folder detected: ", subFolder->path() );
LOG_INFO( "New folder detected: ", subFolder->mrl() );
try
{
addFolder( *subFolder, &currentFolder );
......@@ -214,16 +213,16 @@ void FsDiscoverer::checkFolder( fs::IDirectory& currentFolderFs, Folder& current
// Now all folders we had in DB but haven't seen from the FS must have been deleted.
for ( auto f : subFoldersInDB )
{
LOG_INFO( "Folder ", f->path(), " not found in FS, deleting it" );
LOG_INFO( "Folder ", f->mrl(), " not found in FS, deleting it" );
m_ml->deleteFolder( *f );
}
checkFiles( currentFolderFs, currentFolder );
LOG_INFO( "Done checking subfolders in ", currentFolderFs.path() );
LOG_INFO( "Done checking subfolders in ", currentFolderFs.mrl() );
}
void FsDiscoverer::checkFiles( fs::IDirectory& parentFolderFs, Folder& parentFolder ) const
{
LOG_INFO( "Checking file in ", parentFolderFs.path() );
LOG_INFO( "Checking file in ", parentFolderFs.mrl() );
static const std::string req = "SELECT * FROM " + policy::FileTable::Name
+ " WHERE folder_id = ?";
auto files = File::fetchAll<File>( m_ml, req, parentFolder.id() );
......@@ -232,7 +231,7 @@ void FsDiscoverer::checkFiles( fs::IDirectory& parentFolderFs, Folder& parentFol
for ( const auto& fileFs: parentFolderFs.files() )
{
auto it = std::find_if( begin( files ), end( files ), [fileFs](const std::shared_ptr<File>& f) {
return f->mrl() == fileFs->fullPath();
return f->mrl() == fileFs->mrl();
});
if ( it == end( files ) )
{
......@@ -246,7 +245,7 @@ void FsDiscoverer::checkFiles( fs::IDirectory& parentFolderFs, Folder& parentFol
continue;
}
auto& file = (*it);
LOG_INFO( "Forcing file refresh ", fileFs->fullPath() );
LOG_INFO( "Forcing file refresh ", fileFs->mrl() );
// Pre-cache the file's media, since we need it to remove. However, better doing it
// out of a write context, since that way, other threads can also read the database.
file->media();
......@@ -266,7 +265,7 @@ void FsDiscoverer::checkFiles( fs::IDirectory& parentFolderFs, Folder& parentFol
for ( auto& p : filesToAdd )
m_ml->addFile( *p, parentFolder, parentFolderFs );
t->commit();
LOG_INFO( "Done checking files in ", parentFolderFs.path() );
LOG_INFO( "Done checking files in ", parentFolderFs.mrl() );
}
bool FsDiscoverer::hasDotNoMediaFile( const fs::IDirectory& directory )
......@@ -286,10 +285,11 @@ bool FsDiscoverer::addFolder( fs::IDirectory& folder, Folder* parentFolder ) con
if ( device == nullptr )
{
LOG_INFO( "Creating new device in DB ", deviceFs->uuid() );
device = Device::create( m_ml, deviceFs->uuid(), deviceFs->isRemovable() );
device = Device::create( m_ml, deviceFs->uuid(), utils::file::scheme( folder.mrl() ),
deviceFs->isRemovable() );
}
auto f = Folder::create( m_ml, folder.path(),
auto f = Folder::create( m_ml, folder.mrl(),
parentFolder != nullptr ? parentFolder->id() : 0,
*device, *deviceFs );
if ( f == nullptr )
......
......@@ -28,6 +28,7 @@
#include "filesystem/IDirectory.h"
#include "filesystem/IFile.h"
#include "logging/Logger.h"
#include "utils/Filename.h"
#if defined(__linux__) || defined(__APPLE__)