diff --git a/ChangeLog b/ChangeLog index 4e41b684..ee072f07 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2007-02-06 Tatsuhiro Tsujikawa + + To fix the bug that causes crash on Max OS X: + + * src/SimpleRandomizer.h + (getInstance): Create new instance if the static variable is null. + * src/SimpleRandomizer.cc + (randomizer): Initialized to 0. + * src/BitfieldManFactory.h + (getNewFactory): Removed the call to setRandomizer(). + + To fix the miscalculation of the range of checksum: + + * src/BitfieldMan.h + (isBitSetOffsetRange): New function. + * src/BitfieldMan.cc + (isBitSetOffsetRange): New function. + * src/SegmentMan.cc + (tryChunkChecksumValidation): Use BitfieldMan::isBitSetOffsetRange(). + Use bitfield->getBlockLength() instead of segment.segmentLength. + 2007-02-03 Tatsuhiro Tsujikawa To lower CPU usage in BitTorrent download when --max-upload-limit diff --git a/src/BitfieldMan.cc b/src/BitfieldMan.cc index af8488a4..f142e00a 100644 --- a/src/BitfieldMan.cc +++ b/src/BitfieldMan.cc @@ -644,3 +644,24 @@ void BitfieldMan::unsetBitRange(int32_t startIndex, int32_t endIndex) } updateCache(); } + +bool BitfieldMan::isBitSetOffsetRange(int64_t offset, int64_t length) const +{ + if(length <= 0) { + return false; + } + if(totalLength <= offset) { + return false; + } + if(totalLength < offset+length) { + length = totalLength-offset; + } + int32_t startBlock = offset/blockLength; + int32_t endBlock = (offset+length-1)/blockLength; + for(int32_t i = startBlock; i <= endBlock; i++) { + if(!isBitSet(i)) { + return false; + } + } + return true; +} diff --git a/src/BitfieldMan.h b/src/BitfieldMan.h index 3ced8678..663ae62c 100644 --- a/src/BitfieldMan.h +++ b/src/BitfieldMan.h @@ -254,6 +254,9 @@ public: bool isBitRangeSet(int32_t startIndex, int32_t endIndex) const; void unsetBitRange(int32_t startIndex, int32_t endIndex); + + bool isBitSetOffsetRange(int64_t offset, int64_t length) const; + }; #endif // _D_BITFIELD_MAN_H_ diff --git a/src/BitfieldManFactory.h b/src/BitfieldManFactory.h index 2e1af096..34377a09 100644 --- a/src/BitfieldManFactory.h +++ b/src/BitfieldManFactory.h @@ -53,9 +53,7 @@ public: ~BitfieldManFactory() {} static BitfieldManFactoryHandle getNewFactory() { - BitfieldManFactoryHandle factory = - BitfieldManFactoryHandle(new BitfieldManFactory()); - factory->setRandomizer(defaultRandomizer); + BitfieldManFactoryHandle factory = new BitfieldManFactory(); return factory; } diff --git a/src/SegmentMan.cc b/src/SegmentMan.cc index 2c433641..12edb358 100644 --- a/src/SegmentMan.cc +++ b/src/SegmentMan.cc @@ -497,10 +497,12 @@ void SegmentMan::tryChunkChecksumValidation(const Segment& segment) segment.getPosition(), segment.writtenLength, chunkHashLength); - if(hashStartIndex*chunkHashLength < segment.getPosition() && !bitfield->isBitSet(segment.index-1)) { + if(!bitfield->isBitSetOffsetRange((int64_t)hashStartIndex*chunkHashLength, + chunkHashLength)) { ++hashStartIndex; } - if(hashEndIndex*(chunkHashLength+1) > segment.getPosition()+segment.segmentLength && !bitfield->isBitSet(segment.index+1)) { + if(!bitfield->isBitSetOffsetRange((int64_t)hashEndIndex*chunkHashLength, + chunkHashLength)) { --hashEndIndex; } logger->debug("hashStartIndex=%d, hashEndIndex=%d", @@ -515,7 +517,7 @@ void SegmentMan::tryChunkChecksumValidation(const Segment& segment) Util::indexRange(startIndex, endIndex, hashOffset, (hashEndIndex-hashStartIndex+1)*chunkHashLength, - segment.segmentLength); + bitfield->getBlockLength()); logger->debug("startIndex=%d, endIndex=%d", startIndex, endIndex); if(bitfield->isBitRangeSet(startIndex, endIndex)) { for(int32_t index = hashStartIndex; index <= hashEndIndex; ++index) { diff --git a/src/SimpleRandomizer.cc b/src/SimpleRandomizer.cc index f975aa7e..c13a5f7b 100644 --- a/src/SimpleRandomizer.cc +++ b/src/SimpleRandomizer.cc @@ -34,4 +34,4 @@ /* copyright --> */ #include "SimpleRandomizer.h" -RandomizerHandle SimpleRandomizer::randomizer = RandomizerHandle(new SimpleRandomizer()); +RandomizerHandle SimpleRandomizer::randomizer = 0; diff --git a/src/SimpleRandomizer.h b/src/SimpleRandomizer.h index c826e5dd..13534034 100644 --- a/src/SimpleRandomizer.h +++ b/src/SimpleRandomizer.h @@ -47,11 +47,14 @@ private: public: static RandomizerHandle getInstance() { + if(randomizer.isNull()) { + randomizer = new SimpleRandomizer(); + } return randomizer; } static void init() { - srandom(time(NULL)); + srandom(time(0)); } virtual ~SimpleRandomizer() {} diff --git a/test/BitfieldManTest.cc b/test/BitfieldManTest.cc index 814175b7..60187cc9 100644 --- a/test/BitfieldManTest.cc +++ b/test/BitfieldManTest.cc @@ -15,6 +15,7 @@ class BitfieldManTest:public CppUnit::TestFixture { CPPUNIT_TEST(testFilter); CPPUNIT_TEST(testGetMissingIndex); CPPUNIT_TEST(testGetSparceMissingUnusedIndex); + CPPUNIT_TEST(testIsBitSetOffsetRange); CPPUNIT_TEST_SUITE_END(); private: RandomizerHandle fixedNumberRandomizer; @@ -35,6 +36,7 @@ public: void testFilter(); void testGetMissingIndex(); void testGetSparceMissingUnusedIndex(); + void testIsBitSetOffsetRange(); }; @@ -233,3 +235,35 @@ void BitfieldManTest::testGetSparceMissingUnusedIndex() { bitfield.setBit(9); CPPUNIT_ASSERT_EQUAL(-1, bitfield.getSparseMissingUnusedIndex()); } + +void BitfieldManTest::testIsBitSetOffsetRange() +{ + int64_t totalLength = (int64_t)4*1024*1024*1024; + int32_t pieceLength = 4*1024*1024; + BitfieldMan bitfield(pieceLength, totalLength); + bitfield.setAllBit(); + + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(0, 0)); + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(0, -1)); + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(totalLength, 100)); + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(totalLength+1, 100)); + + CPPUNIT_ASSERT(bitfield.isBitSetOffsetRange(0, totalLength)); + CPPUNIT_ASSERT(bitfield.isBitSetOffsetRange(0, totalLength+1)); + + bitfield.clearAllBit(); + + bitfield.setBit(100); + bitfield.setBit(101); + + CPPUNIT_ASSERT(bitfield.isBitSetOffsetRange(pieceLength*100, pieceLength*2)); + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(pieceLength*100-10, pieceLength*2)); + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(pieceLength*100, pieceLength*2+1)); + + bitfield.clearAllBit(); + + bitfield.setBit(100); + bitfield.setBit(102); + + CPPUNIT_ASSERT(!bitfield.isBitSetOffsetRange(pieceLength*100, pieceLength*3)); +}