diff --git a/src/ui/3rdparty/sqlite/sqlitedb.cpp b/src/ui/3rdparty/sqlite/sqlitedb.cpp index f385a73c..837684b4 100644 --- a/src/ui/3rdparty/sqlite/sqlitedb.cpp +++ b/src/ui/3rdparty/sqlite/sqlitedb.cpp @@ -135,6 +135,14 @@ bool SqliteDb::prepare(SqliteStmt &stmt, const char *sql, const QVariantList &va return stmt.prepare(db(), sql) && (vars.isEmpty() || stmt.bindVars(vars)); } +bool SqliteDb::done(SqliteStmt *stmt) +{ + const SqliteStmt::StepResult res = stmt->step(); + const bool ok = (res == SqliteStmt::StepDone && changes() != 0); + stmt->reset(); + return ok; +} + qint64 SqliteDb::lastInsertRowid() const { return sqlite3_last_insert_rowid(m_db); diff --git a/src/ui/3rdparty/sqlite/sqlitedb.h b/src/ui/3rdparty/sqlite/sqlitedb.h index dd889126..35cfd89b 100644 --- a/src/ui/3rdparty/sqlite/sqlitedb.h +++ b/src/ui/3rdparty/sqlite/sqlitedb.h @@ -37,6 +37,7 @@ public: int resultCount = 1, bool *ok = nullptr); bool prepare(SqliteStmt &stmt, const char *sql, const QVariantList &vars = QVariantList()); + bool done(SqliteStmt *stmt); qint64 lastInsertRowid() const; int changes() const; diff --git a/src/ui/form/conn/connectionswindow.cpp b/src/ui/form/conn/connectionswindow.cpp index cca5dfd5..3efe5212 100644 --- a/src/ui/form/conn/connectionswindow.cpp +++ b/src/ui/form/conn/connectionswindow.cpp @@ -136,12 +136,12 @@ QLayout *ConnectionsWindow::setupHeader() m_actClearConns = editMenu->addAction(IconCache::icon(":/icons/trash.png"), QString()); - connect(m_actCopy, &QAction::triggered, this, [&] { - GuiUtil::setClipboardData(m_connListView->selectedText()); - }); + connect(m_actCopy, &QAction::triggered, this, + [&] { GuiUtil::setClipboardData(m_connListView->selectedText()); }); connect(m_actRemoveConn, &QAction::triggered, this, [&] { - if (fortManager()->showQuestionBox(tr("Are you sure to remove selected connection(s)?"))) { - deleteSelectedConns(); + if (fortManager()->showQuestionBox( + tr("Are you sure to remove connections till this row?"))) { + deleteConn(m_connListView->currentRow()); } }); connect(m_actClearConns, &QAction::triggered, this, [&] { @@ -239,7 +239,9 @@ void ConnectionsWindow::setupTableConnList() m_connListView->setSelectionMode(QAbstractItemView::ExtendedSelection); m_connListView->setSelectionBehavior(QAbstractItemView::SelectItems); - // m_connListView->setSortingEnabled(true); + // TODO: Add ability to select the allowed/blocked mode from UI + connListModel()->setBlockedMode(true); + m_connListView->setModel(connListModel()); m_connListView->setMenu(m_btEdit->menu()); @@ -319,20 +321,12 @@ void ConnectionsWindow::syncShowHostNames() void ConnectionsWindow::deleteConn(int row) { const auto connRow = connListModel()->connRowAt(row); - connListModel()->deleteConn(connRow.connId, connRow.blocked, row); -} - -void ConnectionsWindow::deleteSelectedConns() -{ - const auto rows = m_connListView->selectedRows(); - for (int i = rows.size(); --i >= 0;) { - deleteConn(rows.at(i)); - } + connListModel()->deleteConn(connRow.rowId, connRow.blocked, row); } int ConnectionsWindow::connListCurrentIndex() const { - return m_connListView->currentIndex().row(); + return m_connListView->currentRow(); } QString ConnectionsWindow::connListCurrentPath() const diff --git a/src/ui/form/conn/connectionswindow.h b/src/ui/form/conn/connectionswindow.h index 87372568..1b578e3a 100644 --- a/src/ui/form/conn/connectionswindow.h +++ b/src/ui/form/conn/connectionswindow.h @@ -48,8 +48,6 @@ private: void deleteConn(int row); - void deleteSelectedConns(); - int connListCurrentIndex() const; QString connListCurrentPath() const; diff --git a/src/ui/form/controls/listview.cpp b/src/ui/form/controls/listview.cpp index 5c5e72b2..61ed29e4 100644 --- a/src/ui/form/controls/listview.cpp +++ b/src/ui/form/controls/listview.cpp @@ -2,6 +2,11 @@ ListView::ListView(QWidget *parent) : QListView(parent) { } +int ListView::currentRow() const +{ + return currentIndex().row(); +} + void ListView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { QListView::currentChanged(current, previous); diff --git a/src/ui/form/controls/listview.h b/src/ui/form/controls/listview.h index 3984fab6..2d033d20 100644 --- a/src/ui/form/controls/listview.h +++ b/src/ui/form/controls/listview.h @@ -10,6 +10,8 @@ class ListView : public QListView public: explicit ListView(QWidget *parent = nullptr); + int currentRow() const; + signals: void currentIndexChanged(const QModelIndex &index); diff --git a/src/ui/form/controls/tableview.cpp b/src/ui/form/controls/tableview.cpp index 28603a64..066cf270 100644 --- a/src/ui/form/controls/tableview.cpp +++ b/src/ui/form/controls/tableview.cpp @@ -5,6 +5,11 @@ TableView::TableView(QWidget *parent) : QTableView(parent) { } +int TableView::currentRow() const +{ + return currentIndex().row(); +} + QVector TableView::selectedRows() const { QSet rowsSet; @@ -12,7 +17,7 @@ QVector TableView::selectedRows() const for (const auto index : indexes) { rowsSet.insert(index.row()); } - rowsSet.insert(currentIndex().row()); + rowsSet.insert(currentRow()); auto rows = rowsSet.values(); std::sort(rows.begin(), rows.end()); diff --git a/src/ui/form/controls/tableview.h b/src/ui/form/controls/tableview.h index 14c2f705..89697232 100644 --- a/src/ui/form/controls/tableview.h +++ b/src/ui/form/controls/tableview.h @@ -13,6 +13,7 @@ public: QMenu *menu() const { return m_menu; } void setMenu(QMenu *menu) { m_menu = menu; } + int currentRow() const; QVector selectedRows() const; QModelIndexList sortedSelectedIndexes() const; diff --git a/src/ui/form/opt/pages/schedulepage.cpp b/src/ui/form/opt/pages/schedulepage.cpp index be5ba4f6..6a92bea5 100644 --- a/src/ui/form/opt/pages/schedulepage.cpp +++ b/src/ui/form/opt/pages/schedulepage.cpp @@ -213,5 +213,5 @@ void SchedulePage::setupTableTasksChanged() int SchedulePage::currentTaskIndex() const { - return m_tableTasks->currentIndex().row(); + return m_tableTasks->currentRow(); } diff --git a/src/ui/form/opt/pages/statisticspage.cpp b/src/ui/form/opt/pages/statisticspage.cpp index fa851bc6..cd442fcf 100644 --- a/src/ui/form/opt/pages/statisticspage.cpp +++ b/src/ui/form/opt/pages/statisticspage.cpp @@ -797,7 +797,7 @@ void StatisticsPage::updateTrafUnit() int StatisticsPage::appListCurrentIndex() const { - return m_appListView->currentIndex().row(); + return m_appListView->currentRow(); } QString StatisticsPage::appListCurrentPath() const diff --git a/src/ui/form/prog/programswindow.cpp b/src/ui/form/prog/programswindow.cpp index 774beef4..f0a3637c 100644 --- a/src/ui/form/prog/programswindow.cpp +++ b/src/ui/form/prog/programswindow.cpp @@ -619,7 +619,7 @@ void ProgramsWindow::deleteSelectedApps() int ProgramsWindow::appListCurrentIndex() const { - return m_appListView->currentIndex().row(); + return m_appListView->currentRow(); } QString ProgramsWindow::appListCurrentPath() const diff --git a/src/ui/form/zone/zoneswindow.cpp b/src/ui/form/zone/zoneswindow.cpp index 62de94fb..15348514 100644 --- a/src/ui/form/zone/zoneswindow.cpp +++ b/src/ui/form/zone/zoneswindow.cpp @@ -443,7 +443,7 @@ void ZonesWindow::deleteSelectedZone() int ZonesWindow::zoneListCurrentIndex() const { - return m_zoneListView->currentIndex().row(); + return m_zoneListView->currentRow(); } FortManager *ZonesWindow::fortManager() const diff --git a/src/ui/model/applistmodel.cpp b/src/ui/model/applistmodel.cpp index 92e2bf6d..85c1eca4 100644 --- a/src/ui/model/applistmodel.cpp +++ b/src/ui/model/applistmodel.cpp @@ -352,7 +352,7 @@ QString AppListModel::sqlOrderColumn() const columnsStr = "8"; break; default: // Creation Time - columnsStr = "1"; + columnsStr = "1"; // App ID break; } diff --git a/src/ui/model/connlistmodel.cpp b/src/ui/model/connlistmodel.cpp index e39fa0a3..3609f2b4 100644 --- a/src/ui/model/connlistmodel.cpp +++ b/src/ui/model/connlistmodel.cpp @@ -19,6 +19,14 @@ ConnListModel::ConnListModel(StatManager *statManager, QObject *parent) : { } +void ConnListModel::setBlockedMode(bool v) +{ + if (m_blockedMode != v) { + m_blockedMode = v; + reset(); + } +} + void ConnListModel::setResolveAddress(bool v) { if (m_resolveAddress != v) { @@ -132,8 +140,8 @@ QVariant ConnListModel::data(const QModelIndex &index, int role) const if (role == Qt::ToolTipRole) { if (connRow.blocked) { // Show block reason in tool-tip - const auto connBlock = getConnRowBlock(connRow.connId); - return LogEntryBlockedIp::reasonToString(connBlock.blockReason); + const auto blockRow = getConnRowBlock(connRow.rowId); + return LogEntryBlockedIp::reasonToString(blockRow.blockReason); } } return connRow.inbound ? tr("In") : tr("Out"); @@ -169,11 +177,11 @@ QVariant ConnListModel::data(const QModelIndex &index, int role) const return QVariant(); } -void ConnListModel::deleteConn(qint64 connId, bool blocked, int row) +void ConnListModel::deleteConn(qint64 rowIdTo, bool blocked, int row) { - beginRemoveRows(QModelIndex(), row, row); + beginRemoveRows(QModelIndex(), 0, row); - if (statManager()->deleteConn(connId, blocked)) { + if (statManager()->deleteConn(rowIdTo, blocked)) { invalidateRowCache(); } @@ -187,17 +195,17 @@ const ConnRow &ConnListModel::connRowAt(int row) const return m_connRow; } -ConnRowBlock ConnListModel::getConnRowBlock(qint64 connId) const +ConnRowBlock ConnListModel::getConnRowBlock(qint64 rowId) const { static const char *const sql = "SELECT block_reason FROM conn_block" - " WHERE conn_id = ?1"; + " WHERE conn_block_id = ?1"; - return { quint8(sqliteDb()->executeEx(sql, { connId }).toInt()) }; + return { quint8(sqliteDb()->executeEx(sql, { rowId }).toInt()) }; } void ConnListModel::clear() { - statManager()->deleteConns(); + statManager()->deleteConnAll(); reset(); hostInfoCache()->clear(); @@ -205,11 +213,14 @@ void ConnListModel::clear() bool ConnListModel::updateTableRow(int row) const { + const qint64 rowId = rowIdMin() + row; + SqliteStmt stmt; - if (!(sqliteDb()->prepare(stmt, sql().toLatin1(), { row }) + if (!(sqliteDb()->prepare(stmt, sql().toLatin1(), { rowId }) && stmt.step() == SqliteStmt::StepRow)) return false; + m_connRow.rowId = rowId; m_connRow.connId = stmt.columnInt64(0); m_connRow.appId = stmt.columnInt64(1); m_connRow.connTime = stmt.columnUnixTime(2); @@ -226,23 +237,50 @@ bool ConnListModel::updateTableRow(int row) const return true; } +int ConnListModel::doSqlCount() const +{ + return int(rowIdMax() - rowIdMin()) + 1; +} + QString ConnListModel::sqlBase() const { - return "SELECT" - " t.conn_id," - " t.app_id," - " t.conn_time," - " t.process_id," - " t.inbound," - " t.blocked," - " t.ip_proto," - " t.local_port," - " t.remote_port," - " t.local_ip," - " t.remote_ip," - " a.path" - " FROM conn t" - " JOIN app a ON a.app_id = t.app_id"; + return QString::fromLatin1("SELECT" + " t.conn_id," + " t.app_id," + " t.conn_time," + " t.process_id," + " t.inbound," + " t.blocked," + " t.ip_proto," + " t.local_port," + " t.remote_port," + " t.local_ip," + " t.remote_ip," + " a.path" + " FROM conn t" + " JOIN %1 c ON c.conn_id = t.conn_id" + " JOIN app a ON a.app_id = t.app_id") + .arg(blockedMode() ? "conn_block" : "conn_traffic"); +} + +QString ConnListModel::sqlWhere() const +{ + return " WHERE c.id = ?1"; +} + +QString ConnListModel::sqlLimitOffset() const +{ + return QString(); +} + +qint64 ConnListModel::rowIdMin() const +{ + return blockedMode() ? statManager()->connBlockIdMin() : statManager()->connTrafIdMin(); +} + +qint64 ConnListModel::rowIdMax() const +{ + return blockedMode() ? statManager()->connBlockIdMax() : statManager()->connTrafIdMax(); } QString ConnListModel::formatIpPort(quint32 ip, quint16 port) const diff --git a/src/ui/model/connlistmodel.h b/src/ui/model/connlistmodel.h index 09d88f7a..53c09f31 100644 --- a/src/ui/model/connlistmodel.h +++ b/src/ui/model/connlistmodel.h @@ -23,6 +23,7 @@ struct ConnRow : TableRow quint32 pid = 0; + qint64 rowId = 0; qint64 connId = 0; qint64 appId = 0; @@ -43,6 +44,9 @@ class ConnListModel : public TableSqlModel public: explicit ConnListModel(StatManager *statManager, QObject *parent = nullptr); + bool blockedMode() const { return m_blockedMode; } + void setBlockedMode(bool v); + bool resolveAddress() const { return m_resolveAddress; } void setResolveAddress(bool v); @@ -63,11 +67,11 @@ public: int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - void deleteConn(qint64 connId, bool blocked, int row); + void deleteConn(qint64 rowIdTo, bool blocked, int row); const ConnRow &connRowAt(int row) const; - ConnRowBlock getConnRowBlock(qint64 connId) const; + ConnRowBlock getConnRowBlock(qint64 rowId) const; public slots: void clear(); @@ -76,12 +80,19 @@ protected: bool updateTableRow(int row) const override; TableRow &tableRow() const override { return m_connRow; } + int doSqlCount() const override; QString sqlBase() const override; + QString sqlWhere() const override; + QString sqlLimitOffset() const override; private: + qint64 rowIdMin() const; + qint64 rowIdMax() const; + QString formatIpPort(quint32 ip, quint16 port) const; private: + bool m_blockedMode = false; bool m_resolveAddress = false; int m_connBlockInc = 999999999; // to trigger on first check diff --git a/src/ui/stat/migrations/1.sql b/src/ui/stat/migrations/1.sql index f7290e77..8b0828e1 100644 --- a/src/ui/stat/migrations/1.sql +++ b/src/ui/stat/migrations/1.sql @@ -72,16 +72,22 @@ CREATE TABLE conn( CREATE INDEX conn_app_id_idx ON conn(app_id); CREATE TABLE conn_block( - conn_id INTEGER PRIMARY KEY, + id INTEGER PRIMARY KEY, + conn_id INTEGER NOT NULL, block_reason INTEGER NOT NULL -) WITHOUT ROWID; +); + +CREATE UNIQUE INDEX conn_block_conn_id_uk ON conn_block(conn_id); CREATE TABLE conn_traffic( - conn_id INTEGER PRIMARY KEY, + id INTEGER PRIMARY KEY, + conn_id INTEGER NOT NULL, end_time INTEGER NOT NULL, in_bytes INTEGER NOT NULL, out_bytes INTEGER NOT NULL -) WITHOUT ROWID; +); + +CREATE UNIQUE INDEX conn_traffic_conn_id_uk ON conn_traffic(conn_id); CREATE TABLE conn_flow( conn_id INTEGER PRIMARY KEY, diff --git a/src/ui/stat/statmanager.cpp b/src/ui/stat/statmanager.cpp index 0fac9299..a64578b2 100644 --- a/src/ui/stat/statmanager.cpp +++ b/src/ui/stat/statmanager.cpp @@ -19,7 +19,7 @@ Q_LOGGING_CATEGORY(CLOG_STAT_MANAGER, "stat") #define logWarning() qCWarning(CLOG_STAT_MANAGER, ) #define logCritical() qCCritical(CLOG_STAT_MANAGER, ) -#define DATABASE_USER_VERSION 3 +#define DATABASE_USER_VERSION 4 #define ACTIVE_PERIOD_CHECK_SECS (60 * OS_TICKS_PER_SECOND) @@ -91,9 +91,20 @@ bool StatManager::initialize() return false; } + initializeConnBlockId(); + return true; } +void StatManager::initializeConnBlockId() +{ + const auto vars = m_sqliteDb->executeEx(StatSql::sqlSelectMinMaxConnBlockId, {}, 2).toList(); + if (vars.size() == 2) { + m_connBlockIdMin = vars.at(0).toLongLong(); + m_connBlockIdMax = vars.at(1).toLongLong(); + } +} + void StatManager::initializeActivePeriod() { m_isActivePeriodSet = false; @@ -328,7 +339,7 @@ bool StatManager::logStatTraf(quint16 procCount, const quint32 *procTrafBytes, q << getTrafficStmt(StatSql::sqlDeleteTrafMonth, oldTrafMonth); } - stepStmtList(deleteTrafStmts); + doStmtList(deleteTrafStmts); } m_sqliteDb->commitTransaction(); @@ -363,6 +374,9 @@ bool StatManager::logBlockedIp(bool inbound, quint8 blockReason, quint8 ipProto, ok = (connId > 0); if (ok) { ok = createConnBlock(connId, blockReason); + if (ok) { + m_connBlockIdMax++; + } } } @@ -374,12 +388,11 @@ void StatManager::deleteStatApp(qint64 appId) { m_sqliteDb->beginTransaction(); - deleteAppStmtList(getIdStmt(StatSql::sqlSelectDeletedStatAppPaths, appId), - { getIdStmt(StatSql::sqlDeleteStatAppId, appId), - getIdStmt(StatSql::sqlDeleteAppTrafHour, appId), - getIdStmt(StatSql::sqlDeleteAppTrafDay, appId), - getIdStmt(StatSql::sqlDeleteAppTrafMonth, appId), - getIdStmt(StatSql::sqlDeleteAppTrafTotal, appId) }); + deleteAppStmtList({ getIdStmt(StatSql::sqlDeleteAppTrafHour, appId), + getIdStmt(StatSql::sqlDeleteAppTrafDay, appId), + getIdStmt(StatSql::sqlDeleteAppTrafMonth, appId), + getIdStmt(StatSql::sqlDeleteAppTrafTotal, appId) }, + getIdStmt(StatSql::sqlSelectDeletedStatAppList, appId)); m_sqliteDb->commitTransaction(); } @@ -387,23 +400,23 @@ void StatManager::deleteStatApp(qint64 appId) bool StatManager::deleteOldConnBlock() { const int keepCount = m_conf->blockedIpKeepCount(); - const qint64 connId = - m_sqliteDb->executeEx(StatSql::sqlSelectOldConnBlock, { keepCount }).toLongLong(); - if (connId > 0) { - deleteRangeConnBlock(1, connId); - return true; - } - return false; + const int totalCount = m_connBlockIdMax - m_connBlockIdMin + 1; + const int oldCount = totalCount - keepCount; + if (oldCount <= 0) + return false; + + deleteRangeConnBlock(m_connBlockIdMin, m_connBlockIdMin + oldCount); + return true; } -bool StatManager::deleteConn(qint64 connId, bool blocked) +bool StatManager::deleteConn(qint64 rowIdTo, bool blocked) { m_sqliteDb->beginTransaction(); if (blocked) { - deleteRangeConnBlock(connId, connId); + deleteRangeConnBlock(m_connBlockIdMin, rowIdTo); } else { - // TODO: deleteRangeConnTraf(connId, connId); + // TODO: deleteRangeConnTraf(m_connTrafIdMin, rowIdTo); } m_sqliteDb->commitTransaction(); @@ -411,14 +424,13 @@ bool StatManager::deleteConn(qint64 connId, bool blocked) return true; } -void StatManager::deleteConns() +void StatManager::deleteConnAll() { m_sqliteDb->beginTransaction(); - deleteAppStmtList(getSqliteStmt(StatSql::sqlSelectDeletedAllConnAppPaths), - { getSqliteStmt(StatSql::sqlDeleteAllConnAppId), - getSqliteStmt(StatSql::sqlDeleteAllConn), - getSqliteStmt(StatSql::sqlDeleteAllConnBlock) }); + deleteAppStmtList({ getSqliteStmt(StatSql::sqlDeleteAllConn), + getSqliteStmt(StatSql::sqlDeleteAllConnBlock) }, + getSqliteStmt(StatSql::sqlSelectDeletedAllConnAppList)); m_sqliteDb->commitTransaction(); } @@ -451,23 +463,22 @@ qint64 StatManager::getAppId(const QString &appPath) qint64 StatManager::createAppId(const QString &appPath, qint64 unixTime, bool blocked) { - qint64 appId = INVALID_APP_ID; - SqliteStmt *stmt = getSqliteStmt(StatSql::sqlInsertAppId); stmt->bindText(1, appPath); stmt->bindInt64(2, unixTime); - if (stmt->step() == SqliteStmt::StepDone) { - appId = m_sqliteDb->lastInsertRowid(); + if (m_sqliteDb->done(stmt)) { + const qint64 appId = m_sqliteDb->lastInsertRowid(); if (!blocked) { emit appCreated(appId, appPath); } - } - stmt->reset(); - return appId; + return appId; + } + + return INVALID_APP_ID; } qint64 StatManager::getOrCreateAppId(const QString &appPath, qint64 unixTime, bool blocked) @@ -487,9 +498,16 @@ qint64 StatManager::getOrCreateAppId(const QString &appPath, qint64 unixTime, bo return appId; } +bool StatManager::deleteAppId(qint64 appId) +{ + SqliteStmt *stmt = getIdStmt(StatSql::sqlDeleteAppId, appId); + + return m_sqliteDb->done(stmt); +} + void StatManager::getStatAppList(QStringList &list, QVector &appIds) { - SqliteStmt *stmt = getSqliteStmt(StatSql::sqlSelectStatAppPaths); + SqliteStmt *stmt = getSqliteStmt(StatSql::sqlSelectStatAppList); while (stmt->step() == SqliteStmt::StepRow) { appIds.append(stmt->columnInt64(0)); @@ -524,18 +542,12 @@ bool StatManager::updateTraffic(SqliteStmt *stmt, quint32 inBytes, quint32 outBy stmt->bindInt64(4, appId); } - const SqliteStmt::StepResult res = stmt->step(); - const bool ok = res == SqliteStmt::StepDone && m_sqliteDb->changes() != 0; - stmt->reset(); - - return ok; + return m_sqliteDb->done(stmt); } qint64 StatManager::createConn(bool inbound, quint8 ipProto, quint16 localPort, quint16 remotePort, quint32 localIp, quint32 remoteIp, quint32 pid, qint64 unixTime, qint64 appId) { - qint64 connId = 0; - SqliteStmt *stmt = getSqliteStmt(StatSql::sqlInsertConn); stmt->bindInt64(1, appId); @@ -548,12 +560,11 @@ qint64 StatManager::createConn(bool inbound, quint8 ipProto, quint16 localPort, stmt->bindInt(8, localIp); stmt->bindInt(9, remoteIp); - if (stmt->step() == SqliteStmt::StepDone) { - connId = m_sqliteDb->lastInsertRowid(); + if (m_sqliteDb->done(stmt)) { + return m_sqliteDb->lastInsertRowid(); } - stmt->reset(); - return connId; + return 0; } bool StatManager::createConnBlock(qint64 connId, quint8 blockReason) @@ -563,37 +574,37 @@ bool StatManager::createConnBlock(qint64 connId, quint8 blockReason) stmt->bindInt64(1, connId); stmt->bindInt(2, blockReason); - const bool ok = (stmt->step() == SqliteStmt::StepDone); - stmt->reset(); - - return ok; + return m_sqliteDb->done(stmt); } -void StatManager::deleteRangeConnBlock(qint64 connIdFrom, qint64 connIdTo) +void StatManager::deleteRangeConnBlock(qint64 rowIdFrom, qint64 rowIdTo) { - deleteAppStmtList(getId2Stmt(StatSql::sqlSelectDeletedRangeConnAppPaths, connIdFrom, connIdTo), - { getId2Stmt(StatSql::sqlDeleteRangeConnAppId, connIdFrom, connIdTo), - getId2Stmt(StatSql::sqlDeleteRangeConn, connIdFrom, connIdTo), - getId2Stmt(StatSql::sqlDeleteRangeConnBlock, connIdFrom, connIdTo) }); + deleteAppStmtList({ getId2Stmt(StatSql::sqlDeleteRangeConnForBlock, rowIdFrom, rowIdTo), + getId2Stmt(StatSql::sqlDeleteRangeConnBlock, rowIdFrom, rowIdTo) }, + getId2Stmt(StatSql::sqlSelectDeletedRangeConnBlockAppList, rowIdFrom, rowIdTo)); + + m_connBlockIdMin = rowIdTo + 1; } -void StatManager::deleteAppStmtList( - SqliteStmt *stmtAppPaths, const StatManager::QStmtList &stmtList) +void StatManager::deleteAppStmtList(const StatManager::QStmtList &stmtList, SqliteStmt *stmtAppList) { + // Delete Statements + doStmtList(stmtList); + // Delete Cached AppIds { - while (stmtAppPaths->step() == SqliteStmt::StepRow) { - const QString appPath = stmtAppPaths->columnText(0); + while (stmtAppList->step() == SqliteStmt::StepRow) { + const qint64 appId = stmtAppList->columnInt64(0); + const QString appPath = stmtAppList->columnText(1); + + deleteAppId(appId); clearCachedAppId(appPath); } - stmtAppPaths->reset(); + stmtAppList->reset(); } - - // Delete Statements - stepStmtList(stmtList); } -void StatManager::stepStmtList(const QStmtList &stmtList) +void StatManager::doStmtList(const QStmtList &stmtList) { for (SqliteStmt *stmt : stmtList) { stmt->step(); diff --git a/src/ui/stat/statmanager.h b/src/ui/stat/statmanager.h index e3aea2c6..916ff646 100644 --- a/src/ui/stat/statmanager.h +++ b/src/ui/stat/statmanager.h @@ -23,6 +23,12 @@ public: ~StatManager() override; CLASS_DELETE_COPY_MOVE(StatManager) + qint64 connBlockIdMin() const { return m_connBlockIdMin; } + qint64 connBlockIdMax() const { return m_connBlockIdMax; } + + qint64 connTrafIdMin() const { return m_connTrafIdMin; } + qint64 connTrafIdMax() const { return m_connTrafIdMax; } + const FirewallConf *firewallConf() const { return m_conf; } void setFirewallConf(const FirewallConf *conf); @@ -42,8 +48,8 @@ public: void deleteStatApp(qint64 appId); bool deleteOldConnBlock(); - bool deleteConn(qint64 connId, bool blocked); - void deleteConns(); + bool deleteConn(qint64 rowIdTo, bool blocked); + void deleteConnAll(); void resetAppTrafTotals(); @@ -63,6 +69,7 @@ public slots: private: using QStmtList = QList; + void initializeConnBlockId(); void initializeActivePeriod(); void initializeQuota(); @@ -79,6 +86,7 @@ private: qint64 getAppId(const QString &appPath); qint64 createAppId(const QString &appPath, qint64 unixTime, bool blocked = false); qint64 getOrCreateAppId(const QString &appPath, qint64 unixTime = 0, bool blocked = false); + bool deleteAppId(qint64 appId); void updateTrafficList(const QStmtList &insertStmtList, const QStmtList &updateStmtList, quint32 inBytes, quint32 outBytes, qint64 appId = 0); @@ -88,11 +96,11 @@ private: qint64 createConn(bool inbound, quint8 ipProto, quint16 localPort, quint16 remotePort, quint32 localIp, quint32 remoteIp, quint32 pid, qint64 unixTime, qint64 appId); bool createConnBlock(qint64 connId, quint8 blockReason); - void deleteRangeConnBlock(qint64 connIdFrom, qint64 connIdTo); + void deleteRangeConnBlock(qint64 rowIdFrom, qint64 rowIdTo); - void deleteAppStmtList(SqliteStmt *stmtAppPaths, const QStmtList &stmtList); + void deleteAppStmtList(const QStmtList &stmtList, SqliteStmt *stmtAppList); - void stepStmtList(const QStmtList &stmtList); + void doStmtList(const QStmtList &stmtList); SqliteStmt *getTrafficStmt(const char *sql, qint32 trafTime); SqliteStmt *getIdStmt(const char *sql, qint64 id); @@ -114,6 +122,12 @@ private: qint32 m_lastTrafMonth = 0; qint32 m_lastTick = 0; + qint64 m_connBlockIdMin = 0; + qint64 m_connBlockIdMax = 0; + + qint64 m_connTrafIdMin = 0; + qint64 m_connTrafIdMax = 0; + QuotaManager *m_quotaManager = nullptr; const FirewallConf *m_conf = nullptr; diff --git a/src/ui/stat/statsql.cpp b/src/ui/stat/statsql.cpp index 5a4975c3..ffd4f2b7 100644 --- a/src/ui/stat/statsql.cpp +++ b/src/ui/stat/statsql.cpp @@ -4,17 +4,11 @@ const char *const StatSql::sqlSelectAppId = "SELECT app_id FROM app WHERE path = const char *const StatSql::sqlInsertAppId = "INSERT INTO app(path, creat_time) VALUES(?1, ?2);"; -const char *const StatSql::sqlSelectDeletedStatAppPaths = - "SELECT path FROM app WHERE app_id = ?1" - " and (SELECT 1 FROM conn WHERE app_id = ?1 LIMIT 1) is null;"; +const char *const StatSql::sqlDeleteAppId = "DELETE FROM app WHERE app_id = ?1;"; -const char *const StatSql::sqlDeleteStatAppId = - "DELETE FROM app WHERE app_id = ?1" - " and (SELECT 1 FROM conn WHERE app_id = ?1 LIMIT 1) is null;"; - -const char *const StatSql::sqlSelectStatAppPaths = "SELECT app_id, path" - " FROM app JOIN traffic_app USING(app_id)" - " ORDER BY app_id;"; +const char *const StatSql::sqlSelectStatAppList = "SELECT t.app_id, t.path FROM app t" + " JOIN traffic_app ta ON ta.app_id = t.app_id" + " ORDER BY t.app_id;"; const char *const StatSql::sqlInsertTrafAppHour = "INSERT INTO traffic_app_hour(app_id, traf_time, in_bytes, out_bytes)" @@ -47,22 +41,22 @@ const char *const StatSql::sqlInsertTrafMonth = const char *const StatSql::sqlUpdateTrafAppHour = "UPDATE traffic_app_hour" " SET in_bytes = in_bytes + ?2," " out_bytes = out_bytes + ?3" - " WHERE app_id = ?4 and traf_time = ?1;"; + " WHERE app_id = ?4 AND traf_time = ?1;"; const char *const StatSql::sqlUpdateTrafAppDay = "UPDATE traffic_app_day" " SET in_bytes = in_bytes + ?2," " out_bytes = out_bytes + ?3" - " WHERE app_id = ?4 and traf_time = ?1;"; + " WHERE app_id = ?4 AND traf_time = ?1;"; const char *const StatSql::sqlUpdateTrafAppMonth = "UPDATE traffic_app_month" " SET in_bytes = in_bytes + ?2," " out_bytes = out_bytes + ?3" - " WHERE app_id = ?4 and traf_time = ?1;"; + " WHERE app_id = ?4 AND traf_time = ?1;"; const char *const StatSql::sqlUpdateTrafAppTotal = "UPDATE traffic_app" " SET in_bytes = in_bytes + ?2," " out_bytes = out_bytes + ?3" - " WHERE app_id = ?4 and 0 != ?1;"; + " WHERE app_id = ?4 AND 0 != ?1;"; const char *const StatSql::sqlUpdateTrafHour = "UPDATE traffic_hour" " SET in_bytes = in_bytes + ?2," @@ -101,19 +95,19 @@ const char *const StatSql::sqlSelectMinTrafTotal = "SELECT min(traf_time) FROM t const char *const StatSql::sqlSelectTrafAppHour = "SELECT in_bytes, out_bytes" " FROM traffic_app_hour" - " WHERE app_id = ?2 and traf_time = ?1;"; + " WHERE app_id = ?2 AND traf_time = ?1;"; const char *const StatSql::sqlSelectTrafAppDay = "SELECT in_bytes, out_bytes" " FROM traffic_app_day" - " WHERE app_id = ?2 and traf_time = ?1;"; + " WHERE app_id = ?2 AND traf_time = ?1;"; const char *const StatSql::sqlSelectTrafAppMonth = "SELECT in_bytes, out_bytes" " FROM traffic_app_month" - " WHERE app_id = ?2 and traf_time = ?1;"; + " WHERE app_id = ?2 AND traf_time = ?1;"; const char *const StatSql::sqlSelectTrafAppTotal = "SELECT in_bytes, out_bytes" " FROM traffic_app" - " WHERE app_id = ?2 and 0 != ?1;"; + " WHERE app_id = ?2 AND 0 != ?1;"; const char *const StatSql::sqlSelectTrafHour = "SELECT in_bytes, out_bytes" " FROM traffic_hour WHERE traf_time = ?1;"; @@ -128,13 +122,13 @@ const char *const StatSql::sqlSelectTrafTotal = "SELECT sum(in_bytes), sum(out_b " FROM traffic_app WHERE 0 != ?1;"; const char *const StatSql::sqlDeleteTrafAppHour = "DELETE FROM traffic_app_hour" - " WHERE traf_time < ?1 and app_id > 0;"; + " WHERE traf_time < ?1 AND app_id > 0;"; const char *const StatSql::sqlDeleteTrafAppDay = "DELETE FROM traffic_app_day" - " WHERE traf_time < ?1 and app_id > 0;"; + " WHERE traf_time < ?1 AND app_id > 0;"; const char *const StatSql::sqlDeleteTrafAppMonth = "DELETE FROM traffic_app_month" - " WHERE traf_time < ?1 and app_id > 0;"; + " WHERE traf_time < ?1 AND app_id > 0;"; const char *const StatSql::sqlDeleteTrafHour = "DELETE FROM traffic_hour WHERE traf_time < ?1;"; @@ -154,6 +148,10 @@ const char *const StatSql::sqlDeleteAppTrafMonth = "DELETE FROM traffic_app_mont const char *const StatSql::sqlDeleteAppTrafTotal = "DELETE FROM traffic_app" " WHERE app_id = ?1;"; +const char *const StatSql::sqlSelectDeletedStatAppList = + "SELECT app_id, path FROM app WHERE app_id = ?1" + " AND (SELECT 1 FROM conn WHERE app_id = ?1 LIMIT 1) IS NULL;"; + const char *const StatSql::sqlResetAppTrafTotals = "UPDATE traffic_app" " SET traf_time = ?1, in_bytes = 0, out_bytes = 0;"; @@ -166,37 +164,28 @@ const char *const StatSql::sqlInsertConn = const char *const StatSql::sqlInsertConnBlock = "INSERT INTO conn_block(conn_id, block_reason)" " VALUES(?1, ?2);"; -const char *const StatSql::sqlSelectOldConnBlock = "SELECT conn_id FROM conn_block" - " ORDER BY conn_id DESC" - " LIMIT 1 OFFSET ?1;"; +const char *const StatSql::sqlSelectMinMaxConnBlockId = "SELECT MIN(id), MAX(id) FROM conn_block;"; -const char *const StatSql::sqlSelectDeletedRangeConnAppPaths = - "SELECT path FROM app WHERE app_id in (" - " SELECT app_id FROM conn t" - " LEFT JOIN traffic_app ta USING(app_id)" - " WHERE conn_id between ?1 and ?2 and ta.app_id is null" - ") and (SELECT 1 FROM conn c WHERE c.conn_id not between ?1 and ?2" - " and c.app_id = app.app_id LIMIT 1) is null;"; - -const char *const StatSql::sqlDeleteRangeConnAppId = - "DELETE FROM app WHERE app_id in (" - " SELECT app_id FROM conn" - " LEFT JOIN traffic_app ta USING(app_id)" - " WHERE conn_id between ?1 and ?2 and ta.app_id is null" - ") and (SELECT 1 FROM conn c WHERE c.conn_id not between ?1 and ?2" - " and c.app_id = app.app_id LIMIT 1) is null;"; - -const char *const StatSql::sqlDeleteRangeConn = "DELETE FROM conn WHERE conn_id between ?1 and ?2;"; +const char *const StatSql::sqlDeleteRangeConnForBlock = + "DELETE FROM conn WHERE conn_id IN (" + " SELECT conn_id FROM conn_block WHERE id BETWEEN ?1 AND ?2" + ");"; const char *const StatSql::sqlDeleteRangeConnBlock = - "DELETE FROM conn_block WHERE conn_id between ?1 and ?2;"; + "DELETE FROM conn_block WHERE id BETWEEN ?1 AND ?2;"; -const char *const StatSql::sqlSelectDeletedAllConnAppPaths = - "SELECT path FROM app WHERE app_id not in (SELECT app_id FROM traffic_app);"; - -const char *const StatSql::sqlDeleteAllConnAppId = - "DELETE FROM app WHERE app_id not in (SELECT app_id FROM traffic_app);"; +const char *const StatSql::sqlSelectDeletedRangeConnBlockAppList = + "SELECT t.app_id, t.path FROM app t" + " LEFT JOIN traffic_app ta ON ta.app_id = t.app_id" + " WHERE ta.app_id IS NULL AND (" + " SELECT 1 FROM conn c WHERE c.app_id = t.app_id LIMIT 1" + " ) IS NULL;"; const char *const StatSql::sqlDeleteAllConn = "DELETE FROM conn;"; const char *const StatSql::sqlDeleteAllConnBlock = "DELETE FROM conn_block;"; + +const char *const StatSql::sqlSelectDeletedAllConnAppList = + "SELECT t.app_id, t.path FROM app t" + " LEFT JOIN traffic_app ta ON ta.app_id = t.app_id" + " WHERE ta.app_id IS NULL;"; diff --git a/src/ui/stat/statsql.h b/src/ui/stat/statsql.h index 0b8d141d..38b1c10b 100644 --- a/src/ui/stat/statsql.h +++ b/src/ui/stat/statsql.h @@ -6,11 +6,9 @@ class StatSql public: static const char *const sqlSelectAppId; static const char *const sqlInsertAppId; + static const char *const sqlDeleteAppId; - static const char *const sqlSelectDeletedStatAppPaths; - static const char *const sqlDeleteStatAppId; - - static const char *const sqlSelectStatAppPaths; + static const char *const sqlSelectStatAppList; static const char *const sqlInsertTrafAppHour; static const char *const sqlInsertTrafAppDay; @@ -64,22 +62,22 @@ public: static const char *const sqlDeleteAppTrafMonth; static const char *const sqlDeleteAppTrafTotal; + static const char *const sqlSelectDeletedStatAppList; + static const char *const sqlResetAppTrafTotals; static const char *const sqlInsertConn; static const char *const sqlInsertConnBlock; - static const char *const sqlSelectOldConnBlock; + static const char *const sqlSelectMinMaxConnBlockId; - static const char *const sqlSelectDeletedRangeConnAppPaths; - static const char *const sqlDeleteRangeConnAppId; - static const char *const sqlDeleteRangeConn; + static const char *const sqlDeleteRangeConnForBlock; static const char *const sqlDeleteRangeConnBlock; + static const char *const sqlSelectDeletedRangeConnBlockAppList; - static const char *const sqlSelectDeletedAllConnAppPaths; - static const char *const sqlDeleteAllConnAppId; static const char *const sqlDeleteAllConn; static const char *const sqlDeleteAllConnBlock; + static const char *const sqlSelectDeletedAllConnAppList; }; #endif // STATSQL_H diff --git a/src/ui/util/model/tablesqlmodel.cpp b/src/ui/util/model/tablesqlmodel.cpp index d3aa0ee1..d9216d08 100644 --- a/src/ui/util/model/tablesqlmodel.cpp +++ b/src/ui/util/model/tablesqlmodel.cpp @@ -10,7 +10,7 @@ int TableSqlModel::rowCount(const QModelIndex &parent) const Q_UNUSED(parent); if (m_rowCount < 0) { - m_rowCount = sqliteDb()->executeEx(sqlCount().toLatin1()).toInt(); + m_rowCount = doSqlCount(); } return m_rowCount; @@ -55,6 +55,11 @@ void TableSqlModel::updateRowCache(int row) const } } +int TableSqlModel::doSqlCount() const +{ + return sqliteDb()->executeEx(sqlCount().toLatin1()).toInt(); +} + QString TableSqlModel::sqlCount() const { return "SELECT count(*) FROM (" + sqlBase() + ");"; @@ -62,7 +67,7 @@ QString TableSqlModel::sqlCount() const QString TableSqlModel::sql() const { - return sqlBase() + sqlOrder() + " LIMIT 1 OFFSET ?1;"; + return sqlBase() + sqlWhere() + sqlOrder() + sqlLimitOffset() + ';'; } QString TableSqlModel::sqlOrder() const @@ -82,3 +87,13 @@ QString TableSqlModel::sqlOrderColumn() const { return QString::number(sortColumn()); } + +QString TableSqlModel::sqlWhere() const +{ + return QString(); +} + +QString TableSqlModel::sqlLimitOffset() const +{ + return " LIMIT 1 OFFSET ?1"; +} diff --git a/src/ui/util/model/tablesqlmodel.h b/src/ui/util/model/tablesqlmodel.h index d35dcd28..bb368456 100644 --- a/src/ui/util/model/tablesqlmodel.h +++ b/src/ui/util/model/tablesqlmodel.h @@ -32,12 +32,16 @@ protected: virtual bool updateTableRow(int row) const = 0; virtual TableRow &tableRow() const = 0; + virtual int doSqlCount() const; + virtual QString sqlCount() const; virtual QString sql() const; virtual QString sqlBase() const = 0; virtual QString sqlOrder() const; virtual QString sqlOrderAsc() const; virtual QString sqlOrderColumn() const; + virtual QString sqlWhere() const; + virtual QString sqlLimitOffset() const; int sortColumn() const { return m_sortColumn; } void setSortColumn(int v) { m_sortColumn = v; }