@@ -814,12 +814,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 1)
{
disconnect("'choke' message size != 1", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
incoming_choke();
@@ -849,12 +849,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 1)
{
disconnect("'unchoke' message size != 1", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
incoming_unchoke();
@@ -869,12 +869,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 1)
{
disconnect("'interested' message size != 1", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
incoming_interested();
@@ -889,12 +889,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 1)
{
disconnect("'not interested' message size != 1", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
incoming_not_interested();
@@ -909,12 +909,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 5)
{
disconnect("'have' message size != 5", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
@@ -938,6 +938,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = associated_torrent().lock();
TORRENT_ASSERT(t);
+ m_statistics.received_bytes(0, received);
// if we don't have the metedata, we cannot
// verify the bitfield size
if (t->valid_metadata()
@@ -951,7 +952,6 @@ namespace libtorrent
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
@@ -972,12 +972,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 13)
{
disconnect("'request' message size != 13", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
@@ -1008,7 +1008,10 @@ namespace libtorrent
{
TORRENT_ASSERT(!has_disk_receive_buffer());
if (!allocate_disk_receive_buffer(packet_size() - 9))
+ {
+ m_statistics.received_bytes(0, received);
return;
+ }
}
TORRENT_ASSERT(has_disk_receive_buffer());
@@ -1054,12 +1057,12 @@ namespace libtorrent
INVARIANT_CHECK;
TORRENT_ASSERT(received > 0);
+ m_statistics.received_bytes(0, received);
if (packet_size() != 13)
{
disconnect("'cancel' message size != 13", 2);
return;
}
- m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
@@ -519,9 +519,12 @@ namespace libtorrent
#endif
}
+ int file_index = file_iter - files().begin();
+
// if the file is empty, just create it. But also make sure
// the directory exists.
- if (file_iter->size == 0)
+ if (file_iter->size == 0 && (int(m_file_priority.size()) <= file_index
+ || m_file_priority[file_index] > 0))
{
file(m_save_path / file_iter->path, file::out, ec);
if (ec)
@@ -535,9 +538,10 @@ namespace libtorrent
#ifndef BOOST_NO_EXCEPTIONS
try {
#endif
- // don't allocate files with priority 0
- int file_index = file_iter - files().begin();
- if (allocate_files && (int(m_file_priority.size()) <= file_index
+ // don't allocate files with priority 0 or files
+ // that are pad files
+ if (allocate_files && !file_iter->pad_file
+ && (int(m_file_priority.size()) <= file_index
|| m_file_priority[file_index] > 0))
{
error_code ec;
@@ -1023,38 +1027,13 @@ namespace libtorrent
file_offset -= file_iter->size;
++file_iter;
+ TORRENT_ASSERT(file_iter != files().end());
}
-
+
int buf_pos = 0;
error_code ec;
- boost::shared_ptr<file> in(m_pool.open_file(
- this, m_save_path / file_iter->path, file::in, ec));
- if (!in || ec)
- {
- set_error(m_save_path / file_iter->path, ec);
- return -1;
- }
- TORRENT_ASSERT(file_offset < file_iter->size);
- TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
-
- size_type new_pos = in->seek(file_offset + file_iter->file_base, file::begin, ec);
- if (new_pos != file_offset + file_iter->file_base || ec)
- {
- // the file was not big enough
- if (!fill_zero)
- {
- set_error(m_save_path / file_iter->path, ec);
- return -1;
- }
- std::memset(buf + buf_pos, 0, size - buf_pos);
- return size;
- }
-
-#ifndef NDEBUG
- size_type in_tell = in->tell(ec);
- TORRENT_ASSERT(in_tell == file_offset + file_iter->file_base && !ec);
-#endif
+ boost::shared_ptr<file> in;
int left_to_read = size;
int slot_size = static_cast<int>(m_files.piece_size(slot));
@@ -1069,73 +1048,71 @@ namespace libtorrent
int counter = 0;
#endif
- while (left_to_read > 0)
+ int read_bytes;
+ for (;left_to_read > 0; ++file_iter, left_to_read -= read_bytes
+ , buf_pos += read_bytes)
{
- int read_bytes = left_to_read;
+ TORRENT_ASSERT(file_iter != files().end());
+ TORRENT_ASSERT(buf_pos >= 0);
+
+ read_bytes = left_to_read;
if (file_offset + read_bytes > file_iter->size)
- read_bytes = static_cast<int>(file_iter->size - file_offset);
+ read_bytes = std::max(static_cast<int>(file_iter->size - file_offset), 0);
+
+ if (read_bytes == 0) continue;
- if (read_bytes > 0)
- {
#ifndef NDEBUG
- TORRENT_ASSERT(int(slices.size()) > counter);
- size_type slice_size = slices[counter].size;
- TORRENT_ASSERT(slice_size == read_bytes);
- TORRENT_ASSERT(files().at(slices[counter].file_index).path
- == file_iter->path);
+ TORRENT_ASSERT(int(slices.size()) > counter);
+ size_type slice_size = slices[counter].size;
+ TORRENT_ASSERT(slice_size == read_bytes);
+ TORRENT_ASSERT(files().at(slices[counter].file_index).path
+ == file_iter->path);
+ ++counter;
#endif
- int actual_read = int(in->read(buf + buf_pos, read_bytes, ec));
+ if (file_iter->pad_file)
+ {
+ std::memset(buf + buf_pos, 0, read_bytes);
+ continue;
+ }
- if (read_bytes != actual_read || ec)
- {
- // the file was not big enough
- if (actual_read > 0) buf_pos += actual_read;
- if (!fill_zero)
- {
- set_error(m_save_path / file_iter->path, ec);
- return -1;
- }
- std::memset(buf + buf_pos, 0, size - buf_pos);
- return size;
- }
+ fs::path path = m_save_path / file_iter->path;
- left_to_read -= read_bytes;
- buf_pos += read_bytes;
- TORRENT_ASSERT(buf_pos >= 0);
- file_offset += read_bytes;
+ error_code ec;
+ in = m_pool.open_file(this, path, file::in, ec);
+ if (!in || ec)
+ {
+ set_error(path, ec);
+ return -1;
}
-
- if (left_to_read > 0)
+ size_type pos = in->seek(file_iter->file_base + file_offset, file::begin, ec);
+ if (pos != file_iter->file_base + file_offset || ec)
{
- ++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
- fs::path path = m_save_path / file_iter->path;
-
- file_offset = 0;
- error_code ec;
- in = m_pool.open_file( this, path, file::in, ec);
- if (!in || ec)
+ if (!fill_zero)
{
- set_error(path, ec);
+ set_error(m_save_path / file_iter->path, ec);
return -1;
}
- size_type pos = in->seek(file_iter->file_base, file::begin, ec);
- if (pos != file_iter->file_base || ec)
+ std::memset(buf + buf_pos, 0, size - buf_pos);
+ return size;
+ }
+ file_offset = 0;
+
+ int actual_read = int(in->read(buf + buf_pos, read_bytes, ec));
+
+ if (read_bytes != actual_read || ec)
+ {
+ // the file was not big enough
+ if (actual_read > 0) buf_pos += actual_read;
+ if (!fill_zero)
{
- if (!fill_zero)
- {
- set_error(m_save_path / file_iter->path, ec);
- return -1;
- }
- std::memset(buf + buf_pos, 0, size - buf_pos);
- return size;
+ set_error(m_save_path / file_iter->path, ec);
+ return -1;
}
+ std::memset(buf + buf_pos, 0, size - buf_pos);
+ return size;
}
+
}
return result;
}
@@ -1159,6 +1136,7 @@ namespace libtorrent
#endif
size_type start = slot * (size_type)m_files.piece_length() + offset;
+ TORRENT_ASSERT(start + size <= m_files.total_size());
// find the file iterator and file offset
size_type file_offset = start;
@@ -1174,27 +1152,10 @@ namespace libtorrent
TORRENT_ASSERT(file_iter != files().end());
}
- fs::path p(m_save_path / file_iter->path);
+ int buf_pos = 0;
error_code ec;
- boost::shared_ptr<file> out = m_pool.open_file(
- this, p, file::out | file::in, ec);
-
- if (!out || ec)
- {
- set_error(p, ec);
- return -1;
- }
- TORRENT_ASSERT(file_offset < file_iter->size);
- TORRENT_ASSERT(slices[0].offset == file_offset + file_iter->file_base);
-
- size_type pos = out->seek(file_offset + file_iter->file_base, file::begin, ec);
-
- if (pos != file_offset + file_iter->file_base || ec)
- {
- set_error(p, ec);
- return -1;
- }
+ boost::shared_ptr<file> out;
int left_to_write = size;
int slot_size = static_cast<int>(m_files.piece_size(slot));
@@ -1203,72 +1164,62 @@ namespace libtorrent
TORRENT_ASSERT(left_to_write >= 0);
- int buf_pos = 0;
#ifndef NDEBUG
int counter = 0;
#endif
- while (left_to_write > 0)
- {
- int write_bytes = left_to_write;
- if (file_offset + write_bytes > file_iter->size)
- {
- TORRENT_ASSERT(file_iter->size >= file_offset);
- write_bytes = static_cast<int>(file_iter->size - file_offset);
- }
- if (write_bytes > 0)
- {
- TORRENT_ASSERT(int(slices.size()) > counter);
- TORRENT_ASSERT(slices[counter].size == write_bytes);
- TORRENT_ASSERT(files().at(slices[counter].file_index).path
- == file_iter->path);
+ int write_bytes;
+ for (;left_to_write > 0; ++file_iter, left_to_write -= write_bytes
+ , buf_pos += write_bytes)
+ {
+ TORRENT_ASSERT(file_iter != files().end());
+ TORRENT_ASSERT(buf_pos >= 0);
- TORRENT_ASSERT(buf_pos >= 0);
- TORRENT_ASSERT(write_bytes >= 0);
- error_code ec;
- size_type written = out->write(buf + buf_pos, write_bytes, ec);
+ write_bytes = left_to_write;
+ if (file_offset + write_bytes > file_iter->size)
+ write_bytes = std::max(static_cast<int>(file_iter->size - file_offset), 0);
- if (written != write_bytes || ec)
- {
- set_error(m_save_path / file_iter->path, ec);
- return -1;
- }
+ if (write_bytes == 0) continue;
- left_to_write -= write_bytes;
- buf_pos += write_bytes;
- TORRENT_ASSERT(buf_pos >= 0);
- file_offset += write_bytes;
- TORRENT_ASSERT(file_offset <= file_iter->size);
- }
-
- if (left_to_write > 0)
- {
#ifndef NDEBUG
- if (write_bytes > 0) ++counter;
+ TORRENT_ASSERT(int(slices.size()) > counter);
+ size_type slice_size = slices[counter].size;
+ TORRENT_ASSERT(slice_size == write_bytes);
+ TORRENT_ASSERT(files().at(slices[counter].file_index).path
+ == file_iter->path);
+ ++counter;
#endif
- ++file_iter;
- TORRENT_ASSERT(file_iter != files().end());
- fs::path p = m_save_path / file_iter->path;
- file_offset = 0;
- error_code ec;
- out = m_pool.open_file(
- this, p, file::out | file::in, ec);
+ if (file_iter->pad_file)
+ continue;
- if (!out || ec)
- {
- set_error(p, ec);
- return -1;
- }
+ fs::path path = m_save_path / file_iter->path;
- size_type pos = out->seek(file_iter->file_base, file::begin, ec);
+ error_code ec;
+ out = m_pool.open_file(this, path, file::in | file::out, ec);
+ if (!out || ec)
+ {
+ set_error(path, ec);
+ return -1;
+ }
+ size_type pos = out->seek(file_iter->file_base + file_offset, file::begin, ec);
+ if (pos != file_iter->file_base + file_offset || ec)
+ {
+ set_error(m_save_path / file_iter->path, ec);
+ return -1;
+ }
+ file_offset = 0;
- if (pos != file_iter->file_base || ec)
- {
- set_error(p, ec);
- return -1;
- }
+ int actual_written = int(out->write(buf + buf_pos, write_bytes, ec));
+
+ if (write_bytes != actual_written || ec)
+ {
+ // the file was not big enough
+ if (actual_written > 0) buf_pos += actual_written;
+ set_error(m_save_path / file_iter->path, ec);
+ return -1;
}
+
}
return size;
}
@@ -506,6 +506,27 @@ namespace libtorrent
}
}
+ TORRENT_ASSERT(m_block_size > 0);
+ int file = 0;
+ for (file_storage::iterator i = m_torrent_file->files().begin()
+ , end(m_torrent_file->files().end()); i != end; ++i, ++file)
+ {
+ if (!i->pad_file) continue;
+
+ peer_request pr = m_torrent_file->map_file(file, 0, m_torrent_file->file_at(file).size);
+ int off = pr.start % m_block_size;
+ if (off != 0) { pr.length -= m_block_size - off; pr.start += m_block_size - off; }
+ TORRENT_ASSERT((pr.start % m_block_size) == 0);
+
+ int blocks_per_piece = m_torrent_file->piece_length() / m_block_size;
+ piece_block pb(pr.piece, pr.start / m_block_size);
+ for (; pr.length >= m_block_size; pr.length -= m_block_size, ++pb.block_index)
+ {
+ if (pb.block_index == blocks_per_piece) { pb.block_index = 0; ++pb.piece_index; }
+ m_picker->mark_as_finished(pb, 0);
+ }
+ }
+
m_storage->async_check_fastresume(&m_resume_entry
, bind(&torrent::on_resume_data_checked
, shared_from_this(), _1, _2));
@@ -3278,6 +3299,9 @@ namespace libtorrent
{
INVARIANT_CHECK;
+ TORRENT_ASSERT(is_finished());
+ TORRENT_ASSERT(m_state != torrent_status::finished && m_state != torrent_status::seeding);
+
if (alerts().should_post<torrent_finished_alert>())
{
alerts().post_alert(torrent_finished_alert(
@@ -3408,7 +3432,10 @@ namespace libtorrent
TORRENT_ASSERT(m_torrent_file->is_valid());
INVARIANT_CHECK;
- set_state(torrent_status::downloading);
+ // we might be finished already, in which case we should
+ // not switch to downloading mode.
+ if (m_state != torrent_status::finished)
+ set_state(torrent_status::downloading);
if (m_ses.m_alerts.should_post<torrent_checked_alert>())
{
@@ -4442,6 +4469,15 @@ namespace libtorrent
void torrent::set_state(torrent_status::state_t s)
{
+#ifndef NDEBUG
+ if (s == torrent_status::seeding)
+ TORRENT_ASSERT(is_seed());
+ if (s == torrent_status::finished)
+ TORRENT_ASSERT(is_finished());
+ if (s == torrent_status::downloading && m_state == torrent_status::finished)
+ TORRENT_ASSERT(!is_finished());
+#endif
+
if (m_state == s) return;
m_state = s;
if (m_ses.m_alerts.should_post<state_changed_alert>())