File indexing completed on 2024-05-19 04:49:26

0001 /****************************************************************************************
0002  * Copyright (c) 2009 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
0003  * Copyright (c) 2012 Matěj Laitl <matej@laitl.cz>                                      *
0004  *                                                                                      *
0005  * This program is free software; you can redistribute it and/or modify it under        *
0006  * the terms of the GNU General Public License as published by the Free Software        *
0007  * Foundation; either version 2 of the License, or (at your option) any later           *
0008  * version.                                                                             *
0009  *                                                                                      *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0013  *                                                                                      *
0014  * You should have received a copy of the GNU General Public License along with         *
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0016  ****************************************************************************************/
0017 
0018 #include "PersistentStatisticsStore.h"
0019 
0020 #include "core/meta/Meta.h"
0021 #include "core/support/Amarok.h"
0022 #include "core/support/Debug.h"
0023 
0024 const QString PersistentStatisticsStore::s_sqlDateFormat( QStringLiteral("yyyy-MM-dd hh:mm:ss") );
0025 
0026 PersistentStatisticsStore::PersistentStatisticsStore( Meta::Track *track )
0027     : m_track( track )
0028     , m_score( 0.0 )
0029     , m_rating( 0 )
0030     , m_playCount( 0 )
0031     , m_batch( 0 )
0032 {
0033     subscribeTo( track ); // notice the track being deleted
0034 }
0035 
0036 PersistentStatisticsStore::~PersistentStatisticsStore()
0037 {
0038 }
0039 
0040 double
0041 PersistentStatisticsStore::score() const
0042 {
0043     QReadLocker locker( &m_lock );
0044     return m_score;
0045 }
0046 
0047 void
0048 PersistentStatisticsStore::setScore( double newScore )
0049 {
0050     QWriteLocker locker( &m_lock );
0051     m_score = newScore;
0052     commitIfInNonBatchUpdate();
0053 }
0054 
0055 int
0056 PersistentStatisticsStore::rating() const
0057 {
0058     // no lock, int fetching is atomic
0059     return m_rating;
0060 }
0061 
0062 void
0063 PersistentStatisticsStore::setRating( int newRating )
0064 {
0065     QWriteLocker locker( &m_lock );
0066     m_rating = newRating;
0067     commitIfInNonBatchUpdate();
0068 }
0069 
0070 QDateTime
0071 PersistentStatisticsStore::lastPlayed() const
0072 {
0073     QReadLocker locker( &m_lock );
0074     return m_lastPlayed;
0075 }
0076 
0077 void
0078 PersistentStatisticsStore::setLastPlayed( const QDateTime &dt )
0079 {
0080     QWriteLocker locker( &m_lock );
0081     m_lastPlayed = dt;
0082     commitIfInNonBatchUpdate();
0083 }
0084 
0085 QDateTime
0086 PersistentStatisticsStore::firstPlayed() const
0087 {
0088     QReadLocker locker( &m_lock );
0089     return m_firstPlayed;
0090 }
0091 
0092 void
0093 PersistentStatisticsStore::setFirstPlayed( const QDateTime &dt )
0094 {
0095     QWriteLocker locker( &m_lock );
0096     m_firstPlayed = dt;
0097     commitIfInNonBatchUpdate();
0098 }
0099 
0100 int
0101 PersistentStatisticsStore::playCount() const
0102 {
0103     // no lock, in fetching is atomic
0104     return m_playCount;
0105 }
0106 
0107 void
0108 PersistentStatisticsStore::setPlayCount( int playCount )
0109 {
0110     QWriteLocker locker( &m_lock );
0111     m_playCount = playCount;
0112     commitIfInNonBatchUpdate();
0113 }
0114 
0115 void PersistentStatisticsStore::beginUpdate()
0116 {
0117     QWriteLocker locker( &m_lock );
0118     m_batch++;
0119 }
0120 
0121 void PersistentStatisticsStore::endUpdate()
0122 {
0123     QWriteLocker locker( &m_lock );
0124     Q_ASSERT( m_batch > 0 );
0125     m_batch--;
0126     commitIfInNonBatchUpdate();
0127 }
0128 
0129 void
0130 PersistentStatisticsStore::entityDestroyed()
0131 {
0132     QWriteLocker locker( &m_lock );
0133     m_track = nullptr; // prevent stale pointer
0134 }
0135 
0136 void
0137 PersistentStatisticsStore::commitIfInNonBatchUpdate()
0138 {
0139     if( m_batch > 0 )
0140         return;
0141 
0142     save();
0143     if( m_track )
0144     {
0145         m_lock.unlock(); // better call the notify without lock hold to prevent deadlocks
0146         m_track->notifyObservers();
0147         m_lock.lockForWrite();
0148     }
0149 }