introduced swap_slots and swap_slots3 on storage_interface. All reads that needs it, should now be EOF safe (when using sparse files).

This commit is contained in:
Arvid Norberg 2007-05-16 01:16:08 +00:00
parent b386aa23e9
commit e9601080bb
2 changed files with 58 additions and 34 deletions

View File

@ -106,8 +106,16 @@ namespace libtorrent
virtual bool verify_resume_data(entry& rd, std::string& error) = 0; virtual bool verify_resume_data(entry& rd, std::string& error) = 0;
// moves (or copies) the content in src_slot to dst_slot
virtual void move_slot(int src_slot, int dst_slot) = 0; virtual void move_slot(int src_slot, int dst_slot) = 0;
// swaps the data in slot1 and slot2
virtual void swap_slots(int slot1, int slot2) = 0;
// swaps the puts the data in slot1 in slot2, the data in slot2
// in slot3 and the data in slot3 in slot1
virtual void swap_slots3(int slot1, int slot2, int slot3) = 0;
// this will close all open files that are opened for // this will close all open files that are opened for
// writing. This is called when a torrent has finished // writing. This is called when a torrent has finished
// downloading. // downloading.

View File

@ -376,6 +376,8 @@ namespace libtorrent
size_type read(char* buf, int slot, int offset, int size); size_type read(char* buf, int slot, int offset, int size);
void write(const char* buf, int slot, int offset, int size); void write(const char* buf, int slot, int offset, int size);
void move_slot(int src_slot, int dst_slot); void move_slot(int src_slot, int dst_slot);
void swap_slots(int slot1, int slot2);
void swap_slots3(int slot1, int slot2, int slot3);
bool verify_resume_data(entry& rd, std::string& error); bool verify_resume_data(entry& rd, std::string& error);
size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero); size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero);
@ -582,6 +584,35 @@ namespace libtorrent
write(&m_scratch_buffer[0], dst_slot, 0, piece_size); write(&m_scratch_buffer[0], dst_slot, 0, piece_size);
} }
void storage::swap_slots(int slot1, int slot2)
{
// the size of the target slot is the size of the piece
int piece_size = m_info.piece_length();
int piece1_size = m_info.piece_size(slot2);
int piece2_size = m_info.piece_size(slot1);
m_scratch_buffer.resize(piece_size * 2);
read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true);
read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true);
write(&m_scratch_buffer[0], slot2, 0, piece1_size);
write(&m_scratch_buffer[piece_size], slot1, 0, piece2_size);
}
void storage::swap_slots3(int slot1, int slot2, int slot3)
{
// the size of the target slot is the size of the piece
int piece_size = m_info.piece_length();
int piece1_size = m_info.piece_size(slot2);
int piece2_size = m_info.piece_size(slot3);
int piece3_size = m_info.piece_size(slot1);
m_scratch_buffer.resize(piece_size * 2);
read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true);
read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true);
write(&m_scratch_buffer[0], slot2, 0, piece1_size);
read_impl(&m_scratch_buffer[0], slot3, 0, piece3_size, true);
write(&m_scratch_buffer[piece_size], slot3, 0, piece2_size);
write(&m_scratch_buffer[0], slot1, 0, piece3_size);
}
size_type storage::read( size_type storage::read(
char* buf char* buf
, int slot , int slot
@ -1701,13 +1732,11 @@ namespace libtorrent
m_free_slots.push_back(m_current_slot); m_free_slots.push_back(m_current_slot);
} }
const int slot1_size = static_cast<int>(m_info.piece_size(piece_index)); if (other_piece >= 0)
const int slot2_size = other_piece >= 0 ? static_cast<int>(m_info.piece_size(other_piece)) : 0; m_storage->swap_slots(other_slot, m_current_slot);
std::vector<char> buf1(slot1_size); else
m_storage->read(&buf1[0], m_current_slot, 0, slot1_size); m_storage->move_slot(m_current_slot, other_slot);
if (slot2_size > 0)
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 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,21 +1752,14 @@ namespace libtorrent
m_slot_to_piece[m_current_slot] = other_piece; m_slot_to_piece[m_current_slot] = other_piece;
m_slot_to_piece[other_slot] = piece_index; m_slot_to_piece[other_slot] = piece_index;
m_piece_to_slot[other_piece] = m_current_slot; m_piece_to_slot[other_piece] = m_current_slot;
if (piece_index >= 0) m_piece_to_slot[piece_index] = other_slot;
if (piece_index == unassigned) if (piece_index == unassigned)
{
m_free_slots.push_back(other_slot); m_free_slots.push_back(other_slot);
}
const int slot1_size = static_cast<int>(m_info.piece_size(other_piece)); if (piece_index >= 0)
const int slot2_size = piece_index >= 0 ? static_cast<int>(m_info.piece_size(piece_index)) : 0;
if (slot2_size > 0)
{ {
std::vector<char> buf1(slot1_size); m_piece_to_slot[piece_index] = other_slot;
m_storage->read(&buf1[0], other_slot, 0, slot1_size); m_storage->swap_slots(other_slot, m_current_slot);
m_storage->move_slot(m_current_slot, other_slot);
m_storage->write(&buf1[0], m_current_slot, 0, slot1_size);
} }
else else
{ {
@ -1779,12 +1801,7 @@ namespace libtorrent
assert(piece1 == m_current_slot); assert(piece1 == m_current_slot);
assert(piece_index == slot1); assert(piece_index == slot1);
const int slot3_size = static_cast<int>(m_info.piece_size(piece_index)); m_storage->swap_slots(m_current_slot, slot1);
std::vector<char> buf(static_cast<int>(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 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);
@ -1805,7 +1822,6 @@ namespace libtorrent
m_piece_to_slot[piece_index] = slot1; m_piece_to_slot[piece_index] = slot1;
m_piece_to_slot[m_current_slot] = piece2; m_piece_to_slot[m_current_slot] = piece2;
if (piece1 >= 0) m_piece_to_slot[piece1] = slot2;
if (piece1 == unassigned) if (piece1 == unassigned)
{ {
@ -1816,16 +1832,16 @@ namespace libtorrent
m_free_slots.push_back(slot2); m_free_slots.push_back(slot2);
} }
const int slot1_size = piece1 >= 0 ? static_cast<int>(m_info.piece_size(piece1)) : 0; if (piece1 >= 0)
const int slot3_size = static_cast<int>(m_info.piece_size(piece_index)); {
m_piece_to_slot[piece1] = slot2;
std::vector<char> buf(static_cast<int>(m_info.piece_length())); m_storage->swap_slots3(m_current_slot, slot1, slot2);
}
m_storage->read(&buf[0], m_current_slot, 0, slot3_size); else
m_storage->move_slot(slot2, m_current_slot); {
if (slot1_size > 0) m_storage->move_slot(m_current_slot, slot1);
m_storage->move_slot(slot1, slot2); m_storage->move_slot(slot2, m_current_slot);
m_storage->write(&buf[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);