File indexing completed on 2025-01-05 04:37:09

0001 /*
0002     SPDX-FileCopyrightText: 2009 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "datacheckerjob.h"
0008 #include "datacheckerthread.h"
0009 #include "multidatachecker.h"
0010 #include "singledatachecker.h"
0011 #include <KIO/Global>
0012 #include <klocalizedstring.h>
0013 #include <torrent/torrentcontrol.h>
0014 #include <util/functions.h>
0015 
0016 namespace bt
0017 {
0018 static ResourceManager data_checker_slot(1);
0019 
0020 DataCheckerJob::DataCheckerJob(bool auto_import, bt::TorrentControl *tc, bt::Uint32 from, bt::Uint32 to)
0021     : Job(true, tc)
0022     , Resource(&data_checker_slot, tc->getInfoHash().toString())
0023     , dcheck_thread(nullptr)
0024     , killed(false)
0025     , auto_import(auto_import)
0026     , started(false)
0027     , from(from)
0028     , to(to)
0029 {
0030     if (this->from >= tc->getStats().total_chunks)
0031         this->from = 0;
0032     if (this->to >= tc->getStats().total_chunks)
0033         this->to = tc->getStats().total_chunks - 1;
0034 }
0035 
0036 DataCheckerJob::~DataCheckerJob()
0037 {
0038 }
0039 
0040 void DataCheckerJob::start()
0041 {
0042     registerWithTracker();
0043     DataChecker *dc = nullptr;
0044     const TorrentStats &stats = torrent()->getStats();
0045     if (stats.multi_file_torrent)
0046         dc = new MultiDataChecker(from, to);
0047     else
0048         dc = new SingleDataChecker(from, to);
0049 
0050     connect(dc, &DataChecker::progress, this, &DataCheckerJob::progress, Qt::QueuedConnection);
0051     connect(dc, &DataChecker::status, this, &DataCheckerJob::status, Qt::QueuedConnection);
0052 
0053     TorrentControl *tor = torrent();
0054     dcheck_thread = new DataCheckerThread(dc, //
0055                                           tor->downloadedChunksBitSet(),
0056                                           stats.output_path,
0057                                           tor->getTorrent(),
0058                                           tor->getTorDir() + "dnd" + bt::DirSeparator());
0059 
0060     connect(dcheck_thread, &DataCheckerThread::finished, this, &DataCheckerJob::threadFinished, Qt::QueuedConnection);
0061 
0062     torrent()->beforeDataCheck();
0063 
0064     setTotalAmount(Bytes, to - from + 1);
0065     data_checker_slot.add(this);
0066     if (!started)
0067         infoMessage(this, i18n("Waiting for other data checks to finish"));
0068 }
0069 
0070 void DataCheckerJob::acquired()
0071 {
0072     started = true;
0073     description(this, i18n("Checking data"));
0074     dcheck_thread->start(QThread::IdlePriority);
0075 }
0076 
0077 void DataCheckerJob::kill(bool quietly)
0078 {
0079     killed = true;
0080     if (dcheck_thread && dcheck_thread->isRunning()) {
0081         dcheck_thread->getDataChecker()->stop();
0082         dcheck_thread->wait();
0083         dcheck_thread->deleteLater();
0084         dcheck_thread = nullptr;
0085     }
0086     bt::Job::kill(quietly);
0087 }
0088 
0089 void DataCheckerJob::threadFinished()
0090 {
0091     if (!killed) {
0092         DataChecker *dc = dcheck_thread->getDataChecker();
0093         torrent()->afterDataCheck(this, dc->getResult());
0094         if (!dcheck_thread->getError().isEmpty()) {
0095             setErrorText(dcheck_thread->getError());
0096             setError(KIO::ERR_UNKNOWN);
0097         } else
0098             setError(0);
0099     } else
0100         setError(0);
0101 
0102     dcheck_thread->deleteLater();
0103     dcheck_thread = nullptr;
0104     if (!killed) // Job::kill already emitted the result
0105         emitResult();
0106 
0107     release();
0108 }
0109 
0110 void DataCheckerJob::progress(quint32 num, quint32 total)
0111 {
0112     Q_UNUSED(total);
0113     setProcessedAmount(Bytes, num);
0114 }
0115 
0116 void DataCheckerJob::status(quint32 num_failed, quint32 num_found, quint32 num_downloaded, quint32 num_not_downloaded)
0117 {
0118     QPair<QString, QString> field1 = qMakePair(QString::number(num_failed), QString::number(num_found));
0119     QPair<QString, QString> field2 = qMakePair(QString::number(num_downloaded), QString::number(num_not_downloaded));
0120     description(this, i18n("Checking Data"), field1, field2);
0121 }
0122 }