merged RC_1_1 into master

This commit is contained in:
arvidn 2017-01-08 10:18:41 -05:00
commit 0c7e86078b
12 changed files with 173 additions and 55 deletions

View File

@ -48,6 +48,8 @@
* resume data no longer has timestamps of files
* require C++11 to build libtorrent
* fix division by zero when setting tick_interval > 1000
* fix move_storage() to its own directory (would delete the files)
* fix socks5 support for UDP
* add setting urlseed_max_request_bytes to handle large web seed requests
* fix python build with CC/CXX environment

View File

@ -82,7 +82,7 @@ version_check() {
echo $ECHO_N " testing $vc_checkprog... " $ECHO_C
if $vc_checkprog --version < /dev/null > /dev/null 2>&1; then
vc_actual_version=`$vc_checkprog --version | head -n 1 | \
sed 's/^.*[ ]\([0-9.]*[a-z]*\).*$/\1/'`
sed 's/^[^0-9]*\([0-9.]*\).*$/\1/'`
if compare_versions $vc_min_version $vc_actual_version; then
echo "found $vc_actual_version"
# set variables

View File

@ -37,6 +37,7 @@ alias libtorrent-sims :
[ run test_auto_manage.cpp ]
[ run test_torrent_status.cpp ]
[ run test_swarm.cpp ]
[ run test_session.cpp ]
[ run test_super_seeding.cpp ]
[ run test_utp.cpp ]
[ run test_dht.cpp ]

View File

@ -399,9 +399,9 @@ void setup_swarm(int num_nodes
{
shut_down |= std::all_of(nodes.begin() + 1, nodes.end()
, [](std::shared_ptr<lt::session> const& s)
{ return is_seed(*s); });
{ return is_seed(*s); }) && num_nodes > 1;
if (tick > 88 * (num_nodes - 1) && !shut_down)
if (tick > 88 * (num_nodes - 1) && !shut_down && num_nodes > 1)
{
TEST_ERROR("seeding failed!");
shut_down = true;

View File

@ -39,7 +39,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "utils.hpp"
#include "create_torrent.hpp"
#include "simulator/simulator.hpp"
#include "simulator/utils.hpp"
#include "simulator/utils.hpp" // for timer
#include <iostream>
using namespace sim;

View File

@ -0,0 +1,66 @@
/*
Copyright (c) 2017, 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 "setup_swarm.hpp"
#include "test.hpp"
#include "utils.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/socket.hpp"
#include "simulator/simulator.hpp"
#include "simulator/utils.hpp" // for timer
#include "settings.hpp"
#include "create_torrent.hpp"
using namespace libtorrent;
TORRENT_TEST(seed_mode)
{
// with seed mode
setup_swarm(2, swarm_test::upload
// add session
, [](lt::settings_pack& pack) {
// make sure the session works with a tick interval of 5 seconds
pack.set_int(settings_pack::tick_interval, 5000);
}
// add torrent
, [](lt::add_torrent_params& params) {
params.flags |= add_torrent_params::flag_seed_mode;
}
// on alert
, [](lt::alert const* a, lt::session& ses) {}
// terminate
, [](int ticks, lt::session& ses) -> bool {
// we don't need to finish seeding, exit after 20 seconds
return ticks > 20;
});
}

View File

@ -45,6 +45,7 @@ TORRENT_TEST(status_timers)
{
lt::time_point start_time;
lt::torrent_handle handle;
bool ran_to_completion = false;
setup_swarm(1, swarm_test::upload
// add session
@ -69,12 +70,15 @@ TORRENT_TEST(status_timers)
// represent about 18 hours. The clock steps forward in 4 hour increments
// to stay within that range
if (ticks > 20 * 60 * 60)
{
ran_to_completion = true;
return true;
}
// once an hour, verify that the timers seem correct
if ((ticks % 3600) == 0)
{
lt::time_point now = lt::clock_type::now();
lt::time_point const now = lt::clock_type::now();
auto const since_start = duration_cast<seconds>(now - start_time) - lt::seconds(1);
torrent_status st = handle.status();
TEST_CHECK(st.active_duration == since_start);
@ -94,9 +98,9 @@ TORRENT_TEST(status_timers)
TEST_CHECK(st.last_download == start_time + lt::seconds(1));
}
}
return false;
});
TEST_CHECK(ran_to_completion);
}
// This test makes sure that adding a torrent causes no torrent related alert to

View File

@ -59,29 +59,31 @@ void test_interval(int interval)
sim::simulation sim{network_cfg};
lt::time_point start = lt::clock_type::now();
bool ran_to_completion = false;
sim::asio::io_service web_server(sim, address_v4::from_string("2.2.2.2"));
// listen on port 8080
sim::http_server http(web_server, 8080);
// the timestamps (in seconds) of all announces
std::vector<int> announces;
// the timestamps of all announces
std::vector<lt::time_point> announces;
http.register_handler("/announce"
, [&announces,interval,start](std::string /* method */
, [&announces,interval,start,&ran_to_completion](std::string /* method */
, std::string /* req */
, std::map<std::string, std::string>&)
, std::map<std::string, std::string>&)
{
std::uint32_t const seconds = std::uint32_t(chrono::duration_cast<lt::seconds>(
lt::clock_type::now() - start).count());
announces.push_back(seconds);
// don't collect events once we're done. We're not interested in the
// tracker stopped announce for instance
if (!ran_to_completion)
announces.push_back(lt::clock_type::now());
char response[500];
int const size = std::snprintf(response, sizeof(response), "d8:intervali%de5:peers0:e", interval);
return sim::send_response(200, "OK", size) + response;
});
std::vector<int> announce_alerts;
std::vector<lt::time_point> announce_alerts;
lt::settings_pack default_settings = settings();
lt::add_torrent_params default_add_torrent;
@ -96,26 +98,38 @@ void test_interval(int interval)
// on alert
, [&](lt::alert const* a, lt::session&) {
if (ran_to_completion) return;
if (lt::alert_cast<lt::tracker_announce_alert>(a))
{
std::uint32_t const seconds = std::uint32_t(chrono::duration_cast<lt::seconds>(
a->timestamp() - start).count());
announce_alerts.push_back(seconds);
announce_alerts.push_back(a->timestamp());
}
}
// terminate
, [](int const ticks, lt::session&) -> bool { return ticks > duration; });
, [&](int const ticks, lt::session& ses) -> bool {
if (ticks > duration + 1)
{
ran_to_completion = true;
return true;
}
return false;
});
TEST_CHECK(ran_to_completion);
TEST_EQUAL(announce_alerts.size(), announces.size());
int counter = 0;
for (int i = 0; i < int(announces.size()); ++i)
lt::time_point last_announce = announces[0];
lt::time_point last_alert = announce_alerts[0];
for (int i = 1; i < int(announces.size()); ++i)
{
TEST_EQUAL(announces[i], counter);
TEST_EQUAL(announce_alerts[i], counter);
counter += interval;
if (counter > duration + 1) counter = duration + 1;
// make sure the interval is within 500 ms of what it's supposed to be
// (this accounts for network latencies)
int const actual_interval_ms = duration_cast<lt::milliseconds>(announces[i] - last_announce).count();
TEST_CHECK(abs(actual_interval_ms - interval * 1000) < 500);
last_announce = announces[i];
int const alert_interval_ms = duration_cast<lt::milliseconds>(announce_alerts[i] - last_alert).count();
TEST_CHECK(abs(alert_interval_ms - interval * 1000) < 500);
last_alert = announce_alerts[i];
}
}

View File

@ -698,27 +698,6 @@ namespace libtorrent
}
rename(inf, newf, ec);
// on OSX, the error when trying to rename a file across different
// volumes is EXDEV, which will make it fall back to copying.
if (ec)
{
if (ec != boost::system::errc::no_such_file_or_directory
&& ec != boost::system::errc::invalid_argument
&& ec != boost::system::errc::permission_denied)
{
ec.clear();
copy_file(inf, newf, ec);
if (!ec)
{
// ignore errors when removing
error_code ignore;
remove(inf, ignore);
}
}
}
}
std::string split_path(std::string const& f, bool only_first_part)

View File

@ -5325,14 +5325,14 @@ namespace libtorrent
if (channel == download_channel)
{
return (std::max)((std::max)(m_outstanding_bytes
return std::max((std::max)(m_outstanding_bytes
, m_recv_buffer.packet_bytes_remaining()) + 30
, int(std::int64_t(m_statistics.download_rate()) * 2
/ (1000 / tick_interval)));
* tick_interval / 1000));
}
else
{
return (std::max)((std::max)(m_reading_bytes
return std::max((std::max)(m_reading_bytes
, m_send_buffer.size())
, int((std::int64_t(m_statistics.upload_rate()) * 2
* tick_interval) / 1000));

View File

@ -998,6 +998,10 @@ namespace libtorrent
print_open_files("release files", m_files.name().c_str());
#endif
// indices of all files we ended up copying. These need to be deleted
// later
aux::vector<bool, file_index_t> copied_files(f.num_files(), false);
file_index_t i;
error_code e;
for (i = file_index_t(0); i < f.end_file(); ++i)
@ -1018,10 +1022,22 @@ namespace libtorrent
// volumes, the source should not be deleted until they've all been
// copied. That would let us rollback with higher confidence.
move_file(old_path, new_path, e);
// if the source file doesn't exist. That's not a problem
// we just ignore that file
if (e == boost::system::errc::no_such_file_or_directory)
e.clear();
else if (e
&& e != boost::system::errc::invalid_argument
&& e != boost::system::errc::permission_denied)
{
// moving the file failed
// on OSX, the error when trying to rename a file across different
// volumes is EXDEV, which will make it fall back to copying.
e.clear();
copy_file(old_path, new_path, e);
if (!e) copied_files[i] = true;
}
if (e)
{
@ -1051,15 +1067,16 @@ namespace libtorrent
// files moved out to absolute paths are not moved
if (f.file_absolute_path(i)) continue;
// if we ended up copying the file, don't do anything during
// roll-back
if (copied_files[i]) continue;
std::string const old_path = combine_path(m_save_path, f.file_path(i));
std::string const new_path = combine_path(save_path, f.file_path(i));
if (!exists(old_path))
{
// ignore errors when rolling back
error_code ignore;
move_file(new_path, old_path, ignore);
}
// ignore errors when rolling back
error_code ignore;
move_file(new_path, old_path, ignore);
}
return status_t::fatal_disk_error;
@ -1077,6 +1094,10 @@ namespace libtorrent
if (has_parent_path(f.file_path(i)))
subdirs.insert(parent_path(f.file_path(i)));
// if we ended up renaming the file instead of moving it, there's no
// need to delete the source.
if (copied_files[i] == false) continue;
std::string const old_path = combine_path(old_save_path, f.file_path(i));
// we may still have some files in old old_save_path

View File

@ -1349,6 +1349,37 @@ void delete_dirs(std::string path)
TEST_CHECK(!exists(path));
}
TORRENT_TEST(move_storage_to_self)
{
// call move_storage with the path to the exising storage. should be a no-op
std::string const save_path = current_working_directory();
std::string const test_path = combine_path(save_path, "temp_storage");
delete_dirs(test_path);
aux::session_settings set;
file_storage fs;
std::vector<char> buf;
file_pool fp;
io_service ios;
disk_buffer_pool dp(16 * 1024, ios, std::bind(&nop));
std::shared_ptr<default_storage> s = setup_torrent(fs, fp, buf, save_path, set);
file::iovec_t const b = {&buf[0], 4};
storage_error se;
s->writev(b, piece_index_t(1), 0, 0, se);
TEST_CHECK(exists(combine_path(test_path, combine_path("folder2", "test3.tmp"))));
TEST_CHECK(exists(combine_path(test_path, combine_path("_folder3", "test4.tmp"))));
s->move_storage(save_path, 0, se);
TEST_EQUAL(se.ec, boost::system::errc::success);
TEST_CHECK(exists(test_path));
TEST_CHECK(exists(combine_path(test_path, combine_path("folder2", "test3.tmp"))));
TEST_CHECK(exists(combine_path(test_path, combine_path("_folder3", "test4.tmp"))));
}
TORRENT_TEST(move_storage_into_self)
{
std::string const save_path = current_working_directory();