added alerts for synchronizing disk io when pausing and moving storage

This commit is contained in:
Arvid Norberg 2007-06-11 21:24:14 +00:00
parent 07c8d1242e
commit b75a69cd47
7 changed files with 104 additions and 22 deletions

View File

@ -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
----------

View File

@ -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(

View File

@ -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

View File

@ -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);

View File

@ -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(

View File

@ -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));
}
}

View File

@ -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);
}
}