workaround for sparse files issue on Windows vista

This commit is contained in:
Arvid Norberg 2009-01-05 01:08:09 +00:00
parent f1d229aae6
commit d07ccaf6b8
9 changed files with 110 additions and 1 deletions

View File

@ -1,3 +1,4 @@
* added workaround for sparse file issue on Windows Vista
* added new lt_trackers extension to exchange trackers between
peers
* added support for BEP 17 http seeds

View File

@ -2613,6 +2613,8 @@ It contains the following fields::
int last_scrape;
bool has_incoming;
int sparse_regions;
};
``progress`` is a value in the range [0, 1], that represents the progress of the
@ -2800,6 +2802,9 @@ If it has never done that, this value is -1.
``has_incoming`` is true if there has ever been an incoming connection attempt
to this torrent.'
``sparse_regions`` the number of regions of non-downloaded pieces in the
torrent. This is an interesting metric on windows vista, since there is
a limit on the number of sparse regions in a single file there.
peer_info
=========
@ -3217,6 +3222,8 @@ that will be sent to the tracker. The user-agent is a good way to identify your
bool strict_super_seeding;
int seeding_piece_quota;
int max_sparse_regions;
};
``user_agent`` this is the client identification to the tracker.
@ -3526,6 +3533,16 @@ It defaults to 3 pieces, which means that when seeding, any peer we've
sent more than this number of pieces to will be unchoked in favour of
a choked peer.
``max_sparse_regions`` is a limit of the number of *sparse regions* in
a torrent. A sparse region is defined as a hole of pieces we have not
yet downloaded, in between pieces that have been downloaded. This is
used as a hack for windows vista which has a bug where you cannot
write files with more than a certain number of sparse regions. This
limit is not hard, it will be exceeded. Once it's exceeded, pieces
that will maintain or decrease the number of sparse regions are
prioritized. To disable this functionality, set this to 0. It defaults
to 0 on all platforms except windows.
pe_settings
===========

View File

@ -1382,7 +1382,8 @@ int main(int ac, char* av[])
out << " peers: " << esc("37") << s.num_peers << esc("0") << " (" << esc("37") << s.connect_candidates << esc("0") << ") "
<< "seeds: " << esc("37") << s.num_seeds << esc("0") << " "
<< "distributed copies: " << esc("37") << s.distributed_copies << esc("0")
// << " magnet-link: " << make_magnet_uri(h) << "\n"
<< " sparse regions: " << s.sparse_regions
// << " magnet-link: " << make_magnet_uri(h) << "\n"
<< " download: " << esc("32") << (s.download_rate > 0 ? add_suffix(s.download_rate) + "/s ": " ") << esc("0");
boost::posix_time::time_duration t = s.next_announce;
out << " next announce: " << esc("37")

View File

@ -182,6 +182,7 @@ namespace libtorrent
int cursor() const { return m_cursor; }
int reverse_cursor() const { return m_reverse_cursor; }
int sparse_regions() const { return m_sparse_regions; }
// sets all pieces to dont-have
void init(int blocks_per_piece, int total_num_blocks);
@ -523,6 +524,9 @@ namespace libtorrent
// all the subsequent pieces
int m_reverse_cursor;
// the number of regions of pieces we don't have.
int m_sparse_regions;
// if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces.
mutable bool m_dirty;

View File

@ -148,6 +148,11 @@ namespace libtorrent
, prefer_udp_trackers(true)
, strict_super_seeding(false)
, seeding_piece_quota(3)
#ifdef TORRENT_WINDOWS
, max_sparse_regions(30000)
#else
, max_sparse_regions(0)
#endif
{}
// this is the user agent that will be sent to the tracker
@ -478,6 +483,17 @@ namespace libtorrent
// the number of pieces to send to each peer when seeding
// before rotating to a new peer
int seeding_piece_quota;
// the maximum number of sparse regions before starting
// to prioritize pieces close to other pieces (to maintain
// the number of sparse regions). This is set to 30000 on
// windows because windows vista has a new limit on the
// numbers of sparse regions one file may have
// if it is set to 0 this behavior is disabled
// this is a hack to avoid a terrible bug on windows
// don't use unless you have to, it screws with rarest-first
// piece selection, and reduces swarm performance
int max_sparse_regions;
};
#ifndef TORRENT_DISABLE_DHT

View File

@ -451,6 +451,8 @@ namespace libtorrent
// --------------------------------------------
// PIECE MANAGEMENT
void update_sparse_piece_prio(int piece, int cursor, int reverse_cursor);
bool super_seeding() const
{ return m_super_seeding; }

View File

@ -120,6 +120,7 @@ namespace libtorrent
, seed_rank(0)
, last_scrape(0)
, has_incoming(false)
, sparse_regions(0)
{}
enum state_t
@ -270,6 +271,9 @@ namespace libtorrent
// true if there are incoming connections to this
// torrent
bool has_incoming;
// the number of "holes" in the torrent
int sparse_regions;
};
struct TORRENT_EXPORT block_info

View File

@ -65,6 +65,7 @@ namespace libtorrent
, m_num_have(0)
, m_cursor(0)
, m_reverse_cursor(0)
, m_sparse_regions(1)
, m_dirty(false)
{
#ifdef TORRENT_PICKER_LOG
@ -1073,6 +1074,28 @@ namespace libtorrent
, has_index(index)) == m_downloads.end());
if (p.have()) return;
// maintain sparse_regions
if (index == 0)
{
if (index == m_piece_map.size() - 1
|| m_piece_map[index + 1].have())
--m_sparse_regions;
}
else if (index == int(m_piece_map.size() - 1))
{
if (index == 0
|| m_piece_map[index - 1].have())
--m_sparse_regions;
}
else
{
bool have_before = m_piece_map[index-1].have();
bool have_after = m_piece_map[index+1].have();
if (have_after && have_before) --m_sparse_regions;
else if (!have_after && !have_before) ++m_sparse_regions;
}
if (p.filtered())
{
--m_num_filtered;

View File

@ -1547,6 +1547,19 @@ namespace libtorrent
}
}
void torrent::update_sparse_piece_prio(int i, int start, int end)
{
TORRENT_ASSERT(m_picker);
if (m_picker->have_piece(i) || m_picker->piece_priority(i) == 0)
return;
bool have_before = i == 0 || m_picker->have_piece(i - 1);
bool have_after = i == end - 1 || m_picker->have_piece(i + 1);
if (have_after && have_before)
m_picker->set_piece_priority(i, 7);
else if (have_after || have_before)
m_picker->set_piece_priority(i, 6);
}
void torrent::piece_passed(int index)
{
// INVARIANT_CHECK;
@ -1591,6 +1604,19 @@ namespace libtorrent
if (p->connection) p->connection->received_valid_data(index);
}
if (settings().max_sparse_regions > 0
&& m_picker->sparse_regions() > settings().max_sparse_regions)
{
// we have too many sparse regions. Prioritize pieces
// that won't introduce new sparse regions
// prioritize pieces that will reduce the number of sparse
// regions even higher
int start = m_picker->cursor();
int end = m_picker->reverse_cursor();
if (index > start) update_sparse_piece_prio(index - 1, start, end);
if (index < end - 1) update_sparse_piece_prio(index + 1, start, end);
}
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
@ -4654,6 +4680,20 @@ namespace libtorrent
if (m_time_scaler <= 0)
{
m_time_scaler = 10;
if (settings().max_sparse_regions > 0
&& m_picker
&& m_picker->sparse_regions() > settings().max_sparse_regions)
{
// we have too many sparse regions. Prioritize pieces
// that won't introduce new sparse regions
// prioritize pieces that will reduce the number of sparse
// regions even higher
int start = m_picker->cursor();
int end = m_picker->reverse_cursor();
for (int i = start; i < end; ++i)
update_sparse_piece_prio(i, start, end);
}
m_policy.pulse();
}
}
@ -5059,6 +5099,7 @@ namespace libtorrent
if (has_picker())
{
st.sparse_regions = m_picker->sparse_regions();
int num_pieces = m_picker->num_pieces();
st.pieces.resize(num_pieces, false);
for (int i = 0; i < num_pieces; ++i)