added new alert when individual files complete
This commit is contained in:
parent
52f39a9af0
commit
51992dda6a
|
@ -1,3 +1,4 @@
|
||||||
|
* added new alert when individual files complete
|
||||||
* added support for storing symbolic links in .torrent files
|
* added support for storing symbolic links in .torrent files
|
||||||
* added support for uTorrent interpretation of multi-tracker torrents
|
* added support for uTorrent interpretation of multi-tracker torrents
|
||||||
* handle torrents with duplicate filenames
|
* handle torrents with duplicate filenames
|
||||||
|
|
|
@ -1817,7 +1817,7 @@ Its declaration looks like this::
|
||||||
torrent_handle();
|
torrent_handle();
|
||||||
|
|
||||||
torrent_status status();
|
torrent_status status();
|
||||||
void file_progress(std::vector<size_type>& fp);
|
void file_progress(std::vector<size_type>& fp, int flags = 0);
|
||||||
void get_download_queue(std::vector<partial_piece_info>& queue) const;
|
void get_download_queue(std::vector<partial_piece_info>& queue) const;
|
||||||
void get_peer_info(std::vector<peer_info>& v) const;
|
void get_peer_info(std::vector<peer_info>& v) const;
|
||||||
torrent_info const& get_torrent_info() const;
|
torrent_info const& get_torrent_info() const;
|
||||||
|
@ -2029,7 +2029,7 @@ file_progress()
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
void file_progress(std::vector<size_type>& fp);
|
void file_progress(std::vector<size_type>& fp, int flags = 0);
|
||||||
|
|
||||||
This function fills in the supplied vector with the the number of bytes downloaded
|
This function fills in the supplied vector with the the number of bytes downloaded
|
||||||
of each file in this torrent. The progress values are ordered the same as the files
|
of each file in this torrent. The progress values are ordered the same as the files
|
||||||
|
@ -2037,6 +2037,14 @@ in the `torrent_info`_. This operation is not very cheap. Its complexity is *O(n
|
||||||
Where *n* is the number of files, *m* is the number of downloading pieces and *j*
|
Where *n* is the number of files, *m* is the number of downloading pieces and *j*
|
||||||
is the number of blocks in a piece.
|
is the number of blocks in a piece.
|
||||||
|
|
||||||
|
The ``flags`` parameter can be used to specify the granularity of the file progress. If
|
||||||
|
left at the default value of 0, the progress will be as accurate as possible, but also
|
||||||
|
more expensive to calculate. If ``torrent_handle::piece_granularity`` is specified,
|
||||||
|
the progress will be specified in piece granularity. i.e. only pieces that have been
|
||||||
|
fully downloaded and passed the hash check count. When specifying piece granularity,
|
||||||
|
the operation is a lot cheaper, since libtorrent already keeps track of this internally
|
||||||
|
and no calculation is required.
|
||||||
|
|
||||||
|
|
||||||
save_path()
|
save_path()
|
||||||
-----------
|
-----------
|
||||||
|
@ -4779,7 +4787,7 @@ generated and the torrent is paused.
|
||||||
};
|
};
|
||||||
|
|
||||||
file_renamed_alert
|
file_renamed_alert
|
||||||
------------------------
|
------------------
|
||||||
|
|
||||||
This is posted as a response to a ``torrent_handle::rename_file`` call, if the rename
|
This is posted as a response to a ``torrent_handle::rename_file`` call, if the rename
|
||||||
operation succeeds.
|
operation succeeds.
|
||||||
|
@ -5152,6 +5160,23 @@ This alert is generated when a block request receives a response.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
file_completed_alert
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
This is posted whenever an individual file completes its download. i.e.
|
||||||
|
All pieces overlapping this file have passed their hash check.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
struct file_completed_alert: torrent_alert
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
The ``index`` member refers to the index of the file that completed.
|
||||||
|
|
||||||
|
|
||||||
block_downloading_alert
|
block_downloading_alert
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,30 @@ namespace libtorrent
|
||||||
int size;
|
int size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TORRENT_EXPORT file_completed_alert: torrent_alert
|
||||||
|
{
|
||||||
|
file_completed_alert(torrent_handle const& h
|
||||||
|
, int index_)
|
||||||
|
: torrent_alert(h)
|
||||||
|
, index(index_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual std::auto_ptr<alert> clone() const
|
||||||
|
{ return std::auto_ptr<alert>(new file_completed_alert(*this)); }
|
||||||
|
const static int static_category = alert::progress_notification;
|
||||||
|
virtual int category() const { return static_category; }
|
||||||
|
virtual char const* what() const { return "file completed"; }
|
||||||
|
virtual std::string message() const
|
||||||
|
{
|
||||||
|
char msg[200];
|
||||||
|
snprintf(msg, sizeof(msg), "%s: file %d finished downloading"
|
||||||
|
, torrent_alert::message().c_str(), index);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT file_renamed_alert: torrent_alert
|
struct TORRENT_EXPORT file_renamed_alert: torrent_alert
|
||||||
{
|
{
|
||||||
file_renamed_alert(torrent_handle const& h
|
file_renamed_alert(torrent_handle const& h
|
||||||
|
|
|
@ -270,7 +270,7 @@ namespace libtorrent
|
||||||
|
|
||||||
torrent_status status() const;
|
torrent_status status() const;
|
||||||
|
|
||||||
void file_progress(std::vector<size_type>& fp) const;
|
void file_progress(std::vector<size_type>& fp, int flags = 0) const;
|
||||||
|
|
||||||
void use_interface(const char* net_interface);
|
void use_interface(const char* net_interface);
|
||||||
tcp::endpoint const& get_interface() const { return m_net_interface; }
|
tcp::endpoint const& get_interface() const { return m_net_interface; }
|
||||||
|
@ -427,6 +427,10 @@ namespace libtorrent
|
||||||
return has_picker()?m_picker->have_piece(index):true;
|
return has_picker()?m_picker->have_piece(index):true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called when we learn that we have a piece
|
||||||
|
// only once per piece
|
||||||
|
void we_have(int index);
|
||||||
|
|
||||||
int num_have() const
|
int num_have() const
|
||||||
{
|
{
|
||||||
return has_picker()
|
return has_picker()
|
||||||
|
@ -838,6 +842,11 @@ namespace libtorrent
|
||||||
|
|
||||||
std::vector<boost::uint8_t> m_file_priority;
|
std::vector<boost::uint8_t> m_file_priority;
|
||||||
|
|
||||||
|
// this vector contains the number of bytes completely
|
||||||
|
// downloaded (as in passed-hash-check) in each file.
|
||||||
|
// this lets us trigger on individual files completing
|
||||||
|
std::vector<size_type> m_file_progress;
|
||||||
|
|
||||||
boost::scoped_ptr<piece_picker> m_picker;
|
boost::scoped_ptr<piece_picker> m_picker;
|
||||||
|
|
||||||
std::vector<announce_entry> m_trackers;
|
std::vector<announce_entry> m_trackers;
|
||||||
|
|
|
@ -371,7 +371,12 @@ namespace libtorrent
|
||||||
// the torrent_info.
|
// the torrent_info.
|
||||||
void file_progress(std::vector<float>& progress) const TORRENT_DEPRECATED;
|
void file_progress(std::vector<float>& progress) const TORRENT_DEPRECATED;
|
||||||
#endif
|
#endif
|
||||||
void file_progress(std::vector<size_type>& progress) const;
|
enum file_progress_flags_t
|
||||||
|
{
|
||||||
|
piece_granularity = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
void file_progress(std::vector<size_type>& progress, int flags = 0) const;
|
||||||
|
|
||||||
void clear_error() const;
|
void clear_error() const;
|
||||||
|
|
||||||
|
|
|
@ -91,18 +91,6 @@ namespace libtorrent
|
||||||
m_files[index].path = new_filename;
|
m_files[index].path = new_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
file_storage::iterator file_storage::file_at_offset(size_type offset) const
|
|
||||||
{
|
|
||||||
// TODO: do a binary search
|
|
||||||
std::vector<file_entry>::const_iterator i;
|
|
||||||
for (i = begin(); i != end(); ++i)
|
|
||||||
{
|
|
||||||
if (i->offset <= offset && i->offset + i->size > offset)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool compare_file_offset(file_entry const& lhs, file_entry const& rhs)
|
bool compare_file_offset(file_entry const& lhs, file_entry const& rhs)
|
||||||
|
@ -111,6 +99,21 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
file_storage::iterator file_storage::file_at_offset(size_type offset) const
|
||||||
|
{
|
||||||
|
// find the file iterator and file offset
|
||||||
|
file_entry target;
|
||||||
|
target.offset = offset;
|
||||||
|
TORRENT_ASSERT(!compare_file_offset(target, m_files.front()));
|
||||||
|
|
||||||
|
std::vector<file_entry>::const_iterator file_iter = std::upper_bound(
|
||||||
|
begin(), end(), target, compare_file_offset);
|
||||||
|
|
||||||
|
TORRENT_ASSERT(file_iter != begin());
|
||||||
|
--file_iter;
|
||||||
|
return file_iter;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<file_slice> file_storage::map_block(int piece, size_type offset
|
std::vector<file_slice> file_storage::map_block(int piece, size_type offset
|
||||||
, int size) const
|
, int size) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -238,6 +238,7 @@ namespace libtorrent
|
||||||
if (!m_seed_mode)
|
if (!m_seed_mode)
|
||||||
{
|
{
|
||||||
m_picker.reset(new piece_picker());
|
m_picker.reset(new piece_picker());
|
||||||
|
std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
|
||||||
|
|
||||||
if (!m_resume_data.empty())
|
if (!m_resume_data.empty())
|
||||||
{
|
{
|
||||||
|
@ -599,6 +600,7 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
|
TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
|
||||||
|
|
||||||
m_file_priority.resize(m_torrent_file->num_files(), 1);
|
m_file_priority.resize(m_torrent_file->num_files(), 1);
|
||||||
|
m_file_progress.resize(m_torrent_file->num_files(), 0);
|
||||||
|
|
||||||
m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length());
|
m_block_size = (std::min)(m_block_size, m_torrent_file->piece_length());
|
||||||
|
|
||||||
|
@ -830,7 +832,7 @@ namespace libtorrent
|
||||||
char const* pieces_str = pieces->string_ptr();
|
char const* pieces_str = pieces->string_ptr();
|
||||||
for (int i = 0, end(pieces->string_length()); i < end; ++i)
|
for (int i = 0, end(pieces->string_length()); i < end; ++i)
|
||||||
{
|
{
|
||||||
if (pieces_str[i] & 1) m_picker->we_have(i);
|
if (pieces_str[i] & 1) we_have(i);
|
||||||
if (m_seed_mode && (pieces_str[i] & 2)) m_verified.set_bit(i);
|
if (m_seed_mode && (pieces_str[i] & 2)) m_verified.set_bit(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,7 +844,7 @@ namespace libtorrent
|
||||||
for (int i = 0; i < slots->list_size(); ++i)
|
for (int i = 0; i < slots->list_size(); ++i)
|
||||||
{
|
{
|
||||||
int piece = slots->list_int_value_at(i, -1);
|
int piece = slots->list_int_value_at(i, -1);
|
||||||
if (piece >= 0) m_picker->we_have(piece);
|
if (piece >= 0) we_have(piece);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -931,6 +933,7 @@ namespace libtorrent
|
||||||
|
|
||||||
m_owning_storage->async_release_files();
|
m_owning_storage->async_release_files();
|
||||||
if (!m_picker) m_picker.reset(new piece_picker());
|
if (!m_picker) m_picker.reset(new piece_picker());
|
||||||
|
std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
|
||||||
m_picker->init(m_torrent_file->piece_length() / m_block_size
|
m_picker->init(m_torrent_file->piece_length() / m_block_size
|
||||||
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
|
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
|
||||||
// assume that we don't have anything
|
// assume that we don't have anything
|
||||||
|
@ -1014,7 +1017,7 @@ namespace libtorrent
|
||||||
|
|
||||||
TORRENT_ASSERT(m_picker);
|
TORRENT_ASSERT(m_picker);
|
||||||
if (j.offset >= 0 && !m_picker->have_piece(j.offset))
|
if (j.offset >= 0 && !m_picker->have_piece(j.offset))
|
||||||
m_picker->we_have(j.offset);
|
we_have(j.offset);
|
||||||
|
|
||||||
// we're not done checking yet
|
// we're not done checking yet
|
||||||
// this handler will be called repeatedly until
|
// this handler will be called repeatedly until
|
||||||
|
@ -1789,6 +1792,48 @@ namespace libtorrent
|
||||||
m_picker->set_piece_priority(i, 6);
|
m_picker->set_piece_priority(i, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void torrent::we_have(int index)
|
||||||
|
{
|
||||||
|
// update m_file_progress
|
||||||
|
TORRENT_ASSERT(m_picker);
|
||||||
|
TORRENT_ASSERT(!have_piece(index));
|
||||||
|
|
||||||
|
std::cerr << "[" << this << "] GOT PIECE " << index << std::endl;
|
||||||
|
|
||||||
|
const int piece_size = m_torrent_file->piece_length();
|
||||||
|
size_type off = size_type(index) * piece_size;
|
||||||
|
file_storage::iterator f = m_torrent_file->files().file_at_offset(off);
|
||||||
|
int size = m_torrent_file->piece_size(index);
|
||||||
|
int file_index = f - m_torrent_file->files().begin();
|
||||||
|
for (; size > 0; ++f, ++file_index)
|
||||||
|
{
|
||||||
|
size_type file_offset = off - f->offset;
|
||||||
|
TORRENT_ASSERT(f != m_torrent_file->files().end());
|
||||||
|
TORRENT_ASSERT(file_offset < f->size);
|
||||||
|
int add = (std::min)(f->size - file_offset, (size_type)size);
|
||||||
|
m_file_progress[file_index] += add;
|
||||||
|
std::cerr << " adding " << add << " to " << file_index << std::endl;
|
||||||
|
|
||||||
|
TORRENT_ASSERT(m_file_progress[file_index]
|
||||||
|
<= m_torrent_file->files().at(file_index).size);
|
||||||
|
|
||||||
|
if (m_file_progress[file_index] >= m_torrent_file->files().at(file_index).size)
|
||||||
|
{
|
||||||
|
if (m_ses.m_alerts.should_post<piece_finished_alert>())
|
||||||
|
{
|
||||||
|
// this file just completed, post alert
|
||||||
|
m_ses.m_alerts.post_alert(file_completed_alert(get_handle()
|
||||||
|
, file_index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size -= add;
|
||||||
|
off += add;
|
||||||
|
TORRENT_ASSERT(size >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_picker->we_have(index);
|
||||||
|
}
|
||||||
|
|
||||||
void torrent::piece_passed(int index)
|
void torrent::piece_passed(int index)
|
||||||
{
|
{
|
||||||
// INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
@ -1815,7 +1860,8 @@ namespace libtorrent
|
||||||
std::set<void*> peers;
|
std::set<void*> peers;
|
||||||
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
|
std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin()));
|
||||||
|
|
||||||
m_picker->we_have(index);
|
we_have(index);
|
||||||
|
|
||||||
for (peer_iterator i = m_connections.begin(); i != m_connections.end();)
|
for (peer_iterator i = m_connections.begin(); i != m_connections.end();)
|
||||||
{
|
{
|
||||||
peer_connection* p = *i;
|
peer_connection* p = *i;
|
||||||
|
@ -4454,6 +4500,14 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT((m_torrent_file->piece_length() & (m_block_size-1)) == 0);
|
TORRENT_ASSERT((m_torrent_file->piece_length() & (m_block_size-1)) == 0);
|
||||||
}
|
}
|
||||||
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
|
// if (is_seed()) TORRENT_ASSERT(m_picker.get() == 0);
|
||||||
|
|
||||||
|
|
||||||
|
for (std::vector<size_type>::const_iterator i = m_file_progress.begin()
|
||||||
|
, end(m_file_progress.end()); i != end; ++i)
|
||||||
|
{
|
||||||
|
int index = i - m_file_progress.begin();
|
||||||
|
TORRENT_ASSERT(*i <= m_torrent_file->files().at(index).size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5333,12 +5387,18 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void torrent::file_progress(std::vector<size_type>& fp) const
|
void torrent::file_progress(std::vector<size_type>& fp, int flags) const
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(valid_metadata());
|
TORRENT_ASSERT(valid_metadata());
|
||||||
|
|
||||||
fp.resize(m_torrent_file->num_files(), 0);
|
fp.resize(m_torrent_file->num_files(), 0);
|
||||||
|
|
||||||
|
if (flags & torrent_handle::piece_granularity)
|
||||||
|
{
|
||||||
|
std::copy(m_file_progress.begin(), m_file_progress.end(), fp.begin());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_seed())
|
if (is_seed())
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_torrent_file->num_files(); ++i)
|
for (int i = 0; i < m_torrent_file->num_files(); ++i)
|
||||||
|
|
|
@ -378,10 +378,10 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void torrent_handle::file_progress(std::vector<size_type>& progress) const
|
void torrent_handle::file_progress(std::vector<size_type>& progress, int flags) const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
TORRENT_FORWARD(file_progress(progress));
|
TORRENT_FORWARD(file_progress(progress, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
torrent_status torrent_handle::status() const
|
torrent_status torrent_handle::status() const
|
||||||
|
|
|
@ -71,8 +71,8 @@ void test_rate()
|
||||||
boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0
|
boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0
|
||||||
, true, false, true, "_transfer", 0, &t);
|
, true, false, true, "_transfer", 0, &t);
|
||||||
|
|
||||||
ses1.set_alert_mask(alert::all_categories & ~(alert::progress_notification | alert::performance_warning));
|
ses1.set_alert_mask(alert::all_categories & ~(alert::performance_warning));
|
||||||
ses2.set_alert_mask(alert::all_categories & ~(alert::progress_notification | alert::performance_warning));
|
ses2.set_alert_mask(alert::all_categories & ~(alert::performance_warning));
|
||||||
|
|
||||||
ptime start = time_now();
|
ptime start = time_now();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue