forked from premiere/premiere-libtorrent
added add_piece() to inject data from external sources
This commit is contained in:
parent
3b7e484d6a
commit
14c142d997
|
@ -1,4 +1,5 @@
|
|||
|
||||
* added add_piece() function to inject data from external sources
|
||||
* add_tracker() function added to torrent_handle
|
||||
* if there is no working tracker, current_tracker is the
|
||||
tracker that is currently being tried
|
||||
|
|
|
@ -1717,6 +1717,9 @@ Its declaration looks like this::
|
|||
void rename_file(int index, boost::filesystem::wpath) const;
|
||||
storage_interface* get_storage_impl() const;
|
||||
|
||||
enum flags_t { overwrite_existing = 1 };
|
||||
void add_piece(int piece, char const* data, int flags = 0) const;
|
||||
|
||||
sha1_hash info_hash() const;
|
||||
|
||||
bool operator==(torrent_handle const&) const;
|
||||
|
@ -1868,6 +1871,27 @@ get_storage_impl()
|
|||
Returns the storage implementation for this torrent. This depends on the
|
||||
storage contructor function that was passed to ``session::add_torrent``.
|
||||
|
||||
add_piece()
|
||||
-----------
|
||||
|
||||
::
|
||||
|
||||
enum flags_t { overwrite_existing = 1 };
|
||||
void add_piece(int piece, char const* data, int flags = 0) const;
|
||||
|
||||
This function will write ``data`` to the storage as piece ``piece``, as if it had
|
||||
been downloaded from a peer. ``data`` is expected to point to a buffer of as many
|
||||
bytes as the size of the specified piece. The data in the buffer is copied and
|
||||
passed on to the disk IO thread to be written at a later point.
|
||||
|
||||
By default, data that's already been downloaded is not overwritten by this buffer. If
|
||||
you trust this data to be correct (and pass the piece hash check) you may pass the
|
||||
``overwrite_existing`` flag. This will instruct libtorrent to overwrite any data that
|
||||
may already have been downloaded with this data.
|
||||
|
||||
Since the data is written asynchronously, you may know that is passed or failed the
|
||||
hash check by waiting for ``piece_finished_alert`` or ``has_failed_alert``.
|
||||
|
||||
force_reannounce()
|
||||
------------------
|
||||
|
||||
|
|
|
@ -169,6 +169,11 @@ namespace libtorrent
|
|||
|
||||
int seed_rank(session_settings const& s) const;
|
||||
|
||||
enum flags_t { overwrite_existing = 1 };
|
||||
void add_piece(int piece, char const* data, int flags = 0);
|
||||
void on_disk_write_complete(int ret, disk_io_job const& j
|
||||
, peer_request p);
|
||||
|
||||
storage_mode_t storage_mode() const { return m_storage_mode; }
|
||||
storage_interface* get_storage()
|
||||
{
|
||||
|
|
|
@ -314,6 +314,9 @@ namespace libtorrent
|
|||
|
||||
torrent_handle() {}
|
||||
|
||||
enum flags_t { overwrite_existing = 1 };
|
||||
void add_piece(int piece, char const* data, int flags = 0) const;
|
||||
|
||||
void get_full_peer_list(std::vector<peer_list_entry>& v) const;
|
||||
void get_peer_info(std::vector<peer_info>& v) const;
|
||||
torrent_status status() const;
|
||||
|
|
|
@ -371,6 +371,71 @@ namespace libtorrent
|
|||
disconnect_all();
|
||||
}
|
||||
|
||||
void torrent::add_piece(int piece, char const* data, int flags)
|
||||
{
|
||||
TORRENT_ASSERT(piece >= 0 && piece < m_torrent_file->num_pieces());
|
||||
int piece_size = m_torrent_file->piece_size(piece);
|
||||
int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size;
|
||||
|
||||
peer_request p;
|
||||
p.piece = piece;
|
||||
p.start = 0;
|
||||
picker().inc_refcount(piece);
|
||||
for (int i = 0; i < blocks_in_piece; ++i, p.start += m_block_size)
|
||||
{
|
||||
if (picker().is_finished(piece_block(piece, i))
|
||||
&& (flags & torrent::overwrite_existing) == 0)
|
||||
continue;
|
||||
|
||||
p.length = (std::min)(piece_size - p.start, m_block_size);
|
||||
char* buffer = m_ses.allocate_disk_buffer();
|
||||
// out of memory
|
||||
if (buffer == 0) return;
|
||||
disk_buffer_holder holder(m_ses, buffer);
|
||||
std::memcpy(buffer, data + p.start, p.length);
|
||||
filesystem().async_write(p, holder, bind(&torrent::on_disk_write_complete
|
||||
, shared_from_this(), _1, _2, p));
|
||||
piece_block block(piece, i);
|
||||
picker().mark_as_downloading(block, 0, piece_picker::fast);
|
||||
picker().mark_as_writing(block, 0);
|
||||
}
|
||||
picker().dec_refcount(piece);
|
||||
}
|
||||
|
||||
void torrent::on_disk_write_complete(int ret, disk_io_job const& j
|
||||
, peer_request p)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_abort)
|
||||
{
|
||||
piece_block block_finished(p.piece, p.start / m_block_size);
|
||||
return;
|
||||
}
|
||||
|
||||
piece_block block_finished(p.piece, p.start / m_block_size);
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
if (has_picker()) picker().write_failed(block_finished);
|
||||
if (alerts().should_post<file_error_alert>())
|
||||
alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.str));
|
||||
set_error(j.str);
|
||||
pause();
|
||||
return;
|
||||
}
|
||||
picker().mark_as_finished(block_finished, 0);
|
||||
|
||||
// did we just finish the piece?
|
||||
if (picker().is_piece_finished(p.piece))
|
||||
{
|
||||
async_verify_piece(p.piece, bind(&torrent::piece_finished, shared_from_this()
|
||||
, p.piece, _1));
|
||||
}
|
||||
}
|
||||
|
||||
peer_request torrent::to_req(piece_block const& p)
|
||||
{
|
||||
int block_offset = p.block_index * m_block_size;
|
||||
|
|
|
@ -535,6 +535,12 @@ namespace libtorrent
|
|||
TORRENT_FORWARD(add_tracker(url));
|
||||
}
|
||||
|
||||
void torrent_handle::add_piece(int piece, char const* data, int flags) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
TORRENT_FORWARD(add_piece(piece, data, flags));
|
||||
}
|
||||
|
||||
storage_interface* torrent_handle::get_storage_impl() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
|
@ -49,11 +49,28 @@ void test_running_torrent(boost::intrusive_ptr<torrent_info> info, size_type fil
|
|||
TEST_CHECK(st.total_wanted == file_size);
|
||||
std::cout << "total_wanted_done: " << st.total_wanted_done << " : 0" << std::endl;
|
||||
TEST_CHECK(st.total_wanted_done == 0);
|
||||
|
||||
if (info->num_pieces() > 0)
|
||||
{
|
||||
h.piece_priority(0, 1);
|
||||
st = h.status();
|
||||
TEST_CHECK(st.pieces[0] == false);
|
||||
std::vector<char> piece(info->piece_length());
|
||||
for (int i = 0; i < int(piece.size()); ++i)
|
||||
piece[i] = (i % 26) + 'A';
|
||||
h.add_piece(0, &piece[0]);
|
||||
test_sleep(10000);
|
||||
st = h.status();
|
||||
TEST_CHECK(st.pieces[0] == true);
|
||||
}
|
||||
}
|
||||
|
||||
int test_main()
|
||||
{
|
||||
{
|
||||
remove("test_torrent_dir2/tmp1");
|
||||
remove("test_torrent_dir2/tmp2");
|
||||
remove("test_torrent_dir2/tmp3");
|
||||
file_storage fs;
|
||||
size_type file_size = 1 * 1024 * 1024 * 1024;
|
||||
fs.add_file("test_torrent_dir2/tmp1", file_size);
|
||||
|
@ -69,6 +86,7 @@ int test_main()
|
|||
// calculate the hash for all pieces
|
||||
sha1_hash ph = hasher(&piece[0], piece.size()).final();
|
||||
int num = t.num_pieces();
|
||||
TEST_CHECK(t.num_pieces() > 0);
|
||||
for (int i = 0; i < num; ++i)
|
||||
t.set_hash(i, ph);
|
||||
|
||||
|
@ -76,6 +94,7 @@ int test_main()
|
|||
std::back_insert_iterator<std::vector<char> > out(tmp);
|
||||
bencode(out, t.generate());
|
||||
boost::intrusive_ptr<torrent_info> info(new torrent_info(&tmp[0], tmp.size()));
|
||||
TEST_CHECK(info->num_pieces() > 0);
|
||||
|
||||
test_running_torrent(info, file_size);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue