diff --git a/ChangeLog b/ChangeLog index 7aa57253c..5f5165730 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ + * fixed problem with the resource distribution algorithm + (controlling e.g upload/download rates) + * fixed incorrect asserts in storage related to torrents with + zero-sized files. * added support for trackerless torrents (with kademlia DHT). * support for torrents with the private flag set. * support for torrents containing bootstrap nodes for the diff --git a/include/libtorrent/bencode.hpp b/include/libtorrent/bencode.hpp index 75a135d8d..a142b5864 100755 --- a/include/libtorrent/bencode.hpp +++ b/include/libtorrent/bencode.hpp @@ -256,7 +256,7 @@ namespace libtorrent // ---------------------------------------------- // string default: - if (isdigit(*in)) + if (isdigit((unsigned char)*in)) { std::string len_s = read_until(in, end, ':'); assert(*in == ':'); diff --git a/src/allocate_resources.cpp b/src/allocate_resources.cpp index 49fbebc2d..eee6feb0f 100644 --- a/src/allocate_resources.cpp +++ b/src/allocate_resources.cpp @@ -158,6 +158,7 @@ namespace libtorrent , It end , resource_request T::* res) { + assert(resources >= 0); #ifndef NDEBUG allocate_resources_contract_check contract_check( resources @@ -197,7 +198,9 @@ namespace libtorrent resources = std::max(resources, sum_min); int resources_to_distribute = std::min(resources, sum_max) - sum_min; assert(resources_to_distribute >= 0); - +#ifndef NDEBUG + int prev_resources_to_distribute = resources_to_distribute; +#endif while (resources_to_distribute > 0) { size_type total_used = 0; @@ -215,11 +218,17 @@ namespace libtorrent size_type kNumer = resources_to_distribute; size_type kDenom = total_used; + assert(kNumer >= 0); + assert(kDenom >= 0); + assert(kNumer <= std::numeric_limits::max()); + assert(total_used < std::numeric_limits::max()); if (kNumer * max_used <= kDenom) { kNumer = 1; kDenom = max_used; + assert(kDenom >= 0); + assert(kDenom <= std::numeric_limits::max()); } for (It i = start; i != end && resources_to_distribute > 0; ++i) @@ -241,6 +250,10 @@ namespace libtorrent } assert(resources_to_distribute >= 0); + assert(resources_to_distribute < prev_resources_to_distribute); +#ifndef NDEBUG + prev_resources_to_distribute = resources_to_distribute; +#endif } } diff --git a/src/storage.cpp b/src/storage.cpp index e17fc5916..d7aacf2c3 100755 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -684,32 +684,37 @@ namespace libtorrent 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_pimpl->info.file_at(slices[counter].file_index).path - == file_iter->path); + assert(int(slices.size()) > counter); + size_type slice_size = slices[counter].size; + assert(slice_size == read_bytes); + assert(m_pimpl->info.file_at(slices[counter].file_index).path + == file_iter->path); #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) - { - // the file was not big enough - throw file_error("slot has no storage"); + if (read_bytes != 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; } - 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 - ++counter; + // 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_pimpl->save_path / file_iter->path; @@ -799,32 +804,35 @@ namespace libtorrent write_bytes = static_cast(file_iter->size - file_offset); } - assert(int(slices.size()) > counter); - assert(slices[counter].size == write_bytes); - assert(m_pimpl->info.file_at(slices[counter].file_index).path - == file_iter->path); - - assert(buf_pos >= 0); - assert(write_bytes >= 0); - size_type written = out->write(buf + buf_pos, write_bytes); - - if (written != write_bytes) + if (write_bytes > 0) { - std::stringstream s; - s << "no storage for slot " << slot; - throw file_error(s.str()); - } + assert(int(slices.size()) > counter); + assert(slices[counter].size == write_bytes); + assert(m_pimpl->info.file_at(slices[counter].file_index).path + == file_iter->path); - left_to_write -= write_bytes; - buf_pos += write_bytes; - assert(buf_pos >= 0); - file_offset += write_bytes; - assert(file_offset <= file_iter->size); + assert(buf_pos >= 0); + assert(write_bytes >= 0); + size_type written = out->write(buf + buf_pos, write_bytes); + + if (written != write_bytes) + { + std::stringstream s; + s << "no storage for slot " << slot; + throw file_error(s.str()); + } + + left_to_write -= write_bytes; + buf_pos += write_bytes; + assert(buf_pos >= 0); + file_offset += write_bytes; + assert(file_offset <= file_iter->size); + } if (left_to_write > 0) { #ifndef NDEBUG - ++counter; + if (write_bytes > 0) ++counter; #endif ++file_iter; diff --git a/test/test_storage.cpp b/test/test_storage.cpp index d35813f11..f6e9e1390 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -19,7 +19,10 @@ int test_main() 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); + info.add_file("temp_storage/test2.tmp", 612); + info.add_file("temp_storage/test3.tmp", 0); + info.add_file("temp_storage/test4.tmp", 0); + info.add_file("temp_storage/test5.tmp", 1); char piece0[piece_size] = { 6, 6, 6, 6, 6, 6, 6, 6 @@ -41,7 +44,7 @@ int test_main() create_directory(initial_path() / "temp_storage"); - int num_pieces = (613 + 17 + piece_size - 1) / piece_size; + int num_pieces = (1 + 612 + 17 + piece_size - 1) / piece_size; TEST_CHECK(info.num_pieces() == num_pieces); char piece[piece_size];