forked from premiere/premiere-libtorrent
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;
|
bool has_metadata() const;
|
||||||
|
|
||||||
boost::filesystem::path save_path() 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;
|
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
|
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
|
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
|
the same drive as the original save path. Since disk IO is performed in a separate
|
||||||
returns false, otherwise true. Post condition for successful operation is:
|
thread, this operation is also asynchronous. Once the operation completes, the
|
||||||
``save_path() == save_path``.
|
``storage_moved_alert`` is generated, with the new path as the message.
|
||||||
|
|
||||||
|
|
||||||
force_reannounce()
|
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
|
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
|
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
|
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
|
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;
|
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
|
dispatcher
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -81,8 +81,6 @@ namespace libtorrent
|
||||||
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
|
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct TORRENT_EXPORT tracker_reply_alert: torrent_alert
|
struct TORRENT_EXPORT tracker_reply_alert: torrent_alert
|
||||||
{
|
{
|
||||||
tracker_reply_alert(torrent_handle const& h
|
tracker_reply_alert(torrent_handle const& h
|
||||||
|
@ -186,6 +184,26 @@ namespace libtorrent
|
||||||
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
|
{ 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
|
struct TORRENT_EXPORT url_seed_alert: torrent_alert
|
||||||
{
|
{
|
||||||
url_seed_alert(
|
url_seed_alert(
|
||||||
|
|
|
@ -210,8 +210,10 @@ namespace libtorrent
|
||||||
|
|
||||||
fs::path save_path() const;
|
fs::path save_path() const;
|
||||||
|
|
||||||
void async_release_files();
|
void async_release_files(
|
||||||
void async_move_storage(fs::path const& p);
|
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
|
// fills the vector that maps all allocated
|
||||||
// slots to the piece that is stored (or
|
// slots to the piece that is stored (or
|
||||||
|
|
|
@ -526,6 +526,9 @@ namespace libtorrent
|
||||||
|
|
||||||
private:
|
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
|
void on_piece_verified(int ret, disk_io_job const& j
|
||||||
, boost::function<void(bool)> f);
|
, boost::function<void(bool)> f);
|
||||||
|
|
||||||
|
|
|
@ -1090,21 +1090,23 @@ namespace libtorrent
|
||||||
return m_storage->verify_resume_data(rd, error);
|
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;
|
disk_io_job j;
|
||||||
j.storage = this;
|
j.storage = this;
|
||||||
j.action = disk_io_job::release_files;
|
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;
|
disk_io_job j;
|
||||||
j.storage = this;
|
j.storage = this;
|
||||||
j.action = disk_io_job::move_storage;
|
j.action = disk_io_job::move_storage;
|
||||||
j.str = p.string();
|
j.str = p.string();
|
||||||
m_io_thread.add_job(j);
|
m_io_thread.add_job(j, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void piece_manager::async_read(
|
void piece_manager::async_read(
|
||||||
|
|
|
@ -1007,10 +1007,21 @@ namespace libtorrent
|
||||||
// disconnect all peers and close all
|
// disconnect all peers and close all
|
||||||
// files belonging to the torrents
|
// files belonging to the torrents
|
||||||
disconnect_all();
|
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;
|
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)
|
void torrent::announce_piece(int index)
|
||||||
{
|
{
|
||||||
// INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
@ -2030,7 +2041,8 @@ namespace libtorrent
|
||||||
, bind(&peer_connection::disconnect, _1));
|
, bind(&peer_connection::disconnect, _1));
|
||||||
|
|
||||||
assert(m_storage);
|
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)
|
// called when torrent is complete (all pieces downloaded)
|
||||||
|
@ -2259,7 +2271,8 @@ namespace libtorrent
|
||||||
|
|
||||||
if (m_owning_storage.get())
|
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
|
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()
|
piece_manager& torrent::filesystem()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
@ -2434,7 +2457,8 @@ namespace libtorrent
|
||||||
assert(m_storage);
|
assert(m_storage);
|
||||||
// TOOD: add a callback which posts
|
// TOOD: add a callback which posts
|
||||||
// an alert for the client to sync. with
|
// 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()
|
TEST_CHECK(num_pieces == std::count(pieces.begin(), pieces.end()
|
||||||
, true));
|
, true));
|
||||||
|
|
||||||
|
|
||||||
|
boost::function<void(int, disk_io_job const&)> none;
|
||||||
TEST_CHECK(exists("temp_storage"));
|
TEST_CHECK(exists("temp_storage"));
|
||||||
pm->async_move_storage("temp_storage2");
|
pm->async_move_storage("temp_storage2", none);
|
||||||
test_sleep(2000);
|
test_sleep(2000);
|
||||||
TEST_CHECK(!exists("temp_storage"));
|
TEST_CHECK(!exists("temp_storage"));
|
||||||
TEST_CHECK(exists("temp_storage2/temp_storage"));
|
TEST_CHECK(exists("temp_storage2/temp_storage"));
|
||||||
pm->async_move_storage(".");
|
pm->async_move_storage(".", none);
|
||||||
test_sleep(2000);
|
test_sleep(2000);
|
||||||
TEST_CHECK(!exists("temp_storage2/temp_storage"));
|
TEST_CHECK(!exists("temp_storage2/temp_storage"));
|
||||||
remove_all("temp_storage2");
|
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));
|
pm->async_read(r, bind(&on_read_piece, _1, _2, piece1, piece_size));
|
||||||
r.piece = 2;
|
r.piece = 2;
|
||||||
pm->async_read(r, bind(&on_read_piece, _1, _2, piece2, piece_size));
|
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