Browse Source

Improve move storage handling

PR #18857.
Closes #18795.
adaptive-webui-19844
Vladimir Golovnev 1 year ago committed by GitHub
parent
commit
51132c817b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 29
      src/base/bittorrent/sessionimpl.cpp
  2. 4
      src/base/bittorrent/sessionimpl.h
  3. 51
      src/base/bittorrent/torrentimpl.cpp
  4. 11
      src/base/bittorrent/torrentimpl.h

29
src/base/bittorrent/sessionimpl.cpp

@ -1,6 +1,6 @@
/* /*
* Bittorrent Client using Qt and libtorrent. * Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2022 Vladimir Golovnev <glassez@yandex.ru> * Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org> * Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -72,6 +72,7 @@
#endif #endif
#include <QNetworkInterface> #include <QNetworkInterface>
#include <QRegularExpression> #include <QRegularExpression>
#include <QScopeGuard>
#include <QString> #include <QString>
#include <QThread> #include <QThread>
#include <QThreadPool> #include <QThreadPool>
@ -4859,17 +4860,18 @@ void SessionImpl::handleTorrentInfoHashChanged(TorrentImpl *torrent, const InfoH
} }
} }
bool SessionImpl::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, const MoveStorageMode mode) bool SessionImpl::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, const MoveStorageMode mode, const MoveStorageContext context)
{ {
Q_ASSERT(torrent); Q_ASSERT(torrent);
const lt::torrent_handle torrentHandle = torrent->nativeHandle(); const lt::torrent_handle torrentHandle = torrent->nativeHandle();
const Path currentLocation = torrent->actualStorageLocation(); const Path currentLocation = torrent->actualStorageLocation();
const bool torrentHasActiveJob = !m_moveStorageQueue.isEmpty() && (m_moveStorageQueue.first().torrentHandle == torrentHandle);
if (m_moveStorageQueue.size() > 1) if (m_moveStorageQueue.size() > 1)
{ {
auto iter = std::find_if((m_moveStorageQueue.begin() + 1), m_moveStorageQueue.end() auto iter = std::find_if((m_moveStorageQueue.begin() + 1), m_moveStorageQueue.end()
, [&torrentHandle](const MoveStorageJob &job) , [&torrentHandle](const MoveStorageJob &job)
{ {
return job.torrentHandle == torrentHandle; return job.torrentHandle == torrentHandle;
}); });
@ -4877,20 +4879,13 @@ bool SessionImpl::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &new
if (iter != m_moveStorageQueue.end()) if (iter != m_moveStorageQueue.end())
{ {
// remove existing inactive job // remove existing inactive job
torrent->handleMoveStorageJobFinished(currentLocation, iter->context, torrentHasActiveJob);
LogMsg(tr("Torrent move canceled. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\"").arg(torrent->name(), currentLocation.toString(), iter->path.toString())); LogMsg(tr("Torrent move canceled. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\"").arg(torrent->name(), currentLocation.toString(), iter->path.toString()));
iter = m_moveStorageQueue.erase(iter); m_moveStorageQueue.erase(iter);
iter = std::find_if(iter, m_moveStorageQueue.end(), [&torrentHandle](const MoveStorageJob &job)
{
return job.torrentHandle == torrentHandle;
});
const bool torrentHasOutstandingJob = (iter != m_moveStorageQueue.end());
torrent->handleMoveStorageJobFinished(currentLocation, torrentHasOutstandingJob);
} }
} }
if (!m_moveStorageQueue.isEmpty() && (m_moveStorageQueue.first().torrentHandle == torrentHandle)) if (torrentHasActiveJob)
{ {
// if there is active job for this torrent prevent creating meaningless // if there is active job for this torrent prevent creating meaningless
// job that will move torrent to the same location as current one // job that will move torrent to the same location as current one
@ -4911,7 +4906,7 @@ bool SessionImpl::addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &new
} }
} }
const MoveStorageJob moveStorageJob {torrentHandle, newPath, mode}; const MoveStorageJob moveStorageJob {torrentHandle, newPath, mode, context};
m_moveStorageQueue << moveStorageJob; m_moveStorageQueue << moveStorageJob;
LogMsg(tr("Enqueued torrent move. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\"").arg(torrent->name(), currentLocation.toString(), newPath.toString())); LogMsg(tr("Enqueued torrent move. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\"").arg(torrent->name(), currentLocation.toString(), newPath.toString()));
@ -4942,7 +4937,7 @@ void SessionImpl::handleMoveTorrentStorageJobFinished(const Path &newPath)
moveTorrentStorage(m_moveStorageQueue.first()); moveTorrentStorage(m_moveStorageQueue.first());
const auto iter = std::find_if(m_moveStorageQueue.cbegin(), m_moveStorageQueue.cend() const auto iter = std::find_if(m_moveStorageQueue.cbegin(), m_moveStorageQueue.cend()
, [&finishedJob](const MoveStorageJob &job) , [&finishedJob](const MoveStorageJob &job)
{ {
return job.torrentHandle == finishedJob.torrentHandle; return job.torrentHandle == finishedJob.torrentHandle;
}); });
@ -4952,7 +4947,7 @@ void SessionImpl::handleMoveTorrentStorageJobFinished(const Path &newPath)
TorrentImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash()); TorrentImpl *torrent = m_torrents.value(finishedJob.torrentHandle.info_hash());
if (torrent) if (torrent)
{ {
torrent->handleMoveStorageJobFinished(newPath, torrentHasOutstandingJob); torrent->handleMoveStorageJobFinished(newPath, finishedJob.context, torrentHasOutstandingJob);
} }
else if (!torrentHasOutstandingJob) else if (!torrentHasOutstandingJob)
{ {
@ -5839,7 +5834,7 @@ void SessionImpl::handleStorageMovedFailedAlert(const lt::storage_moved_failed_a
TorrentImpl *torrent = m_torrents.value(id); TorrentImpl *torrent = m_torrents.value(id);
const QString torrentName = (torrent ? torrent->name() : id.toString()); const QString torrentName = (torrent ? torrent->name() : id.toString());
const Path currentLocation = (torrent ? torrent->actualStorageLocation() const Path currentLocation = (torrent ? torrent->actualStorageLocation()
: Path(p->handle.status(lt::torrent_handle::query_save_path).save_path)); : Path(p->handle.status(lt::torrent_handle::query_save_path).save_path));
const QString errorMessage = QString::fromStdString(p->message()); const QString errorMessage = QString::fromStdString(p->message());
LogMsg(tr("Failed to move torrent. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\". Reason: \"%4\"") LogMsg(tr("Failed to move torrent. Torrent: \"%1\". Source: \"%2\". Destination: \"%3\". Reason: \"%4\"")
.arg(torrentName, currentLocation.toString(), currentJob.path.toString(), errorMessage), Log::WARNING); .arg(torrentName, currentLocation.toString(), currentJob.path.toString(), errorMessage), Log::WARNING);

4
src/base/bittorrent/sessionimpl.h

@ -87,6 +87,7 @@ namespace BitTorrent
struct LoadTorrentParams; struct LoadTorrentParams;
enum class MoveStorageMode; enum class MoveStorageMode;
enum class MoveStorageContext;
struct SessionMetricIndices struct SessionMetricIndices
{ {
@ -439,7 +440,7 @@ namespace BitTorrent
void handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data); void handleTorrentResumeDataReady(TorrentImpl *const torrent, const LoadTorrentParams &data);
void handleTorrentInfoHashChanged(TorrentImpl *torrent, const InfoHash &prevInfoHash); void handleTorrentInfoHashChanged(TorrentImpl *torrent, const InfoHash &prevInfoHash);
bool addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, MoveStorageMode mode); bool addMoveTorrentStorageJob(TorrentImpl *torrent, const Path &newPath, MoveStorageMode mode, MoveStorageContext context);
void findIncompleteFiles(const TorrentInfo &torrentInfo, const Path &savePath void findIncompleteFiles(const TorrentInfo &torrentInfo, const Path &savePath
, const Path &downloadPath, const PathList &filePaths = {}) const; , const Path &downloadPath, const PathList &filePaths = {}) const;
@ -482,6 +483,7 @@ namespace BitTorrent
lt::torrent_handle torrentHandle; lt::torrent_handle torrentHandle;
Path path; Path path;
MoveStorageMode mode; MoveStorageMode mode;
MoveStorageContext context;
}; };
struct RemovingTorrentData struct RemovingTorrentData

51
src/base/bittorrent/torrentimpl.cpp

@ -431,12 +431,16 @@ void TorrentImpl::setSavePath(const Path &path)
if (resolvedPath == savePath()) if (resolvedPath == savePath())
return; return;
m_savePath = resolvedPath;
m_session->handleTorrentNeedSaveResumeData(this);
if (isFinished() || m_hasFinishedStatus || downloadPath().isEmpty()) if (isFinished() || m_hasFinishedStatus || downloadPath().isEmpty())
moveStorage(savePath(), MoveStorageMode::KeepExistingFiles); {
moveStorage(resolvedPath, MoveStorageContext::ChangeSavePath);
}
else
{
m_savePath = resolvedPath;
m_session->handleTorrentSavePathChanged(this);
m_session->handleTorrentNeedSaveResumeData(this);
}
} }
Path TorrentImpl::downloadPath() const Path TorrentImpl::downloadPath() const
@ -454,13 +458,17 @@ void TorrentImpl::setDownloadPath(const Path &path)
if (resolvedPath == m_downloadPath) if (resolvedPath == m_downloadPath)
return; return;
m_downloadPath = resolvedPath;
m_session->handleTorrentNeedSaveResumeData(this);
const bool isIncomplete = !(isFinished() || m_hasFinishedStatus); const bool isIncomplete = !(isFinished() || m_hasFinishedStatus);
if (isIncomplete) if (isIncomplete)
moveStorage((m_downloadPath.isEmpty() ? savePath() : m_downloadPath), MoveStorageMode::KeepExistingFiles); {
moveStorage((resolvedPath.isEmpty() ? savePath() : resolvedPath), MoveStorageContext::ChangeDownloadPath);
}
else
{
m_downloadPath = resolvedPath;
m_session->handleTorrentSavePathChanged(this);
m_session->handleTorrentNeedSaveResumeData(this);
}
} }
Path TorrentImpl::rootPath() const Path TorrentImpl::rootPath() const
@ -1754,7 +1762,7 @@ void TorrentImpl::resume(const TorrentOperatingMode mode)
} }
} }
void TorrentImpl::moveStorage(const Path &newPath, const MoveStorageMode mode) void TorrentImpl::moveStorage(const Path &newPath, const MoveStorageContext context)
{ {
if (!hasMetadata()) if (!hasMetadata())
{ {
@ -1762,7 +1770,9 @@ void TorrentImpl::moveStorage(const Path &newPath, const MoveStorageMode mode)
return; return;
} }
if (m_session->addMoveTorrentStorageJob(this, newPath, mode)) const auto mode = (context == MoveStorageContext::AdjustCurrentLocation)
? MoveStorageMode::Overwrite : MoveStorageMode::KeepExistingFiles;
if (m_session->addMoveTorrentStorageJob(this, newPath, mode, context))
{ {
m_storageIsMoving = true; m_storageIsMoving = true;
updateState(); updateState();
@ -1784,16 +1794,17 @@ void TorrentImpl::handleStateUpdate(const lt::torrent_status &nativeStatus)
updateStatus(nativeStatus); updateStatus(nativeStatus);
} }
void TorrentImpl::handleMoveStorageJobFinished(const Path &path, const bool hasOutstandingJob) void TorrentImpl::handleMoveStorageJobFinished(const Path &path, const MoveStorageContext context, const bool hasOutstandingJob)
{ {
m_session->handleTorrentNeedSaveResumeData(this); if (context == MoveStorageContext::ChangeSavePath)
m_savePath = path;
else if (context == MoveStorageContext::ChangeDownloadPath)
m_downloadPath = path;
m_storageIsMoving = hasOutstandingJob; m_storageIsMoving = hasOutstandingJob;
m_nativeStatus.save_path = path.toString().toStdString();
if (actualStorageLocation() != path) m_session->handleTorrentSavePathChanged(this);
{ m_session->handleTorrentNeedSaveResumeData(this);
m_nativeStatus.save_path = path.toString().toStdString();
m_session->handleTorrentSavePathChanged(this);
}
if (!m_storageIsMoving) if (!m_storageIsMoving)
{ {
@ -2221,7 +2232,7 @@ void TorrentImpl::adjustStorageLocation()
const Path targetPath = ((isFinished() || m_hasFinishedStatus || downloadPath.isEmpty()) ? savePath() : downloadPath); const Path targetPath = ((isFinished() || m_hasFinishedStatus || downloadPath.isEmpty()) ? savePath() : downloadPath);
if ((targetPath != actualStorageLocation()) || isMoveInProgress()) if ((targetPath != actualStorageLocation()) || isMoveInProgress())
moveStorage(targetPath, MoveStorageMode::Overwrite); moveStorage(targetPath, MoveStorageContext::AdjustCurrentLocation);
} }
void TorrentImpl::doRenameFile(int index, const Path &path) void TorrentImpl::doRenameFile(int index, const Path &path)

11
src/base/bittorrent/torrentimpl.h

@ -68,6 +68,13 @@ namespace BitTorrent
Overwrite Overwrite
}; };
enum class MoveStorageContext
{
AdjustCurrentLocation,
ChangeSavePath,
ChangeDownloadPath
};
enum class MaintenanceJob enum class MaintenanceJob
{ {
None, None,
@ -252,7 +259,7 @@ namespace BitTorrent
void handleCategoryOptionsChanged(); void handleCategoryOptionsChanged();
void handleAppendExtensionToggled(); void handleAppendExtensionToggled();
void saveResumeData(lt::resume_data_flags_t flags = {}); void saveResumeData(lt::resume_data_flags_t flags = {});
void handleMoveStorageJobFinished(const Path &path, bool hasOutstandingJob); void handleMoveStorageJobFinished(const Path &path, MoveStorageContext context, bool hasOutstandingJob);
void fileSearchFinished(const Path &savePath, const PathList &fileNames); void fileSearchFinished(const Path &savePath, const PathList &fileNames);
TrackerEntry updateTrackerEntry(const lt::announce_entry &announceEntry, const QMap<TrackerEntry::Endpoint, int> &updateInfo); TrackerEntry updateTrackerEntry(const lt::announce_entry &announceEntry, const QMap<TrackerEntry::Endpoint, int> &updateInfo);
@ -289,7 +296,7 @@ namespace BitTorrent
Path wantedActualPath(int index, const Path &path) const; Path wantedActualPath(int index, const Path &path) const;
void adjustStorageLocation(); void adjustStorageLocation();
void doRenameFile(int index, const Path &path); void doRenameFile(int index, const Path &path);
void moveStorage(const Path &newPath, MoveStorageMode mode); void moveStorage(const Path &newPath, MoveStorageContext context);
void manageIncompleteFiles(); void manageIncompleteFiles();
void applyFirstLastPiecePriority(bool enabled); void applyFirstLastPiecePriority(bool enabled);

Loading…
Cancel
Save