refactor: use new tr_variant API in tr_session (#6006)

This commit is contained in:
Charles Kerr
2023-09-16 08:23:35 -05:00
committed by GitHub
parent 85a120faea
commit 6ead147620
15 changed files with 128 additions and 129 deletions

View File

@@ -256,7 +256,7 @@ int tr_main(int argc, char* argv[])
}
}
auto* const h = tr_sessionInit(config_dir.c_str(), false, &settings);
auto* const h = tr_sessionInit(config_dir.c_str(), false, settings);
auto* const ctor = tr_ctorNew(h);
tr_ctorSetPaused(ctor, TR_FORCE, false);
@@ -354,7 +354,7 @@ int tr_main(int argc, char* argv[])
}
}
tr_sessionSaveSettings(h, config_dir.c_str(), &settings);
tr_sessionSaveSettings(h, config_dir.c_str(), settings);
printf("\n");
tr_sessionClose(h);

View File

@@ -684,7 +684,7 @@ void tr_daemon::reconfigure(void)
tr_variantDictAddBool(&newsettings, TR_KEY_rpc_enabled, true);
newsettings.merge(tr_sessionLoadSettings(configDir, MyName));
tr_sessionSet(my_session_, &newsettings);
tr_sessionSet(my_session_, newsettings);
tr_sessionReloadBlocklists(my_session_);
}
}
@@ -725,10 +725,10 @@ int tr_daemon::start([[maybe_unused]] bool foreground)
tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr);
tr_formatter_size_init(DiskK, DiskKStr, DiskMStr, DiskGStr, DiskTStr);
tr_formatter_speed_init(SpeedK, SpeedKStr, SpeedMStr, SpeedGStr, SpeedTStr);
session = tr_sessionInit(cdir, true, &settings_);
session = tr_sessionInit(cdir, true, settings_);
tr_sessionSetRPCCallback(session, on_rpc_callback, this);
tr_logAddInfo(fmt::format(_("Loading settings from '{path}'"), fmt::arg("path", cdir)));
tr_sessionSaveSettings(session, cdir, &settings_);
tr_sessionSaveSettings(session, cdir, settings_);
auto sv = std::string_view{};
(void)tr_variantDictFindStrView(&settings_, key_pidfile_, &sv);
@@ -874,7 +874,7 @@ CLEANUP:
event_base_free(ev_base_);
tr_sessionSaveSettings(my_session_, cdir, &settings_);
tr_sessionSaveSettings(my_session_, cdir, settings_);
tr_sessionClose(my_session_);
pumpLogMessages(logfile_, logfile_flush_);
printf(" done.\n");

View File

@@ -607,7 +607,7 @@ void Application::Impl::on_startup()
}
/* initialize the libtransmission session */
session = tr_sessionInit(config_dir_.c_str(), true, &gtr_pref_get_all());
session = tr_sessionInit(config_dir_.c_str(), true, gtr_pref_get_all());
gtr_pref_flag_set(TR_KEY_alt_speed_enabled, tr_sessionUsesAltSpeed(session));
gtr_pref_int_set(TR_KEY_peer_port, tr_sessionGetPeerPort(session));

View File

@@ -213,5 +213,5 @@ void gtr_pref_string_set(tr_quark const key, std::string_view value)
void gtr_pref_save(tr_session* session)
{
tr_sessionSaveSettings(session, gl_confdir.c_str(), &getPrefs());
tr_sessionSaveSettings(session, gl_confdir.c_str(), getPrefs());
}

View File

@@ -2350,7 +2350,7 @@ void addSessionField(tr_session const* s, tr_variant* d, tr_quark key)
break;
case TR_KEY_units:
tr_formatter_get_units(tr_variantDictAddDict(d, key, 0));
*tr_variantDictAdd(d, key) = tr_formatter_get_units();
break;
case TR_KEY_version:

View File

@@ -76,50 +76,55 @@ void bandwidthGroupRead(tr_session* session, std::string_view config_dir)
return;
}
auto groups_var = tr_variant_serde::json().parse_file(filename);
auto const groups_var = tr_variant_serde::json().parse_file(filename);
if (!groups_var)
{
return;
}
auto idx = size_t{ 0 };
auto key = tr_quark{};
tr_variant* dict = nullptr;
while (tr_variantDictChild(&*groups_var, idx, &key, &dict))
auto const* const groups_map = groups_var->get_if<tr_variant::Map>();
if (groups_map == nullptr)
{
++idx;
return;
}
auto name = tr_interned_string(key);
auto& group = session->getBandwidthGroup(name);
for (auto const& [key, group_var] : *groups_map)
{
auto const* const group_map = group_var.get_if<tr_variant::Map>();
if (group_map == nullptr)
{
continue;
}
auto& group = session->getBandwidthGroup(tr_interned_string{ key });
auto limits = tr_bandwidth_limits{};
if (auto val = bool{}; tr_variantDictFindBool(dict, TR_KEY_uploadLimited, &val))
if (auto const* val = group_map->find_if<bool>(TR_KEY_uploadLimited); val != nullptr)
{
limits.up_limited = val;
limits.up_limited = *val;
}
if (auto val = bool{}; tr_variantDictFindBool(dict, TR_KEY_downloadLimited, &val))
if (auto const* val = group_map->find_if<bool>(TR_KEY_downloadLimited); val != nullptr)
{
limits.down_limited = val;
limits.down_limited = *val;
}
if (auto val = int64_t{}; tr_variantDictFindInt(dict, TR_KEY_uploadLimit, &val))
if (auto const* val = group_map->find_if<int64_t>(TR_KEY_uploadLimit); val != nullptr)
{
limits.up_limit_KBps = static_cast<tr_kilobytes_per_second_t>(val);
limits.up_limit_KBps = static_cast<tr_kilobytes_per_second_t>(*val);
}
if (auto val = int64_t{}; tr_variantDictFindInt(dict, TR_KEY_downloadLimit, &val))
if (auto const* val = group_map->find_if<int64_t>(TR_KEY_downloadLimit); val != nullptr)
{
limits.down_limit_KBps = static_cast<tr_kilobytes_per_second_t>(val);
limits.down_limit_KBps = static_cast<tr_kilobytes_per_second_t>(*val);
}
group.set_limits(&limits);
if (auto honors = bool{}; tr_variantDictFindBool(dict, TR_KEY_honorsSessionLimits, &honors))
if (auto const* val = group_map->find_if<bool>(TR_KEY_honorsSessionLimits); val != nullptr)
{
group.honor_parent_limits(TR_UP, honors);
group.honor_parent_limits(TR_DOWN, honors);
group.honor_parent_limits(TR_UP, *val);
group.honor_parent_limits(TR_DOWN, *val);
}
}
}
@@ -127,27 +132,24 @@ void bandwidthGroupRead(tr_session* session, std::string_view config_dir)
void bandwidthGroupWrite(tr_session const* session, std::string_view config_dir)
{
auto const& groups = session->bandwidthGroups();
auto groups_dict = tr_variant{};
tr_variantInitDict(&groups_dict, std::size(groups));
auto groups_map = tr_variant::Map{ std::size(groups) };
for (auto const& [name, group] : groups)
{
auto const limits = group->get_limits();
auto* const dict = tr_variantDictAddDict(&groups_dict, name.quark(), 5);
tr_variantDictAddStrView(dict, TR_KEY_name, name.sv());
tr_variantDictAddBool(dict, TR_KEY_uploadLimited, limits.up_limited);
tr_variantDictAddInt(dict, TR_KEY_uploadLimit, limits.up_limit_KBps);
tr_variantDictAddBool(dict, TR_KEY_downloadLimited, limits.down_limited);
tr_variantDictAddInt(dict, TR_KEY_downloadLimit, limits.down_limit_KBps);
tr_variantDictAddBool(dict, TR_KEY_honorsSessionLimits, group->are_parent_limits_honored(TR_UP));
auto group_map = tr_variant::Map{ 6U };
group_map.try_emplace(TR_KEY_downloadLimit, limits.down_limit_KBps);
group_map.try_emplace(TR_KEY_downloadLimited, limits.down_limited);
group_map.try_emplace(TR_KEY_honorsSessionLimits, group->are_parent_limits_honored(TR_UP));
group_map.try_emplace(TR_KEY_name, name.sv());
group_map.try_emplace(TR_KEY_uploadLimit, limits.up_limit_KBps);
group_map.try_emplace(TR_KEY_uploadLimited, limits.up_limited);
groups_map.try_emplace(name.quark(), std::move(group_map));
}
auto const filename = tr_pathbuf{ config_dir, '/', BandwidthGroupsFilename };
tr_variant_serde::json().to_file(groups_dict, filename);
tr_variant_serde::json().to_file(
tr_variant{ std::move(groups_map) },
tr_pathbuf{ config_dir, '/', BandwidthGroupsFilename });
}
} // namespace bandwidth_group_helpers
void update_bandwidth(tr_session* session, tr_direction dir)
@@ -467,10 +469,7 @@ tr_variant tr_sessionGetSettings(tr_session const* session)
settings.merge(session->settings_.settings());
settings.merge(session->alt_speeds_.settings());
settings.merge(session->rpc_server_->settings());
tr_variantDictRemove(&settings, TR_KEY_message_level);
tr_variantDictAddInt(&settings, TR_KEY_message_level, tr_logGetLevel());
(*settings.get_if<tr_variant::Map>())[TR_KEY_message_level] = tr_logGetLevel();
return settings;
}
@@ -493,34 +492,31 @@ tr_variant tr_sessionLoadSettings(char const* config_dir, char const* app_name)
return settings;
}
void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_variant const* client_settings)
void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_variant const& client_settings)
{
using namespace bandwidth_group_helpers;
TR_ASSERT(client_settings != nullptr);
TR_ASSERT(client_settings->holds_alternative<tr_variant::Map>());
TR_ASSERT(client_settings.holds_alternative<tr_variant::Map>());
tr_variant settings;
auto const filename = tr_pathbuf{ config_dir, "/settings.json"sv };
tr_variantInitDict(&settings, 0);
/* the existing file settings are the fallback values */
// from highest to lowest precedence:
// - actual values
// - client settings
// - previous session's settings stored in settings.json
// - built-in defaults
auto settings = tr_sessionGetDefaultSettings();
if (auto const file_settings = tr_variant_serde::json().parse_file(filename); file_settings)
{
tr_variantMergeDicts(&settings, &*file_settings);
settings.merge(*file_settings);
}
/* the client's settings override the file settings */
tr_variantMergeDicts(&settings, client_settings);
/* the session's true values override the file & client settings */
settings.merge(client_settings);
settings.merge(tr_sessionGetSettings(session));
/* save the result */
// save 'em
tr_variant_serde::json().to_file(settings, filename);
/* Write bandwidth groups limits to file */
// write bandwidth groups limits to file
bandwidthGroupWrite(session, config_dir);
}
@@ -528,37 +524,51 @@ void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_vari
struct tr_session::init_data
{
init_data(bool message_queuing_enabled_in, std::string_view config_dir_in, tr_variant const& settings_in)
: message_queuing_enabled{ message_queuing_enabled_in }
, config_dir{ config_dir_in }
, settings{ settings_in }
{
}
bool message_queuing_enabled;
std::string_view config_dir;
tr_variant* client_settings;
tr_variant const& settings;
std::condition_variable_any done_cv;
};
tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, tr_variant* client_settings)
tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, tr_variant const& client_settings)
{
using namespace bandwidth_group_helpers;
TR_ASSERT(client_settings != nullptr);
TR_ASSERT(client_settings->holds_alternative<tr_variant::Map>());
TR_ASSERT(config_dir != nullptr);
TR_ASSERT(client_settings.holds_alternative<tr_variant::Map>());
tr_timeUpdate(time(nullptr));
// nice to start logging at the very beginning
if (auto val = int64_t{}; tr_variantDictFindInt(client_settings, TR_KEY_message_level, &val))
// settings order of precedence from highest to lowest:
// - client settings
// - previous session's values in settings.json
// - hardcoded defaults
auto settings = tr_sessionLoadSettings(config_dir, nullptr);
settings.merge(client_settings);
// if logging is desired, start it now before doing more work
if (auto const* settings_map = client_settings.get_if<tr_variant::Map>(); settings_map != nullptr)
{
tr_logSetLevel(static_cast<tr_log_level>(val));
if (auto const* val = settings_map->find_if<bool>(TR_KEY_message_level); val != nullptr)
{
tr_logSetLevel(static_cast<tr_log_level>(*val));
}
}
/* initialize the bare skeleton of the session object */
// initialize the bare skeleton of the session object
auto* const session = new tr_session{ config_dir, tr_variant::make_map() };
bandwidthGroupRead(session, config_dir);
auto data = tr_session::init_data{};
data.config_dir = config_dir;
data.message_queuing_enabled = message_queueing_enabled;
data.client_settings = client_settings;
// run initImpl() in the libtransmission thread
auto data = tr_session::init_data{ message_queueing_enabled, config_dir, settings };
auto lock = session->unique_lock();
session->runInSessionThread([&session, &data]() { session->initImpl(data); });
data.done_cv.wait(lock); // wait for the session to be ready
@@ -590,15 +600,11 @@ void tr_session::initImpl(init_data& data)
auto lock = unique_lock();
TR_ASSERT(am_in_session_thread());
auto* const client_settings = data.client_settings;
TR_ASSERT(client_settings != nullptr);
TR_ASSERT(client_settings->holds_alternative<tr_variant::Map>());
auto const& settings = data.settings;
TR_ASSERT(settings.holds_alternative<tr_variant::Map>());
tr_logAddTrace(fmt::format("tr_sessionInit: the session's top-level bandwidth object is {}", fmt::ptr(&top_bandwidth_)));
auto settings = tr_sessionGetDefaultSettings();
tr_variantMergeDicts(&settings, client_settings);
#ifndef _WIN32
/* Don't exit when writing on a broken socket */
(void)signal(SIGPIPE, SIG_IGN);
@@ -610,7 +616,7 @@ void tr_session::initImpl(init_data& data)
tr_logAddInfo(fmt::format(_("Transmission version {version} starting"), fmt::arg("version", LONG_VERSION_STRING)));
setSettings(client_settings, true);
setSettings(settings, true);
if (this->allowsLPD())
{
@@ -623,20 +629,16 @@ void tr_session::initImpl(init_data& data)
data.done_cv.notify_one();
}
void tr_session::setSettings(tr_variant* settings_dict, bool force)
void tr_session::setSettings(tr_variant const& settings, bool force)
{
TR_ASSERT(am_in_session_thread());
TR_ASSERT(settings_dict != nullptr);
TR_ASSERT(settings_dict->holds_alternative<tr_variant::Map>());
TR_ASSERT(settings.holds_alternative<tr_variant::Map>());
// load the session settings
auto new_settings = tr_session_settings{};
new_settings.load(*settings_dict);
setSettings(std::move(new_settings), force);
setSettings(tr_session_settings{ settings }, force);
// delegate loading out the other settings
alt_speeds_.load(*settings_dict);
rpc_server_->load(*settings_dict);
alt_speeds_.load(settings);
rpc_server_->load(settings);
}
void tr_session::setSettings(tr_session_settings&& settings_in, bool force)
@@ -766,7 +768,7 @@ void tr_session::setSettings(tr_session_settings&& settings_in, bool force)
update_bandwidth(this, TR_DOWN);
}
void tr_sessionSet(tr_session* session, tr_variant* settings)
void tr_sessionSet(tr_session* session, tr_variant const& settings)
{
// do the work in the session thread
auto done_promise = std::promise<void>{};

View File

@@ -966,7 +966,7 @@ private:
struct init_data;
void initImpl(init_data&);
void setSettings(tr_variant* settings_dict, bool force);
void setSettings(tr_variant const& settings_map, bool force);
void setSettings(tr_session_settings&& settings, bool force);
void closeImplPart1(std::promise<void>* closed_promise, std::chrono::time_point<std::chrono::steady_clock> deadline);
@@ -998,7 +998,7 @@ private:
friend tr_kilobytes_per_second_t tr_sessionGetSpeedLimit_KBps(tr_session const* session, tr_direction dir);
friend tr_port_forwarding_state tr_sessionGetPortForwarding(tr_session const* session);
friend tr_sched_day tr_sessionGetAltSpeedDay(tr_session const* session);
friend tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, tr_variant* client_settings);
friend tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, tr_variant const& client_settings);
friend uint16_t tr_sessionGetPeerPort(tr_session const* session);
friend uint16_t tr_sessionGetRPCPort(tr_session const* session);
friend uint16_t tr_sessionSetPeerPortRandom(tr_session* session);
@@ -1006,7 +1006,7 @@ private:
friend tr_variant tr_sessionGetSettings(tr_session const* s);
friend void tr_sessionLimitSpeed(tr_session* session, tr_direction dir, bool limited);
friend void tr_sessionReloadBlocklists(tr_session* session);
friend void tr_sessionSet(tr_session* session, tr_variant* settings);
friend void tr_sessionSet(tr_session* session, tr_variant const& settings);
friend void tr_sessionSetAltSpeedBegin(tr_session* session, size_t minutes_since_midnight);
friend void tr_sessionSetAltSpeedDay(tr_session* session, tr_sched_day days);
friend void tr_sessionSetAltSpeedEnd(tr_session* session, size_t minutes_since_midnight);

View File

@@ -199,7 +199,7 @@ tr_variant tr_sessionLoadSettings(char const* config_dir, char const* app_name);
* @param client_settings the dictionary to save
* @see `tr_sessionLoadSettings()`
*/
void tr_sessionSaveSettings(tr_session* session, char const* config_dir, struct tr_variant const* client_settings);
void tr_sessionSaveSettings(tr_session* session, char const* config_dir, tr_variant const& client_settings);
/**
* @brief Initialize a libtransmission session.
@@ -218,11 +218,11 @@ void tr_sessionSaveSettings(tr_session* session, char const* config_dir, struct
* @see `tr_sessionLoadSettings()`
* @see `tr_getDefaultConfigDir()`
*/
tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, struct tr_variant* settings);
tr_session* tr_sessionInit(char const* config_dir, bool message_queueing_enabled, tr_variant const& settings);
/** @brief Update a session's settings from a benc dictionary
like to the one used in `tr_sessionInit()` */
void tr_sessionSet(tr_session* session, struct tr_variant* settings);
void tr_sessionSet(tr_session* session, tr_variant const& settings);
/** @brief Rescan the blocklists directory and
reload whatever blocklist files are found there */

View File

@@ -851,34 +851,30 @@ std::string tr_formatter_mem_B(size_t bytes_per_second)
return formatter_get_size_str(mem_units, std::data(buf), bytes_per_second, std::size(buf));
}
void tr_formatter_get_units(void* vdict)
tr_variant tr_formatter_get_units()
{
using namespace formatter_impl;
auto* dict = static_cast<tr_variant*>(vdict);
tr_variantDictReserve(dict, 6);
tr_variantDictAddInt(dict, TR_KEY_memory_bytes, mem_units[TR_FMT_KB].value);
tr_variant* l = tr_variantDictAddList(dict, TR_KEY_memory_units, std::size(mem_units));
for (auto const& unit : mem_units)
auto const make_units_vec = [](formatter_units const& units)
{
tr_variantListAddStr(l, std::data(unit.name));
}
auto units_vec = tr_variant::Vector{};
units_vec.reserve(std::size(units));
std::transform(
std::begin(units),
std::end(units),
std::back_inserter(units_vec),
[](auto const& unit) { return std::data(unit.name); });
return units_vec;
};
tr_variantDictAddInt(dict, TR_KEY_size_bytes, size_units[TR_FMT_KB].value);
l = tr_variantDictAddList(dict, TR_KEY_size_units, std::size(size_units));
for (auto const& unit : size_units)
{
tr_variantListAddStr(l, std::data(unit.name));
}
tr_variantDictAddInt(dict, TR_KEY_speed_bytes, speed_units[TR_FMT_KB].value);
l = tr_variantDictAddList(dict, TR_KEY_speed_units, std::size(speed_units));
for (auto const& unit : speed_units)
{
tr_variantListAddStr(l, std::data(unit.name));
}
auto units_map = tr_variant::Map{ 6U };
units_map.try_emplace(TR_KEY_memory_bytes, mem_units[TR_FMT_KB].value);
units_map.try_emplace(TR_KEY_memory_units, make_units_vec(mem_units));
units_map.try_emplace(TR_KEY_size_bytes, size_units[TR_FMT_KB].value);
units_map.try_emplace(TR_KEY_size_units, make_units_vec(size_units));
units_map.try_emplace(TR_KEY_speed_bytes, speed_units[TR_FMT_KB].value);
units_map.try_emplace(TR_KEY_speed_units, make_units_vec(speed_units));
return tr_variant{ std::move(units_map) };
}
// --- ENVIRONMENT

View File

@@ -325,7 +325,7 @@ extern uint64_t tr_size_K; /* unused? */
/** @brief Format a file size from bytes into a user-readable string. */
[[nodiscard]] std::string tr_formatter_size_B(uint64_t bytes);
void tr_formatter_get_units(void* dict);
struct tr_variant tr_formatter_get_units();
[[nodiscard]] static inline size_t tr_toSpeedBytes(size_t KBps)
{

View File

@@ -142,7 +142,7 @@ public:
// --- custom functions
template<typename Type>
[[nodiscard]] TR_CONSTEXPR20 auto TR_CONSTEXPR20 find_if(tr_quark const key) const noexcept
[[nodiscard]] TR_CONSTEXPR20 auto find_if(tr_quark const key) const noexcept
{
auto const iter = find(key);
return iter != end() ? iter->second.get_if<Type>() : nullptr;
@@ -319,9 +319,10 @@ public:
val_.emplace<std::monostate>();
}
void merge(tr_variant const& that)
tr_variant& merge(tr_variant const& that)
{
std::visit(Merge{ *this }, that.val_);
return *this;
}
private:

View File

@@ -544,7 +544,7 @@ void onTorrentCompletenessChanged(tr_torrent* tor, tr_completeness status, bool
tr_formatter_mem_init(1000, kbString.UTF8String, mbString.UTF8String, gbString.UTF8String, tbString.UTF8String);
auto const default_config_dir = tr_getDefaultConfigDir("Transmission");
_fLib = tr_sessionInit(default_config_dir.c_str(), YES, &settings);
_fLib = tr_sessionInit(default_config_dir.c_str(), YES, settings);
_fConfigDirectory = @(default_config_dir.c_str());
tr_sessionSetIdleLimitHitCallback(_fLib, onIdleLimitHit, (__bridge void*)(self));

View File

@@ -356,8 +356,8 @@ void Session::start()
}
else
{
auto settings = tr_sessionLoadSettings(config_dir_.toUtf8().constData(), "qt");
session_ = tr_sessionInit(config_dir_.toUtf8().constData(), true, &settings);
auto const settings = tr_sessionLoadSettings(config_dir_.toUtf8().constData(), "qt");
session_ = tr_sessionInit(config_dir_.toUtf8().constData(), true, settings);
rpc_.start(session_);

View File

@@ -309,7 +309,7 @@ TEST_F(SessionTest, honorsSettings)
tr_variantDictRemove(&settings, key);
tr_variantDictAddBool(&settings, key, true);
}
auto* session = tr_sessionInit(sandboxDir().data(), false, &settings);
auto* session = tr_sessionInit(sandboxDir().data(), false, settings);
// confirm that these settings were enabled
EXPECT_TRUE(session->isPortRandom());

View File

@@ -388,7 +388,7 @@ private:
tr_variantDictAddInt(settings, q, verbose ? TR_LOG_DEBUG : TR_LOG_ERROR);
}
return tr_sessionInit(sandboxDir().data(), !verbose, settings);
return tr_sessionInit(sandboxDir().data(), !verbose, *settings);
}
void sessionClose(tr_session* session)