added alerts for synchronizing disk io when pausing and moving storage
This commit is contained in:
parent
07c8d1242e
commit
b75a69cd47
|
@ -1307,7 +1307,7 @@ Its declaration looks like this::
|
|||
bool has_metadata() const;
|
||||
|
||||
boost::filesystem::path save_path() const;
|
||||
bool move_storage(boost::filesystem::path const& save_path) const;
|
||||
void move_storage(boost::filesystem::path const& save_path) const;
|
||||
|
||||
sha1_hash info_hash() const;
|
||||
|
||||
|
@ -1404,14 +1404,13 @@ move_storage()
|
|||
|
||||
::
|
||||
|
||||
bool move_storage(boost::filesystem::path const& save_path) const;
|
||||
void move_storage(boost::filesystem::path const& save_path) const;
|
||||
|
||||
Moves the file(s) that this torrent are currently seeding from or downloading to. This
|
||||
operation will only have the desired effect if the given ``save_path`` is located on
|
||||
the same drive as the original save path. If the move operation fails, this function
|
||||
returns false, otherwise true. Post condition for successful operation is:
|
||||
``save_path() == save_path``.
|
||||
|
||||
the same drive as the original save path. Since disk IO is performed in a separate
|
||||
thread, this operation is also asynchronous. Once the operation completes, the
|
||||
``storage_moved_alert`` is generated, with the new path as the message.
|
||||
|
||||
force_reannounce()
|
||||
------------------
|
||||
|
@ -1677,7 +1676,9 @@ There are three cases where this function will just return an empty ``entry``:
|
|||
|
||||
Note that by the time this function returns, the resume data may already be invalid if the torrent
|
||||
is still downloading! The recommended practice is to first pause the torrent, then generate the
|
||||
fast resume data, and then close it down.
|
||||
fast resume data, and then close it down. Since the disk IO is done in a separate thread, in order
|
||||
to synchronize, you shoule to wait for the ``torrent_paused_alert`` before you write the resume
|
||||
data.
|
||||
|
||||
It is still a good idea to save resume data periodically during download as well as when
|
||||
closing down. In full allocation mode the reume data is never invalidated by subsequent
|
||||
|
@ -3240,6 +3241,36 @@ This alert is generated when a peer is blocked by the IP filter. It has the seve
|
|||
virtual std::auto_ptr<alert> clone() const;
|
||||
};
|
||||
|
||||
storage_moved_alert
|
||||
-------------------
|
||||
|
||||
The ``storage_moved_alert`` is generated when all the disk IO has completed and the
|
||||
files have been moved, as an effect of a call to ``torrent_handle::move_storage``. This
|
||||
is useful to synchronize with the actual disk.
|
||||
|
||||
::
|
||||
|
||||
struct storage_moved_alert: torrent_alert
|
||||
{
|
||||
storage_moved_alert(torrent_handle const& h, std::string const& path);
|
||||
virtual std::auto_ptr<alert> clone() const;
|
||||
};
|
||||
|
||||
torrent_paused_alert
|
||||
--------------------
|
||||
|
||||
This alert is generated as a response to a ``torrent_handle::pause`` request. It is
|
||||
generated once all disk IO is complete and the files in the torrent have been closed.
|
||||
This is useful for synchronizing with the disk.
|
||||
|
||||
::
|
||||
|
||||
struct torrent_paused_alert: torrent_alert
|
||||
{
|
||||
torrent_paused_alert(torrent_handle const& h, std::string const& msg);
|
||||
virtual std::auto_ptr<alert> clone() const;
|
||||
};
|
||||
|
||||
|
||||
dispatcher
|
||||
----------
|
||||
|
|
|
@ -81,8 +81,6 @@ namespace libtorrent
|
|||
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct TORRENT_EXPORT tracker_reply_alert: torrent_alert
|
||||
{
|
||||
tracker_reply_alert(torrent_handle const& h
|
||||
|
@ -186,6 +184,26 @@ namespace libtorrent
|
|||
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT storage_moved_alert: torrent_alert
|
||||
{
|
||||
storage_moved_alert(torrent_handle const& h, std::string const& path)
|
||||
: torrent_alert(h, alert::warning, path)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new storage_moved_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT torrent_paused_alert: torrent_alert
|
||||
{
|
||||
torrent_paused_alert(torrent_handle const& h, std::string const& msg)
|
||||
: torrent_alert(h, alert::warning, msg)
|
||||
{}
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT url_seed_alert: torrent_alert
|
||||
{
|
||||
url_seed_alert(
|
||||
|
|
|
@ -210,8 +210,10 @@ namespace libtorrent
|
|||
|
||||
fs::path save_path() const;
|
||||
|
||||
void async_release_files();
|
||||
void async_move_storage(fs::path const& p);
|
||||
void async_release_files(
|
||||
boost::function<void(int, disk_io_job const&)> const& handler);
|
||||
void async_move_storage(fs::path const& p
|
||||
, boost::function<void(int, disk_io_job const&)> const& handler);
|
||||
|
||||
// fills the vector that maps all allocated
|
||||
// slots to the piece that is stored (or
|
||||
|
|
|
@ -526,6 +526,9 @@ namespace libtorrent
|
|||
|
||||
private:
|
||||
|
||||
void on_files_released(int ret, disk_io_job const& j);
|
||||
void on_storage_moved(int ret, disk_io_job const& j);
|
||||
|
||||
void on_piece_verified(int ret, disk_io_job const& j
|
||||
, boost::function<void(bool)> f);
|
||||
|
||||
|
|
|
@ -1090,21 +1090,23 @@ namespace libtorrent
|
|||
return m_storage->verify_resume_data(rd, error);
|
||||
}
|
||||
|
||||
void piece_manager::async_release_files()
|
||||
void piece_manager::async_release_files(
|
||||
boost::function<void(int, disk_io_job const&)> const& handler)
|
||||
{
|
||||
disk_io_job j;
|
||||
j.storage = this;
|
||||
j.action = disk_io_job::release_files;
|
||||
m_io_thread.add_job(j);
|
||||
m_io_thread.add_job(j, handler);
|
||||
}
|
||||
|
||||
void piece_manager::async_move_storage(fs::path const& p)
|
||||
void piece_manager::async_move_storage(fs::path const& p
|
||||
, boost::function<void(int, disk_io_job const&)> const& handler)
|
||||
{
|
||||
disk_io_job j;
|
||||
j.storage = this;
|
||||
j.action = disk_io_job::move_storage;
|
||||
j.str = p.string();
|
||||
m_io_thread.add_job(j);
|
||||
m_io_thread.add_job(j, handler);
|
||||
}
|
||||
|
||||
void piece_manager::async_read(
|
||||
|
|
|
@ -1007,10 +1007,21 @@ namespace libtorrent
|
|||
// disconnect all peers and close all
|
||||
// files belonging to the torrents
|
||||
disconnect_all();
|
||||
if (m_owning_storage.get()) m_storage->async_release_files();
|
||||
if (m_owning_storage.get()) m_storage->async_release_files(
|
||||
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
||||
m_owning_storage = 0;
|
||||
}
|
||||
|
||||
void torrent::on_files_released(int ret, disk_io_job const& j)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
if (alerts().should_post(alert::warning))
|
||||
{
|
||||
alerts().post_alert(torrent_paused_alert(get_handle(), "torrent paused"));
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::announce_piece(int index)
|
||||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
@ -2030,7 +2041,8 @@ namespace libtorrent
|
|||
, bind(&peer_connection::disconnect, _1));
|
||||
|
||||
assert(m_storage);
|
||||
m_storage->async_release_files();
|
||||
m_storage->async_release_files(
|
||||
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
||||
}
|
||||
|
||||
// called when torrent is complete (all pieces downloaded)
|
||||
|
@ -2259,7 +2271,8 @@ namespace libtorrent
|
|||
|
||||
if (m_owning_storage.get())
|
||||
{
|
||||
m_owning_storage->async_move_storage(save_path);
|
||||
m_owning_storage->async_move_storage(save_path
|
||||
, bind(&torrent::on_storage_moved, shared_from_this(), _1, _2));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2267,6 +2280,16 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void torrent::on_storage_moved(int ret, disk_io_job const& j)
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
if (alerts().should_post(alert::warning))
|
||||
{
|
||||
alerts().post_alert(storage_moved_alert(get_handle(), j.str));
|
||||
}
|
||||
}
|
||||
|
||||
piece_manager& torrent::filesystem()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
@ -2434,7 +2457,8 @@ namespace libtorrent
|
|||
assert(m_storage);
|
||||
// TOOD: add a callback which posts
|
||||
// an alert for the client to sync. with
|
||||
m_storage->async_release_files();
|
||||
m_storage->async_release_files(
|
||||
bind(&torrent::on_files_released, shared_from_this(), _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,12 +103,14 @@ void run_storage_tests(torrent_info& info, bool compact_allocation = true)
|
|||
TEST_CHECK(num_pieces == std::count(pieces.begin(), pieces.end()
|
||||
, true));
|
||||
|
||||
|
||||
boost::function<void(int, disk_io_job const&)> none;
|
||||
TEST_CHECK(exists("temp_storage"));
|
||||
pm->async_move_storage("temp_storage2");
|
||||
pm->async_move_storage("temp_storage2", none);
|
||||
test_sleep(2000);
|
||||
TEST_CHECK(!exists("temp_storage"));
|
||||
TEST_CHECK(exists("temp_storage2/temp_storage"));
|
||||
pm->async_move_storage(".");
|
||||
pm->async_move_storage(".", none);
|
||||
test_sleep(2000);
|
||||
TEST_CHECK(!exists("temp_storage2/temp_storage"));
|
||||
remove_all("temp_storage2");
|
||||
|
@ -122,7 +124,7 @@ void run_storage_tests(torrent_info& info, bool compact_allocation = true)
|
|||
pm->async_read(r, bind(&on_read_piece, _1, _2, piece1, piece_size));
|
||||
r.piece = 2;
|
||||
pm->async_read(r, bind(&on_read_piece, _1, _2, piece2, piece_size));
|
||||
pm->async_release_files();
|
||||
pm->async_release_files(none);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue