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 uTorrent interpretation of multi-tracker torrents
|
||||
* handle torrents with duplicate filenames
|
||||
|
|
|
@ -1817,7 +1817,7 @@ Its declaration looks like this::
|
|||
torrent_handle();
|
||||
|
||||
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_peer_info(std::vector<peer_info>& v) 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
|
||||
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*
|
||||
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()
|
||||
-----------
|
||||
|
@ -4779,7 +4787,7 @@ generated and the torrent is paused.
|
|||
};
|
||||
|
||||
file_renamed_alert
|
||||
------------------------
|
||||
------------------
|
||||
|
||||
This is posted as a response to a ``torrent_handle::rename_file`` call, if the rename
|
||||
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
|
||||
-----------------------
|
||||
|
||||
|
|
|
@ -125,6 +125,30 @@ namespace libtorrent
|
|||
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
|
||||
{
|
||||
file_renamed_alert(torrent_handle const& h
|
||||
|
|
|
@ -270,7 +270,7 @@ namespace libtorrent
|
|||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
// called when we learn that we have a piece
|
||||
// only once per piece
|
||||
void we_have(int index);
|
||||
|
||||
int num_have() const
|
||||
{
|
||||
return has_picker()
|
||||
|
@ -838,6 +842,11 @@ namespace libtorrent
|
|||
|
||||
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;
|
||||
|
||||
std::vector<announce_entry> m_trackers;
|
||||
|
|
|
@ -371,7 +371,12 @@ namespace libtorrent
|
|||
// the torrent_info.
|
||||
void file_progress(std::vector<float>& progress) const TORRENT_DEPRECATED;
|
||||
#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;
|
||||
|
||||
|
|
|
@ -91,18 +91,6 @@ namespace libtorrent
|
|||
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
|
||||
{
|
||||
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
|
||||
, int size) const
|
||||
{
|
||||
|
|
|
@ -238,6 +238,7 @@ namespace libtorrent
|
|||
if (!m_seed_mode)
|
||||
{
|
||||
m_picker.reset(new piece_picker());
|
||||
std::fill(m_file_progress.begin(), m_file_progress.end(), 0);
|
||||
|
||||
if (!m_resume_data.empty())
|
||||
{
|
||||
|
@ -599,6 +600,7 @@ namespace libtorrent
|
|||
TORRENT_ASSERT(m_torrent_file->total_size() >= 0);
|
||||
|
||||
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());
|
||||
|
||||
|
@ -830,7 +832,7 @@ namespace libtorrent
|
|||
char const* pieces_str = pieces->string_ptr();
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -842,7 +844,7 @@ namespace libtorrent
|
|||
for (int i = 0; i < slots->list_size(); ++i)
|
||||
{
|
||||
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();
|
||||
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
|
||||
, int((m_torrent_file->total_size()+m_block_size-1)/m_block_size));
|
||||
// assume that we don't have anything
|
||||
|
@ -1014,7 +1017,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_picker);
|
||||
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
|
||||
// this handler will be called repeatedly until
|
||||
|
@ -1789,6 +1792,48 @@ namespace libtorrent
|
|||
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)
|
||||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
@ -1815,7 +1860,8 @@ namespace libtorrent
|
|||
std::set<void*> peers;
|
||||
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();)
|
||||
{
|
||||
peer_connection* p = *i;
|
||||
|
@ -4454,6 +4500,14 @@ namespace libtorrent
|
|||
TORRENT_ASSERT((m_torrent_file->piece_length() & (m_block_size-1)) == 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
|
||||
|
||||
|
@ -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());
|
||||
|
||||
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())
|
||||
{
|
||||
for (int i = 0; i < m_torrent_file->num_files(); ++i)
|
||||
|
|
|
@ -378,10 +378,10 @@ namespace libtorrent
|
|||
}
|
||||
#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;
|
||||
TORRENT_FORWARD(file_progress(progress));
|
||||
TORRENT_FORWARD(file_progress(progress, flags));
|
||||
}
|
||||
|
||||
torrent_status torrent_handle::status() const
|
||||
|
|
|
@ -71,8 +71,8 @@ void test_rate()
|
|||
boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0
|
||||
, true, false, true, "_transfer", 0, &t);
|
||||
|
||||
ses1.set_alert_mask(alert::all_categories & ~(alert::progress_notification | alert::performance_warning));
|
||||
ses2.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::performance_warning));
|
||||
|
||||
ptime start = time_now();
|
||||
|
||||
|
|
Loading…
Reference in New Issue