added upload mode
This commit is contained in:
parent
6b048dc85e
commit
f09774607f
|
@ -1,4 +1,5 @@
|
||||||
* by default, all piece priorities are set to 0 when a write fails.
|
* introduced an upload mode, which torrents are switched into when
|
||||||
|
it hits a disk write error, instead of stopping the torrent.
|
||||||
this lets libtorrent keep uploading the parts it has when it
|
this lets libtorrent keep uploading the parts it has when it
|
||||||
encounters a disk-full error for instance
|
encounters a disk-full error for instance
|
||||||
* improved disk error handling and expanded use of error_code in
|
* improved disk error handling and expanded use of error_code in
|
||||||
|
|
|
@ -38,6 +38,34 @@ For a description on how to create torrent files, see make_torrent_.
|
||||||
|
|
||||||
.. _make_torrent: make_torrent.html
|
.. _make_torrent: make_torrent.html
|
||||||
|
|
||||||
|
things to keep in mind
|
||||||
|
======================
|
||||||
|
|
||||||
|
A common problem developers are facing is torrents stopping without explanation.
|
||||||
|
Here is a description on which conditions libtorrent will stop your torrents,
|
||||||
|
how to find out about it and what to do about it.
|
||||||
|
|
||||||
|
Make sure to keep track of the paused state, the error state and the upload
|
||||||
|
mode of your torrents. By default, torrents are auto-managed, which means
|
||||||
|
libtorrent will pause them, unpause them, scrape them and take them out
|
||||||
|
of upload-mode automatically.
|
||||||
|
|
||||||
|
Whenever a torrent encounters a fatal error, it will be stopped, and the
|
||||||
|
``session_status::error`` will describe the error that caused it. If a torrent
|
||||||
|
is auto managed, it is scraped periodically and paused or resumed based on
|
||||||
|
the number of downloaders per seed. This will effectively seed torrents that
|
||||||
|
are in the greatest need of seeds.
|
||||||
|
|
||||||
|
If a torrent hits a disk write error, it will be put into upload mode. This
|
||||||
|
means it will not download anything, but only upload. The assumption is that
|
||||||
|
the write error is caused by a full disk or write permission errors. If the
|
||||||
|
torrent is auto-managed, it will periodically be taken out of the upload
|
||||||
|
mode, trying to write things to the disk again. This means torrent will recover
|
||||||
|
from certain disk errors if the problem is resolved. If the torrent is not
|
||||||
|
auto managed, you have to call `set_upload_mode()`_ to turn
|
||||||
|
downloading back on again.
|
||||||
|
|
||||||
|
|
||||||
network primitives
|
network primitives
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
@ -306,6 +334,7 @@ add_torrent()
|
||||||
void* userdata;
|
void* userdata;
|
||||||
bool seed_mode;
|
bool seed_mode;
|
||||||
bool override_resume_data;
|
bool override_resume_data;
|
||||||
|
bool upload_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
torrent_handle add_torrent(add_torrent_params const& params);
|
torrent_handle add_torrent(add_torrent_params const& params);
|
||||||
|
@ -413,6 +442,11 @@ If ``override_resume_data`` is set to true, the ``paused`` and ``auto_managed``
|
||||||
state of the torrent are not loaded from the resume data, but the states requested
|
state of the torrent are not loaded from the resume data, but the states requested
|
||||||
by this ``add_torrent_params`` will override it.
|
by this ``add_torrent_params`` will override it.
|
||||||
|
|
||||||
|
If ``upload_mode`` is set to true, the torrent will be initialized in upload-mode,
|
||||||
|
which means it will not make any piece requests. This state is typically entered
|
||||||
|
on disk I/O errors, and if the torrent is also auto managed, it will be taken out
|
||||||
|
of this state periodically. This mode can be used to avoid race conditions when
|
||||||
|
adjusting priorities of pieces before allowing the torrent to start downloading.
|
||||||
|
|
||||||
remove_torrent()
|
remove_torrent()
|
||||||
----------------
|
----------------
|
||||||
|
@ -1841,6 +1875,7 @@ Its declaration looks like this::
|
||||||
bool is_seed() const;
|
bool is_seed() const;
|
||||||
void force_recheck() const;
|
void force_recheck() const;
|
||||||
void clear_error() const;
|
void clear_error() const;
|
||||||
|
void set_upload_mode(bool m) const;
|
||||||
|
|
||||||
void resolve_countries(bool r);
|
void resolve_countries(bool r);
|
||||||
bool resolve_countries() const;
|
bool resolve_countries() const;
|
||||||
|
@ -2273,6 +2308,23 @@ clear_error()
|
||||||
If the torrent is in an error state (i.e. ``torrent_status::error`` is non-empty), this
|
If the torrent is in an error state (i.e. ``torrent_status::error`` is non-empty), this
|
||||||
will clear the error and start the torrent again.
|
will clear the error and start the torrent again.
|
||||||
|
|
||||||
|
set_upload_mode()
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
void set_upload_mode(bool m) const;
|
||||||
|
|
||||||
|
Explicitly sets the upload mode of the torrent. In upload mode, the torrent will not
|
||||||
|
request any pieces. If the torrent is auto managed, it will automatically be taken out
|
||||||
|
of upload mode periodically (see ``session_settings::optimistic_disk_retry``). Torrents
|
||||||
|
are automatically put in upload mode whenever they encounter a disk write error.
|
||||||
|
|
||||||
|
``m`` should be true to enter upload mode, and false to leave it.
|
||||||
|
|
||||||
|
To test if a torrent is in upload mode, call ``torrent_handle::status()`` and inspect
|
||||||
|
``torrent_status::upload_mode``.
|
||||||
|
|
||||||
resolve_countries()
|
resolve_countries()
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@ -2776,6 +2828,8 @@ It contains the following fields::
|
||||||
int sparse_regions;
|
int sparse_regions;
|
||||||
|
|
||||||
bool seed_mode;
|
bool seed_mode;
|
||||||
|
|
||||||
|
bool upload_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
``progress`` is a value in the range [0, 1], that represents the progress of the
|
``progress`` is a value in the range [0, 1], that represents the progress of the
|
||||||
|
@ -2974,6 +3028,13 @@ a limit on the number of sparse regions in a single file there.
|
||||||
started in seed mode, it will leave seed mode once all pieces have been
|
started in seed mode, it will leave seed mode once all pieces have been
|
||||||
checked or as soon as one piece fails the hash check.
|
checked or as soon as one piece fails the hash check.
|
||||||
|
|
||||||
|
``upload_mode`` is true if the torrent is blocked from downloading. This
|
||||||
|
typically happens when a disk write operation fails. If the torrent is
|
||||||
|
auto-managed, it will periodically be taken out of this state, in the
|
||||||
|
hope that the disk condition (be it disk full or permission errors) has
|
||||||
|
been resolved. If the torrent is not auto-managed, you have to explicitly
|
||||||
|
take it out of the upload mode by calling `set_upload_mode()`_ on the
|
||||||
|
torrent_handle_.
|
||||||
|
|
||||||
peer_info
|
peer_info
|
||||||
=========
|
=========
|
||||||
|
@ -3451,7 +3512,7 @@ session_settings
|
||||||
int read_cache_line_size;
|
int read_cache_line_size;
|
||||||
int write_cache_line_size;
|
int write_cache_line_size;
|
||||||
|
|
||||||
bool adjust_priority_on_disk_failure;
|
int optimistic_disk_retry;
|
||||||
};
|
};
|
||||||
|
|
||||||
``user_agent`` this is the client identification to the tracker.
|
``user_agent`` this is the client identification to the tracker.
|
||||||
|
@ -3857,15 +3918,14 @@ When a piece in the write cache has ``write_cache_line_size`` contiguous
|
||||||
blocks in it, they will be flushed. Setting this to 1 effectively
|
blocks in it, they will be flushed. Setting this to 1 effectively
|
||||||
disables the write cache.
|
disables the write cache.
|
||||||
|
|
||||||
``adjust_priority_on_disk_failure`` specifies what libtorrent should do
|
``optimistic_disk_retry`` is the number of seconds from a disk write
|
||||||
on disk failures. If this is set to true, instead of pausing the torrent
|
errors occur on a torrent until libtorrent will take it out of the
|
||||||
and setting it to an error state when it fails to write to disk, the
|
upload mode, to test if the error condition has been fixed.
|
||||||
priorities of all pieces are set to 0. This effectively means the client
|
|
||||||
can keep seeding the parts that were already downloaded, instead of
|
|
||||||
leaving the swarm because of the error.
|
|
||||||
|
|
||||||
If a read operation fails, it will still set an error on the torrent
|
libtorrent will only do this automatically for auto managed torrents.
|
||||||
and pause it.
|
|
||||||
|
You can explicitly take a torrent out of upload only mode using
|
||||||
|
`set_upload_mode()`_.
|
||||||
|
|
||||||
pe_settings
|
pe_settings
|
||||||
===========
|
===========
|
||||||
|
|
|
@ -427,7 +427,13 @@ namespace libtorrent
|
||||||
void make_time_critical(piece_block const& block);
|
void make_time_critical(piece_block const& block);
|
||||||
|
|
||||||
// adds a block to the request queue
|
// adds a block to the request queue
|
||||||
void add_request(piece_block const& b, bool time_critical = false);
|
// returns true if successful, false otherwise
|
||||||
|
bool add_request(piece_block const& b, bool time_critical = false);
|
||||||
|
|
||||||
|
// clears the request queue and sends cancels for all messages
|
||||||
|
// in the download queue
|
||||||
|
void cancel_all_requests();
|
||||||
|
|
||||||
// removes a block from the request queue or download queue
|
// removes a block from the request queue or download queue
|
||||||
// sends a cancel message if appropriate
|
// sends a cancel message if appropriate
|
||||||
// refills the request queue, and possibly ignoring pieces requested
|
// refills the request queue, and possibly ignoring pieces requested
|
||||||
|
|
|
@ -174,6 +174,7 @@ namespace libtorrent
|
||||||
, userdata(0)
|
, userdata(0)
|
||||||
, seed_mode(false)
|
, seed_mode(false)
|
||||||
, override_resume_data(false)
|
, override_resume_data(false)
|
||||||
|
, upload_mode(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
boost::intrusive_ptr<torrent_info> ti;
|
boost::intrusive_ptr<torrent_info> ti;
|
||||||
|
@ -190,6 +191,7 @@ namespace libtorrent
|
||||||
void* userdata;
|
void* userdata;
|
||||||
bool seed_mode;
|
bool seed_mode;
|
||||||
bool override_resume_data;
|
bool override_resume_data;
|
||||||
|
bool upload_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
|
class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer
|
||||||
|
|
|
@ -173,7 +173,7 @@ namespace libtorrent
|
||||||
, disk_cache_algorithm(largest_contiguous)
|
, disk_cache_algorithm(largest_contiguous)
|
||||||
, read_cache_line_size(16)
|
, read_cache_line_size(16)
|
||||||
, write_cache_line_size(32)
|
, write_cache_line_size(32)
|
||||||
, adjust_priority_on_disk_failure(true)
|
, optimistic_disk_retry(10 * 60)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// this is the user agent that will be sent to the tracker
|
// this is the user agent that will be sent to the tracker
|
||||||
|
@ -600,13 +600,9 @@ namespace libtorrent
|
||||||
// is flushed immediately
|
// is flushed immediately
|
||||||
int write_cache_line_size;
|
int write_cache_line_size;
|
||||||
|
|
||||||
// if this is set to true, piece priorities
|
// this is the number of seconds a disk failure
|
||||||
// will be automatically changed if there is
|
// occurs until libtorrent will re-try.
|
||||||
// an error writing to the disk, attempting
|
int optimistic_disk_retry;
|
||||||
// to avoid hitting the error again. If there
|
|
||||||
// is an error reading, the torrent will be
|
|
||||||
// paused
|
|
||||||
bool adjust_priority_on_disk_failure;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
|
|
|
@ -159,6 +159,9 @@ namespace libtorrent
|
||||||
void start_announcing();
|
void start_announcing();
|
||||||
void stop_announcing();
|
void stop_announcing();
|
||||||
|
|
||||||
|
void set_upload_mode(bool b);
|
||||||
|
bool upload_mode() const { return m_upload_mode; }
|
||||||
|
|
||||||
int seed_rank(session_settings const& s) const;
|
int seed_rank(session_settings const& s) const;
|
||||||
|
|
||||||
enum flags_t { overwrite_existing = 1 };
|
enum flags_t { overwrite_existing = 1 };
|
||||||
|
@ -730,6 +733,9 @@ namespace libtorrent
|
||||||
// one of the trackers in this torrent
|
// one of the trackers in this torrent
|
||||||
ptime m_last_scrape;
|
ptime m_last_scrape;
|
||||||
|
|
||||||
|
// the time when we switched to upload mode
|
||||||
|
ptime m_upload_mode_time;
|
||||||
|
|
||||||
boost::intrusive_ptr<torrent_info> m_torrent_file;
|
boost::intrusive_ptr<torrent_info> m_torrent_file;
|
||||||
|
|
||||||
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
|
void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
|
||||||
|
@ -995,6 +1001,9 @@ namespace libtorrent
|
||||||
// is true if this torrent has been paused
|
// is true if this torrent has been paused
|
||||||
bool m_paused:1;
|
bool m_paused:1;
|
||||||
|
|
||||||
|
// set to true when this torrent may not download anything
|
||||||
|
bool m_upload_mode:1;
|
||||||
|
|
||||||
// if this is true, libtorrent may pause and resume
|
// if this is true, libtorrent may pause and resume
|
||||||
// this torrent depending on queuing rules. Torrents
|
// this torrent depending on queuing rules. Torrents
|
||||||
// started with auto_managed flag set may be added in
|
// started with auto_managed flag set may be added in
|
||||||
|
|
|
@ -273,6 +273,11 @@ namespace libtorrent
|
||||||
|
|
||||||
// is true if this torrent is (still) in seed_mode
|
// is true if this torrent is (still) in seed_mode
|
||||||
bool seed_mode;
|
bool seed_mode;
|
||||||
|
|
||||||
|
// this is set to true when the torrent is blocked
|
||||||
|
// from downloading, typically caused by a file
|
||||||
|
// write operation failing
|
||||||
|
bool upload_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TORRENT_EXPORT block_info
|
struct TORRENT_EXPORT block_info
|
||||||
|
@ -397,6 +402,8 @@ namespace libtorrent
|
||||||
bool is_paused() const;
|
bool is_paused() const;
|
||||||
void pause() const;
|
void pause() const;
|
||||||
void resume() const;
|
void resume() const;
|
||||||
|
void set_upload_mode(bool b) const;
|
||||||
|
|
||||||
void force_recheck() const;
|
void force_recheck() const;
|
||||||
void save_resume_data() const;
|
void save_resume_data() const;
|
||||||
|
|
||||||
|
|
|
@ -2374,7 +2374,7 @@ namespace libtorrent
|
||||||
++m_queued_time_critical;
|
++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;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
|
@ -2393,6 +2393,8 @@ namespace libtorrent
|
||||||
TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end()
|
TORRENT_ASSERT(std::find(m_request_queue.begin(), m_request_queue.end()
|
||||||
, block) == m_request_queue.end());
|
, block) == m_request_queue.end());
|
||||||
|
|
||||||
|
if (t->upload_mode()) return false;
|
||||||
|
|
||||||
piece_picker::piece_state_t state;
|
piece_picker::piece_state_t state;
|
||||||
peer_speed_t speed = peer_speed();
|
peer_speed_t speed = peer_speed();
|
||||||
char const* speedmsg = 0;
|
char const* speedmsg = 0;
|
||||||
|
@ -2413,7 +2415,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!t->picker().mark_as_downloading(block, peer_info_struct(), state))
|
if (!t->picker().mark_as_downloading(block, peer_info_struct(), state))
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (t->alerts().should_post<block_downloading_alert>())
|
if (t->alerts().should_post<block_downloading_alert>())
|
||||||
{
|
{
|
||||||
|
@ -2431,6 +2433,53 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
m_request_queue.push_back(block);
|
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)
|
void peer_connection::cancel_request(piece_block const& block)
|
||||||
|
@ -2588,7 +2637,8 @@ namespace libtorrent
|
||||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||||
TORRENT_ASSERT(t);
|
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();
|
bool empty_download_queue = m_download_queue.empty();
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (t.is_seed()) return;
|
if (t.is_seed()) return;
|
||||||
if (c.no_download()) return;
|
if (c.no_download()) return;
|
||||||
|
if (t.upload_mode()) return;
|
||||||
|
|
||||||
TORRENT_ASSERT(t.valid_metadata());
|
TORRENT_ASSERT(t.valid_metadata());
|
||||||
TORRENT_ASSERT(c.peer_info_struct() != 0 || !dynamic_cast<bt_peer_connection*>(&c));
|
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
|
// ok, we found a piece that's not being downloaded
|
||||||
// by somebody else. request it from this peer
|
// by somebody else. request it from this peer
|
||||||
// and return
|
// and return
|
||||||
c.add_request(*i);
|
if (!c.add_request(*i)) continue;
|
||||||
TORRENT_ASSERT(p.num_peers(*i) == 1);
|
TORRENT_ASSERT(p.num_peers(*i) == 1);
|
||||||
TORRENT_ASSERT(p.is_requested(*i));
|
TORRENT_ASSERT(p.is_requested(*i));
|
||||||
num_requests--;
|
num_requests--;
|
||||||
|
|
|
@ -144,6 +144,7 @@ namespace libtorrent
|
||||||
, m_total_downloaded(0)
|
, m_total_downloaded(0)
|
||||||
, m_started(time_now())
|
, m_started(time_now())
|
||||||
, m_last_scrape(min_time())
|
, 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_torrent_file(p.ti ? p.ti : new torrent_info(p.info_hash))
|
||||||
, m_storage(0)
|
, m_storage(0)
|
||||||
, m_host_resolver(ses.m_io_service)
|
, m_host_resolver(ses.m_io_service)
|
||||||
|
@ -180,6 +181,7 @@ namespace libtorrent
|
||||||
, m_time_scaler(0)
|
, m_time_scaler(0)
|
||||||
, m_abort(false)
|
, m_abort(false)
|
||||||
, m_paused(p.paused)
|
, m_paused(p.paused)
|
||||||
|
, m_upload_mode(p.upload_mode)
|
||||||
, m_auto_managed(p.auto_managed)
|
, m_auto_managed(p.auto_managed)
|
||||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||||
, m_resolving_country(false)
|
, 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)
|
void torrent::handle_disk_error(disk_io_job const& j, peer_connection* c)
|
||||||
{
|
{
|
||||||
if (!j.error) return;
|
if (!j.error) return;
|
||||||
|
@ -389,20 +421,8 @@ namespace libtorrent
|
||||||
// and the filesystem doesn't support sparse files, only zero the priorities
|
// 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
|
// of the pieces that are at the tails of all files, leaving everything
|
||||||
// up to the highest written piece in each file
|
// up to the highest written piece in each file
|
||||||
if (m_ses.settings().adjust_priority_on_disk_failure
|
set_upload_mode(true);
|
||||||
&& has_picker())
|
return;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// put the torrent in an error-state
|
// put the torrent in an error-state
|
||||||
|
@ -4897,6 +4917,8 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
ptime now = time_now();
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||||
for (extension_list_t::iterator i = m_extensions.begin()
|
for (extension_list_t::iterator i = m_extensions.begin()
|
||||||
, end(m_extensions.end()); i != end; ++i)
|
, end(m_extensions.end()); i != end; ++i)
|
||||||
|
@ -4932,6 +4954,15 @@ namespace libtorrent
|
||||||
m_policy.pulse();
|
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())
|
if (is_paused())
|
||||||
{
|
{
|
||||||
// let the stats fade out to 0
|
// let the stats fade out to 0
|
||||||
|
@ -4965,8 +4996,6 @@ namespace libtorrent
|
||||||
if (is_seed()) m_seeding_time += since_last_tick;
|
if (is_seed()) m_seeding_time += since_last_tick;
|
||||||
m_active_time += since_last_tick;
|
m_active_time += since_last_tick;
|
||||||
|
|
||||||
ptime now = time_now();
|
|
||||||
|
|
||||||
// ---- TIME CRITICAL PIECES ----
|
// ---- TIME CRITICAL PIECES ----
|
||||||
|
|
||||||
if (!m_time_critical_pieces.empty())
|
if (!m_time_critical_pieces.empty())
|
||||||
|
@ -5437,6 +5466,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
st.last_scrape = total_seconds(now - m_last_scrape);
|
st.last_scrape = total_seconds(now - m_last_scrape);
|
||||||
}
|
}
|
||||||
|
st.upload_mode = m_upload_mode;
|
||||||
st.up_bandwidth_queue = 0;
|
st.up_bandwidth_queue = 0;
|
||||||
st.down_bandwidth_queue = 0;
|
st.down_bandwidth_queue = 0;
|
||||||
|
|
||||||
|
|
|
@ -290,6 +290,12 @@ namespace libtorrent
|
||||||
TORRENT_FORWARD(pause());
|
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
|
void torrent_handle::save_resume_data() const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
|
@ -271,24 +271,11 @@ void test_transfer(bool test_disk_full = false)
|
||||||
std::cerr << "moving storage" << std::endl;
|
std::cerr << "moving storage" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_disk_full && tor2.is_finished())
|
if (test_disk_full && st2.upload_mode)
|
||||||
{
|
{
|
||||||
test_disk_full = false;
|
test_disk_full = false;
|
||||||
std::vector<int> priorities2 = tor2.piece_priorities();
|
|
||||||
std::cerr << "piece priorities: ";
|
|
||||||
for (std::vector<int>::iterator i = priorities2.begin()
|
|
||||||
, end(priorities2.end()); i != end; ++i)
|
|
||||||
{
|
|
||||||
TEST_CHECK(*i == 0);
|
|
||||||
std::cerr << *i << ", ";
|
|
||||||
}
|
|
||||||
std::cerr << std::endl;
|
|
||||||
|
|
||||||
((test_storage*)tor2.get_storage_impl())->m_limit = 16 * 1024 * 1024;
|
((test_storage*)tor2.get_storage_impl())->m_limit = 16 * 1024 * 1024;
|
||||||
tor2.prioritize_pieces(priorities);
|
tor2.set_upload_mode(false);
|
||||||
std::cerr << "setting priorities: ";
|
|
||||||
std::copy(priorities.begin(), priorities.end(), std::ostream_iterator<int>(std::cerr, ", "));
|
|
||||||
std::cerr << std::endl;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue