소스 검색

2009-02-11 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Fixed broken selected file BitTorrent download.
	* src/MultiDiskWriter.cc
	* test/MultiDiskWriterTest.cc
	* test/MultiFileAllocationIteratorTest.cc
Tatsuhiro Tsujikawa 16 년 전
부모
커밋
b5af788a00
4개의 변경된 파일113개의 추가작업 그리고 31개의 파일을 삭제
  1. 7 0
      ChangeLog
  2. 39 13
      src/MultiDiskAdaptor.cc
  3. 66 17
      test/MultiDiskAdaptorTest.cc
  4. 1 1
      test/MultiFileAllocationIteratorTest.cc

+ 7 - 0
ChangeLog

@@ -1,3 +1,10 @@
+2009-02-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Fixed broken selected file BitTorrent download.
+	* src/MultiDiskWriter.cc
+	* test/MultiDiskWriterTest.cc
+	* test/MultiFileAllocationIteratorTest.cc
+
 2009-02-11  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Fixed #define guard for EpollEventPoll

+ 39 - 13
src/MultiDiskAdaptor.cc

@@ -34,8 +34,9 @@
 /* copyright --> */
 #include "MultiDiskAdaptor.h"
 
-#include <algorithm>
 #include <cassert>
+#include <algorithm>
+#include <map>
 
 #include "DefaultDiskWriter.h"
 #include "message.h"
@@ -196,18 +197,22 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
       (createDiskWriterEntry(*i, (*i)->isRequested()));
   }
 
+  std::map<std::string, bool> dwreq;
+
   // TODO Currently, pieceLength == 0 is used for unit testing only.
   if(pieceLength > 0) {
     std::deque<SharedHandle<DiskWriterEntry> >::iterator done =
       diskWriterEntries.begin();
     for(std::deque<SharedHandle<DiskWriterEntry> >::iterator itr =
 	  diskWriterEntries.begin(); itr != diskWriterEntries.end();) {
-      if(!(*itr)->getFileEntry()->isRequested()) {
+      const SharedHandle<FileEntry>& fileEntry = (*itr)->getFileEntry();
+
+      if(!fileEntry->isRequested()) {
 	++itr;
 	continue;
       }
       off_t pieceStartOffset =
-	((*itr)->getFileEntry()->getOffset()/pieceLength)*pieceLength;
+	(fileEntry->getOffset()/pieceLength)*pieceLength;
       if(itr != diskWriterEntries.begin()) {
 	for(std::deque<SharedHandle<DiskWriterEntry> >::iterator i =
 	      itr-1; true; --i) {
@@ -225,24 +230,45 @@ void MultiDiskAdaptor::resetDiskWriterEntries()
 	}
       }
 
-      ++itr;
+      if(fileEntry->getLength() > 0) {
+	off_t lastPieceStartOffset =
+	  (fileEntry->getOffset()+fileEntry->getLength()-1)/pieceLength*pieceLength;
+	logger->debug("Checking adjacent backward file to %s"
+		      " whose lastPieceStartOffset+pieceLength=%lld",
+		      fileEntry->getPath().c_str(),
+		      lastPieceStartOffset+pieceLength);
 
-      for(; itr != diskWriterEntries.end(); ++itr) {
-	if((*itr)->getFileEntry()->getOffset() <
-	   static_cast<off_t>(pieceStartOffset+pieceLength)) {
-	  (*itr)->needsFileAllocation(true);
-	} else {
-	  break;
+	++itr;
+	// adjacent backward files are not needed to be allocated. They
+	// just requre DiskWriter
+	for(; itr != diskWriterEntries.end() &&
+	      !(*itr)->getFileEntry()->isRequested(); ++itr) {
+	  logger->debug("file=%s, offset=%lld",
+			(*itr)->getFileEntry()->getPath().c_str(),
+			(*itr)->getFileEntry()->getOffset());
+
+	  if((*itr)->getFileEntry()->getOffset() <
+	     static_cast<off_t>(lastPieceStartOffset+pieceLength)) {
+	    logger->debug("%s needs diskwriter",
+			  (*itr)->getFileEntry()->getPath().c_str());
+	    dwreq[(*itr)->getFileEntry()->getPath()] = true;
+	  } else {
+	    break;
+	  }
 	}
+	done = itr-1;
+      } else {
+	done = itr;
+	++itr;
       }
-
-      done = itr-1;
     }
   }
   DefaultDiskWriterFactory dwFactory;
   for(std::deque<SharedHandle<DiskWriterEntry> >::iterator i =
 	diskWriterEntries.begin(); i != diskWriterEntries.end(); ++i) {
-    if((*i)->needsFileAllocation() || (*i)->fileExists(getTopDirPath())) {
+    if((*i)->needsFileAllocation() ||
+       dwreq.find((*i)->getFileEntry()->getPath()) != dwreq.end() ||
+       (*i)->fileExists(getTopDirPath())) {
       logger->debug("Creating DiskWriter for filename=%s",
 		    (*i)->getFilePath(getTopDirPath()).c_str());
       (*i)->setDiskWriter(dwFactory.newDiskWriter());

+ 66 - 17
test/MultiDiskAdaptorTest.cc

@@ -48,13 +48,22 @@ CPPUNIT_TEST_SUITE_REGISTRATION( MultiDiskAdaptorTest );
 
 std::deque<SharedHandle<FileEntry> > createEntries() {
   SharedHandle<FileEntry> array[] = {
-    SharedHandle<FileEntry>(new FileEntry("file1.txt", 0, 0)),
-    SharedHandle<FileEntry>(new FileEntry("file2.txt", 15, 0)),
-    SharedHandle<FileEntry>(new FileEntry("file3.txt", 7, 15)),
-    SharedHandle<FileEntry>(new FileEntry("file4.txt", 0, 22)),
-    SharedHandle<FileEntry>(new FileEntry("file5.txt", 2, 22)),
-    SharedHandle<FileEntry>(new FileEntry("file6.txt", 0, 24)),
+    SharedHandle<FileEntry>(new FileEntry("file0.txt", 0, 0)),
+    SharedHandle<FileEntry>(new FileEntry("file1.txt", 15, 0)),
+    SharedHandle<FileEntry>(new FileEntry("file2.txt", 7, 15)),
+    SharedHandle<FileEntry>(new FileEntry("file3.txt", 0, 22)),
+    SharedHandle<FileEntry>(new FileEntry("file4.txt", 2, 22)),
+    SharedHandle<FileEntry>(new FileEntry("file5.txt", 0, 24)),
   };
+  //           1    1    2    2
+  // 0....5....0....5....0....5
+  // ++--++--++--++--++--++--++
+  // | file0
+  // *************** file1
+  //                ******* file2
+  //                       | file3
+  //                       ** flie4
+  //                         | file5
   std::deque<SharedHandle<FileEntry> > entries(&array[0],
 					       &array[arrayLength(array)]);
   for(std::deque<SharedHandle<FileEntry> >::const_iterator i = entries.begin();
@@ -115,6 +124,7 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries()
     CPPUNIT_ASSERT(entries[0]->getDiskWriter().isNull());
     // Because entries[2] spans entries[1]
     CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[1]->needsFileAllocation());
     CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
@@ -136,6 +146,7 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries()
     CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
     // Because entries[4] spans entries[3]
     CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[3]->needsFileAllocation());
     CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
 
@@ -154,8 +165,8 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries()
     CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
-    // Because entries[3] spans entries[4]
-    CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
+    // entries[3] is 0 length. No overrap with entries[4]
+    CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
 
     adaptor->closeFile();
@@ -195,6 +206,44 @@ void MultiDiskAdaptorTest::testResetDiskWriterEntries()
     CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
     CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull());
 
+    adaptor->closeFile();
+  }
+  {
+    std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
+    for(size_t i = 1; i < 6; ++i) {
+      fileEntries[i]->setRequested(false);
+    }
+    adaptor->setFileEntries(fileEntries);
+    adaptor->openFile();
+    std::deque<SharedHandle<DiskWriterEntry> > entries =
+      adaptor->getDiskWriterEntries();
+    CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[1]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[2]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[3]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull());
+
+    adaptor->closeFile();
+  }
+  {
+    std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
+    for(size_t i = 2; i < 6; ++i) {
+      fileEntries[i]->setRequested(false);
+    }
+    adaptor->setFileEntries(fileEntries);
+    adaptor->openFile();
+    std::deque<SharedHandle<DiskWriterEntry> > entries =
+      adaptor->getDiskWriterEntries();
+    CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
+    // entries[1] spans entries[2]
+    CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(!entries[2]->needsFileAllocation());
+    CPPUNIT_ASSERT(entries[3]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull());
+    CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull());
+
     adaptor->closeFile();
   }
 }
@@ -220,9 +269,9 @@ void MultiDiskAdaptorTest::testWriteData() {
   adaptor->writeData((const unsigned char*)msg.c_str(), msg.size(), 0);
   adaptor->closeFile();
 
-  CPPUNIT_ASSERT(File("file1.txt").isFile());
+  CPPUNIT_ASSERT(File("file0.txt").isFile());
   char buf[128];
-  readFile("file2.txt", buf, 5);
+  readFile("file1.txt", buf, 5);
   buf[5] = '\0';
   CPPUNIT_ASSERT_EQUAL(msg, std::string(buf));
 
@@ -231,10 +280,10 @@ void MultiDiskAdaptorTest::testWriteData() {
   adaptor->writeData((const unsigned char*)msg2.c_str(), msg2.size(), 5);
   adaptor->closeFile();
 
-  readFile("file2.txt", buf, 15);
+  readFile("file1.txt", buf, 15);
   buf[15] = '\0';
   CPPUNIT_ASSERT_EQUAL(std::string("1234567890ABCDE"), std::string(buf));
-  readFile("file3.txt", buf, 1);
+  readFile("file2.txt", buf, 1);
   buf[1] = '\0';
   CPPUNIT_ASSERT_EQUAL(std::string("F"), std::string(buf));
 
@@ -243,20 +292,20 @@ void MultiDiskAdaptorTest::testWriteData() {
   adaptor->writeData((const unsigned char*)msg3.c_str(), msg3.size(), 10);
   adaptor->closeFile();
 
-  readFile("file2.txt", buf, 15);
+  readFile("file1.txt", buf, 15);
   buf[15] = '\0';
   CPPUNIT_ASSERT_EQUAL(std::string("123456789012345"), std::string(buf));
-  readFile("file3.txt", buf, 7);
+  readFile("file2.txt", buf, 7);
   buf[7] = '\0';
   CPPUNIT_ASSERT_EQUAL(std::string("1234567"), std::string(buf));
 
-  CPPUNIT_ASSERT(File("file4.txt").isFile());
+  CPPUNIT_ASSERT(File("file3.txt").isFile());
 
-  readFile("file5.txt", buf, 2);
+  readFile("file4.txt", buf, 2);
   buf[2] = '\0';
   CPPUNIT_ASSERT_EQUAL(std::string("12"), std::string(buf));
 
-  CPPUNIT_ASSERT(File("file6.txt").isFile());
+  CPPUNIT_ASSERT(File("file5.txt").isFile());
 
   } catch(Exception& e) {
     CPPUNIT_FAIL(e.stackTrace());

+ 1 - 1
test/MultiFileAllocationIteratorTest.cc

@@ -120,7 +120,7 @@ void MultiFileAllocationIteratorTest::testMakeDiskWriterEntries()
   // file9
   CPPUNIT_ASSERT_EQUAL(prefix+std::string("/file9"),
 		       entries[8]->getFilePath(prefix));
-  CPPUNIT_ASSERT(entries[8]->needsFileAllocation());
+  CPPUNIT_ASSERT(!entries[8]->needsFileAllocation());
   CPPUNIT_ASSERT(!entries[8]->getDiskWriter().isNull());
   // fileA
   CPPUNIT_ASSERT_EQUAL(prefix+std::string("/fileA"),