2 * Bittorrent Client using Qt and libtorrent.
3 * Copyright (C) 2024 Vladimir Golovnev <glassez@yandex.ru>
4 * Copyright (C) 2024 Radu Carpa <radu.carpa@cern.ch>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * In addition, as a special exception, the copyright holders give permission to
21 * link this program with the OpenSSL project's "OpenSSL" library (or with
22 * modified versions of it that use the same license as the "OpenSSL" library),
23 * and distribute the linked executables. You must obey the GNU General Public
24 * License in all respects for all of the code used other than "OpenSSL". If you
25 * modify file(s), you may extend this exception to your version of the file(s),
26 * but you are not obligated to do so. If you do not wish to do so, delete this
27 * exception statement from your version.
30 #include "torrentcreationmanager.h"
34 #include <boost/multi_index_container.hpp>
35 #include <boost/multi_index/composite_key.hpp>
36 #include <boost/multi_index/indexed_by.hpp>
37 #include <boost/multi_index/mem_fun.hpp>
38 #include <boost/multi_index/ordered_index.hpp>
42 #define SETTINGS_KEY(name) u"TorrentCreator/Manager/" name
46 using namespace boost::multi_index
;
48 class TorrentCreationManager::TaskSet final
: public boost::multi_index_container
<
49 std::shared_ptr
<TorrentCreationTask
>,
51 ordered_unique
<tag
<struct ByID
>, const_mem_fun
<TorrentCreationTask
, QString
, &TorrentCreationTask::id
>>,
52 ordered_non_unique
<tag
<struct ByCompletion
>, composite_key
<
54 const_mem_fun
<TorrentCreationTask
, bool, &TorrentCreationTask::isFinished
>,
55 const_mem_fun
<TorrentCreationTask
, QDateTime
, &TorrentCreationTask::timeAdded
>>>>>
60 BitTorrent::TorrentCreationManager::TorrentCreationManager(IApplication
*app
, QObject
*parent
)
61 : ApplicationComponent(app
, parent
)
62 , m_maxTasks
{SETTINGS_KEY(u
"MaxTasks"_s
), 256}
63 , m_numThreads
{SETTINGS_KEY(u
"NumThreads"_s
), 1}
64 , m_tasks
{std::make_unique
<TaskSet
>()}
67 m_threadPool
.setObjectName("TorrentCreationManager m_threadPool");
70 m_threadPool
.setMaxThreadCount(m_numThreads
);
73 BitTorrent::TorrentCreationManager::~TorrentCreationManager() = default;
75 std::shared_ptr
<BitTorrent::TorrentCreationTask
> BitTorrent::TorrentCreationManager::createTask(const TorrentCreatorParams
¶ms
, bool startSeeding
)
77 if (std::cmp_greater_equal(m_tasks
->size(), m_maxTasks
.get()))
79 // Try to delete old finished tasks to stay under target
80 auto &tasksByCompletion
= m_tasks
->get
<ByCompletion
>();
81 auto [iter
, endIter
] = tasksByCompletion
.equal_range(std::make_tuple(true));
82 while ((iter
!= endIter
) && std::cmp_greater_equal(m_tasks
->size(), m_maxTasks
.get()))
84 iter
= tasksByCompletion
.erase(iter
);
87 if (std::cmp_greater_equal(m_tasks
->size(), m_maxTasks
.get()))
90 const QString taskID
= generateTaskID();
92 auto *torrentCreator
= new TorrentCreator(params
, this);
93 auto creationTask
= std::make_shared
<TorrentCreationTask
>(app(), taskID
, torrentCreator
, startSeeding
);
94 connect(creationTask
.get(), &QObject::destroyed
, torrentCreator
, &BitTorrent::TorrentCreator::requestInterruption
);
96 m_tasks
->get
<ByID
>().insert(creationTask
);
97 m_threadPool
.start(torrentCreator
);
102 QString
BitTorrent::TorrentCreationManager::generateTaskID() const
104 const auto &tasksByID
= m_tasks
->get
<ByID
>();
105 QString taskID
= QUuid::createUuid().toString(QUuid::WithoutBraces
);
106 while (tasksByID
.find(taskID
) != tasksByID
.end())
107 taskID
= QUuid::createUuid().toString(QUuid::WithoutBraces
);
112 std::shared_ptr
<BitTorrent::TorrentCreationTask
> BitTorrent::TorrentCreationManager::getTask(const QString
&id
) const
114 const auto &tasksByID
= m_tasks
->get
<ByID
>();
115 const auto iter
= tasksByID
.find(id
);
116 if (iter
== tasksByID
.end())
122 QList
<std::shared_ptr
<BitTorrent::TorrentCreationTask
>> BitTorrent::TorrentCreationManager::tasks() const
124 const auto &tasksByCompletion
= m_tasks
->get
<ByCompletion
>();
125 return {tasksByCompletion
.cbegin(), tasksByCompletion
.cend()};
128 bool BitTorrent::TorrentCreationManager::deleteTask(const QString
&id
)
130 auto &tasksByID
= m_tasks
->get
<ByID
>();
131 const auto iter
= tasksByID
.find(id
);
132 if (iter
== tasksByID
.end())
135 tasksByID
.erase(iter
);