Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
#
# $Id$
# $HeadURL$
# $Author$
# Created by Hanna Rathje, SLSE, 2017-12-14
#
SET(SRCS_copy
copy_exercise.cpp
copy_exercise.h
exercise_table_generator.cpp
exercise_table_generator.h
settings.cpp
settings.h
)
NGL_ADD_LIBRARY(AAR SV WS dbAdminCopyExercise ${SRCS_copy})
NGL_TARGET_LINK_LIBRARIES(dbAdminCopyExercise
PUBLIC
Qt5::Core
Qt5::Sql
codegen_base
ngldb
NGLLogger
nglsettings
)
NGL_TARGET_INCLUDE_DIRECTORIES(dbAdminCopyExercise
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
)
SET(SRCS
local_databases_model.cpp
local_databases_model.h
logger.cpp
logger.h
db_administration.cpp
db_administration.h
main.cpp
server_databases_model.cpp
server_databases_model.h
showLogFile.cpp
showLogFile.h
)
NGL_WRAP_UI(SRCS ui/db_administration.ui ui/showLogFile.ui)
NGL_ADD_TOOL_ICON(dbAdministration)
NGL_ADD_EXECUTABLE(AAR SV dbAdministration ${SRCS})
NGL_TARGET_LINK_LIBRARIES(dbAdministration
dbAdminCopyExercise
Qt5::Widgets
Qt5::Core
Qt5::Network
nglapplication
ngldb
nglcoreapplication
ngltools
ngltranslator
nglwidgets
NGLLogger
LtsCommandLineParser
)
NGL_INSTALL_TARGET(dbAdministration)
NGL_INSTALL(SV AAR FILES log4cxx_dba.props DESTINATION bin)
+633
View File
@@ -0,0 +1,633 @@
/*
* @RDE_HEADER@
* Copy exercise from server to evaluation server
* $Id: copy_exercise.cpp 64999 2025-07-01 04:02:56Z fritsche_h $
* $HeadURL: svn://192.168.133.21/TDS/branches/product/release_candidates/guez/3dws_rc/Lts/Tools/DBAdministration/copy_exercise.cpp $
* $Author: fritsche_h $
* Created by Christian Ehrlicher, NLSE, 2018-07-31
*/
#include "copy_exercise.h"
#include <ngldb/dbcommon.h>
#include <ngldb/dbconnection.h>
#include <ngldb/nsqlquery.h>
#include <ngltools/ngltools_filesystem.h>
#include <QProcess>
#include <QFile>
#include <QDir>
#include <QSqlError>
#include <QVariant>
namespace DBAdministration
{
CopyExercise::CopyExercise(NGL::INGLLogger &logger, CopyFor copyFor, QObject *parent)
: QObject(parent)
, m_proc(nullptr)
, m_procPing(nullptr)
, m_exerciseId(-1)
, m_copyFor(copyFor)
, m_timer(new QTimer(this))
, m_stopPing(false)
, m_firstPing(false)
, m_progressBarValue(0)
, m_logger(logger)
{
QStringList args({QStringLiteral("-W 10"), // QStringLiteral("10"),
QStringLiteral("-c 6"), //QStringLiteral("6"),
QStringLiteral("EXCDBS01")});
handleProcPing(args);
}
CopyExercise::~CopyExercise()
{
}
bool CopyExercise::init(int exerciseId,
const QString &srcDbHost, const QString &srcDbName,
const QString &dstDbHost, const QString &dstDbName)
{
if (m_exerciseId > 0 )
return true;
m_exerciseId = exerciseId;
m_srcDbName = srcDbName;
m_srcDbHost = srcDbHost;
m_dstDbHost = dstDbHost;
m_dstDbName = dstDbName;
// Server Databases
m_dbSrv = DBConnection::open(m_logger,
QStringLiteral("ctc_sv"),
QStringLiteral("ctc11de"),
QStringLiteral("QPSQL"),
m_srcDbHost,
m_srcDbName,
QString(), // <-- default
m_srcDbHost + QLatin1Char('_') + m_srcDbName + QLatin1Char('_') + QString::number(m_exerciseId));
if (m_copyFor == CopyForEvaluation)
{
m_dbEvaluation = DBConnection::open(m_logger,
QStringLiteral("ctc_sv"),
QStringLiteral("ctc11de"),
QStringLiteral("QPSQL"),
m_dstDbHost,
m_dstDbName,
QString(),
m_dstDbHost + QLatin1Char('_') + m_dstDbName + QLatin1Char('_') + QString::number(m_exerciseId));
if (!m_dbEvaluation.isOpen())
{
WARNING_LOG(m_logger) << "Could not open DB connection to " << m_dstDbHost
<< ", error: " << m_dbEvaluation.lastError().databaseText()
<< ", " << m_dbEvaluation.lastError().driverText();
return false;
}
}
else if (m_copyFor == CopyForAAR)
{
// Only open exercise for creating exercise user
m_dbEvaluation = DBConnection::open(m_logger,
QStringLiteral("postgres"),
QStringLiteral("postgres"),
QStringLiteral("QPSQL"),
m_dstDbHost,
QStringLiteral("postgres"),
QString(),
m_dstDbHost + QLatin1Char('_') + QStringLiteral("postgres") + QLatin1Char('_') + QString::number(m_exerciseId));
if (!m_dbEvaluation.isOpen())
{
WARNING_LOG(m_logger) << "Could not open DB connection to " << m_dstDbHost
<< ", error: " << m_dbEvaluation.lastError().databaseText()
<< ", " << m_dbEvaluation.lastError().driverText();
}
else
{
NSqlQuery q(m_dbEvaluation);
//QString user = QStringLiteral("ets_ex_") + QString::number(m_exerciseId);
QString user = QStringLiteral("ets_ex_00");
QString stmt = QStringLiteral("SELECT create_user_if_not_exists('") + user + QStringLiteral("')");
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error while executing stmt: " << stmt << " error: " << m_dbEvaluation.lastError().databaseText();
else
INFO_LOG(m_logger) << "Created User " << user;
m_dbEvaluation.close();
}
}
if (!m_dbSrv.isOpen())
{
WARNING_LOG(m_logger) << "Could not open DB connection to " << m_srcDbHost
<< ", error: " << m_dbSrv.lastError().databaseText()
<< ", " << m_dbSrv.lastError().driverText();
return false;
}
DEBUG_LOG(m_logger) << "Successfully initialized database connections";
return true;
}
void CopyExercise::setDownloadScriptIds(const QVector<int> &downloadScriptIds)
{
m_downloadScriptIds = downloadScriptIds;
}
bool CopyExercise::doCopy(int exerciseId)
{
m_firstPing = true;
onPingStart();
if (exerciseId > 0)
m_exerciseId = exerciseId;
return true;
}
void CopyExercise::dropDb()
{
const QString dbName = QStringLiteral("lts_db_") + QString::number(m_exerciseId);
INFO_LOG(m_logger) << "Database to be dropped : " << dbName;
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-h"),
QStringLiteral("localhost"),
dbName});
handleProcInit(QStringLiteral("dropdb"), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyExercise::onDropDbFinished2);
m_proc->start();
}
bool CopyExercise::runPgDump()
{
const QString schema = DBCommon::getExerciseSchemaName(m_exerciseId);
QString stmt = QStringLiteral("select sum(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename)))::bigint from pg_tables where schemaname IN ('") + schema +
QStringLiteral("','exm','asm', 'avm', 'bdv', 'core', 'flm', 'aes', 'ism', 'mdm', 'msg', 'opm', 'ppm', 'srm', 'gna', 'tab', 'whg')");
DEBUG_LOG(m_logger) << "stmt: " << stmt;
NSqlQuery q(m_dbSrv);
if (!q.execAndFetch(stmt))
{
ERROR_LOG(m_logger) << "Error while estimating size of database dump errror: " << m_dbSrv.lastError().databaseText();
m_stopPing = true;
return false;
}
m_sizePgDump = q.value(0).toLongLong();
double seconds = m_sizePgDump / 1024 / 100 * 0.0015;
INFO_LOG(m_logger) << "Size database dump: " << m_sizePgDump;
INFO_LOG(m_logger) << " seconds: " << seconds;
m_timer->setInterval(seconds * 1000);
connect(m_timer, &QTimer::timeout, this, &CopyExercise::onTimeoutTimer);
// start process
const QStringList args({
QStringLiteral("-n"), schema,
QStringLiteral("-n"), QStringLiteral("public"),
QStringLiteral("-n"), QStringLiteral("exm"),
QStringLiteral("-n"), QStringLiteral("asm"),
QStringLiteral("-n"), QStringLiteral("avm"),
QStringLiteral("-n"), QStringLiteral("bdv"),
QStringLiteral("-n"), QStringLiteral("core"),
QStringLiteral("-n"), QStringLiteral("flm"),
QStringLiteral("-n"), QStringLiteral("aes"),
QStringLiteral("-n"), QStringLiteral("ism"),
QStringLiteral("-n"), QStringLiteral("mdm"),
QStringLiteral("-n"), QStringLiteral("msg"),
QStringLiteral("-n"), QStringLiteral("opm"),
QStringLiteral("-n"), QStringLiteral("pdm"),
QStringLiteral("-n"), QStringLiteral("ppm"),
QStringLiteral("-n"), QStringLiteral("srm"),
QStringLiteral("-n"), QStringLiteral("gna"),
QStringLiteral("-n"), QStringLiteral("tab"),
QStringLiteral("-n"), QStringLiteral("whg"),
QStringLiteral("-U"), QStringLiteral("postgres"),
QStringLiteral("-Fc"),
QStringLiteral("-f"), getDumpFile(),
QStringLiteral("-h"), m_srcDbHost,
m_srcDbName
});
handleProcInit(QStringLiteral("pg_dump"), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyExercise::onPgDumpFinished);
m_proc->start();
m_progressBarValue = 1;
m_timer->start();
return true;
}
void CopyExercise::onTimeoutTimer()
{
INFO_LOG(m_logger) << "in onTimeoutTimer()";
m_progressBarValue += 1;
INFO_LOG(m_logger) << "emit : " << m_progressBarValue;
emit nextProgress(m_progressBarValue);
}
void CopyExercise::onPgDumpFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
m_timer->stop();
// 1/4 done
m_progressBarValue = 25;
emit nextProgress(m_progressBarValue);
if (!checkExitStatus(QStringLiteral("onPgDumpFinished"), exitCode, exitStatus))
{
QFile::remove(getDumpFile());
dropDb();
return;
}
const QString dbName = QStringLiteral("lts_db_") + QString::number(m_exerciseId);
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-h"),
m_dstDbHost,
dbName});
handleProcInit(QStringLiteral("dropdb"), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyExercise::onDropDbFinished);
m_proc->start();
}
void CopyExercise::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
INFO_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
m_progressBarValue = 30;
emit nextProgress(m_progressBarValue);
const QString dbName = QStringLiteral("lts_db_") + QString::number(m_exerciseId);
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-T"),
QStringLiteral("template2"),
QStringLiteral("-h"),
m_dstDbHost,
dbName});
handleProcInit(QStringLiteral("createdb"), args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyExercise::onCreateDbFinished);
m_proc->start();
}
void CopyExercise::onDropDbFinished2(int exitCode, QProcess::ExitStatus exitStatus)
{
ERROR_LOG(m_logger) << "onDropDbFinished2: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
emit copyDbFailed();
}
void CopyExercise::onCreateDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
INFO_LOG(m_logger) << "onCreateDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
m_progressBarValue = 35;
emit nextProgress(m_progressBarValue);
if (exitCode > 0)
{
ERROR_LOG(m_logger) << "Exercise " << m_exerciseId << " already exists";
QFile::remove(getDumpFile());
emit copyDbFailed();
return;
}
const QString dbName = QStringLiteral("lts_db_") + QString::number(m_exerciseId);
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-h"),
m_dstDbHost,
QStringLiteral("-d"),
dbName,
QStringLiteral("-j"),
QStringLiteral("4"),
getDumpFile(),
});
handleProcInit(QStringLiteral("pg_restore"), args);
if (m_copyFor == CopyForEvaluation)
{
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyExercise::onPsqlFinishedForEvaluation);
}
else
{
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CopyExercise::onPsqlFinishedForAAR);
}
double seconds = m_sizePgDump / 1024 / 100 * 0.001;
INFO_LOG(m_logger) << " seconds: " << seconds;
m_timer->setInterval(seconds * 1000);
m_timer->start();
m_proc->start();
}
void CopyExercise::onPsqlFinishedForEvaluation(int exitCode, QProcess::ExitStatus exitStatus)
{
m_timer->stop();
m_progressBarValue = 75;
emit nextProgress(m_progressBarValue);
if (!checkExitStatus(QStringLiteral("onPsqlFinishedForEvaluation"), exitCode, exitStatus))
return;
if ( exitStatus == QProcess::ExitStatus::NormalExit )
QFile::remove(getDumpFile());
// get exercise data from db
QVariant exName, exStartTime, exEndTime;
{
NSqlQuery q(m_dbSrv);
QString stmt = QStringLiteral("SELECT name, begin_time, end_time FROM exm.exercise WHERE id = ") + QString::number(m_exerciseId);
if (q.execAndFetch(stmt))
{
int i = 0;
exName = q.value(i++);
exStartTime = q.value(i++);
exEndTime = q.value(i++);
}
else
{
ERROR_LOG(m_logger) << "Error while reading exercise info for exercise " << m_exerciseId << " from source database"
<< ", error: " << q.lastError().databaseText()
<< ", " << q.lastError().driverText()
<< ", stmt: " << stmt;
emit copyDbFailed();
m_stopPing = true;
return;
}
}
NSqlQuery q(m_dbEvaluation);
QString stmt = QStringLiteral("INSERT INTO local_databases (name, db_name, begin_time, end_time) "
"VALUES (:name, :dbName, :beginTime, :endTime) ");
q.prepare(stmt);
q.bindValue(QStringLiteral(":name"), exName);
QString dbName = QStringLiteral("lts_db_") + QString::number(m_exerciseId);
q.bindValue(QStringLiteral(":dbName"), dbName);
q.bindValue(QStringLiteral(":beginTime"), exStartTime);
q.bindValue(QStringLiteral(":endTime"), exEndTime);
if (!q.exec())
{
ERROR_LOG(m_logger) << "Error while inserting data in local_databases: exerciseId = " << m_exerciseId
<< ", error: " << q.lastError().databaseText()
<< ", " << q.lastError().driverText();
emit copyDbFailed();
}
else
{
emit copyDbFinished();
}
m_stopPing = true;
m_dbEvaluation.close();
}
void CopyExercise::onPsqlFinishedForAAR(int exitCode, QProcess::ExitStatus exitStatus)
{
m_timer->stop();
m_progressBarValue = 75;
emit nextProgress(m_progressBarValue);
if (!checkExitStatus(QStringLiteral("onPsqlFinishedForAAR"), exitCode, exitStatus))
return;
if ( exitStatus == QProcess::ExitStatus::NormalExit )
QFile::remove(getDumpFile());
//init procedures in schema public
const QString fileName = QStringLiteral("/shd/CTC/AAR/bin/test/init_db_procedures.sql");
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-h"),
m_dstDbHost,
QStringLiteral("-d"),
m_dstDbName,
QStringLiteral("-f"),
fileName
});
handleProcInit(QStringLiteral("psql"), args);
//init procedures in schema public
// now open the downloaded database
if (!m_dbEvaluation.isOpen())
{
m_dbEvaluation = DBConnection::open(m_logger,
QStringLiteral("postgres"),
QStringLiteral("postgres"),
QStringLiteral("QPSQL"),
m_dstDbHost,
m_dstDbName,
QString(),
m_dstDbHost + QLatin1Char('_') + m_dstDbName + QLatin1Char('_') + QString::number(m_exerciseId));
if (!m_dbEvaluation.isOpen())
{
ERROR_LOG(m_logger) << "Could not open DB connection to " << m_dstDbHost
<< ", error: " << m_dbEvaluation.lastError().databaseText()
<< ", " << m_dbEvaluation.lastError().driverText();
emit copyDbFailed();
m_stopPing = true;
return;
}
}
NSqlQuery q(m_dbEvaluation);
const QString schema = DBCommon::getExerciseSchemaName(m_exerciseId);
QStringList downloadScriptIds;
downloadScriptIds.reserve(m_downloadScriptIds.size());
for (int id : qAsConst(m_downloadScriptIds))
downloadScriptIds.push_back(QString::number(id));
QString stmt = QLatin1String("DELETE FROM ") + schema + QLatin1String(".pre_presentation WHERE id not in (") + downloadScriptIds.join(QLatin1Char(',')) + QLatin1Char(')');
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Error while deleting scripts from database";
emit copyDbFailed();
}
else
{
// stmt = QLatin1String("DELETE FROM exm.exercise WHERE id != ") + QString::number(m_exerciseId);
// deleting foreign key will delete all dependences in cascade, so all FLM data for that exercise
stmt = QLatin1String("UPDATE exm.exercise SET exercise_state_id = 6 WHERE id != ") + QString::number(m_exerciseId);
DEBUG_LOG(m_logger) << "Executing statement: " << stmt;
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error on updating exm.exercise " << m_dbEvaluation.lastError().databaseText();
else
DEBUG_LOG(m_logger) << "Statement succesfully executed";
stmt = QLatin1String("GRANT USAGE ON SCHEMA PUBLIC TO ets_ro;");
DEBUG_LOG(m_logger) << "Executing statement: " << stmt;
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error on grant usage " << m_dbEvaluation.lastError().databaseText();
else
DEBUG_LOG(m_logger) << "Statement succesfully executed";
stmt = QLatin1String("GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO ets_ro;");
DEBUG_LOG(m_logger) << "Executing statement: " << stmt;
if (!q.exec(stmt))
ERROR_LOG(m_logger) << "Error on grant execute " << m_dbEvaluation.lastError().databaseText();
else
DEBUG_LOG(m_logger) << "Statement succesfully executed";
emit copyDbFinished();
}
m_stopPing = true;
m_dbEvaluation.close();
}
bool CopyExercise::checkExitStatus(const QString &procName, int exitCode, QProcess::ExitStatus exitStatus)
{
if (exitCode > 0)
{
NOTICE_LOG(m_logger) << procName << ": exitCode: " << exitCode << ", exitStatus: " << exitStatus;
WARNING_LOG(m_logger) << m_proc->readAllStandardError() << m_proc->readAllStandardOutput();
m_stopPing = true;
return false;
}
return true;
}
void CopyExercise::handleProcPing(const QStringList &args)
{
if (m_procPing)
{
m_procPing->disconnect(this);
m_procPing->deleteLater();
}
m_procPing = new QProcess(this);
QString errStr;
const QString exePath = NGL::postgresExecutablePath(QStringLiteral("ping"), errStr);
if (!errStr.isEmpty())
WARNING_LOG(m_logger) << errStr;
INFO_LOG(m_logger) << "Starting process '" << exePath << "' with args '"
<< args.join(QLatin1Char(' ')) << "'";
m_procPing->setProgram(exePath);
m_procPing->setArguments(args);
connect(m_procPing, &QProcess::errorOccurred,
this, &CopyExercise::onErrorOccured);
connect(m_procPing, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &CopyExercise::onPingFinished);
}
void CopyExercise::onPingStart()
{
m_stopPing = false;
m_procPing->start();
INFO_LOG(m_logger) << "ping started ";
}
void CopyExercise::onPingFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
if (exitCode > 0)
DEBUG_LOG(m_logger) << "got ping result with exitCode != 0. exitCode: " << exitCode << ", exitStatus: " << exitStatus;
else
{
if (m_firstPing)
{
m_firstPing = false;
if (!runPgDump())
{
ERROR_LOG(m_logger) << "Error running pg_dump for exercise " << m_exerciseId;
emit copyDbFailed();
m_stopPing = true;
}
}
if (!m_stopPing)
QTimer::singleShot(2000, this, &CopyExercise::onPingStart);
}
}
void CopyExercise::stopPing()
{
m_stopPing = true;
}
void CopyExercise::handleProcInit(const QString &program, const QStringList &args)
{
if (m_proc)
{
m_proc->disconnect(this);
m_proc->deleteLater();
}
m_proc = new QProcess(this);
QString errStr;
const QString exePath = NGL::postgresExecutablePath(program, errStr);
if (!errStr.isEmpty())
WARNING_LOG(m_logger) << errStr;
INFO_LOG(m_logger) << "Starting process '" << exePath << "' with args '"
<< args.join(QLatin1Char(' ')) << "'";
m_proc->setProgram(exePath);
m_proc->setArguments(args);
connect(m_proc, &QProcess::errorOccurred,
this, &CopyExercise::onErrorOccured);
}
void CopyExercise::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
if (!m_proc)
return;
if (exitCode != 0 || exitStatus != 0)
{
QByteArray out = m_proc->readAllStandardError();
if (!out.isEmpty())
out += '\n';
out += m_proc->readAllStandardOutput();
ERROR_LOG(m_logger) << "Process finished - exitCode: " << exitCode << ", exitStatus = " << exitStatus << ", " << out;
}
m_proc->disconnect(this);
m_proc->deleteLater();
m_proc = nullptr;
}
void CopyExercise::onErrorOccured(QProcess::ProcessError error)
{
ERROR_LOG(m_logger) << "onErrorOccured: error: " << error << ", " << m_proc->readAllStandardOutput() << ", " << m_proc->readAllStandardError();
m_timer->stop();
}
QString CopyExercise::getDumpFile() const
{
return QDir::tempPath() + QLatin1Char('/') + m_srcDbName + QLatin1Char('_')+ QString::number(m_exerciseId) + QStringLiteral(".dump");
}
} // namespace DBAdministration
+91
View File
@@ -0,0 +1,91 @@
/*
* @RDE_HEADER@
* Copy exercise from server to evaluation server
* $Id: copy_exercise.h 64999 2025-07-01 04:02:56Z fritsche_h $
* $HeadURL: svn://192.168.133.21/TDS/branches/product/release_candidates/guez/3dws_rc/Lts/Tools/DBAdministration/copy_exercise.h $
* $Author: fritsche_h $
* Created by Christian Ehrlicher, NLSE, 2018-07-31
*/
#pragma once
#include <QObject>
#include <QProcess>
#include <QSqlDatabase>
#include <QVector>
#include <QTimer>
#include <NGLLogger/INGLLogger.h>
namespace DBAdministration
{
class CopyExercise : public QObject
{
Q_OBJECT
public:
enum CopyFor
{
CopyForEvaluation = 0,
CopyForAAR = 1
};
explicit CopyExercise(NGL::INGLLogger &logger, CopyFor copyFor, QObject *parent = nullptr);
~CopyExercise();
bool init(int exerciseId,
const QString &srcDbHost, const QString &srcDbName,
const QString &dstDbHost, const QString &dstDbName);
bool doCopy(int exerciseId = 0);
void setDownloadScriptIds(const QVector<int> &downloadScriptIds);
void stopPing();
QSqlDatabase serverDb() const { return m_dbSrv; }
QSqlDatabase evaluationDb() const { return m_dbEvaluation; }
void handleProcInit(const QString &program, const QStringList &args);
void handleProcPing(const QStringList &args);
Q_SIGNALS:
void copyDbFailed();
void copyDbFinished();
void nextProgress(int);
private:
bool runPgDump();
void onPgDumpFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onCreateDbFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onDropDbFinished2(int exitCode, QProcess::ExitStatus exitStatus);
void onPsqlFinishedForEvaluation(int exitCode, QProcess::ExitStatus exitStatus);
void onPsqlFinishedForAAR(int exitCode, QProcess::ExitStatus exitStatus);
void onPingFinished(int exitCode, QProcess::ExitStatus exitStatus);
bool checkExitStatus(const QString &procName, int exitCode, QProcess::ExitStatus exitStatus);
QString getDumpFile() const;
void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onErrorOccured(QProcess::ProcessError error);
void onTimeoutTimer();
void onPingStart();
void dropDb();
void onTimerCheckFailed();
private:
QString m_srcDbHost;
QString m_srcDbName;
QString m_dstDbHost;
QString m_dstDbName;
QSqlDatabase m_dbSrv;
QSqlDatabase m_dbEvaluation;
QProcess *m_proc;
QProcess *m_procPing;
int m_exerciseId;
CopyFor m_copyFor;
QVector<int> m_downloadScriptIds;
QTimer* m_timer;
bool m_stopPing;
bool m_firstPing;
int m_progressBarValue;
qint64 m_sizePgDump{0};
NGL::INGLLogger &m_logger;
};
} // namespace DBAdministration
+17
View File
@@ -0,0 +1,17 @@
DROP TABLE IF EXISTS local_databases;
CREATE TABLE local_databases (
id serial,
name text,
db_name text,
begin_time bigint,
end_time bigint
);
GRANT INSERT, UPDATE, DELETE, SELECT ON local_databases TO ets_ro;
GRANT USAGE,SELECT ON local_databases_id_seq TO ets_ro;
--insert into local_databases (name, db_name, begin_time, end_time) values ( 'Test1', 'lts_ets', 1000, 2000);
+441
View File
@@ -0,0 +1,441 @@
/*
* @RDE_HEADER@
* <short description>
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Schröder, SLSE, 2016-06-08
*/
#include "db_administration.h"
#include "ui_db_administration.h"
#include "server_databases_model.h"
#include "local_databases_model.h"
#include "settings.h"
#include <ngldb/dbconnection.h>
#include <ngldb/nsqlquery.h>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
#include <QMessageBox>
#include <QTimer>
#include <QMenu>
#include <QSettings>
#include <QDir>
#include <QNetworkInterface>
#include <QHostInfo>
namespace DBAdministration
{
DBAdministration::DBAdministration(QWidget *parent)
: QMainWindow(parent)
, m_ui(new Ui::DBAdministration)
, m_proc(nullptr)
, m_progressDialog(nullptr)
, m_timer(nullptr)
, m_menuBar(new QMenuBar(this))
, m_showLog(new ShowLogFile)
, m_copyExercise(new CopyExercise(getLogger("CopyExercise"), CopyExercise::CopyForEvaluation, this))
, m_bRunsOnEvaluationServer(checkRunsOnEvaluationServer())
, m_logger(getLogger("DBAdministration"))
{
m_ui->setupUi(this);
m_serverDatabasesModel = new ServerDatabasesModel(this);
m_proxyModelServer = new ServerDatabasesProxyModel(this);
m_proxyModelServer->setSourceModel(m_serverDatabasesModel);
m_ui->tableViewServerDatabases->setModel(m_proxyModelServer);
m_localDatabasesModel = new LocalDatabasesModel(this);
m_proxyModelLocal = new LocalDatabasesProxyModel(this);
m_proxyModelLocal->setSourceModel(m_localDatabasesModel);
m_ui->tableViewLocalDatabases->setModel(m_proxyModelLocal);
connect(m_ui->pbCopy, &QPushButton::clicked, this, &DBAdministration::onCopyButtonClicked);
connect(m_ui->pbClose, &QPushButton::clicked, this, &DBAdministration::onClosedClicked);
connect(m_ui->pbRemove, &QPushButton::clicked, this, &DBAdministration::onRemoveClicked);
connect(m_ui->pbActivate, &QPushButton::clicked, this, &DBAdministration::onActivateClicked);
connect(m_ui->tableViewServerDatabases->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DBAdministration::enaDisa);
connect(m_ui->tableViewLocalDatabases->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DBAdministration::enaDisa);
setWindowTitle(QLatin1String("DBAdministration"));
connect(m_ui->actionShow, &QAction::triggered, this, &DBAdministration::onShowLogFile);
connect(m_ui->actionStart, &QAction::triggered, this, &DBAdministration::onStartApp);
connect(m_ui->actionStop, &QAction::triggered, this, &DBAdministration::onStopApp);
connect(m_copyExercise, &CopyExercise::copyDbFailed, this, &DBAdministration::onCopyDbFailed);
connect(m_copyExercise, &CopyExercise::copyDbFinished, this, &DBAdministration::onCopyDbFinished);
m_ui->actionStart->setEnabled(m_bRunsOnEvaluationServer);
m_ui->actionStop->setEnabled(m_bRunsOnEvaluationServer);
m_ui->menuService_Management->setEnabled(m_bRunsOnEvaluationServer);
enaDisa();
}
DBAdministration::~DBAdministration()
{
delete m_ui;
delete m_serverDatabasesModel;
delete m_progressDialog;
delete m_timer;
delete m_menuBar;
delete m_showLog;
if (m_proc)
m_proc->deleteLater();
}
bool DBAdministration::init()
{
if (!m_copyExercise->init(0,
Settings::serverDatabaseHost(),
Settings::serverDatabaseName(),
Settings::evaluationDatabaseHost(),
Settings::evaluationDatabaseName()))
return false;
m_serverDatabasesModel->initModel(m_copyExercise->serverDb());
m_localDatabasesModel->initModel(m_copyExercise->evaluationDb());
m_ui->tableViewServerDatabases->resizeColumnsToContents();
m_ui->tableViewLocalDatabases->resizeColumnsToContents();
return true;
}
void DBAdministration::onClosedClicked()
{
close();
}
void DBAdministration::onRemoveClicked()
{
disableButtons();
m_localDatabaseToRemove = m_localDatabasesModel->getRowData(m_ui->tableViewLocalDatabases->currentIndex().row());
QString strMsg = QStringLiteral("Do you really want to remove the database '%1'?").arg (m_localDatabaseToRemove.dbName);
int result = QMessageBox::question(this, tr("Remove Database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (result == QMessageBox::No)
{
enableButtons();
return;
}
DEBUG_LOG(m_logger) << "onRemoveClicked: dbName = " << m_localDatabaseToRemove.dbName;
const QStringList args({QStringLiteral("-U"),
QStringLiteral("postgres"),
QStringLiteral("-h"),
Settings::evaluationDatabaseHost(),
m_localDatabaseToRemove.dbName
});
QString errStr;
const QString exePath = NGL::postgresExecutablePath(QStringLiteral("dropdb"), errStr);
if (!errStr.isEmpty())
WARNING_LOG(m_logger) << errStr;
handleProcInit(exePath, args);
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &DBAdministration::onDropDbFinished);
// start process
m_proc->start();
}
void DBAdministration::onActivateClicked()
{
LocalExercise le = m_localDatabasesModel->getRowData(m_ui->tableViewLocalDatabases->currentIndex().row());
QString strMsg = QStringLiteral("Do you really want to active database '%1'?").arg(le.dbName);
int result = QMessageBox::question(this, tr("Activate Database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (result == QMessageBox::No)
return;
DEBUG_LOG(m_logger) << "onActivateClicked: dbName = " << le.dbName;
QString configFileName = QStringLiteral("/lts-cc.conf");
QString filename;
QScopedPointer<QSettings> settings;
filename = QDir::homePath() + configFileName;
if (QFile::exists(filename))
{
settings.reset(new QSettings(filename, QSettings::Format::IniFormat));
}
else
{
#ifdef Q_OS_UNIX
filename = QStringLiteral("/etc") + configFileName;
#else
filename = QCoreApplication::applicationDirPath() + QLatin1String("\\") + configFileName;
#endif
if (QFile::exists(filename))
{
settings.reset(new QSettings(filename, QSettings::Format::IniFormat));
}
else
// fallback
settings.reset(new QSettings(QLatin1String("RDE"), QLatin1String("LTS-CC")));
}
ERROR_LOG(m_logger) << "FileName: " << filename;
settings->setValue(QStringLiteral("Global") + QStringLiteral("/DatabaseName"), le.dbName);
}
void DBAdministration::enaDisa()
{
if (!m_ui)
return;
int selected = m_ui->tableViewServerDatabases->selectionModel()->selectedRows().size();
m_ui->pbCopy->setEnabled(selected > 0);
selected = m_ui->tableViewLocalDatabases->selectionModel()->selectedRows().size();
m_ui->pbRemove->setEnabled(selected > 0);
m_ui->pbActivate->setEnabled(selected > 0 && m_bRunsOnEvaluationServer);
}
void DBAdministration::onCopyButtonClicked()
{
disableButtons();
auto exercise = m_serverDatabasesModel->getRowData(m_proxyModelServer->mapToSource(m_ui->tableViewServerDatabases->currentIndex()).row());
m_copyExercise->doCopy(exercise.id);
if (!m_progressDialog)
m_progressDialog = new QProgressDialog(this);
m_progressDialog->setLabelText(tr("Copying database..."));
m_progressDialog->setMinimum(0);
m_progressDialog->setMaximum(0);
m_progressDialog->show();
}
void DBAdministration::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
INFO_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus;
bool bRemoveLocal = true;
if (exitCode > 0)
{
const QString str = QString::fromLocal8Bit(m_proc->readAllStandardError()) + QLatin1Char('\n') +
QString::fromLocal8Bit(m_proc->readAllStandardOutput());
ERROR_LOG(m_logger) << "Can not drop database: " << str;
QString db0 = QLatin1String("ERROR: database \"")+m_localDatabaseToRemove.dbName+QLatin1String("\" does not exist");
if (!str.contains(db0))
{
bRemoveLocal = false;
QMessageBox::critical(this, tr ("Remove Database"), tr("Database cannot be removed:\n%1.").arg(str), QMessageBox::Ok);
}
}
if (bRemoveLocal)
{
NSqlQuery q(m_copyExercise->evaluationDb());
QString stmt = QStringLiteral("DELETE FROM local_databases WHERE id = ") + QString::number(m_localDatabaseToRemove.id);
if (!q.exec(stmt))
QMessageBox::critical(this, tr ("Remove Database"), tr("Database entry cannot be removed."), QMessageBox::Ok);
else
{
m_localDatabasesModel->initModel(m_copyExercise->evaluationDb());
m_ui->tableViewLocalDatabases->resizeColumnsToContents();
}
m_localDatabaseToRemove = LocalExercise();
}
enableButtons();
}
void DBAdministration::onErrorOccured(QProcess::ProcessError error)
{
ERROR_LOG(m_logger) << "error: " << error;
}
void DBAdministration::incrementProgressBar()
{
m_progressDialog->setValue(m_progressDialog->value()+1);
}
void DBAdministration::onShowLogFile()
{
ERROR_LOG(m_logger) << "IN onShowLogFile";
if (!m_showLog->init())
{
QMessageBox::critical(this, tr ("Show Logfile"), tr("Logfile does not exist."), QMessageBox::Ok);
return;
}
m_showLog->show();
}
void DBAdministration::onStartApp()
{
if (!m_bRunsOnEvaluationServer)
return;
handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")});
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &DBAdministration::onPsauxFinished);
m_proc->start();
}
void DBAdministration::onPsauxFinished()
{
enableButtons();
QByteArray output = m_proc->readAllStandardOutput();
if (output.contains("svcServiceManagement"))
{
ERROR_LOG(m_logger) << "ServiceManagement already started";
QMessageBox::critical(this, tr ("Service Management"), tr("Service Management already started."), QMessageBox::Ok);
}
else
{
ERROR_LOG(m_logger) << "Start svcServiceManagement";
handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-z")});
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &DBAdministration::onStartAppFinished);
m_proc->start();
}
}
void DBAdministration::onStartAppFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
handleProcFinished(exitCode, exitStatus);
}
void DBAdministration::onStopApp()
{
if (!m_bRunsOnEvaluationServer)
return;
disableButtons();
handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")});
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &DBAdministration::onPsauxStopFinished);
m_proc->start();
}
void DBAdministration::onPsauxStopFinished()
{
enableButtons();
QByteArray output = m_proc->readAllStandardOutput();
if (output.contains("svcServiceManagement"))
{
ERROR_LOG(m_logger) << "ServiceManagement started - stopping";
handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-s")});
connect(m_proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &DBAdministration::onStopAppFinished);
m_proc->start();
}
else
{
QMessageBox::critical(this, tr("Service Management"), tr("Service Management already stopped."), QMessageBox::Ok);
ERROR_LOG(m_logger) << "ServiceManagement already stopped";
}
}
void DBAdministration::onStopAppFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
handleProcFinished(exitCode, exitStatus);
}
void DBAdministration::onCopyDbFailed()
{
QMessageBox::critical(this, tr ("Exercise"), tr("Could not copy exercise - maybe the exercise already exists."), QMessageBox::Ok);
enableButtons();
m_progressDialog->hide();
}
void DBAdministration::onCopyDbFinished()
{
m_localDatabasesModel->initModel(m_copyExercise->evaluationDb());
m_ui->tableViewLocalDatabases->resizeColumnsToContents();
enableButtons();
m_progressDialog->hide();
}
void DBAdministration::handleProcInit(const QString &program, const QStringList &args)
{
if (m_proc)
{
m_proc->disconnect(this);
m_proc->deleteLater();
}
m_proc = new QProcess(this);
NOTICE_LOG(m_logger) << "Starting process '" << program << "' with args '"
<< args.join(QLatin1Char(' ')) << "'";
m_proc->setProgram(program);
m_proc->setArguments(args);
connect(m_proc, &QProcess::errorOccurred,
this, &DBAdministration::onErrorOccured);
disableButtons();
}
void DBAdministration::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
enableButtons();
if (!m_proc)
return;
if (exitCode != 0 || exitStatus != 0)
{
QByteArray out = m_proc->readAllStandardError();
if (!out.isEmpty())
out += '\n';
out += m_proc->readAllStandardOutput();
ERROR_LOG(m_logger) << "Process finished - exitCode: " << exitCode << ", exitStatus = " << exitStatus << ", " << out;
QMessageBox::critical(this,
tr ("Execute process"), tr("Error executing process, exitCode: %1, exitStatus: %2, output: %3")
.arg(exitCode).arg(exitStatus).arg(QString::fromLocal8Bit(out)),
QMessageBox::Ok);
}
m_proc->disconnect(this);
m_proc->deleteLater();
m_proc = nullptr;
}
void DBAdministration::enaDisaButtons(bool bEnable)
{
{
const QList<QPushButton*> l = findChildren<QPushButton*>();
for (QPushButton *pb : l)
pb->setEnabled(bEnable);
}
{
const QList<QAction*> l = findChildren<QAction*>();
for (QAction *a : l)
a->setEnabled(bEnable);
}
if (bEnable)
enaDisa();
}
bool DBAdministration::checkRunsOnEvaluationServer() const
{
const QHostInfo hostInfoEvaluationDb = QHostInfo::fromName(Settings::evaluationDatabaseHost());
const auto evaluationDbAddresses = hostInfoEvaluationDb.addresses();
if (hostInfoEvaluationDb.addresses().isEmpty())
return false; // we don't know better ...
const QList<QHostAddress> addresses = QNetworkInterface::allAddresses();
for (const QHostAddress &address : addresses)
{
if (address.isLoopback() || address.isNull())
continue;
if (address.protocol() != QAbstractSocket::IPv4Protocol)
continue;
for (const QHostAddress &evaluationAddress : evaluationDbAddresses)
if (address.isEqual(evaluationAddress))
return true;
}
return false;
}
} // namespace DBAdministration
+86
View File
@@ -0,0 +1,86 @@
/*
* @RDE_HEADER@
* <short description>
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Schröder, SLSE, 2016-06-08
*/
#pragma once
#include <QMainWindow>
#include <QMap>
#include <QStandardItemModel>
#include <QVector>
#include <QCloseEvent>
#include <QProcess>
#include <QProgressDialog>
#include <QMenuBar>
#include <QSqlDatabase>
#include "logger.h"
#include "server_databases_model.h"
#include "local_databases_model.h"
#include "showLogFile.h"
#include "copy_exercise.h"
namespace Ui {
class DBAdministration;
}
namespace DBAdministration
{
class DBAdministration : public QMainWindow
{
Q_OBJECT
public:
explicit DBAdministration(QWidget *parent = nullptr);
~DBAdministration();
bool init();
private slots:
void onClosedClicked();
void onRemoveClicked();
void onActivateClicked();
void onCopyButtonClicked();
void onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onErrorOccured(QProcess::ProcessError error);
void incrementProgressBar();
void onShowLogFile();
void onStartApp();
void onStopApp();
void onPsauxFinished();
void onStartAppFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onPsauxStopFinished();
void onStopAppFinished(int exitCode, QProcess::ExitStatus exitStatus);
void onCopyDbFailed();
void onCopyDbFinished();
private:
void enaDisa();
void handleProcInit(const QString &program, const QStringList &args);
void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
void disableButtons() { enaDisaButtons(false); }
void enableButtons() { enaDisaButtons(true); }
void enaDisaButtons(bool bEnable);
bool checkRunsOnEvaluationServer() const;
private:
Ui::DBAdministration *m_ui;
ServerDatabasesModel *m_serverDatabasesModel;
LocalDatabasesModel *m_localDatabasesModel;
ServerDatabasesProxyModel *m_proxyModelServer;
LocalDatabasesProxyModel *m_proxyModelLocal;
QProcess *m_proc;
QProgressDialog *m_progressDialog;
QTimer *m_timer;
QMenuBar *m_menuBar;
ShowLogFile *m_showLog;
LocalExercise m_localDatabaseToRemove;
CopyExercise *m_copyExercise;
bool m_bRunsOnEvaluationServer;
LOGGER_T m_logger;
};
} // namespace DBAdministration
+791
View File
@@ -0,0 +1,791 @@
/**
* EXM Database Administartion (Create Schema/Tables/Views etc)
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-15
*/
#include "exercise_table_generator.h"
#include <ngldb/nsqlquery.h>
#include <ngldb/dbtransaction.h>
#include <QVariant>
#include <QDir>
#include <QDirIterator>
#include <QFile>
#include <QSqlError>
#include <QTextStream>
namespace DBAdministration
{
ExerciseTableGenerator::ExerciseTableGenerator(NGL::INGLLogger &logger, const QString &xmlPath, QObject *parent)
: QObject(parent)
, m_xmlPath(xmlPath)
, m_ownSchemaName(QLatin1String("exm"))
, m_logger(logger)
{
}
// --------------------------------------------------------------------------------------------------------
ExerciseTableGenerator::~ExerciseTableGenerator()
{
qDeleteAll(m_sqlGeneratorMap);
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::existsSchema(const QString &dbSchema, const QSqlDatabase &dbConn) const
{
NSqlQuery q(dbConn);
// Does service schema exist?
QString stmt = QLatin1String("SELECT EXISTS(SELECT 1 FROM information_schema.schemata") +
QLatin1String(" WHERE schema_name = '") + dbSchema + QLatin1String("')");
if (!q.execAndFetch(stmt))
return false;
return q.value(0).toBool();
}
// --------------------------------------------------------------------------------------------------------
//bool ExerciseTableGenerator::createDbSchemaIfNotExists(const QString &dbSchema) const
//{
// // TODO: make product-dependent
// QString dbUser = QLatin1String("ets_") + dbSchema;
// return createDbSchemaIfNotExists(dbSchema, dbUser);
//}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::createDbSchemaIfNotExists(const QString &dbSchema, QString dbUser) const
{
DEBUG_LOG(m_logger) << "createDbSchema: dbSchema = " << dbSchema << ", dbUser = " << dbUser;
if (existsSchema(dbSchema, m_database))
return true;
// Schema doesn't exist => create
QString stmt = QLatin1String("CREATE SCHEMA IF NOT EXISTS ") + dbSchema;
DEBUG_LOG(m_logger) << "# " << stmt;
NSqlQuery q(m_database);
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Can't create schema '" << dbSchema << "' : " << q.getLastSqlError();
return false;
}
// Create specific user for schema (if exercise-related)
if (dbSchema.startsWith(QLatin1String("ex_")))
{
dbUser = QStringLiteral("ets_ex_00");
stmt = QLatin1String("SELECT create_user_if_not_exists('") + dbUser + QLatin1String("');");
DEBUG_LOG(m_logger) << "# " << stmt;
// Use stored procedure (=> create user only if not exists)
if (!q.exec(stmt))
return false;
// Add user to group <product>_ro: not needed anymore, it is included in stored procedure
// stmt = QLatin1String(" GRANT ets_ro TO ") + dbUser;
// DEBUG_LOG(m_logger) << "# " << stmt;
// if (!q.exec(stmt))
// return false;
}
// TODO: make dba user & db groups depend on product => Check/product Name needed somewhere: lts-cc.conf?
// HR: 09.03.2016
stmt = QLatin1String("GRANT USAGE ON SCHEMA ") + dbSchema +
QLatin1String(" TO ets_ro, ets_admin");
DEBUG_LOG(m_logger) << "# " << stmt;
if (!q.exec(stmt))
return false;
// create db_version table needed later for DB Updates
QString stmtDbVersion = QLatin1String("CREATE TABLE IF NOT EXISTS ") + dbSchema + QLatin1String(".db_version (")+
QLatin1String("id serial, ")+
QLatin1String("description text, ")+
QLatin1String("version text, ")+
QLatin1String("updated bigint DEFAULT (extract(epoch from now()) * 1000), ")+
QLatin1String("success boolean DEFAULT true, ")+
QLatin1String("message text);");
stmtDbVersion += QLatin1String("\nINSERT INTO ") + dbSchema + QLatin1String(".db_version (description, version) VALUES ('Create db_version table for all existent DB schemas', '1.00')");
if (!q.exec(stmtDbVersion))
WARNING_LOG(m_logger) << "DB: Could not create db_version table for schema " << dbSchema << "! Error code: " << q.lastError().nativeErrorCode();
else
INFO_LOG(m_logger) << "DB: created db_version table for schema " << dbSchema;
INFO_LOG(m_logger) << "########## DbSchema " << dbSchema << " created with corresponding rights.";
return true;
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::dropDbSchema(const QString &dbSchema, const QString &dbUser) const
{
// Drop Schema
QString stmt = QLatin1String("DROP SCHEMA IF EXISTS ") + dbSchema + QLatin1String(" CASCADE");
DEBUG_LOG(m_logger) << "# " << stmt;
NSqlQuery q(m_database);
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Can't drop schema '" << dbSchema << "' : " << q.getLastSqlError();
return false;
}
// drop only "old" users: ets_ex_42 etc
if (!dbUser.isEmpty() && dbUser != QStringLiteral("ets_ex_00"))
{
// Drop related user
stmt = QLatin1String("DROP USER ") + dbUser;
if (!q.exec(stmt))
WARNING_LOG(m_logger) << "Can't drop user '" << dbUser << "' : " << q.getLastSqlError();
}
return true;
}
/**
* @brief Checks if table exists / is available for dbUser
* (dbUser has the right to see it)
* @param tableName
* @param dbSchema
* @return true on success
*/
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::existsTable(const QString &tableName, const QString &dbSchema) const
{
QString stmt = QLatin1String("SELECT EXISTS ("
" SELECT 1 FROM information_schema.tables "
" WHERE table_schema = '") + dbSchema + QLatin1String("'"
" AND table_name = '") + tableName + QLatin1String("')");
DEBUG_LOG(m_logger) << "stmt: " << stmt;
NSqlQuery q(m_database);
if (!q.execAndFetch(stmt))
{
INFO_LOG(m_logger) << "Table " << tableName << " does not exist in schema " << dbSchema;
return false;
}
return q.value(0).toBool();
}
/**
* @brief ExerciseTableGenerator::init
* @param createOwnSchema
* @return
*/
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::init(const QSqlDatabase &database, const QString &ownSchemaName, bool createOwnSchema)
{
m_database = database;
m_ownSchemaName = ownSchemaName;
if (!createOwnSchema && !existsSchema(m_ownSchemaName, m_database))
{
ERROR_LOG(m_logger) << "Schema of the service (" << m_ownSchemaName << ") doesn't exist, aborting." ;
return false;
}
resetSearchPath();
// Read all xmlFiles in xmlPath
DEBUG_LOG(m_logger) << "xmlPath: " << m_xmlPath;
QFileInfo fi(m_xmlPath);
if (!fi.isDir())
{
ERROR_LOG(m_logger) << "Given xml path '" << m_xmlPath << "' is not a directory";
return false;
}
QDir xmlDir(m_xmlPath);
// Read xmlFiles only
QStringList filters;
filters << QLatin1String("*.xml");
xmlDir.setNameFilters(filters);
qDeleteAll(m_sqlGeneratorMap);
m_sqlGeneratorMap.clear();
QDirIterator dirIt(xmlDir);
while (dirIt.hasNext())
{
const QString xmlFile = dirIt.next();
DEBUG_LOG(m_logger) << "xmlFile: " << xmlFile;
// Init sqlGenerator for xmlFile
CodeGen::SqlGenerator *sqlGen = new CodeGen::SqlGenerator(xmlFile);
if (sqlGen->generateData(0) && sqlGen->isValid())
m_sqlGeneratorMap.insert(sqlGen->getServiceAbbr(), sqlGen);
else
delete sqlGen;
}
DEBUG_LOG(m_logger) << "sqlGen mapSize: " << m_sqlGeneratorMap.size();
emit aliveSignal();
if (createOwnSchema)
{
// Create Schema exm (i.e. for testing)
// TODO: make product-dependent
QString dbUser = QLatin1String("ets_exm");
if (!createDbSchemaIfNotExists(m_ownSchemaName, dbUser))
return false;
if (!executeSqlTableRelated(QStringLiteral("exm"), m_ownSchemaName, dbUser))
return false;
}
return true;
}
void ExerciseTableGenerator::close()
{
m_database = QSqlDatabase();
}
// Write sql-stmts for a service into a file
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::writeServiceSqlToFile(const QString &svcName, const QString &dbSchema)
{
if (!m_sqlGeneratorMap.contains(svcName))
return false;
DEBUG_LOG(m_logger) << "Write sql for service '" << svcName
<< "' with schema '" << dbSchema << "'";
CodeGen::SqlGenerator *sqlGen = m_sqlGeneratorMap.value(svcName);
// do not write to share/Lts/sql to not overwrite the generated files from codegen
QString fullSqlName = QDir::tempPath() + QLatin1Char('/') + svcName + QLatin1Char('_') + dbSchema + QLatin1String(".sql");
if (!sqlGen->writeSqlToFile(dbSchema, fullSqlName, CodeGen::ExerciseDependency::Exercise))
{
ERROR_LOG(m_logger) << "Failed to write sql-stmt to file "
<< fullSqlName;
return false;
}
DEBUG_LOG(m_logger) << "## => Written sql-stmt to '" << fullSqlName << "'";
return true;
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executeSql(const QString &svcName, const QString &dbSchema, QStringList &handledServices, const CodeGen::ExerciseDependency &ed)
{
// TODO: make product-dependent
QString dbUser;
if (dbSchema.startsWith(QLatin1String("ex_")))
dbUser = QLatin1String("ets_ex_00");
else
dbUser = QLatin1String("ets_") + dbSchema;
return executeSql(svcName, dbSchema, dbUser, handledServices, ed);
}
/**
* @brief Execute all sql-stmts for a service
* @param svcName
* @param dbSchema
* @param dbUser
* @return
*/
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executeSql(const QString &svcName, const QString &dbSchema, const QString &dbUser, QStringList &handledServices, const CodeGen::ExerciseDependency &ed)
{
CodeGen::SqlGenerator *sqlGen = m_sqlGeneratorMap.value(svcName);
if (!sqlGen)
return false;
// check if this service was already handled
if (handledServices.contains(svcName))
{
INFO_LOG(m_logger) << "Service already in handledServices: " << svcName;
return true;
}
handledServices += svcName;
INFO_LOG(m_logger) << "Added service to handledServices: " << svcName;
//check if schema is empty at beginning, after executing some statements is not empty anymore
// for exercise dependent services we execute all statements
bool schemaEmpty = schemaIsEmpty(dbSchema) || ed == CodeGen::ExerciseDependency::Exercise;
// first execute all depedent services
const auto deps = sqlGen->getReferencedServices();
for (const QString &depSvc : deps)
{
if (!executeSql(depSvc, dbSchema, dbUser, handledServices, ed))
{
ERROR_LOG(m_logger) << "Failed to execute sql " << depSvc;
return false;
}
}
const QStringList stmts = sqlGen->getAllSqlStmts(dbSchema, ed);
NSqlQuery q(m_database);
int stmtExecuted = 0;
for (const QString &stmt : stmts)
{
if (stmt.isEmpty() || stmt.startsWith(QLatin1String("--")) || stmt.startsWith(QLatin1String("\n--")))
continue;
if ((stmt.startsWith(QLatin1String("DROP TABLE")) || stmt.startsWith(QLatin1String("INSERT INTO"))) && !schemaEmpty)
continue;
if ((stmt.startsWith(QLatin1String("DROP SEQUENCE")) || stmt.startsWith(QLatin1String("CREATE SEQUENCE"))) && !schemaEmpty)
continue;
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Error while executing stmt: '" << stmt << "' : " << q.getLastSqlError();
return false;
}
checkAliveTimer();
NOTICE_LOG(m_logger) << "Statement executed: " << stmt;
++stmtExecuted;
}
DEBUG_LOG(m_logger) << "#" << stmtExecuted << " stmts executed.";
return true;
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::schemaIsEmpty(const QString &dbSchema) const
{
NSqlQuery q(m_database);
QString stmt = QLatin1String("SELECT COUNT(*) FROM information_schema.tables") +
QLatin1String(" WHERE table_schema = '") + dbSchema + QLatin1String("'");
if (!q.exec(stmt))
{
INFO_LOG(m_logger) << "Schema does not exist : " << dbSchema;
return false;
}
q.next();
if (q.value(0).toInt() > 0)
return false;
return true;
}
/**
* @brief Execute only sql stmts for tables & table-related items (Sequences/PK/FK/Indexes)
*
* Note: sql stmts have an 'CREATE <> IF NOT EXISTS'
* Additional check for tableExists necessary for inserting data
* @param svcName
* @param dbSchema
* @param dbUser
* @return
*/
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executeSqlTableRelated(const QString &svcName, const QString &dbSchema, const QString &dbUser)
{
if (!m_sqlGeneratorMap.contains(svcName))
return false;
const CodeGen::SqlGenerator *sqlGen = m_sqlGeneratorMap.value(svcName);
const CodeGen::SqlGenerator::SqlStatements sqlStatements = sqlGen->getStatements(CodeGen::ExerciseDependency::Global);
const CodeGen::SqlGenerator::SqlItems sqlItems = sqlGen->getSqlItems(CodeGen::ExerciseDependency::Global);
// 1. Step: Check which tables will be created
QStringList tablesNewlyCreated;
for (const QString &tableName : sqlItems.tables)
{
if (!existsTable(tableName, dbSchema))
tablesNewlyCreated += tableName;
}
// 2. Step: Set db-environment (privileges/search path)
INFO_LOG(m_logger) << "Create TABLES for dbSchema = " << dbSchema << ", dbUser = " << dbUser;
QStringList sqlStmts = sqlGen->getDbSettings(dbSchema);
// 3. Step: execute stmts
// Note: create sequence if not exists in postgresql 9.5
sqlStmts += sqlStatements.createTables;
if (!executeStmts(sqlStmts))
return false;
INFO_LOG(m_logger) << " #" << tablesNewlyCreated.size() << " tables created. ";
// Primary Keys
if (!executsSqlConstraints(sqlItems.primaryKeys, sqlStatements.createPrimaryKeys, dbSchema))
return false;
// TODO: Foreign Keys
//if (!executsSqlConstraints(sqlGen->getForeignKeys(), sqlStatements.createForeignKeys, dbSchema))
// return false;
// Indexes
if (!executsSqlConstraints(sqlItems.constraints, sqlStatements.createConstraints, dbSchema))
return false;
// 4. Step: Handle sequences separately
sqlStmts = sqlStatements.createSequences;
int listIndexStmts = 0;
for (QString sequenceName : sqlItems.sequences)
{
// TODO: remove when using postgresql 9.5 feature create sequence if not exists
sequenceName.remove(dbSchema + QLatin1Char('.'));
QString stmt = QLatin1String("SELECT exists_sequence('") + sequenceName + QLatin1String("', '")
+ dbSchema + QLatin1String("')");
NSqlQuery q(m_database);
if (!q.execAndFetch(stmt))
return false;
// Sequence exists?
if (!q.value(0).toBool())
q.exec(sqlStmts.at(listIndexStmts));
listIndexStmts++;
}
bool ok = true;
for (const QString &table : qAsConst(tablesNewlyCreated))
{
if (!insertTableData(table, dbSchema, sqlGen))
{
ERROR_LOG(m_logger) << "Failed to insert data for table " << dbSchema << "." << table;
ok &= false;
}
}
return ok;
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executsSqlConstraints(const QStringList &constraintList, const QStringList &sqlStmts,
const QString &dbSchema)
{
int listIndexStmts = 0;
int createdConstraints = 0;
for (const QString &constraintName : constraintList)
{
DEBUG_LOG(m_logger) << "Check constraint '" << constraintName << "'";
// TODO: remove when using postgresql 9.6 feature create constraint if not exists
QString stmt = QLatin1String("SELECT exists_constraint('") + constraintName.toLower() + QLatin1String("', '")
+ dbSchema + QLatin1String("', '") + QLatin1String("i')");
//DEBUG_LOG(m_logger) << "stmt = " << stmt;
NSqlQuery q(m_database);
if (!q.execAndFetch(stmt))
return false;
// Constraint exists?
if (!q.value(0).toBool())
{
DEBUG_LOG(m_logger) << "Constraint '" << constraintName << "' does not exist, creating ..";
if (!q.exec(sqlStmts.at(listIndexStmts)))
return false;
createdConstraints++;
}
listIndexStmts++;
}
INFO_LOG(m_logger) << " #" << createdConstraints << " constraints created. ";
return true;
}
void ExerciseTableGenerator::checkAliveTimer()
{
if (m_emitAliveTimer.elapsed() > 2000) // longer than 2 sec -> send heartbeat
{
emit aliveSignal();
m_emitAliveTimer.start();
}
}
// (Re)Create sql statements for given exercise
// --------------------------------------------------------------------------------------------------------
void ExerciseTableGenerator::generateSqlDataForExercise(int exerciseId)
{
for (CodeGen::SqlGenerator *sqlGen : qAsConst(m_sqlGeneratorMap))
{
// recreate sql statement with correct schema name (e.g. for serials)
if (!sqlGen->generateData(exerciseId))
ERROR_LOG(m_logger) << "Error generating sql for exercise " << exerciseId;
}
}
/**
* @brief ExerciseTableGenerator::executeStmts
* @param stmts
* @return true on success
*/
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executeStmts(const QStringList &stmts)
{
NSqlQuery q(m_database);
int stmtExecuted = 0;
for (const QString &stmt : stmts)
{
if (stmt.isEmpty() || stmt.startsWith(QLatin1String("--")) || stmt.startsWith(QLatin1String("\n--")))
continue;
if (!q.exec(stmt))
{
ERROR_LOG(m_logger) << "Error while executing stmt: '" << stmt << "' : " << q.getLastSqlError();
return false;
}
DEBUG_LOG(m_logger) << "Executed statement: " << stmt;
++stmtExecuted;
}
DEBUG_LOG(m_logger) << "#" << stmtExecuted << " stmts executed.";
return true;
}
/**
* @brief ExerciseTableGenerator::insertTableData
* insert possible static data for newly created table
* @param table
* @param dbSchema
* @return true on success
*/
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::insertTableData(const QString &table, const QString &dbSchema, const CodeGen::SqlGenerator *sqlGen)
{
// inserts are only enumValues
const QStringList &enumInserts = sqlGen->getEnumerationInsertValues(table, dbSchema);
if (!executeStmts(enumInserts))
return false;
INFO_LOG(m_logger) << " #" << enumInserts.count() << " rows inserted for " << dbSchema << "." << table;
// TODO: add other static data
return true;
}
// --------------------------------------------------------------------------------------------------------
// Write sql-stmts to a file for a specific exercise
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::writeExerciseServicesSql(qint32 exerciseId)
{
bool ok = false;
QString schemaName = DBCommon::getExerciseSchemaName(exerciseId);
for (auto it = m_sqlGeneratorMap.constBegin(); it != m_sqlGeneratorMap.constEnd(); ++it)
{
if (!it.value()->isServiceExerciseIndependent())
ok &= writeServiceSqlToFile(it.key(), schemaName);
}
return ok;
}
/**
* @brief getAvailableExerciseServices
* @return
*/
// --------------------------------------------------------------------------------------------------------
QStringList ExerciseTableGenerator::getAvailableExerciseServices() const
{
QStringList services;
for (auto it = m_sqlGeneratorMap.constBegin(); it != m_sqlGeneratorMap.constEnd(); ++it)
{
if (!it.value()->isServiceExerciseIndependent())
services.append(it.key());
}
return services;
}
// --------------------------------------------------------------------------------------------------------
QStringList ExerciseTableGenerator::getAvailableGlobalServices() const
{
QStringList services;
for (auto it = m_sqlGeneratorMap.constBegin(); it != m_sqlGeneratorMap.constEnd(); ++it)
{
// if (it.value()->isServiceExerciseIndependent() || it.value()->getExerciseDependency() == CodeGen::ExerciseDependency::GlobalAndExercise)
if (it.value()->isServiceGlobal())
{
services.append(it.key());
DEBUG_LOG(m_logger) << "Global service found: " << it.key();
}
}
return services;
}
// Execute sql-stmts for a specific exercise (for all exercise-depended services)
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executeSql(qint32 exerciseId)
{
const QStringList services = getAvailableExerciseServices();
// Define schema for given exerciseId
QString schemaName = DBCommon::getExerciseSchemaName(exerciseId);
DEBUG_LOG(m_logger) << "Create schema for EXERCISE " << schemaName;
generateSqlDataForExercise(exerciseId);
m_emitAliveTimer.start();
// Create dbSchema & tables, .. in a transaction
// => can be reverted if an error occured
DBTransaction trans(m_database);
QStringList handledServices;
for (const QString &svcName : services)
{
CodeGen::SqlGenerator *sqlGen = m_sqlGeneratorMap.value(svcName);
if (!sqlGen)
{
ERROR_LOG(m_logger) << "Can not find sqlgen for service " << svcName
<< " - Skipping!";
continue;
}
DEBUG_LOG(m_logger) << "-----------------------------------------------------------------------------";
DEBUG_LOG(m_logger) << "Create exercise dependent tables/views/indexes/.. for service '" << svcName << "', exercise: " << exerciseId;
if (!executeSql(svcName, schemaName, handledServices, CodeGen::ExerciseDependency::Exercise))
{
ERROR_LOG(m_logger) << "Failed to create db-environment (tables/views/indexes/..) for service '" << svcName << "'";
trans.rollback();
return false;
}
checkAliveTimer();
QFile predefinedSql;
QString filePath = m_xmlPath;
filePath.replace(QLatin1String("xml"), QLatin1String("sql"));
DEBUG_LOG(m_logger) << "File Path: " << filePath;
predefinedSql.setFileName(filePath + svcName + QLatin1String("_predefined_data.sql"));
DEBUG_LOG(m_logger) << "Predefined filename " << predefinedSql.fileName();
if (predefinedSql.exists())
{
if (!predefinedSql.open(QIODevice::ReadOnly | QIODevice::Text))
return false;
QStringList predefinedInserts;
QTextStream textStream(&predefinedSql);
while (!textStream.atEnd())
{
QString line = textStream.readLine();
line = line.replace(QStringLiteral("%ex_id%"), QString::number(exerciseId));
DEBUG_LOG(m_logger) << "Line: " << line;
predefinedInserts << line;
}
predefinedSql.close();
DEBUG_LOG(m_logger) << "Executing predefined statements: \n" << predefinedInserts.join(QStringLiteral("\n"));
if (!executeStmts(predefinedInserts))
return false;
checkAliveTimer();
}
INFO_LOG(m_logger) << "db-environment (tables/views/indexes/..) created for service '" << svcName << "'";
}
// Commit all dbChanges
trans.commit();
resetSearchPath();
return true;
}
// Execute sql-stmts for all exercise-independent services
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::executeSql()
{
const QStringList services = getAvailableGlobalServices();
DEBUG_LOG(m_logger) << "Found global services :" << services.size() ;
// Create dbSchema & tables, .. in a transaction
// => can be reverted if an error occured
DBTransaction trans(m_database);
QStringList handledServices;
NSqlQuery querySchemaExists(m_database);
// querySchemaExists.prepare(QStringLiteral("SELECT count(*) FROM information_schema.schemata where schema_name = :sn"));
querySchemaExists.prepare(QStringLiteral("SELECT count(*) FROM information_schema.tables where table_schema = :sn"));
for (const QString &svc : services)
{
// we should not recreate already existing schemas since this will destroy FKs from ex_N.foo.bar_id to <global>.bar.id
querySchemaExists.bindValue(QStringLiteral(":sn"), svc);
if (querySchemaExists.execAndFetch())
{
const int num = querySchemaExists.value(0).toInt();
if (num > 0)
{
DEBUG_LOG(m_logger) << "Schema " << svc << " already exists - skip creating tables for this service";
continue;
}
}
DEBUG_LOG(m_logger) << "-------------------------------------------------------------------------------";
DEBUG_LOG(m_logger) << "Create exercise independent tables/views/indexes/.. for service '" << svc << "'";
if (!executeSql(svc, svc, handledServices, CodeGen::ExerciseDependency::Global))
{
ERROR_LOG(m_logger) << "Failed to create db-environment (tables/views/indexes/..) for service '" << svc << "'";
trans.rollback();
return false;
}
INFO_LOG(m_logger) << "db-environment (tables/views/indexes/..) created for service '" << svc << "'";
}
// Commit all dbChanges
trans.commit();
resetSearchPath();
return true;
}
// Convenience functions
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::createExerciseSchema(qint32 exerciseId)
{
// Define schema for given exerciseId
QString dbSchema = DBCommon::getExerciseSchemaName(exerciseId);
QString dbUser = QLatin1String("ets_ex_00");
return createDbSchemaIfNotExists(dbSchema, dbUser);
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::dropExerciseSchema(qint32 exerciseId, bool bDropUser)
{
// Define schema for given exerciseId
QString dbSchema = DBCommon::getExerciseSchemaName(exerciseId);
// TODO: make product-depended
return dropDbSchema(dbSchema, bDropUser ? QLatin1String("ets_") + dbSchema : QString());
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::resetSearchPath() const
{
// Reset of SEARCH_PATH (has changed in the process of creating a db)
NSqlQuery q(m_database);
QString stmt = QLatin1String("SET SEARCH_PATH TO ") + m_ownSchemaName + QLatin1String(", PUBLIC");
return q.exec(stmt);
}
// --------------------------------------------------------------------------------------------------------
bool ExerciseTableGenerator::isServiceGlobal(const QString &svcAbbr) const
{
CodeGen::SqlGenerator *sqlGen = m_sqlGeneratorMap.value(svcAbbr);
if (!sqlGen)
return false;
return sqlGen->isServiceGlobal();
}
} // namespace DBAdministration
+91
View File
@@ -0,0 +1,91 @@
/**
* EXM Database Administartion (Create Schema/Tables/Views etc)
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-15
*/
#pragma once
#include <QElapsedTimer>
#include <QString>
#include <QStringList>
#include <QMap>
#include <QSqlDatabase>
#include <CodeGen/SqlGenerator.h>
#include <NGLLogger/INGLLogger.h>
namespace CodeGen
{
class SqlGenerator;
}
namespace DBAdministration
{
class ExerciseTableGenerator : public QObject
{
Q_OBJECT
public:
explicit ExerciseTableGenerator(NGL::INGLLogger &logger, const QString &xmlPath, QObject *parent = nullptr);
virtual ~ExerciseTableGenerator();
bool init(const QSqlDatabase &database, const QString &ownSchemaName, bool createOwnSchema = false);
void close();
QStringList getAvailableServices() const { return m_sqlGeneratorMap.keys(); }
bool isServiceGlobal(const QString &svcAbbr) const;
// Write sql-stmt for a service into a file
bool writeServiceSqlToFile(const QString &svcName, const QString &dbSchema);
bool executeSql(const QString &svcName, const QString &dbSchema, QStringList &handledServices, const CodeGen::ExerciseDependency &ed);
bool executeSql(const QString &svcName, const QString &dbSchema, const QString &dbUser, QStringList &handledServices, const CodeGen::ExerciseDependency &ed);
// TODO: better naming
bool executeSqlTableRelated(const QString &svcName, const QString &dbSchema, const QString &dbUser);
bool existsSchema(const QString &dbSchema, const QSqlDatabase &dbConn) const;
//bool createDbSchemaIfNotExists(const QString &dbSchema) const;
bool createDbSchemaIfNotExists(const QString &dbSchema, QString dbUser) const;
bool dropDbSchema(const QString &dbSchema, const QString &dbUser) const;
bool existsTable(const QString &tableName, const QString &dbSchema) const;
bool insertTableData(const QString &table, const QString &dbSchema, const CodeGen::SqlGenerator *sqlGen );
bool executeSql();
// Methods for a specific exercise
bool writeExerciseServicesSql(qint32 exerciseId);
bool executeSql(qint32 exerciseId);
bool createExerciseSchema(qint32 exerciseId);
bool dropExerciseSchema(qint32 exerciseId, bool bDropUser);
QStringList getAvailableExerciseServices() const;
QStringList getAvailableGlobalServices() const;
bool resetSearchPath() const;
bool schemaIsEmpty(const QString &dbSchema) const;
Q_SIGNALS:
void aliveSignal();
protected:
void generateSqlDataForExercise(int exerciseId);
bool executeStmts(const QStringList &stmts);
bool executsSqlConstraints(const QStringList &constraintList,
const QStringList &sqlStmts,
const QString &dbSchema);
void checkAliveTimer();
private:
// QMap<svcAbbr,Pointer SqlGenerator>
QMap<QString,CodeGen::SqlGenerator*> m_sqlGeneratorMap;
QString m_xmlPath;
QString m_ownSchemaName;
QSqlDatabase m_database;
QElapsedTimer m_emitAliveTimer;
NGL::INGLLogger &m_logger;
};
} // namespace DBAdministration
+165
View File
@@ -0,0 +1,165 @@
/**
* @RDE_HEADER@
* PresentationManangement - Script Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-03-15
*/
#include "local_databases_model.h"
#include <ngltools/ngltools_dtg.h>
#include <ngldb/nsqlquery.h>
#include <QDateTime>
#include <QPalette>
namespace DBAdministration
{
LocalDatabasesModel::LocalDatabasesModel(QObject *parent)
: QAbstractTableModel(parent)
, m_logger(getLogger("LocalDatabasesModel"))
{}
LocalDatabasesModel::~LocalDatabasesModel()
{}
bool LocalDatabasesModel::initModel(const QSqlDatabase &db)
{
beginResetModel();
m_vecData.clear();
endResetModel();
NSqlQuery q(db);
QString stmt = QStringLiteral("SELECT id, name, db_name, begin_time, end_time FROM local_databases");
if (!q.exec(stmt))
return false;
while (q.next())
{
LocalExercise e;
e.id = q.value(0).toInt();
e.name = q.value(1).toString();
e.dbName = q.value(2).toString();
e.startTime = q.value(3).toLongLong();
e.endTime = q.value(4).toLongLong();
insertRow(e);
}
INFO_LOG(m_logger) << "initModel - #exercises: " << m_vecData.size();
return true;
}
QVariant LocalDatabasesModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole || !index.isValid() || index.row() >= m_vecData.size())
return QVariant();
const LocalExercise &e = m_vecData.at(index.row());
switch (index.column())
{
case Id:
return e.id;
case Name:
return QString(e.name);
case DbName:
return QString(e.dbName);
case StartTime:
return DTG::toStringMSec(e.startTime);
case EndTime:
return DTG::toStringMSec(e.endTime);
}
return QVariant();
}
int LocalDatabasesModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_vecData.size();
}
int LocalDatabasesModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : EndTime + 1;
}
QVariant LocalDatabasesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal
&& role == Qt::DisplayRole)
{
Columns col = static_cast<Columns>(section);
switch (col)
{
case Id:
return tr("Id");
case Name:
return tr("Name");
case DbName:
return tr("Database Name");
case StartTime:
return tr("Start Time");
case EndTime:
return tr("End Time");
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
LocalExercise LocalDatabasesModel::getRowData(int row) const
{
if (row < 0 || row >= m_vecData.size())
return LocalExercise();
return m_vecData.at(row);
}
bool LocalDatabasesModel::insertRow(const LocalExercise &item)
{
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
m_vecData.append(item);
endInsertRows();
return true;
}
void LocalDatabasesProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<LocalDatabasesModel*>(sourceModel);
QSortFilterProxyModel::setSourceModel(sourceModel);
}
bool LocalDatabasesProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel ||
source_left.column() != source_right.column() ||
!source_left.isValid() ||
!source_right.isValid())
return QSortFilterProxyModel::lessThan(source_left, source_right);
const auto &dataLeft = m_sourceModel->m_vecData.at(source_left.row());
const auto dataRight = m_sourceModel->m_vecData.at(source_right.row());
switch (source_left.column())
{
case LocalDatabasesModel::StartTime:
return dataLeft.startTime < dataRight.startTime;
case LocalDatabasesModel::EndTime:
return dataLeft.endTime < dataRight.endTime;
case LocalDatabasesModel::Id:
case LocalDatabasesModel::Name:
case LocalDatabasesModel::DbName:
break;
}
return QSortFilterProxyModel::lessThan(source_left, source_right);
}
} // namespace DBAdministration
+76
View File
@@ -0,0 +1,76 @@
/**
* @RDE_HEADER@
* PresentationManangement - Script Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-03-15
*/
#pragma once
#include "logger.h"
#include <QAbstractTableModel>
#include <QSortFilterProxyModel>
class QSqlDatabase;
namespace DBAdministration
{
struct LocalExercise
{
qint32 id;
QString name;
QString dbName;
qint64 startTime;
qint64 endTime;
};
class LocalDatabasesModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum Columns
{
Id = 0,
Name,
DbName,
StartTime,
EndTime
};
explicit LocalDatabasesModel(QObject *parent = nullptr);
~LocalDatabasesModel();
bool initModel(const QSqlDatabase &db);
QVariant data(const QModelIndex &, int) const override final;
int rowCount(const QModelIndex &parent) const override final;
int columnCount(const QModelIndex &parent) const override final;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
LocalExercise getRowData(int row) const;
bool insertRow(const LocalExercise &item);
friend class LocalDatabasesProxyModel;
private:
QVector<LocalExercise> m_vecData;
LOGGER_T m_logger;
};
class LocalDatabasesProxyModel final : public QSortFilterProxyModel
{
Q_OBJECT
public:
using QSortFilterProxyModel::QSortFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel) override;
protected:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
private:
LocalDatabasesModel *m_sourceModel = nullptr;
};
}
+77
View File
@@ -0,0 +1,77 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# DbAdministration
###########################################################
#log4j.logger.DbAdministration=DEBUG
# File
###########################################################
log4j.appender.file=Lts::RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
# Appnd_Syslog
###########################################################
log4j.appender.syslog=org.apache.log4j.SyslogAppender
log4j.appender.syslog.Threshold=ERROR
log4j.appender.syslog.SysLogHost=localhost
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace DBAdministration
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "DBA.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace DBAdministration
+23
View File
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Logging for Evaluations
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
namespace DBAdministration
{
typedef NGL::INGLLogger &LOGGER_T;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace DBAdministration
+100
View File
@@ -0,0 +1,100 @@
/*
* @RDE_HEADER@
* <short description>
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Schröder, SLSE, 2016-06-08
*/
#include "db_administration.h"
#include "copy_exercise.h"
#include "settings.h"
#include <NGLLogger/INGLLogger.h>
#include <nglapplication/nglapplication.h>
#include <nglapplication/nglcoreapplication.h>
#include <ngltranslator/ngltranslator.h>
#include <LtsCommandLineParser/LtsCommandLineParser.h>
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
{
public:
CmdLineParser()
: LtsCommandLineParser(ProvideCommandLineParameterOptions::None)
{
addOption({{QStringLiteral("l"), QStringLiteral("lang")},
QStringLiteral("Language iso code to use (de_DE, en_GB, en_US)"),
QStringLiteral("<locale iso code>")
});
}
QString langIsoCode() const { return value(QStringLiteral("l")); }
};
int main(int argc, char *argv[])
{
int retval = -1;
bool bHeadless = false;
for (int i = 1; i < argc; ++i)
{
if (strcmp(argv[i], "-e") == 0)
{
bHeadless = true;
break;
}
}
QScopedPointer<QCoreApplication> app;
app.reset(bHeadless ? dynamic_cast<QCoreApplication*>(new NGLCoreApplication(argc, argv))
: dynamic_cast<QCoreApplication*>(new NGLApplication(argc, argv)));
QCoreApplication::setApplicationName(QLatin1String("DBAdministration"));
QCoreApplication::setOrganizationName(QLatin1String("RME"));
NGL::LoggerHandler *lh = dynamic_cast<NGL::LoggerHandler*>(app.data());
lh->createLogger("DbAdministration", "log4cxx_dba.props");
NGL::INGLLogger &logger = lh->baseLogger();
// Parse Options
CmdLineParser options;
if (!options.init())
return retval;
// Set Translation
QString langIsoCode = options.langIsoCode();
if (langIsoCode.isEmpty())
langIsoCode = QLocale::system().name();
NGL::setTranslationLocale(langIsoCode.toLatin1());
DBAdministration::Settings::setIniFile(options.iniFile());
INFO_LOG(logger) << "ExerciseId: " << options.exerciseId();
if (options.exerciseId() <= 0)
{
QScopedPointer<DBAdministration::DBAdministration> w(new DBAdministration::DBAdministration);
if (!w->init())
return -2;
STARTUP_LOG(logger);
w->show();
QGuiApplication::setQuitOnLastWindowClosed(true);
retval = QCoreApplication::exec();
}
else
{
DBAdministration::CopyExercise::CopyFor copyFor = DBAdministration::CopyExercise::CopyForEvaluation;
QScopedPointer<DBAdministration::CopyExercise> w(new DBAdministration::CopyExercise(DBAdministration::getLogger("CopyExercise"), copyFor));
if (!w->init(options.exerciseId(),
DBAdministration::Settings::serverDatabaseHost(),
DBAdministration::Settings::serverDatabaseName(),
DBAdministration::Settings::evaluationDatabaseHost(),
DBAdministration::Settings::evaluationDatabaseName()))
return -2;
STARTUP_LOG(logger);
if (!w->doCopy())
return -3;
retval = QCoreApplication::exec();
}
SHUTDOWN_LOG(logger);
return retval;
}
+158
View File
@@ -0,0 +1,158 @@
/**
* @RDE_HEADER@
* PresentationManangement - Script Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-03-15
*/
#include "server_databases_model.h"
#include <ngltools/ngltools_dtg.h>
#include <ngldb/nsqlquery.h>
#include <QDateTime>
#include <QPalette>
namespace DBAdministration
{
ServerDatabasesModel::ServerDatabasesModel(QObject *parent)
: QAbstractTableModel(parent)
, m_logger(getLogger("ServerDatabasesModel"))
{}
ServerDatabasesModel::~ServerDatabasesModel()
{}
bool ServerDatabasesModel::initModel(const QSqlDatabase &db)
{
beginResetModel();
m_vecData.clear();
endResetModel();
NSqlQuery q(db);
QString stmt = QStringLiteral("SELECT id, name, begin_time, end_time FROM exm.exercise");
if (!q.exec(stmt))
return false;
while (q.next())
{
Exercise e;
e.id = q.value(0).toInt();
e.name = q.value(1).toString();
e.startTime = q.value(2).toLongLong();
e.endTime = q.value(3).toLongLong();
insertRow(e);
}
INFO_LOG(m_logger) << "initModel - #exercises: " << m_vecData.size();
return true;
}
QVariant ServerDatabasesModel::data(const QModelIndex &index, int role) const
{
if (role != Qt::DisplayRole || !index.isValid() || index.row() >= m_vecData.size())
return QVariant();
const Exercise &e = m_vecData.at(index.row());
switch (index.column())
{
case Id:
return e.id;
case Name:
return QString(e.name);
case StartTime:
return DTG::toStringMSec(e.startTime);
case EndTime:
return DTG::toStringMSec(e.endTime);
}
return QVariant();
}
int ServerDatabasesModel::rowCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : m_vecData.size();
}
int ServerDatabasesModel::columnCount(const QModelIndex &parent) const
{
return parent.isValid() ? 0 : EndTime + 1;
}
QVariant ServerDatabasesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal
&& role == Qt::DisplayRole)
{
Columns col = static_cast<Columns>(section);
switch (col)
{
case Id:
return tr("Id");
case Name:
return tr("Name");
case StartTime:
return tr("Start Time");
case EndTime:
return tr("End Time");
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
Exercise ServerDatabasesModel::getRowData(int row) const
{
if (row < 0 || row >= m_vecData.size())
return Exercise();
return m_vecData.at(row);
}
bool ServerDatabasesModel::insertRow(const Exercise &item)
{
beginInsertRows(QModelIndex(), m_vecData.size(), m_vecData.size());
m_vecData.append(item);
endInsertRows();
return true;
}
void ServerDatabasesProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
{
m_sourceModel = qobject_cast<ServerDatabasesModel*>(sourceModel);
QSortFilterProxyModel::setSourceModel(sourceModel);
}
bool ServerDatabasesProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
if (!m_sourceModel ||
source_left.column() != source_right.column() ||
!source_left.isValid() ||
!source_right.isValid())
return QSortFilterProxyModel::lessThan(source_left, source_right);
const auto &dataLeft = m_sourceModel->m_vecData.at(source_left.row());
const auto dataRight = m_sourceModel->m_vecData.at(source_right.row());
switch (source_left.column())
{
case ServerDatabasesModel::StartTime:
return dataLeft.startTime < dataRight.startTime;
case ServerDatabasesModel::EndTime:
return dataLeft.endTime < dataRight.endTime;
case ServerDatabasesModel::Id:
case ServerDatabasesModel::Name:
break;
}
return QSortFilterProxyModel::lessThan(source_left, source_right);
}
} // namespace DBAdministration
+75
View File
@@ -0,0 +1,75 @@
/**
* @RDE_HEADER@
* PresentationManangement - Script Overview Dialog Model
* $Id$
* $HeadURL$
* $Author$
*
* Created by Mike Wille, SLSE, 2017-03-15
*/
#pragma once
#include "logger.h"
#include <QAbstractTableModel>
#include <QSortFilterProxyModel>
class QSqlDatabase;
namespace DBAdministration
{
struct Exercise
{
qint32 id = 0;
QString name;
qint64 startTime = 0;
qint64 endTime = 0;
};
class ServerDatabasesModel : public QAbstractTableModel
{
Q_OBJECT
public:
enum Columns
{
Id = 0,
Name,
StartTime,
EndTime
};
explicit ServerDatabasesModel(QObject *parent = nullptr);
~ServerDatabasesModel();
bool initModel(const QSqlDatabase &db);
QVariant data(const QModelIndex &, int) const override final;
int rowCount(const QModelIndex &parent) const override final;
int columnCount(const QModelIndex &parent) const override final;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override final;
Exercise getRowData(int row) const;
bool insertRow(const Exercise &item);
friend class ServerDatabasesProxyModel;
protected:
private:
QVector<Exercise> m_vecData;
LOGGER_T m_logger;
};
class ServerDatabasesProxyModel final : public QSortFilterProxyModel
{
Q_OBJECT
public:
using QSortFilterProxyModel::QSortFilterProxyModel;
void setSourceModel(QAbstractItemModel *sourceModel) override;
protected:
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
private:
ServerDatabasesModel *m_sourceModel = nullptr;
};
}
+68
View File
@@ -0,0 +1,68 @@
/**
* Settings for CentralEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <QtCore/QVariant>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
namespace DBAdministration
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//-----------------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//-----------------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
//-----------------------------------------------------------------------------
QString Settings::serverDatabaseHost()
{
return s()->settings()->value(QStringLiteral("dbAdministration/DatabaseHostname"), QStringLiteral("EXCDBS01")).toString();
}
//-----------------------------------------------------------------------------
QString Settings::serverDatabaseName()
{
return s()->settings()->value(QStringLiteral("dbAdministration/DatabaseName"), QStringLiteral("lts_ets_pro")).toString();
}
//-----------------------------------------------------------------------------
QString Settings::evaluationDatabaseHost()
{
return s()->settings()->value(QStringLiteral("EvaluationDb/DatabaseHostname"), QStringLiteral("EXCADB01")).toString();
}
//-----------------------------------------------------------------------------
QString Settings::evaluationDatabaseName()
{
return s()->settings()->value(QStringLiteral("EvaluationDb/DatabaseName"), QStringLiteral("dbAdmin")).toString();
}
} // namespace DBAdministration
+28
View File
@@ -0,0 +1,28 @@
/**
* Settings for CentralEffectSimulation
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QString>
namespace NGL
{
class Settings;
}
namespace DBAdministration
{
namespace Settings
{
NGL::Settings *settings();
void setIniFile(const QString &ini);
QString serverDatabaseHost();
QString serverDatabaseName();
QString evaluationDatabaseHost();
QString evaluationDatabaseName();
}
} // namespace CentralEffectSimulation
+58
View File
@@ -0,0 +1,58 @@
/*
* @RDE_HEADER@
* <short description>
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Schröder, SLSE, 2016-06-08
*/
#include "showLogFile.h"
#include "ui_showLogFile.h"
#include <nglsettings/nglsettings_settings.h>
namespace DBAdministration
{
ShowLogFile::ShowLogFile(QWidget *parent)
: QWidget(parent)
, m_ui(new Ui::ShowLogFile)
, m_logger(getLogger("ShowLogFile"))
{
m_ui->setupUi(this);
connect(m_ui->pbClose, &QPushButton::clicked, this, &ShowLogFile::onClosedClicked);
}
ShowLogFile::~ShowLogFile()
{
delete m_ui;
}
bool ShowLogFile::init()
{
QString logFile = NGL::Settings::logPath() + QStringLiteral("/") + QString::fromLatin1(qgetenv("USER")) + QStringLiteral("_scm.log");
ERROR_LOG(m_logger) << "Logfile: " << logFile;
QFile file(logFile);
if (!file.open(QIODevice::ReadOnly))
{
ERROR_LOG(m_logger) << "Cannot open file " << logFile;
return false;
}
QByteArray output = file.readAll();
m_ui->plainTextEdit->setPlainText(QString::fromLocal8Bit(output));
return true;
}
void ShowLogFile::onClosedClicked()
{
close();
}
} // namespace DBAdministration
+39
View File
@@ -0,0 +1,39 @@
/*
* @RDE_HEADER@
* <short description>
* $Id$
* $HeadURL$
* $Author$
* Created by Malte Schröder, SLSE, 2016-06-08
*/
#pragma once
#include <QWidget>
#include "logger.h"
namespace Ui {
class ShowLogFile;
}
namespace DBAdministration
{
class ShowLogFile : public QWidget
{
Q_OBJECT
public:
explicit ShowLogFile(QWidget *parent = nullptr);
~ShowLogFile();
bool init();
private slots:
void onClosedClicked();
private:
Ui::ShowLogFile *m_ui;
LOGGER_T m_logger;
};
}
+180
View File
@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DBAdministration</class>
<widget class="QMainWindow" name="DBAdministration">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>846</width>
<height>382</height>
</rect>
</property>
<property name="windowTitle">
<string>Database administration</string>
</property>
<property name="statusTip">
<string/>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonIconOnly</enum>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QTableView" name="tableViewServerDatabases">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblServerDatabases">
<property name="text">
<string>Server Databases:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lblLocalDatabases">
<property name="text">
<string>Local Databases:</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QTableView" name="tableViewLocalDatabases">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="pbCopy">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../../Z/src/nglwidgets/nglresources.qrc">
<normaloff>:/icons/16x16/go-next.png</normaloff>:/icons/16x16/go-next.png</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pbActivate">
<property name="text">
<string>Activate Database</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbRemove">
<property name="text">
<string>Remove Database</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>846</width>
<height>31</height>
</rect>
</property>
<widget class="QMenu" name="menuShow_Service_Management_Log_File">
<property name="title">
<string>&amp;Logfile</string>
</property>
<addaction name="actionShow"/>
</widget>
<widget class="QMenu" name="menuService_Management">
<property name="title">
<string>Service &amp;Management</string>
</property>
<addaction name="actionStart"/>
<addaction name="actionStop"/>
</widget>
<addaction name="menuShow_Service_Management_Log_File"/>
<addaction name="menuService_Management"/>
</widget>
<action name="actionShow">
<property name="text">
<string>&amp;Show</string>
</property>
</action>
<action name="actionStart">
<property name="text">
<string>&amp;Start</string>
</property>
</action>
<action name="actionStop">
<property name="text">
<string>St&amp;op</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="../../../../Z/src/nglwidgets/nglresources.qrc"/>
</resources>
<connections/>
<slots>
<slot>oeffnenClicked()</slot>
</slots>
</ui>
+55
View File
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ShowLogFile</class>
<widget class="QWidget" name="ShowLogFile">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>845</width>
<height>532</height>
</rect>
</property>
<property name="windowTitle">
<string>Show Logfile</string>
</property>
<property name="statusTip">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPlainTextEdit" name="plainTextEdit"/>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pbClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
<slots>
<slot>oeffnenClicked()</slot>
</slots>
</ui>