Browse Source

Perform fastresume data saving in separate thread

Closes #4315
adaptive-webui-19844
Vladimir Golovnev (qlassez) 9 years ago committed by Vladimir Golovnev (Glassez)
parent
commit
4f01660591
  1. 2
      src/base/base.pri
  2. 54
      src/base/bittorrent/private/resumedatasavingmanager.cpp
  3. 50
      src/base/bittorrent/private/resumedatasavingmanager.h
  4. 44
      src/base/bittorrent/session.cpp
  5. 6
      src/base/bittorrent/session.h

2
src/base/base.pri

@ -36,6 +36,7 @@ HEADERS += \ @@ -36,6 +36,7 @@ HEADERS += \
$$PWD/bittorrent/private/bandwidthscheduler.h \
$$PWD/bittorrent/private/filterparserthread.h \
$$PWD/bittorrent/private/statistics.h \
$$PWD/bittorrent/private/resumedatasavingmanager.h \
$$PWD/rss/rssmanager.h \
$$PWD/rss/rssfeed.h \
$$PWD/rss/rssfolder.h \
@ -87,6 +88,7 @@ SOURCES += \ @@ -87,6 +88,7 @@ SOURCES += \
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
$$PWD/bittorrent/private/filterparserthread.cpp \
$$PWD/bittorrent/private/statistics.cpp \
$$PWD/bittorrent/private/resumedatasavingmanager.cpp \
$$PWD/rss/rssmanager.cpp \
$$PWD/rss/rssfeed.cpp \
$$PWD/rss/rssfolder.cpp \

54
src/base/bittorrent/private/resumedatasavingmanager.cpp

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#include <QDebug>
#include <QFile>
#include "base/utils/fs.h"
#include "resumedatasavingmanager.h"
ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath)
: m_resumeDataDir(resumeFolderPath)
{
}
void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data, int priority) 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 filepath = m_resumeDataDir.absoluteFilePath(filename);
qDebug() << "Saving resume data in" << filepath;
QFile resumeFile(filepath);
if (resumeFile.open(QIODevice::WriteOnly))
resumeFile.write(data);
}

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

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#ifndef RESUMEDATASAVINGMANAGER_H
#define RESUMEDATASAVINGMANAGER_H
#include <QObject>
#include <QByteArray>
#include <QDir>
class ResumeDataSavingManager: public QObject
{
Q_OBJECT
public:
explicit ResumeDataSavingManager(const QString &resumeFolderPath);
public slots:
void saveResumeData(QString infoHash, QByteArray data, int priority) const;
private:
QDir m_resumeDataDir;
};
#endif // RESUMEDATASAVINGMANAGER_H

44
src/base/bittorrent/session.cpp

@ -43,6 +43,7 @@ using namespace BitTorrent; @@ -43,6 +43,7 @@ using namespace BitTorrent;
#include <QTimer>
#include <QProcess>
#include <QCoreApplication>
#include <QThread>
#include <queue>
#include <vector>
@ -80,6 +81,7 @@ using namespace BitTorrent; @@ -80,6 +81,7 @@ using namespace BitTorrent;
#include "private/filterparserthread.h"
#include "private/statistics.h"
#include "private/bandwidthscheduler.h"
#include "private/resumedatasavingmanager.h"
#include "trackerentry.h"
#include "tracker.h"
#include "magneturi.h"
@ -205,6 +207,11 @@ Session::Session(QObject *parent) @@ -205,6 +207,11 @@ Session::Session(QObject *parent)
connect(&m_networkManager, SIGNAL(configurationRemoved(const QNetworkConfiguration&)), SLOT(networkConfigurationChange(const QNetworkConfiguration&)));
connect(&m_networkManager, SIGNAL(configurationChanged(const QNetworkConfiguration&)), SLOT(networkConfigurationChange(const QNetworkConfiguration&)));
m_ioThread = new QThread(this);
m_resumeDataSavingManager = new ResumeDataSavingManager(m_resumeFolderPath);
m_resumeDataSavingManager->moveToThread(m_ioThread);
connect(m_ioThread, SIGNAL(finished()), m_resumeDataSavingManager, SLOT(deleteLater()));
m_ioThread->start();
m_resumeDataTimer->start();
// initialize PortForwarder instance
@ -282,6 +289,9 @@ Session::~Session() @@ -282,6 +289,9 @@ Session::~Session()
qDebug("Deleting the session");
delete m_nativeSession;
m_ioThread->quit();
m_ioThread->wait();
m_resumeFolderLock.close();
m_resumeFolderLock.remove();
}
@ -1710,7 +1720,17 @@ void Session::handleTorrentFinished(TorrentHandle *const torrent) @@ -1710,7 +1720,17 @@ void Session::handleTorrentFinished(TorrentHandle *const torrent)
void Session::handleTorrentResumeDataReady(TorrentHandle *const torrent, const libtorrent::entry &data)
{
--m_numResumeData;
writeResumeDataFile(torrent, data);
// Separated thread is used for the blocking IO which results in slow processing of many torrents.
// Encoding data in parallel while doing IO saves time. Copying libtorrent::entry objects around
// isn't cheap too.
QByteArray out;
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()));
}
void Session::handleTorrentResumeDataFailed(TorrentHandle *const torrent)
@ -2356,28 +2376,6 @@ bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, MagnetUr @@ -2356,28 +2376,6 @@ bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, MagnetUr
return true;
}
bool Session::writeResumeDataFile(TorrentHandle *const torrent, const libt::entry &data)
{
const QDir resumeDataDir(m_resumeFolderPath);
QStringList filters(QString("%1.fastresume.*").arg(torrent->hash()));
const QStringList files = resumeDataDir.entryList(filters, QDir::Files, QDir::Unsorted);
foreach (const QString &file, files)
Utils::Fs::forceRemove(resumeDataDir.absoluteFilePath(file));
QString filename = QString("%1.fastresume.%2").arg(torrent->hash()).arg(torrent->queuePosition());
QString filepath = resumeDataDir.absoluteFilePath(filename);
qDebug("Saving resume data in %s", qPrintable(filepath));
QFile resumeFile(filepath);
QVector<char> out;
libt::bencode(std::back_inserter(out), data);
if (resumeFile.open(QIODevice::WriteOnly))
return (resumeFile.write(&out[0], out.size()) == out.size());
return false;
}
void torrentQueuePositionUp(const libt::torrent_handle &handle)
{
try {

6
src/base/bittorrent/session.h

@ -86,6 +86,7 @@ namespace libtorrent @@ -86,6 +86,7 @@ namespace libtorrent
struct external_ip_alert;
}
class QThread;
class QTimer;
class QStringList;
class QString;
@ -95,6 +96,7 @@ template<typename T> class QList; @@ -95,6 +96,7 @@ template<typename T> class QList;
class FilterParserThread;
class BandwidthScheduler;
class Statistics;
class ResumeDataSavingManager;
typedef QPair<QString, QString> QStringPair;
@ -314,7 +316,6 @@ namespace BitTorrent @@ -314,7 +316,6 @@ namespace BitTorrent
void handleExternalIPAlert(libtorrent::external_ip_alert *p);
void saveResumeData();
bool writeResumeDataFile(TorrentHandle *const torrent, const libtorrent::entry &data);
void dispatchAlerts(std::auto_ptr<libtorrent::alert> alertPtr);
void getPendingAlerts(QVector<libtorrent::alert *> &out, ulong time = 0);
@ -355,6 +356,9 @@ namespace BitTorrent @@ -355,6 +356,9 @@ namespace BitTorrent
QPointer<BandwidthScheduler> m_bwScheduler;
// Tracker
QPointer<Tracker> m_tracker;
// fastresume data writing thread
QThread *m_ioThread;
ResumeDataSavingManager *m_resumeDataSavingManager;
QHash<InfoHash, TorrentInfo> m_loadedMetadata;
QHash<InfoHash, TorrentHandle *> m_torrents;

Loading…
Cancel
Save