feat: add setting to choose between lazy-verify or full verify (#4611)
This commit is contained in:
parent
3bc1a1be04
commit
33a7d131b4
|
@ -84,6 +84,7 @@ Here is a sample of the three basic types: respectively Boolean, Number and Stri
|
||||||
* **script-torrent-done-filename:** String (default = "") Path to script.
|
* **script-torrent-done-filename:** String (default = "") Path to script.
|
||||||
* **script-torrent-done-seeding-enabled:** Boolean (default = false) Run a script when a torrent is done seeding. Environmental variables are passed in as detailed on the [Scripts](./Scripts.md) page
|
* **script-torrent-done-seeding-enabled:** Boolean (default = false) Run a script when a torrent is done seeding. Environmental variables are passed in as detailed on the [Scripts](./Scripts.md) page
|
||||||
* **script-torrent-done-seeding-filename:** String (default = "") Path to script.
|
* **script-torrent-done-seeding-filename:** String (default = "") Path to script.
|
||||||
|
* **torrent-added-verify-mode:** String ("fast", "full", default: "fast") Whether newly-added torrents' local data should be fully verified when added, or wait and verify them on-demand later. See [#2626](https://github.com/transmission/transmission/pull/2626) for more discussion.
|
||||||
* **utp-enabled:** Boolean (default = true) Enable [Micro Transport Protocol (µTP)](https://en.wikipedia.org/wiki/Micro_Transport_Protocol)
|
* **utp-enabled:** Boolean (default = true) Enable [Micro Transport Protocol (µTP)](https://en.wikipedia.org/wiki/Micro_Transport_Protocol)
|
||||||
|
|
||||||
#### Peers
|
#### Peers
|
||||||
|
|
|
@ -18,7 +18,7 @@ using namespace std::literals;
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
auto constexpr MyStatic = std::array<std::string_view, 400>{ ""sv,
|
auto constexpr MyStatic = std::array<std::string_view, 401>{ ""sv,
|
||||||
"activeTorrentCount"sv,
|
"activeTorrentCount"sv,
|
||||||
"activity-date"sv,
|
"activity-date"sv,
|
||||||
"activityDate"sv,
|
"activityDate"sv,
|
||||||
|
@ -367,6 +367,7 @@ auto constexpr MyStatic = std::array<std::string_view, 400>{ ""sv,
|
||||||
"torrent-added"sv,
|
"torrent-added"sv,
|
||||||
"torrent-added-notification-command"sv,
|
"torrent-added-notification-command"sv,
|
||||||
"torrent-added-notification-enabled"sv,
|
"torrent-added-notification-enabled"sv,
|
||||||
|
"torrent-added-verify-mode"sv,
|
||||||
"torrent-complete-notification-command"sv,
|
"torrent-complete-notification-command"sv,
|
||||||
"torrent-complete-notification-enabled"sv,
|
"torrent-complete-notification-enabled"sv,
|
||||||
"torrent-complete-sound-command"sv,
|
"torrent-complete-sound-command"sv,
|
||||||
|
|
|
@ -370,6 +370,7 @@ enum
|
||||||
TR_KEY_torrent_added,
|
TR_KEY_torrent_added,
|
||||||
TR_KEY_torrent_added_notification_command,
|
TR_KEY_torrent_added_notification_command,
|
||||||
TR_KEY_torrent_added_notification_enabled,
|
TR_KEY_torrent_added_notification_enabled,
|
||||||
|
TR_KEY_torrent_added_verify_mode,
|
||||||
TR_KEY_torrent_complete_notification_command,
|
TR_KEY_torrent_complete_notification_command,
|
||||||
TR_KEY_torrent_complete_notification_enabled,
|
TR_KEY_torrent_complete_notification_enabled,
|
||||||
TR_KEY_torrent_complete_sound_command,
|
TR_KEY_torrent_complete_sound_command,
|
||||||
|
|
|
@ -72,7 +72,8 @@ struct tr_variant;
|
||||||
V(TR_KEY_trash_original_torrent_files, should_delete_source_torrents, bool, false, "") \
|
V(TR_KEY_trash_original_torrent_files, should_delete_source_torrents, bool, false, "") \
|
||||||
V(TR_KEY_umask, umask, tr_mode_t, 022, "") \
|
V(TR_KEY_umask, umask, tr_mode_t, 022, "") \
|
||||||
V(TR_KEY_upload_slots_per_torrent, upload_slots_per_torrent, size_t, 8U, "") \
|
V(TR_KEY_upload_slots_per_torrent, upload_slots_per_torrent, size_t, 8U, "") \
|
||||||
V(TR_KEY_utp_enabled, utp_enabled, bool, true, "")
|
V(TR_KEY_utp_enabled, utp_enabled, bool, true, "") \
|
||||||
|
V(TR_KEY_torrent_added_verify_mode, torrent_added_verify_mode, tr_verify_added_mode, TR_VERIFY_ADDED_FAST, "")
|
||||||
|
|
||||||
struct tr_session_settings
|
struct tr_session_settings
|
||||||
{
|
{
|
||||||
|
|
|
@ -707,6 +707,11 @@ public:
|
||||||
return !settings_.should_start_added_torrents;
|
return !settings_.should_start_added_torrents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr auto shouldFullyVerifyAddedTorrents() const noexcept
|
||||||
|
{
|
||||||
|
return settings_.torrent_added_verify_mode == TR_VERIFY_ADDED_FULL;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto shouldDeleteSource() const noexcept
|
[[nodiscard]] constexpr auto shouldDeleteSource() const noexcept
|
||||||
{
|
{
|
||||||
return settings_.should_delete_source_torrents;
|
return settings_.should_delete_source_torrents;
|
||||||
|
|
|
@ -1188,7 +1188,7 @@ void torrentInit(tr_torrent* tor, tr_ctor const* ctor)
|
||||||
opts.has_local_data = has_local_data;
|
opts.has_local_data = has_local_data;
|
||||||
torrentStart(tor, opts);
|
torrentStart(tor, opts);
|
||||||
}
|
}
|
||||||
else if (isNewTorrentASeed(tor))
|
else if (!session->shouldFullyVerifyAddedTorrents() && isNewTorrentASeed(tor))
|
||||||
{
|
{
|
||||||
tor->completion.setHasAll();
|
tor->completion.setHasAll();
|
||||||
tor->doneDate = tor->addedDate;
|
tor->doneDate = tor->addedDate;
|
||||||
|
|
|
@ -60,6 +60,16 @@ using tr_priority_t = int8_t;
|
||||||
|
|
||||||
#define TR_RPC_SESSION_ID_HEADER "X-Transmission-Session-Id"
|
#define TR_RPC_SESSION_ID_HEADER "X-Transmission-Session-Id"
|
||||||
|
|
||||||
|
enum tr_verify_added_mode
|
||||||
|
{
|
||||||
|
// See discussion @ https://github.com/transmission/transmission/pull/2626
|
||||||
|
// Let newly-added torrents skip upfront verify do it on-demand later.
|
||||||
|
TR_VERIFY_ADDED_FAST = 0,
|
||||||
|
|
||||||
|
// Force torrents to be fully verified as they are added.
|
||||||
|
TR_VERIFY_ADDED_FULL = 1
|
||||||
|
};
|
||||||
|
|
||||||
enum tr_preallocation_mode
|
enum tr_preallocation_mode
|
||||||
{
|
{
|
||||||
TR_PREALLOCATE_NONE = 0,
|
TR_PREALLOCATE_NONE = 0,
|
||||||
|
|
|
@ -14,9 +14,40 @@
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
auto constexpr EncryptionKeys = std::array<std::pair<std::string_view, tr_encryption_mode>, 3>{ {
|
||||||
|
{ "required", TR_ENCRYPTION_REQUIRED },
|
||||||
|
{ "preferred", TR_ENCRYPTION_PREFERRED },
|
||||||
|
{ "allowed", TR_CLEAR_PREFERRED },
|
||||||
|
} };
|
||||||
|
|
||||||
|
auto constexpr LogKeys = std::array<std::pair<std::string_view, tr_log_level>, 7>{ {
|
||||||
|
{ "critical", TR_LOG_CRITICAL },
|
||||||
|
{ "debug", TR_LOG_DEBUG },
|
||||||
|
{ "error", TR_LOG_ERROR },
|
||||||
|
{ "info", TR_LOG_INFO },
|
||||||
|
{ "off", TR_LOG_OFF },
|
||||||
|
{ "trace", TR_LOG_TRACE },
|
||||||
|
{ "warn", TR_LOG_WARN },
|
||||||
|
} };
|
||||||
|
|
||||||
|
auto constexpr PreallocationKeys = std::array<std::pair<std::string_view, tr_preallocation_mode>, 5>{ {
|
||||||
|
{ "off", TR_PREALLOCATE_NONE },
|
||||||
|
{ "none", TR_PREALLOCATE_NONE },
|
||||||
|
{ "fast", TR_PREALLOCATE_SPARSE },
|
||||||
|
{ "sparse", TR_PREALLOCATE_SPARSE },
|
||||||
|
{ "full", TR_PREALLOCATE_FULL },
|
||||||
|
} };
|
||||||
|
|
||||||
|
auto constexpr VerifyModeKeys = std::array<std::pair<std::string_view, tr_verify_added_mode>, 2>{ {
|
||||||
|
{ "fast", TR_VERIFY_ADDED_FAST },
|
||||||
|
{ "full", TR_VERIFY_ADDED_FULL },
|
||||||
|
} };
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace libtransmission
|
namespace libtransmission
|
||||||
{
|
{
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
std::optional<bool> VariantConverter::load<bool>(tr_variant* src)
|
std::optional<bool> VariantConverter::load<bool>(tr_variant* src)
|
||||||
{
|
{
|
||||||
|
@ -55,21 +86,10 @@ void VariantConverter::save<double>(tr_variant* tgt, double const& val)
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
namespace EncryptionHelpers
|
|
||||||
{
|
|
||||||
// clang-format off
|
|
||||||
static auto constexpr Keys = std::array<std::pair<std::string_view, tr_encryption_mode>, 3>{{
|
|
||||||
{ "required", TR_ENCRYPTION_REQUIRED },
|
|
||||||
{ "preferred", TR_ENCRYPTION_PREFERRED },
|
|
||||||
{ "allowed", TR_CLEAR_PREFERRED }
|
|
||||||
}};
|
|
||||||
// clang-format on
|
|
||||||
} // namespace EncryptionHelpers
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
std::optional<tr_encryption_mode> VariantConverter::load<tr_encryption_mode>(tr_variant* src)
|
std::optional<tr_encryption_mode> VariantConverter::load<tr_encryption_mode>(tr_variant* src)
|
||||||
{
|
{
|
||||||
using namespace EncryptionHelpers;
|
static constexpr auto Keys = EncryptionKeys;
|
||||||
|
|
||||||
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
||||||
{
|
{
|
||||||
|
@ -106,25 +126,10 @@ void VariantConverter::save<tr_encryption_mode>(tr_variant* tgt, tr_encryption_m
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
namespace LogLevelHelpers
|
|
||||||
{
|
|
||||||
// clang-format off
|
|
||||||
static auto constexpr Keys = std::array<std::pair<std::string_view, tr_log_level>, 7>{ {
|
|
||||||
{ "critical", TR_LOG_CRITICAL },
|
|
||||||
{ "debug", TR_LOG_DEBUG },
|
|
||||||
{ "error", TR_LOG_ERROR },
|
|
||||||
{ "info", TR_LOG_INFO },
|
|
||||||
{ "off", TR_LOG_OFF },
|
|
||||||
{ "trace", TR_LOG_TRACE },
|
|
||||||
{ "warn", TR_LOG_WARN },
|
|
||||||
}};
|
|
||||||
// clang-format on
|
|
||||||
} // namespace LogLevelHelpers
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
std::optional<tr_log_level> VariantConverter::load<tr_log_level>(tr_variant* src)
|
std::optional<tr_log_level> VariantConverter::load<tr_log_level>(tr_variant* src)
|
||||||
{
|
{
|
||||||
using namespace LogLevelHelpers;
|
static constexpr auto Keys = LogKeys;
|
||||||
|
|
||||||
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
||||||
{
|
{
|
||||||
|
@ -207,23 +212,10 @@ void VariantConverter::save<tr_port>(tr_variant* tgt, tr_port const& val)
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
namespace PreallocationModeHelpers
|
|
||||||
{
|
|
||||||
// clang-format off
|
|
||||||
static auto constexpr Keys = std::array<std::pair<std::string_view, tr_preallocation_mode>, 5>{{
|
|
||||||
{ "off", TR_PREALLOCATE_NONE },
|
|
||||||
{ "none", TR_PREALLOCATE_NONE },
|
|
||||||
{ "fast", TR_PREALLOCATE_SPARSE },
|
|
||||||
{ "sparse", TR_PREALLOCATE_SPARSE },
|
|
||||||
{ "full", TR_PREALLOCATE_FULL },
|
|
||||||
}};
|
|
||||||
// clang-format on
|
|
||||||
} // namespace PreallocationModeHelpers
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
std::optional<tr_preallocation_mode> VariantConverter::load<tr_preallocation_mode>(tr_variant* src)
|
std::optional<tr_preallocation_mode> VariantConverter::load<tr_preallocation_mode>(tr_variant* src)
|
||||||
{
|
{
|
||||||
using namespace PreallocationModeHelpers;
|
static constexpr auto Keys = PreallocationKeys;
|
||||||
|
|
||||||
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
||||||
{
|
{
|
||||||
|
@ -320,4 +312,53 @@ void VariantConverter::save<tr_tos_t>(tr_variant* tgt, tr_tos_t const& val)
|
||||||
tr_variantInitStr(tgt, val.toString());
|
tr_variantInitStr(tgt, val.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
template<>
|
||||||
|
std::optional<tr_verify_added_mode> VariantConverter::load<tr_verify_added_mode>(tr_variant* src)
|
||||||
|
{
|
||||||
|
static constexpr auto& Keys = VerifyModeKeys;
|
||||||
|
|
||||||
|
if (auto val = std::string_view{}; tr_variantGetStrView(src, &val))
|
||||||
|
{
|
||||||
|
auto const needle = tr_strlower(tr_strvStrip(val));
|
||||||
|
|
||||||
|
for (auto const& [name, value] : Keys)
|
||||||
|
{
|
||||||
|
if (name == needle)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto val = int64_t{}; tr_variantGetInt(src, &val))
|
||||||
|
{
|
||||||
|
for (auto const& [name, value] : Keys)
|
||||||
|
{
|
||||||
|
if (value == val)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void VariantConverter::save<tr_verify_added_mode>(tr_variant* tgt, tr_verify_added_mode const& val)
|
||||||
|
{
|
||||||
|
for (auto const& [key, value] : VerifyModeKeys)
|
||||||
|
{
|
||||||
|
if (value == val)
|
||||||
|
{
|
||||||
|
tr_variantInitStrView(tgt, key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tr_variantInitInt(tgt, val);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace libtransmission
|
} // namespace libtransmission
|
||||||
|
|
|
@ -406,3 +406,45 @@ TEST_F(SettingsTest, canSaveTos)
|
||||||
EXPECT_EQ(ChangedValue.toString(), val);
|
EXPECT_EQ(ChangedValue.toString(), val);
|
||||||
tr_variantClear(&dict);
|
tr_variantClear(&dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTest, canLoadVerify)
|
||||||
|
{
|
||||||
|
static auto constexpr Key = TR_KEY_torrent_added_verify_mode;
|
||||||
|
static auto constexpr ChangedValue = TR_VERIFY_ADDED_FULL;
|
||||||
|
|
||||||
|
auto settings = std::make_unique<tr_session_settings>();
|
||||||
|
auto const default_value = settings->torrent_added_verify_mode;
|
||||||
|
ASSERT_NE(ChangedValue, default_value);
|
||||||
|
|
||||||
|
auto dict = tr_variant{};
|
||||||
|
tr_variantInitDict(&dict, 1);
|
||||||
|
tr_variantDictAddStrView(&dict, Key, "full");
|
||||||
|
settings->load(&dict);
|
||||||
|
tr_variantClear(&dict);
|
||||||
|
EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode);
|
||||||
|
|
||||||
|
settings = std::make_unique<tr_session_settings>();
|
||||||
|
tr_variantInitDict(&dict, 1);
|
||||||
|
tr_variantDictAddInt(&dict, Key, ChangedValue);
|
||||||
|
settings->load(&dict);
|
||||||
|
tr_variantClear(&dict);
|
||||||
|
EXPECT_EQ(ChangedValue, settings->torrent_added_verify_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SettingsTest, canSaveVerify)
|
||||||
|
{
|
||||||
|
static auto constexpr Key = TR_KEY_torrent_added_verify_mode;
|
||||||
|
static auto constexpr ChangedValue = TR_VERIFY_ADDED_FULL;
|
||||||
|
|
||||||
|
auto settings = tr_session_settings{};
|
||||||
|
ASSERT_NE(ChangedValue, settings.torrent_added_verify_mode);
|
||||||
|
|
||||||
|
auto dict = tr_variant{};
|
||||||
|
tr_variantInitDict(&dict, 100);
|
||||||
|
settings.torrent_added_verify_mode = ChangedValue;
|
||||||
|
settings.save(&dict);
|
||||||
|
auto val = std::string_view{};
|
||||||
|
EXPECT_TRUE(tr_variantDictFindStrView(&dict, Key, &val));
|
||||||
|
EXPECT_EQ("full", val);
|
||||||
|
tr_variantClear(&dict);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue