From 60600d55d4334fddf51ecb00e87ff2d53f561eb1 Mon Sep 17 00:00:00 2001 From: stickz Date: Mon, 18 Dec 2023 06:35:54 -0500 Subject: [PATCH] rTorrent: Add tracker scrape feature Resolves a software stability issue on rTorrent with tens of thousands of trackers. Announces trackers by default at regular intervals instead of forcefully announcing everything at startup. --- Dockerfile | 1 + README.md | 10 +++ patches/rtorrent/rtorrent-scrape.patch | 91 ++++++++++++++++++++++++++ rootfs/etc/cont-init.d/03-config.sh | 1 + rootfs/tpls/etc/rtorrent/.rtlocal.rc | 3 + 5 files changed, 106 insertions(+) create mode 100644 patches/rtorrent/rtorrent-scrape.patch diff --git a/Dockerfile b/Dockerfile index 710c2b49..6e6eadc4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -156,6 +156,7 @@ WORKDIR /usr/local/src/rtorrent COPY --from=src-rtorrent /src . COPY /patches/rtorrent . RUN patch -p1 < lockfile-fix.patch \ + && patch -p1 < rtorrent-scrape.patch \ && patch -p1 < scgi-fix.patch \ && patch -p1 < session-file-fix.patch \ && patch -p1 < xmlrpc-fix.patch \ diff --git a/README.md b/README.md index 7c6d6aec..f2d3bbe4 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ ___ * [mktorrent](https://github.com/Rudde/mktorrent) installed for ruTorrent create plugin * [Traefik](https://github.com/containous/traefik-library-image) Docker image as reverse proxy and creation/renewal of Let's Encrypt certificates (see [this template](examples/traefik)) * [geoip-updater](https://github.com/crazy-max/geoip-updater) Docker image to download MaxMind's GeoIP2 databases on a time-based schedule for geolocation +* [rTorrent Patches](https://github.com/crazy-max/docker-rtorrent-rutorrent/tree/master/patches/rtorrent) Extended support for rTorrent to increase software stability. ## Build locally @@ -132,6 +133,7 @@ Image: crazymax/rtorrent-rutorrent:latest * `RT_LOG_EXECUTE`: Log executed commands to `/data/rtorrent/log/execute.log` (default `false`) * `RT_LOG_XMLRPC`: Log XMLRPC queries to `/data/rtorrent/log/xmlrpc.log` (default `false`) * `RT_SESSION_SAVE_SECONDS`: Seconds between writing torrent information to disk (default `3600`) +* `RT_TRACKER_DELAY_SCRAPE`: Delay tracker announces at startup (default `true`) * `RT_DHT_PORT`: DHT UDP port (`dht.port.set`, default `6881`) * `RT_INC_PORT`: Incoming connections (`network.port_range.set`, default `50000`) @@ -342,6 +344,14 @@ Only torrent statistics are lost during a crash. (Ratio, Total Uploaded & Downlo Higher values will reduce disk usage, at the cost of minor stat loss during a crash. Consider increasing to 10800 seconds (3 hours) if running thousands of torrents. +### rTorrent tracker scrape patch + +`RT_TRACKER_DELAY_SCRAPE` specifies whether to delay tracker announces at rTorrent startup. +The default value is `true`. There are two main benefits to keeping this feature enabled: + +1) Software Stability: rTorrent will not crash or time-out with tens of thousands of trackers. +2) Immediate Access: ruTorrent can be accessed immediately after rTorrent is started. + ## Upgrade To upgrade, pull the newer image and launch the container: diff --git a/patches/rtorrent/rtorrent-scrape.patch b/patches/rtorrent/rtorrent-scrape.patch new file mode 100644 index 00000000..cfaa6d1a --- /dev/null +++ b/patches/rtorrent/rtorrent-scrape.patch @@ -0,0 +1,91 @@ +From b68c3b5f8d15a91955f90c1bdd24a0708a2fed2e Mon Sep 17 00:00:00 2001 +From: stickz +Date: Mon, 17 Apr 2023 19:08:21 -0400 +Subject: [PATCH] Disable forced tracker startup scrape + +--- + src/command_tracker.cc | 1 + + src/core/download_factory.cc | 7 ++++++- + src/core/download_factory.h | 4 ++++ + src/main.cc | 2 ++ + 4 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/command_tracker.cc b/src/command_tracker.cc +index 30c56eec7..e06947610 100644 +--- a/src/command_tracker.cc ++++ b/src/command_tracker.cc +@@ -159,6 +159,7 @@ initialize_command_tracker() { + CMD2_ANY_VALUE ("trackers.disable", std::bind(&apply_enable_trackers, int64_t(0))); + CMD2_VAR_VALUE ("trackers.numwant", -1); + CMD2_VAR_BOOL ("trackers.use_udp", true); ++ CMD2_VAR_BOOL ("trackers.delay_scrape", true); + + CMD2_ANY_STRING_V ("dht.mode.set", std::bind(&core::DhtManager::set_mode, control->dht_manager(), std::placeholders::_2)); + CMD2_VAR_VALUE ("dht.port", int64_t(6881)); +diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc +index b1bdd64b9..2d2ea5a3b 100644 +--- a/src/core/download_factory.cc ++++ b/src/core/download_factory.cc +@@ -105,7 +105,8 @@ DownloadFactory::DownloadFactory(Manager* m) : + m_session(false), + m_start(false), + m_printLog(true), +- m_isFile(false) { ++ m_isFile(false), ++ m_initLoad(false) { + + m_taskLoad.slot() = std::bind(&DownloadFactory::receive_load, this); + m_taskCommit.slot() = std::bind(&DownloadFactory::receive_commit, this); +@@ -274,6 +275,10 @@ DownloadFactory::receive_success() { + + if (!rpc::call_command_value("trackers.use_udp")) + download->enable_udp_trackers(false); ++ ++ // Skip forcing trackers to scrape when rtorrent starts ++ if (m_initLoad && rpc::call_command_value("trackers.delay_scrape")) ++ download->set_resume_flags(torrent::Download::start_skip_tracker); + + // Check first if we already have these values set in the session + // torrent, so that it is safe to change the values. +diff --git a/src/core/download_factory.h b/src/core/download_factory.h +index 01695e882..29fa9760b 100644 +--- a/src/core/download_factory.h ++++ b/src/core/download_factory.h +@@ -76,6 +76,9 @@ class DownloadFactory { + + bool get_start() const { return m_start; } + void set_start(bool v) { m_start = v; } ++ ++ bool get_init_load() const { return m_initLoad; } ++ void set_init_load(bool v) { m_initLoad = v; } + + bool print_log() const { return m_printLog; } + void set_print_log(bool v) { m_printLog = v; } +@@ -105,6 +108,7 @@ class DownloadFactory { + bool m_start; + bool m_printLog; + bool m_isFile; ++ bool m_initLoad; + + command_list_type m_commands; + torrent::Object::map_type m_variables; +diff --git a/src/main.cc b/src/main.cc +index 6be6a4dee..c76558f8f 100644 +--- a/src/main.cc ++++ b/src/main.cc +@@ -132,6 +132,7 @@ load_session_torrents() { + + // Replace with session torrent flag. + f->set_session(true); ++ f->set_init_load(true); + f->slot_finished(std::bind(&rak::call_delete_func, f)); + f->load(entries.path() + first->d_name); + f->commit(); +@@ -146,6 +147,7 @@ load_arg_torrents(char** first, char** last) { + + // Replace with session torrent flag. + f->set_start(true); ++ f->set_init_load(true); + f->slot_finished(std::bind(&rak::call_delete_func, f)); + f->load(*first); + f->commit(); diff --git a/rootfs/etc/cont-init.d/03-config.sh b/rootfs/etc/cont-init.d/03-config.sh index 7047afac..58affa72 100644 --- a/rootfs/etc/cont-init.d/03-config.sh +++ b/rootfs/etc/cont-init.d/03-config.sh @@ -25,6 +25,7 @@ RT_LOG_LEVEL=${RT_LOG_LEVEL:-info} RT_LOG_EXECUTE=${RT_LOG_EXECUTE:-false} RT_LOG_XMLRPC=${RT_LOG_XMLRPC:-false} RT_SESSION_SAVE_SECONDS=${RT_SESSION_SAVE_SECONDS:-3600} +RT_TRACKER_DELAY_SCRAPE=${RT_TRACKER_DELAY_SCRAPE:-true} RU_REMOVE_CORE_PLUGINS=${RU_REMOVE_CORE_PLUGINS:-httprpc} RU_HTTP_USER_AGENT=${RU_HTTP_USER_AGENT:-Mozilla/5.0 (Windows NT 6.0; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0} diff --git a/rootfs/tpls/etc/rtorrent/.rtlocal.rc b/rootfs/tpls/etc/rtorrent/.rtlocal.rc index 8496d2e4..49be284d 100644 --- a/rootfs/tpls/etc/rtorrent/.rtlocal.rc +++ b/rootfs/tpls/etc/rtorrent/.rtlocal.rc @@ -43,6 +43,9 @@ schedule2 = session_save, 1200, @RT_SESSION_SAVE_SECONDS@, ((session.save)) # Save torrents immediately to prevent losing them between session saving intervals method.set_key = event.download.inserted, 2_save_session, ((d.save_full_session)) +# Configure whether to delay tracker announces at startup +trackers.delay_scrape = @RT_TRACKER_DELAY_SCRAPE@ + # Logging ## levels = critical error warn notice info debug ## groups = connection_* dht_* peer_* rpc_* storage_* thread_* tracker_* torrent_*