Warning, file /multimedia/amarok/src/services/ServiceSqlRegistry.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /**************************************************************************************** 0002 * Copyright (c) 2007 Maximilian Kossick <maximilian.kossick@googlemail.com> * 0003 * * 0004 * This program is free software; you can redistribute it and/or modify it under * 0005 * the terms of the GNU General Public License as published by the Free Software * 0006 * Foundation; either version 2 of the License, or (at your option) any later * 0007 * version. * 0008 * * 0009 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 0010 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 0011 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 0012 * * 0013 * You should have received a copy of the GNU General Public License along with * 0014 * this program. If not, see <http://www.gnu.org/licenses/>. * 0015 ****************************************************************************************/ 0016 0017 #define DEBUG_PREFIX "ServiceSqlRegistry" 0018 0019 #include "ServiceSqlRegistry.h" 0020 0021 #include "core/support/Debug.h" 0022 0023 0024 #include <QMutableHashIterator> 0025 #include <QMutexLocker> 0026 0027 using namespace Meta; 0028 0029 ServiceSqlRegistry::ServiceSqlRegistry( ServiceMetaFactory * metaFactory ) 0030 : QObject( nullptr ) 0031 , m_metaFactory( metaFactory ) 0032 { 0033 setObjectName( QStringLiteral("ServiceSqlRegistry") ); 0034 0035 /* m_timer = new QTimer( this ); 0036 m_timer->setInterval( 60000 ); //try to clean up every 60 seconds, change if necessary 0037 m_timer->setSingleShot( false ); 0038 connect( m_timer, &QTimer::timeout, this, SLOT(emptyCache()) ); 0039 m_timer->start();*/ 0040 } 0041 0042 ServiceSqlRegistry::~ServiceSqlRegistry() 0043 { 0044 //don't delete m_collection 0045 } 0046 0047 TrackPtr 0048 ServiceSqlRegistry::getTrack( const QStringList &rowData ) 0049 { 0050 //test if rowData is the correct length 0051 int correctLength = m_metaFactory->getTrackSqlRowCount() + m_metaFactory->getAlbumSqlRowCount() + m_metaFactory->getArtistSqlRowCount() + m_metaFactory->getGenreSqlRowCount(); 0052 0053 if ( rowData.size() != correctLength ) 0054 return Meta::TrackPtr(); 0055 0056 int id = rowData[0].toInt(); 0057 0058 QMutexLocker locker( &m_trackMutex ); 0059 if( m_trackMap.contains( id ) ) 0060 { 0061 return m_trackMap.value( id ); 0062 } 0063 else 0064 { 0065 int index = 0; 0066 TrackPtr trackPtr = m_metaFactory->createTrack( rowData.mid(index, m_metaFactory->getTrackSqlRowCount() ) ); 0067 index += m_metaFactory->getTrackSqlRowCount(); 0068 0069 ServiceTrack * track = static_cast<ServiceTrack *> ( trackPtr.data() ); 0070 AlbumPtr albumPtr; 0071 0072 if ( m_albumMap.contains( track->albumId() ) ) 0073 albumPtr = m_albumMap.value( track->albumId() ); 0074 else 0075 albumPtr = getAlbum( rowData.mid( index, rowData.count() -1 ) ); 0076 0077 index += m_metaFactory->getAlbumSqlRowCount(); 0078 0079 ServiceAlbum * album = static_cast<ServiceAlbum *> ( albumPtr.data() ); 0080 0081 album->addTrack( trackPtr ); 0082 track->setAlbumPtr( albumPtr ); 0083 0084 m_albumMap.insert( track->albumId(), albumPtr ); 0085 0086 0087 ArtistPtr artistPtr; 0088 0089 if ( m_artistMap.contains( track->artistId() ) ) 0090 artistPtr = m_artistMap.value( track->artistId() ); 0091 else 0092 { 0093 QStringList subRows = rowData.mid(index, m_metaFactory->getArtistSqlRowCount() ); 0094 artistPtr = m_metaFactory->createArtist( subRows ); 0095 } 0096 0097 index += m_metaFactory->getArtistSqlRowCount(); 0098 0099 ServiceArtist * artist = static_cast<ServiceArtist *> ( artistPtr.data() ); 0100 0101 artist->addTrack( trackPtr ); 0102 track->setArtist( artistPtr ); 0103 0104 m_artistMap.insert( track->artistId(), artistPtr ); 0105 0106 GenrePtr genrePtr; 0107 0108 int genreId = rowData[index].toInt(); 0109 0110 if( m_genreMap.contains( genreId ) ) 0111 genrePtr = m_genreMap.value( genreId ); 0112 else 0113 genrePtr = m_metaFactory->createGenre( rowData.mid(index, m_metaFactory->getGenreSqlRowCount() ) ); 0114 0115 ServiceGenre * genre = dynamic_cast<ServiceGenre *> ( genrePtr.data() ); 0116 Q_ASSERT( genre ); 0117 0118 if( genre ) 0119 genre->addTrack( trackPtr ); 0120 0121 track->setGenre( genrePtr ); 0122 0123 m_genreMap.insert( genreId, genrePtr ); 0124 0125 m_trackMap.insert( id, trackPtr ); 0126 return trackPtr; 0127 } 0128 } 0129 0130 ArtistPtr 0131 ServiceSqlRegistry::getArtist( const QStringList &rowData ) 0132 { 0133 int id = rowData[0].toInt(); 0134 0135 QMutexLocker locker( &m_artistMutex ); 0136 if( m_artistMap.contains( id ) ) 0137 return m_artistMap.value( id ); 0138 else 0139 { 0140 ArtistPtr artist = m_metaFactory->createArtist( rowData ); 0141 m_artistMap.insert( id, artist ); 0142 return artist; 0143 } 0144 } 0145 0146 GenrePtr 0147 ServiceSqlRegistry::getGenre( const QStringList &rowData ) 0148 { 0149 int id = rowData[0].toInt(); 0150 QMutexLocker locker( &m_genreMutex ); 0151 if( m_genreMap.contains( id ) ) 0152 return m_genreMap.value( id ); 0153 else 0154 { 0155 GenrePtr genre = m_metaFactory->createGenre( rowData ); 0156 m_genreMap.insert( id, genre ); 0157 return genre; 0158 } 0159 } 0160 0161 /*ComposerPtr 0162 ServiceSqlRegistry::getComposer( const QString &name, int id ) 0163 { 0164 QMutexLocker locker( &m_composerMutex ); 0165 if( m_composerMap.contains( name ) ) 0166 return m_composerMap.value( name ); 0167 else 0168 { 0169 ComposerPtr composer( new SqlComposer( m_collection, id, name ) ); 0170 m_composerMap.insert( name, composer ); 0171 return composer; 0172 } 0173 }*/ 0174 0175 /*YearPtr 0176 ServiceSqlRegistry::getYear( const QString &name, int id ) 0177 { 0178 QMutexLocker locker( &m_yearMutex ); 0179 if( m_yearMap.contains( name ) ) 0180 return m_yearMap.value( name ); 0181 else 0182 { 0183 YearPtr year( new SqlYear( m_collection, id, name ) ); 0184 m_yearMap.insert( name, year ); 0185 return year; 0186 } 0187 }*/ 0188 0189 AlbumPtr 0190 ServiceSqlRegistry::getAlbum( const QStringList &rowData ) 0191 { 0192 int id = rowData[0].toInt(); 0193 QMutexLocker locker( &m_albumMutex ); 0194 if( m_albumMap.contains( id ) ) 0195 return m_albumMap.value( id ); 0196 else 0197 { 0198 int index = 0; 0199 0200 QStringList testString = rowData.mid( index, m_metaFactory->getAlbumSqlRowCount() ); 0201 0202 AlbumPtr albumPtr = m_metaFactory->createAlbum( rowData.mid(index, m_metaFactory->getAlbumSqlRowCount() ) ); 0203 m_albumMap.insert( id, albumPtr ); 0204 0205 index += m_metaFactory->getAlbumSqlRowCount(); 0206 0207 ServiceAlbum* album = static_cast<ServiceAlbum *> ( albumPtr.data() ); 0208 0209 ArtistPtr artistPtr; 0210 0211 // we need to set the artist for this album 0212 if ( m_artistMap.contains( album->artistId() ) ) 0213 artistPtr = m_artistMap.value( album->artistId() ); 0214 else 0215 { 0216 QStringList subRows = rowData.mid(index, m_metaFactory->getArtistSqlRowCount() ); 0217 artistPtr = m_metaFactory->createArtist( subRows ); 0218 } 0219 0220 index += m_metaFactory->getArtistSqlRowCount(); 0221 0222 ServiceArtist * artist = static_cast<ServiceArtist *> ( artistPtr.data() ); 0223 0224 album->setAlbumArtist( artistPtr ); 0225 0226 m_artistMap.insert( artist->id(), artistPtr ); 0227 0228 return albumPtr; 0229 } 0230 } 0231 0232 /* 0233 void 0234 ServiceSqlRegistry::emptyCache() 0235 { 0236 DEBUG_BLOCK 0237 bool hasTrack, hasAlbum, hasArtist, hasYear, hasGenre, hasComposer; 0238 hasTrack = hasAlbum = hasArtist = hasYear = hasGenre = hasComposer = false; 0239 0240 //try to avoid possible deadlocks by aborting when we can't get all locks 0241 if ( ( hasTrack = m_trackMutex.tryLock() ) 0242 && ( hasAlbum = m_albumMutex.tryLock() ) 0243 && ( hasArtist = m_artistMutex.tryLock() ) 0244 && ( hasYear = m_yearMutex.tryLock() ) 0245 && ( hasGenre = m_genreMutex.tryLock() ) 0246 && ( hasComposer = m_composerMutex.tryLock() ) ) 0247 { 0248 //this very simple garbage collector doesn't handle cyclic object graphs 0249 //so care has to be taken to make sure that we are not dealing with a cyclic graph 0250 //by invalidating the tracks cache on all objects 0251 #define foreachInvalidateCache( Type, RealType, x ) \ 0252 for( QMutableHashIterator<QString,Type > iter(x); iter.hasNext(); ) \ 0253 RealType::staticCast( iter.next().value() )->invalidateCache() 0254 0255 foreachInvalidateCache( AlbumPtr, AmarokSharedPointer<SqlAlbum>, m_albumMap ); 0256 foreachInvalidateCache( ArtistPtr, AmarokSharedPointer<SqlArtist>, m_artistMap ); 0257 foreachInvalidateCache( GenrePtr, AmarokSharedPointer<SqlGenre>, m_genreMap ); 0258 foreachInvalidateCache( ComposerPtr, AmarokSharedPointer<SqlComposer>, m_composerMap ); 0259 foreachInvalidateCache( YearPtr, AmarokSharedPointer<SqlYear>, m_yearMap ); 0260 0261 //elem.count() == 2 is correct because elem is one pointer to the object 0262 //and the other is stored in the hash map 0263 #define foreachCollectGarbage( Key, Type, x ) \ 0264 for( QMutableHashIterator<Key,Type > iter(x); iter.hasNext(); ) \ 0265 { \ 0266 Type elem = iter.next().value(); \ 0267 if( elem.count() == 2 ) \ 0268 iter.remove(); \ 0269 } 0270 0271 foreachCollectGarbage( TrackId, TrackPtr, m_trackMap ) 0272 //run before artist so that album artist pointers can be garbage collected 0273 foreachCollectGarbage( QString, AlbumPtr, m_albumMap ) 0274 foreachCollectGarbage( QString, ArtistPtr, m_artistMap ) 0275 foreachCollectGarbage( QString, GenrePtr, m_genreMap ) 0276 foreachCollectGarbage( QString, ComposerPtr, m_composerMap ) 0277 foreachCollectGarbage( QString, YearPtr, m_yearMap ) 0278 } 0279 0280 //make sure to unlock all necessary locks 0281 //important: calling unlock() on an unlocked mutex gives an undefined result 0282 //unlocking a mutex locked by another thread results in an error, so be careful 0283 if( hasTrack ) m_trackMutex.unlock(); 0284 if( hasAlbum ) m_albumMutex.unlock(); 0285 if( hasArtist ) m_artistMutex.unlock(); 0286 if( hasYear ) m_yearMutex.unlock(); 0287 if( hasGenre ) m_genreMutex.unlock(); 0288 if( hasComposer ) m_composerMutex.unlock(); 0289 }*/ 0290 0291 ServiceMetaFactory * ServiceSqlRegistry::factory() 0292 { 0293 return m_metaFactory; 0294 } 0295 0296 0297