Run multiple session save requests in parallel.

This commit is contained in:
Jari Sundell
2025-12-21 22:26:35 +01:00
committed by GitHub
parent 5dbb0020dc
commit 4bdeb58eb6
21 changed files with 404 additions and 317 deletions
+40 -14
View File
@@ -1,11 +1,15 @@
#ifndef RTORRENT_SESSION_SESSION_MANAGER_H
#define RTORRENT_SESSION_SESSION_MANAGER_H
#include <condition_variable>
#include <deque>
#include <future>
#include <list>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>
#include <torrent/common.h>
namespace core {
@@ -32,36 +36,48 @@ class SessionManager {
public:
typedef std::unique_ptr<std::stringstream> stream_ptr;
// TODO: This should depend on max open sockets / be configurable.
constexpr static int max_concurrent_saves = 16;
constexpr static int max_cleanup_saves = 64;
SessionManager(torrent::utils::Thread* thread);
~SessionManager();
bool is_used() const;
// TODO: Replace with protected `bool shutdown_if_done()`.
bool is_empty();
// bool is_empty_and_done();
void start();
std::string path() const;
void set_path(const std::string& path);
bool use_fsyncdisk() const;
void set_use_fsyncdisk(bool use_fsyncdisk);
bool use_lock() const;
void set_use_lock(bool use_lock);
void freeze_info();
void save_download(core::Download* download, std::string path, stream_ptr torrent_stream, stream_ptr rtorrent_stream, stream_ptr libtorrent_stream);
void remove_download(core::Download* download, std::string path);
void save_full_download(core::Download* download) { save_download(download, false); }
void save_resume_download(core::Download* download) { save_download(download, true); }
void remove_download(core::Download* download);
protected:
friend class Control;
friend class ThreadSession;
void save_download(core::Download* download, bool skip_static);
void start();
void cleanup();
private:
void process_save_request();
void process_next_save_request_unsafe();
void process_finished_saves();
void wait_for_one_save_unsafe(std::unique_lock<std::mutex>& lock);
// Requires a higher number of open sockets, and should only be used during shutdown.
void flush_all_and_wait_unsafe(std::unique_lock<std::mutex>& lock);
bool remove_save_request_unsafe(core::Download* download, std::unique_lock<std::mutex>& lock);
void save_download_unsafe(const SaveRequest& request);
bool save_download_stream_unsafe(const std::string& path, const std::unique_ptr<std::stringstream>& stream);
@@ -70,18 +86,28 @@ private:
bool m_freeze_info{};
std::string m_path;
bool m_use_fsyncdisk{true};
bool m_use_lock{true};
std::mutex m_mutex;
bool m_active{};
std::deque<SaveRequest> m_save_requests;
typedef std::pair<std::future<void>, SaveRequest> ProcessingSave;
// TODO: Add deque of DownloadStorers requests that have yet to build streams.
std::deque<SaveRequest> m_save_requests;
std::list<ProcessingSave> m_processing_saves;
std::condition_variable m_finished_condition;
std::vector<ProcessingSave> m_finished_saves;
std::unique_ptr<utils::Lockfile> m_lockfile;
};
inline bool SessionManager::is_used() const { return !m_path.empty(); }
inline std::string SessionManager::path() const { return m_path; }
inline bool SessionManager::use_lock() const { return m_use_lock; }
inline bool SessionManager::is_used() const { return !m_path.empty(); }
inline std::string SessionManager::path() const { return m_path; }
inline bool SessionManager::use_fsyncdisk() const { return true; }
inline bool SessionManager::use_lock() const { return m_use_lock; }
} // namespace session