forked from premiere/premiere-libtorrent
merged RC_1_1 into master
This commit is contained in:
commit
0c7e86078b
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
src/file.cpp
21
src/file.cpp
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue