From c89a3e8a2f056217c374366eec2914a75973621e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Tue, 20 May 2014 23:27:17 +0300 Subject: [PATCH] Rework object creation & insertion to cache to avoid invalid states. Objects were always created and added to cache, regardless of their status in DB --- src/Cache.h | 37 +++++++++++++++++++++---------------- src/File.cpp | 18 +++++++++--------- src/File.h | 4 +++- src/Label.cpp | 16 ++++++++-------- src/Label.h | 5 +++-- src/MediaLibrary.cpp | 14 ++------------ src/SqliteTools.h | 12 ++++++++++++ 7 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/Cache.h b/src/Cache.h index 31822d97e..831f21378 100644 --- a/src/Cache.h +++ b/src/Cache.h @@ -1,6 +1,7 @@ #ifndef CACHE_H #define CACHE_H +#include #include #include #include @@ -86,22 +87,6 @@ class Cache return inst; } - /* - * Create a new instance of the cache class. - * This doesn't check for the existence of a similar entity already cached. - */ - template - static std::shared_ptr create( Args&&... args ) - { - auto res = std::make_shared( std::forward( args )... ); - - typename CACHEPOLICY::KeyType cacheKey = CACHEPOLICY::key( res ); - - std::lock_guard lock( Mutex ); - Store[cacheKey] = res; - return res; - } - static bool destroy( sqlite3* dbConnection, const typename CACHEPOLICY::KeyType& key ) { std::lock_guard lock( Mutex ); @@ -125,6 +110,26 @@ class Cache Store.clear(); } + protected: + /* + * Create a new instance of the cache class. + */ + template + static unsigned int insert( sqlite3* dbConnection, std::shared_ptr self, const char* req, const Args&... args ) + { + unsigned int pKey = SqliteTools::insert( dbConnection, req, args... ); + if ( pKey == 0 ) + return 0; + auto cacheKey = CACHEPOLICY::key( self ); + + std::lock_guard lock( Mutex ); + // We expect the cache column to be PRIMARY KEY / UNIQUE, so an insertion with + // a duplicated key should have been rejected by sqlite. This indicates an invalid state + assert( Store.find( cacheKey ) == Store.end() ); + Store[cacheKey] = self; + return pKey; + } + private: static std::unordered_map > Store; static std::mutex Mutex; diff --git a/src/File.cpp b/src/File.cpp index 915f7ac0c..0183b3a06 100644 --- a/src/File.cpp +++ b/src/File.cpp @@ -36,18 +36,18 @@ File::File( const std::string& mrl ) { } -bool File::insert( sqlite3* dbConnection ) +FilePtr File::create( sqlite3* dbConnection, const std::string& mrl ) { - assert( m_dbConnection == NULL ); - assert( m_id == 0 ); + auto self = std::make_shared( mrl ); static const std::string req = "INSERT INTO " + policy::FileTable::Name + " VALUES(NULL, ?, ?, ?, ?, ?, ?)"; - if ( SqliteTools::executeRequest( dbConnection, req.c_str(), (int)m_type, m_duration, - m_albumTrackId, m_playCount, m_showEpisodeId, m_mrl ) == false ) - return false; - m_id = sqlite3_last_insert_rowid( dbConnection ); - m_dbConnection = dbConnection; - return true; + auto pKey = _Cache::insert( dbConnection, self, req.c_str(), (int)self->m_type, self->m_duration, + self->m_albumTrackId, self->m_playCount, self->m_showEpisodeId, self->m_mrl ); + if ( pKey == 0 ) + return nullptr; + self->m_id = pKey; + self->m_dbConnection = dbConnection; + return self; } std::shared_ptr File::albumTrack() diff --git a/src/File.h b/src/File.h index fc50fc0ee..e0c7a97ff 100644 --- a/src/File.h +++ b/src/File.h @@ -30,6 +30,8 @@ struct FileCache class File : public IFile, public Cache { + private: + typedef Cache _Cache; public: enum Type { @@ -47,7 +49,7 @@ class File : public IFile, public Cache& Label::files() return *m_files; } -bool Label::insert( sqlite3* dbConnection ) +LabelPtr Label::create( sqlite3* dbConnection, const std::string& name ) { - assert( m_dbConnection == nullptr ); - assert( m_id == 0 ); + auto self = std::make_shared