Skip to content

Commit

Permalink
CoverArtCache - accumulate covers for half second and then update the…
Browse files Browse the repository at this point in the history
… database at once

- sqlite can only do about 50 writes per second, so it is important to collect all new covers and write them at once.
  • Loading branch information
cardinot committed Jul 30, 2014
1 parent 9e64660 commit 806e476
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 5 deletions.
38 changes: 33 additions & 5 deletions src/library/coverartcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <QPixmap>
#include <QStringBuilder>
#include <QtConcurrentRun>
#include <QTimer>

#include "coverartcache.h"
#include "soundsourceproxy.h"
Expand All @@ -11,7 +12,10 @@ CoverArtCache::CoverArtCache()
: m_pCoverArtDAO(NULL),
m_pTrackDAO(NULL),
m_sDefaultCoverLocation(":/images/library/default_cover.png"),
m_defaultCover(m_sDefaultCoverLocation) {
m_defaultCover(m_sDefaultCoverLocation),
m_timer(new QTimer(this)) {
m_timer->setSingleShot(true);
connect(m_timer, SIGNAL(timeout()), SLOT(updateDB()));
}

CoverArtCache::~CoverArtCache() {
Expand Down Expand Up @@ -70,6 +74,12 @@ QPixmap CoverArtCache::requestPixmap(int trackId,
return QPixmap();
}

// check if we have already found a cover for this track
// and if it is just waiting to be inserted/updated in the DB.
if (m_queueOfUpdates.contains(trackId)) {
return QPixmap();
}

// If this request comes from CoverDelegate (table view),
// it'll want to get a cropped cover which is ready to be drawn
// in the table view (cover art column).
Expand Down Expand Up @@ -302,15 +312,33 @@ void CoverArtCache::imageFound() {
}

// update DB
if (res.newImgFound) {
int coverId = m_pCoverArtDAO->saveCoverArt(res.coverLocation,
res.md5Hash);
m_pTrackDAO->updateCoverArt(res.trackId, coverId);
if (res.newImgFound && !m_queueOfUpdates.contains(res.trackId)) {
m_queueOfUpdates.insert(res.trackId,
qMakePair(res.coverLocation, res.md5Hash));
}

if (m_queueOfUpdates.size() == 1 && !m_timer->isActive()) {
m_timer->start(500); // after 0.5s, it will call `updateDB()`
}

m_runningIds.remove(res.trackId);
}

// sqlite can only do about 50 writes per second,

This comment has been minimized.

Copy link
@kain88-de

kain88-de Jul 31, 2014

That number varies hugely between different systems. For SSD's it will be larger. I remember this number from a sqlite doc that I read a few years ago. Please write a date to things like this or at least a source. Otherwise use a more general comment.

// so it is important to collect all new covers and write them at once.
void CoverArtCache::updateDB() {
if (m_queueOfUpdates.isEmpty()) {
return;
}

QList<int> coverIds = m_pCoverArtDAO->saveCoverArt(m_queueOfUpdates.values());

This comment has been minimized.

Copy link
@kain88-de

kain88-de Aug 1, 2014

QHash does not guarantee any order!! You rely on the ordering later in your code. If you need ordering that you have to use a map data structure. In you case I would rather return a QSet<QPair< int, int>>. Simply because only the coverArtDAO will know for which covers the insert worked. You will have a hard time figuring that out later on.


Q_ASSERT(m_queueOfUpdates.keys().size() == coverIds.size());

This comment has been minimized.

Copy link
@kain88-de

kain88-de Aug 1, 2014

Do not use an ASSERT in functions that save stuff to our database. This will crash mixxx which happened to me twice testing your branch.

Instead roll back the database and recover gracefully.

m_pTrackDAO->updateCoverArt(m_queueOfUpdates.keys(), coverIds);

m_queueOfUpdates.clear();
}

// It will return a cropped cover that is ready to be
// used by the tableview-cover_column (CoverDelegate).
// As QImage is optimized to manipulate images, we will do it here
Expand Down
5 changes: 5 additions & 0 deletions src/library/coverartcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class CoverArtCache : public QObject, public Singleton<CoverArtCache>
void imageFound();
void imageLoaded();

private slots:
void updateDB();

signals:
void pixmapFound(int trackId, QPixmap pixmap);

Expand Down Expand Up @@ -63,7 +66,9 @@ class CoverArtCache : public QObject, public Singleton<CoverArtCache>
TrackDAO* m_pTrackDAO;
const QString m_sDefaultCoverLocation;
const QPixmap m_defaultCover;
QTimer* m_timer;
QSet<int> m_runningIds;
QHash<int, QPair<QString, QString> > m_queueOfUpdates;

QString calculateMD5(QImage img);
QImage cropImage(QImage img);
Expand Down

0 comments on commit 806e476

Please sign in to comment.