added upload mode

This commit is contained in:
Arvid Norberg
2009-06-18 22:32:55 +00:00
parent 6b048dc85e
commit f09774607f
12 changed files with 209 additions and 54 deletions

View File

@@ -2374,7 +2374,7 @@ namespace libtorrent
++m_queued_time_critical;
}
void peer_connection::add_request(piece_block const& block, bool time_critical)
bool peer_connection::add_request(piece_block const& block, bool time_critical)
{
// INVARIANT_CHECK;
@@ -2393,6 +2393,8 @@ namespace libtorrent
TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end()
, block) == m_request_queue.end());
if (t->upload_mode()) return false;
piece_picker::piece_state_t state;
peer_speed_t speed = peer_speed();
char const* speedmsg = 0;
@@ -2413,7 +2415,7 @@ namespace libtorrent
}
if (!t->picker().mark_as_downloading(block, peer_info_struct(), state))
return;
return false;
if (t->alerts().should_post<block_downloading_alert>())
{
@@ -2431,6 +2433,53 @@ namespace libtorrent
{
m_request_queue.push_back(block);
}
return true;
}
void peer_connection::cancel_all_requests()
{
INVARIANT_CHECK;
boost::shared_ptr<torrent> t = m_torrent.lock();
// this peer might be disconnecting
if (!t) return;
TORRENT_ASSERT(t->valid_metadata());
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** CANCEL ALL REQUESTS\n";
#endif
while (!m_request_queue.empty())
{
t->picker().abort_download(m_request_queue.back());
m_request_queue.pop_back();
}
for (std::vector<pending_block>::iterator i = m_download_queue.begin()
, end(m_download_queue.end()); i != end; ++i)
{
piece_block b = i->block;
int block_offset = b.block_index * t->block_size();
int block_size
= (std::min)(t->torrent_file().piece_size(b.piece_index)-block_offset,
t->block_size());
TORRENT_ASSERT(block_size > 0);
TORRENT_ASSERT(block_size <= t->block_size());
peer_request r;
r.piece = b.piece_index;
r.start = block_offset;
r.length = block_size;
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " ==> CANCEL [ piece: " << b.piece_index << " | s: "
<< block_offset << " | l: " << block_size << " | " << b.block_index << " ]\n";
#endif
write_cancel(r);
}
}
void peer_connection::cancel_request(piece_block const& block)
@@ -2588,7 +2637,8 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock();
TORRENT_ASSERT(t);
if ((int)m_download_queue.size() >= m_desired_queue_size) return;
if ((int)m_download_queue.size() >= m_desired_queue_size
|| t->upload_mode()) return;
bool empty_download_queue = m_download_queue.empty();

View File

@@ -193,6 +193,7 @@ namespace libtorrent
{
if (t.is_seed()) return;
if (c.no_download()) return;
if (t.upload_mode()) return;
TORRENT_ASSERT(t.valid_metadata());
TORRENT_ASSERT(c.peer_info_struct() != 0 || !dynamic_cast<bt_peer_connection*>(&c));
@@ -313,7 +314,7 @@ namespace libtorrent
// ok, we found a piece that's not being downloaded
// by somebody else. request it from this peer
// and return
c.add_request(*i);
if (!c.add_request(*i)) continue;
TORRENT_ASSERT(p.num_peers(*i) == 1);
TORRENT_ASSERT(p.is_requested(*i));
num_requests--;

View File

@@ -144,6 +144,7 @@ namespace libtorrent
, m_total_downloaded(0)
, m_started(time_now())
, m_last_scrape(min_time())
, m_upload_mode_time(time_now())
, m_torrent_file(p.ti ? p.ti : new torrent_info(p.info_hash))
, m_storage(0)
, m_host_resolver(ses.m_io_service)
@@ -180,6 +181,7 @@ namespace libtorrent
, m_time_scaler(0)
, m_abort(false)
, m_paused(p.paused)
, m_upload_mode(p.upload_mode)
, m_auto_managed(p.auto_managed)
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
, m_resolving_country(false)
@@ -341,6 +343,36 @@ namespace libtorrent
}
}
void torrent::set_upload_mode(bool b)
{
if (b == m_upload_mode) return;
m_upload_mode = b;
if (m_upload_mode)
{
// clear request queues of all peers
for (std::set<peer_connection*>::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
peer_connection* p = (*i);
p->cancel_all_requests();
}
// this is used to try leaving upload only mode periodically
m_upload_mode_time = time_now();
}
else
{
// send_block_requests on all peers
for (std::set<peer_connection*>::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
peer_connection* p = (*i);
p->send_block_requests();
}
}
}
void torrent::handle_disk_error(disk_io_job const& j, peer_connection* c)
{
if (!j.error) return;
@@ -389,20 +421,8 @@ namespace libtorrent
// and the filesystem doesn't support sparse files, only zero the priorities
// of the pieces that are at the tails of all files, leaving everything
// up to the highest written piece in each file
if (m_ses.settings().adjust_priority_on_disk_failure
&& has_picker())
{
bool filter_updated = false;
bool was_finished = is_finished();
const int num_pieces = m_torrent_file->num_pieces();
for (int i = 0; i < num_pieces; ++i)
{
filter_updated |= m_picker->set_piece_priority(i, 0);
TORRENT_ASSERT(num_have() >= m_picker->num_have_filtered());
}
if (filter_updated) update_peer_interest(was_finished);
return;
}
set_upload_mode(true);
return;
}
// put the torrent in an error-state
@@ -4897,6 +4917,8 @@ namespace libtorrent
{
INVARIANT_CHECK;
ptime now = time_now();
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
@@ -4932,6 +4954,15 @@ namespace libtorrent
m_policy.pulse();
}
// if we're in upload only mode and we're auto-managed
// leave upload mode every 10 minutes hoping that the error
// condition has been fixed
if (m_upload_mode && m_auto_managed && now - m_upload_mode_time
> seconds(m_settings.optimistic_disk_retry))
{
set_upload_mode(false);
}
if (is_paused())
{
// let the stats fade out to 0
@@ -4965,8 +4996,6 @@ namespace libtorrent
if (is_seed()) m_seeding_time += since_last_tick;
m_active_time += since_last_tick;
ptime now = time_now();
// ---- TIME CRITICAL PIECES ----
if (!m_time_critical_pieces.empty())
@@ -5437,6 +5466,7 @@ namespace libtorrent
{
st.last_scrape = total_seconds(now - m_last_scrape);
}
st.upload_mode = m_upload_mode;
st.up_bandwidth_queue = 0;
st.down_bandwidth_queue = 0;

View File

@@ -290,6 +290,12 @@ namespace libtorrent
TORRENT_FORWARD(pause());
}
void torrent_handle::set_upload_mode(bool b) const
{
INVARIANT_CHECK;
TORRENT_FORWARD(set_upload_mode(b));
}
void torrent_handle::save_resume_data() const
{
INVARIANT_CHECK;