Browse Source

Improve BandwidthScheduler

Don't disable scheduler when manually switching speed limits.
Closes #7306.
adaptive-webui-19844
Vladimir Golovnev (qlassez) 7 years ago
parent
commit
93f5d4058d
No known key found for this signature in database
GPG Key ID: 52A2C7DEE2DFA6F7
  1. 75
      src/base/bittorrent/private/bandwidthscheduler.cpp
  2. 22
      src/base/bittorrent/private/bandwidthscheduler.h
  3. 71
      src/base/bittorrent/session.cpp
  4. 5
      src/base/bittorrent/session.h
  5. 4
      src/gui/mainwindow.cpp
  6. 4
      src/gui/optionsdlg.cpp

75
src/base/bittorrent/private/bandwidthscheduler.cpp

@ -1,6 +1,7 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez * Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -24,72 +25,78 @@
* modify file(s), you may extend this exception to your version of the file(s), * modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this * but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version. * exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/ */
#include "bandwidthscheduler.h"
#include <utility>
#include <QDate>
#include <QTime> #include <QTime>
#include <QDateTime>
#include "base/bittorrent/session.h"
#include "base/preferences.h" #include "base/preferences.h"
#include "bandwidthscheduler.h"
BandwidthScheduler::BandwidthScheduler(QObject *parent) BandwidthScheduler::BandwidthScheduler(QObject *parent)
: QTimer(parent) : QObject(parent)
, m_lastAlternative(false)
{ {
// Single shot, we call start() again manually connect(&m_timer, &QTimer::timeout, this, &BandwidthScheduler::onTimeout);
setSingleShot(true);
// Connect Signals/Slots
connect(this, SIGNAL(timeout()), this, SLOT(start()));
} }
void BandwidthScheduler::start() void BandwidthScheduler::start()
{
m_lastAlternative = isTimeForAlternative();
emit bandwidthLimitRequested(m_lastAlternative);
// Timeout regularly to accommodate for external system clock changes
// eg from the user or from a timesync utility
m_timer.start(30000);
}
bool BandwidthScheduler::isTimeForAlternative() const
{ {
const Preferences* const pref = Preferences::instance(); const Preferences* const pref = Preferences::instance();
bool alt_bw_enabled = BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled();
QTime start = pref->getSchedulerStartTime(); QTime start = pref->getSchedulerStartTime();
QTime end = pref->getSchedulerEndTime(); QTime end = pref->getSchedulerEndTime();
QTime now = QTime::currentTime(); const QTime now = QTime::currentTime();
int sched_days = pref->getSchedulerDays(); const int schedulerDays = pref->getSchedulerDays();
int day = QDateTime::currentDateTime().toLocalTime().date().dayOfWeek(); const int day = QDate::currentDate().dayOfWeek();
bool new_mode = false; bool alternative = false;
bool reverse = false;
if (start > end) { if (start > end) {
QTime temp = start; std::swap(start, end);
start = end; alternative = true;
end = temp;
reverse = true;
} }
if ((start <= now) && (end >= now)) { if ((start <= now) && (end >= now)) {
switch(sched_days) { switch (schedulerDays) {
case EVERY_DAY: case EVERY_DAY:
new_mode = true; alternative = !alternative;
break; break;
case WEEK_ENDS: case WEEK_ENDS:
if ((day == 6) || (day == 7)) if ((day == 6) || (day == 7))
new_mode = true; alternative = !alternative;
break; break;
case WEEK_DAYS: case WEEK_DAYS:
if ((day != 6) && (day != 7)) if ((day != 6) && (day != 7))
new_mode = true; alternative = !alternative;
break; break;
default: default:
if (day == (sched_days - 2)) if (day == (schedulerDays - 2))
new_mode = true; alternative = !alternative;
} }
} }
if (reverse) return alternative;
new_mode = !new_mode; }
if (new_mode != alt_bw_enabled) void BandwidthScheduler::onTimeout()
emit switchToAlternativeMode(new_mode); {
bool alternative = isTimeForAlternative();
// Timeout regularly to accommodate for external system clock changes if (alternative != m_lastAlternative) {
// eg from the user or from a timesync utility m_lastAlternative = alternative;
QTimer::start(1500); emit bandwidthLimitRequested(alternative);
}
} }

22
src/base/bittorrent/private/bandwidthscheduler.h

@ -1,6 +1,7 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez * Copyright (C) 2017 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -24,27 +25,32 @@
* modify file(s), you may extend this exception to your version of the file(s), * modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this * but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version. * exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/ */
#ifndef BANDWIDTHSCHEDULER_H #ifndef BANDWIDTHSCHEDULER_H
#define BANDWIDTHSCHEDULER_H #define BANDWIDTHSCHEDULER_H
#include <QObject>
#include <QTimer> #include <QTimer>
class BandwidthScheduler : public QTimer class BandwidthScheduler: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_DISABLE_COPY(BandwidthScheduler)
public: public:
BandwidthScheduler(QObject *parent = 0); explicit BandwidthScheduler(QObject *parent = nullptr);
public slots:
void start(); void start();
signals: signals:
void switchToAlternativeMode(bool alternative); void bandwidthLimitRequested(bool alternative);
private:
bool isTimeForAlternative() const;
void onTimeout();
QTimer m_timer;
bool m_lastAlternative;
}; };
#endif // BANDWIDTHSCHEDULER_H #endif // BANDWIDTHSCHEDULER_H

71
src/base/bittorrent/session.cpp

@ -441,6 +441,9 @@ Session::Session(QObject *parent)
.arg(encryption() == 0 ? tr("ON") : encryption() == 1 ? tr("FORCED") : tr("OFF")) .arg(encryption() == 0 ? tr("ON") : encryption() == 1 ? tr("FORCED") : tr("OFF"))
, Log::INFO); , Log::INFO);
if (isBandwidthSchedulerEnabled())
enableBandwidthScheduler();
if (isIPFilteringEnabled()) { if (isIPFilteringEnabled()) {
// Manually banned IPs are handled in that function too(in the slots) // Manually banned IPs are handled in that function too(in the slots)
enableIPFilter(); enableIPFilter();
@ -953,13 +956,8 @@ Session::~Session()
void Session::initInstance() void Session::initInstance()
{ {
if (!m_instance) { if (!m_instance)
m_instance = new Session; m_instance = new Session;
// BandwidthScheduler::start() depends on Session being fully constructed
if (m_instance->isBandwidthSchedulerEnabled())
m_instance->enableBandwidthScheduler();
}
} }
void Session::freeInstance() void Session::freeInstance()
@ -990,6 +988,19 @@ void Session::adjustLimits()
} }
} }
void Session::applyBandwidthLimits()
{
#if LIBTORRENT_VERSION_NUM < 10100
libt::session_settings sessionSettings(m_nativeSession->settings());
applyBandwidthLimits(sessionSettings);
m_nativeSession->set_settings(sessionSettings);
#else
libt::settings_pack settingsPack = m_nativeSession->get_settings();
applyBandwidthLimits(settingsPack);
m_nativeSession->apply_settings(settingsPack);
#endif
}
// Set BitTorrent session configuration // Set BitTorrent session configuration
void Session::configure() void Session::configure()
{ {
@ -1042,6 +1053,13 @@ void Session::adjustLimits(libt::settings_pack &settingsPack)
, maxActive > -1 ? maxActive + m_extraLimit : maxActive); , maxActive > -1 ? maxActive + m_extraLimit : maxActive);
} }
void Session::applyBandwidthLimits(libtorrent::settings_pack &settingsPack)
{
const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled();
settingsPack.set_int(libt::settings_pack::download_rate_limit, altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit());
settingsPack.set_int(libt::settings_pack::upload_rate_limit, altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit());
}
void Session::initMetrics() void Session::initMetrics()
{ {
m_metricIndices.net.hasIncomingConnections = libt::find_metric_idx("net.has_incoming_connections"); m_metricIndices.net.hasIncomingConnections = libt::find_metric_idx("net.has_incoming_connections");
@ -1185,9 +1203,7 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
m_listenInterfaceChanged = false; m_listenInterfaceChanged = false;
} }
const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled(); applyBandwidthLimits(settingsPack);
settingsPack.set_int(libt::settings_pack::download_rate_limit, altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit());
settingsPack.set_int(libt::settings_pack::upload_rate_limit, altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit());
// The most secure, rc4 only so that all streams are encrypted // The most secure, rc4 only so that all streams are encrypted
settingsPack.set_int(libt::settings_pack::allowed_enc_level, libt::settings_pack::pe_rc4); settingsPack.set_int(libt::settings_pack::allowed_enc_level, libt::settings_pack::pe_rc4);
@ -1397,11 +1413,16 @@ void Session::adjustLimits(libt::session_settings &sessionSettings)
sessionSettings.active_limit = maxActive > -1 ? maxActive + m_extraLimit : maxActive; sessionSettings.active_limit = maxActive > -1 ? maxActive + m_extraLimit : maxActive;
} }
void Session::configure(libtorrent::session_settings &sessionSettings) void Session::applyBandwidthLimits(libt::session_settings &sessionSettings)
{ {
const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled(); const bool altSpeedLimitEnabled = isAltGlobalSpeedLimitEnabled();
sessionSettings.download_rate_limit = altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit(); sessionSettings.download_rate_limit = altSpeedLimitEnabled ? altGlobalDownloadSpeedLimit() : globalDownloadSpeedLimit();
sessionSettings.upload_rate_limit = altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit(); sessionSettings.upload_rate_limit = altSpeedLimitEnabled ? altGlobalUploadSpeedLimit() : globalUploadSpeedLimit();
}
void Session::configure(libtorrent::session_settings &sessionSettings)
{
applyBandwidthLimits(sessionSettings);
// The most secure, rc4 only so that all streams are encrypted // The most secure, rc4 only so that all streams are encrypted
libt::pe_settings encryptionSettings; libt::pe_settings encryptionSettings;
@ -1568,7 +1589,8 @@ void Session::enableBandwidthScheduler()
{ {
if (!m_bwScheduler) { if (!m_bwScheduler) {
m_bwScheduler = new BandwidthScheduler(this); m_bwScheduler = new BandwidthScheduler(this);
connect(m_bwScheduler.data(), SIGNAL(switchToAlternativeMode(bool)), this, SLOT(switchToAlternativeMode(bool))); connect(m_bwScheduler.data(), &BandwidthScheduler::bandwidthLimitRequested
, this, &Session::setAltGlobalSpeedLimitEnabled);
} }
m_bwScheduler->start(); m_bwScheduler->start();
} }
@ -1650,11 +1672,6 @@ void Session::handleRedirectedToMagnet(const QString &url, const QString &magnet
addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(magnetUri)); addTorrent_impl(m_downloadedTorrents.take(url), MagnetUri(magnetUri));
} }
void Session::switchToAlternativeMode(bool alternative)
{
changeSpeedLimitMode_impl(alternative);
}
// Add to BitTorrent session the downloaded torrent file // Add to BitTorrent session the downloaded torrent file
void Session::handleDownloadFinished(const QString &url, const QString &filePath) void Session::handleDownloadFinished(const QString &url, const QString &filePath)
{ {
@ -2147,18 +2164,6 @@ void Session::exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolde
} }
} }
void Session::changeSpeedLimitMode_impl(bool alternative)
{
qDebug() << Q_FUNC_INFO << alternative;
if (alternative == isAltGlobalSpeedLimitEnabled()) return;
// Save new state to remember it on startup
m_isAltGlobalSpeedLimitEnabled = alternative;
configureDeferred();
// Notify
emit speedLimitModeChanged(alternative);
}
void Session::generateResumeData(bool final) void Session::generateResumeData(bool final)
{ {
foreach (TorrentHandle *const torrent, m_torrents) { foreach (TorrentHandle *const torrent, m_torrents) {
@ -2488,11 +2493,13 @@ bool Session::isAltGlobalSpeedLimitEnabled() const
void Session::setAltGlobalSpeedLimitEnabled(bool enabled) void Session::setAltGlobalSpeedLimitEnabled(bool enabled)
{ {
// Stop the scheduler when the user has manually changed the bandwidth mode if (enabled == isAltGlobalSpeedLimitEnabled()) return;
if (isBandwidthSchedulerEnabled())
setBandwidthSchedulerEnabled(false);
changeSpeedLimitMode_impl(enabled); // Save new state to remember it on startup
m_isAltGlobalSpeedLimitEnabled = enabled;
applyBandwidthLimits();
// Notify
emit speedLimitModeChanged(m_isAltGlobalSpeedLimitEnabled);
} }
bool Session::isBandwidthSchedulerEnabled() const bool Session::isBandwidthSchedulerEnabled() const

5
src/base/bittorrent/session.h

@ -480,7 +480,6 @@ namespace BitTorrent
void handleDownloadFinished(const QString &url, const QString &filePath); void handleDownloadFinished(const QString &url, const QString &filePath);
void handleDownloadFailed(const QString &url, const QString &reason); void handleDownloadFailed(const QString &url, const QString &reason);
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri); void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
void switchToAlternativeMode(bool alternative);
// Session reconfiguration triggers // Session reconfiguration triggers
void networkOnlineStateChanged(const bool online); void networkOnlineStateChanged(const bool online);
@ -500,17 +499,19 @@ namespace BitTorrent
#if LIBTORRENT_VERSION_NUM < 10100 #if LIBTORRENT_VERSION_NUM < 10100
void configure(libtorrent::session_settings &sessionSettings); void configure(libtorrent::session_settings &sessionSettings);
void adjustLimits(libtorrent::session_settings &sessionSettings); void adjustLimits(libtorrent::session_settings &sessionSettings);
void applyBandwidthLimits(libtorrent::session_settings &sessionSettings);
#else #else
void configure(libtorrent::settings_pack &settingsPack); void configure(libtorrent::settings_pack &settingsPack);
void configurePeerClasses(); void configurePeerClasses();
void adjustLimits(libtorrent::settings_pack &settingsPack); void adjustLimits(libtorrent::settings_pack &settingsPack);
void applyBandwidthLimits(libtorrent::settings_pack &settingsPack);
void initMetrics(); void initMetrics();
#endif #endif
void adjustLimits(); void adjustLimits();
void applyBandwidthLimits();
void processBannedIPs(libtorrent::ip_filter &filter); void processBannedIPs(libtorrent::ip_filter &filter);
const QStringList getListeningIPs(); const QStringList getListeningIPs();
void configureListeningInterface(); void configureListeningInterface();
void changeSpeedLimitMode_impl(bool alternative);
void enableTracker(bool enable); void enableTracker(bool enable);
void enableBandwidthScheduler(); void enableBandwidthScheduler();
void populateAdditionalTrackers(); void populateAdditionalTrackers();

4
src/gui/mainwindow.cpp

@ -1293,7 +1293,7 @@ static bool dockClickHandler(id self, SEL cmd, ...)
} }
void MainWindow::setupDockClickHandler() void MainWindow::setupDockClickHandler()
{ {
dockMainWindowHandle = this; dockMainWindowHandle = this;
overrideDockClickHandler(dockClickHandler); overrideDockClickHandler(dockClickHandler);
} }
@ -1831,8 +1831,6 @@ void MainWindow::handleUpdateCheckFinished(bool updateAvailable, QString newVers
void MainWindow::toggleAlternativeSpeeds() void MainWindow::toggleAlternativeSpeeds()
{ {
BitTorrent::Session *const session = BitTorrent::Session::instance(); BitTorrent::Session *const session = BitTorrent::Session::instance();
if (session->isBandwidthSchedulerEnabled())
m_statusBar->showMessage(tr("Manual change of rate limits mode. The scheduler is disabled."), 5000);
session->setAltGlobalSpeedLimitEnabled(!session->isAltGlobalSpeedLimitEnabled()); session->setAltGlobalSpeedLimitEnabled(!session->isAltGlobalSpeedLimitEnabled());
} }

4
src/gui/optionsdlg.cpp

@ -84,7 +84,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
#if (defined(Q_OS_UNIX)) #if (defined(Q_OS_UNIX))
setWindowTitle(tr("Preferences")); setWindowTitle(tr("Preferences"));
#endif #endif
// Icons // Icons
m_ui->tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop")); m_ui->tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop"));
m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network")); m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network"));
@ -586,10 +586,10 @@ void OptionsDialog::saveOptions()
const QPair<int, int> alt_down_up_limit = getAltGlobalBandwidthLimits(); const QPair<int, int> alt_down_up_limit = getAltGlobalBandwidthLimits();
session->setAltGlobalDownloadSpeedLimit(alt_down_up_limit.first); session->setAltGlobalDownloadSpeedLimit(alt_down_up_limit.first);
session->setAltGlobalUploadSpeedLimit(alt_down_up_limit.second); session->setAltGlobalUploadSpeedLimit(alt_down_up_limit.second);
session->setBandwidthSchedulerEnabled(m_ui->check_schedule->isChecked());
pref->setSchedulerStartTime(m_ui->schedule_from->time()); pref->setSchedulerStartTime(m_ui->schedule_from->time());
pref->setSchedulerEndTime(m_ui->schedule_to->time()); pref->setSchedulerEndTime(m_ui->schedule_to->time());
pref->setSchedulerDays(static_cast<scheduler_days>(m_ui->schedule_days->currentIndex())); pref->setSchedulerDays(static_cast<scheduler_days>(m_ui->schedule_days->currentIndex()));
session->setBandwidthSchedulerEnabled(m_ui->check_schedule->isChecked());
auto proxyConfigManager = Net::ProxyConfigurationManager::instance(); auto proxyConfigManager = Net::ProxyConfigurationManager::instance();
Net::ProxyConfiguration proxyConf; Net::ProxyConfiguration proxyConf;

Loading…
Cancel
Save