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-01-20 18:27:56 +00:00
|
|
|
// or any future license endorsed by Mnemosyne LLC.
|
|
|
|
// License text can be found in the licenses/ folder.
|
2006-07-16 19:39:23 +00:00
|
|
|
|
2017-11-14 20:21:28 +00:00
|
|
|
#pragma once
|
|
|
|
|
2008-11-24 20:17:36 +00:00
|
|
|
#ifndef __TRANSMISSION__
|
2017-04-19 12:04:45 +00:00
|
|
|
#error only libtransmission should #include this header.
|
2008-11-24 20:17:36 +00:00
|
|
|
#endif
|
|
|
|
|
2021-11-25 18:26:51 +00:00
|
|
|
#include <algorithm>
|
2021-12-15 21:25:42 +00:00
|
|
|
#include <cstddef> // size_t
|
2024-03-30 19:45:00 +00:00
|
|
|
#include <cstdint>
|
|
|
|
#include <functional>
|
2021-11-25 18:26:51 +00:00
|
|
|
#include <optional>
|
2021-11-09 03:30:03 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2023-07-08 15:24:03 +00:00
|
|
|
#include "libtransmission/transmission.h"
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-07-08 15:24:03 +00:00
|
|
|
#include "libtransmission/block-info.h"
|
|
|
|
#include "libtransmission/bitfield.h"
|
|
|
|
#include "libtransmission/tr-macros.h"
|
2007-06-18 03:40:41 +00:00
|
|
|
|
2021-11-25 18:26:51 +00:00
|
|
|
/**
|
|
|
|
* @brief knows which blocks and pieces we have
|
|
|
|
*/
|
2021-10-06 14:26:07 +00:00
|
|
|
struct tr_completion
|
2009-01-02 17:01:55 +00:00
|
|
|
{
|
2024-03-30 19:45:00 +00:00
|
|
|
using PieceIsWantedFunc = std::function<bool(tr_piece_index_t piece)>;
|
2021-11-28 01:58:35 +00:00
|
|
|
|
2024-03-30 19:45:00 +00:00
|
|
|
tr_completion(PieceIsWantedFunc&& piece_is_wanted, tr_block_info const* block_info)
|
|
|
|
: piece_is_wanted_{ std::move(piece_is_wanted) }
|
2021-11-25 18:26:51 +00:00
|
|
|
, block_info_{ block_info }
|
2023-04-23 01:25:55 +00:00
|
|
|
, blocks_{ block_info_->block_count() }
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
blocks_.set_has_none();
|
2021-11-25 18:26:51 +00:00
|
|
|
}
|
|
|
|
|
2024-03-30 19:45:00 +00:00
|
|
|
tr_completion(tr_torrent const* tor, tr_block_info const* block_info);
|
|
|
|
|
2022-04-02 00:48:09 +00:00
|
|
|
[[nodiscard]] constexpr tr_bitfield const& blocks() const noexcept
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
return blocks_;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr bool has_all() const noexcept
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return has_metainfo() && blocks_.has_all();
|
2021-11-25 18:26:51 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] TR_CONSTEXPR20 bool has_block(tr_block_index_t block) const
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
return blocks_.test(block);
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] bool has_blocks(tr_block_span_t span) const
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
return blocks_.count(span.begin, span.end) == span.end - span.begin;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr bool has_none() const noexcept
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return !has_metainfo() || blocks_.has_none();
|
2021-11-25 18:26:51 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] bool has_piece(tr_piece_index_t piece) const
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return block_info_->piece_size() != 0 && count_missing_blocks_in_piece(piece) == 0;
|
2021-11-25 18:26:51 +00:00
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr uint64_t has_total() const noexcept
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
return size_now_;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] uint64_t has_valid() const;
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] auto left_until_done() const
|
2022-04-05 03:51:56 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return size_when_done() - has_total();
|
2022-04-05 03:51:56 +00:00
|
|
|
}
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr double percent_complete() const
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
auto const denom = block_info_->total_size();
|
2021-11-25 18:26:51 +00:00
|
|
|
return denom ? std::clamp(double(size_now_) / denom, 0.0, 1.0) : 0.0;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] double percent_done() const
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
auto const denom = size_when_done();
|
2021-11-25 18:26:51 +00:00
|
|
|
return denom ? std::clamp(double(size_now_) / denom, 0.0, 1.0) : 0.0;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] uint64_t size_when_done() const;
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2022-08-31 04:17:23 +00:00
|
|
|
[[nodiscard]] tr_completeness status() const
|
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
if (!has_metainfo())
|
2022-08-31 04:17:23 +00:00
|
|
|
{
|
|
|
|
return TR_LEECH;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
if (has_all())
|
2022-08-31 04:17:23 +00:00
|
|
|
{
|
|
|
|
return TR_SEED;
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
if (size_now_ == size_when_done())
|
2022-08-31 04:17:23 +00:00
|
|
|
{
|
|
|
|
return TR_PARTIAL_SEED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TR_LEECH;
|
|
|
|
}
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] std::vector<uint8_t> create_piece_bitfield() const;
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] size_t count_missing_blocks_in_piece(tr_piece_index_t piece) const
|
2023-01-27 20:25:08 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
auto const [begin, end] = block_info_->block_span_for_piece(piece);
|
2023-01-27 20:25:08 +00:00
|
|
|
return (end - begin) - blocks_.count(begin, end);
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] size_t count_missing_bytes_in_piece(tr_piece_index_t piece) const
|
2023-01-27 20:25:08 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return block_info_->piece_size(piece) - count_has_bytes_in_piece(piece);
|
2023-01-27 20:25:08 +00:00
|
|
|
}
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void amount_done(float* tab, size_t n_tabs) const;
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void add_block(tr_block_index_t block);
|
|
|
|
void add_piece(tr_piece_index_t piece);
|
|
|
|
void remove_piece(tr_piece_index_t piece);
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void set_has_piece(tr_piece_index_t i, bool has)
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
if (has)
|
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
add_piece(i);
|
2021-11-25 18:26:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
remove_piece(i);
|
2021-11-25 18:26:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void set_has_all() noexcept;
|
2022-02-14 19:17:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void set_blocks(tr_bitfield blocks);
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void invalidate_size_when_done()
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
size_when_done_.reset();
|
|
|
|
}
|
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] uint64_t count_has_bytes_in_span(tr_byte_span_t) const;
|
2021-12-26 18:43:27 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] constexpr bool has_metainfo() const noexcept
|
2021-11-25 18:26:51 +00:00
|
|
|
{
|
|
|
|
return !std::empty(blocks_);
|
|
|
|
}
|
|
|
|
|
2022-03-29 04:29:35 +00:00
|
|
|
private:
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] uint64_t compute_has_valid() const;
|
|
|
|
[[nodiscard]] uint64_t compute_size_when_done() const;
|
2022-07-04 16:48:54 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
[[nodiscard]] uint64_t count_has_bytes_in_piece(tr_piece_index_t piece) const
|
2022-07-04 16:48:54 +00:00
|
|
|
{
|
2023-04-23 01:25:55 +00:00
|
|
|
return count_has_bytes_in_span(block_info_->byte_span_for_piece(piece));
|
2022-07-04 16:48:54 +00:00
|
|
|
}
|
2021-11-25 18:26:51 +00:00
|
|
|
|
2023-04-23 01:25:55 +00:00
|
|
|
void remove_block(tr_block_index_t block);
|
2023-02-14 01:51:23 +00:00
|
|
|
|
2024-03-30 19:45:00 +00:00
|
|
|
PieceIsWantedFunc piece_is_wanted_;
|
2021-11-25 18:26:51 +00:00
|
|
|
tr_block_info const* block_info_;
|
|
|
|
|
|
|
|
tr_bitfield blocks_{ 0 };
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2021-12-15 15:53:20 +00:00
|
|
|
// Number of bytes we'll have when done downloading. [0..totalSize]
|
2021-11-25 18:26:51 +00:00
|
|
|
// Mutable because lazy-calculated
|
|
|
|
mutable std::optional<uint64_t> size_when_done_;
|
2011-03-28 16:31:05 +00:00
|
|
|
|
2021-12-15 15:53:20 +00:00
|
|
|
// Number of verified bytes we have right now. [0..totalSize]
|
2021-11-25 18:26:51 +00:00
|
|
|
// Mutable because lazy-calculated
|
|
|
|
mutable std::optional<uint64_t> has_valid_;
|
2008-09-23 19:11:04 +00:00
|
|
|
|
2021-11-25 18:26:51 +00:00
|
|
|
// Number of bytes we have now. [0..sizeWhenDone]
|
|
|
|
uint64_t size_now_ = 0;
|
2021-10-06 14:26:07 +00:00
|
|
|
};
|