From 14646d0f9eb49836a942b0d46260af82b63ddfbd Mon Sep 17 00:00:00 2001 From: Christophe Dumez Date: Fri, 26 Dec 2008 13:17:08 +0000 Subject: [PATCH] Rewrote folder scanning code (Now uses a filesystem watcher) --- Changelog | 2 + src/GUI.cpp | 16 ------ src/GUI.h | 1 - src/bittorrent.cpp | 75 +++++++++++++-------------- src/bittorrent.h | 11 ++-- src/options.ui | 31 ----------- src/options_imp.cpp | 13 ----- src/options_imp.h | 1 - src/search_engine/engines/mininova.py | 1 - 9 files changed, 42 insertions(+), 109 deletions(-) diff --git a/Changelog b/Changelog index 46e304afa..9e053af05 100644 --- a/Changelog +++ b/Changelog @@ -12,10 +12,12 @@ - FEATURE: Got rid of libmagick++ dependency - FEATURE: Updated Web interface to MochaUI v0.9.5 - FEATURE: Added notification in WebUI when qBittorrent is not reachable + - FEATURE: Rewrote folder scanning code (Now uses a filesystem watcher) - BUGFIX: Fixed several memory leaks - BUGFIX: WebUI is now working with IE7 - BUGFIX: Fixed spacing problem in toolbar when toggling its visibility - BUGFIX: Fixed some compilation and Qt4 warnings + - BUGFIX: Do not use an addition dialog for torrents from folder scanning * Sun Nov 9 2008 - Christophe Dumez - v1.2.1 - BUGFIX: Fixed possible crash when deleting a torrent permanently diff --git a/src/GUI.cpp b/src/GUI.cpp index a08beec67..78ddd83dd 100644 --- a/src/GUI.cpp +++ b/src/GUI.cpp @@ -122,7 +122,6 @@ GUI::GUI(QWidget *parent, QStringList torrentCmdLine) : QMainWindow(parent), dis connect(BTSession, SIGNAL(fullDiskError(QTorrentHandle&)), this, SLOT(fullDiskError(QTorrentHandle&))); connect(BTSession, SIGNAL(finishedTorrent(QTorrentHandle&)), this, SLOT(finishedTorrent(QTorrentHandle&))); connect(BTSession, SIGNAL(trackerAuthenticationRequired(QTorrentHandle&)), this, SLOT(trackerAuthenticationRequired(QTorrentHandle&))); - connect(BTSession, SIGNAL(scanDirFoundTorrents(const QStringList&)), this, SLOT(processScannedFiles(const QStringList&))); connect(BTSession, SIGNAL(newDownloadedTorrent(QString, QString)), this, SLOT(processDownloadedFiles(QString, QString))); connect(BTSession, SIGNAL(downloadFromUrlFailure(QString, QString)), this, SLOT(handleDownloadFromUrlFailure(QString, QString))); connect(BTSession, SIGNAL(deletedTorrent(QString)), this, SLOT(deleteTorrent(QString))); @@ -869,20 +868,6 @@ void GUI::addTorrent(QString path) { BTSession->addTorrent(path); } -void GUI::processScannedFiles(const QStringList& params) { - QString param; - QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); - bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); - foreach(param, params) { - if(useTorrentAdditionDialog) { - torrentAdditionDialog *dialog = new torrentAdditionDialog(this, BTSession); - dialog->showLoad(param, true); - }else{ - BTSession->addTorrent(param, true); - } - } -} - void GUI::processDownloadedFiles(QString path, QString url) { QSettings settings(QString::fromUtf8("qBittorrent"), QString::fromUtf8("qBittorrent")); bool useTorrentAdditionDialog = settings.value(QString::fromUtf8("Preferences/Downloads/AdditionDialog"), true).toBool(); @@ -927,7 +912,6 @@ void GUI::configureSession(bool deleteOptions) { BTSession->disableDirectoryScanning(); }else{ //Interval first - BTSession->setTimerScanInterval(options->getFolderScanInterval()); BTSession->enableDirectoryScanning(options->getScanDir()); } // Connection diff --git a/src/GUI.h b/src/GUI.h index 7c3c08209..4c572d57a 100644 --- a/src/GUI.h +++ b/src/GUI.h @@ -156,7 +156,6 @@ class GUI : public QMainWindow, private Ui::MainWindow{ void processParams(const QStringList& params); void addTorrent(QString path); void addUnauthenticatedTracker(QPair tracker); - void processScannedFiles(const QStringList& params); void processDownloadedFiles(QString path, QString url); void downloadFromURLList(const QStringList& urls); void deleteTorrent(QString hash); diff --git a/src/bittorrent.cpp b/src/bittorrent.cpp index d0def6ed5..9abbf6e93 100644 --- a/src/bittorrent.cpp +++ b/src/bittorrent.cpp @@ -23,7 +23,9 @@ #include #include #include +#include #include +#include #include "bittorrent.h" #include "misc.h" @@ -43,7 +45,7 @@ #define MAX_TRACKER_ERRORS 2 // Main constructor -bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), folderScanInterval(5), queueingEnabled(false) { +bittorrent::bittorrent() : DHTEnabled(false), preAllocateAll(false), addInPause(false), maxConnecsPerTorrent(500), maxUploadsPerTorrent(4), max_ratio(-1), UPnPEnabled(false), NATPMPEnabled(false), LSDEnabled(false), queueingEnabled(false) { // To avoid some exceptions fs::path::default_name_check(fs::no_check); // Creating bittorrent session @@ -73,6 +75,7 @@ bittorrent::bittorrent() : timerScan(0), DHTEnabled(false), preAllocateAll(false connect(downloader, SIGNAL(downloadFailure(QString, QString)), this, SLOT(handleDownloadFailure(QString, QString))); BigRatioTimer = 0; filterParser = 0; + FSWatcher = 0; qDebug("* BTSession constructed"); } @@ -437,7 +440,7 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bo QTorrentHandle h; bool fastResume=false; QDir torrentBackup(misc::qBittorrentPath() + "BT_backup"); - QString file, dest_file, scan_dir; + QString file, dest_file; // Checking if BT_backup Dir exists // create it if it is not @@ -469,11 +472,10 @@ void bittorrent::addTorrent(QString path, bool fromScanDir, QString from_url, bo } addConsoleMessage(tr("This file is either corrupted or this isn't a torrent."),QString::fromUtf8("red")); if(fromScanDir) { - // Remove .corrupt file in case it already exists - QFile::remove(file+".corrupt"); - //Rename file extension so that it won't display error message more than once - QFile::rename(file,file+".corrupt"); + // Remove file + QFile::remove(file); } + return; } qDebug(" -> Hash: %s", misc::toString(t->info_hash()).c_str()); qDebug(" -> Name: %s", t->name().c_str()); @@ -979,56 +981,49 @@ bool bittorrent::isFilePreviewPossible(QString hash) const{ // Scan the first level of the directory for torrent files // and add them to download list -void bittorrent::scanDirectory() { +void bittorrent::scanDirectory(QString scan_dir) { + FSMutex->lock(); + qDebug("Scanning directory: %s", scan_dir.toUtf8().data()); QString file; - if(!scan_dir.isNull()) { - QStringList to_add; - QDir dir(scan_dir); - QStringList filters; - filters << "*.torrent"; - QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted); - foreach(file, files) { + QDir dir(scan_dir); + QStringList filters; + filters << "*.torrent"; + QStringList files = dir.entryList(filters, QDir::Files, QDir::Unsorted); + foreach(file, files) { QString fullPath = dir.path()+QDir::separator()+file; - QFile::rename(fullPath, fullPath+QString::fromUtf8(".old")); - to_add << fullPath+QString::fromUtf8(".old"); - } - emit scanDirFoundTorrents(to_add); + QFile torrent(fullPath); + if(torrent.size() != 0) { + qDebug("Adding for scan_dir: %s", fullPath.toUtf8().data()); + addTorrent(fullPath, true); + } else { + qDebug("Ignoring empty file: %s", fullPath.toUtf8().data()); + } } + FSMutex->unlock(); } void bittorrent::setDefaultSavePath(QString savepath) { defaultSavePath = savepath; } -void bittorrent::setTimerScanInterval(int secs) { - if(folderScanInterval != secs) { - folderScanInterval = secs; - if(!scan_dir.isNull()) { - timerScan->start(folderScanInterval*1000); - } - } -} - // Enable directory scanning -void bittorrent::enableDirectoryScanning(QString _scan_dir) { - if(!_scan_dir.isEmpty()) { - scan_dir = _scan_dir; - timerScan = new QTimer(this); - connect(timerScan, SIGNAL(timeout()), this, SLOT(scanDirectory())); - timerScan->start(folderScanInterval*1000); +void bittorrent::enableDirectoryScanning(QString scan_dir) { + if(!scan_dir.isEmpty()) { + Q_ASSERT(FSWatcher == 0); + FSMutex = new QMutex(); + FSWatcher = new QFileSystemWatcher(QStringList(scan_dir), this); + connect(FSWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(scanDirectory(QString))); + // Initial scan + scanDirectory(scan_dir); } } // Disable directory scanning void bittorrent::disableDirectoryScanning() { - if(!scan_dir.isNull()) { - scan_dir = QString::null; - if(timerScan->isActive()) { - timerScan->stop(); - } + if(FSWatcher) { + delete FSWatcher; + delete FSMutex; } - if(timerScan) - delete timerScan; } // Set the ports range in which is chosen the port the bittorrent diff --git a/src/bittorrent.h b/src/bittorrent.h index 41f62c5e1..f0c73e8be 100644 --- a/src/bittorrent.h +++ b/src/bittorrent.h @@ -35,6 +35,8 @@ using namespace libtorrent; class downloadThread; class QTimer; +class QFileSystemWatcher; +class QMutex; class FilterParserThread; class bittorrent : public QObject { @@ -42,8 +44,8 @@ class bittorrent : public QObject { private: session *s; - QString scan_dir; - QPointer timerScan; + QPointer FSWatcher; + QMutex* FSMutex; QPointer timerAlerts; QPointer BigRatioTimer; bool DHTEnabled; @@ -64,7 +66,6 @@ class bittorrent : public QObject { bool LSDEnabled; QPointer filterParser; QString filterPath; - int folderScanInterval; // in seconds bool queueingEnabled; QStringList url_skippingDlg; @@ -157,12 +158,11 @@ class bittorrent : public QObject { void enableNATPMP(bool b); void enableLSD(bool b); bool enableDHT(bool b); - void setTimerScanInterval(int secs); void addConsoleMessage(QString msg, QColor color=QApplication::palette().color(QPalette::WindowText)); void addPeerBanMessage(QString msg, bool from_ipfilter); protected slots: - void scanDirectory(); + void scanDirectory(QString); void readAlerts(); void processDownloadedFile(QString, QString); bool loadTrackerFile(QString hash); @@ -178,7 +178,6 @@ class bittorrent : public QObject { void fullDiskError(QTorrentHandle& h); void trackerError(QString hash, QString time, QString msg); void trackerAuthenticationRequired(QTorrentHandle& h); - void scanDirFoundTorrents(const QStringList& pathList); void newDownloadedTorrent(QString path, QString url); void updateFileSize(QString hash); void downloadFromUrlFailure(QString url, QString reason); diff --git a/src/options.ui b/src/options.ui index 582361a16..05a3ec485 100644 --- a/src/options.ui +++ b/src/options.ui @@ -497,37 +497,6 @@ - - - - - - Folder scan interval: - - - - - - - 1 - - - 9999 - - - 5 - - - - - - - seconds - - - - - diff --git a/src/options_imp.cpp b/src/options_imp.cpp index 930425ace..0085b720f 100644 --- a/src/options_imp.cpp +++ b/src/options_imp.cpp @@ -174,7 +174,6 @@ options_imp::options_imp(QWidget *parent):QDialog(parent){ connect(checkStartPaused, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); connect(checkScanDir, SIGNAL(stateChanged(int)), this, SLOT(enableApplyButton())); connect(textScanDir, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton())); - connect(FolderScanSpin, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton())); // Connection tab connect(spinPortMin, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton())); connect(spinPortMax, SIGNAL(valueChanged(QString)), this, SLOT(enableApplyButton())); @@ -302,7 +301,6 @@ void options_imp::saveOptions(){ settings.setValue(QString::fromUtf8("AdditionDialog"), useAdditionDialog()); settings.setValue(QString::fromUtf8("StartInPause"), addTorrentsInPause()); settings.setValue(QString::fromUtf8("ScanDir"), getScanDir()); - settings.setValue(QString::fromUtf8("ScanDirInterval"), getFolderScanInterval()); settings.setValue(QString::fromUtf8("DblClOnTorDl"), getActionOnDblClOnTorrentDl()); settings.setValue(QString::fromUtf8("DblClOnTorFn"), getActionOnDblClOnTorrentFn()); // End Downloads preferences @@ -513,7 +511,6 @@ void options_imp::loadOptions(){ // enable checkScanDir->setChecked(true); textScanDir->setText(strValue); - FolderScanSpin->setValue(settings.value(QString::fromUtf8("ScanDirInterval"), 5).toInt()); enableDirScan(2); } actionTorrentDlOnDblClBox->setCurrentIndex(settings.value(QString::fromUtf8("DblClOnTorDl"), 0).toInt()); @@ -1112,23 +1109,13 @@ void options_imp::enableDirScan(int checkBoxValue){ //enable textScanDir->setEnabled(true); browseScanDirButton->setEnabled(true); - FolderScanSpin->setEnabled(true); - FolderScanLbl->setEnabled(true); - FolderScanLbl2->setEnabled(true); }else{ //disable textScanDir->setEnabled(false); browseScanDirButton->setEnabled(false); - FolderScanSpin->setEnabled(false); - FolderScanLbl->setEnabled(false); - FolderScanLbl2->setEnabled(false); } } -int options_imp::getFolderScanInterval() const { - return FolderScanSpin->value(); -} - bool options_imp::speedInTitleBar() const { return checkSpeedInTitle->isChecked(); } diff --git a/src/options_imp.h b/src/options_imp.h index 1449e1d49..0e96bf6d0 100644 --- a/src/options_imp.h +++ b/src/options_imp.h @@ -74,7 +74,6 @@ class options_imp : public QDialog, private Ui::Dialog { bool addTorrentsInPause() const; bool isDirScanEnabled() const; QString getScanDir() const; - int getFolderScanInterval() const; int getActionOnDblClOnTorrentDl() const; int getActionOnDblClOnTorrentFn() const; // Connection options diff --git a/src/search_engine/engines/mininova.py b/src/search_engine/engines/mininova.py index 0f416fcd7..cbd07ed0f 100644 --- a/src/search_engine/engines/mininova.py +++ b/src/search_engine/engines/mininova.py @@ -36,7 +36,6 @@ class mininova(object): table_items = 'added cat name size seeds leech'.split() def search(self, what): - order = 'seeds' # must be one in self.table_items def get_link(lnk): lnks = lnk.getElementsByTagName('a')