more storage fixes for problems related to sparse files support
This commit is contained in:
parent
d7ed474a46
commit
d95ddde3f2
|
@ -629,8 +629,6 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
|
|
||||||
int buf_pos = 0;
|
int buf_pos = 0;
|
||||||
try
|
|
||||||
{
|
|
||||||
boost::shared_ptr<file> in(m_files.open_file(
|
boost::shared_ptr<file> in(m_files.open_file(
|
||||||
this, m_save_path / file_iter->path, file::in));
|
this, m_save_path / file_iter->path, file::in));
|
||||||
|
|
||||||
|
@ -642,13 +640,16 @@ namespace libtorrent
|
||||||
if (new_pos != 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");
|
throw file_error("slot has no storage");
|
||||||
|
std::memset(buf + buf_pos, 0, size - buf_pos);
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
size_type in_tell = in->tell();
|
size_type in_tell = in->tell();
|
||||||
assert(in_tell == file_offset);
|
assert(in_tell == file_offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int left_to_read = size;
|
int left_to_read = size;
|
||||||
int slot_size = static_cast<int>(m_info.piece_size(slot));
|
int slot_size = static_cast<int>(m_info.piece_size(slot));
|
||||||
|
@ -660,9 +661,9 @@ namespace libtorrent
|
||||||
|
|
||||||
size_type result = left_to_read;
|
size_type result = left_to_read;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (left_to_read > 0)
|
while (left_to_read > 0)
|
||||||
{
|
{
|
||||||
|
@ -672,21 +673,24 @@ namespace libtorrent
|
||||||
|
|
||||||
if (read_bytes > 0)
|
if (read_bytes > 0)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
assert(int(slices.size()) > counter);
|
assert(int(slices.size()) > counter);
|
||||||
size_type slice_size = slices[counter].size;
|
size_type slice_size = slices[counter].size;
|
||||||
assert(slice_size == read_bytes);
|
assert(slice_size == read_bytes);
|
||||||
assert(m_info.file_at(slices[counter].file_index).path
|
assert(m_info.file_at(slices[counter].file_index).path
|
||||||
== file_iter->path);
|
== file_iter->path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_type actual_read = in->read(buf + buf_pos, read_bytes);
|
size_type actual_read = in->read(buf + buf_pos, read_bytes);
|
||||||
|
|
||||||
if (read_bytes != actual_read)
|
if (read_bytes != actual_read)
|
||||||
{
|
{
|
||||||
if (actual_read > 0) buf_pos += actual_read;
|
|
||||||
// the file was not big enough
|
// the file was not big enough
|
||||||
|
if (actual_read > 0) buf_pos += actual_read;
|
||||||
|
if (!fill_zero)
|
||||||
throw file_error("slot has no storage");
|
throw file_error("slot has no storage");
|
||||||
|
std::memset(buf + buf_pos, 0, size - buf_pos);
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
left_to_read -= read_bytes;
|
left_to_read -= read_bytes;
|
||||||
|
@ -698,11 +702,11 @@ namespace libtorrent
|
||||||
if (left_to_read > 0)
|
if (left_to_read > 0)
|
||||||
{
|
{
|
||||||
++file_iter;
|
++file_iter;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// empty files are not returned by map_block, so if
|
// empty files are not returned by map_block, so if
|
||||||
// this file was empty, don't increment the slice counter
|
// this file was empty, don't increment the slice counter
|
||||||
if (read_bytes > 0) ++counter;
|
if (read_bytes > 0) ++counter;
|
||||||
#endif
|
#endif
|
||||||
path path = m_save_path / file_iter->path;
|
path path = m_save_path / file_iter->path;
|
||||||
|
|
||||||
file_offset = 0;
|
file_offset = 0;
|
||||||
|
@ -713,16 +717,6 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
|
||||||
{
|
|
||||||
if (fill_zero)
|
|
||||||
{
|
|
||||||
std::memset(buf + buf_pos, 0, size - buf_pos);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// throws file_error if it fails to write
|
// throws file_error if it fails to write
|
||||||
void storage::write(
|
void storage::write(
|
||||||
|
@ -1217,6 +1211,7 @@ namespace libtorrent
|
||||||
int slot_index
|
int slot_index
|
||||||
, int block_size
|
, int block_size
|
||||||
, piece_picker::block_info const* bi)
|
, piece_picker::block_info const* bi)
|
||||||
|
try
|
||||||
{
|
{
|
||||||
assert(slot_index >= 0);
|
assert(slot_index >= 0);
|
||||||
assert(slot_index < m_info.num_pieces());
|
assert(slot_index < m_info.num_pieces());
|
||||||
|
@ -1249,6 +1244,10 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
return crc.final();
|
return crc.final();
|
||||||
}
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_type piece_manager::impl::read(
|
size_type piece_manager::impl::read(
|
||||||
char* buf
|
char* buf
|
||||||
|
@ -1693,11 +1692,7 @@ namespace libtorrent
|
||||||
std::vector<char> buf1(slot1_size);
|
std::vector<char> buf1(slot1_size);
|
||||||
m_storage->read(&buf1[0], m_current_slot, 0, slot1_size);
|
m_storage->read(&buf1[0], m_current_slot, 0, slot1_size);
|
||||||
if (slot2_size > 0)
|
if (slot2_size > 0)
|
||||||
{
|
m_storage->move_slot(piece_index, m_current_slot);
|
||||||
std::vector<char> 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->write(&buf1[0], piece_index, 0, slot1_size);
|
m_storage->write(&buf1[0], piece_index, 0, slot1_size);
|
||||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
|| 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<int>(m_info.piece_size(other_piece));
|
const int slot1_size = static_cast<int>(m_info.piece_size(other_piece));
|
||||||
const int slot2_size = piece_index >= 0 ? static_cast<int>(m_info.piece_size(piece_index)) : 0;
|
const int slot2_size = piece_index >= 0 ? static_cast<int>(m_info.piece_size(piece_index)) : 0;
|
||||||
std::vector<char> buf1(slot1_size);
|
|
||||||
m_storage->read(&buf1[0], other_slot, 0, slot1_size);
|
|
||||||
if (slot2_size > 0)
|
if (slot2_size > 0)
|
||||||
{
|
{
|
||||||
std::vector<char> buf2(slot2_size);
|
std::vector<char> buf1(slot1_size);
|
||||||
m_storage->read(&buf2[0], m_current_slot, 0, slot2_size);
|
m_storage->read(&buf1[0], other_slot, 0, slot1_size);
|
||||||
m_storage->write(&buf2[0], other_slot, 0, slot2_size);
|
m_storage->move_slot(m_current_slot, other_slot);
|
||||||
}
|
|
||||||
m_storage->write(&buf1[0], m_current_slot, 0, slot1_size);
|
m_storage->write(&buf1[0], m_current_slot, 0, slot1_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_storage->move_slot(other_slot, m_current_slot);
|
||||||
|
}
|
||||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
|| 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(piece1 == m_current_slot);
|
||||||
assert(piece_index == slot1);
|
assert(piece_index == slot1);
|
||||||
|
|
||||||
const int slot1_size = static_cast<int>(m_info.piece_size(piece1));
|
|
||||||
const int slot3_size = static_cast<int>(m_info.piece_size(piece_index));
|
const int slot3_size = static_cast<int>(m_info.piece_size(piece_index));
|
||||||
std::vector<char> buf1(static_cast<int>(slot1_size));
|
std::vector<char> buf(static_cast<int>(slot3_size));
|
||||||
std::vector<char> buf2(static_cast<int>(slot3_size));
|
|
||||||
|
|
||||||
m_storage->read(&buf2[0], m_current_slot, 0, slot3_size);
|
m_storage->read(&buf[0], m_current_slot, 0, slot3_size);
|
||||||
m_storage->read(&buf1[0], slot1, 0, slot1_size);
|
m_storage->move_slot(slot1, m_current_slot);
|
||||||
m_storage->write(&buf1[0], m_current_slot, 0, slot1_size);
|
m_storage->write(&buf[0], slot1, 0, slot3_size);
|
||||||
m_storage->write(&buf2[0], slot1, 0, slot3_size);
|
|
||||||
|
|
||||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
|| 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<int>(m_info.piece_size(piece1)) : 0;
|
const int slot1_size = piece1 >= 0 ? static_cast<int>(m_info.piece_size(piece1)) : 0;
|
||||||
const int slot2_size = static_cast<int>(m_info.piece_size(piece2));
|
|
||||||
const int slot3_size = static_cast<int>(m_info.piece_size(piece_index));
|
const int slot3_size = static_cast<int>(m_info.piece_size(piece_index));
|
||||||
|
|
||||||
std::vector<char> buf1(static_cast<int>(m_info.piece_length()));
|
std::vector<char> buf(static_cast<int>(m_info.piece_length()));
|
||||||
std::vector<char> buf2(static_cast<int>(m_info.piece_length()));
|
|
||||||
|
|
||||||
m_storage->read(&buf2[0], m_current_slot, 0, slot3_size);
|
m_storage->read(&buf[0], m_current_slot, 0, slot3_size);
|
||||||
m_storage->read(&buf1[0], slot2, 0, slot2_size);
|
m_storage->move_slot(slot2, m_current_slot);
|
||||||
m_storage->write(&buf1[0], m_current_slot, 0, slot2_size);
|
|
||||||
if (slot1_size > 0)
|
if (slot1_size > 0)
|
||||||
{
|
m_storage->move_slot(slot1, slot2);
|
||||||
m_storage->read(&buf1[0], slot1, 0, slot1_size);
|
m_storage->write(&buf[0], slot1, 0, slot3_size);
|
||||||
m_storage->write(&buf1[0], slot2, 0, slot1_size);
|
|
||||||
}
|
|
||||||
m_storage->write(&buf2[0], slot1, 0, slot3_size);
|
|
||||||
assert(m_slot_to_piece[m_current_slot] == unassigned
|
assert(m_slot_to_piece[m_current_slot] == unassigned
|
||||||
|| m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot);
|
|| 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_index]
|
||||||
, m_piece_to_slot[piece_at_our_slot]);
|
, m_piece_to_slot[piece_at_our_slot]);
|
||||||
|
|
||||||
const int slot_size = static_cast<int>(m_info.piece_size(slot_index));
|
m_storage->move_slot(piece_index, slot_index);
|
||||||
std::vector<char> buf(slot_size);
|
|
||||||
m_storage->read(&buf[0], piece_index, 0, slot_size);
|
|
||||||
m_storage->write(&buf[0], slot_index, 0, slot_size);
|
|
||||||
|
|
||||||
assert(m_slot_to_piece[piece_index] == piece_index);
|
assert(m_slot_to_piece[piece_index] == piece_index);
|
||||||
assert(m_piece_to_slot[piece_index] == piece_index);
|
assert(m_piece_to_slot[piece_index] == piece_index);
|
||||||
|
|
Loading…
Reference in New Issue