From a5780dd66ca45fbbd0f12218a12f774f7a7bb4e6 Mon Sep 17 00:00:00 2001 From: "Vladimir Golovnev (qlassez)" Date: Wed, 16 Dec 2015 17:08:27 +0300 Subject: [PATCH] Switch to using previous fastresume file names --- src/app/upgrade.h | 78 ++++++++++++------- .../private/resumedatasavingmanager.cpp | 9 +-- .../private/resumedatasavingmanager.h | 2 +- src/base/bittorrent/session.cpp | 75 ++++++++++-------- src/base/bittorrent/torrenthandle.cpp | 1 + 5 files changed, 96 insertions(+), 69 deletions(-) diff --git a/src/app/upgrade.h b/src/app/upgrade.h index 82ea229fb..c92af216c 100644 --- a/src/app/upgrade.h +++ b/src/app/upgrade.h @@ -36,6 +36,7 @@ #include #include #include +#include #ifndef DISABLE_GUI #include #endif @@ -76,7 +77,7 @@ bool userAcceptsUpgrade() return false; } -bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent, int &maxPrio) +bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent = QVariantHash()) { QFile file1(filepath); if (!file1.open(QIODevice::ReadOnly)) @@ -93,19 +94,32 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent, libtorrent::entry fastNew; fastNew = fastOld; - int priority = fastOld.dict_find_int_value("qBt-queuePosition"); - if (priority > maxPrio) - maxPrio = priority; + bool v3_3 = false; + int queuePosition = 0; + QString outFilePath = filepath; + QRegExp rx(QLatin1String("([A-Fa-f0-9]{40})\\.fastresume\\.(\\d+)$")); + if (rx.indexIn(filepath) != -1) { + // old v3.3.x format + queuePosition = rx.cap(2).toInt(); + v3_3 = true; + outFilePath.replace(QRegExp("\\.\\d+$"), ""); + } + else { + queuePosition = fastOld.dict_find_int_value("qBt-queuePosition", 0); + fastNew["qBt-name"] = Utils::String::toStdString(oldTorrent.value("name").toString()); + fastNew["qBt-tempPathDisabled"] = false; + } - fastNew["qBt-name"] = Utils::String::toStdString(oldTorrent.value("name").toString()); - fastNew["qBt-tempPathDisabled"] = false; + // in versions < 3.3 we have -1 for seeding torrents, so we convert it to 0 + fastNew["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0); - QFile file2(QString("%1.%2").arg(filepath).arg(priority > 0 ? priority : 0)); + QFile file2(outFilePath); QVector out; libtorrent::bencode(std::back_inserter(out), fastNew); if (file2.open(QIODevice::WriteOnly)) { if (file2.write(&out[0], out.size()) == out.size()) { - Utils::Fs::forceRemove(filepath); + if (v3_3) + Utils::Fs::forceRemove(filepath); return true; } } @@ -118,26 +132,35 @@ bool upgrade(bool ask = true) // Move RSS cookies to common storage Preferences::instance()->moveRSSCookies(); + QString backupFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + "BT_backup"); + QDir backupFolderDir(backupFolderPath); + + // **************************************************************************************** + // Silently converts old v3.3.x .fastresume files + QStringList backupFiles_3_3 = backupFolderDir.entryList( + QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted); + foreach (const QString &backupFile, backupFiles_3_3) + upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile)); + // **************************************************************************************** + QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume"); QString oldResumeFilename = oldResumeSettings->fileName(); QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash(); delete oldResumeSettings; - bool oldResumeWasEmpty = oldResumeData.isEmpty(); - if (oldResumeWasEmpty) - Utils::Fs::forceRemove(oldResumeFilename); + if (oldResumeData.isEmpty()) { + Utils::Fs::forceRemove(oldResumeFilename); + return true; + } - QString backupFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + "BT_backup"); - QDir backupFolderDir(backupFolderPath); - QStringList backupFiles = backupFolderDir.entryList(QStringList() << QLatin1String("*.fastresume"), QDir::Files, QDir::Unsorted); - if (backupFiles.isEmpty() && oldResumeWasEmpty) return true; if (ask && !userAcceptsUpgrade()) return false; - int maxPrio = 0; + QStringList backupFiles = backupFolderDir.entryList( + QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted); QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); foreach (QString backupFile, backupFiles) { if (rx.indexIn(backupFile) != -1) { - if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[rx.cap(1)].toHash(), maxPrio)) + if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[rx.cap(1)].toHash())) oldResumeData.remove(rx.cap(1)); else Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING); @@ -162,7 +185,10 @@ bool upgrade(bool ask = true) resumeData["qBt-seedStatus"] = oldTorrent.value("seed").toBool(); resumeData["qBt-tempPathDisabled"] = false; - QString filename = QString("%1.fastresume.%2").arg(hash).arg(++maxPrio); + int queuePosition = oldTorrent.value("priority", 0).toInt(); + resumeData["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0); + + QString filename = QString("%1.fastresume").arg(hash); QString filepath = backupFolderDir.absoluteFilePath(filename); QFile resumeFile(filepath); @@ -173,17 +199,13 @@ bool upgrade(bool ask = true) } } - if (!oldResumeWasEmpty) { - int counter = 0; - QString backupResumeFilename = oldResumeFilename + ".bak"; - - while (QFile::exists(backupResumeFilename)) { - ++counter; - backupResumeFilename = oldResumeFilename + ".bak" + QString::number(counter); - } - - QFile::rename(oldResumeFilename, backupResumeFilename); + int counter = 0; + QString backupResumeFilename = oldResumeFilename + ".bak"; + while (QFile::exists(backupResumeFilename)) { + ++counter; + backupResumeFilename = oldResumeFilename + ".bak" + QString::number(counter); } + QFile::rename(oldResumeFilename, backupResumeFilename); return true; } diff --git a/src/base/bittorrent/private/resumedatasavingmanager.cpp b/src/base/bittorrent/private/resumedatasavingmanager.cpp index 17928eaff..c32a1f65a 100644 --- a/src/base/bittorrent/private/resumedatasavingmanager.cpp +++ b/src/base/bittorrent/private/resumedatasavingmanager.cpp @@ -37,14 +37,9 @@ ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath { } -void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data, int priority) const +void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data) const { - QStringList filters(QString("%1.fastresume.*").arg(infoHash)); - const QStringList files = m_resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted); - foreach (const QString &file, files) - Utils::Fs::forceRemove(m_resumeDataDir.absoluteFilePath(file)); - - QString filename = QString("%1.fastresume.%2").arg(infoHash).arg(priority); + QString filename = QString("%1.fastresume").arg(infoHash); QString filepath = m_resumeDataDir.absoluteFilePath(filename); qDebug() << "Saving resume data in" << filepath; diff --git a/src/base/bittorrent/private/resumedatasavingmanager.h b/src/base/bittorrent/private/resumedatasavingmanager.h index dae12d40a..08bcfb0e2 100644 --- a/src/base/bittorrent/private/resumedatasavingmanager.h +++ b/src/base/bittorrent/private/resumedatasavingmanager.h @@ -41,7 +41,7 @@ public: explicit ResumeDataSavingManager(const QString &resumeFolderPath); public slots: - void saveResumeData(QString infoHash, QByteArray data, int priority) const; + void saveResumeData(QString infoHash, QByteArray data) const; private: QDir m_resumeDataDir; diff --git a/src/base/bittorrent/session.cpp b/src/base/bittorrent/session.cpp index 50b3a1964..22c6ca099 100644 --- a/src/base/bittorrent/session.cpp +++ b/src/base/bittorrent/session.cpp @@ -97,7 +97,7 @@ namespace libt = libtorrent; using namespace BitTorrent; static bool readFile(const QString &path, QByteArray &buf); -static bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, MagnetUri &magnetUri); +static bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, int &prio, MagnetUri &magnetUri); static void torrentQueuePositionUp(const libt::torrent_handle &handle); static void torrentQueuePositionDown(const libt::torrent_handle &handle); @@ -1729,8 +1729,7 @@ void Session::handleTorrentResumeDataReady(TorrentHandle *const torrent, const l libt::bencode(std::back_inserter(out), data); QMetaObject::invokeMethod(m_resumeDataSavingManager, "saveResumeData", - Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out), - Q_ARG(int, torrent->queuePosition())); + Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out)); } void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent) @@ -1897,48 +1896,56 @@ void Session::startUpTorrents() const QDir resumeDataDir(m_resumeFolderPath); QStringList fastresumes = resumeDataDir.entryList( - QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted); - - typedef QPair PrioHashPair; - typedef std::vector PrioHashVector; - typedef std::greater PrioHashGreater; - std::priority_queue torrentQueue; - // Fastresume file name format: - // .fastresume. - // E.g.: - // fc8a15a2faf2734dbb1dc5f7afdc5c9beaeb1f59.fastresume.2 - QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume\\.(\\d+)$")); - foreach (const QString &fastresume, fastresumes) { - if (rx.indexIn(fastresume) != -1) { - PrioHashPair p = qMakePair(rx.cap(2).toInt(), rx.cap(1)); - torrentQueue.push(p); - } - } + QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted); QString filePath; Logger *const logger = Logger::instance(); + typedef struct + { + QString hash; + MagnetUri magnetUri; + AddTorrentData addTorrentData; + QByteArray data; + } TorrentResumeData; + qDebug("Starting up torrents"); - qDebug("Priority queue size: %ld", (long)torrentQueue.size()); + qDebug("Queue size: %d", fastresumes.size()); // Resume downloads - while (!torrentQueue.empty()) { - const int prio = torrentQueue.top().first; - const QString hash = torrentQueue.top().second; - torrentQueue.pop(); + QMap queuedResumeData; + QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$")); + foreach (const QString &fastresumeName, fastresumes) { + if (rx.indexIn(fastresumeName) == -1) continue; + QString hash = rx.cap(1); QString fastresumePath = - resumeDataDir.absoluteFilePath(QString("%1.fastresume.%2").arg(hash).arg(prio)); + resumeDataDir.absoluteFilePath(fastresumeName); QByteArray data; AddTorrentData resumeData; MagnetUri magnetUri; - if (readFile(fastresumePath, data) && loadTorrentResumeData(data, resumeData, magnetUri)) { - filePath = resumeDataDir.filePath(QString("%1.torrent").arg(hash)); - qDebug("Starting up torrent %s ...", qPrintable(hash)); - if (!addTorrent_impl(resumeData, magnetUri, TorrentInfo::loadFromFile(filePath), data)) - logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.") - .arg(Utils::Fs::toNativePath(hash)), Log::CRITICAL); + int queuePosition; + if (readFile(fastresumePath, data) && loadTorrentResumeData(data, resumeData, queuePosition, magnetUri)) { + if (queuePosition == 0) { + filePath = resumeDataDir.filePath(QString("%1.torrent").arg(hash)); + qDebug("Starting up torrent %s ...", qPrintable(hash)); + if (!addTorrent_impl(resumeData, magnetUri, TorrentInfo::loadFromFile(filePath), data)) + logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.") + .arg(hash), Log::CRITICAL); + } + else { + queuedResumeData[queuePosition] = { hash, magnetUri, resumeData, data }; + } } } + + // starting up downloading torrents (queue position > 0) + foreach (const TorrentResumeData &torrentResumeData, queuedResumeData) { + filePath = resumeDataDir.filePath(QString("%1.torrent").arg(torrentResumeData.hash)); + qDebug("Starting up torrent %s ...", qPrintable(torrentResumeData.hash)); + if (!addTorrent_impl(torrentResumeData.addTorrentData, torrentResumeData.magnetUri, TorrentInfo::loadFromFile(filePath), torrentResumeData.data)) + logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.") + .arg(torrentResumeData.hash), Log::CRITICAL); + } } quint64 Session::getAlltimeDL() const @@ -2351,7 +2358,7 @@ bool readFile(const QString &path, QByteArray &buf) return true; } -bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, MagnetUri &magnetUri) +bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, int &prio, MagnetUri &magnetUri) { out = AddTorrentData(); out.resumed = true; @@ -2373,6 +2380,8 @@ bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, MagnetUr out.addPaused = fast.dict_find_int_value("qBt-paused"); out.addForced = fast.dict_find_int_value("qBt-forced"); + prio = fast.dict_find_int_value("qBt-queuePosition"); + return true; } diff --git a/src/base/bittorrent/torrenthandle.cpp b/src/base/bittorrent/torrenthandle.cpp index 057f83a27..8aee9fff6 100644 --- a/src/base/bittorrent/torrenthandle.cpp +++ b/src/base/bittorrent/torrenthandle.cpp @@ -1432,6 +1432,7 @@ void TorrentHandle::handleSaveResumeDataAlert(libtorrent::save_resume_data_alert resumeData["qBt-name"] = Utils::String::toStdString(m_name); resumeData["qBt-seedStatus"] = m_hasSeedStatus; resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled; + resumeData["qBt-queuePosition"] = queuePosition(); m_session->handleTorrentResumeDataReady(this, resumeData); }