소스 검색

2009-05-03 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Fixed the bug that with --check-integrity option aria2 reports
	downloaded file size is 0 even if some parts of file is
	correctly downloaded.  This bug is reproducible for the download
	that a file includes last piece is missing. This bug doesn't
	reveal for single-torrent with file allocation on.
	* src/IteratableChecksumValidator.cc
	* test/IteratableChecksumValidatorTest.cc
Tatsuhiro Tsujikawa 16 년 전
부모
커밋
ee229c6f00
3개의 변경된 파일55개의 추가작업 그리고 14개의 파일을 삭제
  1. 10 0
      ChangeLog
  2. 13 14
      src/IteratableChunkChecksumValidator.cc
  3. 32 0
      test/IteratableChunkChecksumValidatorTest.cc

+ 10 - 0
ChangeLog

@@ -1,3 +1,13 @@
+2009-05-03  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Fixed the bug that with --check-integrity option aria2 reports
+	downloaded file size is 0 even if some parts of file is correctly
+	downloaded.  This bug is reproducible for the download that a file
+	includes last piece is missing. This bug doesn't reveal for
+	single-torrent with file allocation on.
+	* src/IteratableChecksumValidator.cc
+	* test/IteratableChecksumValidatorTest.cc
+
 2009-05-01  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Avoid circular reference between RequestGroup and AdaptiveURISelector

+ 13 - 14
src/IteratableChunkChecksumValidator.cc

@@ -83,23 +83,22 @@ void IteratableChunkChecksumValidator::validateChunk()
     std::string actualChecksum;
     try {
       actualChecksum = calculateActualChecksum();
+      if(actualChecksum == _dctx->getPieceHashes()[_currentIndex]) {
+	_bitfield->setBit(_currentIndex);
+      } else {
+	_logger->info(EX_INVALID_CHUNK_CHECKSUM,
+		      _currentIndex,
+		      Util::itos(getCurrentOffset(), true).c_str(),
+		      _dctx->getPieceHashes()[_currentIndex].c_str(),
+		      actualChecksum.c_str());
+	_bitfield->unsetBit(_currentIndex);
+      }
     } catch(RecoverableException& ex) {
       _logger->debug("Caught exception while validating piece index=%d. Some part of file may be missing. Continue operation.", ex, _currentIndex);
       _bitfield->unsetBit(_currentIndex);
-      _currentIndex++;
-      return;
     }
-    if(actualChecksum == _dctx->getPieceHashes()[_currentIndex]) {
-      _bitfield->setBit(_currentIndex);
-    } else {
-      _logger->info(EX_INVALID_CHUNK_CHECKSUM,
-		    _currentIndex,
-		    Util::itos(getCurrentOffset(), true).c_str(),
-		    _dctx->getPieceHashes()[_currentIndex].c_str(),
-		    actualChecksum.c_str());
-      _bitfield->unsetBit(_currentIndex);
-    }
-    _currentIndex++;
+
+    ++_currentIndex;
     if(finished()) {
       _pieceStorage->setBitfield(_bitfield->getBitfield(), _bitfield->getBitfieldLength());
     }
@@ -152,7 +151,7 @@ std::string IteratableChunkChecksumValidator::digest(off_t offset, size_t length
   while(curoffset < max) {
     size_t r = _pieceStorage->getDiskAdaptor()->readData(_buffer, BUFSIZE,
 							 curoffset);
-    if(r == 0) {
+    if(r == 0 || r < static_cast<size_t>(woffset)) {
       throw DlAbortEx
 	(StringFormat(EX_FILE_READ, _dctx->getActualBasePath().c_str(),
 		      strerror(errno)).str());

+ 32 - 0
test/IteratableChunkChecksumValidatorTest.cc

@@ -15,6 +15,7 @@ class IteratableChunkChecksumValidatorTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(IteratableChunkChecksumValidatorTest);
   CPPUNIT_TEST(testValidate);
+  CPPUNIT_TEST(testValidate_readError);
   CPPUNIT_TEST_SUITE_END();
 private:
 
@@ -24,6 +25,7 @@ public:
   }
 
   void testValidate();
+  void testValidate_readError();
 };
 
 
@@ -70,4 +72,34 @@ void IteratableChunkChecksumValidatorTest::testValidate() {
   CPPUNIT_ASSERT(ps->hasPiece(2));
 }
 
+void IteratableChunkChecksumValidatorTest::testValidate_readError() {
+  Option option;
+  SharedHandle<SingleFileDownloadContext> dctx
+    (new SingleFileDownloadContext(100, 500, "chunkChecksumTestFile250.txt"));
+  std::deque<std::string> hashes(&csArray[0], &csArray[3]);
+  hashes.push_back("ffffffffffffffffffffffffffffffffffffffff");
+  hashes.push_back("ffffffffffffffffffffffffffffffffffffffff");
+  dctx->setPieceHashes(hashes);
+  dctx->setPieceHashAlgo("sha1");
+  SharedHandle<DefaultPieceStorage> ps(new DefaultPieceStorage(dctx, &option));
+  ps->initStorage();
+  ps->getDiskAdaptor()->openFile();
+
+  IteratableChunkChecksumValidator validator(dctx, ps);
+  validator.init();
+
+  while(!validator.finished()) {
+    validator.validateChunk();
+  }
+
+  CPPUNIT_ASSERT(ps->hasPiece(0));
+  CPPUNIT_ASSERT(ps->hasPiece(1));
+  CPPUNIT_ASSERT(!ps->hasPiece(2)); // #2 piece is not valid because
+				    // #program expects its size is
+				    // #100, but it reads only 50
+				    // #bytes and raises error.
+  CPPUNIT_ASSERT(!ps->hasPiece(3));
+  CPPUNIT_ASSERT(!ps->hasPiece(4));
+}
+
 } // namespace aria2