Merge pull request #167 from arvidn/auto-manage-fix

simplify the queuing logic for checking torrents
This commit is contained in:
Arvid Norberg 2015-09-30 00:40:44 -04:00
commit a16c24dc0b
26 changed files with 977 additions and 188 deletions

View File

@ -1,3 +1,5 @@
* make all non-auto managed torrents exempt from queuing logic, including
checking torrents.
* add option to not proxy tracker connections through proxy
* removed sparse-regions feature
* support using 0 disk threads (to perform disk I/O in network thread)

View File

@ -174,20 +174,130 @@ The format of the magnet URI is:
queuing
=======
libtorrent supports *queuing*. Which means it makes sure that a limited number of
torrents are being downloaded at any given time, and once a torrent is completely
downloaded, the next in line is started.
libtorrent supports *queuing*. Queuing is a mechanism to automatically pause and
resume torrents based on certain criteria. The criteria depends on the overall
state the torrent is in (checking, downloading or seeding).
Torrents that are *auto managed* are subject to the queuing and the active
torrents limits. To make a torrent auto managed, set add_torrent_params::flag_auto_managed
when adding the torrent (see async_add_torrent() and add_torrent()).
To opt-out of the queuing logic, make sure your torrents are added with the
add_torrent_params::flag_auto_managed bit *cleared*. Or call
``torrent_handle::auto_managed(false)`` on the torrent handle.
The limits of the number of downloading and seeding torrents are controlled via
settings_pack::active_downloads, settings_pack::active_seeds and settings_pack::active_limit in
settings_pack. These limits takes non auto managed torrents into account as
well. If there are more non-auto managed torrents being downloaded than the
settings_pack::active_downloads setting, any auto managed torrents will be queued until
torrents are removed so that the number drops below the limit.
The overall purpose of the queuing logic is to improve performance under arbitrary
torrent downloading and seeding load. For example, if you want to download 100
torrents on a limited home connection, you improve performance by downloading
them one at a time (or maybe two at a time), over downloading them all in
parallel. The benefits are:
* the average completion time of a torrent is half of what it would be if all
downloaded in parallel.
* The amount of upload capacity is more likely to reach the *reciprocation rate*
of your peers, and is likely to improve your *return on investment* (download
to upload ratio)
* your disk I/O load is likely to be more local which may improve I/O
performance and decrease fragmentation.
There are fundamentally 3 seaparate queues:
* checking torrents
* downloading torrents
* seeding torrents
Every torrent that is not seeding has a queue number associated with it, this is
its place in line to be started. See torrent_status::queue_position.
On top of the limits of each queue, there is an over arching limit, set in
settings_pack::active_limit. The auto manager will never start more than this
number of torrents (with one exception described below). Non-auto-managed
torrents are exempt from this logic, and not counted.
At a regular interval, torrents are checked if there needs to be any
re-ordering of which torrents are active and which are queued. This interval
can be controlled via settings_pack::auto_manage_interval.
For queuing to work, resume data needs to be saved and restored for all
torrents. See torrent_handle::save_resume_data().
queue position
--------------
The torrents in the front of the queue are started and the rest are ordered by
their queue position. Any newly added torrent is placed at the end of the queue.
Once a torrent is removed or turns into a seed, its queue position is -1 and all
torrents that used to be after it in the queue, decreases their position in
order to fill the gap.
The queue positions are always contiguous, in a sequence without any gaps.
Lower queue position means closer to the front of the queue, and will be
started sooner than torrents with higher queue positions.
To query a torrent for its position in the queue, or change its position, see:
torrent_handle::queue_position(), torrent_handle::queue_position_up(),
torrent_handle::queue_position_down(), torrent_handle::queue_position_top()
and torrent_handle::queue_position_bottom().
checking queue
--------------
The checking queue affects torrents in the torrent_status::checking or
torrent_status::allocating state that are auto-managed.
The checking queue will make sure that (of the torrents in its queue) no more than
settings_pack::active_checking_limit torrents are started at any given time.
Once a torrent completes checking and moves into a diffferent state, the next in
line will be started for checking.
Any torrent added force-started or force-stopped (i.e. the auto managed flag is
_not_ set), will not be subject to this limit and they will all check
independently and in parallel.
downloading queue
-----------------
Similarly to the checking queue, the downloading queue will make sure that no
more than settings_pack::active_downloads torrents are in the downloading
state at any given time.
The torrent_status::queue_position is used again here to determine who is next
in line to be started once a downloading torrent completes or is stopped/removed.
seeding queue
-------------
The seeding queue does not use torrent_status::queue_position to determine which
torrent to seed. Instead, it estimates the *demand* for the torrent to be
seeded. A torrent with few other seeds and many downloaders is assumed to have a
higher demand of more seeds than one with many seeds and few downloaders.
It limits the number of started seeds to settings_pack::active_seeds.
On top of this basic bias, *seed priority* can be controller by specifying a
seed ratio (the upload to download ratio), a seed-time ratio (the download
time to seeding time ratio) and a seed-time (the abosulte time to be seeding a
torrent). Until all those targets are hit, the torrent will be prioritized for
seeding.
Among torrents that have met their seed target, torrents where we don't know of
any other seed take strict priority.
In order to avoid flapping, torrents that were started less than 30 minutes ago
also have priority to keep seeding.
Finally, for torrents where none of the above apply, they are prioritized based
on the download to seed ratio.
The relevant settings to control these limits are
settings_pack::share_ratio_limit, settings_pack::seed_time_ratio_limit and
settings_pack::seed_time_limit.
queuing options
---------------
In addition to simply starting and stopping torrents, the queuing mechanism can
have more fine grained control of the resources used by torrents.
half-started torrents
.....................
In addition to the downloading and seeding limits, there are limits on *actions*
torrents perform. The downloading and seeding limits control whether peers are
@ -203,49 +313,36 @@ limit. These limits are controlled by settings_pack::active_tracker_limit,
settings_pack::active_dht_limit and settings_pack::active_lsd_limit
respectively.
A client that is not concerned about the separate costs of these actions should
set all 3 of these limits to the same value as settings_pack::active_limit (i.e.
the max limit of any active torrent).
Specifically, announcing to a tracker is typically cheaper than
announcing to the DHT. ``active_dht_limit`` will limit the number of
torrents that are allowed to announce to the DHT. The highest priority ones
will, and the lower priority ones won't. The will still be considered started
though, and any incoming peers will still be accepted.
At a regular interval, torrents are checked if there needs to be any
re-ordering of which torrents are active and which are queued. This interval
can be controlled via settings_pack::auto_manage_interval.
If you do not wish to impose such limits (basically, if you do not wish to have
half-started torrents) make sure to set these limits to -1 (infinite).
For queuing to work, resume data needs to be saved and restored for all
torrents. See save_resume_data().
prefer seeds
............
downloading
-----------
In the case where ``active_downloads`` + ``active_seeds`` > ``active_limit``,
there's an ambiguity whether the downloads should be satisfied first or the
seeds. To disambiguate this case, the settings_pack::auto_manage_prefer_seeds
determines whether seeds are preferred or not.
Torrents that are currently being downloaded or incomplete (with bytes still to
download) are queued. The torrents in the front of the queue are started to be
actively downloaded and the rest are ordered with regards to their queue
position. Any newly added torrent is placed at the end of the queue. Once a
torrent is removed or turns into a seed, its queue position is -1 and all
torrents that used to be after it in the queue, decreases their position in
order to fill the gap.
inactive torrents
.................
The queue positions are always in a sequence without any gaps.
Torrents that are not transferring any bytes (downloading or uploading) have a
relatively low cost to be started. It's possible to exempt such torrents from
the download and seed queues by setting settings_pack::dont_count_slow_torrents
to true.
Lower queue position means closer to the front of the queue, and will be
started sooner than torrents with higher queue positions.
To query a torrent for its position in the queue, or change its position, see:
queue_position(), queue_position_up(), queue_position_down(),
queue_position_top() and queue_position_bottom().
seeding
-------
Auto managed seeding torrents are rotated, so that all of them are allocated a
fair amount of seeding. Torrents with fewer completed *seed cycles* are
prioritized for seeding. A seed cycle is completed when a torrent meets either
the share ratio limit (uploaded bytes / downloaded bytes), the share time ratio
(time seeding / time downloaing) or seed time limit (time seeded).
The relevant settings to control these limits are
settings_pack::share_ratio_limit, settings_pack::seed_time_ratio_limit and
settings_pack::seed_time_limit.
Since it sometimes may take a few minutes for a newly started torrent to find
peers and be unchoked, or find peers that are interested in requesting data,
torrents are not considered inactive immadiately. There must be an extended
period of no transfers before it is considered inactive and exempt from the
queuing limits.
fast resume
===========

View File

@ -978,6 +978,10 @@ namespace libtorrent
// ``active_downloads`` and ``active_seeds`` are upper limits on the
// number of downloading torrents and seeding torrents respectively.
// Setting the value to -1 means unlimited.
//
// ``active_checking`` is the limit of number of checking torrents.
// Note that this limit applies to started non-auto-managed torrents as
// well (as long as they are the the checking_files state).
//
// For example if there are 10 seeding torrents and 10 downloading
// torrents, and ``active_downloads`` is 4 and ``active_seeds`` is 4,
@ -987,8 +991,9 @@ namespace libtorrent
// active. Torrents that are not auto managed are not counted against
// these limits.
//
// ``active_limit`` is a hard limit on the number of active torrents.
// This applies even to slow torrents.
// ``active_limit`` is a hard limit on the number of active (auto
// managed) torrents. This limit also applies to slow torrents. It does
// not apply to checking torrents.
//
// ``active_dht_limit`` is the max number of torrents to announce to
// the DHT. By default this is set to 88, which is no more than one
@ -1019,6 +1024,7 @@ namespace libtorrent
// see dynamic-loading-of-torrent-files_.
active_downloads,
active_seeds,
active_checking,
active_dht_limit,
active_tracker_limit,
active_lsd_limit,

View File

@ -1458,9 +1458,11 @@ namespace libtorrent
// ----
// total time we've been available on this torrent
// does not count when the torrent is stopped or paused
// in seconds
// total time we've been active on this torrent. i.e. either (trying to)
// download or seed. does not count time when the torrent is stopped or
// paused. specified in seconds. This only track time _before_ we started
// the torrent this last time. When the torrent is paused, this counter is
// incremented to include this current session.
unsigned int m_active_time:24;
// the index to the last tracker that worked
@ -1468,8 +1470,8 @@ namespace libtorrent
// ----
// total time we've been finished with this torrent
// does not count when the torrent is stopped or paused
// total time we've been finished with this torrent.
// does not count when the torrent is stopped or paused.
unsigned int m_finished_time:24;
// in case the piece picker hasn't been constructed
@ -1512,8 +1514,11 @@ namespace libtorrent
// ----
// total time we've been available as a seed on this torrent
// does not count when the torrent is stopped or paused
// total time we've been available as a seed on this torrent.
// does not count when the torrent is stopped or paused. This value only
// accounts for the time prior to the current start of the torrent. When
// the torrent is paused, this counter is incremented to account for the
// additional seeding time.
unsigned int m_seeding_time:24;
// ----

View File

@ -545,10 +545,12 @@ namespace libtorrent
// requested from it, it is disconnected. This is a graceful shut down of
// the torrent in the sense that no downloaded bytes are wasted.
//
// torrents that are auto-managed may be automatically resumed again. It
// does not make sense to pause an auto-managed torrent without making it
// not automanaged first. Torrents are auto-managed by default when added
// to the session. For more information, see queuing_.
// .. note::
// Torrents that are auto-managed may be automatically resumed again. It
// does not make sense to pause an auto-managed torrent without making it
// not automanaged first. Torrents are auto-managed by default when added
// to the session. For more information, see queuing_.
//
void pause(int flags = 0) const;
void resume() const;

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) 2015, 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

@ -3556,17 +3556,18 @@ retry:
torrent* t = *i;
TORRENT_ASSERT(t->state() == torrent_status::checking_files);
if (limit <= 0)
{
t->pause();
}
else
{
t->resume();
t->start_checking();
--limit;
}
TORRENT_ASSERT(t->is_auto_managed());
if (limit <= 0)
{
t->pause();
}
else
{
t->resume();
t->start_checking();
--limit;
}
}
}
void session_impl::auto_manage_torrents(std::vector<torrent*>& list
@ -3580,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);
@ -3593,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);
}
}
@ -3629,18 +3646,20 @@ retry:
// these counters are set to the number of torrents
// of each kind we're allowed to have active
int num_downloaders = settings().get_int(settings_pack::active_downloads);
int num_seeds = settings().get_int(settings_pack::active_seeds);
int checking_limit = 1;
int downloading_limit = settings().get_int(settings_pack::active_downloads);
int seeding_limit = settings().get_int(settings_pack::active_seeds);
int checking_limit = settings().get_int(settings_pack::active_checking);
int dht_limit = settings().get_int(settings_pack::active_dht_limit);
int tracker_limit = settings().get_int(settings_pack::active_tracker_limit);
int lsd_limit = settings().get_int(settings_pack::active_lsd_limit);
int hard_limit = settings().get_int(settings_pack::active_limit);
if (num_downloaders == -1)
num_downloaders = (std::numeric_limits<int>::max)();
if (num_seeds == -1)
num_seeds = (std::numeric_limits<int>::max)();
if (downloading_limit == -1)
downloading_limit = (std::numeric_limits<int>::max)();
if (seeding_limit == -1)
seeding_limit = (std::numeric_limits<int>::max)();
if (checking_limit == -1)
checking_limit = (std::numeric_limits<int>::max)();
if (hard_limit == -1)
hard_limit = (std::numeric_limits<int>::max)();
if (dht_limit == -1)
@ -3650,20 +3669,6 @@ retry:
if (tracker_limit == -1)
tracker_limit = (std::numeric_limits<int>::max)();
// deduct "force started" torrents from the hard_limit
// we don't have explicit access to the number of force started torrents,
// but we know how many started downloading and seeding torrents we have.
// if we subtract all non-force started torrents from the total, we get
// the number of force started.
hard_limit -= m_stats_counters[counters::num_downloading_torrents] -
downloaders.size();
hard_limit -= m_stats_counters[counters::num_seeding_torrents]
+ m_stats_counters[counters::num_upload_only_torrents] -
seeds.size();
// TODO: 3 also deduct force started checking torrents from checking_limit
// also deduct started inactive torrents from hard_limit
// if hard_limit is <= 0, all torrents in these lists should be paused.
// The order is not relevant
if (hard_limit > 0)
@ -3691,16 +3696,16 @@ retry:
if (settings().get_bool(settings_pack::auto_manage_prefer_seeds))
{
auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit
, hard_limit, num_seeds);
, hard_limit, seeding_limit);
auto_manage_torrents(downloaders, dht_limit, tracker_limit, lsd_limit
, hard_limit, num_downloaders);
, hard_limit, downloading_limit);
}
else
{
auto_manage_torrents(downloaders, dht_limit, tracker_limit, lsd_limit
, hard_limit, num_downloaders);
, hard_limit, downloading_limit);
auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit
, hard_limit, num_seeds);
, hard_limit, seeding_limit);
}
}

View File

@ -260,6 +260,7 @@ namespace libtorrent
SET(peer_tos, 0, &session_impl::update_peer_tos),
SET(active_downloads, 3, &session_impl::trigger_auto_manage),
SET(active_seeds, 5, &session_impl::trigger_auto_manage),
SET_NOPREV(active_checking, 1, &session_impl::trigger_auto_manage),
SET(active_dht_limit, 88, 0),
SET(active_tracker_limit, 1600, 0),
SET(active_lsd_limit, 60, 0),

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;
@ -8082,23 +8085,27 @@ namespace libtorrent
bool is_downloading = false;
bool is_seeding = false;
if (m_state == torrent_status::checking_files
&& (is_auto_managed() || allows_peers()))
if (is_auto_managed() && !has_error())
{
is_checking = true;
}
else if (is_auto_managed() && !has_error()
&& (is_paused()
|| !is_inactive()
|| !settings().get_bool(settings_pack::dont_count_slow_torrents)))
{
// torrents that are started (not paused) and
// inactive are not part of any list. They will not be touched because
// they are inactive
if (is_finished())
is_seeding = true;
else
is_downloading = true;
if (m_state == torrent_status::checking_files
|| m_state == torrent_status::allocating)
{
is_checking = true;
}
else if (m_state == torrent_status::downloading_metadata
|| m_state == torrent_status::downloading
|| m_state == torrent_status::finished
|| m_state == torrent_status::seeding
|| m_state == torrent_status::downloading)
{
// torrents that are started (not paused) and
// inactive are not part of any list. They will not be touched because
// they are inactive
if (is_finished())
is_seeding = true;
else
is_downloading = true;
}
}
update_list(aux::session_interface::torrent_downloading_auto_managed
@ -8550,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();
}
@ -8825,20 +8828,24 @@ namespace libtorrent
bool is_downloading = false;
bool is_seeding = false;
if (m_state == torrent_status::checking_files
&& (is_auto_managed() || allows_peers()))
if (is_auto_managed() && !has_error())
{
is_checking = true;
}
else if (is_auto_managed() && !has_error()
&& (is_paused()
|| !is_inactive()
|| !settings().get_bool(settings_pack::dont_count_slow_torrents)))
{
if (is_finished())
is_seeding = true;
else
is_downloading = true;
if (m_state == torrent_status::checking_files
|| m_state == torrent_status::allocating)
{
is_checking = true;
}
else if (m_state == torrent_status::downloading_metadata
|| m_state == torrent_status::downloading
|| m_state == torrent_status::finished
|| m_state == torrent_status::seeding
|| m_state == torrent_status::downloading)
{
if (is_finished())
is_seeding = true;
else
is_downloading = true;
}
}
TORRENT_ASSERT(m_links[aux::session_interface::torrent_checking_auto_managed].in_list()
@ -9359,9 +9366,9 @@ namespace libtorrent
enum flags
{
seed_ratio_not_met = 0x40000000,
no_seeds = 0x20000000,
recently_started = 0x10000000,
prio_mask = 0x0fffffff
no_seeds = 0x20000000,
recently_started = 0x10000000,
prio_mask = 0x0fffffff
};
if (!is_finished()) return 0;
@ -9556,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()
@ -9675,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();
@ -9730,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())
@ -9974,18 +9989,27 @@ namespace libtorrent
int torrent::finished_time() const
{
// m_finished_time does not account for the current "session", just the
// time before we last started this torrent. To get the current time, we
// need to add the time since we started it
return m_finished_time + ((!is_finished() || is_paused()) ? 0
: (m_ses.session_time() - m_became_finished));
}
int torrent::active_time() const
{
// m_active_time does not account for the current "session", just the
// time before we last started this torrent. To get the current time, we
// need to add the time since we started it
return m_active_time + (is_paused() ? 0
: m_ses.session_time() - m_started);
}
int torrent::seeding_time() const
{
// m_seeding_time does not account for the current "session", just the
// time before we last started this torrent. To get the current time, we
// need to add the time since we started it
return m_seeding_time + ((!is_seed() || is_paused()) ? 0
: m_ses.session_time() - m_became_seed);
}

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