Browse Source

More reliable folder scanning

adaptive-webui-19844
Christophe Dumez 14 years ago
parent
commit
9c9944715a
  1. 85
      src/filesystemwatcher.h
  2. 11
      src/misc.cpp
  3. 2
      src/misc.h

85
src/filesystemwatcher.h

@ -19,6 +19,8 @@
#endif #endif
#endif #endif
#include "misc.h"
#ifndef CIFS_MAGIC_NUMBER #ifndef CIFS_MAGIC_NUMBER
#define CIFS_MAGIC_NUMBER 0xFF534D42 #define CIFS_MAGIC_NUMBER 0xFF534D42
#endif #endif
@ -27,6 +29,9 @@
#define NFS_SUPER_MAGIC 0x6969 #define NFS_SUPER_MAGIC 0x6969
#endif #endif
const int WATCH_INTERVAL = 10000; // 10 sec
const int MAX_PARTIAL_RETRIES = 5;
/* /*
* Subclassing QFileSystemWatcher in order to support Network File * Subclassing QFileSystemWatcher in order to support Network File
* System watching (NFS, CIFS) on Linux and Mac OS. * System watching (NFS, CIFS) on Linux and Mac OS.
@ -39,11 +44,14 @@ private:
QList<QDir> watched_folders; QList<QDir> watched_folders;
QPointer<QTimer> watch_timer; QPointer<QTimer> watch_timer;
#endif #endif
QStringList filters; QStringList m_filters;
// Partial torrents
QHash<QString, int> m_partialTorrents;
QPointer<QTimer> m_partialTorrentTimer;
#ifndef Q_WS_WIN #ifndef Q_WS_WIN
protected: private:
bool isNetworkFileSystem(QString path) { static bool isNetworkFileSystem(QString path) {
QString file = path; QString file = path;
if(!file.endsWith(QDir::separator())) if(!file.endsWith(QDir::separator()))
file += QDir::separator(); file += QDir::separator();
@ -99,7 +107,7 @@ protected:
public: public:
FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) { FileSystemWatcher(QObject *parent): QFileSystemWatcher(parent) {
filters << "*.torrent"; m_filters << "*.torrent";
connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString))); connect(this, SIGNAL(directoryChanged(QString)), this, SLOT(scanLocalFolder(QString)));
} }
@ -108,6 +116,8 @@ public:
if(watch_timer) if(watch_timer)
delete watch_timer; delete watch_timer;
#endif #endif
if(m_partialTorrentTimer)
delete m_partialTorrentTimer;
} }
QStringList directories() const { QStringList directories() const {
@ -137,7 +147,7 @@ public:
if (!watch_timer) { if (!watch_timer) {
watch_timer = new QTimer(this); watch_timer = new QTimer(this);
connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanNetworkFolders())); connect(watch_timer, SIGNAL(timeout()), this, SLOT(scanNetworkFolders()));
watch_timer->start(5000); // 5 sec watch_timer->start(WATCH_INTERVAL); // 5 sec
} }
} else { } else {
#endif #endif
@ -196,19 +206,72 @@ protected slots:
#endif #endif
} }
void processPartialTorrents() {
QStringList no_longer_partial;
// Check which torrents are still partial
foreach(const QString& torrent_path, m_partialTorrents.keys()) {
if(!QFile::exists(torrent_path)) {
m_partialTorrents.remove(torrent_path);
continue;
}
if(misc::isValidTorrentFile(torrent_path)) {
no_longer_partial << torrent_path;
m_partialTorrents.remove(torrent_path);
} else {
if(m_partialTorrents[torrent_path] >= MAX_PARTIAL_RETRIES) {
m_partialTorrents.remove(torrent_path);
QFile::rename(torrent_path, torrent_path+".invalid");
} else {
m_partialTorrents[torrent_path]++;
}
}
}
// Stop the partial timer if necessary
if(m_partialTorrents.empty()) {
m_partialTorrentTimer->stop();
m_partialTorrentTimer->deleteLater();
qDebug("No longer any partial torrent.");
} else {
qDebug("Still %d partial torrents after delayed processing.", m_partialTorrents.count());
m_partialTorrentTimer->start(WATCH_INTERVAL);
}
// Notify of new torrents
if(!no_longer_partial.isEmpty())
emit torrentsAdded(no_longer_partial);
}
signals: signals:
void torrentsAdded(QStringList &pathList); void torrentsAdded(QStringList &pathList);
private: private:
void startPartialTorrentTimer() {
Q_ASSERT(!m_partialTorrents.isEmpty());
if(!m_partialTorrentTimer) {
m_partialTorrentTimer = new QTimer();
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents()));
m_partialTorrentTimer->setSingleShot(true);
m_partialTorrentTimer->start(WATCH_INTERVAL);
}
}
void addTorrentsFromDir(const QDir &dir, QStringList &torrents) { void addTorrentsFromDir(const QDir &dir, QStringList &torrents) {
const QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted); const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted);
foreach(const QString &file, files) { foreach(const QString &file, files) {
#if defined(Q_WS_WIN) || defined(Q_OS_OS2) const QString file_abspath = dir.absoluteFilePath(file);
torrents << dir.absoluteFilePath(file).replace("/", "\\"); if(misc::isValidTorrentFile(file_abspath)) {
#else torrents << file_abspath;
torrents << dir.absoluteFilePath(file); } else {
#endif if(!m_partialTorrents.contains(file_abspath)) {
qDebug("Partial torrent detected at: %s", qPrintable(file_abspath));
qDebug("Delay the file's processing...");
m_partialTorrents.insert(file_abspath, 0);
}
}
} }
if(!m_partialTorrents.empty())
startPartialTorrentTimer();
} }
}; };

11
src/misc.cpp

@ -748,3 +748,14 @@ quint64 misc::computePathSize(QString path)
} }
return size; return size;
} }
bool misc::isValidTorrentFile(const QString &torrent_path) {
try {
boost::intrusive_ptr<libtorrent::torrent_info> t = new torrent_info(torrent_path.toUtf8().constData());
if(!t->is_valid() || t->num_files() == 0)
throw std::exception();
} catch(std::exception&) {
return false;
}
return true;
}

2
src/misc.h

@ -170,6 +170,8 @@ public:
static QStringList toStringList(const QList<bool> &l); static QStringList toStringList(const QList<bool> &l);
static QList<int> intListfromStringList(const QStringList &l); static QList<int> intListfromStringList(const QStringList &l);
static QList<bool> boolListfromStringList(const QStringList &l); static QList<bool> boolListfromStringList(const QStringList &l);
static bool isValidTorrentFile(const QString &path);
}; };
// Trick to get a portable sleep() function // Trick to get a portable sleep() function

Loading…
Cancel
Save