added option to delete files from disk as a torrent is removed
This commit is contained in:
parent
09bcb3ff2e
commit
59c7f5bfbb
|
@ -252,6 +252,16 @@ namespace libtorrent
|
|||
{ return std::auto_ptr<alert>(new storage_moved_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert
|
||||
{
|
||||
torrent_deleted_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_deleted_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT torrent_paused_alert: torrent_alert
|
||||
{
|
||||
torrent_paused_alert(torrent_handle const& h, std::string const& msg)
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace libtorrent
|
|||
checker_impl(session_impl& s): m_ses(s), m_abort(false) {}
|
||||
void operator()();
|
||||
piece_checker_data* find_torrent(const sha1_hash& info_hash);
|
||||
void remove_torrent(sha1_hash const& info_hash);
|
||||
void remove_torrent(sha1_hash const& info_hash, int options);
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const;
|
||||
|
@ -270,7 +270,7 @@ namespace libtorrent
|
|||
, bool paused
|
||||
, void* userdata);
|
||||
|
||||
void remove_torrent(torrent_handle const& h);
|
||||
void remove_torrent(torrent_handle const& h, int options);
|
||||
|
||||
std::vector<torrent_handle> get_torrents();
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ namespace libtorrent
|
|||
, hash
|
||||
, move_storage
|
||||
, release_files
|
||||
, delete_files
|
||||
};
|
||||
|
||||
action_t action;
|
||||
|
|
|
@ -219,7 +219,13 @@ namespace libtorrent
|
|||
// number of half open connections.
|
||||
int num_connections() const;
|
||||
|
||||
void remove_torrent(const torrent_handle& h);
|
||||
enum options_t
|
||||
{
|
||||
none = 0,
|
||||
delete_files = 1
|
||||
};
|
||||
|
||||
void remove_torrent(const torrent_handle& h, int options = none);
|
||||
|
||||
void set_settings(session_settings const& s);
|
||||
session_settings const& settings();
|
||||
|
|
|
@ -151,6 +151,10 @@ namespace libtorrent
|
|||
// writing. This is called when a torrent has finished
|
||||
// downloading.
|
||||
virtual void release_files() = 0;
|
||||
|
||||
// this will close all open files and delete them
|
||||
virtual void delete_files() = 0;
|
||||
|
||||
virtual ~storage_interface() {}
|
||||
};
|
||||
|
||||
|
@ -226,6 +230,10 @@ namespace libtorrent
|
|||
boost::function<void(int, disk_io_job const&)> const& handler
|
||||
= boost::function<void(int, disk_io_job const&)>());
|
||||
|
||||
void async_delete_files(
|
||||
boost::function<void(int, disk_io_job const&)> const& handler
|
||||
= boost::function<void(int, disk_io_job const&)>());
|
||||
|
||||
void async_move_storage(fs::path const& p
|
||||
, boost::function<void(int, disk_io_job const&)> const& handler);
|
||||
|
||||
|
@ -270,7 +278,8 @@ namespace libtorrent
|
|||
void switch_to_full_mode();
|
||||
sha1_hash hash_for_piece_impl(int piece);
|
||||
|
||||
void release_files_impl();
|
||||
void release_files_impl() { m_storage->release_files(); }
|
||||
void delete_files_impl() { m_storage->delete_files(); }
|
||||
|
||||
bool move_storage_impl(fs::path const& save_path);
|
||||
|
||||
|
|
|
@ -177,6 +177,8 @@ namespace libtorrent
|
|||
void resume();
|
||||
bool is_paused() const { return m_paused; }
|
||||
|
||||
void delete_files();
|
||||
|
||||
// ============ start deprecation =============
|
||||
void filter_piece(int index, bool filter);
|
||||
void filter_pieces(std::vector<bool> const& bitmask);
|
||||
|
@ -550,6 +552,7 @@ namespace libtorrent
|
|||
|
||||
private:
|
||||
|
||||
void on_files_deleted(int ret, disk_io_job const& j);
|
||||
void on_files_released(int ret, disk_io_job const& j);
|
||||
void on_torrent_paused(int ret, disk_io_job const& j);
|
||||
void on_storage_moved(int ret, disk_io_job const& j);
|
||||
|
|
|
@ -125,6 +125,7 @@ namespace libtorrent
|
|||
, boost::function<void(int, disk_io_job const&)> const& f)
|
||||
{
|
||||
TORRENT_ASSERT(!j.callback);
|
||||
TORRENT_ASSERT(j.storage);
|
||||
boost::mutex::scoped_lock l(m_mutex);
|
||||
|
||||
std::deque<disk_io_job>::reverse_iterator i = m_jobs.rbegin();
|
||||
|
@ -220,6 +221,7 @@ namespace libtorrent
|
|||
bool free_buffer = true;
|
||||
try
|
||||
{
|
||||
TORRENT_ASSERT(j.storage);
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
ptime start = time_now();
|
||||
#endif
|
||||
|
@ -288,6 +290,12 @@ namespace libtorrent
|
|||
#endif
|
||||
j.storage->release_files_impl();
|
||||
break;
|
||||
case disk_io_job::delete_files:
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " delete" << std::endl;
|
||||
#endif
|
||||
j.storage->delete_files_impl();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
|
|
@ -225,9 +225,9 @@ namespace libtorrent
|
|||
, storage_mode, sc, paused, userdata);
|
||||
}
|
||||
|
||||
void session::remove_torrent(const torrent_handle& h)
|
||||
void session::remove_torrent(const torrent_handle& h, int options)
|
||||
{
|
||||
m_impl->remove_torrent(h);
|
||||
m_impl->remove_torrent(h, options);
|
||||
}
|
||||
|
||||
bool session::listen_on(
|
||||
|
|
|
@ -481,7 +481,7 @@ namespace detail
|
|||
return 0;
|
||||
}
|
||||
|
||||
void checker_impl::remove_torrent(sha1_hash const& info_hash)
|
||||
void checker_impl::remove_torrent(sha1_hash const& info_hash, int options)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
for (std::deque<boost::shared_ptr<piece_checker_data> >::iterator i
|
||||
|
@ -490,6 +490,8 @@ namespace detail
|
|||
if ((*i)->info_hash == info_hash)
|
||||
{
|
||||
TORRENT_ASSERT((*i)->processing == false);
|
||||
if (options & session::delete_files)
|
||||
(*i)->torrent_ptr->delete_files();
|
||||
m_torrents.erase(i);
|
||||
return;
|
||||
}
|
||||
|
@ -500,6 +502,8 @@ namespace detail
|
|||
if ((*i)->info_hash == info_hash)
|
||||
{
|
||||
TORRENT_ASSERT((*i)->processing == false);
|
||||
if (options & session::delete_files)
|
||||
(*i)->torrent_ptr->delete_files();
|
||||
m_processing.erase(i);
|
||||
return;
|
||||
}
|
||||
|
@ -1754,7 +1758,7 @@ namespace detail
|
|||
return torrent_handle(this, &m_checker_impl, info_hash);
|
||||
}
|
||||
|
||||
void session_impl::remove_torrent(const torrent_handle& h)
|
||||
void session_impl::remove_torrent(const torrent_handle& h, int options)
|
||||
{
|
||||
if (h.m_ses != this) return;
|
||||
TORRENT_ASSERT(h.m_chk == &m_checker_impl || h.m_chk == 0);
|
||||
|
@ -1769,6 +1773,8 @@ namespace detail
|
|||
if (i != m_torrents.end())
|
||||
{
|
||||
torrent& t = *i->second;
|
||||
if (options & session::delete_files)
|
||||
t.delete_files();
|
||||
t.abort();
|
||||
|
||||
if ((!t.is_paused() || t.should_request())
|
||||
|
@ -1815,7 +1821,7 @@ namespace detail
|
|||
if (d != 0)
|
||||
{
|
||||
if (d->processing) d->abort = true;
|
||||
else m_checker_impl.remove_torrent(h.m_info_hash);
|
||||
else m_checker_impl.remove_torrent(h.m_info_hash, options);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,6 +361,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
void release_files();
|
||||
void delete_files();
|
||||
void initialize(bool allocate_files);
|
||||
bool move_storage(fs::path save_path);
|
||||
size_type read(char* buf, int slot, int offset, int size);
|
||||
|
@ -470,6 +471,38 @@ namespace libtorrent
|
|||
std::vector<char>().swap(m_scratch_buffer);
|
||||
}
|
||||
|
||||
void storage::delete_files()
|
||||
{
|
||||
// make sure we don't have the files open
|
||||
m_files.release(this);
|
||||
std::vector<char>().swap(m_scratch_buffer);
|
||||
|
||||
// delete the files from disk
|
||||
std::set<std::string> directories;
|
||||
typedef std::set<std::string>::iterator iter_t;
|
||||
for (torrent_info::file_iterator i = m_info->begin_files(true)
|
||||
, end(m_info->end_files(true)); i != end; ++i)
|
||||
{
|
||||
std::string p = (m_save_path / i->path).string();
|
||||
fs::path bp = i->path.branch_path();
|
||||
std::pair<iter_t, bool> ret = directories.insert(bp.string());
|
||||
while (ret.second && !bp.empty())
|
||||
{
|
||||
bp = bp.branch_path();
|
||||
std::pair<iter_t, bool> ret = directories.insert(bp.string());
|
||||
}
|
||||
std::remove(p.c_str());
|
||||
}
|
||||
|
||||
// remove the directories. Reverse order to delete
|
||||
// subdirectories first
|
||||
std::for_each(directories.rbegin(), directories.rend()
|
||||
, bind((int(*)(char const*))&std::remove, bind(&std::string::c_str, _1)));
|
||||
|
||||
std::string p = (m_save_path / m_info->name()).string();
|
||||
std::remove(p.c_str());
|
||||
}
|
||||
|
||||
void storage::write_resume_data(entry& rd) const
|
||||
{
|
||||
std::vector<std::pair<size_type, std::time_t> > file_sizes
|
||||
|
@ -981,6 +1014,15 @@ namespace libtorrent
|
|||
m_io_thread.add_job(j, handler);
|
||||
}
|
||||
|
||||
void piece_manager::async_delete_files(
|
||||
boost::function<void(int, disk_io_job const&)> const& handler)
|
||||
{
|
||||
disk_io_job j;
|
||||
j.storage = this;
|
||||
j.action = disk_io_job::delete_files;
|
||||
m_io_thread.add_job(j, handler);
|
||||
}
|
||||
|
||||
void piece_manager::async_move_storage(fs::path const& p
|
||||
, boost::function<void(int, disk_io_job const&)> const& handler)
|
||||
{
|
||||
|
@ -1063,11 +1105,6 @@ namespace libtorrent
|
|||
return m_storage->hash_for_slot(slot, ph, m_info->piece_size(piece));
|
||||
}
|
||||
|
||||
void piece_manager::release_files_impl()
|
||||
{
|
||||
m_storage->release_files();
|
||||
}
|
||||
|
||||
bool piece_manager::move_storage_impl(fs::path const& save_path)
|
||||
{
|
||||
if (m_storage->move_storage(save_path))
|
||||
|
@ -1077,6 +1114,7 @@ namespace libtorrent
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void piece_manager::export_piece_map(
|
||||
std::vector<int>& p, std::vector<bool> const& have) const
|
||||
{
|
||||
|
|
|
@ -1032,6 +1032,16 @@ namespace libtorrent
|
|||
m_announce_timer.cancel();
|
||||
}
|
||||
|
||||
void torrent::on_files_deleted(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_deleted_alert(get_handle(), "files deleted"));
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::on_files_released(int ret, disk_io_job const& j)
|
||||
{
|
||||
/*
|
||||
|
@ -2549,6 +2559,29 @@ namespace libtorrent
|
|||
return limit;
|
||||
}
|
||||
|
||||
void torrent::delete_files()
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
(*i->second->m_logger) << "*** DELETING FILES IN TORRENT\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
disconnect_all();
|
||||
m_paused = true;
|
||||
// tell the tracker that we stopped
|
||||
m_event = tracker_request::stopped;
|
||||
|
||||
if (m_owning_storage.get())
|
||||
{
|
||||
TORRENT_ASSERT(m_storage);
|
||||
m_storage->async_delete_files(
|
||||
bind(&torrent::on_files_deleted, shared_from_this(), _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::pause()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "setup_transfer.hpp"
|
||||
|
||||
using boost::filesystem::remove_all;
|
||||
using boost::filesystem::exists;
|
||||
|
||||
void test_swarm()
|
||||
{
|
||||
|
@ -113,6 +114,11 @@ void test_swarm()
|
|||
TEST_CHECK(std::fabs(average2 - float(rate_limit)) < 3000.f);
|
||||
TEST_CHECK(std::fabs(average3 - float(rate_limit)) < 3000.f);
|
||||
if (tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";
|
||||
|
||||
// make sure the files are deleted
|
||||
ses1.remove_torrent(tor1, session::delete_files);
|
||||
ses2.remove_torrent(tor2, session::delete_files);
|
||||
ses3.remove_torrent(tor3, session::delete_files);
|
||||
}
|
||||
|
||||
int test_main()
|
||||
|
@ -127,6 +133,11 @@ int test_main()
|
|||
|
||||
test_swarm();
|
||||
|
||||
test_sleep(2000);
|
||||
TEST_CHECK(!exists("./tmp1/temporary"));
|
||||
TEST_CHECK(!exists("./tmp2/temporary"));
|
||||
TEST_CHECK(!exists("./tmp3/temporary"));
|
||||
|
||||
remove_all("./tmp1");
|
||||
remove_all("./tmp2");
|
||||
remove_all("./tmp3");
|
||||
|
|
Loading…
Reference in New Issue