#include "ormhandler.h" #include "dcxmlconfig.h" #include "log.h" #include "dbrelation.h" #include "threadcontext.h" #include #include #include #include #include using namespace osdev::components; typedef QList Relations; OrmHandler::OrmHandler(QObject *_parent) : QObject( _parent ) , m_qhOrmTables() , m_dbConnection() , m_className( "OrmHandler" ) { m_dbConnection.setCredentials( DCXmlConfig::Instance().getDbCredentials() ); // Check if a watchdog is required and connect those. If a database goes offline, all data should be redirected to the TransQueue. if( DCXmlConfig::Instance().getEnableDbWatchDog() ) { // Start the watchdog and set the interval. m_dbConnection.startDbWatchDog( DCXmlConfig::Instance().getDbCheckInterval() ); } } OrmHandler::~OrmHandler() { } void OrmHandler::start() { // connect the database. LogInfo( m_className, "Connecting to database.." ); if( m_dbConnection.connectDatabase() ) { // Read configuration QStringList tableList = DCXmlConfig::Instance().getOrmTables(); if( 0 == tableList.count() ) { tableList = m_dbConnection.getTableNames(); } LogInfo( m_className, QString("Connected to database %1") .arg( m_dbConnection.getDatabaseName() ) ); // First make sure we have all tables created, before we create all relations... for( const QString& tableName : tableList ) { createOrmObject( tableName ); } // ------------------------------------------------- // Create all relations on the same list of tables. for( const QString& tableName : tableList ) { QString status; // If creation of the object succeeded it is safe to add the relations. switch( createOrmRelation( tableName ) ) { case OrmStatus::OrmStatusFailed: status = "failed."; break; case OrmStatus::OrmStatusNoRelation: status = "not created (As there are none.)"; break; case OrmStatus::OrmStatusSuccess: status = "succeeded."; break; } LogInfo( "[OrmHandler::start]", QString( "Creation of ORM Relation for table : %1 %2" ).arg( tableName ).arg( status ) ); } } else { LogInfo( m_className, QString( "Connection to database %1 failed with error : %2" ) .arg( m_dbConnection.getDatabaseName() ) .arg( m_dbConnection.getLastError() ) ); //@todo : This will produce a SegmentationFault for now due to mutlihreaded pluginloading. // This should be fixed in future releases by implementing a nice rolldown with locking // mechanisms and shutdown events. QMetaObject::invokeMethod( qApp, "quit", Qt::QueuedConnection ); } } bool OrmHandler::createOrmObject( const QString& _table ) { bool l_result = false; OrmTable *pModel = new OrmTable( m_dbConnection, this ); if ( pModel ) { pModel->setTrackField( DCXmlConfig::Instance().getRecordTrackFieldName() ); pModel->setTable( m_dbConnection.quoteTableName( _table ) ); m_qhOrmTables.insert( _table, pModel ); // cascade connect the rejectedsignal. connect( pModel, &OrmTable::signalRejectedData, this, &OrmHandler::signalRejectedData ); l_result = true; } return l_result; } OrmHandler::OrmStatus OrmHandler::createOrmRelation( const QString& _table ) { OrmStatus ormResult = OrmStatus::OrmStatusFailed; Relations lstRelations = m_dbConnection.getRelationByTableName( _table ); if( lstRelations.isEmpty() ) { return OrmStatus::OrmStatusNoRelation; } // Each relation found should be added to the table. for( auto& relation : lstRelations ) { // Save the relation to the table administration. m_qhOrmTables.value( _table )->saveRelation( relation->constraintName(), relation ); // Create a QSortProxyFilterModel and add to the table. QSortFilterProxyModel *pModel = new QSortFilterProxyModel(); pModel->setSourceModel( m_qhOrmTables.value( relation->foreignTable() ) ); m_qhOrmTables.value( _table )->setRelatedTable( relation->foreignTable(), pModel ); } // Check if the number of relations found is equal to the number of relations // added to the ORM-table. if( lstRelations.count() == m_qhOrmTables.value( _table )->numberOfRelations() ) { ormResult = OrmStatus::OrmStatusSuccess; } else { LogDebug( "[OrmHandler::createOrmRelation]", QString( "Number of relations : %1 => Number of relations registered : %2" ).arg( lstRelations.count() ).arg( m_qhOrmTables.value( _table )->numberOfRelations() ) ); ormResult = OrmStatus::OrmStatusFailed; } return ormResult; } void OrmHandler::receiveData( const QSharedPointer& dataContainer ) { ThreadContextScope tcs( dataContainer->traceId() ); LogDebug( "[OrmHandler::receiveData]", dataContainer->asString() ); // Check if we have an actual database running. *if* it died, redirect immediately if( m_dbConnection.isOpen() ) { if( m_qhOrmTables.contains( dataContainer->getMainTableName() ) ) { LogDebug("[OrmHandler::receiveData]", QString("Table entry found for %1").arg( dataContainer->getMainTableName() ) ); m_qhOrmTables.value( dataContainer->getMainTableName() )->writeData( dataContainer ); } else { LogWarning("[OrmHandler::receiveData]", QString("No table entry found for %1").arg( dataContainer->getMainTableName() ) ); emit signalRejectedData( dataContainer ); } } else { emit signalRejectedData( dataContainer ); } } QString OrmHandler::getPrimaryKey( const QString& tableName ) const { if( m_qhOrmTables.contains( tableName ) ) { return m_qhOrmTables.value( tableName )->primaryKey().name(); } return QString(); }