added option to delete files from disk as a torrent is removed

This commit is contained in:
Arvid Norberg 2007-10-13 03:33:33 +00:00
parent 09bcb3ff2e
commit 59c7f5bfbb
12 changed files with 139 additions and 14 deletions

View File

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

View File

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

View File

@ -64,6 +64,7 @@ namespace libtorrent
, hash
, move_storage
, release_files
, delete_files
};
action_t action;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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