diff --git a/src/storage.cpp b/src/storage.cpp index 5b155e635..995a5b742 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -147,7 +147,6 @@ namespace std::time_t last_write_time_win( const path & ph ) { - // Works for both Windows and POSIX struct _stat path_stat; std::wstring wph(safe_convert(ph.native_file_string())); if ( ::_wstat( wph.c_str(), &path_stat ) != 0 ) @@ -1495,6 +1494,44 @@ namespace libtorrent assert(slot1 >= 0); assert(slot2 >= 0); assert(piece2 >= 0); + + if (slot1 == slot2) + { + // this means there are only two pieces involved in the swap + assert(piece1 >= 0); + + // movement diagram: + // +-----------------------------+ + // | | + // +--> slot1 --> current_slot --+ + + m_slot_to_piece[slot1] = piece_index; + m_slot_to_piece[current_slot] = piece1; + + m_piece_to_slot[piece_index] = slot1; + m_piece_to_slot[piece1] = current_slot; + + assert(piece1 == current_slot); + assert(piece_index == slot1); + + const int slot1_size = static_cast(m_info.piece_size(piece1)); + const int slot3_size = static_cast(m_info.piece_size(piece_index)); + std::vector buf1(static_cast(slot1_size)); + std::vector buf2(static_cast(slot3_size)); + + m_storage.read(&buf2[0], current_slot, 0, slot3_size); + m_storage.read(&buf1[0], slot1, 0, slot1_size); + m_storage.write(&buf1[0], current_slot, 0, slot1_size); + m_storage.write(&buf2[0], slot1, 0, slot3_size); + + assert(m_slot_to_piece[current_slot] == unassigned + || m_piece_to_slot[m_slot_to_piece[current_slot]] == current_slot); + + continue; + } + + assert(slot1 != slot2); + assert(piece1 != piece2); // movement diagram: // +---------------------------------------+ diff --git a/test/Jamfile b/test/Jamfile index d6812ae3c..c8c82c982 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -8,7 +8,7 @@ project ; test-suite libtorrent : -# [ run test_storage.cpp ] + [ run test_storage.cpp ] [ run test_piece_picker.cpp ] # [ run test_entry.cpp ] [ run test_bencoding.cpp ] diff --git a/test/test_storage.cpp b/test/test_storage.cpp new file mode 100644 index 000000000..a5fe4fe2c --- /dev/null +++ b/test/test_storage.cpp @@ -0,0 +1,101 @@ +#include "libtorrent/storage.hpp" +#include "libtorrent/hasher.hpp" +#include "libtorrent/session.hpp" + +#include +#include +#include +#include + +#include "test.hpp" + +#define _FILE_OFFSET_BITS 64 +#include +#include +#include +#include +#include + + + +using namespace libtorrent; +using namespace boost::filesystem; + +int test_main() +{ + const int piece_size = 16; + const int half = piece_size / 2; + torrent_info info; + info.set_piece_size(piece_size); + info.add_file("temp_storage/test1.tmp", 17); + info.add_file("temp_storage/test2.tmp", 613); + + char piece0[piece_size] = + { 6, 6, 6, 6, 6, 6, 6, 6 + , 9, 9, 9, 9, 9, 9, 9, 9}; + + char piece1[piece_size] = + { 0, 0, 0, 0, 0, 0, 0, 0 + , 1, 1, 1, 1, 1, 1, 1, 1}; + + char piece2[piece_size] = + { 0, 0, 1, 0, 0, 0, 0, 0 + , 1, 1, 1, 1, 1, 1, 1, 1}; + + info.set_hash(0, hasher(piece0, piece_size).final()); + info.set_hash(1, hasher(piece1, piece_size).final()); + info.set_hash(2, hasher(piece2, piece_size).final()); + + info.create_torrent(); + + create_directory(initial_path() / "temp_storage"); + + int num_pieces = (613 + 17 + piece_size - 1) / piece_size; + TEST_CHECK(info.num_pieces() == num_pieces); + + storage s(info, initial_path()); + + // write piece 1 (in slot 0) + s.write(piece1, 0, 0, half); + s.write(piece1 + half, 0, half, half); + + // verify piece 1 + char piece[piece_size]; + s.read(piece, 0, 0, piece_size); + TEST_CHECK(std::equal(piece, piece + piece_size, piece1)); + + // do the same with piece 0 and 2 (in slot 1 and 2) + s.write(piece0, 1, 0, piece_size); + s.write(piece2, 2, 0, piece_size); + + // verify piece 0 and 2 + s.read(piece, 1, 0, piece_size); + TEST_CHECK(std::equal(piece, piece + piece_size, piece0)); + + s.read(piece, 2, 0, piece_size); + TEST_CHECK(std::equal(piece, piece + piece_size, piece2)); + + // make sure the files have the correct size + TEST_CHECK(file_size(initial_path() / "temp_storage" / "test1.tmp") == 17); + TEST_CHECK(file_size(initial_path() / "temp_storage" / "test2.tmp") == 31); + + // make sure the piece_manager can identify the pieces + piece_manager pm(info, initial_path()); + boost::mutex lock; + libtorrent::detail::piece_checker_data d; + + std::vector pieces; + pm.check_pieces(lock, d, pieces, true); + + pm.read(piece, 0, 0, piece_size); + TEST_CHECK(std::equal(piece, piece + piece_size, piece0)); + + pm.read(piece, 1, 0, piece_size); + TEST_CHECK(std::equal(piece, piece + piece_size, piece1)); + + pm.read(piece, 2, 0, piece_size); + TEST_CHECK(std::equal(piece, piece + piece_size, piece2)); + + return 0; +} +