This repository has been archived by the owner on Oct 19, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#include "mainwindow.h" | ||
#include <QApplication> | ||
|
||
|
||
int main(int argc, char *argv[]) | ||
{ | ||
QApplication a(argc, argv); | ||
|
||
MainWindow w; | ||
// w.show(); | ||
|
||
w.startRace(); | ||
|
||
return a.exec(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
#include "mainwindow.h" | ||
#include "ui_mainwindow.h" | ||
#include "sleeperthread.h" | ||
|
||
#include <QDateTime> | ||
#include <QDebug> | ||
#include <QSqlError> | ||
#include <QSqlQuery> | ||
#include <QSqlRecord> | ||
#include <QThread> | ||
|
||
#include <QtConcurrentRun> | ||
#include <QFuture> | ||
|
||
const QString tableName = QString ("test_table"); | ||
const QString createTableText = QString("CREATE TABLE IF NOT EXISTS test_table " | ||
"( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, " | ||
"test_string CHAR( 255 ) )"); | ||
const QString connectionName = QString("main_connection"); | ||
|
||
const QString insertStartInfo = QString("INSERT INTO %1 (test_string) VALUES ('START: %2')") | ||
.arg(tableName) | ||
.arg(QDateTime::currentDateTime().toString()); | ||
|
||
const QString selectQuery = QString("SELECT * from %1").arg(tableName); | ||
|
||
MainWindow::MainWindow(QWidget *parent) : | ||
QMainWindow(parent), | ||
ui(new Ui::MainWindow) | ||
{ | ||
ui->setupUi(this); | ||
if (!prepareAndOpenDb()) { | ||
qDebug() << "Error while opening DB"; | ||
} | ||
} | ||
|
||
bool MainWindow::prepareAndOpenDb() | ||
{ | ||
QStringList driverList( QSqlDatabase::drivers() ); | ||
|
||
if (!driverList.contains(QString("QSQLITE"), Qt::CaseInsensitive)) { | ||
qDebug() << "No SQLITE support"; | ||
return false; | ||
} else { | ||
qDebug() << "SQLITE support is present"; | ||
} | ||
|
||
mWorkDb = QSqlDatabase::addDatabase("QSQLITE", connectionName); | ||
mWorkDb.setHostName("localhost"); | ||
mWorkDb.setDatabaseName("sqlitetest"); | ||
|
||
if (!mWorkDb.open()) { | ||
qDebug() << "DB was not opened!"; | ||
return false; | ||
} | ||
|
||
// QString journalMode("OFF"); // default: "DELETE", "WAL" | ||
// if (setDbJournalMode(mWorkDb, journalMode) ) | ||
// { | ||
// qDebug() << "Sucessfuly switched to" << journalMode; | ||
// } | ||
|
||
QStringList tables = mWorkDb.tables(QSql::Tables); | ||
|
||
if ( !tables.contains("test_table") ) { | ||
QSqlQuery createTableQuery(mWorkDb); | ||
if ( !createTableQuery.exec(createTableText) ) { | ||
qDebug() << "Can't create table" << tableName << "in" << mWorkDb.databaseName() | ||
<< ":" << createTableQuery.lastError().text(); | ||
return false; | ||
} | ||
} else { | ||
qDebug() << mWorkDb.databaseName() << "already has table" << tableName; | ||
} | ||
QSqlQuery q(insertStartInfo, mWorkDb); | ||
return true; | ||
} | ||
|
||
bool MainWindow::setDbJournalMode(QSqlDatabase &db, const QString &mode) | ||
{ | ||
QSqlQuery q(db); | ||
q.prepare( QString("PRAGMA journal_mode = %1").arg(mode) ); | ||
return q.exec(); | ||
} | ||
|
||
void MainWindow::readFromDb() | ||
{ | ||
const int threadId = QThread::currentThreadId(); | ||
qDebug() << "READER:" << threadId; | ||
|
||
// wait for transaction in writer begins | ||
while (transInProcess==false) | ||
{ | ||
qDebug() << " # Reader is waiting"; | ||
SleeperThread::msSleep(7); | ||
} | ||
qDebug() << "# reader got transInProcess==true"; | ||
QString connectionName = QString ("Reader_%1").arg(threadId); | ||
|
||
QSqlDatabase readDb = QSqlDatabase::cloneDatabase(mWorkDb, connectionName); | ||
|
||
if (!readDb.open()) { | ||
qDebug() << "DB was not opened to read!"; | ||
return; | ||
} | ||
|
||
QSqlQuery q(selectQuery, readDb); | ||
q.exec(); | ||
outpuQuery(q); | ||
} | ||
|
||
void MainWindow::writeToDb() | ||
{ | ||
const int threadId = QThread::currentThreadId(); | ||
qDebug() << "WRITER:" << threadId; | ||
|
||
QString connectionName = QString ("Writer_%1").arg(threadId); | ||
QSqlDatabase writeDb = QSqlDatabase::cloneDatabase(mWorkDb, connectionName); | ||
|
||
if (!writeDb.open()) { | ||
qDebug() << "DB was not opened to write!"; | ||
return; | ||
} | ||
|
||
const QString insertWriterInfo = QString("INSERT INTO %1 (test_string) VALUES ('WRITER at %2, %3')") | ||
.arg(tableName) | ||
.arg(QString::number(threadId)) | ||
.arg(QDateTime::currentDateTime().toString()); | ||
|
||
// insert some pause just to feel waiting process in Reader | ||
SleeperThread::msSleep(21); | ||
writeDb.transaction(); | ||
transInProcess = true; | ||
SleeperThread::msSleep(21); | ||
QSqlQuery q(insertWriterInfo, writeDb); | ||
writeDb.commit(); | ||
transInProcess = false; | ||
} | ||
|
||
void MainWindow::startRace() | ||
{ | ||
transInProcess = false; | ||
QtConcurrent::run(this, &MainWindow::readFromDb); | ||
QtConcurrent::run(this, &MainWindow::writeToDb); | ||
|
||
// probably all queries will be applied | ||
SleeperThread::msSleep(600); | ||
qDebug() << "Summary:"; | ||
QSqlQuery q(selectQuery, mWorkDb); | ||
q.exec(); | ||
outpuQuery(q); | ||
} | ||
|
||
|
||
MainWindow::~MainWindow() | ||
{ | ||
delete ui; | ||
} | ||
|
||
|
||
void MainWindow::outpuQuery(QSqlQuery &query) | ||
{ | ||
if (query.isActive()) { | ||
while (query.next()) { | ||
qDebug("%4i: %s", query.value(0).toInt(), qPrintable(query.value(1).toString())); // << query.value(0).toInt() << ":" << query.value(1).toString(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#ifndef MAINWINDOW_H | ||
#define MAINWINDOW_H | ||
|
||
#include <QMainWindow> | ||
#include <QSqlDatabase> | ||
|
||
class QSqlQuery; | ||
|
||
namespace Ui { | ||
class MainWindow; | ||
} | ||
|
||
class MainWindow : public QMainWindow | ||
{ | ||
Q_OBJECT | ||
QSqlDatabase mWorkDb; | ||
public: | ||
explicit MainWindow(QWidget *parent = 0); | ||
~MainWindow(); | ||
|
||
bool prepareAndOpenDb(); | ||
bool setDbJournalMode(QSqlDatabase& db, const QString& mode); | ||
void readFromDb(); | ||
void writeToDb(); | ||
void startRace(); | ||
void outpuQuery(QSqlQuery& query); | ||
volatile bool transInProcess; | ||
|
||
private: | ||
Ui::MainWindow *ui; | ||
}; | ||
|
||
#endif // MAINWINDOW_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<ui version="4.0"> | ||
<class>MainWindow</class> | ||
<widget class="QMainWindow" name="MainWindow" > | ||
<property name="geometry" > | ||
<rect> | ||
<x>0</x> | ||
<y>0</y> | ||
<width>400</width> | ||
<height>300</height> | ||
</rect> | ||
</property> | ||
<property name="windowTitle" > | ||
<string>MainWindow</string> | ||
</property> | ||
<widget class="QMenuBar" name="menuBar" /> | ||
<widget class="QToolBar" name="mainToolBar" /> | ||
<widget class="QWidget" name="centralWidget" /> | ||
<widget class="QStatusBar" name="statusBar" /> | ||
</widget> | ||
<layoutDefault spacing="6" margin="11" /> | ||
<pixmapfunction></pixmapfunction> | ||
<resources/> | ||
<connections/> | ||
</ui> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
#ifndef SLEEPERTHREAD_H | ||
#define SLEEPERTHREAD_H | ||
|
||
#include <QThread> | ||
|
||
class SleeperThread : public QThread | ||
{ | ||
Q_OBJECT | ||
public: | ||
static void msSleep(uint ms) { | ||
if ( !ms ) { return; } | ||
|
||
SleeperThread sleeper(ms); | ||
sleeper.run(); | ||
} | ||
explicit SleeperThread(uint ms) : m_sleepTime(ms) {} | ||
virtual void run() { msleep( m_sleepTime );} | ||
void setSleepTime(uint ms) { m_sleepTime = ms ;} | ||
uint sleepTime() const { return m_sleepTime; } | ||
private: | ||
uint m_sleepTime; | ||
}; | ||
#endif // SLEEPERTHREAD_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#------------------------------------------------- | ||
# | ||
# Project created by QtCreator 2013-07-10T21:33:13 | ||
# | ||
#------------------------------------------------- | ||
|
||
QT += core gui sql | ||
|
||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets | ||
|
||
TARGET = sqlite_test | ||
TEMPLATE = app | ||
|
||
|
||
SOURCES += main.cpp\ | ||
mainwindow.cpp | ||
|
||
HEADERS += mainwindow.h \ | ||
sleeperthread.h | ||
|
||
FORMS += mainwindow.ui |