popov-aa

Atm::DbProvider::Concurrent.cpp

Feb 7th, 2020
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.94 KB | None | 0 0
  1. #include "ConcurrentSqlDatabaseFactory.h"
  2. #include "../Exceptions/OpenDatabase.h"
  3.  
  4. #include <QReadWriteLock>
  5. #include <QThread>
  6.  
  7. Q_LOGGING_CATEGORY( sqlDatabaseFactory, "sqlDatabaseFactory" )
  8.  
  9. namespace Atm { namespace DbProvider { namespace Concurrent {
  10.  
  11. SqlDatabaseFactory::SqlDatabaseFactory( QObject * parent )
  12.   : SqlDatabaseFactory( ConnectionParameters(), parent )
  13. {}
  14.  
  15. SqlDatabaseFactory::SqlDatabaseFactory( const ConnectionParameters & connectionParameters, QObject * parent )
  16.   : QObject( parent )
  17.   , m_connectionParameters( connectionParameters )
  18.   , m_lock( std::make_unique<QReadWriteLock>() )
  19. {}
  20.  
  21. SqlDatabaseFactory::~SqlDatabaseFactory() = default;
  22.  
  23. const ConnectionParameters & SqlDatabaseFactory::connectionParameters() const
  24. {
  25.     return m_connectionParameters;
  26. }
  27.  
  28. void SqlDatabaseFactory::setConnectionParameters( const ConnectionParameters & connectionParameters )
  29. {
  30.     m_connectionParameters = connectionParameters;
  31. }
  32.  
  33. QSqlDatabase SqlDatabaseFactory::getSqlDatabase()
  34. {
  35.     Qt::HANDLE threadId = QThread::currentThreadId();
  36.  
  37.     bool isExists = false;
  38.     QSqlDatabase sqlDatabase;
  39.     m_lock->lockForRead();
  40.     bool isThreadInitialized = m_threadConnections.contains( threadId );
  41.     if ( m_connectionNames.contains( threadId ) ) {
  42.         isExists = true;
  43.         sqlDatabase = QSqlDatabase::database( m_connectionNames[threadId], false );
  44.     }
  45.     m_lock->unlock();
  46.  
  47.     if ( isExists ) {
  48.         bool connectionWasClosed = !sqlDatabase.isOpen();
  49.         bool connectionParametersWasChanged =
  50.           m_connectionParameters != ConnectionParameters::fromSqlDatabase( sqlDatabase );
  51.         if ( connectionWasClosed || connectionParametersWasChanged ) {
  52.             if ( connectionParametersWasChanged ) {
  53.                 if ( !connectionWasClosed ) {
  54.                     sqlDatabase.close();
  55.                 }
  56.                 sqlDatabase = m_connectionParameters.createSqlDatabase( getConnectionName( threadId ) );
  57.             }
  58.             if ( sqlDatabase.open() ) {
  59.                 qCDebug( sqlDatabaseFactory ).noquote()
  60.                   << reconnectionComment( threadId, connectionWasClosed, connectionParametersWasChanged );
  61.             } else {
  62.                 throw Exceptions::OpenDatabase( sqlDatabase.lastError() );
  63.             }
  64.         } else {
  65.             qCDebug( sqlDatabaseFactory ) << "Exists database connection was returned for thread " << threadId;
  66.         }
  67.         return sqlDatabase;
  68.     } else {
  69.         const QString connectionName = getConnectionName( threadId );
  70.         sqlDatabase = m_connectionParameters.createSqlDatabase( connectionName );
  71.         if ( !sqlDatabase.open() ) {
  72.             throw Exceptions::OpenDatabase( sqlDatabase.lastError() );
  73.         }
  74.  
  75.         m_lock->lockForWrite();
  76.         m_connectionNames.insert( threadId, connectionName );
  77.         if ( !isThreadInitialized ) {
  78.             QMetaObject::Connection connection =
  79.               QObject::connect( QThread::currentThread(), &QThread::finished, [threadId, this]() {
  80.                   m_lock->lockForRead();
  81.                   QString connectionName = m_connectionNames.value( threadId );
  82.                   QMetaObject::Connection connection = m_threadConnections.value( threadId );
  83.                   m_lock->unlock();
  84.                   if ( !connectionName.isNull() ) {
  85.                       QSqlDatabase sqlDatabase = QSqlDatabase::database( connectionName );
  86.                       if ( sqlDatabase.isOpen() ) {
  87.                           sqlDatabase.close();
  88.                           sqlDatabase = QSqlDatabase();
  89.                           qCDebug( sqlDatabaseFactory ).noquote()
  90.                             << QString( "Thread %1 was finished, close database connection \"%2\"" )
  91.                                  .arg( threadIdToString( threadId ) )
  92.                                  .arg( connectionName );
  93.                       } else {
  94.                           qCDebug( sqlDatabaseFactory ).noquote()
  95.                             << QString( "Thread %1 was finished, database connection \"%2\" is closed already." )
  96.                                  .arg( threadIdToString( threadId ) )
  97.                                  .arg( connectionName );
  98.                       }
  99.                       QSqlDatabase::removeDatabase( connectionName );
  100.                       m_lock->lockForWrite();
  101.                       m_connectionNames.remove( threadId );
  102.                       m_threadConnections.remove( threadId );
  103.                       m_lock->unlock();
  104.                       QObject::disconnect( connection );
  105.                   }
  106.               } );
  107.             m_threadConnections.insert( threadId, connection );
  108.         }
  109.         m_lock->unlock();
  110.  
  111.         qCDebug( sqlDatabaseFactory ) << "New database connection was created for thread " << threadId;
  112.     }
  113.     return sqlDatabase;
  114. }
  115.  
  116. void SqlDatabaseFactory::removeSqlDatabase()
  117. {}
  118.  
  119. QString SqlDatabaseFactory::threadIdToString( Qt::HANDLE threadId ) const
  120. {
  121.     return QString( "0x%1" ).arg( ulong( threadId ), 0, 16 );
  122. }
  123.  
  124. QString SqlDatabaseFactory::getConnectionName( Qt::HANDLE threadId ) const
  125. {
  126.     return QString( "SqlDatabaseFactory_%1" ).arg( ulong( threadId ), 0, 16 );
  127. }
  128.  
  129. QString SqlDatabaseFactory::reconnectionComment( Qt::HANDLE threadId,
  130.                                                  bool connectionWasClosed,
  131.                                                  bool connectionParametersWasChanged ) const
  132. {
  133.     QString cause;
  134.     if ( connectionWasClosed ) {
  135.         cause.append( "connection was closed" );
  136.     }
  137.     if ( connectionWasClosed && connectionParametersWasChanged ) {
  138.         cause.append( " and " );
  139.     }
  140.     if ( connectionParametersWasChanged ) {
  141.         cause.append( "database parameters was changed" );
  142.     }
  143.     return QString( "Old database connection for thread %1 was created reopened, because %2" )
  144.       .arg( threadIdToString( threadId ) )
  145.       .arg( cause );
  146. }
  147.  
  148. }}} // namespace Atm::DbProvider::Concurrent
Add Comment
Please, Sign In to add comment