│ │ │
set_piece_hashes()
│ │ │
Declared in "libtorrent/create_torrent.hpp"
│ │ │
│ │ │ -void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ +inline void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ + , std::function<void(piece_index_t)> const& f);
│ │ │ +inline void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ , settings_interface const& settings
│ │ │ - , std::function<void(piece_index_t)> const& f, error_code& ec);
│ │ │ + , std::function<void(piece_index_t)> const& f);
│ │ │ void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ , std::function<void(piece_index_t)> const& f, error_code& ec);
│ │ │ -inline void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ - , std::function<void(piece_index_t)> const& f);
│ │ │ +inline void set_piece_hashes (create_torrent& t, std::string const& p, error_code& ec);
│ │ │ void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ , settings_interface const& settings, disk_io_constructor_type disk_io
│ │ │ , std::function<void(piece_index_t)> const& f, error_code& ec);
│ │ │ -inline void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ +void set_piece_hashes (create_torrent& t, std::string const& p
│ │ │ , settings_interface const& settings
│ │ │ - , std::function<void(piece_index_t)> const& f);
│ │ │ + , std::function<void(piece_index_t)> const& f, error_code& ec);
│ │ │ inline void set_piece_hashes (create_torrent& t, std::string const& p);
│ │ │ -inline void set_piece_hashes (create_torrent& t, std::string const& p, error_code& ec);
│ │ │
│ │ │
This function will assume that the files added to the torrent file exists at path
│ │ │ p, read those files and hash the content and set the hashes in the create_torrent
│ │ │ object. The optional function f is called in between every hash that is set. f
│ │ │ must have the following signature:
│ │ │
│ │ │ void Fun(piece_index_t);
│ │ │ ├── html2text {}
│ │ │ │ @@ -18,16 +18,16 @@
│ │ │ │ o _s_e_t___r_o_o_t___c_e_r_t_(_)
│ │ │ │ o _s_e_t___p_r_i_v_(_)_ _p_r_i_v_(_)
│ │ │ │ o _n_u_m___p_i_e_c_e_s_(_)
│ │ │ │ o _p_i_e_c_e___r_a_n_g_e_(_)
│ │ │ │ o _f_i_l_e___r_a_n_g_e_(_)
│ │ │ │ o _f_i_l_e___p_i_e_c_e___r_a_n_g_e_(_)
│ │ │ │ o _t_o_t_a_l___s_i_z_e_(_)
│ │ │ │ - o _p_i_e_c_e___l_e_n_g_t_h_(_)_ _p_i_e_c_e___s_i_z_e_(_)
│ │ │ │ - o _a_d_d___s_i_m_i_l_a_r___t_o_r_r_e_n_t_(_)_ _a_d_d___c_o_l_l_e_c_t_i_o_n_(_)
│ │ │ │ + o _p_i_e_c_e___s_i_z_e_(_)_ _p_i_e_c_e___l_e_n_g_t_h_(_)
│ │ │ │ + o _a_d_d___c_o_l_l_e_c_t_i_o_n_(_)_ _a_d_d___s_i_m_i_l_a_r___t_o_r_r_e_n_t_(_)
│ │ │ │ * _a_d_d___f_i_l_e_s_(_)
│ │ │ │ * _s_e_t___p_i_e_c_e___h_a_s_h_e_s_(_)
│ │ │ │ This section describes the functions and classes that are used to create
│ │ │ │ torrent files. It is a layered API with low level classes and higher level
│ │ │ │ convenience functions. A torrent is created in 4 steps:
│ │ │ │ 1. first the files that will be part of the torrent are determined.
│ │ │ │ 2. the torrent properties are set, such as tracker url, web seeds, DHT nodes
│ │ │ │ @@ -66,19 +66,19 @@
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._h_p_p"
│ │ │ │ This class holds state for creating a torrent. After having added all
│ │ │ │ information to it, call _c_r_e_a_t_e___t_o_r_r_e_n_t_:_:_g_e_n_e_r_a_t_e_(_) to generate the torrent. The
│ │ │ │ _e_n_t_r_y that's returned can then be bencoded into a .torrent file using _b_e_n_c_o_d_e
│ │ │ │ _(_).
│ │ │ │ struct create_torrent
│ │ │ │ {
│ │ │ │ + explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti);
│ │ │ │ explicit ccrreeaattee__ttoorrrreenntt (file_storage& fs, int piece_size = 0
│ │ │ │ , create_flags_t flags = {});
│ │ │ │ - explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti);
│ │ │ │ - entry ggeenneerraattee () const;
│ │ │ │ std::vector ggeenneerraattee__bbuuff () const;
│ │ │ │ + entry ggeenneerraattee () const;
│ │ │ │ file_storage const& ffiilleess () const;
│ │ │ │ void sseett__ccoommmmeenntt (char const* str);
│ │ │ │ void sseett__ccrreeaattoorr (char const* str);
│ │ │ │ void sseett__ccrreeaattiioonn__ddaattee (std::time_t timestamp);
│ │ │ │ void sseett__hhaasshh (piece_index_t index, sha1_hash const& h);
│ │ │ │ void sseett__hhaasshh22 (file_index_t file, piece_index_t::diff_type piece,
│ │ │ │ sha256_hash const& h);
│ │ │ │ @@ -94,32 +94,32 @@
│ │ │ │ int nnuumm__ppiieecceess () const;
│ │ │ │ piece_index_t eenndd__ppiieeccee () const;
│ │ │ │ index_range ppiieeccee__rraannggee () const noexcept;
│ │ │ │ file_index_t eenndd__ffiillee () const;
│ │ │ │ index_range ffiillee__rraannggee () const noexcept;
│ │ │ │ index_range ffiillee__ppiieeccee__rraannggee (file_index_t f);
│ │ │ │ std::int64_t ttoottaall__ssiizzee () const;
│ │ │ │ - int ppiieeccee__lleennggtthh () const;
│ │ │ │ int ppiieeccee__ssiizzee (piece_index_t i) const;
│ │ │ │ - void aadddd__ccoolllleeccttiioonn (string_view c);
│ │ │ │ + int ppiieeccee__lleennggtthh () const;
│ │ │ │ void aadddd__ssiimmiillaarr__ttoorrrreenntt (sha1_hash ih);
│ │ │ │ + void aadddd__ccoolllleeccttiioonn (string_view c);
│ │ │ │
│ │ │ │ static constexpr create_flags_t mmooddiiffiiccaattiioonn__ttiimmee = 2_bit;
│ │ │ │ static constexpr create_flags_t ssyymmlliinnkkss = 3_bit;
│ │ │ │ static constexpr create_flags_t vv22__oonnllyy = 5_bit;
│ │ │ │ static constexpr create_flags_t vv11__oonnllyy = 6_bit;
│ │ │ │ static constexpr create_flags_t ccaannoonniiccaall__ffiilleess = 7_bit;
│ │ │ │ static constexpr create_flags_t nnoo__aattttrriibbuutteess = 8_bit;
│ │ │ │ static constexpr create_flags_t ccaannoonniiccaall__ffiilleess__nnoo__ttaaiill__ppaaddddiinngg = 9_bit;
│ │ │ │ };
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ********** ccrreeaattee__ttoorrrreenntt(()) **********
│ │ │ │ +explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti);
│ │ │ │ explicit ccrreeaattee__ttoorrrreenntt (file_storage& fs, int piece_size = 0
│ │ │ │ , create_flags_t flags = {});
│ │ │ │ -explicit ccrreeaattee__ttoorrrreenntt (torrent_info const& ti);
│ │ │ │ The piece_size is the size of each piece in bytes. It must be a power of 2 and
│ │ │ │ a minimum of 16 kiB. If a piece size of 0 is specified, a piece_size will be
│ │ │ │ set automatically. Piece sizes greater than 128 MiB are considered unreasonable
│ │ │ │ and will be rejected (with an lt::system_error exception).
│ │ │ │ The flags arguments specifies options for the torrent creation. It can be any
│ │ │ │ combination of the flags defined by create_flags_t.
│ │ │ │ The _f_i_l_e___s_t_o_r_a_g_e (fs) parameter defines the files, sizes and their properties
│ │ │ │ @@ -132,16 +132,16 @@
│ │ │ │ (such as _s_e_t___h_a_s_h_(_)), will have any affect. Instead of using this overload,
│ │ │ │ consider using _w_r_i_t_e___t_o_r_r_e_n_t___f_i_l_e_(_) instead.
│ │ │ │ Warning
│ │ │ │ The _f_i_l_e___s_t_o_r_a_g_e and _t_o_r_r_e_n_t___i_n_f_o objects must stay alive for the entire
│ │ │ │ duration of the _c_r_e_a_t_e___t_o_r_r_e_n_t object.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ********** ggeenneerraattee(()) ggeenneerraattee__bbuuff(()) **********
│ │ │ │ -entry ggeenneerraattee () const;
│ │ │ │ std::vector ggeenneerraattee__bbuuff () const;
│ │ │ │ +entry ggeenneerraattee () const;
│ │ │ │ This function will generate the .torrent file as a bencode tree, or a bencoded
│ │ │ │ into a buffer. In order to encode the _e_n_t_r_y into a flat file, use the _b_e_n_c_o_d_e_(_)
│ │ │ │ function.
│ │ │ │ The function returning an _e_n_t_r_y may be useful to add custom entries to the
│ │ │ │ torrent file before bencoding it and saving it to disk.
│ │ │ │ Whether the resulting torrent object is v1, v2 or hybrid depends on whether any
│ │ │ │ of the v1_only or v2_only flags were set on the constructor. If neither were
│ │ │ │ @@ -263,24 +263,24 @@
│ │ │ │ for v2 and hybrid torrents only, the pieces in the specified file, specified as
│ │ │ │ delta from the first piece in the file. i.e. the first index is 0.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ********** ttoottaall__ssiizzee(()) **********
│ │ │ │ std::int64_t ttoottaall__ssiizzee () const;
│ │ │ │ the total number of bytes of all files and pad files
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ -********** ppiieeccee__lleennggtthh(()) ppiieeccee__ssiizzee(()) **********
│ │ │ │ -int ppiieeccee__lleennggtthh () const;
│ │ │ │ +********** ppiieeccee__ssiizzee(()) ppiieeccee__lleennggtthh(()) **********
│ │ │ │ int ppiieeccee__ssiizzee (piece_index_t i) const;
│ │ │ │ +int ppiieeccee__lleennggtthh () const;
│ │ │ │ piece_length() returns the piece size of all pieces but the last one.
│ │ │ │ piece_size() returns the size of the specified piece. these functions are just
│ │ │ │ forwarding to the associated _f_i_l_e___s_t_o_r_a_g_e.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ -********** aadddd__ssiimmiillaarr__ttoorrrreenntt(()) aadddd__ccoolllleeccttiioonn(()) **********
│ │ │ │ -void aadddd__ccoolllleeccttiioonn (string_view c);
│ │ │ │ +********** aadddd__ccoolllleeccttiioonn(()) aadddd__ssiimmiillaarr__ttoorrrreenntt(()) **********
│ │ │ │ void aadddd__ssiimmiillaarr__ttoorrrreenntt (sha1_hash ih);
│ │ │ │ +void aadddd__ccoolllleeccttiioonn (string_view c);
│ │ │ │ Add similar torrents (by info-hash) or collections of similar torrents. Similar
│ │ │ │ torrents are expected to share some files with this torrent. Torrents sharing a
│ │ │ │ collection name with this torrent are also expected to share files with this
│ │ │ │ torrent. A torrent may have more than one collection and more than one similar
│ │ │ │ torrents. For more information, see _B_E_P_ _3_8.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ modification_time
│ │ │ │ @@ -330,17 +330,17 @@
│ │ │ │ behavior deviates from the specification but was the way libtorrent
│ │ │ │ created torrents in version up to and including 2.0.7. This flag is here
│ │ │ │ for backwards compatibility.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ************ aadddd__ffiilleess(()) ************
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._h_p_p"
│ │ │ │ void aadddd__ffiilleess (file_storage& fs, std::string const& file
│ │ │ │ - , create_flags_t flags = {});
│ │ │ │ -void aadddd__ffiilleess (file_storage& fs, std::string const& file
│ │ │ │ , std::function p, create_flags_t flags = {});
│ │ │ │ +void aadddd__ffiilleess (file_storage& fs, std::string const& file
│ │ │ │ + , create_flags_t flags = {});
│ │ │ │ Adds the file specified by path to the _f_i_l_e___s_t_o_r_a_g_e object. In case path refers
│ │ │ │ to a directory, files will be added recursively from the directory.
│ │ │ │ If specified, the predicate p is called once for every file and directory that
│ │ │ │ is encountered. Files for which p returns true are added, and directories for
│ │ │ │ which p returns true are traversed. p must have the following signature:
│ │ │ │ bool Pred(std::string const& p);
│ │ │ │ The path that is passed in to the predicate is the full path of the file or
│ │ │ │ @@ -348,30 +348,30 @@
│ │ │ │ directories are traversed.
│ │ │ │ The ".." directory is never traversed.
│ │ │ │ The flags argument should be the same as the flags passed to the _c_r_e_a_t_e___t_o_r_r_e_n_t
│ │ │ │ constructor.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ************ sseett__ppiieeccee__hhaasshheess(()) ************
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_c_r_e_a_t_e___t_o_r_r_e_n_t_._h_p_p"
│ │ │ │ -void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ +inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ + , std::function const& f);
│ │ │ │ +inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ , settings_interface const& settings
│ │ │ │ - , std::function const& f, error_code& ec);
│ │ │ │ + , std::function const& f);
│ │ │ │ void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ , std::function const& f, error_code& ec);
│ │ │ │ -inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ - , std::function const& f);
│ │ │ │ +inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p,
│ │ │ │ +error_code& ec);
│ │ │ │ void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ , settings_interface const& settings, disk_io_constructor_type disk_io
│ │ │ │ , std::function const& f, error_code& ec);
│ │ │ │ -inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ +void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p
│ │ │ │ , settings_interface const& settings
│ │ │ │ - , std::function const& f);
│ │ │ │ + , std::function const& f, error_code& ec);
│ │ │ │ inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p);
│ │ │ │ -inline void sseett__ppiieeccee__hhaasshheess (create_torrent& t, std::string const& p,
│ │ │ │ -error_code& ec);
│ │ │ │ This function will assume that the files added to the torrent file exists at
│ │ │ │ path p, read those files and hash the content and set the hashes in the
│ │ │ │ create_torrent object. The optional function f is called in between every hash
│ │ │ │ that is set. f must have the following signature:
│ │ │ │ void Fun(piece_index_t);
│ │ │ │ The overloads taking a _s_e_t_t_i_n_g_s___p_a_c_k may be used to configure the underlying
│ │ │ │ disk access. Such as settings_pack::aio_threads.
│ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-Custom_Storage.html
│ │ │ @@ -28,69 +28,345 @@
│ │ │ | 2.0.11 |
│ │ │
│ │ │
│ │ │ home
│ │ │
│ │ │
Table of contents
│ │ │
│ │ │ -You have some control over session configuration through the session::apply_settings()
│ │ │ -member function. To change one or more configuration options, create a settings_pack
│ │ │ -object and fill it with the settings to be set and pass it in to session::apply_settings().
│ │ │ -The settings_pack object is a collection of settings updates that are applied
│ │ │ -to the session when passed to session::apply_settings(). It's empty when
│ │ │ -constructed.
│ │ │ -You have control over proxy and authorization settings and also the user-agent
│ │ │ -that will be sent to the tracker. The user-agent will also be used to identify the
│ │ │ -client with other peers.
│ │ │ -Each configuration option is named with an enum value inside the
│ │ │ -settings_pack class. These are the available settings:
│ │ │ -[report issue]
│ │ │ +
The disk I/O can be customized in libtorrent. In previous versions, the
│ │ │ +customization was at the level of each torrent. Now, the customization point
│ │ │ +is at the session level. All torrents added to a session will use the same
│ │ │ +disk I/O subsystem, as determined by the disk_io_constructor (in
│ │ │ +session_params).
│ │ │ +
This allows the disk subsystem to also customize threading and disk job
│ │ │ +management.
│ │ │ +
To customize the disk subsystem, implement disk_interface and provide a
│ │ │ +factory function to the session constructor (via session_params).
│ │ │ +
Example use:
│ │ │ +
│ │ │ +struct temp_storage
│ │ │ +{
│ │ │ + explicit temp_storage(lt::file_storage const& fs) : m_files(fs) {}
│ │ │ +
│ │ │ + lt::span<char const> readv(lt::peer_request const r, lt::storage_error& ec) const
│ │ │ + {
│ │ │ + auto const i = m_file_data.find(r.piece);
│ │ │ + if (i == m_file_data.end())
│ │ │ + {
│ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ + return {};
│ │ │ + }
│ │ │ + if (int(i->second.size()) <= r.start)
│ │ │ + {
│ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ + return {};
│ │ │ + }
│ │ │ + return { i->second.data() + r.start, std::min(r.length, int(i->second.size()) - r.start) };
│ │ │ + }
│ │ │ + void writev(lt::span<char const> const b, lt::piece_index_t const piece, int const offset)
│ │ │ + {
│ │ │ + auto& data = m_file_data[piece];
│ │ │ + if (data.empty())
│ │ │ + {
│ │ │ + int const size = piece_size(piece);
│ │ │ + data.resize(std::size_t(size));
│ │ │ + }
│ │ │ + TORRENT_ASSERT(offset + b.size() <= int(data.size()));
│ │ │ + std::memcpy(data.data() + offset, b.data(), std::size_t(b.size()));
│ │ │ + }
│ │ │ + lt::sha1_hash hash(lt::piece_index_t const piece
│ │ │ + , lt::span<lt::sha256_hash> const block_hashes, lt::storage_error& ec) const
│ │ │ + {
│ │ │ + auto const i = m_file_data.find(piece);
│ │ │ + if (i == m_file_data.end())
│ │ │ + {
│ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ + return {};
│ │ │ + }
│ │ │ + if (!block_hashes.empty())
│ │ │ + {
│ │ │ + int const piece_size2 = m_files.piece_size2(piece);
│ │ │ + int const blocks_in_piece2 = m_files.blocks_in_piece2(piece);
│ │ │ + char const* buf = i->second.data();
│ │ │ + std::int64_t offset = 0;
│ │ │ + for (int k = 0; k < blocks_in_piece2; ++k)
│ │ │ + {
│ │ │ + lt::hasher256 h2;
│ │ │ + std::ptrdiff_t const len2 = std::min(lt::default_block_size, int(piece_size2 - offset));
│ │ │ + h2.update({ buf, len2 });
│ │ │ + buf += len2;
│ │ │ + offset += len2;
│ │ │ + block_hashes[k] = h2.final();
│ │ │ + }
│ │ │ + }
│ │ │ + return lt::hasher(i->second).final();
│ │ │ + }
│ │ │ + lt::sha256_hash hash2(lt::piece_index_t const piece, int const offset, lt::storage_error& ec)
│ │ │ + {
│ │ │ + auto const i = m_file_data.find(piece);
│ │ │ + if (i == m_file_data.end())
│ │ │ + {
│ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ + return {};
│ │ │ + }
│ │ │ +
│ │ │ + int const piece_size = m_files.piece_size2(piece);
│ │ │ +
│ │ │ + std::ptrdiff_t const len = std::min(lt::default_block_size, piece_size - offset);
│ │ │ +
│ │ │ + lt::span<char const> b = {i->second.data() + offset, len};
│ │ │ + return lt::hasher256(b).final();
│ │ │ + }
│ │ │ +
│ │ │ +private:
│ │ │ + int piece_size(lt::piece_index_t piece) const
│ │ │ + {
│ │ │ + int const num_pieces = static_cast<int>((m_files.total_size() + m_files.piece_length() - 1) / m_files.piece_length());
│ │ │ + return static_cast<int>(piece) < num_pieces - 1
│ │ │ + ? m_files.piece_length() : static_cast<int>(m_files.total_size() - std::int64_t(num_pieces - 1) * m_files.piece_length());
│ │ │ + }
│ │ │ +
│ │ │ + lt::file_storage const& m_files;
│ │ │ + std::map<lt::piece_index_t, std::vector<char>> m_file_data;
│ │ │ +};
│ │ │ +
│ │ │ +lt::storage_index_t pop(std::vector<lt::storage_index_t>& q)
│ │ │ +{
│ │ │ + TORRENT_ASSERT(!q.empty());
│ │ │ + lt::storage_index_t const ret = q.back();
│ │ │ + q.pop_back();
│ │ │ + return ret;
│ │ │ +}
│ │ │ +
│ │ │ +struct temp_disk_io final : lt::disk_interface
│ │ │ + , lt::buffer_allocator_interface
│ │ │ +{
│ │ │ + explicit temp_disk_io(lt::io_context& ioc): m_ioc(ioc) {}
│ │ │ +
│ │ │ + void settings_updated() override {}
│ │ │ +
│ │ │ + lt::storage_holder new_torrent(lt::storage_params const& params
│ │ │ + , std::shared_ptr<void> const&) override
│ │ │ + {
│ │ │ + lt::storage_index_t const idx = m_free_slots.empty()
│ │ │ + ? m_torrents.end_index()
│ │ │ + : pop(m_free_slots);
│ │ │ + auto storage = std::make_unique<temp_storage>(params.files);
│ │ │ + if (idx == m_torrents.end_index()) m_torrents.emplace_back(std::move(storage));
│ │ │ + else m_torrents[idx] = std::move(storage);
│ │ │ + return lt::storage_holder(idx, *this);
│ │ │ + }
│ │ │ +
│ │ │ + void remove_torrent(lt::storage_index_t const idx) override
│ │ │ + {
│ │ │ + m_torrents[idx].reset();
│ │ │ + m_free_slots.push_back(idx);
│ │ │ + }
│ │ │ +
│ │ │ + void abort(bool) override {}
│ │ │ +
│ │ │ + void async_read(lt::storage_index_t storage, lt::peer_request const& r
│ │ │ + , std::function<void(lt::disk_buffer_holder block, lt::storage_error const& se)> handler
│ │ │ + , lt::disk_job_flags_t) override
│ │ │ + {
│ │ │ + lt::storage_error error;
│ │ │ + lt::span<char const> b = m_torrents[storage]->readv(r, error);
│ │ │ +
│ │ │ + post(m_ioc, [handler, error, b, this]
│ │ │ + { handler(lt::disk_buffer_holder(*this, const_cast<char*>(b.data()), int(b.size())), error); });
│ │ │ + }
│ │ │ +
│ │ │ + bool async_write(lt::storage_index_t storage, lt::peer_request const& r
│ │ │ + , char const* buf, std::shared_ptr<lt::disk_observer>
│ │ │ + , std::function<void(lt::storage_error const&)> handler
│ │ │ + , lt::disk_job_flags_t) override
│ │ │ + {
│ │ │ + lt::span<char const> const b = { buf, r.length };
│ │ │ +
│ │ │ + m_torrents[storage]->writev(b, r.piece, r.start);
│ │ │ +
│ │ │ + post(m_ioc, [=]{ handler(lt::storage_error()); });
│ │ │ + return false;
│ │ │ + }
│ │ │ +
│ │ │ + void async_hash(lt::storage_index_t storage, lt::piece_index_t const piece
│ │ │ + , lt::span<lt::sha256_hash> block_hashes, lt::disk_job_flags_t
│ │ │ + , std::function<void(lt::piece_index_t, lt::sha1_hash const&, lt::storage_error const&)> handler) override
│ │ │ + {
│ │ │ + lt::storage_error error;
│ │ │ + lt::sha1_hash const hash = m_torrents[storage]->hash(piece, block_hashes, error);
│ │ │ + post(m_ioc, [=]{ handler(piece, hash, error); });
│ │ │ + }
│ │ │ +
│ │ │ + void async_hash2(lt::storage_index_t storage, lt::piece_index_t const piece
│ │ │ + , int const offset, lt::disk_job_flags_t
│ │ │ + , std::function<void(lt::piece_index_t, lt::sha256_hash const&, lt::storage_error const&)> handler) override
│ │ │ + {
│ │ │ + lt::storage_error error;
│ │ │ + lt::sha256_hash const hash = m_torrents[storage]->hash2(piece, offset, error);
│ │ │ + post(m_ioc, [=]{ handler(piece, hash, error); });
│ │ │ + }
│ │ │ +
│ │ │ + void async_move_storage(lt::storage_index_t, std::string p, lt::move_flags_t
│ │ │ + , std::function<void(lt::status_t, std::string const&, lt::storage_error const&)> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, [=]{
│ │ │ + handler(lt::status_t::fatal_disk_error, p
│ │ │ + , lt::storage_error(lt::error_code(boost::system::errc::operation_not_supported, lt::system_category())));
│ │ │ + });
│ │ │ + }
│ │ │ +
│ │ │ + void async_release_files(lt::storage_index_t, std::function<void()>) override {}
│ │ │ +
│ │ │ + void async_delete_files(lt::storage_index_t, lt::remove_flags_t
│ │ │ + , std::function<void(lt::storage_error const&)> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, [=]{ handler(lt::storage_error()); });
│ │ │ + }
│ │ │ +
│ │ │ + void async_check_files(lt::storage_index_t
│ │ │ + , lt::add_torrent_params const*
│ │ │ + , lt::aux::vector<std::string, lt::file_index_t>
│ │ │ + , std::function<void(lt::status_t, lt::storage_error const&)> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, [=]{ handler(lt::status_t::no_error, lt::storage_error()); });
│ │ │ + }
│ │ │ +
│ │ │ + void async_rename_file(lt::storage_index_t
│ │ │ + , lt::file_index_t const idx
│ │ │ + , std::string const name
│ │ │ + , std::function<void(std::string const&, lt::file_index_t, lt::storage_error const&)> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, [=]{ handler(name, idx, lt::storage_error()); });
│ │ │ + }
│ │ │ +
│ │ │ + void async_stop_torrent(lt::storage_index_t, std::function<void()> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, handler);
│ │ │ + }
│ │ │ +
│ │ │ + void async_set_file_priority(lt::storage_index_t
│ │ │ + , lt::aux::vector<lt::download_priority_t, lt::file_index_t> prio
│ │ │ + , std::function<void(lt::storage_error const&
│ │ │ + , lt::aux::vector<lt::download_priority_t, lt::file_index_t>)> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, [=]{
│ │ │ + handler(lt::storage_error(lt::error_code(
│ │ │ + boost::system::errc::operation_not_supported, lt::system_category())), std::move(prio));
│ │ │ + });
│ │ │ + }
│ │ │ +
│ │ │ + void async_clear_piece(lt::storage_index_t, lt::piece_index_t index
│ │ │ + , std::function<void(lt::piece_index_t)> handler) override
│ │ │ + {
│ │ │ + post(m_ioc, [=]{ handler(index); });
│ │ │ + }
│ │ │ +
│ │ │ + void free_disk_buffer(char*) override
│ │ │ + {
│ │ │ + }
│ │ │ +
│ │ │ + void update_stats_counters(lt::counters&) const override {}
│ │ │ +
│ │ │ + std::vector<lt::open_file_state> get_status(lt::storage_index_t) const override
│ │ │ + { return {}; }
│ │ │ +
│ │ │ + void submit_jobs() override {}
│ │ │ +
│ │ │ +private:
│ │ │ +
│ │ │ + lt::aux::vector<std::shared_ptr<temp_storage>, lt::storage_index_t> m_torrents;
│ │ │ +
│ │ │ + std::vector<lt::storage_index_t> m_free_slots;
│ │ │ +
│ │ │ + lt::io_context& m_ioc;
│ │ │ +};
│ │ │ +
│ │ │ +std::unique_ptr<lt::disk_interface> temp_disk_constructor(
│ │ │ + lt::io_context& ioc, lt::settings_interface const&, lt::counters&)
│ │ │ +{
│ │ │ + return std::make_unique<temp_disk_io>(ioc);
│ │ │ +}
│ │ │ +
│ │ │ +
[report issue]
│ │ │ +
settings_interface
│ │ │ +
Declared in "libtorrent/settings_pack.hpp"
│ │ │ +
the common interface to settings_pack and the internal representation of
│ │ │ +settings.
│ │ │ +
│ │ │ +struct settings_interface
│ │ │ +{
│ │ │ + virtual void set_str (int name, std::string val) = 0;
│ │ │ + virtual void set_bool (int name, bool val) = 0;
│ │ │ + virtual void set_int (int name, int val) = 0;
│ │ │ + virtual bool has_val (int name) const = 0;
│ │ │ + virtual bool get_bool (int name) const = 0;
│ │ │ + virtual std::string const& get_str (int name) const = 0;
│ │ │ + virtual int get_int (int name) const = 0;
│ │ │ +};
│ │ │ +
│ │ │ +
[report issue]
│ │ │ +
│ │ │
open_file_state
│ │ │
Declared in "libtorrent/disk_interface.hpp"
│ │ │
this contains information about a file that's currently open by the
│ │ │ libtorrent disk I/O subsystem. It's associated with a single torrent.
│ │ │
│ │ │ struct open_file_state
│ │ │ {
│ │ │ @@ -199,18 +475,18 @@
│ │ │ remove_torrent()
│ │ │
│ │ │ virtual void remove_torrent (storage_index_t) = 0;
│ │ │
│ │ │ remove the storage with the specified index. This is not expected to
│ │ │ delete any files from disk, just to clean up any resources associated
│ │ │ with the specified storage.
│ │ │ -
│ │ │ -[report issue]
│ │ │ -
│ │ │ -
async_write() async_read()
│ │ │ +
│ │ │ +
[report issue]
│ │ │ +
│ │ │ +
async_read() async_write()
│ │ │
│ │ │ virtual bool async_write (storage_index_t storage, peer_request const& r
│ │ │ , char const* buf, std::shared_ptr<disk_observer> o
│ │ │ , std::function<void(storage_error const&)> handler
│ │ │ , disk_job_flags_t flags = {}) = 0;
│ │ │ virtual void async_read (storage_index_t storage, peer_request const& r
│ │ │ , std::function<void(disk_buffer_holder, storage_error const&)> handler
│ │ │ @@ -469,22 +745,22 @@
│ │ │ internal libtorrent torrent object to tie the storage object allocated
│ │ │ for a torrent to the lifetime of the internal torrent object. When a
│ │ │ torrent is removed from the session, this holder is destructed and will
│ │ │ inform the disk object.
│ │ │
│ │ │ struct storage_holder
│ │ │ {
│ │ │ - storage_holder (storage_index_t idx, disk_interface& disk_io);
│ │ │ storage_holder () = default;
│ │ │ + storage_holder (storage_index_t idx, disk_interface& disk_io);
│ │ │ ~storage_holder ();
│ │ │ explicit operator bool () const;
│ │ │ operator storage_index_t () const;
│ │ │ void reset ();
│ │ │ - storage_holder (storage_holder const&) = delete;
│ │ │ storage_holder& operator= (storage_holder const&) = delete;
│ │ │ + storage_holder (storage_holder const&) = delete;
│ │ │ storage_holder (storage_holder&& rhs) noexcept;
│ │ │ storage_holder& operator= (storage_holder&& rhs) noexcept;
│ │ │ };
│ │ │
│ │ │ [report issue]
│ │ │
│ │ │
disk_observer
│ │ │ @@ -524,18 +800,18 @@
│ │ │
The disk buffer holder acts like a unique_ptr that frees a disk buffer
│ │ │ when it's destructed
│ │ │
If this buffer holder is moved-from, default constructed or reset,
│ │ │ data() will return nullptr.
│ │ │
│ │ │ struct disk_buffer_holder
│ │ │ {
│ │ │ - disk_buffer_holder (disk_buffer_holder&&) noexcept;
│ │ │ disk_buffer_holder& operator= (disk_buffer_holder&&) & noexcept;
│ │ │ - disk_buffer_holder (disk_buffer_holder const&) = delete;
│ │ │ + disk_buffer_holder (disk_buffer_holder&&) noexcept;
│ │ │ disk_buffer_holder& operator= (disk_buffer_holder const&) = delete;
│ │ │ + disk_buffer_holder (disk_buffer_holder const&) = delete;
│ │ │ disk_buffer_holder (buffer_allocator_interface& alloc
│ │ │ , char* buf, int sz) noexcept;
│ │ │ disk_buffer_holder () noexcept = default;
│ │ │ ~disk_buffer_holder ();
│ │ │ char* data () const noexcept;
│ │ │ void reset ();
│ │ │ void swap (disk_buffer_holder& h) noexcept;
│ │ │ @@ -600,34 +876,16 @@
│ │ │
│ │ │
bool()
│ │ │
│ │ │ explicit operator bool () const noexcept;
│ │ │
│ │ │
implicitly convertible to true if the object is currently holding a
│ │ │ buffer
│ │ │ -
[report issue]
│ │ │ -
│ │ │ -
│ │ │ -
settings_interface
│ │ │ -
Declared in "libtorrent/settings_pack.hpp"
│ │ │ -
the common interface to settings_pack and the internal representation of
│ │ │ -settings.
│ │ │ -
│ │ │ -struct settings_interface
│ │ │ -{
│ │ │ - virtual void set_int (int name, int val) = 0;
│ │ │ - virtual bool has_val (int name) const = 0;
│ │ │ - virtual void set_str (int name, std::string val) = 0;
│ │ │ - virtual void set_bool (int name, bool val) = 0;
│ │ │ - virtual int get_int (int name) const = 0;
│ │ │ - virtual std::string const& get_str (int name) const = 0;
│ │ │ - virtual bool get_bool (int name) const = 0;
│ │ │ -};
│ │ │ -
│ │ │
[report issue]
│ │ │ +
│ │ │
│ │ │
file_open_mode_t
│ │ │
Declared in "libtorrent/disk_interface.hpp"
│ │ │
│ │ │ - read_only
│ │ │ - open the file for reading only
│ │ │
│ │ │ ├── html2text {}
│ │ │ │ @@ -1,17 +1,18 @@
│ │ │ │ >
│ │ │ │ _[_l_i_b_t_o_r_r_e_n_t_ _l_o_g_o_]
│ │ │ │ VVeerrssiioonn:: 2.0.11
│ │ │ │ _h_o_m_e
│ │ │ │ Table of contents
│ │ │ │ + * _s_e_t_t_i_n_g_s___i_n_t_e_r_f_a_c_e
│ │ │ │ * _o_p_e_n___f_i_l_e___s_t_a_t_e
│ │ │ │ * _d_i_s_k___i_n_t_e_r_f_a_c_e
│ │ │ │ o _n_e_w___t_o_r_r_e_n_t_(_)
│ │ │ │ o _r_e_m_o_v_e___t_o_r_r_e_n_t_(_)
│ │ │ │ - o _a_s_y_n_c___w_r_i_t_e_(_)_ _a_s_y_n_c___r_e_a_d_(_)
│ │ │ │ + o _a_s_y_n_c___r_e_a_d_(_)_ _a_s_y_n_c___w_r_i_t_e_(_)
│ │ │ │ o _a_s_y_n_c___h_a_s_h_(_)
│ │ │ │ o _a_s_y_n_c___h_a_s_h_2_(_)
│ │ │ │ o _a_s_y_n_c___m_o_v_e___s_t_o_r_a_g_e_(_)
│ │ │ │ o _a_s_y_n_c___r_e_l_e_a_s_e___f_i_l_e_s_(_)
│ │ │ │ o _a_s_y_n_c___c_h_e_c_k___f_i_l_e_s_(_)
│ │ │ │ o _a_s_y_n_c___s_t_o_p___t_o_r_r_e_n_t_(_)
│ │ │ │ o _a_s_y_n_c___r_e_n_a_m_e___f_i_l_e_(_)
│ │ │ │ @@ -32,28 +33,322 @@
│ │ │ │ o _d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_(_)
│ │ │ │ o _~_d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_(_)
│ │ │ │ o _d_a_t_a_(_)
│ │ │ │ o _r_e_s_e_t_(_)
│ │ │ │ o _s_w_a_p_(_)
│ │ │ │ o _i_s___m_u_t_a_b_l_e_(_)
│ │ │ │ o _b_o_o_l_(_)
│ │ │ │ - * _s_e_t_t_i_n_g_s___i_n_t_e_r_f_a_c_e
│ │ │ │ * _f_i_l_e___o_p_e_n___m_o_d_e___t
│ │ │ │ -You have some control over _s_e_s_s_i_o_n configuration through the session::
│ │ │ │ -apply_settings() member function. To change one or more configuration options,
│ │ │ │ -create a _s_e_t_t_i_n_g_s___p_a_c_k object and fill it with the settings to be set and pass
│ │ │ │ -it in to session::apply_settings().
│ │ │ │ -The _s_e_t_t_i_n_g_s___p_a_c_k object is a collection of settings updates that are applied
│ │ │ │ -to the _s_e_s_s_i_o_n when passed to session::apply_settings(). It's empty when
│ │ │ │ -constructed.
│ │ │ │ -You have control over proxy and authorization settings and also the user-agent
│ │ │ │ -that will be sent to the tracker. The user-agent will also be used to identify
│ │ │ │ -the client with other peers.
│ │ │ │ -Each configuration option is named with an enum value inside the _s_e_t_t_i_n_g_s___p_a_c_k
│ │ │ │ -class. These are the available settings:
│ │ │ │ +The disk I/O can be customized in libtorrent. In previous versions, the
│ │ │ │ +customization was at the level of each torrent. Now, the customization point is
│ │ │ │ +at the _s_e_s_s_i_o_n level. All torrents added to a _s_e_s_s_i_o_n will use the same disk I/
│ │ │ │ +O subsystem, as determined by the disk_io_constructor (in _s_e_s_s_i_o_n___p_a_r_a_m_s).
│ │ │ │ +This allows the disk subsystem to also customize threading and disk job
│ │ │ │ +management.
│ │ │ │ +To customize the disk subsystem, implement _d_i_s_k___i_n_t_e_r_f_a_c_e and provide a factory
│ │ │ │ +function to the _s_e_s_s_i_o_n constructor (via _s_e_s_s_i_o_n___p_a_r_a_m_s).
│ │ │ │ +Example use:
│ │ │ │ +struct temp_storage
│ │ │ │ +{
│ │ │ │ + explicit temp_storage(lt::file_storage const& fs) : m_files(fs) {}
│ │ │ │ +
│ │ │ │ + lt::span
readv(lt::peer_request const r, lt::storage_error& ec)
│ │ │ │ +const
│ │ │ │ + {
│ │ │ │ + auto const i = m_file_data.find(r.piece);
│ │ │ │ + if (i == m_file_data.end())
│ │ │ │ + {
│ │ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ │ + return {};
│ │ │ │ + }
│ │ │ │ + if (int(i->second.size()) <= r.start)
│ │ │ │ + {
│ │ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ │ + return {};
│ │ │ │ + }
│ │ │ │ + return { i->second.data() + r.start, std::min(r.length, int(i->second.size
│ │ │ │ +()) - r.start) };
│ │ │ │ + }
│ │ │ │ + void writev(lt::span const b, lt::piece_index_t const piece, int
│ │ │ │ +const offset)
│ │ │ │ + {
│ │ │ │ + auto& data = m_file_data[piece];
│ │ │ │ + if (data.empty())
│ │ │ │ + {
│ │ │ │ + // allocate the whole piece, otherwise we'll invalidate the pointers
│ │ │ │ + // we have returned back to libtorrent
│ │ │ │ + int const size = piece_size(piece);
│ │ │ │ + data.resize(std::size_t(size));
│ │ │ │ + }
│ │ │ │ + TORRENT_ASSERT(offset + b.size() <= int(data.size()));
│ │ │ │ + std::memcpy(data.data() + offset, b.data(), std::size_t(b.size()));
│ │ │ │ + }
│ │ │ │ + lt::sha1_hash hash(lt::piece_index_t const piece
│ │ │ │ + , lt::span const block_hashes, lt::storage_error& ec)
│ │ │ │ +const
│ │ │ │ + {
│ │ │ │ + auto const i = m_file_data.find(piece);
│ │ │ │ + if (i == m_file_data.end())
│ │ │ │ + {
│ │ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ │ + return {};
│ │ │ │ + }
│ │ │ │ + if (!block_hashes.empty())
│ │ │ │ + {
│ │ │ │ + int const piece_size2 = m_files.piece_size2(piece);
│ │ │ │ + int const blocks_in_piece2 = m_files.blocks_in_piece2(piece);
│ │ │ │ + char const* buf = i->second.data();
│ │ │ │ + std::int64_t offset = 0;
│ │ │ │ + for (int k = 0; k < blocks_in_piece2; ++k)
│ │ │ │ + {
│ │ │ │ + lt::hasher256 h2;
│ │ │ │ + std::ptrdiff_t const len2 = std::min(lt::default_block_size, int
│ │ │ │ +(piece_size2 - offset));
│ │ │ │ + h2.update({ buf, len2 });
│ │ │ │ + buf += len2;
│ │ │ │ + offset += len2;
│ │ │ │ + block_hashes[k] = h2.final();
│ │ │ │ + }
│ │ │ │ + }
│ │ │ │ + return lt::hasher(i->second).final();
│ │ │ │ + }
│ │ │ │ + lt::sha256_hash hash2(lt::piece_index_t const piece, int const offset, lt::
│ │ │ │ +storage_error& ec)
│ │ │ │ + {
│ │ │ │ + auto const i = m_file_data.find(piece);
│ │ │ │ + if (i == m_file_data.end())
│ │ │ │ + {
│ │ │ │ + ec.operation = lt::operation_t::file_read;
│ │ │ │ + ec.ec = boost::asio::error::eof;
│ │ │ │ + return {};
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + int const piece_size = m_files.piece_size2(piece);
│ │ │ │ +
│ │ │ │ + std::ptrdiff_t const len = std::min(lt::default_block_size, piece_size -
│ │ │ │ +offset);
│ │ │ │ +
│ │ │ │ + lt::span b = {i->second.data() + offset, len};
│ │ │ │ + return lt::hasher256(b).final();
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ +private:
│ │ │ │ + int piece_size(lt::piece_index_t piece) const
│ │ │ │ + {
│ │ │ │ + int const num_pieces = static_cast((m_files.total_size() +
│ │ │ │ +m_files.piece_length() - 1) / m_files.piece_length());
│ │ │ │ + return static_cast(piece) < num_pieces - 1
│ │ │ │ + ? m_files.piece_length() : static_cast(m_files.total_size() - std::
│ │ │ │ +int64_t(num_pieces - 1) * m_files.piece_length());
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + lt::file_storage const& m_files;
│ │ │ │ + std::map> m_file_data;
│ │ │ │ +};
│ │ │ │ +
│ │ │ │ +lt::storage_index_t pop(std::vector& q)
│ │ │ │ +{
│ │ │ │ + TORRENT_ASSERT(!q.empty());
│ │ │ │ + lt::storage_index_t const ret = q.back();
│ │ │ │ + q.pop_back();
│ │ │ │ + return ret;
│ │ │ │ +}
│ │ │ │ +
│ │ │ │ +struct temp_disk_io final : lt::disk_interface
│ │ │ │ + , lt::buffer_allocator_interface
│ │ │ │ +{
│ │ │ │ + explicit temp_disk_io(lt::io_context& ioc): m_ioc(ioc) {}
│ │ │ │ +
│ │ │ │ + void settings_updated() override {}
│ │ │ │ +
│ │ │ │ + lt::storage_holder new_torrent(lt::storage_params const& params
│ │ │ │ + , std::shared_ptr const&) override
│ │ │ │ + {
│ │ │ │ + lt::storage_index_t const idx = m_free_slots.empty()
│ │ │ │ + ? m_torrents.end_index()
│ │ │ │ + : pop(m_free_slots);
│ │ │ │ + auto storage = std::make_unique(params.files);
│ │ │ │ + if (idx == m_torrents.end_index()) m_torrents.emplace_back(std::move
│ │ │ │ +(storage));
│ │ │ │ + else m_torrents[idx] = std::move(storage);
│ │ │ │ + return lt::storage_holder(idx, *this);
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void remove_torrent(lt::storage_index_t const idx) override
│ │ │ │ + {
│ │ │ │ + m_torrents[idx].reset();
│ │ │ │ + m_free_slots.push_back(idx);
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void abort(bool) override {}
│ │ │ │ +
│ │ │ │ + void async_read(lt::storage_index_t storage, lt::peer_request const& r
│ │ │ │ + , std::function handler
│ │ │ │ + , lt::disk_job_flags_t) override
│ │ │ │ + {
│ │ │ │ + // this buffer is owned by the storage. It will remain valid for as
│ │ │ │ + // long as the torrent remains in the session. We don't need any lifetime
│ │ │ │ + // management of it.
│ │ │ │ + lt::storage_error error;
│ │ │ │ + lt::span b = m_torrents[storage]->readv(r, error);
│ │ │ │ +
│ │ │ │ + post(m_ioc, [handler, error, b, this]
│ │ │ │ + { handler(lt::disk_buffer_holder(*this, const_cast(b.data()), int
│ │ │ │ +(b.size())), error); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + bool async_write(lt::storage_index_t storage, lt::peer_request const& r
│ │ │ │ + , char const* buf, std::shared_ptr
│ │ │ │ + , std::function handler
│ │ │ │ + , lt::disk_job_flags_t) override
│ │ │ │ + {
│ │ │ │ + lt::span const b = { buf, r.length };
│ │ │ │ +
│ │ │ │ + m_torrents[storage]->writev(b, r.piece, r.start);
│ │ │ │ +
│ │ │ │ + post(m_ioc, [=]{ handler(lt::storage_error()); });
│ │ │ │ + return false;
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_hash(lt::storage_index_t storage, lt::piece_index_t const piece
│ │ │ │ + , lt::span block_hashes, lt::disk_job_flags_t
│ │ │ │ + , std::function handler) override
│ │ │ │ + {
│ │ │ │ + lt::storage_error error;
│ │ │ │ + lt::sha1_hash const hash = m_torrents[storage]->hash(piece, block_hashes,
│ │ │ │ +error);
│ │ │ │ + post(m_ioc, [=]{ handler(piece, hash, error); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_hash2(lt::storage_index_t storage, lt::piece_index_t const piece
│ │ │ │ + , int const offset, lt::disk_job_flags_t
│ │ │ │ + , std::function handler) override
│ │ │ │ + {
│ │ │ │ + lt::storage_error error;
│ │ │ │ + lt::sha256_hash const hash = m_torrents[storage]->hash2(piece, offset,
│ │ │ │ +error);
│ │ │ │ + post(m_ioc, [=]{ handler(piece, hash, error); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_move_storage(lt::storage_index_t, std::string p, lt::move_flags_t
│ │ │ │ + , std::function handler) override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, [=]{
│ │ │ │ + handler(lt::status_t::fatal_disk_error, p
│ │ │ │ + , lt::storage_error(lt::error_code(boost::system::errc::
│ │ │ │ +operation_not_supported, lt::system_category())));
│ │ │ │ + });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_release_files(lt::storage_index_t, std::function) override
│ │ │ │ +{}
│ │ │ │ +
│ │ │ │ + void async_delete_files(lt::storage_index_t, lt::remove_flags_t
│ │ │ │ + , std::function handler) override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, [=]{ handler(lt::storage_error()); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_check_files(lt::storage_index_t
│ │ │ │ + , lt::add_torrent_params const*
│ │ │ │ + , lt::aux::vector
│ │ │ │ + , std::function handler)
│ │ │ │ +override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, [=]{ handler(lt::status_t::no_error, lt::storage_error()); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_rename_file(lt::storage_index_t
│ │ │ │ + , lt::file_index_t const idx
│ │ │ │ + , std::string const name
│ │ │ │ + , std::function handler) override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, [=]{ handler(name, idx, lt::storage_error()); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_stop_torrent(lt::storage_index_t, std::function handler)
│ │ │ │ +override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, handler);
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_set_file_priority(lt::storage_index_t
│ │ │ │ + , lt::aux::vector prio
│ │ │ │ + , std::function)> handler)
│ │ │ │ +override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, [=]{
│ │ │ │ + handler(lt::storage_error(lt::error_code(
│ │ │ │ + boost::system::errc::operation_not_supported, lt::system_category())),
│ │ │ │ +std::move(prio));
│ │ │ │ + });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void async_clear_piece(lt::storage_index_t, lt::piece_index_t index
│ │ │ │ + , std::function handler) override
│ │ │ │ + {
│ │ │ │ + post(m_ioc, [=]{ handler(index); });
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + // implements buffer_allocator_interface
│ │ │ │ + void free_disk_buffer(char*) override
│ │ │ │ + {
│ │ │ │ + // never free any buffer. We only return buffers owned by the storage
│ │ │ │ + // object
│ │ │ │ + }
│ │ │ │ +
│ │ │ │ + void update_stats_counters(lt::counters&) const override {}
│ │ │ │ +
│ │ │ │ + std::vector get_status(lt::storage_index_t) const
│ │ │ │ +override
│ │ │ │ + { return {}; }
│ │ │ │ +
│ │ │ │ + void submit_jobs() override {}
│ │ │ │ +
│ │ │ │ +private:
│ │ │ │ +
│ │ │ │ + lt::aux::vector, lt::storage_index_t>
│ │ │ │ +m_torrents;
│ │ │ │ +
│ │ │ │ + // slots that are unused in the m_torrents vector
│ │ │ │ + std::vector m_free_slots;
│ │ │ │ +
│ │ │ │ + // callbacks are posted on this
│ │ │ │ + lt::io_context& m_ioc;
│ │ │ │ +};
│ │ │ │ +
│ │ │ │ +std::unique_ptr temp_disk_constructor(
│ │ │ │ + lt::io_context& ioc, lt::settings_interface const&, lt::counters&)
│ │ │ │ +{
│ │ │ │ + return std::make_unique(ioc);
│ │ │ │ +}
│ │ │ │ +[_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ +************ sseettttiinnggss__iinntteerrffaaccee ************
│ │ │ │ +Declared in "_l_i_b_t_o_r_r_e_n_t_/_s_e_t_t_i_n_g_s___p_a_c_k_._h_p_p"
│ │ │ │ +the common interface to _s_e_t_t_i_n_g_s___p_a_c_k and the internal representation of
│ │ │ │ +settings.
│ │ │ │ +struct settings_interface
│ │ │ │ +{
│ │ │ │ + virtual void sseett__ssttrr (int name, std::string val) = 0;
│ │ │ │ + virtual void sseett__bbooooll (int name, bool val) = 0;
│ │ │ │ + virtual void sseett__iinntt (int name, int val) = 0;
│ │ │ │ + virtual bool hhaass__vvaall (int name) const = 0;
│ │ │ │ + virtual bool ggeett__bbooooll (int name) const = 0;
│ │ │ │ + virtual std::string const& ggeett__ssttrr (int name) const = 0;
│ │ │ │ + virtual int ggeett__iinntt (int name) const = 0;
│ │ │ │ +};
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ************ ooppeenn__ffiillee__ssttaattee ************
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___i_n_t_e_r_f_a_c_e_._h_p_p"
│ │ │ │ this contains information about a file that's currently open by the libtorrent
│ │ │ │ disk I/O subsystem. It's associated with a single torrent.
│ │ │ │ struct open_file_state
│ │ │ │ {
│ │ │ │ @@ -159,15 +454,15 @@
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ********** rreemmoovvee__ttoorrrreenntt(()) **********
│ │ │ │ virtual void rreemmoovvee__ttoorrrreenntt (storage_index_t) = 0;
│ │ │ │ remove the storage with the specified index. This is not expected to delete any
│ │ │ │ files from disk, just to clean up any resources associated with the specified
│ │ │ │ storage.
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ -********** aassyynncc__wwrriittee(()) aassyynncc__rreeaadd(()) **********
│ │ │ │ +********** aassyynncc__rreeaadd(()) aassyynncc__wwrriittee(()) **********
│ │ │ │ virtual bool aassyynncc__wwrriittee (storage_index_t storage, peer_request const& r
│ │ │ │ , char const* buf, std::shared_ptr o
│ │ │ │ , std::function handler
│ │ │ │ , disk_job_flags_t flags = {}) = 0;
│ │ │ │ virtual void aassyynncc__rreeaadd (storage_index_t storage, peer_request const& r
│ │ │ │ , std::function handler
│ │ │ │ , disk_job_flags_t flags = {}) = 0;
│ │ │ │ @@ -361,22 +656,22 @@
│ │ │ │ a unique, owning, reference to the storage of a torrent in a disk io subsystem
│ │ │ │ (class that implements _d_i_s_k___i_n_t_e_r_f_a_c_e). This is held by the internal libtorrent
│ │ │ │ torrent object to tie the storage object allocated for a torrent to the
│ │ │ │ lifetime of the internal torrent object. When a torrent is removed from the
│ │ │ │ _s_e_s_s_i_o_n, this holder is destructed and will inform the disk object.
│ │ │ │ struct storage_holder
│ │ │ │ {
│ │ │ │ - ssttoorraaggee__hhoollddeerr (storage_index_t idx, disk_interface& disk_io);
│ │ │ │ ssttoorraaggee__hhoollddeerr () = default;
│ │ │ │ + ssttoorraaggee__hhoollddeerr (storage_index_t idx, disk_interface& disk_io);
│ │ │ │ ~~ssttoorraaggee__hhoollddeerr ();
│ │ │ │ explicit operator bbooooll () const;
│ │ │ │ operator ssttoorraaggee__iinnddeexx__tt () const;
│ │ │ │ void rreesseett ();
│ │ │ │ - ssttoorraaggee__hhoollddeerr (storage_holder const&) = delete;
│ │ │ │ storage_holder& ooppeerraattoorr== (storage_holder const&) = delete;
│ │ │ │ + ssttoorraaggee__hhoollddeerr (storage_holder const&) = delete;
│ │ │ │ ssttoorraaggee__hhoollddeerr (storage_holder&& rhs) noexcept;
│ │ │ │ storage_holder& ooppeerraattoorr== (storage_holder&& rhs) noexcept;
│ │ │ │ };
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ************ ddiisskk__oobbsseerrvveerr ************
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___o_b_s_e_r_v_e_r_._h_p_p"
│ │ │ │ struct disk_observer
│ │ │ │ @@ -403,18 +698,18 @@
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___b_u_f_f_e_r___h_o_l_d_e_r_._h_p_p"
│ │ │ │ The disk buffer holder acts like a unique_ptr that frees a disk buffer when
│ │ │ │ it's destructed
│ │ │ │ If this buffer holder is moved-from, default constructed or reset, data() will
│ │ │ │ return nullptr.
│ │ │ │ struct disk_buffer_holder
│ │ │ │ {
│ │ │ │ - ddiisskk__bbuuffffeerr__hhoollddeerr (disk_buffer_holder&&) noexcept;
│ │ │ │ disk_buffer_holder& ooppeerraattoorr== (disk_buffer_holder&&) & noexcept;
│ │ │ │ - ddiisskk__bbuuffffeerr__hhoollddeerr (disk_buffer_holder const&) = delete;
│ │ │ │ + ddiisskk__bbuuffffeerr__hhoollddeerr (disk_buffer_holder&&) noexcept;
│ │ │ │ disk_buffer_holder& ooppeerraattoorr== (disk_buffer_holder const&) = delete;
│ │ │ │ + ddiisskk__bbuuffffeerr__hhoollddeerr (disk_buffer_holder const&) = delete;
│ │ │ │ ddiisskk__bbuuffffeerr__hhoollddeerr (buffer_allocator_interface& alloc
│ │ │ │ , char* buf, int sz) noexcept;
│ │ │ │ ddiisskk__bbuuffffeerr__hhoollddeerr () noexcept = default;
│ │ │ │ ~~ddiisskk__bbuuffffeerr__hhoollddeerr ();
│ │ │ │ char* ddaattaa () const noexcept;
│ │ │ │ void rreesseett ();
│ │ │ │ void sswwaapp (disk_buffer_holder& h) noexcept;
│ │ │ │ @@ -454,29 +749,14 @@
│ │ │ │ bool iiss__mmuuttaabbllee () const noexcept;
│ │ │ │ if this returns true, the buffer may not be modified in place
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ********** bbooooll(()) **********
│ │ │ │ explicit operator bbooooll () const noexcept;
│ │ │ │ implicitly convertible to true if the object is currently holding a buffer
│ │ │ │ [_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ -************ sseettttiinnggss__iinntteerrffaaccee ************
│ │ │ │ -Declared in "_l_i_b_t_o_r_r_e_n_t_/_s_e_t_t_i_n_g_s___p_a_c_k_._h_p_p"
│ │ │ │ -the common interface to _s_e_t_t_i_n_g_s___p_a_c_k and the internal representation of
│ │ │ │ -settings.
│ │ │ │ -struct settings_interface
│ │ │ │ -{
│ │ │ │ - virtual void sseett__iinntt (int name, int val) = 0;
│ │ │ │ - virtual bool hhaass__vvaall (int name) const = 0;
│ │ │ │ - virtual void sseett__ssttrr (int name, std::string val) = 0;
│ │ │ │ - virtual void sseett__bbooooll (int name, bool val) = 0;
│ │ │ │ - virtual int ggeett__iinntt (int name) const = 0;
│ │ │ │ - virtual std::string const& ggeett__ssttrr (int name) const = 0;
│ │ │ │ - virtual bool ggeett__bbooooll (int name) const = 0;
│ │ │ │ -};
│ │ │ │ -[_r_e_p_o_r_t_ _i_s_s_u_e]
│ │ │ │ ************ ffiillee__ooppeenn__mmooddee__tt ************
│ │ │ │ Declared in "_l_i_b_t_o_r_r_e_n_t_/_d_i_s_k___i_n_t_e_r_f_a_c_e_._h_p_p"
│ │ │ │ read_only
│ │ │ │ open the file for reading only
│ │ │ │ write_only
│ │ │ │ open the file for writing only
│ │ │ │ read_write
│ │ ├── ./usr/share/doc/libtorrent-rasterbar-doc/html/reference-DHT.html
│ │ │ @@ -47,16 +47,16 @@
│ │ │ get_mutable_item()
│ │ │ put_mutable_item()
│ │ │ get_infohashes_sample()
│ │ │ tick()
│ │ │ counters()
│ │ │
│ │ │
│ │ │ -sign_mutable_item()
│ │ │ -dht_default_storage_constructor()
│ │ │ +dht_default_storage_constructor()
│ │ │ +sign_mutable_item()
│ │ │ announce_flags_t
│ │ │
│ │ │
│ │ │ [report issue]
│ │ │
│ │ │
counters()
│ │ │
│ │ │ virtual dht_storage_counters counters () const = 0;
│ │ │
│ │ │
return stats counters for the store
│ │ │ -
[report issue]
│ │ │ +[report issue]