Browse Source

introducing a new torrent piece property to be persisted on disk: max_seen

is the maximum availability (peer count) ever seen for this piece.
new rpc getpiecemaxseen.
miguelfreitas
Miguel Freitas 10 years ago
parent
commit
1056d874bf
  1. 15
      libtorrent/include/libtorrent/piece_picker.hpp
  2. 1
      libtorrent/include/libtorrent/torrent.hpp
  3. 1
      libtorrent/include/libtorrent/torrent_handle.hpp
  4. 46
      libtorrent/src/piece_picker.cpp
  5. 29
      libtorrent/src/torrent.cpp
  6. 6
      libtorrent/src/torrent_handle.cpp
  7. 2
      src/bitcoinrpc.cpp
  8. 1
      src/bitcoinrpc.h
  9. 20
      src/twister.cpp

15
libtorrent/include/libtorrent/piece_picker.hpp

@ -180,6 +180,7 @@ namespace libtorrent
piece_picker(); piece_picker();
void get_availability(std::vector<int>& avail) const; void get_availability(std::vector<int>& avail) const;
void get_max_seen(std::vector<int>& max_seen) const;
// increases the peer count for the given piece // increases the peer count for the given piece
// (is used when a HAVE message is received) // (is used when a HAVE message is received)
@ -249,6 +250,12 @@ namespace libtorrent
// returns the current piece priorities for all pieces // returns the current piece priorities for all pieces
void piece_priorities(std::vector<int>& pieces) const; void piece_priorities(std::vector<int>& pieces) const;
// sets the max_seen of a piece.
void set_piece_max_seen(int index, int new_piece_max_seen);
// returns the max_seen for the piece at 'index'
int piece_max_seen(int index) const;
// ========== start deprecation ============== // ========== start deprecation ==============
// fills the bitmask with 1's for pieces that are filtered // fills the bitmask with 1's for pieces that are filtered
@ -412,6 +419,7 @@ namespace libtorrent
piece_pos() {} piece_pos() {}
piece_pos(int peer_count_, int index_) piece_pos(int peer_count_, int index_)
: peer_count(peer_count_) : peer_count(peer_count_)
, max_seen((peer_count_ <= max_seen_count) ? peer_count_ : max_seen_count)
, downloading(0) , downloading(0)
, full(0) , full(0)
, piece_priority(1) , piece_priority(1)
@ -428,6 +436,8 @@ namespace libtorrent
#else #else
boost::uint32_t peer_count : 16; boost::uint32_t peer_count : 16;
#endif #endif
// max_seen is max of peer_count (saturated to 6 bits = max_seen_count)
boost::uint32_t max_seen : 6;
// post flags (1 = rt, 2 = dm, 4 = fav, 12 = pfav) // post flags (1 = rt, 2 = dm, 4 = fav, 12 = pfav)
boost::uint32_t post_flags : 4; boost::uint32_t post_flags : 4;
// is 1 if the piece is marked as being downloaded // is 1 if the piece is marked as being downloaded
@ -467,10 +477,11 @@ namespace libtorrent
filter_priority = 0, filter_priority = 0,
// the max number the peer count can hold // the max number the peer count can hold
#if TORRENT_COMPACT_PICKER #if TORRENT_COMPACT_PICKER
max_peer_count = 0x1ff max_peer_count = 0x1ff,
#else #else
max_peer_count = 0xffff max_peer_count = 0xffff,
#endif #endif
max_seen_count = 0x3f
}; };
bool have() const { return index == we_have_index; } bool have() const { return index == we_have_index; }

1
libtorrent/include/libtorrent/torrent.hpp

@ -302,6 +302,7 @@ namespace libtorrent
// ============ end deprecation ============= // ============ end deprecation =============
void piece_availability(std::vector<int>& avail) const; void piece_availability(std::vector<int>& avail) const;
void piece_max_seen(std::vector<int>& max_seen) const;
void set_piece_priority(int index, int priority); void set_piece_priority(int index, int priority);
int piece_priority(int index) const; int piece_priority(int index) const;

1
libtorrent/include/libtorrent/torrent_handle.hpp

@ -351,6 +351,7 @@ namespace libtorrent
#endif #endif
void piece_availability(std::vector<int>& avail) const; void piece_availability(std::vector<int>& avail) const;
void piece_max_seen(std::vector<int>& max_seen) const;
// priority must be within the range [0, 7] // priority must be within the range [0, 7]
void piece_priority(int index, int priority) const; void piece_priority(int index, int priority) const;

46
libtorrent/src/piece_picker.cpp

@ -111,6 +111,7 @@ namespace libtorrent
, end(m_piece_map.end()); i != end; ++i) , end(m_piece_map.end()); i != end; ++i)
{ {
i->peer_count = 0; i->peer_count = 0;
i->max_seen = 0;
i->downloading = 0; i->downloading = 0;
i->index = 0; i->index = 0;
#ifdef TORRENT_DEBUG_REFCOUNTS #ifdef TORRENT_DEBUG_REFCOUNTS
@ -157,6 +158,7 @@ namespace libtorrent
, end(m_piece_map.end()); i != end; ++i) , end(m_piece_map.end()); i != end; ++i)
{ {
i->peer_count = 0; i->peer_count = 0;
i->max_seen = 0;
i->downloading = 0; i->downloading = 0;
i->index = 0; i->index = 0;
#ifdef TORRENT_DEBUG_REFCOUNTS #ifdef TORRENT_DEBUG_REFCOUNTS
@ -987,6 +989,11 @@ namespace libtorrent
int prev_priority = p.priority(this); int prev_priority = p.priority(this);
++p.peer_count; ++p.peer_count;
if( p.peer_count > p.max_seen ) {
p.max_seen = (p.peer_count <= piece_pos::max_seen_count)
? p.peer_count : piece_pos::max_seen_count;
}
if (m_dirty) return; if (m_dirty) return;
int new_priority = p.priority(this); int new_priority = p.priority(this);
if (prev_priority == new_priority) return; if (prev_priority == new_priority) return;
@ -1013,6 +1020,10 @@ namespace libtorrent
, end(m_piece_map.end()); i != end; ++i) , end(m_piece_map.end()); i != end; ++i)
{ {
++i->peer_count; ++i->peer_count;
if( i->peer_count > i->max_seen ) {
i->max_seen = (i->peer_count <= piece_pos::max_seen_count)
? i->peer_count : piece_pos::max_seen_count;
}
} }
m_dirty = true; m_dirty = true;
@ -1068,6 +1079,10 @@ namespace libtorrent
#endif #endif
++m_piece_map[index].peer_count; ++m_piece_map[index].peer_count;
if( m_piece_map[index].peer_count > m_piece_map[index].max_seen ) {
m_piece_map[index].max_seen = (m_piece_map[index].peer_count <= piece_pos::max_seen_count)
? m_piece_map[index].peer_count : piece_pos::max_seen_count;
}
updated = true; updated = true;
} }
} }
@ -1449,6 +1464,26 @@ namespace libtorrent
} }
} }
void piece_picker::set_piece_max_seen(int index, int new_piece_max_seen)
{
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
#endif
TORRENT_ASSERT(new_piece_max_seen >= 0);
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size());
m_piece_map[index].max_seen = new_piece_max_seen < piece_pos::max_seen_count ?
new_piece_max_seen : piece_pos::max_seen_count;
}
int piece_picker::piece_max_seen(int index) const
{
TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < (int)m_piece_map.size());
return m_piece_map[index].max_seen;
}
// ============ start deprecation ============== // ============ start deprecation ==============
void piece_picker::filtered_pieces(std::vector<bool>& mask) const void piece_picker::filtered_pieces(std::vector<bool>& mask) const
@ -2339,6 +2374,17 @@ namespace libtorrent
*j = i->peer_count + m_seeds; *j = i->peer_count + m_seeds;
} }
void piece_picker::get_max_seen(std::vector<int>& max_seen) const
{
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
max_seen.resize(m_piece_map.size());
std::vector<int>::iterator j = max_seen.begin();
for (std::vector<piece_pos>::const_iterator i = m_piece_map.begin()
, end(m_piece_map.end()); i != end; ++i, ++j)
*j = i->max_seen;
}
bool piece_picker::mark_as_writing(piece_block block, void* peer) bool piece_picker::mark_as_writing(piece_block block, void* peer)
{ {
#ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS #ifdef TORRENT_EXPENSIVE_INVARIANT_CHECKS

29
libtorrent/src/torrent.cpp

@ -3830,6 +3830,20 @@ namespace libtorrent
m_picker->get_availability(avail); m_picker->get_availability(avail);
} }
void torrent::piece_max_seen(std::vector<int>& max_seen) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(valid_metadata());
if (!has_picker())
{
max_seen.clear();
return;
}
m_picker->get_max_seen(max_seen);
}
void torrent::set_piece_priority(int index, int priority) void torrent::set_piece_priority(int index, int priority)
{ {
// INVARIANT_CHECK; // INVARIANT_CHECK;
@ -5043,6 +5057,15 @@ namespace libtorrent
m_policy.recalculate_connect_candidates(); m_policy.recalculate_connect_candidates();
} }
lazy_entry const* piece_max_seen = rd.dict_find_string("piece_max_seen");
if (piece_max_seen && piece_max_seen->string_length()
== m_torrent_file->num_pieces())
{
char const* p = piece_max_seen->string_ptr();
for (int i = 0; i < piece_max_seen->string_length(); ++i)
m_picker->set_piece_max_seen(i, p[i]);
}
if (!m_override_resume_data) if (!m_override_resume_data)
{ {
int auto_managed_ = rd.dict_find_int_value("auto_managed", -1); int auto_managed_ = rd.dict_find_int_value("auto_managed", -1);
@ -5385,6 +5408,12 @@ namespace libtorrent
piece_priority[i] = m_picker->piece_priority(i); piece_priority[i] = m_picker->piece_priority(i);
} }
// write piece max_seen
entry::string_type& piece_max_seen = ret["piece_max_seen"].string();
piece_max_seen.resize(m_torrent_file->num_pieces());
for (int i = 0, end(piece_max_seen.size()); i < end; ++i)
piece_max_seen[i] = m_picker->piece_max_seen(i);
// write file priorities // write file priorities
entry::list_type& file_priority = ret["file_priority"].list(); entry::list_type& file_priority = ret["file_priority"].list();
file_priority.clear(); file_priority.clear();

6
libtorrent/src/torrent_handle.cpp

@ -555,6 +555,12 @@ namespace libtorrent
TORRENT_SYNC_CALL1(piece_availability, boost::ref(avail)); TORRENT_SYNC_CALL1(piece_availability, boost::ref(avail));
} }
void torrent_handle::piece_max_seen(std::vector<int>& max_seen) const
{
INVARIANT_CHECK;
TORRENT_SYNC_CALL1(piece_max_seen, boost::ref(max_seen));
}
void torrent_handle::piece_priority(int index, int priority) const void torrent_handle::piece_priority(int index, int priority) const
{ {
INVARIANT_CHECK; INVARIANT_CHECK;

2
src/bitcoinrpc.cpp

@ -280,6 +280,7 @@ static const CRPCCommand vRPCCommands[] =
{ "newgroupdescription", &newgroupdescription, false, true, false }, { "newgroupdescription", &newgroupdescription, false, true, false },
{ "leavegroup", &leavegroup, false, true, false }, { "leavegroup", &leavegroup, false, true, false },
{ "getpieceavailability", &getpieceavailability, false, true, true }, { "getpieceavailability", &getpieceavailability, false, true, true },
{ "getpiecemaxseen", &getpiecemaxseen, false, true, true },
}; };
CRPCTable::CRPCTable() CRPCTable::CRPCTable()
@ -1346,6 +1347,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "newgroupinvite" && n > 3) ConvertTo<Array>(params[3]); if (strMethod == "newgroupinvite" && n > 3) ConvertTo<Array>(params[3]);
if (strMethod == "newgroupdescription" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "newgroupdescription" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getpieceavailability" && n > 1) ConvertTo<boost::int64_t>(params[1]); if (strMethod == "getpieceavailability" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getpiecemaxseen" && n > 1) ConvertTo<boost::int64_t>(params[1]);
return params; return params;
} }

1
src/bitcoinrpc.h

@ -233,5 +233,6 @@ extern json_spirit::Value newgroupinvite(const json_spirit::Array& params, bool
extern json_spirit::Value newgroupdescription(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value newgroupdescription(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value leavegroup(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value leavegroup(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getpieceavailability(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value getpieceavailability(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getpiecemaxseen(const json_spirit::Array& params, bool fHelp);
#endif #endif

20
src/twister.cpp

@ -3824,3 +3824,23 @@ Value getpieceavailability(const Array& params, bool fHelp)
return avail.size() > k ? avail.at(k) : 0; return avail.size() > k ? avail.at(k) : 0;
} }
Value getpiecemaxseen(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 2 )
throw runtime_error(
"getpiecemaxseen <username> <k>'\n"
"Get piece max seen availability (max peer count for this piece)");
EnsureWalletIsUnlocked();
string strUsername = params[0].get_str();
int k = params[1].get_int();
torrent_handle h = getTorrentUser(strUsername);
std::vector<int> max_seen;
h.piece_max_seen(max_seen);
return max_seen.size() > k ? max_seen.at(k) : 0;
}

Loading…
Cancel
Save