now that force-started torrents aren't affected by the auto-manager, they need to be explicitly kicked when entering checking state (it would be nice if all this could be done through set_state())

This commit is contained in:
arvidn 2015-09-19 21:06:56 -04:00
parent dab0f8b8d0
commit 5da511f140
20 changed files with 729 additions and 59 deletions

View File

@ -23,6 +23,7 @@ project
;
alias libtorrent-sims :
[ run test_auto_manage.cpp ]
[ run test_torrent_status.cpp ]
[ run test_swarm.cpp ]
[ run test_super_seeding.cpp ]

View File

@ -82,7 +82,8 @@ struct swarm
m_torrents.push_back(lt::torrent_handle());
lt::add_torrent_params params = m_config.add_torrent(i);
ses->async_add_torrent(params);
if (!params.save_path.empty())
ses->async_add_torrent(params);
ses->set_alert_notify(boost::bind(&swarm::on_alert_notify, this, i));
}

View File

@ -59,7 +59,7 @@ struct swarm_config : swarm_setup_provider
if (ec) fprintf(stderr, "failed to create directory: \"%s\": %s\n"
, path.c_str(), ec.message().c_str());
std::ofstream file(combine_path(path, "temporary").c_str());
m_ti = ::create_torrent(&file, 0x4000, 9, false);
m_ti = ::create_torrent(&file, "temporary", 0x4000, 9, false);
file.close();
}

View File

@ -0,0 +1,626 @@
/*
Copyright (c) 2008, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/session.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/settings_pack.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/deadline_timer.hpp"
#include "test.hpp"
#include "swarm_config.hpp"
#include "settings.hpp"
#include "simulator/simulator.hpp"
#include <iostream>
using namespace sim;
const int num_torrents = 10;
lt::add_torrent_params create_torrent(int idx, bool seed)
{
// TODO: if we want non-seeding torrents, that could be a bit cheaper to
// create
lt::add_torrent_params params;
int swarm_id = test_counter();
char name[200];
snprintf(name, sizeof(name), "temp-%02d", idx);
char path[200];
snprintf(path, sizeof(path), "swarm-%04d-peer-%02d"
, swarm_id, idx);
error_code ec;
create_directory(path, ec);
if (ec) fprintf(stderr, "failed to create directory: \"%s\": %s\n"
, path, ec.message().c_str());
std::ofstream file(combine_path(path, name).c_str());
params.ti = ::create_torrent(&file, name
, 0x4000, 9 + idx, false);
file.close();
// by setting the save path to a dummy path, it won't be seeding
params.save_path = seed ? path : "dummy";
return params;
}
using sim::asio::ip::address_v4;
std::unique_ptr<sim::asio::io_service> make_io_service(sim::simulation& sim, int i)
{
char ep[30];
snprintf(ep, sizeof(ep), "50.0.%d.%d", (i + 1) >> 8, (i + 1) & 0xff);
return std::unique_ptr<sim::asio::io_service>(new sim::asio::io_service(
sim, asio::ip::address_v4::from_string(ep)));
}
// this is the general template for these tests. create the session with custom
// settings (Settings), set up the test, by adding torrents with certain
// arguments (Setup), run the test and verify the end state (Test)
template <typename Settings, typename Setup, typename Test>
void run_test(Settings const& sett, Setup const& setup, Test const& test)
{
// setup the simulation
sim::default_config network_cfg;
sim::simulation sim{network_cfg};
std::unique_ptr<sim::asio::io_service> ios = make_io_service(sim, 0);
lt::session_proxy zombie;
// setup settings pack to use for the session (customization point)
lt::settings_pack pack = settings();
sett(pack);
// create session
std::shared_ptr<lt::session> ses = std::make_shared<lt::session>(pack, *ios);
// set up test, like adding torrents (customization point)
setup(*ses);
// set up a timer to fire later, to verify everything we expected to happen
// happened
lt::deadline_timer timer(*ios);
timer.expires_from_now(lt::seconds((num_torrents + 1) * 60));
timer.async_wait([&](boost::system::error_code const& ec)
{
test(*ses);
// shut down
zombie = ses->abort();
ses.reset();
});
sim.run();
}
TORRENT_TEST(dont_count_slow_torrents)
{
run_test(
[](settings_pack& sett) {
// session settings
sett.set_bool(settings_pack::dont_count_slow_torrents, true);
sett.set_int(settings_pack::active_downloads, 1);
sett.set_int(settings_pack::active_seeds, 1);
},
[](lt::session& ses) {
// add torrents
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, false);
params.flags |= add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point last = lt::time_point::min();
lt::time_point start_time = alerts[0]->timestamp();
int num_started = 0;
for (alert* a : alerts)
{
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
if (alert_cast<torrent_resumed_alert>(a) == nullptr) continue;
lt::time_point t = a->timestamp();
if (last != lt::time_point::min())
{
// expect starting of new torrents to be spaced by 60 seconds
// the division by 2 is to allow some slack (it's integer
// division)
TEST_EQUAL(duration_cast<lt::seconds>(t - last).count() / 2, 60 / 2);
}
last = t;
++num_started;
}
TEST_EQUAL(num_started, num_torrents);
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(h.status().auto_managed);
TEST_EQUAL(h.status().paused, false);
}
});
}
TORRENT_TEST(count_slow_torrents)
{
run_test(
[](settings_pack& sett) {
// session settings
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
sett.set_int(settings_pack::active_downloads, 1);
sett.set_int(settings_pack::active_seeds, 1);
},
[](lt::session& ses) {
// add torrents
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, false);
params.flags |= add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (only one should have been started, even though
// they're all idle)
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
int num_started = 0;
for (alert* a : alerts)
{
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
if (alert_cast<torrent_resumed_alert>(a) == nullptr) continue;
++num_started;
}
TEST_EQUAL(num_started, 1);
num_started = 0;
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(h.status().auto_managed);
num_started += !h.status().paused;
}
TEST_EQUAL(num_started, 1);
});
}
TORRENT_TEST(force_stopped_download)
{
run_test(
[](settings_pack& sett) {
// session settings
sett.set_bool(settings_pack::dont_count_slow_torrents, true);
sett.set_int(settings_pack::active_downloads, 10);
sett.set_int(settings_pack::active_seeds, 10);
},
[](lt::session& ses) {
// add torrents
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, false);
// torrents are paused and not auto-managed
params.flags &= ~add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (none should have been started)
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
for (alert* a : alerts)
{
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
// we don't expect any torrents being started or stopped, since
// they're all force stopped
TEST_CHECK(alert_cast<torrent_resumed_alert>(a) == nullptr);
TEST_CHECK(alert_cast<torrent_paused_alert>(a) == nullptr);
}
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(!h.status().auto_managed);
TEST_CHECK(h.status().paused);
}
});
}
TORRENT_TEST(force_started)
{
run_test(
[](settings_pack& sett) {
// session settings
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
sett.set_int(settings_pack::active_downloads, 1);
sett.set_int(settings_pack::active_seeds, 1);
},
[](lt::session& ses) {
// add torrents
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, false);
// torrents are started and not auto-managed
params.flags &= ~add_torrent_params::flag_auto_managed;
params.flags &= ~add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (none should have been started)
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
for (alert* a : alerts)
{
printf("%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
// we don't expect any torrents being started or stopped, since
// they're all force started
TEST_CHECK(alert_cast<torrent_resumed_alert>(a) == nullptr);
TEST_CHECK(alert_cast<torrent_paused_alert>(a) == nullptr);
}
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(!h.status().auto_managed);
TEST_CHECK(!h.status().paused);
}
});
}
TORRENT_TEST(seed_limit)
{
run_test(
[](settings_pack& sett) {
// session settings
// set the seed limit to 3
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
sett.set_int(settings_pack::active_checking, 1);
sett.set_int(settings_pack::active_seeds, 3);
},
[](lt::session& ses) {
// add torrents
// add 5 seeds
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, true);
// torrents are paused and auto-managed
params.flags |= add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (none should have been started)
// make sure only 3 got started
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
int num_started = 0;
int num_checking = 0;
int num_seeding = 0;
for (alert* a : alerts)
{
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
if (alert_cast<torrent_resumed_alert>(a))
{
++num_started;
fprintf(stderr, "started: %d checking: %d seeding: %d\n"
, num_started, num_checking, num_seeding);
}
else if (alert_cast<torrent_paused_alert>(a))
{
TEST_CHECK(num_started > 0);
--num_started;
fprintf(stderr, "started: %d checking: %d seeding: %d\n"
, num_started, num_checking, num_seeding);
}
else if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
{
if (sc->prev_state == torrent_status::checking_files)
--num_checking;
else if (sc->prev_state == torrent_status::seeding)
--num_seeding;
if (sc->state == torrent_status::checking_files)
++num_checking;
else if (sc->state == torrent_status::seeding)
++num_seeding;
fprintf(stderr, "started: %d checking: %d seeding: %d\n"
, num_started, num_checking, num_seeding);
// while at least one torrent is checking, there may be another
// started torrent (the checking one), other than that, only 3
// torrents are allowed to be started and seeding
TEST_CHECK(num_started <= 3 + 1);
TEST_CHECK(num_started <= 1 || num_seeding > 0);
}
}
TEST_EQUAL(num_started, 3);
num_started = 0;
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(h.status().auto_managed);
TEST_CHECK(h.status().is_seeding);
num_started += !h.status().paused;
}
TEST_EQUAL(num_started, 3);
});
}
TORRENT_TEST(download_limit)
{
run_test(
[](settings_pack& sett) {
// session settings
// set the seed limit to 3
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
sett.set_int(settings_pack::active_checking, 1);
sett.set_int(settings_pack::active_downloads, 3);
},
[](lt::session& ses) {
// add torrents
// add 5 seeds
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, false);
// torrents are paused and auto-managed
params.flags |= add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (none should have been started)
// make sure only 3 got started
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
int num_started = 0;
int num_checking = 0;
int num_downloading = 0;
for (alert* a : alerts)
{
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
if (alert_cast<torrent_resumed_alert>(a))
{
++num_started;
fprintf(stderr, "started: %d checking: %d downloading: %d\n"
, num_started, num_checking, num_downloading);
}
else if (alert_cast<torrent_paused_alert>(a))
{
TEST_CHECK(num_started > 0);
--num_started;
fprintf(stderr, "started: %d checking: %d downloading: %d\n"
, num_started, num_checking, num_downloading);
}
else if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
{
if (sc->prev_state == torrent_status::checking_files)
--num_checking;
else if (sc->prev_state == torrent_status::downloading)
--num_downloading;
if (sc->state == torrent_status::checking_files)
++num_checking;
else if (sc->state == torrent_status::downloading)
++num_downloading;
fprintf(stderr, "started: %d checking: %d downloading: %d\n"
, num_started, num_checking, num_downloading);
// while at least one torrent is checking, there may be another
// started torrent (the checking one), other than that, only 3
// torrents are allowed to be started and seeding
TEST_CHECK(num_started <= 3 + 1);
TEST_CHECK(num_started <= 1 || num_downloading > 0);
}
}
TEST_EQUAL(num_started, 3);
num_started = 0;
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(h.status().auto_managed);
TEST_CHECK(!h.status().is_finished);
num_started += !h.status().paused;
}
TEST_EQUAL(num_started, 3);
});
}
// make sure torrents don't announce to the tracker when transitioning from
// checking to paused downloading
TORRENT_TEST(checking_announce)
{
run_test(
[](settings_pack& sett) {
// session settings
// set the seed limit to 3
sett.set_bool(settings_pack::dont_count_slow_torrents, false);
sett.set_int(settings_pack::active_checking, 1);
// just set the tracker retry intervals really long, to make sure we
// don't keep retrying the tracker (since there's nothing running
// there, it will fail)
sett.set_int(settings_pack::tracker_backoff, 100000);
// only the first torrent added should ever announce
sett.set_int(settings_pack::active_seeds, 1);
},
[](lt::session& ses) {
// add torrents
// add 5 seeds
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, true);
// torrents are paused and auto-managed
params.flags |= add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
// we need this to get the tracker_announce_alert
params.trackers.push_back("http://10.10.0.2/announce");
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (none should have been started)
// make sure only 3 got started
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
int num_announce = 0;
for (alert* a : alerts)
{
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
if (alert_cast<tracker_announce_alert>(a))
++num_announce;
}
TEST_EQUAL(num_announce, 1);
int num_started = 0;
for (torrent_handle const& h : ses.get_torrents())
{
TEST_CHECK(h.status().auto_managed);
num_started += !h.status().paused;
}
TEST_EQUAL(num_started, 1);
});
}
TORRENT_TEST(paused_checking)
{
run_test(
[](settings_pack& sett) {
// session settings
// set the seed limit to 3
sett.set_bool(settings_pack::dont_count_slow_torrents, true);
sett.set_int(settings_pack::active_checking, 1);
},
[](lt::session& ses) {
// add torrents
// add 5 seeds
for (int i = 0; i < num_torrents; ++i)
{
lt::add_torrent_params params = create_torrent(i, true);
// torrents are paused and auto-managed
params.flags &= ~add_torrent_params::flag_auto_managed;
params.flags |= add_torrent_params::flag_paused;
ses.async_add_torrent(params);
}
},
[](lt::session& ses) {
// verify result (none should have been started)
// make sure only 3 got started
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
lt::time_point start_time = alerts[0]->timestamp();
for (alert* a : alerts)
{
fprintf(stderr, "%-3d %s\n", int(duration_cast<lt::seconds>(a->timestamp()
- start_time).count()), a->message().c_str());
if (state_changed_alert* sc = alert_cast<state_changed_alert>(a))
{
TEST_CHECK(sc->state == torrent_status::checking_files
|| sc->state == torrent_status::checking_resume_data);
}
}
for (torrent_handle const& h : ses.get_torrents())
{
// even though all torrents are seeding, libtorrent shouldn't know
// that, because they should never have been checked (because they
// were force stopped)
TEST_CHECK(!h.status().is_seeding);
TEST_CHECK(!h.status().auto_managed);
TEST_CHECK(h.status().paused);
}
});
}
// TODO: assert that the torrent_paused_alert is posted when pausing
// downloading, seeding, checking torrents as well as the graceful pause
// TODO: test limits of tracker, DHT and LSD announces

View File

@ -39,6 +39,7 @@ using namespace libtorrent;
using namespace sim;
namespace lt = libtorrent;
// this is a test for torrent_status time counters are correct
struct test_swarm_config : swarm_config
{
test_swarm_config()

View File

@ -63,7 +63,7 @@ struct swarm_config : swarm_setup_provider
create_directory(save_path, ec);
std::ofstream file(combine_path(save_path, "temporary").c_str());
m_ti = ::create_torrent(&file, 0x4000, 90, false);
m_ti = ::create_torrent(&file, "temporary", 0x4000, 90, false);
file.close();
}

View File

@ -3800,6 +3800,15 @@ namespace libtorrent
peer_log(peer_log_alert::info, "GRACEFUL_PAUSE", "NO MORE DOWNLOAD");
#endif
disconnect(errors::torrent_paused, op_bittorrent);
// if this was the last connection, post the alert
// TODO: it would be nice if none of this logic would leak outside of
// the torrent object)
if (t->num_peers() == 0)
{
if (t->alerts().should_post<torrent_paused_alert>())
t->alerts().emplace_alert<torrent_paused_alert>(t->get_handle());
}
return;
}

View File

@ -3581,6 +3581,23 @@ retry:
TORRENT_ASSERT(t->state() != torrent_status::checking_files);
// inactive torrents don't count (and if you configured them to do so,
// the torrent won't say it's inactive)
if (hard_limit > 0 && t->is_inactive())
{
t->set_announce_to_dht(--dht_limit >= 0);
t->set_announce_to_trackers(--tracker_limit >= 0);
t->set_announce_to_lsd(--lsd_limit >= 0);
--hard_limit;
#ifndef TORRENT_DISABLE_LOGGING
if (!t->allows_peers())
t->log_to_all_peers("auto manager starting (inactive) torrent");
#endif
t->set_allow_peers(true);
continue;
}
if (type_limit > 0 && hard_limit > 0)
{
t->set_announce_to_dht(--dht_limit >= 0);
@ -3594,19 +3611,18 @@ retry:
t->log_to_all_peers("auto manager starting torrent");
#endif
t->set_allow_peers(true);
continue;
}
else
{
#ifndef TORRENT_DISABLE_LOGGING
if (t->allows_peers())
t->log_to_all_peers("auto manager pausing torrent");
if (t->allows_peers())
t->log_to_all_peers("auto manager pausing torrent");
#endif
// use graceful pause for auto-managed torrents
t->set_allow_peers(false, true);
t->set_announce_to_dht(false);
t->set_announce_to_trackers(false);
t->set_announce_to_lsd(false);
}
// use graceful pause for auto-managed torrents
t->set_allow_peers(false, true);
t->set_announce_to_dht(false);
t->set_announce_to_trackers(false);
t->set_announce_to_lsd(false);
}
}

View File

@ -2553,6 +2553,7 @@ namespace libtorrent
// either the fastresume data was rejected or there are
// some files
set_state(torrent_status::checking_files);
if (should_check_files()) start_checking();
// start the checking right away (potentially)
m_ses.trigger_auto_manage();
@ -2814,20 +2815,19 @@ namespace libtorrent
return;
}
if (m_graceful_pause_mode && !m_allow_peers && m_checking_piece == m_num_checked_pieces)
{
// we are in graceful pause mode, and we just completed the last outstanding job.
// now we can be considered paused
if (alerts().should_post<torrent_paused_alert>())
alerts().emplace_alert<torrent_paused_alert>(get_handle());
}
// we paused the checking
if (!should_check_files())
{
#ifndef TORRENT_DISABLE_LOGGING
debug_log("on_piece_hashed, checking paused");
#endif
if (m_checking_piece == m_num_checked_pieces)
{
// we are paused, and we just completed the last outstanding job.
// now we can be considered paused
if (alerts().should_post<torrent_paused_alert>())
alerts().emplace_alert<torrent_paused_alert>(get_handle());
}
return;
}
@ -2853,12 +2853,15 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_LOGGING
debug_log("on_piece_hashed, completed");
#endif
// we're done checking!
files_checked();
if (m_auto_managed)
{
// if we're auto managed. assume we need to be paused until the auto
// managed logic runs again (which is triggered further down)
pause();
}
// recalculate auto-managed torrents sooner
// in order to start checking the next torrent
m_ses.trigger_auto_manage();
// we're done checking! (this should cause a call to trigger_auto_manage)
files_checked();
// reset the checking state
m_checking_piece = 0;
@ -8554,10 +8557,6 @@ namespace libtorrent
m_need_save_resume_data = true;
}
// if we just finished checking and we're not a seed, we are
// likely to be unpaused
m_ses.trigger_auto_manage();
if (is_finished() && m_state != torrent_status::finished)
finished();
}
@ -9564,17 +9563,8 @@ namespace libtorrent
m_need_save_resume_data = true;
state_updated();
bool prev_graceful = m_graceful_pause_mode;
m_graceful_pause_mode = graceful;
update_gauge();
if (!m_ses.is_paused() || (prev_graceful && !m_graceful_pause_mode))
{
do_pause();
// if this torrent was just paused
// we might have to resume some other auto-managed torrent
m_ses.trigger_auto_manage();
}
}
void torrent::do_pause()
@ -9683,6 +9673,11 @@ namespace libtorrent
p->disconnect(errors::torrent_paused, op_bittorrent);
i = j;
}
if (m_connections.empty())
{
if (alerts().should_post<torrent_paused_alert>())
alerts().emplace_alert<torrent_paused_alert>(get_handle());
}
if (update_ticks)
{
update_want_peers();
@ -9738,8 +9733,20 @@ namespace libtorrent
{
TORRENT_ASSERT(is_single_thread());
if (m_allow_peers == b
&& m_graceful_pause_mode == graceful) return;
if (m_allow_peers == b)
{
// there is one special case here. If we are
// currently in graceful pause mode, and we just turned into regular
// paused mode, we need to actually pause the torrent properly
if (m_allow_peers == false
&& m_graceful_pause_mode == true
&& graceful == false)
{
m_graceful_pause_mode = graceful;
do_pause();
}
return;
}
m_allow_peers = b;
if (!m_ses.is_paused())

View File

@ -68,6 +68,7 @@ using namespace libtorrent;
int old_stdout = -1;
int old_stderr = -1;
bool redirect_output = true;
bool keep_files = false;
extern int _g_test_idx;
@ -143,6 +144,8 @@ void print_usage(char const* executable)
"OPTIONS:\n"
"-h,--help show this help\n"
"-l,--list list the tests available to run\n"
"-k,--keep keep files created by the test\n"
" regardless of whether it passed or not\n"
"-n,--no-redirect don't redirect test output to\n"
" temporary file, but let it go straight\n"
" to stdout\n"
@ -181,6 +184,11 @@ EXPORT int main(int argc, char const* argv[])
{
redirect_output = false;
}
if (strcmp(argv[0], "-k") == 0 || strcmp(argv[0], "--keep") == 0)
{
keep_files = true;
}
++argv;
--argc;
}
@ -365,7 +373,7 @@ EXPORT int main(int argc, char const* argv[])
int ret = print_failures();
#if !defined TORRENT_LOGGING
if (ret == 0)
if (ret == 0 && !keep_files)
{
remove_all(test_dir, ec);
if (ec)

View File

@ -615,7 +615,8 @@ void create_random_files(std::string const& path, const int file_sizes[], int nu
free(random_data);
}
boost::shared_ptr<torrent_info> create_torrent(std::ostream* file, int piece_size
boost::shared_ptr<torrent_info> create_torrent(std::ostream* file
, char const* name, int piece_size
, int num_pieces, bool add_tracker, std::string ssl_certificate)
{
// excercise the path when encountering invalid urls
@ -624,7 +625,7 @@ boost::shared_ptr<torrent_info> create_torrent(std::ostream* file, int piece_siz
file_storage fs;
int total_size = piece_size * num_pieces;
fs.add_file("temporary", total_size);
fs.add_file(name, total_size);
libtorrent::create_torrent t(fs, piece_size);
if (add_tracker)
{
@ -744,7 +745,7 @@ setup_transfer(lt::session* ses1, lt::session* ses2, lt::session* ses3
error_code ec;
create_directory("tmp1" + suffix, ec);
std::ofstream file(combine_path("tmp1" + suffix, "temporary").c_str());
t = ::create_torrent(&file, piece_size, 9, false);
t = ::create_torrent(&file, "temporary", piece_size, 9, false);
file.close();
if (clear_files)
{

View File

@ -83,8 +83,8 @@ EXPORT void test_sleep(int millisec);
EXPORT void create_random_files(std::string const& path, const int file_sizes[], int num_files);
EXPORT boost::shared_ptr<libtorrent::torrent_info> create_torrent(std::ostream* file = 0
, int piece_size = 16 * 1024, int num_pieces = 13, bool add_tracker = true
, std::string ssl_certificate = "");
, char const* name = "temporary", int piece_size = 16 * 1024, int num_pieces = 13
, bool add_tracker = true, std::string ssl_certificate = "");
EXPORT boost::tuple<libtorrent::torrent_handle
, libtorrent::torrent_handle

View File

@ -119,7 +119,7 @@ void test_transfer(settings_pack const& sett)
error_code ec;
create_directory("tmp1_priority", ec);
std::ofstream file("tmp1_priority/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
add_torrent_params addp;

View File

@ -139,7 +139,7 @@ session_proxy test_proxy(settings_pack::proxy_type_t proxy_type, int flags)
remove_all("tmp1_privacy", ec);
create_directory("tmp1_privacy", ec);
std::ofstream file(combine_path("tmp1_privacy", "temporary").c_str());
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
char http_tracker_url[200];

View File

@ -80,7 +80,7 @@ TORRENT_TEST(recheck)
create_directory("tmp1_recheck", ec);
if (ec) fprintf(stderr, "create_directory: %s\n", ec.message().c_str());
std::ofstream file("tmp1_recheck/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 4 * 1024 * 1024
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 4 * 1024 * 1024
, 7, false);
file.close();

View File

@ -256,7 +256,7 @@ void test_remap_files_scatter(storage_mode_t storage_mode = storage_mode_sparse)
create_directory("tmp1_remap2", ec);
std::ofstream file("tmp1_remap2/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 32 * 1024, 7);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 32 * 1024, 7);
file.close();
file_storage fs;

View File

@ -160,7 +160,7 @@ void test_ssl(int test_idx, bool use_utp)
create_directory("tmp1_ssl", ec);
std::ofstream file("tmp1_ssl/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary"
, 16 * 1024, 13, false, combine_path("..", combine_path("ssl", "root_ca_cert.pem")));
file.close();
@ -549,7 +549,7 @@ void test_malicious_peer()
// create torrent
create_directory("tmp3_ssl", ec);
std::ofstream file("tmp3_ssl/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary"
, 16 * 1024, 13, false, combine_path("..", combine_path("ssl", "root_ca_cert.pem")));
file.close();

View File

@ -330,7 +330,7 @@ TORRENT_TEST(udp_tracker)
remove_all("tmp1_tracker", ec);
create_directory("tmp1_tracker", ec);
std::ofstream file(combine_path("tmp1_tracker", "temporary").c_str());
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
char tracker_url[200];
@ -411,7 +411,7 @@ TORRENT_TEST(try_next)
remove_all("tmp2_tracker", ec);
create_directory("tmp2_tracker", ec);
std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str());
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
// this should fail
@ -519,7 +519,7 @@ TORRENT_TEST(http_peers)
remove_all("tmp2_tracker", ec);
create_directory("tmp2_tracker", ec);
std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str());
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
char tracker_url[200];
@ -593,7 +593,7 @@ void test_proxy(bool proxy_trackers)
remove_all("tmp2_tracker", ec);
create_directory("tmp2_tracker", ec);
std::ofstream file(combine_path("tmp2_tracker", "temporary").c_str());
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
char tracker_url[200];

View File

@ -235,7 +235,7 @@ void test_transfer(int proxy_type, settings_pack const& sett
create_directory("tmp1_transfer", ec);
std::ofstream file("tmp1_transfer/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 16 * 1024, 13, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 16 * 1024, 13, false);
file.close();
TEST_CHECK(exists(combine_path("tmp1_transfer", "temporary")));

View File

@ -93,7 +93,7 @@ void test_transfer()
create_directory("./tmp1_utp", ec);
std::ofstream file("./tmp1_utp/temporary");
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, 128 * 1024, 6, false);
boost::shared_ptr<torrent_info> t = ::create_torrent(&file, "temporary", 128 * 1024, 6, false);
file.close();
// for performance testing