Browse Source

Switch to using previous fastresume file names

adaptive-webui-19844
Vladimir Golovnev (qlassez) 9 years ago committed by Vladimir Golovnev (Glassez)
parent
commit
a5780dd66c
  1. 62
      src/app/upgrade.h
  2. 9
      src/base/bittorrent/private/resumedatasavingmanager.cpp
  3. 2
      src/base/bittorrent/private/resumedatasavingmanager.h
  4. 67
      src/base/bittorrent/session.cpp
  5. 1
      src/base/bittorrent/torrenthandle.cpp

62
src/app/upgrade.h

@ -36,6 +36,7 @@
#include <QString> #include <QString>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QRegExp>
#ifndef DISABLE_GUI #ifndef DISABLE_GUI
#include <QMessageBox> #include <QMessageBox>
#endif #endif
@ -76,7 +77,7 @@ bool userAcceptsUpgrade()
return false; return false;
} }
bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent, int &maxPrio) bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent = QVariantHash())
{ {
QFile file1(filepath); QFile file1(filepath);
if (!file1.open(QIODevice::ReadOnly)) if (!file1.open(QIODevice::ReadOnly))
@ -93,18 +94,31 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent,
libtorrent::entry fastNew; libtorrent::entry fastNew;
fastNew = fastOld; fastNew = fastOld;
int priority = fastOld.dict_find_int_value("qBt-queuePosition"); bool v3_3 = false;
if (priority > maxPrio) int queuePosition = 0;
maxPrio = priority; 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-name"] = Utils::String::toStdString(oldTorrent.value("name").toString());
fastNew["qBt-tempPathDisabled"] = false; 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<char> out; QVector<char> out;
libtorrent::bencode(std::back_inserter(out), fastNew); libtorrent::bencode(std::back_inserter(out), fastNew);
if (file2.open(QIODevice::WriteOnly)) { if (file2.open(QIODevice::WriteOnly)) {
if (file2.write(&out[0], out.size()) == out.size()) { if (file2.write(&out[0], out.size()) == out.size()) {
if (v3_3)
Utils::Fs::forceRemove(filepath); Utils::Fs::forceRemove(filepath);
return true; return true;
} }
@ -118,26 +132,35 @@ bool upgrade(bool ask = true)
// Move RSS cookies to common storage // Move RSS cookies to common storage
Preferences::instance()->moveRSSCookies(); 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"); QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume");
QString oldResumeFilename = oldResumeSettings->fileName(); QString oldResumeFilename = oldResumeSettings->fileName();
QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash(); QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash();
delete oldResumeSettings; 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; 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$")); QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
foreach (QString backupFile, backupFiles) { foreach (QString backupFile, backupFiles) {
if (rx.indexIn(backupFile) != -1) { 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)); oldResumeData.remove(rx.cap(1));
else else
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING); 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-seedStatus"] = oldTorrent.value("seed").toBool();
resumeData["qBt-tempPathDisabled"] = false; 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); QString filepath = backupFolderDir.absoluteFilePath(filename);
QFile resumeFile(filepath); QFile resumeFile(filepath);
@ -173,17 +199,13 @@ bool upgrade(bool ask = true)
} }
} }
if (!oldResumeWasEmpty) {
int counter = 0; int counter = 0;
QString backupResumeFilename = oldResumeFilename + ".bak"; QString backupResumeFilename = oldResumeFilename + ".bak";
while (QFile::exists(backupResumeFilename)) { while (QFile::exists(backupResumeFilename)) {
++counter; ++counter;
backupResumeFilename = oldResumeFilename + ".bak" + QString::number(counter); backupResumeFilename = oldResumeFilename + ".bak" + QString::number(counter);
} }
QFile::rename(oldResumeFilename, backupResumeFilename); QFile::rename(oldResumeFilename, backupResumeFilename);
}
return true; return true;
} }

9
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)); QString filename = 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 filepath = m_resumeDataDir.absoluteFilePath(filename); QString filepath = m_resumeDataDir.absoluteFilePath(filename);
qDebug() << "Saving resume data in" << filepath; qDebug() << "Saving resume data in" << filepath;

2
src/base/bittorrent/private/resumedatasavingmanager.h

@ -41,7 +41,7 @@ public:
explicit ResumeDataSavingManager(const QString &resumeFolderPath); explicit ResumeDataSavingManager(const QString &resumeFolderPath);
public slots: public slots:
void saveResumeData(QString infoHash, QByteArray data, int priority) const; void saveResumeData(QString infoHash, QByteArray data) const;
private: private:
QDir m_resumeDataDir; QDir m_resumeDataDir;

67
src/base/bittorrent/session.cpp

@ -97,7 +97,7 @@ namespace libt = libtorrent;
using namespace BitTorrent; using namespace BitTorrent;
static bool readFile(const QString &path, QByteArray &buf); 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 torrentQueuePositionUp(const libt::torrent_handle &handle);
static void torrentQueuePositionDown(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); libt::bencode(std::back_inserter(out), data);
QMetaObject::invokeMethod(m_resumeDataSavingManager, "saveResumeData", QMetaObject::invokeMethod(m_resumeDataSavingManager, "saveResumeData",
Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out), Q_ARG(QString, torrent->hash()), Q_ARG(QByteArray, out));
Q_ARG(int, torrent->queuePosition()));
} }
void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent) void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent)
@ -1897,48 +1896,56 @@ void Session::startUpTorrents()
const QDir resumeDataDir(m_resumeFolderPath); const QDir resumeDataDir(m_resumeFolderPath);
QStringList fastresumes = resumeDataDir.entryList( QStringList fastresumes = resumeDataDir.entryList(
QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted); QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted);
typedef QPair<int, QString> PrioHashPair;
typedef std::vector<PrioHashPair> PrioHashVector;
typedef std::greater<PrioHashPair> PrioHashGreater;
std::priority_queue<PrioHashPair, PrioHashVector, PrioHashGreater> torrentQueue;
// Fastresume file name format:
// <torrent_info_hash>.fastresume.<torrent_queue_position>
// 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);
}
}
QString filePath; QString filePath;
Logger *const logger = Logger::instance(); Logger *const logger = Logger::instance();
typedef struct
{
QString hash;
MagnetUri magnetUri;
AddTorrentData addTorrentData;
QByteArray data;
} TorrentResumeData;
qDebug("Starting up torrents"); qDebug("Starting up torrents");
qDebug("Priority queue size: %ld", (long)torrentQueue.size()); qDebug("Queue size: %d", fastresumes.size());
// Resume downloads // Resume downloads
while (!torrentQueue.empty()) { QMap<int, TorrentResumeData> queuedResumeData;
const int prio = torrentQueue.top().first; QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
const QString hash = torrentQueue.top().second; foreach (const QString &fastresumeName, fastresumes) {
torrentQueue.pop(); if (rx.indexIn(fastresumeName) == -1) continue;
QString hash = rx.cap(1);
QString fastresumePath = QString fastresumePath =
resumeDataDir.absoluteFilePath(QString("%1.fastresume.%2").arg(hash).arg(prio)); resumeDataDir.absoluteFilePath(fastresumeName);
QByteArray data; QByteArray data;
AddTorrentData resumeData; AddTorrentData resumeData;
MagnetUri magnetUri; MagnetUri magnetUri;
if (readFile(fastresumePath, data) && loadTorrentResumeData(data, resumeData, magnetUri)) { int queuePosition;
if (readFile(fastresumePath, data) && loadTorrentResumeData(data, resumeData, queuePosition, magnetUri)) {
if (queuePosition == 0) {
filePath = resumeDataDir.filePath(QString("%1.torrent").arg(hash)); filePath = resumeDataDir.filePath(QString("%1.torrent").arg(hash));
qDebug("Starting up torrent %s ...", qPrintable(hash)); qDebug("Starting up torrent %s ...", qPrintable(hash));
if (!addTorrent_impl(resumeData, magnetUri, TorrentInfo::loadFromFile(filePath), data)) if (!addTorrent_impl(resumeData, magnetUri, TorrentInfo::loadFromFile(filePath), data))
logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.") logger->addMessage(tr("Unable to resume torrent '%1'.", "e.g: Unable to resume torrent 'hash'.")
.arg(Utils::Fs::toNativePath(hash)), Log::CRITICAL); .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 quint64 Session::getAlltimeDL() const
@ -2351,7 +2358,7 @@ bool readFile(const QString &path, QByteArray &buf)
return true; 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 = AddTorrentData();
out.resumed = true; 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.addPaused = fast.dict_find_int_value("qBt-paused");
out.addForced = fast.dict_find_int_value("qBt-forced"); out.addForced = fast.dict_find_int_value("qBt-forced");
prio = fast.dict_find_int_value("qBt-queuePosition");
return true; return true;
} }

1
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-name"] = Utils::String::toStdString(m_name);
resumeData["qBt-seedStatus"] = m_hasSeedStatus; resumeData["qBt-seedStatus"] = m_hasSeedStatus;
resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled; resumeData["qBt-tempPathDisabled"] = m_tempPathDisabled;
resumeData["qBt-queuePosition"] = queuePosition();
m_session->handleTorrentResumeDataReady(this, resumeData); m_session->handleTorrentResumeDataReady(this, resumeData);
} }

Loading…
Cancel
Save