2023-11-01 21:11:11 +00:00
|
|
|
// This file Copyright © Mnemosyne LLC.
|
2022-08-08 18:05:39 +00:00
|
|
|
// It may be used under GPLv2 (SPDX: GPL-2.0-only), GPLv3 (SPDX: GPL-3.0-only),
|
2022-03-01 23:06:29 +00:00
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#ifndef __TRANSMISSION__
|
|
|
|
#error only libtransmission should #include this header.
|
|
|
|
#endif
|
|
|
|
|
2023-10-30 20:38:02 +00:00
|
|
|
#include <algorithm>
|
2023-06-30 04:51:55 +00:00
|
|
|
#include <cstddef> // size_t
|
2022-03-01 23:06:29 +00:00
|
|
|
#include <ctime>
|
2023-10-30 20:38:02 +00:00
|
|
|
#include <functional>
|
|
|
|
#include <iterator>
|
2022-03-01 23:06:29 +00:00
|
|
|
#include <string_view>
|
2022-08-17 16:08:36 +00:00
|
|
|
#include <utility>
|
2022-03-01 23:06:29 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2023-07-08 15:24:03 +00:00
|
|
|
#include "libtransmission/transmission.h"
|
2022-03-01 23:06:29 +00:00
|
|
|
|
2023-07-08 15:24:03 +00:00
|
|
|
#include "libtransmission/torrent-metainfo.h"
|
|
|
|
#include "libtransmission/tr-macros.h"
|
2022-03-01 23:06:29 +00:00
|
|
|
|
|
|
|
struct tr_torrent;
|
|
|
|
|
|
|
|
// A helper class to manage tracking sets of tr_torrent objects.
|
|
|
|
class tr_torrents
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// returns a fast lookup id for `tor`
|
2022-06-17 15:43:04 +00:00
|
|
|
[[nodiscard]] tr_torrent_id_t add(tr_torrent* tor);
|
2022-03-01 23:06:29 +00:00
|
|
|
|
|
|
|
void remove(tr_torrent const* tor, time_t current_time);
|
|
|
|
|
|
|
|
// O(1)
|
2023-11-12 17:53:04 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 tr_torrent* get(tr_torrent_id_t id) const
|
2022-12-23 21:21:40 +00:00
|
|
|
{
|
|
|
|
auto const uid = static_cast<size_t>(id);
|
|
|
|
return uid >= std::size(by_id_) ? nullptr : by_id_.at(uid);
|
|
|
|
}
|
2022-03-01 23:06:29 +00:00
|
|
|
|
|
|
|
// O(log n)
|
2023-11-12 17:53:04 +00:00
|
|
|
[[nodiscard]] tr_torrent* get(tr_sha1_digest_t const& hash) const;
|
2022-03-01 23:06:29 +00:00
|
|
|
|
2023-11-12 17:53:04 +00:00
|
|
|
[[nodiscard]] tr_torrent* get(tr_torrent_metainfo const& metainfo) const
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return get(metainfo.info_hash());
|
2022-03-01 23:06:29 +00:00
|
|
|
}
|
|
|
|
|
2023-10-24 19:24:52 +00:00
|
|
|
// O(n)}
|
2023-11-28 16:51:13 +00:00
|
|
|
[[nodiscard]] tr_torrent* find_from_obfuscated_hash(tr_sha1_digest_t const& obfuscated_hash) const;
|
2023-10-24 19:24:52 +00:00
|
|
|
|
2022-03-01 23:06:29 +00:00
|
|
|
// These convenience functions use get(tr_sha1_digest_t const&)
|
|
|
|
// after parsing the magnet link to get the info hash. If you have
|
|
|
|
// the info hash already, use get() instead to avoid excess parsing.
|
2023-11-12 17:53:04 +00:00
|
|
|
[[nodiscard]] tr_torrent* get(std::string_view magnet_link) const;
|
2022-03-01 23:06:29 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
[[nodiscard]] bool contains(T const& key) const
|
|
|
|
{
|
|
|
|
return get(key) != nullptr;
|
|
|
|
}
|
|
|
|
|
2023-01-28 23:58:20 +00:00
|
|
|
[[nodiscard]] std::vector<tr_torrent_id_t> removedSince(time_t timestamp) const;
|
2022-03-01 23:06:29 +00:00
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto cbegin() const noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return std::cbegin(by_hash_);
|
|
|
|
}
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto begin() const noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return cbegin();
|
|
|
|
}
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto begin() noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return std::begin(by_hash_);
|
|
|
|
}
|
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto cend() const noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return std::cend(by_hash_);
|
|
|
|
}
|
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto end() const noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return cend();
|
|
|
|
}
|
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto end() noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return std::end(by_hash_);
|
|
|
|
}
|
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto size() const noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return std::size(by_hash_);
|
|
|
|
}
|
|
|
|
|
2022-12-23 21:21:40 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 auto empty() const noexcept
|
2022-03-01 23:06:29 +00:00
|
|
|
{
|
|
|
|
return std::empty(by_hash_);
|
|
|
|
}
|
|
|
|
|
2023-10-30 20:38:02 +00:00
|
|
|
[[nodiscard]] auto get_matching(std::function<bool(tr_torrent const*)> pred_in) const
|
2023-10-25 17:42:14 +00:00
|
|
|
{
|
2023-10-30 20:38:02 +00:00
|
|
|
auto const pred = [&pred_in](tr_torrent const* const tor)
|
|
|
|
{
|
|
|
|
return tor != nullptr && pred_in(tor);
|
|
|
|
};
|
|
|
|
|
|
|
|
auto vec = std::vector<tr_torrent*>{};
|
|
|
|
vec.reserve(size());
|
|
|
|
std::copy_if(std::begin(by_id_), std::end(by_id_), std::back_inserter(vec), pred);
|
|
|
|
return vec;
|
|
|
|
}
|
|
|
|
|
|
|
|
[[nodiscard]] auto get_all() const
|
|
|
|
{
|
|
|
|
return get_matching([](tr_torrent const*) { return true; });
|
2023-10-25 17:42:14 +00:00
|
|
|
}
|
|
|
|
|
2022-03-01 23:06:29 +00:00
|
|
|
private:
|
|
|
|
std::vector<tr_torrent*> by_hash_;
|
|
|
|
|
2022-06-17 15:43:04 +00:00
|
|
|
// This is a lookup table where by_id_[id]->id() == id.
|
2022-03-01 23:06:29 +00:00
|
|
|
// There is a small tradeoff here -- lookup is O(1) at the cost
|
|
|
|
// of a wasted slot in the lookup table whenever a torrent is
|
|
|
|
// removed. This improves speed for all use cases at the cost of
|
|
|
|
// wasting a small amount of memory in uncommon use cases, e.g. a
|
2022-03-24 05:18:41 +00:00
|
|
|
// long-lived session where thousands of torrents are removed.
|
|
|
|
//
|
|
|
|
// Insert an empty pointer at by_id_[0] to ensure that the first
|
|
|
|
// added torrent doesn't get an ID of 0; ie, that every torrent has
|
|
|
|
// a positive ID number. This constraint isn't needed by libtransmission
|
|
|
|
// code but the ID is exported in the RPC API to 3rd party clients that
|
|
|
|
// may be testing for >0 as a validity check.
|
|
|
|
std::vector<tr_torrent*> by_id_{ nullptr };
|
2022-03-01 23:06:29 +00:00
|
|
|
|
2022-06-17 15:43:04 +00:00
|
|
|
std::vector<std::pair<tr_torrent_id_t, time_t>> removed_;
|
2022-03-01 23:06:29 +00:00
|
|
|
};
|