Commit 786131a3 by Hugo Beauzée-Luyssen

IMediaLibrary: Use a more specific return code for initialize

parent 6986003b
......@@ -69,6 +69,20 @@ enum class SortingCriteria
Artist,
};
enum class InitializeResult
{
//< Everything worked out fine
Success,
//< Should be considered the same as Success, but is an indication of
// unrequired subsequent calls to initialize.
AlreadyInitialized,
//< A fatal error occured, the IMediaLibrary instance should be destroyed
Failed,
//< The database was reset, the caller needs to re-configure folders to
// discover at the bare minimum.
DbReset,
};
class IMediaLibraryCb
{
public:
......@@ -195,11 +209,13 @@ class IMediaLibrary
* \param mlCallback A pointer to an IMediaLibraryCb that will be invoked with various
* events during the medialibrary lifetime.
* \return true in case of success, false otherwise
* If initialize returns false, this medialibrary must not be used anymore, and should be
* disposed off.
* If it returns true the first time, calling this method again is a no-op
* If initialize returns Fail, this medialibrary must not be used
* anymore, and should be disposed off.
* If it returns Ok the first time, calling this method again is a no-op
* In case DbReset is returned, it is up to application to decide what
* to do to repopulate the database.
*/
virtual bool initialize( const std::string& dbPath, const std::string& thumbnailPath, IMediaLibraryCb* mlCallback ) = 0;
virtual InitializeResult initialize( const std::string& dbPath, const std::string& thumbnailPath, IMediaLibraryCb* mlCallback ) = 0;
/**
* @brief start Starts the background thread and reload the medialibrary content
......
......@@ -232,13 +232,15 @@ bool MediaLibrary::validateSearchPattern( const std::string& pattern )
return pattern.size() >= 3;
}
bool MediaLibrary::initialize( const std::string& dbPath, const std::string& thumbnailPath, IMediaLibraryCb* mlCallback )
InitializeResult MediaLibrary::initialize( const std::string& dbPath,
const std::string& thumbnailPath,
IMediaLibraryCb* mlCallback )
{
LOG_INFO( "Initializing medialibrary..." );
if ( m_initialized == true )
{
LOG_INFO( "...Already initialized" );
return true;
return InitializeResult::AlreadyInitialized;
}
if ( m_deviceLister == nullptr )
{
......@@ -246,7 +248,7 @@ bool MediaLibrary::initialize( const std::string& dbPath, const std::string& thu
if ( m_deviceLister == nullptr )
{
LOG_ERROR( "No available IDeviceLister was found." );
return false;
return InitializeResult::Failed;
}
}
addLocalFsFactory();
......@@ -259,7 +261,7 @@ bool MediaLibrary::initialize( const std::string& dbPath, const std::string& thu
if ( errno != EEXIST )
{
LOG_ERROR( "Failed to create thumbnail directory: ", strerror( errno ) );
return false;
return InitializeResult::Failed;
}
}
m_thumbnailPath = thumbnailPath;
......@@ -271,35 +273,37 @@ bool MediaLibrary::initialize( const std::string& dbPath, const std::string& thu
// Which allows us to register hooks, or not, depending on the presence of a notifier
registerEntityHooks();
auto res = InitializeResult::Success;
try
{
if ( createAllTables() == false )
{
LOG_ERROR( "Failed to create database structure" );
return false;
return InitializeResult::Failed;
}
if ( m_settings.load() == false )
{
LOG_ERROR( "Failed to load settings" );
return false;
return InitializeResult::Failed;
}
if ( m_settings.dbModelVersion() != Settings::DbModelVersion )
{
if ( updateDatabaseModel( m_settings.dbModelVersion(), dbPath ) == false )
res = updateDatabaseModel( m_settings.dbModelVersion(), dbPath );
if ( res == InitializeResult::Failed )
{
LOG_ERROR( "Failed to update database model" );
return false;
return res;
}
}
}
catch ( const sqlite::errors::Generic& ex )
{
LOG_ERROR( "Can't initialize medialibrary: ", ex.what() );
return false;
return InitializeResult::Failed;
}
m_initialized = true;
LOG_INFO( "Successfuly initialized" );
return true;
return res;
}
bool MediaLibrary::start()
......@@ -737,7 +741,7 @@ void MediaLibrary::addLocalFsFactory()
m_fsFactories.insert( begin( m_fsFactories ), std::make_shared<factory::FileSystemFactory>( m_deviceLister ) );
}
bool MediaLibrary::updateDatabaseModel( unsigned int previousVersion,
InitializeResult MediaLibrary::updateDatabaseModel( unsigned int previousVersion,
const std::string& dbPath )
{
LOG_INFO( "Updating database model from ", previousVersion, " to ", Settings::DbModelVersion );
......@@ -759,7 +763,7 @@ bool MediaLibrary::updateDatabaseModel( unsigned int previousVersion,
{
if( recreateDatabase( dbPath ) == false )
throw std::runtime_error( "Failed to recreate the database" );
return true;
return InitializeResult::DbReset;
}
/**
* Migration from 3 to 4 didn't happen so well and broke a few
......@@ -781,8 +785,8 @@ bool MediaLibrary::updateDatabaseModel( unsigned int previousVersion,
assert( previousVersion == Settings::DbModelVersion );
m_settings.setDbModelVersion( Settings::DbModelVersion );
if ( m_settings.save() == false )
return false;
return true;
return InitializeResult::Failed;
return InitializeResult::Success;
}
catch( const std::exception& ex )
{
......@@ -801,7 +805,7 @@ bool MediaLibrary::updateDatabaseModel( unsigned int previousVersion,
try
{
if( recreateDatabase( dbPath ) == true )
return true;
return InitializeResult::DbReset;
}
catch( const std::exception& ex )
{
......@@ -813,7 +817,7 @@ bool MediaLibrary::updateDatabaseModel( unsigned int previousVersion,
}
LOG_WARN( "Retrying to recreate the database, attempt ", i + 1, " / 3" );
}
return false;
return InitializeResult::Failed;
}
bool MediaLibrary::recreateDatabase( const std::string& dbPath )
......
......@@ -61,7 +61,9 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb
public:
MediaLibrary();
~MediaLibrary();
virtual bool initialize( const std::string& dbPath, const std::string& thumbnailPath, IMediaLibraryCb* mlCallback ) override;
virtual InitializeResult initialize( const std::string& dbPath,
const std::string& thumbnailPath,
IMediaLibraryCb* mlCallback ) override;
virtual bool start() override;
virtual void setVerbosity( LogLevel v ) override;
......@@ -158,8 +160,8 @@ class MediaLibrary : public IMediaLibrary, public IDeviceListerCb
virtual void startDiscoverer();
virtual void startDeletionNotifier();
bool recreateDatabase( const std::string& dbPath );
bool updateDatabaseModel( unsigned int previousVersion,
const std::string& path );
InitializeResult updateDatabaseModel( unsigned int previousVersion,
const std::string& path );
bool migrateModel3to5();
bool createAllTables();
void registerEntityHooks();
......
......@@ -77,7 +77,8 @@ void Tests::SetUp()
else if ( Verbose == true )
m_ml->setVerbosity( LogLevel::Info );
ASSERT_TRUE( m_ml->initialize( "test.db", "/tmp", m_cb.get() ) );
auto res = m_ml->initialize( "test.db", "/tmp", m_cb.get() );
ASSERT_EQ( InitializeResult::Success, res );
ASSERT_TRUE( m_ml->start() );
}
......
......@@ -112,7 +112,7 @@ TEST_F( DbModel, Upgrade3to5 )
{
LoadFakeDB( SRC_DIR "/test/unittest/db_v3.sql" );
auto res = ml->initialize( "test.db", "/tmp", cbMock.get() );
ASSERT_TRUE( res );
ASSERT_EQ( InitializeResult::Success, res );
// All is done during the database initialization, we only care about no
// exception being thrown, and MediaLibrary::initialize() returning true
}
......@@ -121,7 +121,7 @@ TEST_F( DbModel, Upgrade4to5 )
{
LoadFakeDB( SRC_DIR "/test/unittest/db_v4.sql" );
auto res = ml->initialize( "test.db", "/tmp", cbMock.get() );
ASSERT_TRUE( res );
ASSERT_EQ( InitializeResult::DbReset, res );
// The culprit with V4 was an invalid migration, leading to missing fields
// in File and most likely Playlist tables. Simply try to create/fetch a file
......
......@@ -63,10 +63,10 @@ void Tests::Reload( std::shared_ptr<factory::IFileSystem> fs /*= nullptr*/, IMed
ml->setFsFactory( fs );
ml->setDeviceLister( mockDeviceLister );
ml->setVerbosity( LogLevel::Error );
bool res = ml->initialize( "test.db", "/tmp", metadataCb );
ASSERT_TRUE( res );
res = ml->start();
ASSERT_TRUE( res );
auto res = ml->initialize( "test.db", "/tmp", metadataCb );
ASSERT_EQ( InitializeResult::Success, res );
auto startRes = ml->start();
ASSERT_TRUE( startRes );
ml->reload();
}
......
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