mardi 17 février 2015

Class for synchronization of database access

I have a singleton class for managing database access from multiple threads. The class has to meet the following requirements:



  1. There can be simultaneous read operations, but writing has to be exclusive (no other writes or reads).

  2. A single connection should be reused for multiple queries (within a thread).

  3. Each thread needs to have it's own connection to the database.

  4. The interface should not reveal implementation details and only expose access to resources (so the client is not aware whether it's working with a database, files or memory)


My current solution uses QReadWriteLock which takes care of synchronization, however all threads are using a single database connection, which is not safe. Below is a simplified version.



class ResourceManager
{
public:
bool initialize(const QString& databasePath);
bool shutdown();

static ResourceManager& get()
{
static ResourceManager instance;
return instance;
}

QByteArray getResource(int resourceId)
{
QReadLocker locker(m_lock);
QSqlQuery query(m_db);
// ...
}

bool setResource(int resourceId, QByteArray data)
{
QWriteLocker locker(m_lock);
QSqlQuery query(m_db)
// ...
}

private:
QSqlDatabase m_db;
QReadWriteLock m_lock;
}


My idea is to implement some kind of connections cache, like the following:



QHash<ThreadHandle, QString> m_connectionCache; // thread handle - connection name

// then
if (!m_connectionCache[QThread::currentThread]) // Create new connection
QSqlQuery query(m_connectionCache[QThread::currentThread]);


The problem here is that I can't think of a good clean-up mechanism which would get rid of connections which are no longer needed, so the map will keep growing up with every new thread.


Does it seem like a good idea? Any other suggestions?


Aucun commentaire:

Enregistrer un commentaire