From d95ddde3f2e2923c609e3345b37b4d0befeaa3b9 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Wed, 9 May 2007 20:16:18 +0000 Subject: [PATCH] more storage fixes for problems related to sparse files support --- src/storage.cpp | 224 +++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 119 deletions(-) diff --git a/src/storage.cpp b/src/storage.cpp index 8e7ec6713..24cc18276 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -629,99 +629,93 @@ namespace libtorrent } int buf_pos = 0; - try + boost::shared_ptr in(m_files.open_file( + this, m_save_path / file_iter->path, file::in)); + + assert(file_offset < file_iter->size); + + assert(slices[0].offset == file_offset); + + size_type new_pos = in->seek(file_offset); + if (new_pos != file_offset) { - boost::shared_ptr in(m_files.open_file( - this, m_save_path / file_iter->path, file::in)); - - assert(file_offset < file_iter->size); - - assert(slices[0].offset == file_offset); - - size_type new_pos = in->seek(file_offset); - if (new_pos != file_offset) - { - // the file was not big enough + // the file was not big enough + if (!fill_zero) throw file_error("slot has no storage"); - } - - #ifndef NDEBUG - size_type in_tell = in->tell(); - assert(in_tell == file_offset); - #endif - - int left_to_read = size; - int slot_size = static_cast(m_info.piece_size(slot)); - - if (offset + left_to_read > slot_size) - left_to_read = slot_size - offset; - - assert(left_to_read >= 0); - - size_type result = left_to_read; - - #ifndef NDEBUG - int counter = 0; - #endif - - while (left_to_read > 0) - { - int read_bytes = left_to_read; - if (file_offset + read_bytes > file_iter->size) - read_bytes = static_cast(file_iter->size - file_offset); - - if (read_bytes > 0) - { - #ifndef NDEBUG - assert(int(slices.size()) > counter); - size_type slice_size = slices[counter].size; - assert(slice_size == read_bytes); - assert(m_info.file_at(slices[counter].file_index).path - == file_iter->path); - #endif - - size_type actual_read = in->read(buf + buf_pos, read_bytes); - - if (read_bytes != actual_read) - { - if (actual_read > 0) buf_pos += actual_read; - // the file was not big enough - throw file_error("slot has no storage"); - } - - left_to_read -= read_bytes; - buf_pos += read_bytes; - assert(buf_pos >= 0); - file_offset += read_bytes; - } - - if (left_to_read > 0) - { - ++file_iter; - #ifndef NDEBUG - // empty files are not returned by map_block, so if - // this file was empty, don't increment the slice counter - if (read_bytes > 0) ++counter; - #endif - path path = m_save_path / file_iter->path; - - file_offset = 0; - in = m_files.open_file( - this, path, file::in); - in->seek(0); - } - } - return result; + std::memset(buf + buf_pos, 0, size - buf_pos); + return size; } - catch (std::exception&) + +#ifndef NDEBUG + size_type in_tell = in->tell(); + assert(in_tell == file_offset); +#endif + + int left_to_read = size; + int slot_size = static_cast(m_info.piece_size(slot)); + + if (offset + left_to_read > slot_size) + left_to_read = slot_size - offset; + + assert(left_to_read >= 0); + + size_type result = left_to_read; + +#ifndef NDEBUG + int counter = 0; +#endif + + while (left_to_read > 0) { - if (fill_zero) + int read_bytes = left_to_read; + if (file_offset + read_bytes > file_iter->size) + read_bytes = static_cast(file_iter->size - file_offset); + + if (read_bytes > 0) { - std::memset(buf + buf_pos, 0, size - buf_pos); - return size; +#ifndef NDEBUG + assert(int(slices.size()) > counter); + size_type slice_size = slices[counter].size; + assert(slice_size == read_bytes); + assert(m_info.file_at(slices[counter].file_index).path + == file_iter->path); +#endif + + size_type actual_read = in->read(buf + buf_pos, read_bytes); + + if (read_bytes != actual_read) + { + // the file was not big enough + if (actual_read > 0) buf_pos += actual_read; + if (!fill_zero) + throw file_error("slot has no storage"); + std::memset(buf + buf_pos, 0, size - buf_pos); + return size; + } + + left_to_read -= read_bytes; + buf_pos += read_bytes; + assert(buf_pos >= 0); + file_offset += read_bytes; + } + + if (left_to_read > 0) + { + ++file_iter; +#ifndef NDEBUG + // empty files are not returned by map_block, so if + // this file was empty, don't increment the slice counter + if (read_bytes > 0) ++counter; +#endif + path path = m_save_path / file_iter->path; + + file_offset = 0; + in = m_files.open_file( + this, path, file::in); + in->seek(0); } - throw; } + return result; } // throws file_error if it fails to write @@ -1217,6 +1211,7 @@ namespace libtorrent int slot_index , int block_size , piece_picker::block_info const* bi) + try { assert(slot_index >= 0); assert(slot_index < m_info.num_pieces()); @@ -1249,6 +1244,10 @@ namespace libtorrent } return crc.final(); } + catch (std::exception&) + { + return 0; + } size_type piece_manager::impl::read( char* buf @@ -1693,11 +1692,7 @@ namespace libtorrent std::vector buf1(slot1_size); m_storage->read(&buf1[0], m_current_slot, 0, slot1_size); if (slot2_size > 0) - { - std::vector buf2(slot2_size); - m_storage->read(&buf2[0], piece_index, 0, slot2_size); - m_storage->write(&buf2[0], m_current_slot, 0, slot2_size); - } + m_storage->move_slot(piece_index, m_current_slot); m_storage->write(&buf1[0], piece_index, 0, slot1_size); assert(m_slot_to_piece[m_current_slot] == unassigned || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); @@ -1723,15 +1718,17 @@ namespace libtorrent const int slot1_size = static_cast(m_info.piece_size(other_piece)); const int slot2_size = piece_index >= 0 ? static_cast(m_info.piece_size(piece_index)) : 0; - std::vector buf1(slot1_size); - m_storage->read(&buf1[0], other_slot, 0, slot1_size); if (slot2_size > 0) { - std::vector buf2(slot2_size); - m_storage->read(&buf2[0], m_current_slot, 0, slot2_size); - m_storage->write(&buf2[0], other_slot, 0, slot2_size); + std::vector buf1(slot1_size); + m_storage->read(&buf1[0], other_slot, 0, slot1_size); + m_storage->move_slot(m_current_slot, other_slot); + m_storage->write(&buf1[0], m_current_slot, 0, slot1_size); + } + else + { + m_storage->move_slot(other_slot, m_current_slot); } - m_storage->write(&buf1[0], m_current_slot, 0, slot1_size); assert(m_slot_to_piece[m_current_slot] == unassigned || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); } @@ -1768,15 +1765,12 @@ namespace libtorrent assert(piece1 == m_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)); + std::vector buf(static_cast(slot3_size)); - m_storage->read(&buf2[0], m_current_slot, 0, slot3_size); - m_storage->read(&buf1[0], slot1, 0, slot1_size); - m_storage->write(&buf1[0], m_current_slot, 0, slot1_size); - m_storage->write(&buf2[0], slot1, 0, slot3_size); + m_storage->read(&buf[0], m_current_slot, 0, slot3_size); + m_storage->move_slot(slot1, m_current_slot); + m_storage->write(&buf[0], slot1, 0, slot3_size); assert(m_slot_to_piece[m_current_slot] == unassigned || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); @@ -1809,21 +1803,16 @@ namespace libtorrent } const int slot1_size = piece1 >= 0 ? static_cast(m_info.piece_size(piece1)) : 0; - const int slot2_size = static_cast(m_info.piece_size(piece2)); const int slot3_size = static_cast(m_info.piece_size(piece_index)); - std::vector buf1(static_cast(m_info.piece_length())); - std::vector buf2(static_cast(m_info.piece_length())); + std::vector buf(static_cast(m_info.piece_length())); - m_storage->read(&buf2[0], m_current_slot, 0, slot3_size); - m_storage->read(&buf1[0], slot2, 0, slot2_size); - m_storage->write(&buf1[0], m_current_slot, 0, slot2_size); + m_storage->read(&buf[0], m_current_slot, 0, slot3_size); + m_storage->move_slot(slot2, m_current_slot); if (slot1_size > 0) - { - m_storage->read(&buf1[0], slot1, 0, slot1_size); - m_storage->write(&buf1[0], slot2, 0, slot1_size); - } - m_storage->write(&buf2[0], slot1, 0, slot3_size); + m_storage->move_slot(slot1, slot2); + m_storage->write(&buf[0], slot1, 0, slot3_size); + assert(m_slot_to_piece[m_current_slot] == unassigned || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); } @@ -2000,10 +1989,7 @@ namespace libtorrent m_piece_to_slot[piece_index] , m_piece_to_slot[piece_at_our_slot]); - const int slot_size = static_cast(m_info.piece_size(slot_index)); - std::vector buf(slot_size); - m_storage->read(&buf[0], piece_index, 0, slot_size); - m_storage->write(&buf[0], slot_index, 0, slot_size); + m_storage->move_slot(piece_index, slot_index); assert(m_slot_to_piece[piece_index] == piece_index); assert(m_piece_to_slot[piece_index] == piece_index);