Commit 78c00e4e authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Device: Remove outdated devices

parent 885dc3d8
......@@ -40,10 +40,12 @@ Device::Device( MediaLibraryPtr ml, sqlite::Row& row )
>> m_uuid
>> m_scheme
>> m_isRemovable
>> m_isPresent;
>> m_isPresent
>> m_lastSeen;
}
Device::Device( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable )
Device::Device( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme,
bool isRemovable, time_t lastSeen )
: m_ml( ml )
, m_id( 0 )
, m_uuid( uuid )
......@@ -51,6 +53,7 @@ Device::Device( MediaLibraryPtr ml, const std::string& uuid, const std::string&
, m_isRemovable( isRemovable )
// Assume we can't add an absent device
, m_isPresent( true )
, m_lastSeen( lastSeen )
{
}
......@@ -89,12 +92,30 @@ const std::string& Device::scheme() const
return m_scheme;
}
time_t Device::lastSeen() const
{
return m_lastSeen;
}
void Device::updateLastSeen()
{
const std::string req = "UPDATE " + policy::DeviceTable::Name + " SET "
"last_seen = ? WHERE id_device = ?";
auto lastSeen = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
sqlite::Tools::executeUpdate( m_ml->getConn(), req, lastSeen, m_id );
}
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, 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 )
+ "(uuid, scheme, is_removable, is_present, last_seen) VALUES(?, ?, ?, ?, ?)";
auto lastSeen = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
auto self = std::make_shared<Device>( ml, uuid, scheme, isRemovable, lastSeen );
if ( insert( ml, self, req, uuid, scheme, isRemovable, self->isPresent(), lastSeen ) == false )
return nullptr;
return self;
}
......@@ -115,4 +136,13 @@ std::shared_ptr<Device> Device::fromUuid( MediaLibraryPtr ml, const std::string&
return fetch( ml, req, uuid );
}
void Device::removeOldDevices( MediaLibraryPtr ml, std::chrono::seconds maxLifeTime )
{
static const std::string req = "DELETE FROM " + policy::DeviceTable::Name + " "
"WHERE last_seen < ?";
auto deadline = std::chrono::duration_cast<std::chrono::seconds>(
(std::chrono::system_clock::now() - maxLifeTime).time_since_epoch() );
sqlite::Tools::executeDelete( ml->getConn(), req, deadline.count() );
}
}
......@@ -24,6 +24,7 @@
#include "Types.h"
#include "database/DatabaseHelpers.h"
#include <chrono>
namespace medialibrary
{
......@@ -43,7 +44,8 @@ struct DeviceTable
class Device : public DatabaseHelpers<Device, policy::DeviceTable>
{
public:
Device( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable );
Device( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme,
bool isRemovable, time_t insertionDate );
Device( MediaLibraryPtr ml, sqlite::Row& row );
int64_t id() const;
const std::string& uuid() const;
......@@ -57,10 +59,13 @@ public:
/// \return
///
const std::string& scheme() const;
time_t lastSeen() const;
void updateLastSeen();
static std::shared_ptr<Device> create( MediaLibraryPtr ml, const std::string& uuid, const std::string& scheme, bool isRemovable );
static void createTable( sqlite::Connection* connection );
static std::shared_ptr<Device> fromUuid( MediaLibraryPtr ml, const std::string& uuid );
static void removeOldDevices( MediaLibraryPtr ml, std::chrono::seconds maxLifeTime );
private:
MediaLibraryPtr m_ml;
......@@ -72,6 +77,7 @@ private:
std::string m_scheme;
bool m_isRemovable;
bool m_isPresent;
time_t m_lastSeen;
friend struct policy::DeviceTable;
};
......
......@@ -367,6 +367,10 @@ bool MediaLibrary::start()
populateFsFactories();
for ( auto& fsFactory : m_fsFactories )
refreshDevices( *fsFactory );
// Now that we know which devices are plugged, check for outdated devices
// Approximate 6 months for old device precision.
Device::removeOldDevices( this, std::chrono::seconds{ 3600 * 24 * 30 * 6 } );
startDiscoverer();
if ( startParser() == false )
return false;
......@@ -1167,6 +1171,7 @@ void MediaLibrary::migrateModel13to14()
Artist::createTriggers( getConn(), 14 );
Show::createTriggers( getConn() );
Playlist::createTriggers( getConn() );
Folder::createTriggers( getConn() );
t->commit();
}
......@@ -1361,6 +1366,9 @@ void MediaLibrary::refreshDevices( fs::IFileSystemFactory& fsFactory )
}
else
LOG_INFO( "Device ", d->uuid(), " unchanged" );
if ( d->isPresent() == true )
d->updateLastSeen();
}
}
......
......@@ -110,6 +110,26 @@
"INSERT INTO PlaylistMediaRelation SELECT media_id, NULL, playlist_id, position "
"FROM PlaylistMediaRelation_backup",
/******************* Migrate Device table *************************************/
"CREATE TEMPORARY TABLE " + policy::DeviceTable::Name + "_backup"
"("
"id_device INTEGER PRIMARY KEY AUTOINCREMENT,"
"uuid TEXT UNIQUE ON CONFLICT FAIL,"
"scheme TEXT,"
"is_removable BOOLEAN,"
"is_present BOOLEAN"
")",
"INSERT INTO " + DeviceTable::Name + "_backup SELECT * FROM " + DeviceTable::Name,
"DROP TABLE " + DeviceTable::Name,
#include "database/tables/Device_v14.sql"
"INSERT INTO " + DeviceTable::Name + " SELECT id_device, uuid, scheme, is_removable, is_present,"
"strftime('%s', 'now') FROM " + DeviceTable::Name,
/******************* Delete other tables **************************************/
"DROP TABLE " + AlbumTable::Name,
......
......@@ -4,5 +4,6 @@
"uuid TEXT UNIQUE ON CONFLICT FAIL,"
"scheme TEXT,"
"is_removable BOOLEAN,"
"is_present BOOLEAN"
"is_present BOOLEAN,"
"last_seen UNSIGNED INTEGER"
")",
......@@ -214,3 +214,9 @@ void MediaLibraryTester::deleteMedia( int64_t mediaId )
{
Media::destroy( this, mediaId );
}
void MediaLibraryTester::outdateAllDevices()
{
std::string req = "UPDATE " + policy::DeviceTable::Name + " SET last_seen = 1";
sqlite::Tools::executeUpdate( getConn(), req );
}
......@@ -77,6 +77,7 @@ public:
virtual void populateFsFactories();
MediaPtr addMedia( const std::string& mrl );
void deleteMedia( int64_t mediaId );
void outdateAllDevices();
private:
std::shared_ptr<fs::IDirectory> dummyDirectory;
......
......@@ -372,3 +372,20 @@ TEST_F( DeviceFs, UnknownMountpoint )
bool discovered = cbMock->waitDiscovery();
ASSERT_TRUE( discovered );
}
TEST_F( DeviceFs, OutdatedDevices )
{
ml->discover( mock::FileSystemFactory::Root );
bool discovered = cbMock->waitDiscovery();
ASSERT_TRUE( discovered );
ASSERT_EQ( 7u, ml->files().size() );
auto oldMediaCount = ml->files().size();
ml->outdateAllDevices();
fsMock->removeDevice( RemovableDeviceUuid );
Reload();
ASSERT_NE( oldMediaCount, ml->files().size() );
}
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