From 1fce01fedad8bf604ea7688e87fbd7d7c0f68366 Mon Sep 17 00:00:00 2001 From: Sandip Pandey Date: Thu, 29 Oct 2020 10:34:13 +0100 Subject: [PATCH] Set libtorrent max rate limit --- .../tribler_common/simpledefs.py | 8 ++++++ .../config/test_tribler_config.py | 14 +++++++++++ .../tribler_core/config/tribler_config.py | 6 +++-- .../restapi/tests/test_settings_endpoint.py | 25 +++++++++++++++++++ .../tribler_gui/widgets/settingspage.py | 17 +++++++------ 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/tribler-common/tribler_common/simpledefs.py b/src/tribler-common/tribler_common/simpledefs.py index 6712bfcd885..f2841fb97ea 100644 --- a/src/tribler-common/tribler_common/simpledefs.py +++ b/src/tribler-common/tribler_common/simpledefs.py @@ -100,3 +100,11 @@ class NTFY(Enum): LOW_SPACE = "low_space" EVENTS_START = "events_start" TRIBLER_EXCEPTION = "tribler_exception" + + +# Max download or upload rate limit for libtorrent. +# On Win64, the compiled version of libtorrent only supported 2^31 - 1 +# as rate limit values instead of sys.maxsize or 2^63 -1. Since 2^31 +# is a sufficiently large value for download/upload rate limit, +# here we set the max values for these parameters. +MAX_LIBTORRENT_RATE_LIMIT = 2**31 - 1 # bytes per second diff --git a/src/tribler-core/tribler_core/config/test_tribler_config.py b/src/tribler-core/tribler_core/config/test_tribler_config.py index 430d543808d..b29afb87799 100644 --- a/src/tribler-core/tribler_core/config/test_tribler_config.py +++ b/src/tribler-core/tribler_core/config/test_tribler_config.py @@ -1,3 +1,4 @@ +from tribler_common.simpledefs import MAX_LIBTORRENT_RATE_LIMIT from tribler_core.config.tribler_config import CONFIG_FILENAME, TriblerConfig from tribler_core.tests.tools.base_test import TriblerCoreTest @@ -196,6 +197,19 @@ def test_get_set_methods_libtorrent(self): self.tribler_config.set_libtorrent_dht_enabled(False) self.assertFalse(self.tribler_config.get_libtorrent_dht_enabled()) + # Add tests for setting libtorrent rate limits + rate_limit = MAX_LIBTORRENT_RATE_LIMIT - 1024 # lower than the max value set + self.tribler_config.set_libtorrent_max_upload_rate(rate_limit) + self.assertEqual(self.tribler_config.get_libtorrent_max_upload_rate(), rate_limit) + self.tribler_config.set_libtorrent_max_download_rate(rate_limit) + self.assertEqual(self.tribler_config.get_libtorrent_max_download_rate(), rate_limit) + + rate_limit = MAX_LIBTORRENT_RATE_LIMIT + 1024 # higher than the max value set + self.tribler_config.set_libtorrent_max_upload_rate(rate_limit) + self.assertEqual(self.tribler_config.get_libtorrent_max_upload_rate(), MAX_LIBTORRENT_RATE_LIMIT) + self.tribler_config.set_libtorrent_max_download_rate(rate_limit) + self.assertEqual(self.tribler_config.get_libtorrent_max_download_rate(), MAX_LIBTORRENT_RATE_LIMIT) + def test_get_set_methods_tunnel_community(self): """ Check whether tunnel community get and set methods are working as expected. diff --git a/src/tribler-core/tribler_core/config/tribler_config.py b/src/tribler-core/tribler_core/config/tribler_config.py index 7d23454d006..a10d9d9ebdc 100644 --- a/src/tribler-core/tribler_core/config/tribler_config.py +++ b/src/tribler-core/tribler_core/config/tribler_config.py @@ -8,6 +8,8 @@ from validate import Validator +from tribler_common.simpledefs import MAX_LIBTORRENT_RATE_LIMIT + from tribler_core.exceptions import InvalidConfigException from tribler_core.modules.libtorrent.download_config import get_default_dest_dir from tribler_core.utilities import path_util @@ -406,7 +408,7 @@ def get_libtorrent_max_upload_rate(self): :return: the maximum upload rate in kB / s """ - return self.config['libtorrent'].as_int('max_upload_rate') + return min(self.config['libtorrent'].as_int('max_upload_rate'), MAX_LIBTORRENT_RATE_LIMIT) def set_libtorrent_max_download_rate(self, value): """ @@ -423,7 +425,7 @@ def get_libtorrent_max_download_rate(self): :return: the maximum download rate in kB / s """ - return self.config['libtorrent'].as_int('max_download_rate') + return min(self.config['libtorrent'].as_int('max_download_rate'), MAX_LIBTORRENT_RATE_LIMIT) def set_libtorrent_dht_enabled(self, value): self.config['libtorrent']['dht'] = value diff --git a/src/tribler-core/tribler_core/restapi/tests/test_settings_endpoint.py b/src/tribler-core/tribler_core/restapi/tests/test_settings_endpoint.py index d7525b5f1f4..bd9b3b7b1c2 100644 --- a/src/tribler-core/tribler_core/restapi/tests/test_settings_endpoint.py +++ b/src/tribler-core/tribler_core/restapi/tests/test_settings_endpoint.py @@ -1,3 +1,5 @@ +from tribler_common.simpledefs import MAX_LIBTORRENT_RATE_LIMIT + from tribler_core.modules.libtorrent.download_config import DownloadConfig from tribler_core.restapi.base_api_test import AbstractApiTest from tribler_core.tests.tools.base_test import MockObject @@ -88,3 +90,26 @@ async def test_set_settings(self): self.assertEqual(self.session.config.get_seeding_mode(), 'ratio') self.assertEqual(self.session.config.get_seeding_ratio(), 3) self.assertEqual(self.session.config.get_seeding_time(), 123) + + @timeout(10) + async def test_set_rate_settings(self): + """ + Testing whether libtorrent rate limits works for large number without overflow error. + """ + + dcfg = DownloadConfig() + download = MockObject() + download.config = dcfg + self.session.dlmgr.get_downloads = lambda: [download] + + extra_rate = 1024 * 1024 * 1024 # 1GB/s + post_data = { + 'libtorrent': { + 'max_download_rate': MAX_LIBTORRENT_RATE_LIMIT + extra_rate, + 'max_upload_rate': MAX_LIBTORRENT_RATE_LIMIT + extra_rate + } + } + await self.do_request('settings', expected_code=200, request_type='POST', post_data=post_data) + + self.assertEqual(self.session.config.get_libtorrent_max_download_rate(), MAX_LIBTORRENT_RATE_LIMIT) + self.assertEqual(self.session.config.get_libtorrent_max_upload_rate(), MAX_LIBTORRENT_RATE_LIMIT) diff --git a/src/tribler-gui/tribler_gui/widgets/settingspage.py b/src/tribler-gui/tribler_gui/widgets/settingspage.py index 800c9b542b4..83f3ddc1d53 100644 --- a/src/tribler-gui/tribler_gui/widgets/settingspage.py +++ b/src/tribler-gui/tribler_gui/widgets/settingspage.py @@ -1,10 +1,10 @@ -import sys - from PIL.ImageQt import ImageQt from PyQt5 import QtCore, QtGui from PyQt5.QtWidgets import QFileDialog, QLabel, QSizePolicy, QWidget +from tribler_common.simpledefs import MAX_LIBTORRENT_RATE_LIMIT + import tribler_core.utilities.json_util as json from tribler_gui.defs import ( @@ -455,14 +455,14 @@ def save_settings(self): try: if self.window().upload_rate_limit_input.text(): - user_upload_rate_limit = int(self.window().upload_rate_limit_input.text()) * 1024 - if user_upload_rate_limit < sys.maxsize: + user_upload_rate_limit = int(float(self.window().upload_rate_limit_input.text()) * 1024) + if user_upload_rate_limit < MAX_LIBTORRENT_RATE_LIMIT: settings_data['libtorrent']['max_upload_rate'] = user_upload_rate_limit else: raise ValueError if self.window().download_rate_limit_input.text(): - user_download_rate_limit = int(self.window().download_rate_limit_input.text()) * 1024 - if user_download_rate_limit < sys.maxsize: + user_download_rate_limit = int(float(self.window().download_rate_limit_input.text()) * 1024) + if user_download_rate_limit < MAX_LIBTORRENT_RATE_LIMIT: settings_data['libtorrent']['max_download_rate'] = user_download_rate_limit else: raise ValueError @@ -470,8 +470,9 @@ def save_settings(self): ConfirmationDialog.show_error( self.window(), "Invalid value for bandwidth limit", - "You've entered an invalid value for the maximum upload/download rate. " - "Please enter a whole number (max: %d)" % (sys.maxsize / 1000), + "You've entered an invalid value for the maximum upload/download rate. \n" + "The rate is specified in KB/s and the value permitted is between 0 and %d KB/s.\n" + "Note that the decimal values are truncated." % (MAX_LIBTORRENT_RATE_LIMIT / 1024), ) return