Commit 67ca0b8c authored by Alexandre Fernandez's avatar Alexandre Fernandez Committed by Hugo Beauzée-Luyssen

Refactor: Allow parsing process to start without File & Media object

Signed-off-by: default avatarHugo Beauzée-Luyssen <hugo@beauzee.fr>
parent 39317320
......@@ -26,6 +26,7 @@
#include <algorithm>
#include <functional>
#include <utility>
#include <sys/stat.h>
#include "Album.h"
......@@ -424,10 +425,18 @@ std::shared_ptr<Media> MediaLibrary::addFile( std::shared_ptr<fs::IFile> fileFs,
return nullptr;
}
if ( m_parser != nullptr )
m_parser->parse( mptr, file );
m_parser->parse( file, fileFs->mrl() );
return mptr;
}
void MediaLibrary::addDiscoveredFile( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs )
{
if ( m_parser != nullptr )
m_parser->parse( std::move( fileFs ), std::move( parentFolder ), std::move( parentFolderFs ) );
}
bool MediaLibrary::deleteFolder( const Folder& folder )
{
if ( Folder::destroy( this, folder.id() ) == false )
......
......@@ -75,6 +75,9 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb
std::shared_ptr<Media> addFile( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs );
virtual void addDiscoveredFile( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs );
bool deleteFolder(const Folder& folder );
......
......@@ -67,7 +67,6 @@ public:
std::shared_ptr<File> addFile( const fs::IFile& fileFs, int64_t parentFolderId,
bool isFolderFsRemovable );
static bool createTable( DBConnection dbConn );
static bool createTriggers( DBConnection dbConn );
static std::vector<PlaylistPtr> search( MediaLibraryPtr ml, const std::string& name );
......
......@@ -302,7 +302,7 @@ void FsDiscoverer::checkFiles( std::shared_ptr<fs::IDirectory> parentFolderFs,
sqlite::Tools::withRetries( 3, [this, &parentFolder, &parentFolderFs]
( FilesT files, FilesToAddT filesToAdd, FilesToRemoveT filesToRemove ) {
auto t = m_ml->getConn()->newTransaction();
for ( auto file : files )
for ( const auto& file : files )
{
LOG_INFO( "File ", file->mrl(), " not found on filesystem, deleting it" );
auto media = file->media();
......@@ -330,7 +330,7 @@ void FsDiscoverer::checkFiles( std::shared_ptr<fs::IDirectory> parentFolderFs,
}
// Insert all files at once to avoid SQL write contention
for ( auto& p : filesToAdd )
m_ml->addFile( p, parentFolder, parentFolderFs );
m_ml->addDiscoveredFile( p, parentFolder, parentFolderFs );
t->commit();
LOG_INFO( "Done checking files in ", parentFolderFs->mrl() );
}, std::move( files ), std::move( filesToAdd ), std::move( filesToRemove ) );
......
......@@ -29,8 +29,12 @@
#include "AlbumTrack.h"
#include "Artist.h"
#include "File.h"
#include "filesystem/IDevice.h"
#include "filesystem/IDirectory.h"
#include "Folder.h"
#include "Genre.h"
#include "Media.h"
#include "Playlist.h"
#include "Show.h"
#include "utils/Filename.h"
#include "utils/ModificationsNotifier.h"
......@@ -71,6 +75,32 @@ int MetadataParser::toInt( VLC::Media& vlcMedia, libvlc_meta_t meta, const char*
parser::Task::Status MetadataParser::run( parser::Task& task )
{
if ( task.file != nullptr )
task.media = task.file->media();
else // Create Media & File
{
auto t = m_ml->getConn()->newTransaction();
LOG_INFO( "Adding ", task.mrl );
task.media = Media::create( m_ml, IMedia::Type::Unknown, utils::file::fileName( task.mrl ) );
if ( task.media == nullptr )
{
LOG_ERROR( "Failed to add media ", task.mrl, " to the media library" );
return parser::Task::Status::Fatal;
}
// For now, assume all media are made of a single file
task.file = task.media->addFile( *task.fileFs, task.parentFolder->id(),
task.parentFolderFs->device()->isRemovable(),
File::Type::Main );
if ( task.file == nullptr )
{
LOG_ERROR( "Failed to add file ", task.mrl, " to media #", task.media->id() );
return parser::Task::Status::Fatal;
}
t->commit();
// Synchronize file step tracker with task
task.markStepCompleted( static_cast<parser::Task::ParserStep>( task.step ) );
}
const auto& tracks = task.vlcMedia.tracks();
// If we failed to extract any tracks, don't make any assumption and forward to the
......@@ -530,8 +560,8 @@ uint8_t MetadataParser::nbThreads() const
bool MetadataParser::isCompleted( const parser::Task& task ) const
{
// We always need to run this task if the metadata extraction isn't completed
return ( static_cast<uint8_t>( task.file->parserStep() ) &
static_cast<uint8_t>( parser::Task::ParserStep::MetadataAnalysis ) ) != 0;
return ( static_cast<uint8_t>( task.step ) &
static_cast<uint8_t>( parser::Task::ParserStep::MetadataAnalysis ) ) != 0;
}
}
......@@ -40,14 +40,13 @@ VLCMetadataService::VLCMetadataService()
parser::Task::Status VLCMetadataService::run( parser::Task& task )
{
auto file = task.file;
LOG_INFO( "Parsing ", file->mrl() );
auto mrl = task.mrl;
LOG_INFO( "Parsing ", mrl );
// Having a valid media means we're re-executing this parser after the thumbnailer,
// which isn't expected, as we always mark this task as completed.
assert( task.vlcMedia.isValid() == false );
task.vlcMedia = VLC::Media( m_instance, file->mrl(), VLC::Media::FromType::FromLocation );
task.vlcMedia = VLC::Media( m_instance, mrl, VLC::Media::FromType::FromLocation );
VLC::Media::ParsedStatus status;
bool done = false;
......@@ -73,7 +72,7 @@ parser::Task::Status VLCMetadataService::run( parser::Task& task )
return parser::Task::Status::Fatal;
auto tracks = task.vlcMedia.tracks();
if ( tracks.size() == 0 )
LOG_WARN( "Failed to fetch any tracks for ", file->mrl() );
LOG_WARN( "Failed to fetch any tracks for ", mrl );
// Don't save the file parsing step yet, since all data are just in memory. Just mark
// the extraction as done.
task.markStepCompleted( parser::Task::ParserStep::MetadataExtraction );
......
......@@ -27,6 +27,7 @@
#include "Parser.h"
#include <algorithm>
#include <utility>
#include "medialibrary/IMediaLibrary.h"
#include "Media.h"
......@@ -56,11 +57,11 @@ void Parser::addService( ServicePtr service )
m_services.push_back( std::move( service ) );
}
void Parser::parse( std::shared_ptr<Media> media, std::shared_ptr<File> file )
void Parser::parse( std::shared_ptr<File> file, const std::string& mrl )
{
if ( m_services.size() == 0 )
if ( m_services.empty() == true )
return;
m_services[0]->parse( std::unique_ptr<parser::Task>( new parser::Task( media, file ) ) );
m_services[0]->parse( std::unique_ptr<parser::Task>( new parser::Task( std::move( file ), mrl ) ) );
m_opToDo += m_services.size();
updateStats();
}
......@@ -69,10 +70,11 @@ void Parser::parse( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs )
{
if ( m_services.size() == 0 )
if ( m_services.empty() == true )
return;
std::string mrl = fileFs->mrl();
m_services[0]->parse( std::unique_ptr<parser::Task>( new parser::Task(
std::move( fileFs ), std::move( parentFolder ), std::move( parentFolderFs ) ) ) );
std::move( fileFs ), std::move( parentFolder ), std::move( parentFolderFs ), mrl ) ) );
m_opToDo += m_services.size();
updateStats();
}
......@@ -115,8 +117,7 @@ void Parser::restore()
LOG_INFO( "Resuming parsing on ", files.size(), " mrl" );
for ( auto& f : files )
{
auto m = f->media();
parse( m, f );
parse( f, f->mrl() );
}
}
......@@ -147,7 +148,7 @@ void Parser::done( std::unique_ptr<parser::Task> t, parser::Task::Status status
if ( status == parser::Task::Status::TemporaryUnavailable ||
status == parser::Task::Status::Fatal ||
t->file->parserStep() == parser::Task::ParserStep::Completed )
( t->file != nullptr && t->file->parserStep() == parser::Task::ParserStep::Completed ) )
{
if ( serviceIdx < m_services.size() )
{
......@@ -163,7 +164,7 @@ void Parser::done( std::unique_ptr<parser::Task> t, parser::Task::Status status
{
t->currentService = serviceIdx = 0;
m_opToDo += m_services.size();
LOG_INFO("Running parser chain again for ", t->file->mrl());
LOG_INFO("Running parser chain again for ", t->mrl);
}
updateStats();
m_services[serviceIdx]->parse( std::move( t ) );
......
......@@ -50,7 +50,7 @@ public:
Parser( MediaLibrary* ml );
virtual ~Parser();
void addService( ServicePtr service );
void parse( std::shared_ptr<Media> media, std::shared_ptr<File> file );
void parse( std::shared_ptr<File> file, const std::string& mrl );
void parse( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs );
......
......@@ -165,29 +165,31 @@ void ParserService::mainloop()
}
if ( isCompleted( *task ) == true )
{
LOG_INFO( "Skipping completed task [", serviceName, "] on ", task->file->mrl() );
LOG_INFO( "Skipping completed task [", serviceName, "] on ", task->mrl );
m_parserCb->done( std::move( task ), parser::Task::Status::Success );
continue;
}
parser::Task::Status status;
try
{
LOG_INFO( "Executing ", serviceName, " task on ", task->file->mrl() );
LOG_INFO( "Executing ", serviceName, " task on ", task->mrl );
auto chrono = std::chrono::steady_clock::now();
if ( task->file->isDeleted() || task->media->isDeleted() )
if ( ( task->file != nullptr && task->file->isDeleted() )
|| ( task->media != nullptr && task->media->isDeleted() ) )
status = parser::Task::Status::Fatal;
else
{
task->file->startParserStep();
if ( task->file != nullptr )
task->file->startParserStep(); // FIXME ?
status = run( *task );
auto duration = std::chrono::steady_clock::now() - chrono;
LOG_INFO( "Done executing ", serviceName, " task on ", task->file->mrl(), " in ",
LOG_INFO( "Done executing ", serviceName, " task on ", task->mrl, " in ",
std::chrono::duration_cast<std::chrono::milliseconds>( duration ).count(), "ms" );
}
}
catch ( const std::exception& ex )
{
LOG_ERROR( "Caught an exception during ", task->file->mrl(), " [", serviceName, "] parsing: ", ex.what() );
LOG_ERROR( "Caught an exception during ", task->mrl, " [", serviceName, "] parsing: ", ex.what() );
status = parser::Task::Status::Fatal;
}
m_parserCb->done( std::move( task ), status );
......
......@@ -27,8 +27,6 @@
#include "Task.h"
#include <utility>
#include "filesystem/IFile.h"
#include "File.h"
......@@ -38,20 +36,24 @@ namespace medialibrary
namespace parser
{
Task::Task( std::shared_ptr<Media> media, std::shared_ptr<File> file )
: media( std::move( media ) )
, file( std::move( file ) )
, currentService( 0 )
Task::Task( std::shared_ptr<File> file, std::string mrl )
: file( std::move( file ) )
, mrl( std::move( mrl ) )
, currentService( 0 )
, step( this->file->parserStep() )
{
}
Task::Task( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs)
: fileFs( std::move( fileFs ) )
, parentFolder( std::move( parentFolder ) )
, parentFolderFs( std::move( parentFolderFs ) )
, currentService( 0 )
std::shared_ptr<fs::IDirectory> parentFolderFs,
std::string mrl )
: fileFs( std::move( fileFs ) )
, parentFolder( std::move( parentFolder ) )
, parentFolderFs( std::move( parentFolderFs ) )
, mrl( std::move( mrl ) )
, currentService( 0 )
, step( ParserStep::None )
{
}
......
......@@ -71,10 +71,11 @@ struct Task
Completed = 1 | 2 | 4,
};
Task( std::shared_ptr<Media> media, std::shared_ptr<File> file );
Task( std::shared_ptr<File> file, std::string mrl );
Task( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs );
std::shared_ptr<fs::IDirectory> parentFolderFs,
std::string mrl );
void markStepCompleted( ParserStep stepCompleted );
void markStepUncompleted( ParserStep stepUncompleted );
......
......@@ -154,3 +154,10 @@ std::vector<const char*> MediaLibraryTester::getSupportedExtensions() const
res.push_back( supportedExtensions[i] );
return res;
}
void MediaLibraryTester::addDiscoveredFile(std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs)
{
MediaLibrary::addFile( fileFs, parentFolder, parentFolderFs );
}
......@@ -61,6 +61,9 @@ public:
virtual void addLocalFsFactory() override;
std::shared_ptr<Device> device( const std::string& uuid );
std::vector<const char*> getSupportedExtensions() const;
virtual void addDiscoveredFile( std::shared_ptr<fs::IFile> fileFs,
std::shared_ptr<Folder> parentFolder,
std::shared_ptr<fs::IDirectory> parentFolderFs ) override;
private:
std::shared_ptr<fs::IDirectory> dummyDirectory;
......
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