2007-02-06 Tatsuhiro Tsujikawa <tujikawa dot rednoah dot com>

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.
pull/1/head
Tatsuhiro Tsujikawa 2007-02-06 14:49:22 +00:00
parent a4e7bd7ec4
commit 5b2f8f036e
8 changed files with 90 additions and 8 deletions

View File

@ -1,3 +1,24 @@
2007-02-06 Tatsuhiro Tsujikawa <tujikawa dot rednoah dot com>
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 <tujikawa at rednoah dot com>
To lower CPU usage in BitTorrent download when --max-upload-limit

View File

@ -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;
}

View File

@ -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_

View File

@ -53,9 +53,7 @@ public:
~BitfieldManFactory() {}
static BitfieldManFactoryHandle getNewFactory() {
BitfieldManFactoryHandle factory =
BitfieldManFactoryHandle(new BitfieldManFactory());
factory->setRandomizer(defaultRandomizer);
BitfieldManFactoryHandle factory = new BitfieldManFactory();
return factory;
}

View File

@ -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) {

View File

@ -34,4 +34,4 @@
/* copyright --> */
#include "SimpleRandomizer.h"
RandomizerHandle SimpleRandomizer::randomizer = RandomizerHandle(new SimpleRandomizer());
RandomizerHandle SimpleRandomizer::randomizer = 0;

View File

@ -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() {}

View File

@ -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));
}