merge checking fix from RC_0_16

This commit is contained in:
Arvid Norberg 2013-01-06 04:53:26 +00:00
parent e45124fc22
commit 38d7e58177
9 changed files with 213 additions and 42 deletions

View File

@ -8,6 +8,7 @@
* fix uTP edge case where udp socket buffer fills up
* fix nagle implementation in uTP
* fixed files checking issue
* added missing pop_alerts() to python bindings
* fixed typos in configure script, inversing some feature-enable/disable flags
* added missing flag_update_subscribe to python bindings

View File

@ -463,7 +463,8 @@ namespace libtorrent
std::vector<boost::uint8_t>().swap(m_file_priority);
// close files that were opened in write mode
m_pool.release(this);
return false;
return error() ? true : false;
}
void default_storage::finalize_file(int index)
@ -2020,6 +2021,7 @@ ret:
{
error = m_storage->error();
TORRENT_ASSERT(error);
m_current_slot = 0;
return fatal_disk_error;
}
m_state = state_finished;
@ -2253,7 +2255,16 @@ ret:
{
if (m_state == state_none) return check_no_fastresume(error);
TORRENT_ASSERT(int(m_piece_to_slot.size()) == m_files.num_pieces());
if (m_piece_to_slot.empty())
{
m_piece_to_slot.clear();
m_piece_to_slot.resize(m_files.num_pieces(), has_no_slot);
}
if (m_slot_to_piece.empty())
{
m_slot_to_piece.clear();
m_slot_to_piece.resize(m_files.num_pieces(), unallocated);
}
current_slot = m_current_slot;
have_piece = -1;

View File

@ -1727,6 +1727,8 @@ namespace libtorrent
if (ret == piece_manager::fatal_disk_error)
{
handle_disk_error(j);
auto_managed(false);
pause();
set_state(torrent_status::queued_for_checking);
std::vector<char>().swap(m_resume_data);
lazy_entry().swap(m_resume_entry);
@ -2050,6 +2052,7 @@ namespace libtorrent
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
debug_log("fatal disk error: (%d) %s", j.error.value(), j.error.message().c_str());
#endif
auto_managed(false);
pause();
set_error(j.error, j.error_file);
// recalculate auto-managed torrents sooner
@ -6876,7 +6879,6 @@ namespace libtorrent
if (!m_storage) init();
if (!checking_files && should_check_files())
queue_torrent_check();
}
void torrent::set_error(error_code const& ec, std::string const& error_file)

View File

@ -56,6 +56,7 @@ test-suite libtorrent :
[ run test_upnp.cpp ]
[ run test_tracker.cpp ]
[ run test_checking.cpp ]
[ run test_web_seed.cpp ]
[ run test_bdecode_performance.cpp ]
[ run test_pe_crypto.cpp ]

View File

@ -5,6 +5,7 @@ test_programs = \
test_bdecode_performance \
test_bencoding \
test_buffer \
test_checking \
test_fast_extension \
test_hasher \
test_http_connection \

View File

@ -221,6 +221,30 @@ boost::intrusive_ptr<T> clone_ptr(boost::intrusive_ptr<T> const& ptr)
return boost::intrusive_ptr<T>(new T(*ptr));
}
void create_random_files(std::string const& path, const int file_sizes[], int num_files)
{
error_code ec;
char* random_data = (char*)malloc(300000);
for (int i = 0; i != num_files; ++i)
{
std::generate(random_data, random_data + 300000, &std::rand);
char filename[200];
snprintf(filename, sizeof(filename), "%s/test%d", path.c_str(), i);
int to_write = file_sizes[i];
file f(filename, file::write_only, ec);
size_type offset = 0;
while (to_write > 0)
{
int s = (std::min)(to_write, 300000);
file::iovec_t b = { random_data, s};
f.writev(offset, &b, 1, ec);
offset += s;
to_write -= s;
}
}
free(random_data);
}
boost::intrusive_ptr<torrent_info> create_torrent(std::ostream* file, int piece_size
, int num_pieces, bool add_tracker, bool encrypted_torrent)
{

View File

@ -55,6 +55,8 @@ void test_sleep(int millisec);
extern int g_udp_tracker_requests;
extern int g_http_tracker_requests;
void create_random_files(std::string const& path, const int file_sizes[], int num_files);
boost::intrusive_ptr<libtorrent::torrent_info> create_torrent(std::ostream* file = 0
, int piece_size = 16 * 1024, int num_pieces = 13, bool add_tracker = true, bool encrypted = false);

166
test/test_checking.cpp Normal file
View File

@ -0,0 +1,166 @@
/*
Copyright (c) 2013, 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 "test.hpp"
#include "setup_transfer.hpp"
#include "libtorrent/create_torrent.hpp"
#include <fstream>
void test_checking(bool read_only_files, bool corrupt_files = false)
{
using namespace libtorrent;
fprintf(stderr, "==== TEST CHECKING %s%s=====\n"
, read_only_files?"read-only-files ":""
, corrupt_files?"corrupt ":"");
// in case the previous run was terminated
error_code ec;
remove_all("tmp1_checking", ec);
if (ec) fprintf(stderr, "ERROR: removing tmp1_checking: (%d) %s\n"
, ec.value(), ec.message().c_str());
create_directory("tmp1_checking", ec);
if (ec) fprintf(stderr, "ERROR: creating directory tmp1_checking: (%d) %s\n"
, ec.value(), ec.message().c_str());
create_directory("tmp1_checking/test_torrent_dir", ec);
if (ec) fprintf(stderr, "ERROR: creating directory test_torrent_dir: (%d) %s\n"
, ec.value(), ec.message().c_str());
file_storage fs;
std::srand(10);
int piece_size = 0x4000;
static const int file_sizes[] =
{ 5, 16 - 5, 16000, 17, 10, 8000, 8000, 1,1,1,1,1,100,1,1,1,1,100,1,1,1,1,1,1
,1,1,1,1,1,1,13,65000,34,75,2,30,400,500,23000,900,43000,400,4300,6, 4};
const int num_files = sizeof(file_sizes)/sizeof(file_sizes[0]);
create_random_files("tmp1_checking/test_torrent_dir", file_sizes, num_files);
add_files(fs, "tmp1_checking/test_torrent_dir");
libtorrent::create_torrent t(fs, piece_size, 0x4000, libtorrent::create_torrent::optimize);
// calculate the hash for all pieces
set_piece_hashes(t, "tmp1_checking", ec);
if (ec) fprintf(stderr, "ERROR: set_piece_hashes: (%d) %s\n"
, ec.value(), ec.message().c_str());
std::vector<char> buf;
bencode(std::back_inserter(buf), t.generate());
boost::intrusive_ptr<torrent_info> ti(new torrent_info(&buf[0], buf.size(), ec));
fprintf(stderr, "generated torrent: %s tmp1_checking/test_torrent_dir\n"
, to_hex(ti->info_hash().to_string()).c_str());
// overwrite the files with new random data
if (corrupt_files)
{
// increase the size of some files. When they're read only that forces
// the checker to open them in write-mode to truncate them
static const int file_sizes2[] =
{ 5, 16 - 5, 16001, 30, 10, 8000, 8000, 1,1,1,1,1,100,1,1,1,1,100,1,1,1,1,1,1
,1,1,1,1,1,1,13,65000,34,75,2,30,400,500,23000,900,43000,400,4300,6, 4};
create_random_files("tmp1_checking/test_torrent_dir", file_sizes2, num_files);
}
// make the files read only
if (read_only_files)
{
for (int i = 0; i < num_files; ++i)
{
char path[1024];
snprintf(path, sizeof(path), "tmp1_checking/test_torrent_dir/test%d", i);
#ifdef TORRENT_WINDOWS
SetFileAttributes(path, FILE_ATTRIBUTE_READONLY);
#else
chmod(path, S_IRUSR);
#endif
}
}
session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48000, 49000), "0.0.0.0", 0);
ses1.set_alert_mask(alert::all_categories);
add_torrent_params p;
p.save_path = "tmp1_checking";
p.ti = ti;
torrent_handle tor1 = ses1.add_torrent(p, ec);
TEST_CHECK(!ec);
torrent_status st;
for (int i = 0; i < 5; ++i)
{
print_alerts(ses1, "ses1");
st = tor1.status();
printf("%d %f %s\n", st.state, st.progress_ppm / 10000.f, st.error.c_str());
if (st.state != torrent_status::queued_for_checking
&& st.state != torrent_status::checking_files
&& st.state != torrent_status::checking_resume_data)
break;
if (!st.error.empty()) break;
test_sleep(1000);
}
if (corrupt_files)
{
TEST_CHECK(!st.is_seeding);
TEST_CHECK(!st.error.empty());
// wait a while to make sure libtorrent survived the error
test_sleep(5000);
st = tor1.status();
TEST_CHECK(!st.is_seeding);
TEST_CHECK(!st.error.empty());
}
else
{
TEST_CHECK(st.is_seeding);
}
remove_all("tmp1_checking", ec);
if (ec) fprintf(stderr, "ERROR: removing tmp1_checking: (%d) %s\n"
, ec.value(), ec.message().c_str());
}
int test_main()
{
test_checking(false);
test_checking(true);
test_checking(true, true);
return 0;
}

View File

@ -225,27 +225,8 @@ int run_suite(char const* protocol, bool test_url_seed, bool chunked_encoding, b
if (test_url_seed)
{
char* random_data = (char*)malloc(300000);
for (int i = 0; i != sizeof(file_sizes)/sizeof(file_sizes[0]); ++i)
{
std::generate(random_data, random_data + 300000, &std::rand);
char filename[200];
snprintf(filename, sizeof(filename), "tmp1_web_seed/test_torrent_dir/test%d", i);
int to_write = file_sizes[i];
file f(filename, file::write_only, ec);
size_type offset = 0;
while (to_write > 0)
{
int s = (std::min)(to_write, 300000);
file::iovec_t b = { random_data, s};
f.writev(offset, &b, 1, ec);
offset += s;
to_write -= s;
}
}
create_random_files("tmp1_web_seed/test_torrent_dir", file_sizes, sizeof(file_sizes)/sizeof(file_sizes[0]));
add_files(fs, "tmp1_web_seed/test_torrent_dir");
free(random_data);
}
else
{
@ -301,25 +282,7 @@ int run_suite(char const* protocol, bool test_url_seed, bool chunked_encoding, b
// corrupt the files now, so that the web seed will be banned
if (test_url_seed)
{
char* random_data = (char*)malloc(300000);
for (int i = 0; i != sizeof(file_sizes)/sizeof(file_sizes[0]); ++i)
{
std::generate(random_data, random_data + 300000, &std::rand);
char filename[200];
snprintf(filename, sizeof(filename), "tmp1_web_seed/test_torrent_dir/test%d", i);
int to_write = file_sizes[i];
file f(filename, file::write_only, ec);
size_type offset = 0;
while (to_write > 0)
{
int s = (std::min)(to_write, 300000);
file::iovec_t b = { random_data, s};
f.writev(offset, &b, 1, ec);
offset += s;
to_write -= s;
}
}
free(random_data);
create_random_files("tmp1_web_seed/test_torrent_dir", file_sizes, sizeof(file_sizes)/sizeof(file_sizes[0]));
}
else
{