Browse Source

Improve torrent initialization

Don't post "torrent resumed" event when torrent starts in "resumed"
state.
Fix confusing names. Now "resumed torrent" means "unpaused torrent"
only. When we load previously added torrent it is called "restored
torrent".
adaptive-webui-19844
Vladimir Golovnev (Glassez) 7 years ago
parent
commit
cd44ab2fc6
No known key found for this signature in database
GPG Key ID: 52A2C7DEE2DFA6F7
  1. 113
      src/base/bittorrent/session.cpp
  2. 6
      src/base/bittorrent/session.h
  3. 68
      src/base/bittorrent/torrenthandle.cpp
  4. 20
      src/base/bittorrent/torrenthandle.h

113
src/base/bittorrent/session.cpp

@ -111,7 +111,7 @@ using namespace BitTorrent; @@ -111,7 +111,7 @@ using namespace BitTorrent;
namespace
{
bool readFile(const QString &path, QByteArray &buf);
bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &torrentData, int &prio, MagnetUri &magnetUri);
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri);
void torrentQueuePositionUp(const libt::torrent_handle &handle);
void torrentQueuePositionDown(const libt::torrent_handle &handle);
@ -2110,15 +2110,15 @@ bool Session::addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams @@ -2110,15 +2110,15 @@ bool Session::addTorrent(const TorrentInfo &torrentInfo, const AddTorrentParams
}
// Add a torrent to the BitTorrent session
bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri,
bool Session::addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
TorrentInfo torrentInfo, const QByteArray &fastresumeData)
{
addData.savePath = normalizeSavePath(addData.savePath, "");
params.savePath = normalizeSavePath(params.savePath, "");
if (!addData.category.isEmpty()) {
if (!m_categories.contains(addData.category) && !addCategory(addData.category)) {
qWarning() << "Couldn't create category" << addData.category;
addData.category = "";
if (!params.category.isEmpty()) {
if (!m_categories.contains(params.category) && !addCategory(params.category)) {
qWarning() << "Couldn't create category" << params.category;
params.category = "";
}
}
@ -2127,10 +2127,10 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri @@ -2127,10 +2127,10 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri
std::vector<boost::uint8_t> filePriorities;
QString savePath;
if (addData.savePath.isEmpty()) // using Automatic mode
savePath = categorySavePath(addData.category);
if (params.savePath.isEmpty()) // using Automatic mode
savePath = categorySavePath(params.category);
else // using Manual mode
savePath = addData.savePath;
savePath = params.savePath;
bool fromMagnetUri = magnetUri.isValid();
if (fromMagnetUri) {
@ -2151,7 +2151,7 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri @@ -2151,7 +2151,7 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri
adjustLimits();
// use common 2nd step of torrent addition
m_addingTorrents.insert(hash, addData);
m_addingTorrents.insert(hash, params);
createTorrentHandle(handle);
return true;
}
@ -2159,23 +2159,23 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri @@ -2159,23 +2159,23 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri
p = magnetUri.addTorrentParams();
}
else if (torrentInfo.isValid()) {
if (!addData.resumed) {
if (!addData.hasRootFolder)
if (!params.restored) {
if (!params.hasRootFolder)
torrentInfo.stripRootFolder();
// Metadata
if (!addData.hasSeedStatus)
if (!params.hasSeedStatus)
findIncompleteFiles(torrentInfo, savePath);
// if torrent name wasn't explicitly set we handle the case of
// initial renaming of torrent content and rename torrent accordingly
if (addData.name.isEmpty()) {
if (params.name.isEmpty()) {
QString contentName = torrentInfo.rootFolder();
if (contentName.isEmpty() && (torrentInfo.filesCount() == 1))
contentName = torrentInfo.fileName(0);
if (!contentName.isEmpty() && (contentName != torrentInfo.name()))
addData.name = contentName;
params.name = contentName;
}
}
@ -2189,13 +2189,13 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri @@ -2189,13 +2189,13 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri
return false;
}
if (addData.resumed && !fromMagnetUri) {
if (params.restored && !fromMagnetUri) {
// Set torrent fast resume data
p.resume_data = {fastresumeData.constData(), fastresumeData.constData() + fastresumeData.size()};
p.flags |= libt::add_torrent_params::flag_use_resume_save_path;
}
else {
foreach (int prio, addData.filePriorities)
foreach (int prio, params.filePriorities)
filePriorities.push_back(prio);
p.file_priorities = filePriorities;
}
@ -2228,7 +2228,7 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri @@ -2228,7 +2228,7 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri
// Seeding mode
// Skip checking and directly start seeding (new in libtorrent v0.15)
if (addData.skipChecking)
if (params.skipChecking)
p.flags |= libt::add_torrent_params::flag_seed_mode;
else
p.flags &= ~libt::add_torrent_params::flag_seed_mode;
@ -2237,10 +2237,10 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri @@ -2237,10 +2237,10 @@ bool Session::addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri
p.max_connections = maxConnectionsPerTorrent();
p.max_uploads = maxUploadsPerTorrent();
p.save_path = Utils::Fs::toNativePath(savePath).toStdString();
p.upload_limit = addData.uploadLimit;
p.download_limit = addData.downloadLimit;
p.upload_limit = params.uploadLimit;
p.download_limit = params.downloadLimit;
m_addingTorrents.insert(hash, addData);
m_addingTorrents.insert(hash, params);
// Adding torrent to BitTorrent session
m_nativeSession->async_add_torrent(p);
return true;
@ -3849,7 +3849,7 @@ void Session::startUpTorrents() @@ -3849,7 +3849,7 @@ void Session::startUpTorrents()
{
QString hash;
MagnetUri magnetUri;
AddTorrentData addTorrentData;
CreateTorrentParams addTorrentData;
QByteArray data;
} TorrentResumeData;
@ -3882,12 +3882,12 @@ void Session::startUpTorrents() @@ -3882,12 +3882,12 @@ void Session::startUpTorrents()
QString hash = rxMatch.captured(1);
QString fastresumePath = resumeDataDir.absoluteFilePath(fastresumeName);
QByteArray data;
AddTorrentData resumeData;
CreateTorrentParams torrentParams;
MagnetUri magnetUri;
int queuePosition;
if (readFile(fastresumePath, data) && loadTorrentResumeData(data, resumeData, queuePosition, magnetUri)) {
if (readFile(fastresumePath, data) && loadTorrentResumeData(data, torrentParams, queuePosition, magnetUri)) {
if (queuePosition <= nextQueuePosition) {
startupTorrent({ hash, magnetUri, resumeData, data });
startupTorrent({ hash, magnetUri, torrentParams, data });
if (queuePosition == nextQueuePosition) {
++nextQueuePosition;
@ -3904,7 +3904,7 @@ void Session::startUpTorrents() @@ -3904,7 +3904,7 @@ void Session::startUpTorrents()
if (q != queuePosition) {
++numOfRemappedFiles;
}
queuedResumeData[q] = {hash, magnetUri, resumeData, data};
queuedResumeData[q] = {hash, magnetUri, torrentParams, data};
}
}
}
@ -4108,25 +4108,19 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle) @@ -4108,25 +4108,19 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle)
// Magnet added for preload its metadata
if (!m_addingTorrents.contains(nativeHandle.info_hash())) return;
AddTorrentData data = m_addingTorrents.take(nativeHandle.info_hash());
CreateTorrentParams params = m_addingTorrents.take(nativeHandle.info_hash());
TorrentHandle *const torrent = new TorrentHandle(this, nativeHandle, data);
TorrentHandle *const torrent = new TorrentHandle(this, nativeHandle, params);
m_torrents.insert(torrent->hash(), torrent);
Logger *const logger = Logger::instance();
bool fromMagnetUri = !torrent->hasMetadata();
if (data.resumed) {
if (fromMagnetUri && !data.addPaused)
torrent->resume(data.addForced);
logger->addMessage(tr("'%1' resumed. (fast resume)", "'torrent name' was resumed. (fast resume)")
.arg(torrent->name()));
if (params.restored) {
logger->addMessage(tr("'%1' restored.", "'torrent name' restored.").arg(torrent->name()));
}
else {
qDebug("This is a NEW torrent (first time)...");
// The following is useless for newly added magnet
if (!fromMagnetUri) {
// Backup torrent file
@ -4145,9 +4139,6 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle) @@ -4145,9 +4139,6 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle)
if (isAddTrackersEnabled() && !torrent->isPrivate())
torrent->addTrackers(m_additionalTrackerList);
// Start torrent because it was added in paused state
if (!data.addPaused)
torrent->resume();
logger->addMessage(tr("'%1' added to download list.", "'torrent name' was added to download list.")
.arg(torrent->name()));
@ -4163,7 +4154,7 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle) @@ -4163,7 +4154,7 @@ void Session::createTorrentHandle(const libt::torrent_handle &nativeHandle)
// Send torrent addition signal
emit torrentAdded(torrent);
// Send new torrent signal
if (!data.resumed)
if (!params.restored)
emit torrentNew(torrent);
}
@ -4513,11 +4504,11 @@ namespace @@ -4513,11 +4504,11 @@ namespace
return true;
}
bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &torrentData, int &prio, MagnetUri &magnetUri)
bool loadTorrentResumeData(const QByteArray &data, CreateTorrentParams &torrentParams, int &prio, MagnetUri &magnetUri)
{
torrentData = AddTorrentData();
torrentData.resumed = true;
torrentData.skipChecking = false;
torrentParams = CreateTorrentParams();
torrentParams.restored = true;
torrentParams.skipChecking = false;
libt::error_code ec;
#if LIBTORRENT_VERSION_NUM < 10100
@ -4530,36 +4521,36 @@ namespace @@ -4530,36 +4521,36 @@ namespace
if (ec || (fast.type() != libt::bdecode_node::dict_t)) return false;
#endif
torrentData.savePath = Profile::instance().fromPortablePath(
torrentParams.savePath = Profile::instance().fromPortablePath(
Utils::Fs::fromNativePath(QString::fromStdString(fast.dict_find_string_value("qBt-savePath"))));
std::string ratioLimitString = fast.dict_find_string_value("qBt-ratioLimit");
if (ratioLimitString.empty())
torrentData.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
torrentParams.ratioLimit = fast.dict_find_int_value("qBt-ratioLimit", TorrentHandle::USE_GLOBAL_RATIO * 1000) / 1000.0;
else
torrentData.ratioLimit = QString::fromStdString(ratioLimitString).toDouble();
torrentData.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
torrentParams.ratioLimit = QString::fromStdString(ratioLimitString).toDouble();
torrentParams.seedingTimeLimit = fast.dict_find_int_value("qBt-seedingTimeLimit", TorrentHandle::USE_GLOBAL_SEEDING_TIME);
// **************************************************************************************
// Workaround to convert legacy label to category
// TODO: Should be removed in future
torrentData.category = QString::fromStdString(fast.dict_find_string_value("qBt-label"));
if (torrentData.category.isEmpty())
torrentParams.category = QString::fromStdString(fast.dict_find_string_value("qBt-label"));
if (torrentParams.category.isEmpty())
// **************************************************************************************
torrentData.category = QString::fromStdString(fast.dict_find_string_value("qBt-category"));
torrentParams.category = QString::fromStdString(fast.dict_find_string_value("qBt-category"));
// auto because the return type depends on the #if above.
const auto tagsEntry = fast.dict_find_list("qBt-tags");
if (isList(tagsEntry))
torrentData.tags = entryListToSet(tagsEntry);
torrentData.name = QString::fromStdString(fast.dict_find_string_value("qBt-name"));
torrentData.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
torrentData.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
torrentData.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder");
torrentParams.tags = entryListToSet(tagsEntry);
torrentParams.name = QString::fromStdString(fast.dict_find_string_value("qBt-name"));
torrentParams.hasSeedStatus = fast.dict_find_int_value("qBt-seedStatus");
torrentParams.disableTempPath = fast.dict_find_int_value("qBt-tempPathDisabled");
torrentParams.hasRootFolder = fast.dict_find_int_value("qBt-hasRootFolder");
magnetUri = MagnetUri(QString::fromStdString(fast.dict_find_string_value("qBt-magnetUri")));
torrentData.addPaused = fast.dict_find_int_value("qBt-paused");
torrentData.addForced = fast.dict_find_int_value("qBt-forced");
torrentData.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority");
torrentData.sequential = fast.dict_find_int_value("qBt-sequential");
torrentParams.paused = fast.dict_find_int_value("qBt-paused");
torrentParams.forced = fast.dict_find_int_value("qBt-forced");
torrentParams.firstLastPiecePriority = fast.dict_find_int_value("qBt-firstLastPiecePriority");
torrentParams.sequential = fast.dict_find_int_value("qBt-sequential");
prio = fast.dict_find_int_value("qBt-queuePosition");

6
src/base/bittorrent/session.h

@ -138,7 +138,7 @@ namespace BitTorrent @@ -138,7 +138,7 @@ namespace BitTorrent
class Tracker;
class MagnetUri;
class TrackerEntry;
struct AddTorrentData;
struct CreateTorrentParams;
struct TorrentStatusReport
{
@ -598,7 +598,7 @@ namespace BitTorrent @@ -598,7 +598,7 @@ namespace BitTorrent
void enableIPFilter();
void disableIPFilter();
bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri,
bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
TorrentInfo torrentInfo = TorrentInfo(),
const QByteArray &fastresumeData = QByteArray());
bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const;
@ -758,7 +758,7 @@ namespace BitTorrent @@ -758,7 +758,7 @@ namespace BitTorrent
QHash<InfoHash, TorrentInfo> m_loadedMetadata;
QHash<InfoHash, TorrentHandle *> m_torrents;
QHash<InfoHash, AddTorrentData> m_addingTorrents;
QHash<InfoHash, CreateTorrentParams> m_addingTorrents;
QHash<QString, AddTorrentParams> m_downloadedTorrents;
QHash<InfoHash, RemovingTorrentData> m_removingTorrents;
TorrentStatusReport m_torrentStatusReport;

68
src/base/bittorrent/torrenthandle.cpp

@ -85,16 +85,16 @@ namespace @@ -85,16 +85,16 @@ namespace
// AddTorrentData
AddTorrentData::AddTorrentData()
: resumed(false)
CreateTorrentParams::CreateTorrentParams()
: restored(false)
, disableTempPath(false)
, sequential(false)
, firstLastPiecePriority(false)
, hasSeedStatus(false)
, skipChecking(false)
, hasRootFolder(true)
, addForced(false)
, addPaused(false)
, forced(false)
, paused(false)
, uploadLimit(-1)
, downloadLimit(-1)
, ratioLimit(TorrentHandle::USE_GLOBAL_RATIO)
@ -102,8 +102,8 @@ AddTorrentData::AddTorrentData() @@ -102,8 +102,8 @@ AddTorrentData::AddTorrentData()
{
}
AddTorrentData::AddTorrentData(const AddTorrentParams &params)
: resumed(false)
CreateTorrentParams::CreateTorrentParams(const AddTorrentParams &params)
: restored(false)
, name(params.name)
, category(params.category)
, tags(params.tags)
@ -116,8 +116,8 @@ AddTorrentData::AddTorrentData(const AddTorrentParams &params) @@ -116,8 +116,8 @@ AddTorrentData::AddTorrentData(const AddTorrentParams &params)
, hasRootFolder(params.createSubfolder == TriStateBool::Undefined
? Session::instance()->isCreateTorrentSubfolder()
: params.createSubfolder == TriStateBool::True)
, addForced(params.addForced == TriStateBool::True)
, addPaused(params.addPaused == TriStateBool::Undefined
, forced(params.addForced == TriStateBool::True)
, paused(params.addPaused == TriStateBool::Undefined
? Session::instance()->isAddTorrentPaused()
: params.addPaused == TriStateBool::True)
, uploadLimit(params.uploadLimit)
@ -172,23 +172,23 @@ namespace @@ -172,23 +172,23 @@ namespace
}
TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
const AddTorrentData &data)
const CreateTorrentParams &params)
: QObject(session)
, m_session(session)
, m_nativeHandle(nativeHandle)
, m_state(TorrentState::Unknown)
, m_renameCount(0)
, m_useAutoTMM(data.savePath.isEmpty())
, m_name(data.name)
, m_savePath(Utils::Fs::toNativePath(data.savePath))
, m_category(data.category)
, m_tags(data.tags)
, m_hasSeedStatus(data.hasSeedStatus)
, m_ratioLimit(data.ratioLimit)
, m_seedingTimeLimit(data.seedingTimeLimit)
, m_tempPathDisabled(data.disableTempPath)
, m_useAutoTMM(params.savePath.isEmpty())
, m_name(params.name)
, m_savePath(Utils::Fs::toNativePath(params.savePath))
, m_category(params.category)
, m_tags(params.tags)
, m_hasSeedStatus(params.hasSeedStatus)
, m_ratioLimit(params.ratioLimit)
, m_seedingTimeLimit(params.seedingTimeLimit)
, m_tempPathDisabled(params.disableTempPath)
, m_hasMissingFiles(false)
, m_hasRootFolder(data.hasRootFolder)
, m_hasRootFolder(params.hasRootFolder)
, m_needsToSetFirstLastPiecePriority(false)
, m_pauseAfterRecheck(false)
{
@ -206,15 +206,29 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle @@ -206,15 +206,29 @@ TorrentHandle::TorrentHandle(Session *session, const libtorrent::torrent_handle
// download sequentially or have first/last piece priority enabled when
// its resume data was saved. These two settings are restored later. But
// if we set them to false now, both will erroneously not be restored.
if (!data.resumed || data.sequential)
setSequentialDownload(data.sequential);
if (!data.resumed || data.firstLastPiecePriority)
setFirstLastPiecePriority(data.firstLastPiecePriority);
if (!params.restored || params.sequential)
setSequentialDownload(params.sequential);
if (!params.restored || params.firstLastPiecePriority)
setFirstLastPiecePriority(params.firstLastPiecePriority);
if (!data.resumed && hasMetadata()) {
if (!params.restored && hasMetadata()) {
if (filesCount() == 1)
m_hasRootFolder = false;
}
// "started" means "all initialization has completed and torrent has started regular processing".
// When torrent added/restored in "paused" state it become "started" immediately after construction.
// When it is added/restored in "resumed" state, it become "started" after it is really resumed
// (i.e. after receiving "torrent resumed" alert).
m_started = (params.restored && hasMetadata() ? isPaused() : params.paused);
if (!m_started) {
if (!params.restored || !hasMetadata()) {
// Resume torrent because it was added in "resumed" state
// but it's actually paused during initialization
resume(params.forced);
}
}
}
TorrentHandle::~TorrentHandle() {}
@ -1589,7 +1603,11 @@ void TorrentHandle::handleTorrentPausedAlert(const libtorrent::torrent_paused_al @@ -1589,7 +1603,11 @@ void TorrentHandle::handleTorrentPausedAlert(const libtorrent::torrent_paused_al
void TorrentHandle::handleTorrentResumedAlert(const libtorrent::torrent_resumed_alert *p)
{
Q_UNUSED(p);
m_session->handleTorrentResumed(this);
if (m_started)
m_session->handleTorrentResumed(this);
else
m_started = true;
}
void TorrentHandle::handleSaveResumeDataAlert(const libtorrent::save_resume_data_alert *p)

20
src/base/bittorrent/torrenthandle.h

@ -88,10 +88,10 @@ namespace BitTorrent @@ -88,10 +88,10 @@ namespace BitTorrent
class TrackerEntry;
struct AddTorrentParams;
struct AddTorrentData
struct CreateTorrentParams
{
bool resumed;
// for both new and resumed torrents
bool restored; // is existing torrent job?
// for both new and restored torrents
QString name;
QString category;
QSet<QString> tags;
@ -102,18 +102,18 @@ namespace BitTorrent @@ -102,18 +102,18 @@ namespace BitTorrent
bool hasSeedStatus;
bool skipChecking;
bool hasRootFolder;
bool addForced;
bool addPaused;
bool forced;
bool paused;
int uploadLimit;
int downloadLimit;
// for new torrents
QVector<int> filePriorities;
// for resumed torrents
// for restored torrents
qreal ratioLimit;
int seedingTimeLimit;
AddTorrentData();
AddTorrentData(const AddTorrentParams &params);
CreateTorrentParams();
CreateTorrentParams(const AddTorrentParams &params);
};
struct TrackerInfo
@ -170,7 +170,7 @@ namespace BitTorrent @@ -170,7 +170,7 @@ namespace BitTorrent
static const int MAX_SEEDING_TIME;
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
const AddTorrentData &data);
const CreateTorrentParams &params);
~TorrentHandle();
bool isValid() const;
@ -462,6 +462,8 @@ namespace BitTorrent @@ -462,6 +462,8 @@ namespace BitTorrent
bool m_pauseAfterRecheck;
QHash<QString, TrackerInfo> m_trackerInfos;
bool m_started = false;
};
}

Loading…
Cancel
Save