FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period)

This commit is contained in:
Christophe Dumez 2010-01-24 11:57:15 +00:00
parent 540da69d61
commit 48dbaf05ae
9 changed files with 160 additions and 20 deletions

View file

@ -1,5 +1,6 @@
* Unreleased - Christophe Dumez <chris@qbittorrent.org> - v2.2.0 * Unreleased - Christophe Dumez <chris@qbittorrent.org> - v2.2.0
- FEATURE: User can set alternative speed limits for fast toggling - FEATURE: User can set alternative speed limits for fast toggling
- FEATURE: Bandwidth scheduler (automatically use alternative speed limits for a given period)
* Mon Jan 18 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.0 * Mon Jan 18 2010 - Christophe Dumez <chris@qbittorrent.org> - v2.1.0
- FEATURE: Graphical User Interface can be disabled at compilation time (headless running) - FEATURE: Graphical User Interface can be disabled at compilation time (headless running)

View file

@ -116,6 +116,7 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&))); connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&)));
connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString))); connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString)));
connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString))); connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString)));
connect(BTSession, SIGNAL(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
qDebug("create tabWidget"); qDebug("create tabWidget");
tabs = new QTabWidget(); tabs = new QTabWidget();
@ -181,7 +182,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis
// Create status bar // Create status bar
status_bar = new StatusBar(QMainWindow::statusBar(), BTSession); status_bar = new StatusBar(QMainWindow::statusBar(), BTSession);
connect(actionUse_alternative_speed_limits, SIGNAL(triggered()), status_bar, SLOT(toggleAlternativeSpeeds())); connect(actionUse_alternative_speed_limits, SIGNAL(triggered()), status_bar, SLOT(toggleAlternativeSpeeds()));
connect(status_bar, SIGNAL(alternativeSpeedsToggled(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
show(); show();

111
src/bandwidthscheduler.h Normal file
View file

@ -0,0 +1,111 @@
#ifndef BANDWIDTHSCHEDULER_H
#define BANDWIDTHSCHEDULER_H
#include <QTimer>
#include <QTime>
#include <QDateTime>
#include "preferences.h"
#include <iostream>
class BandwidthScheduler: public QTimer {
Q_OBJECT
private:
bool in_alternative_mode;
public:
BandwidthScheduler(QObject *parent): QTimer(parent), in_alternative_mode(false) {
Q_ASSERT(Preferences::isSchedulerEnabled());
// Signal shot, we call start() again manually
setSingleShot(true);
// Connect Signals/Slots
connect(this, SIGNAL(timeout()), this, SLOT(switchMode()));
}
public slots:
void start() {
Q_ASSERT(Preferences::isSchedulerEnabled());
QTime startAltSpeeds = Preferences::getSchedulerStartTime();
QTime endAltSpeeds = Preferences::getSchedulerEndTime();
if(startAltSpeeds == endAltSpeeds) {
std::cerr << "Error: bandwidth scheduler have the same start time and end time." << std::endl;
std::cerr << "The bandwidth scheduler will be disabled" << std::endl;
stop();
emit switchToAlternativeMode(false);
return;
}
// Determine what the closest QTime is
QTime now = QTime::currentTime();
uint time_to_start = secsTo(now, startAltSpeeds);
uint time_to_end = secsTo(now, endAltSpeeds);
if(time_to_end < time_to_start) {
// We should be in alternative mode
in_alternative_mode = true;
// Start counting
QTimer::start(time_to_end*1000);
} else {
// We should be in normal mode
in_alternative_mode = false;
// Start counting
QTimer::start(time_to_start*1000);
}
// Send signal to notify BTSession
emit switchToAlternativeMode(in_alternative_mode);
}
void switchMode() {
// Get the day this mode was started (either today or yesterday)
QDate current_date = QDateTime::currentDateTime().toLocalTime().date();
int day = current_date.dayOfWeek();
if(in_alternative_mode) {
// It is possible that starttime was yesterday
if(QTime::currentTime().secsTo(Preferences::getSchedulerStartTime()) > 0) {
current_date.addDays(-1); // Go to yesterday
day = current_date.day();
}
}
// Check if the day is in scheduler days
// Notify BTSession only if necessary
switch(Preferences::getSchedulerDays()) {
case EVERY_DAY:
emit switchToAlternativeMode(!in_alternative_mode);
break;
case WEEK_ENDS:
if(day == Qt::Saturday || day == Qt::Sunday)
emit switchToAlternativeMode(!in_alternative_mode);
break;
case WEEK_DAYS:
if(day != Qt::Saturday && day != Qt::Sunday)
emit switchToAlternativeMode(!in_alternative_mode);
break;
default:
// Convert our enum index to Qt enum index
int scheduler_day = ((int)Preferences::getSchedulerDays()) - 2;
if(day == scheduler_day)
emit switchToAlternativeMode(!in_alternative_mode);
break;
}
// Call start again
start();
}
signals:
void switchToAlternativeMode(bool alternative);
private:
// Qt function can return negative values and we
// don't want that
uint secsTo(QTime now, QTime t) {
int diff = now.secsTo(t);
if(diff < 0) {
// 86400 seconds in a day
diff += 86400;
}
Q_ASSERT(diff >= 0);
return diff;
}
};
#endif // BANDWIDTHSCHEDULER_H

View file

@ -46,6 +46,7 @@
#endif #endif
#include "torrentpersistentdata.h" #include "torrentpersistentdata.h"
#include "httpserver.h" #include "httpserver.h"
#include "bandwidthscheduler.h"
#include <libtorrent/extensions/ut_metadata.hpp> #include <libtorrent/extensions/ut_metadata.hpp>
#ifdef LIBTORRENT_0_15 #ifdef LIBTORRENT_0_15
#include <libtorrent/extensions/lt_trackers.hpp> #include <libtorrent/extensions/lt_trackers.hpp>
@ -173,9 +174,10 @@ Bittorrent::~Bittorrent() {
if(filterParser) if(filterParser)
delete filterParser; delete filterParser;
delete downloader; delete downloader;
if(FSWatcher) { if(FSWatcher)
delete FSWatcher; delete FSWatcher;
} if(bd_scheduler)
delete bd_scheduler;
// HTTP Server // HTTP Server
if(httpServer) if(httpServer)
delete httpServer; delete httpServer;
@ -313,6 +315,15 @@ void Bittorrent::configureSession() {
// Enabled // Enabled
setUploadRateLimit(up_limit*1024); setUploadRateLimit(up_limit*1024);
} }
if(Preferences::isSchedulerEnabled()) {
if(!bd_scheduler) {
bd_scheduler = new BandwidthScheduler(this);
connect(bd_scheduler, SIGNAL(switchToAlternativeMode(bool)), this, SLOT(useAlternativeSpeedsLimit(bool)));
}
bd_scheduler->start();
} else {
if(bd_scheduler) delete bd_scheduler;
}
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
// Resolve countries // Resolve countries
qDebug("Loading country resolution settings"); qDebug("Loading country resolution settings");
@ -587,6 +598,20 @@ bool Bittorrent::initWebUi(QString username, QString password, int port) {
return success; return success;
} }
void Bittorrent::useAlternativeSpeedsLimit(bool alternative) {
// Save new state to remember it on startup
Preferences::setAltBandwidthEnabled(alternative);
// Apply settings to the bittorrent session
if(alternative) {
s->set_download_rate_limit(Preferences::getAltGlobalDownloadLimit()*1024);
s->set_upload_rate_limit(Preferences::getAltGlobalUploadLimit()*1024);
} else {
s->set_download_rate_limit(Preferences::getGlobalDownloadLimit()*1024);
s->set_upload_rate_limit(Preferences::getGlobalUploadLimit()*1024);
}
emit alternativeSpeedsModeChanged(alternative);
}
void Bittorrent::takeETASamples() { void Bittorrent::takeETASamples() {
bool change = false;; bool change = false;;
foreach(const QString &hash, ETA_samples.keys()) { foreach(const QString &hash, ETA_samples.keys()) {

View file

@ -55,6 +55,7 @@ class QTimer;
class FileSystemWatcher; class FileSystemWatcher;
class FilterParserThread; class FilterParserThread;
class HttpServer; class HttpServer;
class BandwidthScheduler;
class TrackerInfos { class TrackerInfos {
public: public:
@ -92,6 +93,7 @@ private:
// Bittorrent // Bittorrent
session *s; session *s;
QPointer<QTimer> timerAlerts; QPointer<QTimer> timerAlerts;
QPointer<BandwidthScheduler> bd_scheduler;
QMap<QUrl, QString> savepath_fromurl; QMap<QUrl, QString> savepath_fromurl;
QHash<QString, QHash<QString, TrackerInfos> > trackersInfos; QHash<QString, QHash<QString, TrackerInfos> > trackersInfos;
QStringList torrentsToPausedAfterChecking; QStringList torrentsToPausedAfterChecking;
@ -182,6 +184,7 @@ public slots:
void startUpTorrents(); void startUpTorrents();
session_proxy asyncDeletion(); session_proxy asyncDeletion();
void recheckTorrent(QString hash); void recheckTorrent(QString hash);
void useAlternativeSpeedsLimit(bool alternative);
/* Needed by Web UI */ /* Needed by Web UI */
void pauseAllTorrents(); void pauseAllTorrents();
void pauseTorrent(QString hash); void pauseTorrent(QString hash);
@ -261,6 +264,7 @@ signals:
void metadataReceived(QTorrentHandle &h); void metadataReceived(QTorrentHandle &h);
void savePathChanged(QTorrentHandle &h); void savePathChanged(QTorrentHandle &h);
void newConsoleMessage(QString msg); void newConsoleMessage(QString msg);
void alternativeSpeedsModeChanged(bool alternative);
}; };
#endif #endif

View file

@ -37,7 +37,7 @@ public:
} }
~FeedList() { ~FeedList() {
//delete unread_item; delete unread_item;
} }
void itemAdded(QTreeWidgetItem *item, RssFile* file) { void itemAdded(QTreeWidgetItem *item, RssFile* file) {

View file

@ -204,7 +204,8 @@ HEADERS += misc.h \
stacktrace.h \ stacktrace.h \
torrentpersistentdata.h \ torrentpersistentdata.h \
filesystemwatcher.h \ filesystemwatcher.h \
preferences.h preferences.h \
bandwidthscheduler.h
contains(DEFINES, DISABLE_GUI) { contains(DEFINES, DISABLE_GUI) {
HEADERS += headlessloader.h HEADERS += headlessloader.h

View file

@ -64,6 +64,7 @@ private:
public: public:
StatusBar(QStatusBar *bar, Bittorrent *BTSession): bar(bar), BTSession(BTSession) { StatusBar(QStatusBar *bar, Bittorrent *BTSession): bar(bar), BTSession(BTSession) {
connect(BTSession, SIGNAL(alternativeSpeedsModeChanged(bool)), this, SLOT(updateAltSpeedsBtn(bool)));
container = new QWidget(); container = new QWidget();
layout = new QGridLayout(container); layout = new QGridLayout(container);
layout->setVerticalSpacing(0); layout->setVerticalSpacing(0);
@ -198,17 +199,7 @@ public slots:
} }
void toggleAlternativeSpeeds() { void toggleAlternativeSpeeds() {
bool alt = !Preferences::isAltBandwidthEnabled(); BTSession->useAlternativeSpeedsLimit(!Preferences::isAltBandwidthEnabled());
Preferences::setAltBandwidthEnabled(alt);
if(alt) {
BTSession->getSession()->set_download_rate_limit(Preferences::getAltGlobalDownloadLimit()*1024);
BTSession->getSession()->set_upload_rate_limit(Preferences::getAltGlobalUploadLimit()*1024);
} else {
BTSession->getSession()->set_download_rate_limit(Preferences::getGlobalDownloadLimit()*1024);
BTSession->getSession()->set_upload_rate_limit(Preferences::getGlobalUploadLimit()*1024);
}
updateAltSpeedsBtn(alt);
emit alternativeSpeedsToggled(alt);
} }
void capDownloadSpeed() { void capDownloadSpeed() {
@ -246,8 +237,6 @@ public slots:
} }
} }
signals:
void alternativeSpeedsToggled(bool alternative);
}; };
#endif // STATUSBAR_H #endif // STATUSBAR_H

View file

@ -1661,6 +1661,12 @@ QGroupBox {
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="displayFormat">
<string>hh:mm</string>
</property>
<property name="calendarPopup">
<bool>false</bool>
</property>
<property name="time"> <property name="time">
<time> <time>
<hour>8</hour> <hour>8</hour>
@ -1685,6 +1691,9 @@ QGroupBox {
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="displayFormat">
<string>hh:mm</string>
</property>
<property name="time"> <property name="time">
<time> <time>
<hour>20</hour> <hour>20</hour>
@ -1789,8 +1798,8 @@ QGroupBox {
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>620</width> <width>466</width>
<height>490</height> <height>415</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_20"> <layout class="QVBoxLayout" name="verticalLayout_20">