mirror of
https://github.com/transmission/transmission.git
synced 2026-05-08 09:39:08 +01:00
refactor: tr_stats (#3542)
This commit is contained in:
+4
-5
@@ -581,18 +581,17 @@ MainWindow::Impl::Impl(MainWindow& window, Glib::RefPtr<Gio::ActionGroup> const&
|
||||
void MainWindow::Impl::updateStats()
|
||||
{
|
||||
Glib::ustring buf;
|
||||
tr_session_stats stats;
|
||||
auto const* const session = core_->get_session();
|
||||
|
||||
/* update the stats */
|
||||
if (auto const pch = gtr_pref_string_get(TR_KEY_statusbar_stats); pch == "session-ratio")
|
||||
{
|
||||
tr_sessionGetStats(session, &stats);
|
||||
auto const stats = tr_sessionGetStats(session);
|
||||
buf = fmt::format(_("Ratio: {ratio}"), fmt::arg("ratio", tr_strlratio(stats.ratio)));
|
||||
}
|
||||
else if (pch == "session-transfer")
|
||||
{
|
||||
tr_sessionGetStats(session, &stats);
|
||||
auto const stats = tr_sessionGetStats(session);
|
||||
buf = fmt::format(
|
||||
C_("current session totals", "Down: {downloaded_size}, Up: {uploaded_size}"),
|
||||
fmt::arg("downloaded_size", tr_strlsize(stats.downloadedBytes)),
|
||||
@@ -600,7 +599,7 @@ void MainWindow::Impl::updateStats()
|
||||
}
|
||||
else if (pch == "total-transfer")
|
||||
{
|
||||
tr_sessionGetCumulativeStats(session, &stats);
|
||||
auto const stats = tr_sessionGetCumulativeStats(session);
|
||||
buf = fmt::format(
|
||||
C_("all-time totals", "Down: {downloaded_size}, Up: {uploaded_size}"),
|
||||
fmt::arg("downloaded_size", tr_strlsize(stats.downloadedBytes)),
|
||||
@@ -608,7 +607,7 @@ void MainWindow::Impl::updateStats()
|
||||
}
|
||||
else /* default is total-ratio */
|
||||
{
|
||||
tr_sessionGetCumulativeStats(session, &stats);
|
||||
auto const stats = tr_sessionGetCumulativeStats(session);
|
||||
buf = fmt::format(_("Ratio: {ratio}"), fmt::arg("ratio", tr_strlratio(stats.ratio)));
|
||||
}
|
||||
|
||||
|
||||
+11
-15
@@ -71,22 +71,18 @@ auto startedTimesText(uint64_t n)
|
||||
|
||||
bool StatsDialog::Impl::updateStats()
|
||||
{
|
||||
tr_session_stats one;
|
||||
tr_session_stats all;
|
||||
auto stats = tr_sessionGetStats(core_->get_session());
|
||||
setLabel(one_up_lb_, tr_strlsize(stats.uploadedBytes));
|
||||
setLabel(one_down_lb_, tr_strlsize(stats.downloadedBytes));
|
||||
setLabel(one_time_lb_, tr_format_time(stats.secondsActive));
|
||||
setLabelFromRatio(one_ratio_lb_, stats.ratio);
|
||||
|
||||
tr_sessionGetStats(core_->get_session(), &one);
|
||||
tr_sessionGetCumulativeStats(core_->get_session(), &all);
|
||||
|
||||
setLabel(one_up_lb_, tr_strlsize(one.uploadedBytes));
|
||||
setLabel(one_down_lb_, tr_strlsize(one.downloadedBytes));
|
||||
setLabel(one_time_lb_, tr_format_time(one.secondsActive));
|
||||
setLabelFromRatio(one_ratio_lb_, one.ratio);
|
||||
|
||||
setLabel(all_sessions_lb_, startedTimesText(all.sessionCount));
|
||||
setLabel(all_up_lb_, tr_strlsize(all.uploadedBytes));
|
||||
setLabel(all_down_lb_, tr_strlsize(all.downloadedBytes));
|
||||
setLabel(all_time_lb_, tr_format_time(all.secondsActive));
|
||||
setLabelFromRatio(all_ratio_lb_, all.ratio);
|
||||
stats = tr_sessionGetCumulativeStats(core_->get_session());
|
||||
setLabel(all_sessions_lb_, startedTimesText(stats.sessionCount));
|
||||
setLabel(all_up_lb_, tr_strlsize(stats.uploadedBytes));
|
||||
setLabel(all_down_lb_, tr_strlsize(stats.downloadedBytes));
|
||||
setLabel(all_time_lb_, tr_format_time(stats.secondsActive));
|
||||
setLabelFromRatio(all_ratio_lb_, stats.ratio);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "file.h"
|
||||
#include "inout.h"
|
||||
#include "log.h"
|
||||
#include "stats.h" /* tr_statsFileCreated() */
|
||||
#include "torrent.h"
|
||||
#include "tr-assert.h"
|
||||
#include "utils.h"
|
||||
@@ -136,7 +135,7 @@ int readOrWriteBytes(
|
||||
if (fd && do_write)
|
||||
{
|
||||
// make a note that we just created a file
|
||||
tr_statsFileCreated(tor->session);
|
||||
tor->session->addFileCreated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "peer-mgr.h"
|
||||
#include "peer-msgs.h"
|
||||
#include "session.h"
|
||||
#include "stats.h" /* tr_statsAddUploaded, tr_statsAddDownloaded */
|
||||
#include "torrent.h"
|
||||
#include "tr-assert.h"
|
||||
#include "tr-dht.h"
|
||||
@@ -997,7 +996,7 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
|
||||
tr_announcerAddBytes(tor, TR_ANN_UP, e->length);
|
||||
tor->setDateActive(now);
|
||||
tor->setDirty();
|
||||
tr_statsAddUploaded(tor->session, e->length);
|
||||
tor->session->addUploaded(e->length);
|
||||
|
||||
if (peer->atom != nullptr)
|
||||
{
|
||||
@@ -1015,8 +1014,7 @@ static void peerCallbackFunc(tr_peer* peer, tr_peer_event const* e, void* vs)
|
||||
tor->downloadedCur += e->length;
|
||||
tor->setDateActive(now);
|
||||
tor->setDirty();
|
||||
|
||||
tr_statsAddDownloaded(tor->session, e->length);
|
||||
tor->session->addDownloaded(e->length);
|
||||
|
||||
if (peer->atom != nullptr)
|
||||
{
|
||||
|
||||
+12
-17
@@ -31,7 +31,6 @@
|
||||
#include "rpcimpl.h"
|
||||
#include "session-id.h"
|
||||
#include "session.h"
|
||||
#include "stats.h"
|
||||
#include "torrent.h"
|
||||
#include "tr-assert.h"
|
||||
#include "tr-macros.h"
|
||||
@@ -2067,9 +2066,6 @@ static char const* sessionStats(
|
||||
tr_variant* args_out,
|
||||
tr_rpc_idle_data* /*idle_data*/)
|
||||
{
|
||||
auto currentStats = tr_session_stats{};
|
||||
auto cumulativeStats = tr_session_stats{};
|
||||
|
||||
auto const& torrents = session->torrents();
|
||||
auto const total = std::size(torrents);
|
||||
auto const running = std::count_if(
|
||||
@@ -2077,28 +2073,27 @@ static char const* sessionStats(
|
||||
std::end(torrents),
|
||||
[](auto const* tor) { return tor->isRunning; });
|
||||
|
||||
tr_sessionGetStats(session, ¤tStats);
|
||||
tr_sessionGetCumulativeStats(session, &cumulativeStats);
|
||||
|
||||
tr_variantDictAddInt(args_out, TR_KEY_activeTorrentCount, running);
|
||||
tr_variantDictAddReal(args_out, TR_KEY_downloadSpeed, tr_sessionGetPieceSpeed_Bps(session, TR_DOWN));
|
||||
tr_variantDictAddInt(args_out, TR_KEY_pausedTorrentCount, total - running);
|
||||
tr_variantDictAddInt(args_out, TR_KEY_torrentCount, total);
|
||||
tr_variantDictAddReal(args_out, TR_KEY_uploadSpeed, tr_sessionGetPieceSpeed_Bps(session, TR_UP));
|
||||
|
||||
auto stats = session->stats().cumulative();
|
||||
tr_variant* d = tr_variantDictAddDict(args_out, TR_KEY_cumulative_stats, 5);
|
||||
tr_variantDictAddInt(d, TR_KEY_downloadedBytes, cumulativeStats.downloadedBytes);
|
||||
tr_variantDictAddInt(d, TR_KEY_filesAdded, cumulativeStats.filesAdded);
|
||||
tr_variantDictAddInt(d, TR_KEY_secondsActive, cumulativeStats.secondsActive);
|
||||
tr_variantDictAddInt(d, TR_KEY_sessionCount, cumulativeStats.sessionCount);
|
||||
tr_variantDictAddInt(d, TR_KEY_uploadedBytes, cumulativeStats.uploadedBytes);
|
||||
tr_variantDictAddInt(d, TR_KEY_downloadedBytes, stats.downloadedBytes);
|
||||
tr_variantDictAddInt(d, TR_KEY_filesAdded, stats.filesAdded);
|
||||
tr_variantDictAddInt(d, TR_KEY_secondsActive, stats.secondsActive);
|
||||
tr_variantDictAddInt(d, TR_KEY_sessionCount, stats.sessionCount);
|
||||
tr_variantDictAddInt(d, TR_KEY_uploadedBytes, stats.uploadedBytes);
|
||||
|
||||
stats = session->stats().current();
|
||||
d = tr_variantDictAddDict(args_out, TR_KEY_current_stats, 5);
|
||||
tr_variantDictAddInt(d, TR_KEY_downloadedBytes, currentStats.downloadedBytes);
|
||||
tr_variantDictAddInt(d, TR_KEY_filesAdded, currentStats.filesAdded);
|
||||
tr_variantDictAddInt(d, TR_KEY_secondsActive, currentStats.secondsActive);
|
||||
tr_variantDictAddInt(d, TR_KEY_sessionCount, currentStats.sessionCount);
|
||||
tr_variantDictAddInt(d, TR_KEY_uploadedBytes, currentStats.uploadedBytes);
|
||||
tr_variantDictAddInt(d, TR_KEY_downloadedBytes, stats.downloadedBytes);
|
||||
tr_variantDictAddInt(d, TR_KEY_filesAdded, stats.filesAdded);
|
||||
tr_variantDictAddInt(d, TR_KEY_secondsActive, stats.secondsActive);
|
||||
tr_variantDictAddInt(d, TR_KEY_sessionCount, stats.sessionCount);
|
||||
tr_variantDictAddInt(d, TR_KEY_uploadedBytes, stats.uploadedBytes);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+51
-23
@@ -50,7 +50,6 @@
|
||||
#include "rpc-server.h"
|
||||
#include "session-id.h"
|
||||
#include "session.h"
|
||||
#include "stats.h"
|
||||
#include "torrent.h"
|
||||
#include "tr-assert.h"
|
||||
#include "tr-dht.h" /* tr_dhtUpkeep() */
|
||||
@@ -586,7 +585,7 @@ static void onSaveTimer(evutil_socket_t /*fd*/, short /*what*/, void* vsession)
|
||||
tr_torrentSave(tor);
|
||||
}
|
||||
|
||||
tr_statsSaveDirty(session);
|
||||
session->stats().saveIfDirty();
|
||||
|
||||
tr_timerAdd(*session->saveTimer, SaveIntervalSecs, 0);
|
||||
}
|
||||
@@ -613,7 +612,7 @@ tr_session* tr_sessionInit(char const* config_dir, bool messageQueuingEnabled, t
|
||||
tr_timeUpdate(time(nullptr));
|
||||
|
||||
/* initialize the bare skeleton of the session object */
|
||||
auto* session = new tr_session{};
|
||||
auto* const session = new tr_session{ config_dir };
|
||||
session->udp_socket = TR_BAD_SOCKET;
|
||||
session->udp6_socket = TR_BAD_SOCKET;
|
||||
session->cache = std::make_unique<Cache>(session->torrents(), 1024 * 1024 * 2);
|
||||
@@ -739,8 +738,6 @@ static void tr_sessionInitImpl(init_data* data)
|
||||
|
||||
tr_logSetQueueEnabled(data->messageQueuingEnabled);
|
||||
|
||||
session->initConfigDir(data->config_dir);
|
||||
|
||||
session->peerMgr = tr_peerMgrNew(session);
|
||||
|
||||
session->shared = tr_sharedInit(session);
|
||||
@@ -761,8 +758,6 @@ static void tr_sessionInitImpl(init_data* data)
|
||||
|
||||
tr_logAddInfo(fmt::format(_("Transmission version {version} starting"), fmt::arg("version", LONG_VERSION_STRING)));
|
||||
|
||||
tr_statsInit(session);
|
||||
|
||||
tr_sessionSet(session, &settings);
|
||||
|
||||
tr_udpInit(session);
|
||||
@@ -1957,7 +1952,8 @@ static void sessionCloseImplFinish(tr_session* session)
|
||||
tr_tracker_udp_close(session);
|
||||
tr_udpUninit(session);
|
||||
|
||||
tr_statsClose(session);
|
||||
session->stats().saveIfDirty();
|
||||
|
||||
tr_peerMgrFree(session->peerMgr);
|
||||
|
||||
tr_utpClose(session);
|
||||
@@ -2994,20 +2990,52 @@ void tr_sessionSetCompletenessCallback(tr_session* session, tr_torrent_completen
|
||||
session->setTorrentCompletenessCallback(cb, user_data);
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
void tr_session::initConfigDir(std::string_view config_dir)
|
||||
tr_session_stats tr_sessionGetStats(tr_session const* session)
|
||||
{
|
||||
return session->stats().current();
|
||||
}
|
||||
|
||||
tr_session_stats tr_sessionGetCumulativeStats(tr_session const* session)
|
||||
{
|
||||
return session->stats().cumulative();
|
||||
}
|
||||
|
||||
void tr_sessionClearStats(tr_session* session)
|
||||
{
|
||||
session->stats().clear();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
auto makeResumeDir(std::string_view config_dir)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
auto dir = fmt::format("{:s}/Resume"sv, config_dir);
|
||||
#else
|
||||
auto dir = fmt::format("{:s}/resume"sv, config_dir);
|
||||
#endif
|
||||
tr_sys_dir_create(dir.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777);
|
||||
return dir;
|
||||
}
|
||||
|
||||
auto makeTorrentDir(std::string_view config_dir)
|
||||
{
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
auto dir = fmt::format("{:s}/Torrents"sv, config_dir);
|
||||
#else
|
||||
auto dir = fmt::format("{:s}/torrents"sv, config_dir);
|
||||
#endif
|
||||
tr_sys_dir_create(dir.c_str(), TR_SYS_DIR_CREATE_PARENTS, 0777);
|
||||
return dir;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
tr_session::tr_session(std::string_view config_dir)
|
||||
: config_dir_{ config_dir }
|
||||
, resume_dir_{ makeResumeDir(config_dir) }
|
||||
, torrent_dir_{ makeTorrentDir(config_dir) }
|
||||
, session_stats_{ config_dir, time(nullptr) }
|
||||
{
|
||||
TR_ASSERT(std::empty(config_dir_));
|
||||
config_dir_ = config_dir;
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
resume_dir_ = fmt::format("{:s}/Resume"sv, config_dir);
|
||||
torrent_dir_ = fmt::format("{:s}/Torrents"sv, config_dir);
|
||||
#else
|
||||
resume_dir_ = fmt::format("{:s}/resume"sv, config_dir);
|
||||
torrent_dir_ = fmt::format("{:s}/torrents"sv, config_dir);
|
||||
#endif
|
||||
tr_sys_dir_create(resume_dir_, TR_SYS_DIR_CREATE_PARENTS, 0777);
|
||||
tr_sys_dir_create(torrent_dir_, TR_SYS_DIR_CREATE_PARENTS, 0777);
|
||||
}
|
||||
|
||||
+54
-26
@@ -32,6 +32,7 @@
|
||||
#include "net.h" // tr_socket_t
|
||||
#include "open-files.h"
|
||||
#include "quark.h"
|
||||
#include "stats.h"
|
||||
#include "torrents.h"
|
||||
#include "web.h"
|
||||
|
||||
@@ -69,32 +70,32 @@ struct tr_bindinfo
|
||||
struct tr_turtle_info
|
||||
{
|
||||
/* TR_UP and TR_DOWN speed limits */
|
||||
unsigned int speedLimit_Bps[2];
|
||||
unsigned int speedLimit_Bps[2] = {};
|
||||
|
||||
/* is turtle mode on right now? */
|
||||
bool isEnabled;
|
||||
bool isEnabled = false;
|
||||
|
||||
/* does turtle mode turn itself on and off at given times? */
|
||||
bool isClockEnabled;
|
||||
bool isClockEnabled = false;
|
||||
|
||||
/* when clock mode is on, minutes after midnight to turn on turtle mode */
|
||||
int beginMinute;
|
||||
int beginMinute = 0;
|
||||
|
||||
/* when clock mode is on, minutes after midnight to turn off turtle mode */
|
||||
int endMinute;
|
||||
int endMinute = 0;
|
||||
|
||||
/* only use clock mode on these days of the week */
|
||||
tr_sched_day days;
|
||||
tr_sched_day days = {};
|
||||
|
||||
/* called when isEnabled changes */
|
||||
tr_altSpeedFunc callback;
|
||||
tr_altSpeedFunc callback = nullptr;
|
||||
|
||||
/* the callback's user_data argument */
|
||||
void* callbackUserData;
|
||||
void* callbackUserData = nullptr;
|
||||
|
||||
/* the callback's changedByUser argument.
|
||||
* indicates whether the change came from the user or from the clock. */
|
||||
bool changedByUser;
|
||||
bool changedByUser = false;
|
||||
|
||||
/* bitfield of all the minutes in a week.
|
||||
* Each bit's value indicates whether the scheduler wants turtle
|
||||
@@ -104,13 +105,15 @@ struct tr_turtle_info
|
||||
tr_bitfield* minutes = nullptr;
|
||||
|
||||
/* recent action that was done by turtle's automatic switch */
|
||||
tr_auto_switch_state_t autoTurtleState;
|
||||
tr_auto_switch_state_t autoTurtleState = TR_AUTO_SWITCH_UNUSED;
|
||||
};
|
||||
|
||||
/** @brief handle to an active libtransmission session */
|
||||
struct tr_session
|
||||
{
|
||||
public:
|
||||
tr_session(std::string_view config_dir);
|
||||
|
||||
[[nodiscard]] constexpr auto& torrents()
|
||||
{
|
||||
return torrents_;
|
||||
@@ -133,8 +136,6 @@ public:
|
||||
|
||||
// paths
|
||||
|
||||
void initConfigDir(std::string_view config_dir);
|
||||
|
||||
[[nodiscard]] constexpr auto const& configDir() const noexcept
|
||||
{
|
||||
return config_dir_;
|
||||
@@ -402,6 +403,33 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// stats
|
||||
|
||||
[[nodiscard]] auto& stats() noexcept
|
||||
{
|
||||
return session_stats_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto const& stats() const noexcept
|
||||
{
|
||||
return session_stats_;
|
||||
}
|
||||
|
||||
void addUploaded(uint32_t n_bytes) noexcept
|
||||
{
|
||||
session_stats_.addUploaded(n_bytes);
|
||||
}
|
||||
|
||||
void addDownloaded(uint32_t n_bytes) noexcept
|
||||
{
|
||||
session_stats_.addDownloaded(n_bytes);
|
||||
}
|
||||
|
||||
void addFileCreated() noexcept
|
||||
{
|
||||
session_stats_.addFileCreated();
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr std::array<std::tuple<tr_quark, tr_quark, TrScript>, 3> Scripts{
|
||||
{ { TR_KEY_script_torrent_added_enabled, TR_KEY_script_torrent_added_filename, TR_SCRIPT_ON_TORRENT_ADDED },
|
||||
@@ -521,18 +549,16 @@ public:
|
||||
WebMediator web_mediator{ this };
|
||||
std::unique_ptr<tr_web> web;
|
||||
|
||||
struct tr_session_id* session_id;
|
||||
struct tr_session_id* session_id = nullptr;
|
||||
|
||||
tr_rpc_func rpc_func;
|
||||
void* rpc_func_user_data;
|
||||
tr_rpc_func rpc_func = nullptr;
|
||||
void* rpc_func_user_data = nullptr;
|
||||
|
||||
struct tr_stats_handle* sessionStats;
|
||||
struct tr_announcer* announcer = nullptr;
|
||||
struct tr_announcer_udp* announcer_udp = nullptr;
|
||||
|
||||
struct tr_announcer* announcer;
|
||||
struct tr_announcer_udp* announcer_udp;
|
||||
|
||||
struct event* nowTimer;
|
||||
struct event* saveTimer;
|
||||
struct event* nowTimer = nullptr;
|
||||
struct event* saveTimer = nullptr;
|
||||
|
||||
// monitors the "global pool" speeds
|
||||
tr_bandwidth top_bandwidth_;
|
||||
@@ -543,8 +569,8 @@ public:
|
||||
|
||||
uint16_t idleLimitMinutes;
|
||||
|
||||
struct tr_bindinfo* bind_ipv4;
|
||||
struct tr_bindinfo* bind_ipv6;
|
||||
struct tr_bindinfo* bind_ipv4 = nullptr;
|
||||
struct tr_bindinfo* bind_ipv6 = nullptr;
|
||||
|
||||
std::unique_ptr<tr_rpc_server> rpc_server_;
|
||||
|
||||
@@ -562,16 +588,18 @@ private:
|
||||
|
||||
std::array<std::string, TR_SCRIPT_N_TYPES> scripts_;
|
||||
|
||||
std::string config_dir_;
|
||||
std::string const config_dir_;
|
||||
std::string const resume_dir_;
|
||||
std::string const torrent_dir_;
|
||||
std::string download_dir_;
|
||||
std::string incomplete_dir_;
|
||||
std::string resume_dir_;
|
||||
std::string torrent_dir_;
|
||||
|
||||
std::string blocklist_url_;
|
||||
std::string default_trackers_str_;
|
||||
std::string peer_congestion_algorithm_;
|
||||
|
||||
tr_stats session_stats_;
|
||||
|
||||
std::optional<tr_address> external_ip_;
|
||||
|
||||
queue_start_callback_t queue_start_callback_ = nullptr;
|
||||
|
||||
+32
-166
@@ -1,47 +1,30 @@
|
||||
// This file Copyright © 2007-2022 Mnemosyne LLC.
|
||||
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
||||
// This file Copyright 2007-2022 Mnemosyne LLC.
|
||||
// It may be used under GPLv2 (SPDX: GPL-2.0), GPLv3 (SPDX: GPL-3.0),
|
||||
// or any future license endorsed by Mnemosyne LLC.
|
||||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
#include "transmission.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "session.h"
|
||||
#include "stats.h"
|
||||
#include "tr-strbuf.h"
|
||||
#include "utils.h"
|
||||
#include "utils.h" // for tr_getRatio(), tr_time()
|
||||
#include "variant.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
/** @brief Opaque, per-session data structure for bandwidth use statistics */
|
||||
struct tr_stats_handle
|
||||
tr_session_stats tr_stats::loadOldStats(std::string_view config_dir)
|
||||
{
|
||||
tr_session_stats single;
|
||||
tr_session_stats old;
|
||||
time_t startTime;
|
||||
bool isDirty;
|
||||
};
|
||||
auto ret = tr_session_stats{};
|
||||
|
||||
static void loadCumulativeStats(tr_session const* session, tr_session_stats* setme)
|
||||
{
|
||||
auto top = tr_variant{};
|
||||
|
||||
auto filename = tr_pathbuf{ session->configDir(), "/stats.json"sv };
|
||||
auto filename = tr_pathbuf{ config_dir, "/stats.json"sv };
|
||||
bool loaded = tr_variantFromFile(&top, TR_VARIANT_PARSE_JSON, filename.sv(), nullptr);
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
// maybe the user just upgraded from an old version of Transmission
|
||||
// that was still using stats.benc
|
||||
filename.assign(session->configDir(), "/stats.benc");
|
||||
filename.assign(config_dir, "/stats.benc");
|
||||
loaded = tr_variantFromFile(&top, TR_VARIANT_PARSE_BENC, filename.sv(), nullptr);
|
||||
}
|
||||
|
||||
@@ -51,178 +34,61 @@ static void loadCumulativeStats(tr_session const* session, tr_session_stats* set
|
||||
|
||||
if (tr_variantDictFindInt(&top, TR_KEY_downloaded_bytes, &i))
|
||||
{
|
||||
setme->downloadedBytes = (uint64_t)i;
|
||||
ret.downloadedBytes = (uint64_t)i;
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(&top, TR_KEY_files_added, &i))
|
||||
{
|
||||
setme->filesAdded = (uint64_t)i;
|
||||
ret.filesAdded = (uint64_t)i;
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(&top, TR_KEY_seconds_active, &i))
|
||||
{
|
||||
setme->secondsActive = (uint64_t)i;
|
||||
ret.secondsActive = (uint64_t)i;
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(&top, TR_KEY_session_count, &i))
|
||||
{
|
||||
setme->sessionCount = (uint64_t)i;
|
||||
ret.sessionCount = (uint64_t)i;
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(&top, TR_KEY_uploaded_bytes, &i))
|
||||
{
|
||||
setme->uploadedBytes = (uint64_t)i;
|
||||
ret.uploadedBytes = (uint64_t)i;
|
||||
}
|
||||
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void saveCumulativeStats(tr_session const* session, tr_session_stats const* s)
|
||||
void tr_stats::save() const
|
||||
{
|
||||
auto const filename = tr_pathbuf{ session->configDir(), "/stats.json"sv };
|
||||
auto const saveme = cumulative();
|
||||
auto const filename = tr_pathbuf{ config_dir_, "/stats.json"sv };
|
||||
auto top = tr_variant{};
|
||||
tr_variantInitDict(&top, 5);
|
||||
tr_variantDictAddInt(&top, TR_KEY_downloaded_bytes, s->downloadedBytes);
|
||||
tr_variantDictAddInt(&top, TR_KEY_files_added, s->filesAdded);
|
||||
tr_variantDictAddInt(&top, TR_KEY_seconds_active, s->secondsActive);
|
||||
tr_variantDictAddInt(&top, TR_KEY_session_count, s->sessionCount);
|
||||
tr_variantDictAddInt(&top, TR_KEY_uploaded_bytes, s->uploadedBytes);
|
||||
tr_variantToFile(&top, TR_VARIANT_FMT_JSON, filename.sv());
|
||||
tr_variantDictAddInt(&top, TR_KEY_downloaded_bytes, saveme.downloadedBytes);
|
||||
tr_variantDictAddInt(&top, TR_KEY_files_added, saveme.filesAdded);
|
||||
tr_variantDictAddInt(&top, TR_KEY_seconds_active, saveme.secondsActive);
|
||||
tr_variantDictAddInt(&top, TR_KEY_session_count, saveme.sessionCount);
|
||||
tr_variantDictAddInt(&top, TR_KEY_uploaded_bytes, saveme.uploadedBytes);
|
||||
tr_variantToFile(&top, TR_VARIANT_FMT_JSON, filename);
|
||||
tr_variantFree(&top);
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
void tr_statsInit(tr_session* session)
|
||||
void tr_stats::clear()
|
||||
{
|
||||
auto* const stats = tr_new0(struct tr_stats_handle, 1);
|
||||
|
||||
loadCumulativeStats(session, &stats->old);
|
||||
stats->single.sessionCount = 1;
|
||||
stats->startTime = tr_time();
|
||||
session->sessionStats = stats;
|
||||
single_ = old_ = Zero;
|
||||
is_dirty_ = true;
|
||||
start_time_ = tr_time();
|
||||
}
|
||||
|
||||
static tr_stats_handle* getStats(tr_session const* session)
|
||||
[[nodiscard]] tr_session_stats tr_stats::current() const
|
||||
{
|
||||
return session != nullptr ? session->sessionStats : nullptr;
|
||||
}
|
||||
|
||||
void tr_statsSaveDirty(tr_session* session)
|
||||
{
|
||||
auto* const h = getStats(session);
|
||||
|
||||
if (h != nullptr && h->isDirty)
|
||||
{
|
||||
auto cumulative = tr_session_stats{};
|
||||
tr_sessionGetCumulativeStats(session, &cumulative);
|
||||
saveCumulativeStats(session, &cumulative);
|
||||
h->isDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void tr_statsClose(tr_session* session)
|
||||
{
|
||||
tr_statsSaveDirty(session);
|
||||
|
||||
tr_free(session->sessionStats);
|
||||
session->sessionStats = nullptr;
|
||||
}
|
||||
|
||||
/***
|
||||
****
|
||||
***/
|
||||
|
||||
static void updateRatio(tr_session_stats* setme)
|
||||
{
|
||||
setme->ratio = tr_getRatio(setme->uploadedBytes, setme->downloadedBytes);
|
||||
}
|
||||
|
||||
static void addStats(tr_session_stats* setme, tr_session_stats const* a, tr_session_stats const* b)
|
||||
{
|
||||
setme->uploadedBytes = a->uploadedBytes + b->uploadedBytes;
|
||||
setme->downloadedBytes = a->downloadedBytes + b->downloadedBytes;
|
||||
setme->filesAdded = a->filesAdded + b->filesAdded;
|
||||
setme->sessionCount = a->sessionCount + b->sessionCount;
|
||||
setme->secondsActive = a->secondsActive + b->secondsActive;
|
||||
updateRatio(setme);
|
||||
}
|
||||
|
||||
void tr_sessionGetStats(tr_session const* session, tr_session_stats* setme)
|
||||
{
|
||||
struct tr_stats_handle const* stats = getStats(session);
|
||||
|
||||
if (stats != nullptr)
|
||||
{
|
||||
*setme = stats->single;
|
||||
setme->secondsActive = tr_time() - stats->startTime;
|
||||
updateRatio(setme);
|
||||
}
|
||||
}
|
||||
|
||||
void tr_sessionGetCumulativeStats(tr_session const* session, tr_session_stats* setme)
|
||||
{
|
||||
struct tr_stats_handle const* stats = getStats(session);
|
||||
auto current = tr_session_stats{};
|
||||
|
||||
if (stats != nullptr)
|
||||
{
|
||||
tr_sessionGetStats(session, ¤t);
|
||||
addStats(setme, &stats->old, ¤t);
|
||||
}
|
||||
}
|
||||
|
||||
void tr_sessionClearStats(tr_session* session)
|
||||
{
|
||||
tr_session_stats zero;
|
||||
|
||||
zero.uploadedBytes = 0;
|
||||
zero.downloadedBytes = 0;
|
||||
zero.ratio = TR_RATIO_NA;
|
||||
zero.filesAdded = 0;
|
||||
zero.sessionCount = 0;
|
||||
zero.secondsActive = 0;
|
||||
|
||||
session->sessionStats->isDirty = true;
|
||||
session->sessionStats->single = session->sessionStats->old = zero;
|
||||
session->sessionStats->startTime = tr_time();
|
||||
}
|
||||
|
||||
/**
|
||||
***
|
||||
**/
|
||||
|
||||
void tr_statsAddUploaded(tr_session* session, uint32_t bytes)
|
||||
{
|
||||
auto* const s = getStats(session);
|
||||
|
||||
if (s != nullptr)
|
||||
{
|
||||
s->single.uploadedBytes += bytes;
|
||||
s->isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tr_statsAddDownloaded(tr_session* session, uint32_t bytes)
|
||||
{
|
||||
auto* const s = getStats(session);
|
||||
|
||||
if (s != nullptr)
|
||||
{
|
||||
s->single.downloadedBytes += bytes;
|
||||
s->isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void tr_statsFileCreated(tr_session* session)
|
||||
{
|
||||
auto* const s = getStats(session);
|
||||
|
||||
if (s != nullptr)
|
||||
{
|
||||
s->single.filesAdded++;
|
||||
}
|
||||
auto ret = single_;
|
||||
ret.secondsActive = time(nullptr) - start_time_;
|
||||
ret.ratio = tr_getRatio(ret.uploadedBytes, ret.downloadedBytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+87
-6
@@ -9,9 +9,90 @@
|
||||
#error only libtransmission should #include this header.
|
||||
#endif
|
||||
|
||||
void tr_statsInit(tr_session* session);
|
||||
void tr_statsClose(tr_session* session);
|
||||
void tr_statsSaveDirty(tr_session* session);
|
||||
void tr_statsAddUploaded(tr_session* session, uint32_t bytes);
|
||||
void tr_statsAddDownloaded(tr_session* session, uint32_t bytes);
|
||||
void tr_statsFileCreated(tr_session* session);
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "transmission.h" // for tr_session_stats
|
||||
|
||||
#include "utils.h" // for tr_getRatio()
|
||||
|
||||
// per-session data structure for bandwidth use statistics
|
||||
class tr_stats
|
||||
{
|
||||
public:
|
||||
tr_stats(std::string_view config_dir, time_t now)
|
||||
: config_dir_{ config_dir }
|
||||
, start_time_{ now }
|
||||
{
|
||||
single_.sessionCount = 1;
|
||||
old_ = loadOldStats(config_dir_);
|
||||
}
|
||||
|
||||
~tr_stats()
|
||||
{
|
||||
saveIfDirty();
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
[[nodiscard]] tr_session_stats current() const;
|
||||
|
||||
[[nodiscard]] auto cumulative() const
|
||||
{
|
||||
return add(current(), old_);
|
||||
}
|
||||
|
||||
void addUploaded(uint32_t n_bytes) noexcept
|
||||
{
|
||||
single_.uploadedBytes += n_bytes;
|
||||
is_dirty_ = true;
|
||||
}
|
||||
|
||||
void addDownloaded(uint32_t n_bytes) noexcept
|
||||
{
|
||||
single_.downloadedBytes += n_bytes;
|
||||
is_dirty_ = true;
|
||||
}
|
||||
|
||||
void addFileCreated() noexcept
|
||||
{
|
||||
++single_.filesAdded;
|
||||
is_dirty_ = true;
|
||||
}
|
||||
|
||||
void saveIfDirty()
|
||||
{
|
||||
if (is_dirty_)
|
||||
{
|
||||
save();
|
||||
is_dirty_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static tr_session_stats add(tr_session_stats const& a, tr_session_stats const& b)
|
||||
{
|
||||
auto ret = tr_session_stats{};
|
||||
ret.uploadedBytes = a.uploadedBytes + b.uploadedBytes;
|
||||
ret.downloadedBytes = a.downloadedBytes + b.downloadedBytes;
|
||||
ret.filesAdded = a.filesAdded + b.filesAdded;
|
||||
ret.sessionCount = a.sessionCount + b.sessionCount;
|
||||
ret.secondsActive = a.secondsActive + b.secondsActive;
|
||||
ret.ratio = tr_getRatio(ret.uploadedBytes, ret.downloadedBytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void save() const;
|
||||
|
||||
static tr_session_stats loadOldStats(std::string_view config_dir);
|
||||
|
||||
std::string const config_dir_;
|
||||
time_t start_time_;
|
||||
|
||||
static constexpr auto Zero = tr_session_stats{ TR_RATIO_NA, 0U, 0U, 0U, 0U, 0U };
|
||||
tr_session_stats single_ = Zero;
|
||||
tr_session_stats old_ = Zero;
|
||||
|
||||
bool is_dirty_ = false;
|
||||
};
|
||||
|
||||
@@ -454,10 +454,10 @@ struct tr_session_stats
|
||||
};
|
||||
|
||||
/** @brief Get bandwidth use statistics for the current session */
|
||||
void tr_sessionGetStats(tr_session const* session, tr_session_stats* setme);
|
||||
tr_session_stats tr_sessionGetStats(tr_session const* session);
|
||||
|
||||
/** @brief Get cumulative bandwidth statistics for current and past sessions */
|
||||
void tr_sessionGetCumulativeStats(tr_session const* session, tr_session_stats* setme);
|
||||
tr_session_stats tr_sessionGetCumulativeStats(tr_session const* session);
|
||||
|
||||
void tr_sessionClearStats(tr_session* session);
|
||||
|
||||
|
||||
@@ -864,9 +864,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
|
||||
//shamelessly ask for donations
|
||||
if ([self.fDefaults boolForKey:@"WarningDonate"])
|
||||
{
|
||||
tr_session_stats stats;
|
||||
tr_sessionGetCumulativeStats(self.fLib, &stats);
|
||||
BOOL const firstLaunch = stats.sessionCount <= 1;
|
||||
BOOL const firstLaunch = tr_sessionGetCumulativeStats(self.fLib).sessionCount <= 1;
|
||||
|
||||
NSDate* lastDonateDate = [self.fDefaults objectForKey:@"DonateAskDate"];
|
||||
BOOL const timePassed = !lastDonateDate || (-1 * lastDonateDate.timeIntervalSinceNow) >= DONATE_NAG_TIME;
|
||||
|
||||
@@ -182,9 +182,8 @@ tr_session* fLib = NULL;
|
||||
|
||||
- (void)updateStats
|
||||
{
|
||||
tr_session_stats statsAll, statsSession;
|
||||
tr_sessionGetCumulativeStats(fLib, &statsAll);
|
||||
tr_sessionGetStats(fLib, &statsSession);
|
||||
auto const statsAll = tr_sessionGetCumulativeStats(fLib);
|
||||
auto const statsSession = tr_sessionGetStats(fLib);
|
||||
|
||||
NSByteCountFormatter* byteFormatter = [[NSByteCountFormatter alloc] init];
|
||||
byteFormatter.allowedUnits = NSByteCountFormatterUseBytes;
|
||||
|
||||
@@ -93,15 +93,7 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
||||
BOOL total;
|
||||
if ((total = [statusLabel isEqualToString:STATUS_RATIO_TOTAL]) || [statusLabel isEqualToString:STATUS_RATIO_SESSION])
|
||||
{
|
||||
tr_session_stats stats;
|
||||
if (total)
|
||||
{
|
||||
tr_sessionGetCumulativeStats(self.fLib, &stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_sessionGetStats(self.fLib, &stats);
|
||||
}
|
||||
auto const stats = total ? tr_sessionGetCumulativeStats(self.fLib) : tr_sessionGetStats(self.fLib);
|
||||
|
||||
statusString = [NSLocalizedString(@"Ratio", "status bar -> status label")
|
||||
stringByAppendingFormat:@": %@", [NSString stringForRatio:stats.ratio]];
|
||||
@@ -110,15 +102,7 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
||||
{
|
||||
total = [statusLabel isEqualToString:STATUS_TRANSFER_TOTAL];
|
||||
|
||||
tr_session_stats stats;
|
||||
if (total)
|
||||
{
|
||||
tr_sessionGetCumulativeStats(self.fLib, &stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_sessionGetStats(self.fLib, &stats);
|
||||
}
|
||||
auto const stats = total ? tr_sessionGetCumulativeStats(self.fLib) : tr_sessionGetStats(self.fLib);
|
||||
|
||||
statusString = [NSString stringWithFormat:@"%@: %@ %@: %@",
|
||||
NSLocalizedString(@"DL", "status bar -> status label"),
|
||||
|
||||
Reference in New Issue
Block a user