mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-06 06:07:37 +02:00
* Use a separate database connection for each db-worker thread.
This commit is contained in:
@@ -26,12 +26,7 @@
|
|||||||
#include "Source.h"
|
#include "Source.h"
|
||||||
|
|
||||||
#define DEFAULT_WORKER_THREADS 4
|
#define DEFAULT_WORKER_THREADS 4
|
||||||
|
#define MAX_WORKER_THREADS 16
|
||||||
#if ( QT_VERSION >= QT_VERSION_CHECK(4, 8, 2) )
|
|
||||||
#define MAX_WORKER_THREADS 1
|
|
||||||
#else
|
|
||||||
#define MAX_WORKER_THREADS 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Database* Database::s_instance = 0;
|
Database* Database::s_instance = 0;
|
||||||
|
|
||||||
@@ -47,7 +42,7 @@ Database::Database( const QString& dbname, QObject* parent )
|
|||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
, m_ready( false )
|
, m_ready( false )
|
||||||
, m_impl( new DatabaseImpl( dbname, this ) )
|
, m_impl( new DatabaseImpl( dbname, this ) )
|
||||||
, m_workerRW( new DatabaseWorker( m_impl, this, true ) )
|
, m_workerRW( new DatabaseWorker( this, true ) )
|
||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
@@ -105,7 +100,7 @@ Database::enqueue( const QSharedPointer<DatabaseCommand>& lc )
|
|||||||
// create new thread if < WORKER_THREADS
|
// create new thread if < WORKER_THREADS
|
||||||
if ( m_workers.count() < m_maxConcurrentThreads )
|
if ( m_workers.count() < m_maxConcurrentThreads )
|
||||||
{
|
{
|
||||||
DatabaseWorker* worker = new DatabaseWorker( m_impl, this, false );
|
DatabaseWorker* worker = new DatabaseWorker( this, false );
|
||||||
worker->start();
|
worker->start();
|
||||||
|
|
||||||
m_workers << worker;
|
m_workers << worker;
|
||||||
|
@@ -53,12 +53,13 @@ public:
|
|||||||
~Database();
|
~Database();
|
||||||
|
|
||||||
QString dbid() const;
|
QString dbid() const;
|
||||||
bool indexReady() const { return m_indexReady; }
|
|
||||||
|
|
||||||
void loadIndex();
|
void loadIndex();
|
||||||
|
bool indexReady() const { return m_indexReady; }
|
||||||
bool isReady() const { return m_ready; }
|
bool isReady() const { return m_ready; }
|
||||||
|
|
||||||
|
DatabaseImpl* impl() const { return m_impl; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void indexReady(); // search index
|
void indexReady(); // search index
|
||||||
void ready();
|
void ready();
|
||||||
@@ -74,8 +75,6 @@ private slots:
|
|||||||
void setIsReadyTrue() { m_ready = true; }
|
void setIsReadyTrue() { m_ready = true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DatabaseImpl* impl() const { return m_impl; }
|
|
||||||
|
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
DatabaseImpl* m_impl;
|
DatabaseImpl* m_impl;
|
||||||
DatabaseWorker* m_workerRW;
|
DatabaseWorker* m_workerRW;
|
||||||
|
@@ -46,9 +46,7 @@
|
|||||||
|
|
||||||
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
||||||
: QObject( (QObject*) parent )
|
: QObject( (QObject*) parent )
|
||||||
, m_lastartid( 0 )
|
, m_parent( parent )
|
||||||
, m_lastalbid( 0 )
|
|
||||||
, m_lasttrkid( 0 )
|
|
||||||
{
|
{
|
||||||
QTime t;
|
QTime t;
|
||||||
t.start();
|
t.start();
|
||||||
@@ -67,13 +65,10 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
|||||||
m_dbid = uuid();
|
m_dbid = uuid();
|
||||||
query.exec( QString( "INSERT INTO settings(k,v) VALUES('dbid','%1')" ).arg( m_dbid ) );
|
query.exec( QString( "INSERT INTO settings(k,v) VALUES('dbid','%1')" ).arg( m_dbid ) );
|
||||||
}
|
}
|
||||||
tLog() << "Database ID:" << m_dbid;
|
|
||||||
|
|
||||||
// make sqlite behave how we want:
|
tLog() << "Database ID:" << m_dbid;
|
||||||
query.exec( "PRAGMA auto_vacuum = FULL" );
|
init();
|
||||||
query.exec( "PRAGMA synchronous = ON" );
|
|
||||||
query.exec( "PRAGMA foreign_keys = ON" );
|
|
||||||
//query.exec( "PRAGMA temp_store = MEMORY" );
|
|
||||||
tDebug( LOGVERBOSE ) << "Tweaked db pragmas:" << t.elapsed();
|
tDebug( LOGVERBOSE ) << "Tweaked db pragmas:" << t.elapsed();
|
||||||
|
|
||||||
// in case of unclean shutdown last time:
|
// in case of unclean shutdown last time:
|
||||||
@@ -84,7 +79,6 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
|||||||
QTimer::singleShot( 0, this, SLOT( updateIndex() ) );
|
QTimer::singleShot( 0, this, SLOT( updateIndex() ) );
|
||||||
|
|
||||||
tDebug( LOGVERBOSE ) << "Loaded index:" << t.elapsed();
|
tDebug( LOGVERBOSE ) << "Loaded index:" << t.elapsed();
|
||||||
|
|
||||||
if ( qApp->arguments().contains( "--dumpdb" ) )
|
if ( qApp->arguments().contains( "--dumpdb" ) )
|
||||||
{
|
{
|
||||||
dumpDatabase();
|
dumpDatabase();
|
||||||
@@ -93,6 +87,30 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DatabaseImpl::DatabaseImpl( Database* parent, const QString& dbname )
|
||||||
|
: QObject( (QObject*) QThread::currentThread() )
|
||||||
|
, m_parent( parent )
|
||||||
|
{
|
||||||
|
openDatabase( dbname, false );
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DatabaseImpl::init()
|
||||||
|
{
|
||||||
|
m_lastartid = m_lastalbid = m_lasttrkid = 0;
|
||||||
|
|
||||||
|
TomahawkSqlQuery query = newquery();
|
||||||
|
|
||||||
|
// make sqlite behave how we want:
|
||||||
|
query.exec( "PRAGMA auto_vacuum = FULL" );
|
||||||
|
query.exec( "PRAGMA synchronous = ON" );
|
||||||
|
query.exec( "PRAGMA foreign_keys = ON" );
|
||||||
|
//query.exec( "PRAGMA temp_store = MEMORY" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DatabaseImpl::~DatabaseImpl()
|
DatabaseImpl::~DatabaseImpl()
|
||||||
{
|
{
|
||||||
delete m_fuzzyIndex;
|
delete m_fuzzyIndex;
|
||||||
@@ -115,6 +133,16 @@ DatabaseImpl::~DatabaseImpl()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DatabaseImpl*
|
||||||
|
DatabaseImpl::clone() const
|
||||||
|
{
|
||||||
|
DatabaseImpl* impl = new DatabaseImpl( m_parent, m_db.databaseName() );
|
||||||
|
impl->setDatabaseID( m_dbid );
|
||||||
|
impl->setFuzzyIndex( m_fuzzyIndex );
|
||||||
|
return impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DatabaseImpl::dumpDatabase()
|
DatabaseImpl::dumpDatabase()
|
||||||
{
|
{
|
||||||
@@ -681,27 +709,35 @@ DatabaseImpl::resultFromHint( const Tomahawk::query_ptr& origquery )
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DatabaseImpl::openDatabase( const QString& dbname )
|
DatabaseImpl::openDatabase( const QString& dbname, bool checkSchema )
|
||||||
{
|
{
|
||||||
|
const QStringList conns = QSqlDatabase::connectionNames();
|
||||||
|
const QString connName = QString( "tomahawk%1" ).arg( conns.count() ? QString::number( conns.count() ) : "" );
|
||||||
|
|
||||||
bool schemaUpdated = false;
|
bool schemaUpdated = false;
|
||||||
int version = -1;
|
int version = -1;
|
||||||
{
|
{
|
||||||
QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" );
|
QSqlDatabase db = QSqlDatabase::addDatabase( "QSQLITE", connName );
|
||||||
db.setDatabaseName( dbname );
|
db.setDatabaseName( dbname );
|
||||||
if ( !db.open() )
|
if ( !db.open() )
|
||||||
{
|
{
|
||||||
tLog() << "Failed to open database" << dbname;
|
tLog() << "Failed to open database" << dbname;
|
||||||
throw "failed to open db"; // TODO
|
throw "failed to open db"; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
QSqlQuery qry = QSqlQuery( db );
|
if ( checkSchema )
|
||||||
qry.exec( "SELECT v FROM settings WHERE k='schema_version'" );
|
|
||||||
if ( qry.next() )
|
|
||||||
{
|
{
|
||||||
version = qry.value( 0 ).toInt();
|
QSqlQuery qry = QSqlQuery( db );
|
||||||
tLog() << "Database schema of" << dbname << "is" << version;
|
qry.exec( "SELECT v FROM settings WHERE k='schema_version'" );
|
||||||
|
if ( qry.next() )
|
||||||
|
{
|
||||||
|
version = qry.value( 0 ).toInt();
|
||||||
|
tLog() << "Database schema of" << dbname << "is" << version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
version = CURRENT_SCHEMA_VERSION;
|
||||||
|
|
||||||
if ( version < 0 || version == CURRENT_SCHEMA_VERSION )
|
if ( version < 0 || version == CURRENT_SCHEMA_VERSION )
|
||||||
m_db = db;
|
m_db = db;
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,7 @@ public:
|
|||||||
DatabaseImpl( const QString& dbname, Database* parent = 0 );
|
DatabaseImpl( const QString& dbname, Database* parent = 0 );
|
||||||
~DatabaseImpl();
|
~DatabaseImpl();
|
||||||
|
|
||||||
bool openDatabase( const QString& dbname );
|
DatabaseImpl* clone() const;
|
||||||
|
|
||||||
TomahawkSqlQuery newquery() { return TomahawkSqlQuery( m_db ); }
|
TomahawkSqlQuery newquery() { return TomahawkSqlQuery( m_db ); }
|
||||||
QSqlDatabase& database() { return m_db; }
|
QSqlDatabase& database() { return m_db; }
|
||||||
@@ -85,10 +85,17 @@ private slots:
|
|||||||
void updateIndex();
|
void updateIndex();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString cleanSql( const QString& sql );
|
DatabaseImpl( Database* parent, const QString& dbname );
|
||||||
|
void setFuzzyIndex( FuzzyIndex* fi ) { m_fuzzyIndex = fi; }
|
||||||
|
void setDatabaseID( const QString& dbid ) { m_dbid = dbid; }
|
||||||
|
|
||||||
|
void init();
|
||||||
|
bool openDatabase( const QString& dbname, bool checkSchema = true );
|
||||||
bool updateSchema( int oldVersion );
|
bool updateSchema( int oldVersion );
|
||||||
void dumpDatabase();
|
void dumpDatabase();
|
||||||
|
QString cleanSql( const QString& sql );
|
||||||
|
|
||||||
|
Database* m_parent;
|
||||||
bool m_ready;
|
bool m_ready;
|
||||||
QSqlDatabase m_db;
|
QSqlDatabase m_db;
|
||||||
|
|
||||||
|
@@ -34,9 +34,9 @@
|
|||||||
//#define DEBUG_TIMING TRUE
|
//#define DEBUG_TIMING TRUE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DatabaseWorker::DatabaseWorker( DatabaseImpl* lib, Database* db, bool mutates )
|
DatabaseWorker::DatabaseWorker( Database* db, bool mutates )
|
||||||
: QThread()
|
: QThread()
|
||||||
, m_dbimpl( lib )
|
, m_db( db )
|
||||||
, m_outstanding( 0 )
|
, m_outstanding( 0 )
|
||||||
{
|
{
|
||||||
Q_UNUSED( db );
|
Q_UNUSED( db );
|
||||||
@@ -68,6 +68,8 @@ DatabaseWorker::~DatabaseWorker()
|
|||||||
void
|
void
|
||||||
DatabaseWorker::run()
|
DatabaseWorker::run()
|
||||||
{
|
{
|
||||||
|
m_dbimpl = m_db->impl()->clone();
|
||||||
|
tDebug() << "New db connection with name:" << m_dbimpl->database().connectionName();
|
||||||
exec();
|
exec();
|
||||||
qDebug() << Q_FUNC_INFO << "DatabaseWorker finishing...";
|
qDebug() << Q_FUNC_INFO << "DatabaseWorker finishing...";
|
||||||
}
|
}
|
||||||
|
@@ -39,7 +39,7 @@ class DatabaseWorker : public QThread
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DatabaseWorker( DatabaseImpl*, Database*, bool mutates );
|
DatabaseWorker( Database*, bool mutates );
|
||||||
~DatabaseWorker();
|
~DatabaseWorker();
|
||||||
|
|
||||||
bool busy() const { return m_outstanding > 0; }
|
bool busy() const { return m_outstanding > 0; }
|
||||||
@@ -59,6 +59,7 @@ private:
|
|||||||
void logOp( DatabaseCommandLoggable* command );
|
void logOp( DatabaseCommandLoggable* command );
|
||||||
|
|
||||||
QMutex m_mut;
|
QMutex m_mut;
|
||||||
|
Database* m_db;
|
||||||
DatabaseImpl* m_dbimpl;
|
DatabaseImpl* m_dbimpl;
|
||||||
QList< QSharedPointer<DatabaseCommand> > m_commands;
|
QList< QSharedPointer<DatabaseCommand> > m_commands;
|
||||||
int m_outstanding;
|
int m_outstanding;
|
||||||
|
Reference in New Issue
Block a user