From 337533855f09237b8a1e3551b32baa4a87a317b4 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Tue, 20 Jun 2017 23:53:19 +0200 Subject: Fix saving of waveform analysis in database The initialization of the AnalysisDao with the thread-local database connection was missing. The restricted design of the analyzer API required to move the AnalysisDao from AnalyzeWaveform to AnalyzerQueue. --- src/analyzer/analyzerqueue.cpp | 33 ++++++++++++++++++++++++++------- src/analyzer/analyzerqueue.h | 3 +++ src/analyzer/analyzerwaveform.cpp | 13 +++++++------ src/analyzer/analyzerwaveform.h | 6 +++--- src/test/analyserwaveformtest.cpp | 4 +++- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/analyzer/analyzerqueue.cpp b/src/analyzer/analyzerqueue.cpp index ba579fff32..6f25bbd195 100644 --- a/src/analyzer/analyzerqueue.cpp +++ b/src/analyzer/analyzerqueue.cpp @@ -7,11 +7,13 @@ #include "analyzer/analyzergain.h" #include "analyzer/analyzerebur128.h" #include "analyzer/analyzerwaveform.h" +#include "library/dao/analysisdao.h" #include "mixer/playerinfo.h" #include "sources/soundsourceproxy.h" #include "track/track.h" #include "util/compatibility.h" #include "util/db/dbconnectionpooler.h" +#include "util/db/dbconnectionpooled.h" #include "util/event.h" #include "util/timer.h" #include "util/trace.h" @@ -51,7 +53,8 @@ AnalyzerQueue::AnalyzerQueue( m_queue_size(0) { if (mode != Mode::WithoutWaveform) { - m_pAnalyzers.push_back(std::make_unique(pConfig)); + m_pAnalysisDao = std::make_unique(pConfig); + m_pAnalyzers.push_back(std::make_unique(m_pAnalysisDao.get())); } m_pAnalyzers.push_back(std::make_unique(pConfig)); m_pAnalyzers.push_back(std::make_unique(pConfig)); @@ -299,12 +302,21 @@ void AnalyzerQueue::run() { } void AnalyzerQueue::execThread() { - const mixxx::DbConnectionPooler dbConnection(m_pDbConnectionPool); - if (!dbConnection) { - kLogger.warning() - << "Failed to open database connection for analyzer queue"; - kLogger.debug() << "Exiting thread"; - return; + mixxx::DbConnectionPooler dbConnectionPooler; + if (m_pAnalysisDao) { + // Only create/open a new database connection for when needed + // for storing waveform analyses + dbConnectionPooler = mixxx::DbConnectionPooler(m_pDbConnectionPool); + if (!dbConnectionPooler) { + kLogger.warning() + << "Failed to open database connection for analyzer queue thread"; + return; + } + // Use the newly created database connection for this thread + m_pAnalysisDao->initialize(mixxx::DbConnectionPooled(m_pDbConnectionPool)); + // The database connection is valid until dbConnectionPooler is destroyed + // when exiting the enclosing function scope. The pooler as the owner of + // the connection must not be destroyed now! } m_progressInfo.current_track.reset(); @@ -380,6 +392,13 @@ void AnalyzerQueue::execThread() { } emptyCheck(); } + + if (m_pAnalysisDao) { + // Invalidate reference to the thread-local database connection + // that will be closed soon. Not necessary, just in case ;) + m_pAnalysisDao->initialize(QSqlDatabase()); + } + emit(queueEmpty()); // emit in case of exit; } diff --git a/src/analyzer/analyzerqueue.h b/src/analyzer/analyzerqueue.h index b37341a61d..c6c62e97cf 100644 --- a/src/analyzer/analyzerqueue.h +++ b/src/analyzer/analyzerqueue.h @@ -16,6 +16,7 @@ #include "util/memory.h" class Analyzer; +class AnalysisDao; class AnalyzerQueue : public QThread { Q_OBJECT @@ -60,6 +61,8 @@ class AnalyzerQueue : public QThread { mixxx::DbConnectionPoolPtr m_pDbConnectionPool; + std::unique_ptr m_pAnalysisDao; + typedef std::unique_ptr AnalyzerPtr; std::vector m_pAnalyzers; diff --git a/src/analyzer/analyzerwaveform.cpp b/src/analyzer/analyzerwaveform.cpp index 19fb2a8663..eb90ba1627 100644 --- a/src/analyzer/analyzerwaveform.cpp +++ b/src/analyzer/analyzerwaveform.cpp @@ -16,14 +16,15 @@ mixxx::Logger kLogger("AnalyzerWaveform"); } // anonymous AnalyzerWaveform::AnalyzerWaveform( - const UserSettingsPointer& pConfig) : - m_analysisDao(pConfig), + AnalysisDao* pAnalysisDao) : + m_pAnalysisDao(pAnalysisDao), m_skipProcessing(false), m_waveformData(nullptr), m_waveformSummaryData(nullptr), m_stride(0, 0), m_currentStride(0), m_currentSummaryStride(0) { + DEBUG_ASSERT(m_pAnalysisDao); // mandatory m_filter[0] = 0; m_filter[1] = 0; m_filter[2] = 0; @@ -102,7 +103,7 @@ bool AnalyzerWaveform::isDisabledOrLoadStoredSuccess(TrackPointer tio) const { if (trackId.isValid() && (missingWaveform || missingWavesummary)) { QList analyses = - m_analysisDao.getAnalysesForTrack(trackId); + m_pAnalysisDao->getAnalysesForTrack(trackId); QListIterator it(analyses); while (it.hasNext()) { @@ -117,7 +118,7 @@ bool AnalyzerWaveform::isDisabledOrLoadStoredSuccess(TrackPointer tio) const { missingWaveform = false; } else if (vc != WaveformFactory::VC_KEEP) { // remove all other Analysis except that one we should keep - m_analysisDao.deleteAnalysis(analysis.analysisId); + m_pAnalysisDao->deleteAnalysis(analysis.analysisId); } } if (analysis.type == AnalysisDao::TYPE_WAVESUMMARY) { vc = WaveformFactory::waveformSummaryVersionToVersionClass(analysis.version); @@ -127,7 +128,7 @@ bool AnalyzerWaveform::isDisabledOrLoadStoredSuccess(TrackPointer tio) const { missingWavesummary = false; } else if (vc != WaveformFactory::VC_KEEP) { // remove all other Analysis except that one we should keep - m_analysisDao.deleteAnalysis(analysis.analysisId); + m_pAnalysisDao->deleteAnalysis(analysis.analysisId); } } } @@ -309,7 +310,7 @@ void AnalyzerWaveform::finalize(TrackPointer tio) { // waveforms (i.e. if the config setting was disabled in a previous scan) // and then it is not called. The other analyzers have signals which control // the update of their data. - m_analysisDao.saveTrackAnalyses(*tio); + m_pAnalysisDao->saveTrackAnalyses(*tio); kLogger.debug() << "Waveform generation for track" << tio->getId() << "done" << m_timer.elapsed().debugSecondsWithUnit(); diff --git a/src/analyzer/analyzerwaveform.h b/src/analyzer/analyzerwaveform.h index ccc4bdf778..085194707d 100644 --- a/src/analyzer/analyzerwaveform.h +++ b/src/analyzer/analyzerwaveform.h @@ -7,7 +7,6 @@ #include "analyzer/analyzer.h" #include "waveform/waveform.h" -#include "library/dao/analysisdao.h" #include "util/math.h" #include "util/performancetimer.h" @@ -15,6 +14,7 @@ //#define TEST_HEAT_MAP class EngineFilterIIRBase; +class AnalysisDao; inline CSAMPLE scaleSignal(CSAMPLE invalue, FilterIndex index = FilterCount) { if (invalue == 0.0) { @@ -137,7 +137,7 @@ struct WaveformStride { class AnalyzerWaveform : public Analyzer { public: explicit AnalyzerWaveform( - const UserSettingsPointer& pConfig); + AnalysisDao* pAnalysisDao); ~AnalyzerWaveform() override; bool initialize(TrackPointer tio, int sampleRate, int totalSamples) override; @@ -154,7 +154,7 @@ class AnalyzerWaveform : public Analyzer { void destroyFilters(); void storeIfGreater(float* pDest, float source); - mutable AnalysisDao m_analysisDao; + AnalysisDao* m_pAnalysisDao; bool m_skipProcessing; diff --git a/src/test/analyserwaveformtest.cpp b/src/test/analyserwaveformtest.cpp index ad619b842f..8e40121dbb 100644 --- a/src/test/analyserwaveformtest.cpp +++ b/src/test/analyserwaveformtest.cpp @@ -18,7 +18,8 @@ namespace { class AnalyzerWaveformTest: public MixxxTest { protected: AnalyzerWaveformTest() - : aw(config()), + : analysisDao(config()), + aw(&analysisDao), bigbuf(nullptr), canaryBigBuf(nullptr) { } @@ -49,6 +50,7 @@ class AnalyzerWaveformTest: public MixxxTest { } protected: + AnalysisDao analysisDao; AnalyzerWaveform aw; TrackPointer tio; CSAMPLE* bigbuf; -- cgit v1.2.3