From 35763a2ae01683088b0772173f322f6509b77deb Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 25 Apr 2009 10:30:25 +0000 Subject: [PATCH] 2009-04-25 Tatsuhiro Tsujikawa Fixed the bug that prevents torrent download from finishing. The bug doesn't reveal for all torrents. The torrents affected this bug satisfies ((N+7)/8)%4 == 0 and N%32 != 0 where N is the number of pieces. * src/bitfield.h * test/bitfieldTest.cc --- ChangeLog | 10 ++++++++++ src/bitfield.h | 11 ++++++----- test/bitfieldTest.cc | 16 +++++++++++----- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index db611ff4..482f3435 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2009-04-25 Tatsuhiro Tsujikawa + + + Fixed the bug that prevents torrent download from finishing. The + bug doesn't reveal for all torrents. The torrents affected this + bug satisfies ((N+7)/8)%4 == 0 and N%32 != 0 where N is the number + of pieces. + * src/bitfield.h + * test/bitfieldTest.cc + 2009-04-24 Tatsuhiro Tsujikawa Code cleanup diff --git a/src/bitfield.h b/src/bitfield.h index 2c000031..e1b0cfaa 100644 --- a/src/bitfield.h +++ b/src/bitfield.h @@ -97,17 +97,18 @@ inline size_t countSetBit(const unsigned char* bitfield, size_t nbits) size_t count = 0; size_t size = sizeof(uint32_t); size_t len = (nbits+7)/8; + if(nbits%32 != 0) { + --len; + count += + countBit32(static_cast(bitfield[len]&lastByteMask(nbits))); + } size_t to = len/size; for(size_t i = 0; i < to; ++i) { count += countBit32(*reinterpret_cast(&bitfield[i*size])); } - for(size_t i = len-len%size; i < len-1; ++i) { + for(size_t i = len-len%size; i < len; ++i) { count += countBit32(static_cast(bitfield[i])); } - if(nbits%32 != 0) { - count += - countBit32(static_cast(bitfield[len-1]&lastByteMask(nbits))); - } return count; } diff --git a/test/bitfieldTest.cc b/test/bitfieldTest.cc index 6577093e..4dc7901c 100644 --- a/test/bitfieldTest.cc +++ b/test/bitfieldTest.cc @@ -40,11 +40,17 @@ void bitfieldTest::testCountBit32() void bitfieldTest::testCountSetBit() { - unsigned char bitfield[] = { 0xff, 0xff, 0xff, 0xf0, 0xff, 0x01 }; - - CPPUNIT_ASSERT_EQUAL((size_t)37, bitfield::countSetBit(bitfield, 48)); - CPPUNIT_ASSERT_EQUAL((size_t)36, bitfield::countSetBit(bitfield, 47)); - CPPUNIT_ASSERT_EQUAL((size_t)28, bitfield::countSetBit(bitfield, 32)); + unsigned char bitfield[] = { 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf9 }; + // (nbits+7)/8 == 0 && nbits%32 == 0 + CPPUNIT_ASSERT_EQUAL((size_t)62, bitfield::countSetBit(bitfield, 64)); + // (nbits+7)/8 != 0 && nbits%32 != 0 && len%4 == 0 + CPPUNIT_ASSERT_EQUAL((size_t)56, bitfield::countSetBit(bitfield, 56)); + // (nbits+7)/8 != 0 && nbits%32 != 0 && len%4 != 0 + CPPUNIT_ASSERT_EQUAL((size_t)40, bitfield::countSetBit(bitfield, 40)); + // (nbits+7)/8 == 0 && nbits%32 != 0 + CPPUNIT_ASSERT_EQUAL((size_t)61, bitfield::countSetBit(bitfield, 63)); + // nbts == 0 CPPUNIT_ASSERT_EQUAL((size_t)0, bitfield::countSetBit(bitfield, 0)); }