Do the compilation processing in the database thread, and make everything lock on the database to ensure two threads don't access it at once.

This commit is contained in:
David Sansome 2010-06-02 16:22:20 +00:00
parent 03d876a599
commit c834a5f31f
9 changed files with 42 additions and 3 deletions

View File

@ -139,12 +139,14 @@ void Database::SqliteLike(sqlite3_context* context, int argc, sqlite3_value** ar
Database::Database(QObject* parent, const QString& database_name)
: QObject(parent),
mutex_(QMutex::Recursive),
injected_database_name_(database_name),
query_hash_(0)
{
directory_ = QDir::toNativeSeparators(
QDir::homePath() + "/.config/" + QCoreApplication::organizationName());
QMutexLocker l(&mutex_);
Connect();
}

View File

@ -40,6 +40,7 @@ class Database : public QObject {
QSqlDatabase Connect();
bool CheckErrors(const QSqlError& error);
QMutex* Mutex() { return &mutex_; }
signals:
void Error(const QString& message);
@ -49,6 +50,7 @@ class Database : public QObject {
QString directory_;
QMutex connect_mutex_;
QMutex mutex_;
// Used by tests
QString injected_database_name_;

View File

@ -76,6 +76,8 @@ void Library::WatcherInitialised() {
backend_, SLOT(AddOrUpdateSubdirs(SubdirectoryList)));
connect(watcher, SIGNAL(SubdirsMTimeUpdated(SubdirectoryList)),
backend_, SLOT(AddOrUpdateSubdirs(SubdirectoryList)));
connect(watcher, SIGNAL(CompilationsNeedUpdating()),
backend_, SLOT(UpdateCompilations()));
// This will start the watcher checking for updates
backend_->LoadDirectoriesAsync();

View File

@ -47,6 +47,7 @@ void LibraryBackend::UpdateTotalSongCountAsync() {
}
void LibraryBackend::LoadDirectories() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("SELECT ROWID, path FROM %1").arg(dirs_table_), db);
@ -63,6 +64,7 @@ void LibraryBackend::LoadDirectories() {
}
SubdirectoryList LibraryBackend::SubdirsInDirectory(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db = db_->Connect();
return SubdirsInDirectory(id, db);
}
@ -87,6 +89,7 @@ SubdirectoryList LibraryBackend::SubdirsInDirectory(int id, QSqlDatabase &db) {
}
void LibraryBackend::UpdateTotalSongCount() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("SELECT COUNT(*) FROM %1").arg(songs_table_), db);
@ -98,6 +101,7 @@ void LibraryBackend::UpdateTotalSongCount() {
}
void LibraryBackend::AddDirectory(const QString &path) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("INSERT INTO %1 (path, subdirs)"
@ -114,6 +118,7 @@ void LibraryBackend::AddDirectory(const QString &path) {
}
void LibraryBackend::RemoveDirectory(const Directory& dir) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
// Remove songs first
@ -141,6 +146,7 @@ void LibraryBackend::RemoveDirectory(const Directory& dir) {
}
SongList LibraryBackend::FindSongsInDirectory(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("SELECT ROWID, " + Song::kColumnSpec +
@ -160,6 +166,7 @@ SongList LibraryBackend::FindSongsInDirectory(int id) {
}
void LibraryBackend::AddOrUpdateSubdirs(const SubdirectoryList& subdirs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery find_query(QString("SELECT ROWID FROM %1"
" WHERE directory = :id AND path = :path")
@ -208,6 +215,7 @@ void LibraryBackend::AddOrUpdateSubdirs(const SubdirectoryList& subdirs) {
}
void LibraryBackend::AddOrUpdateSongs(const SongList& songs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery check_dir(QString("SELECT ROWID FROM %1 WHERE ROWID = :id")
@ -275,6 +283,7 @@ void LibraryBackend::AddOrUpdateSongs(const SongList& songs) {
}
void LibraryBackend::UpdateMTimesOnly(const SongList& songs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("UPDATE %1 SET mtime = :mtime WHERE ROWID = :id")
@ -291,6 +300,7 @@ void LibraryBackend::UpdateMTimesOnly(const SongList& songs) {
}
void LibraryBackend::DeleteSongs(const SongList &songs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("DELETE FROM %1 WHERE ROWID = :id")
@ -314,6 +324,7 @@ QStringList LibraryBackend::GetAllArtists(const QueryOptions& opt) {
query.SetColumnSpec("DISTINCT artist");
query.AddCompilationRequirement(false);
QMutexLocker l(db_->Mutex());
if (!ExecQuery(&query)) return QStringList();
QStringList ret;
@ -339,6 +350,7 @@ SongList LibraryBackend::GetSongs(const QString& artist, const QString& album, c
query.AddWhere("artist", artist);
query.AddWhere("album", album);
QMutexLocker l(db_->Mutex());
if (!ExecQuery(&query)) return SongList();
SongList ret;
@ -351,6 +363,7 @@ SongList LibraryBackend::GetSongs(const QString& artist, const QString& album, c
}
Song LibraryBackend::GetSongById(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("SELECT ROWID, " + Song::kColumnSpec + " FROM %1"
@ -371,6 +384,7 @@ bool LibraryBackend::HasCompilations(const QueryOptions& opt) {
query.SetColumnSpec("ROWID");
query.AddCompilationRequirement(true);
QMutexLocker l(db_->Mutex());
if (!ExecQuery(&query)) return false;
return query.Next();
@ -386,6 +400,7 @@ SongList LibraryBackend::GetCompilationSongs(const QString& album, const QueryOp
query.AddCompilationRequirement(true);
query.AddWhere("album", album);
QMutexLocker l(db_->Mutex());
if (!ExecQuery(&query)) return SongList();
SongList ret;
@ -398,6 +413,7 @@ SongList LibraryBackend::GetCompilationSongs(const QString& album, const QueryOp
}
void LibraryBackend::UpdateCompilations() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
// Look for albums that have songs by more than one artist in the same
@ -513,6 +529,7 @@ LibraryBackend::AlbumList LibraryBackend::GetAlbums(const QString& artist,
query.AddWhere("artist", artist);
}
QMutexLocker l(db_->Mutex());
if (!ExecQuery(&query)) return ret;
QString last_album;
@ -548,6 +565,7 @@ LibraryBackend::Album LibraryBackend::GetAlbumArt(const QString& artist, const Q
query.AddWhere("artist", artist);
query.AddWhere("album", album);
QMutexLocker l(db_->Mutex());
if (!ExecQuery(&query)) return ret;
if (query.Next()) {
@ -570,6 +588,7 @@ void LibraryBackend::UpdateManualAlbumArtAsync(const QString &artist,
void LibraryBackend::UpdateManualAlbumArt(const QString &artist,
const QString &album,
const QString &art) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QString sql(QString("UPDATE %1 SET art_manual = :art"
@ -588,6 +607,7 @@ void LibraryBackend::UpdateManualAlbumArt(const QString &artist,
}
void LibraryBackend::ForceCompilation(const QString& artist, const QString& album, bool on) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
// Get the songs before they're updated

View File

@ -36,6 +36,8 @@ class LibraryBackend : public QObject {
void Init(boost::shared_ptr<Database> db, const QString& songs_table,
const QString& dirs_table, const QString& subdirs_table);
boost::shared_ptr<Database> db() const { return db_; }
struct Album {
Album() {}
Album(const QString& _artist, const QString& _album_name,

View File

@ -18,6 +18,7 @@
#include "librarybackend.h"
#include "libraryitem.h"
#include "librarydirectorymodel.h"
#include "core/database.h"
#include "playlist/songmimedata.h"
#include "ui/iconloader.h"
@ -366,6 +367,7 @@ void LibraryModel::LazyPopulate(LibraryItem* parent, bool signal) {
}
// Execute the query
QMutexLocker l(backend_->db()->Mutex());
if (!backend_->ExecQuery(&q))
return;

View File

@ -171,7 +171,7 @@ void LibraryWatcher::AddDirectory(const Directory& dir, const SubdirectoryList&
}
}
backend_->UpdateCompilations();
emit CompilationsNeedUpdating();
}
void LibraryWatcher::ScanSubdirectory(
@ -388,7 +388,7 @@ void LibraryWatcher::RescanPathsNow() {
rescan_queue_.clear();
backend_->UpdateCompilations();
emit CompilationsNeedUpdating();
}
QString LibraryWatcher::PickBestImage(const QStringList& images) {
@ -448,5 +448,5 @@ void LibraryWatcher::IncrementalScanNow() {
ScanSubdirectory(subdir.path, subdir, &transaction);
}
}
backend_->UpdateCompilations();
emit CompilationsNeedUpdating();
}

View File

@ -48,6 +48,7 @@ class LibraryWatcher : public QObject {
void SongsDeleted(const SongList& songs);
void SubdirsDiscovered(const SubdirectoryList& subdirs);
void SubdirsMTimeUpdated(const SubdirectoryList& subdirs);
void CompilationsNeedUpdating();
void ScanStarted();
void ScanFinished();

View File

@ -30,6 +30,7 @@ PlaylistBackend::PlaylistBackend(QObject* parent)
}
PlaylistBackend::PlaylistList PlaylistBackend::GetAllPlaylists() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
PlaylistList ret;
@ -51,6 +52,7 @@ PlaylistBackend::PlaylistList PlaylistBackend::GetAllPlaylists() {
}
PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, name, last_played FROM playlists"
@ -71,6 +73,7 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) {
}
PlaylistItemList PlaylistBackend::GetPlaylistItems(int playlist) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
PlaylistItemList ret;
@ -116,6 +119,7 @@ void PlaylistBackend::SavePlaylistAsync(int playlist, const PlaylistItemList &it
void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items,
int last_played) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery clear("DELETE FROM playlist_items WHERE playlist = :playlist", db);
@ -154,6 +158,7 @@ void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items,
}
int PlaylistBackend::CreatePlaylist(const QString &name) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("INSERT INTO playlists (name) VALUES (:name)", db);
@ -166,6 +171,7 @@ int PlaylistBackend::CreatePlaylist(const QString &name) {
}
void PlaylistBackend::RemovePlaylist(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery delete_playlist("DELETE FROM playlists WHERE ROWID=:id", db);
QSqlQuery delete_items("DELETE FROM playlist_items WHERE playlist=:id", db);
@ -187,6 +193,7 @@ void PlaylistBackend::RemovePlaylist(int id) {
}
void PlaylistBackend::RenamePlaylist(int id, const QString &new_name) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("UPDATE playlists SET name=:name WHERE ROWID=:id", db);
q.bindValue(":name", new_name);
@ -197,6 +204,7 @@ void PlaylistBackend::RenamePlaylist(int id, const QString &new_name) {
}
void PlaylistBackend::SetPlaylistOrder(const QList<int>& ids) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("UPDATE playlists SET ui_order=:index WHERE ROWID=:id", db);