Commit 73ddf7ae authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

SqliteConnection: Let multiple read requests execute concurrently

parent 797291b0
......@@ -26,6 +26,8 @@
SqliteConnection::SqliteConnection( const std::string &dbPath )
: m_dbPath( dbPath )
, m_readLock( m_contextLock )
, m_writeLock( m_contextLock )
{
if ( sqlite3_threadsafe() == 0 )
throw std::runtime_error( "SQLite isn't built with threadsafe mode" );
......@@ -68,7 +70,12 @@ std::unique_ptr<sqlite::Transaction> SqliteConnection::newTransaction()
return std::unique_ptr<sqlite::Transaction>{ new sqlite::Transaction( this ) };
}
SqliteConnection::RequestContext SqliteConnection::acquireContext()
SqliteConnection::ReadContext SqliteConnection::acquireReadContext()
{
return RequestContext{ m_contextMutex };
return ReadContext{ m_readLock };
}
SqliteConnection::WriteContext SqliteConnection::acquireWriteContext()
{
return WriteContext{ m_writeLock };
}
......@@ -30,6 +30,8 @@
#include <thread>
#include <unordered_map>
#include "utils/SWMRLock.h"
namespace sqlite
{
class Transaction;
......@@ -38,7 +40,8 @@ namespace sqlite
class SqliteConnection
{
public:
using RequestContext = std::unique_lock<std::mutex>;
using ReadContext = std::unique_lock<utils::ReadLocker>;
using WriteContext = std::unique_lock<utils::WriteLocker>;
explicit SqliteConnection( const std::string& dbPath );
// Returns the current thread's connection
......@@ -47,14 +50,17 @@ public:
// Release the current thread's connection
void release();
std::unique_ptr<sqlite::Transaction> newTransaction();
RequestContext acquireContext();
ReadContext acquireReadContext();
WriteContext acquireWriteContext();
private:
using ConnPtr = std::unique_ptr<sqlite3, int(*)(sqlite3*)>;
const std::string m_dbPath;
std::mutex m_connMutex;
std::unordered_map<std::thread::id, ConnPtr> m_conns;
std::mutex m_contextMutex;
utils::SWMRLock m_contextLock;
utils::ReadLocker m_readLock;
utils::WriteLocker m_writeLock;
};
#endif // SQLITECONNECTION_H
......@@ -187,9 +187,9 @@ class Tools
template <typename IMPL, typename INTF, typename... Args>
static std::vector<std::shared_ptr<INTF> > fetchAll( DBConnection dbConnection, const std::string& req, Args&&... args )
{
SqliteConnection::RequestContext ctx;
SqliteConnection::ReadContext ctx;
if (Transaction::transactionInProgress() == false)
ctx = dbConnection->acquireContext();
ctx = dbConnection->acquireReadContext();
auto chrono = std::chrono::steady_clock::now();
std::vector<std::shared_ptr<INTF>> results;
......@@ -210,9 +210,9 @@ class Tools
template <typename T, typename... Args>
static std::shared_ptr<T> fetchOne( DBConnection dbConnection, const std::string& req, Args&&... args )
{
SqliteConnection::RequestContext ctx;
SqliteConnection::ReadContext ctx;
if (Transaction::transactionInProgress() == false)
ctx = dbConnection->acquireContext();
ctx = dbConnection->acquireReadContext();
auto chrono = std::chrono::steady_clock::now();
auto stmt = Statement( dbConnection, req );
......@@ -230,18 +230,18 @@ class Tools
template <typename... Args>
static bool executeRequest( DBConnection dbConnection, const std::string& req, Args&&... args )
{
SqliteConnection::RequestContext ctx;
SqliteConnection::WriteContext ctx;
if (Transaction::transactionInProgress() == false)
ctx = dbConnection->acquireContext();
ctx = dbConnection->acquireWriteContext();
return executeRequestLocked( dbConnection, req, std::forward<Args>( args )... );
}
template <typename... Args>
static bool executeDelete( DBConnection dbConnection, const std::string& req, Args&&... args )
{
SqliteConnection::RequestContext ctx;
SqliteConnection::WriteContext ctx;
if (Transaction::transactionInProgress() == false)
ctx = dbConnection->acquireContext();
ctx = dbConnection->acquireWriteContext();
if ( executeRequestLocked( dbConnection, req, std::forward<Args>( args )... ) == false )
return false;
return sqlite3_changes( dbConnection->getConn() ) > 0;
......@@ -261,9 +261,9 @@ class Tools
template <typename... Args>
static unsigned int insert( DBConnection dbConnection, const std::string& req, Args&&... args )
{
SqliteConnection::RequestContext ctx;
SqliteConnection::WriteContext ctx;
if (Transaction::transactionInProgress() == false)
ctx = dbConnection->acquireContext();
ctx = dbConnection->acquireWriteContext();
if ( executeRequestLocked( dbConnection, req, std::forward<Args>( args )... ) == false )
return 0;
return sqlite3_last_insert_rowid( dbConnection->getConn() );
......
......@@ -31,7 +31,7 @@ thread_local Transaction* Transaction::CurrentTransaction = nullptr;
Transaction::Transaction(DBConnection dbConn)
: m_dbConn( dbConn )
, m_ctx( dbConn->acquireContext() )
, m_ctx( dbConn->acquireWriteContext() )
{
assert( CurrentTransaction == nullptr );
LOG_DEBUG( "Starting SQLite transaction" );
......
......@@ -38,7 +38,7 @@ public:
private:
DBConnection m_dbConn;
SqliteConnection::RequestContext m_ctx;
SqliteConnection::WriteContext m_ctx;
static thread_local Transaction* CurrentTransaction;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment