refactor: pause torrent after verifying if files disappeared (#6277)

This commit is contained in:
Yat Ho 2023-11-26 06:20:17 +08:00 committed by GitHub
parent b977ac77ca
commit 7af71d9695
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 42 additions and 142 deletions

View File

@ -112,14 +112,13 @@ username and password (respectively), separated by a colon.
## 3 Torrent requests
### 3.1 Torrent action requests
| Method name | libtransmission function
| Method name | libtransmission function
|:--|:--
| `torrent-start` | tr_torrentStart
| `torrent-start-now` | tr_torrentStartNow
| `torrent-stop` | tr_torrentStop
| `torrent-verify` | tr_torrentVerify
| `torrent-verify-force` | tr_torrentVerifyForce
| `torrent-reannounce` | tr_torrentManualUpdate ("ask tracker for more peers")
| `torrent-start` | tr_torrentStart
| `torrent-start-now` | tr_torrentStartNow
| `torrent-stop` | tr_torrentStop
| `torrent-verify` | tr_torrentVerify
| `torrent-reannounce` | tr_torrentManualUpdate ("ask tracker for more peers")
Request arguments: `ids`, which specifies which torrents to use.
All torrents are used if the `ids` argument is omitted.
@ -1026,4 +1025,3 @@ Transmission 4.1.0 (`rpc-version-semver` 5.4.0, `rpc-version`: 18)
| `torrent-get` | new arg `files.beginPiece`
| `torrent-get` | new arg `files.endPiece`
| `port-test` | new arg `ipProtocol`
| `torrent-verify-force` | new method

View File

@ -282,33 +282,16 @@ char const* torrentReannounce(
return nullptr;
}
namespace torrent_verify_helpers
{
char const* torrentVerifyImpl(tr_session* session, tr_variant* args_in, bool force)
char const* torrentVerify(tr_session* session, tr_variant* args_in, tr_variant* /*args_out*/, tr_rpc_idle_data* /*idle_data*/)
{
for (auto* tor : getTorrents(session, args_in))
{
tr_torrentVerify(tor, force);
tr_torrentVerify(tor);
session->rpcNotify(TR_RPC_TORRENT_CHANGED, tor);
}
return nullptr;
}
} // namespace torrent_verify_helpers
char const* torrentVerify(tr_session* session, tr_variant* args_in, tr_variant* /*args_out*/, tr_rpc_idle_data* /*idle_data*/)
{
return torrent_verify_helpers::torrentVerifyImpl(session, args_in, false);
}
char const* torrentVerifyForce(
tr_session* session,
tr_variant* args_in,
tr_variant* /*args_out*/,
tr_rpc_idle_data* /*idle_data*/)
{
return torrent_verify_helpers::torrentVerifyImpl(session, args_in, true);
}
// ---
@ -2341,7 +2324,7 @@ struct rpc_method
handler func;
};
auto constexpr Methods = std::array<rpc_method, 25>{ {
auto constexpr Methods = std::array<rpc_method, 24>{ {
{ "blocklist-update"sv, false, blocklistUpdate },
{ "free-space"sv, true, freeSpace },
{ "group-get"sv, true, groupGet },
@ -2366,7 +2349,6 @@ auto constexpr Methods = std::array<rpc_method, 25>{ {
{ "torrent-start-now"sv, true, torrentStartNow },
{ "torrent-stop"sv, true, torrentStop },
{ "torrent-verify"sv, true, torrentVerify },
{ "torrent-verify-force"sv, true, torrentVerifyForce },
} };
void noop_response_callback(tr_session* /*session*/, tr_variant* /*response*/, void* /*user_data*/)

View File

@ -148,16 +148,22 @@ bool tr_torrentSetMetainfoFromFile(tr_torrent* tor, tr_torrent_metainfo const* m
namespace
{
bool setLocalErrorIfFilesDisappeared(tr_torrent* tor, std::optional<bool> has_local_data = {})
bool did_files_disappear(tr_torrent* tor, std::optional<bool> has_local_data = {})
{
auto const has = has_local_data ? *has_local_data : tor->has_any_local_data();
bool const files_disappeared = tor->has_total() > 0 && !has;
return tor->has_total() > 0 && !has;
}
bool set_local_error_if_files_disappeared(tr_torrent* tor, std::optional<bool> has_local_data = {})
{
auto const files_disappeared = did_files_disappear(tor, has_local_data);
if (files_disappeared)
{
tr_logAddTraceTor(tor, "[LAZY] uh oh, the files disappeared");
tor->error().set_local_error(_(
"No data found! Ensure your drives are connected or use \"Set Location\". To re-download, remove the torrent and re-add it."));
tor->error().set_local_error(
_("No data found! Ensure your drives are connected or use \"Set Location\". "
"To re-download, use \"Verify Local Data\" and start the torrent afterwards."));
}
return files_disappeared;
@ -735,7 +741,7 @@ void torrentStart(tr_torrent* tor, torrent_start_opts opts)
}
/* don't allow the torrent to be started if the files disappeared */
if (setLocalErrorIfFilesDisappeared(tor, opts.has_local_data))
if (set_local_error_if_files_disappeared(tor, opts.has_local_data))
{
return;
}
@ -1072,7 +1078,7 @@ void tr_torrent::init(tr_ctor const* const ctor)
}
else
{
setLocalErrorIfFilesDisappeared(this, has_local_data);
set_local_error_if_files_disappeared(this, has_local_data);
}
}
@ -1578,10 +1584,10 @@ void tr_torrentStartMagnet(tr_torrent* tor)
// ---
void tr_torrentVerify(tr_torrent* tor, bool force)
void tr_torrentVerify(tr_torrent* tor)
{
tor->session->runInSessionThread(
[tor, force]()
[tor]()
{
TR_ASSERT(tor->session->am_in_session_thread());
auto const lock = tor->unique_lock();
@ -1603,10 +1609,15 @@ void tr_torrentVerify(tr_torrent* tor, bool force)
tor->stop_now();
}
if (force || !setLocalErrorIfFilesDisappeared(tor))
if (did_files_disappear(tor))
{
tor->session->verify_add(tor);
tor->error().set_local_error(
_("Paused torrent as no data was found! Ensure your drives are connected or use \"Set Location\", "
"then use \"Verify Local Data\" again. To re-download, start the torrent."));
tor->start_when_stable = false;
}
tor->session->verify_add(tor);
});
}
@ -2271,7 +2282,7 @@ void tr_torrent::set_download_dir(std::string_view path, bool is_new_torrent)
recheck_completeness();
}
}
else if (error_.error_type() == TR_STAT_LOCAL_ERROR && !setLocalErrorIfFilesDisappeared(this))
else if (error_.error_type() == TR_STAT_LOCAL_ERROR && !set_local_error_if_files_disappeared(this))
{
error_.clear();
}

View File

@ -1058,7 +1058,7 @@ private:
friend void tr_torrentGotBlock(tr_torrent* tor, tr_block_index_t block);
friend void tr_torrentRemove(tr_torrent* tor, bool delete_flag, tr_fileFunc delete_func, void* user_data);
friend void tr_torrentStop(tr_torrent* tor);
friend void tr_torrentVerify(tr_torrent* tor, bool force);
friend void tr_torrentVerify(tr_torrent* tor);
enum class VerifyState : uint8_t
{

View File

@ -1386,7 +1386,7 @@ void tr_torrentAmountFinished(tr_torrent const* torrent, float* tab, int n_tabs)
/**
* Queue a torrent for verification.
*/
void tr_torrentVerify(tr_torrent* torrent, bool force = false);
void tr_torrentVerify(tr_torrent* torrent);
bool tr_torrentHasMetadata(tr_torrent const* tor);

View File

@ -88,10 +88,6 @@ export class ActionManager extends EventTarget {
shortcut: 'V',
text: 'Verify local data',
},
'verify-selected-torrents-force': {
enabled: false,
text: 'Verify local data (force)',
},
});
}
@ -205,7 +201,6 @@ export class ActionManager extends EventTarget {
'show-move-dialog',
'trash-selected-torrents',
'verify-selected-torrents',
'verify-selected-torrents-force',
]);
set_enabled(counts.selected === 1, ['show-rename-dialog']);

View File

@ -95,7 +95,6 @@ export class ContextMenu extends EventTarget {
add_item('trash-selected-torrents', true);
add_separator();
add_item('verify-selected-torrents');
add_item('verify-selected-torrents-force');
add_item('show-move-dialog');
add_item('show-rename-dialog');
add_item('show-labels-dialog');

View File

@ -1,69 +0,0 @@
/* @license This file Copyright © Mnemosyne LLC.
It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
or any future license endorsed by Mnemosyne LLC.
License text can be found in the licenses/ folder. */
import { createDialogContainer } from './utils.js';
export class ForceVerifyDialog extends EventTarget {
constructor(options) {
super();
// options: remote, torrents, callback, controller
this.options = options;
this.elements = ForceVerifyDialog._create(options);
this.elements.dismiss.addEventListener('click', () => this._onDismiss());
this.elements.confirm.addEventListener('click', () => this._onConfirm());
document.body.append(this.elements.root);
this.elements.dismiss.focus();
}
close() {
if (!this.closed) {
this.elements.root.remove();
this.dispatchEvent(new Event('close'));
for (const key of Object.keys(this)) {
delete this[key];
}
this.closed = true;
}
}
_onDismiss() {
this.close();
}
_onConfirm() {
const { remote, torrents, callback, controller } = this.options;
if (torrents.length > 0) {
remote.verifyTorrents(
torrents.map((t) => t.getId()),
true,
callback,
controller,
);
}
this.close();
}
static _create(options) {
const { heading, message } = ForceVerifyDialog._createMessage(options);
const elements = createDialogContainer('remove-dialog');
elements.heading.textContent = heading;
elements.message.textContent = message;
elements.confirm.textContent = 'Verify';
return elements;
}
static _createMessage(options) {
const { torrents } = options;
const heading =
torrents.length === 1
? `Force verify local data of ${torrents[0].getName()}?`
: `Force verify local data of ${torrents.length} transfers?`;
const message = `Missing files will be re-downloaded, use the non-forced verify function if you'd like to check for missing files.`;
return { heading, message };
}
}

View File

@ -227,9 +227,9 @@ export class Remote {
this._controller.refreshTorrents();
});
}
verifyTorrents(torrent_ids, force, callback, context) {
verifyTorrents(torrent_ids, callback, context) {
this.sendTorrentActionRequests(
force ? 'torrent-verify-force' : 'torrent-verify',
'torrent-verify',
torrent_ids,
callback,
context,

View File

@ -4,7 +4,6 @@
import { AboutDialog } from './about-dialog.js';
import { ContextMenu } from './context-menu.js';
import { ForceVerifyDialog } from './force-verify-dialog';
import { Formatter } from './formatter.js';
import { Inspector } from './inspector.js';
import { MoveDialog } from './move-dialog.js';
@ -175,10 +174,7 @@ export class Transmission extends EventTarget {
this._removeSelectedTorrents(true);
break;
case 'verify-selected-torrents':
this._verifyTorrents(this.getSelectedTorrents(), false);
break;
case 'verify-selected-torrents-force':
this._verifyTorrents(this.getSelectedTorrents(), true);
this._verifyTorrents(this.getSelectedTorrents());
break;
default:
console.warn(`unhandled action: ${event_.action}`);
@ -857,24 +853,12 @@ TODO: fix this when notifications get fixed
this,
);
}
_verifyTorrents(torrents, force) {
if (force) {
this.setCurrentPopup(
new ForceVerifyDialog({
callback: this.refreshTorrents,
controller: this,
remote: this.remote,
torrents,
}),
);
} else {
this.remote.verifyTorrents(
Transmission._getTorrentIds(torrents),
force,
this.refreshTorrents,
this,
);
}
_verifyTorrents(torrents) {
this.remote.verifyTorrents(
Transmission._getTorrentIds(torrents),
this.refreshTorrents,
this,
);
}
_reannounceTorrents(torrents) {