Ver Fonte

2009-07-04 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Made URI reusing function work.
	* src/CreateRequestCommand.cc
	* src/FileEntry.cc
	* src/FileEntry.h
	* test/FileEntryTest.cc
Tatsuhiro Tsujikawa há 16 anos atrás
pai
commit
a7c222b8ab
5 ficheiros alterados com 74 adições e 0 exclusões
  1. 8 0
      ChangeLog
  2. 4 0
      src/CreateRequestCommand.cc
  3. 35 0
      src/FileEntry.cc
  4. 6 0
      src/FileEntry.h
  5. 21 0
      test/FileEntryTest.cc

+ 8 - 0
ChangeLog

@@ -1,3 +1,11 @@
+2009-07-04  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Made URI reusing function work.
+	* src/CreateRequestCommand.cc
+	* src/FileEntry.cc
+	* src/FileEntry.h
+	* test/FileEntryTest.cc
+
 2009-07-04  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Add formerly fastest PeerStat's sessionDownloadLength to new

+ 4 - 0
src/CreateRequestCommand.cc

@@ -67,6 +67,10 @@ bool CreateRequestCommand::executeInternal()
     _fileEntry = _requestGroup->getDownloadContext()->findFileEntryByOffset
       (_segments.front()->getPositionToWrite());
   }
+  if(_fileEntry->getRemainingUris().empty() &&
+     getOption()->getAsBool(PREF_REUSE_URI)) {
+    _fileEntry->reuseUri(_requestGroup->getNumConcurrentCommand());
+  }
   req = _fileEntry->getRequest(_requestGroup->getURISelector(),
 			       getOption()->get(PREF_REFERER),
 			       // Don't use HEAD request when file

+ 35 - 0
src/FileEntry.cc

@@ -278,4 +278,39 @@ void FileEntry::extractURIResult
   _uriResults.erase(_uriResults.begin(), i);
 }
 
+void FileEntry::reuseUri(size_t num)
+{
+  std::deque<std::string> uris = _spentUris;
+  std::sort(uris.begin(), uris.end());
+  uris.erase(std::unique(uris.begin(), uris.end()), uris.end());
+
+  std::deque<std::string> errorUris(_uriResults.size());
+  std::transform(_uriResults.begin(), _uriResults.end(),
+		 errorUris.begin(), std::mem_fun_ref(&URIResult::getURI));
+  std::sort(errorUris.begin(), errorUris.end());
+  errorUris.erase(std::unique(errorUris.begin(), errorUris.end()),
+		  errorUris.end());
+     
+  std::deque<std::string> reusableURIs;
+  std::set_difference(uris.begin(), uris.end(),
+		      errorUris.begin(), errorUris.end(),
+		      std::back_inserter(reusableURIs));
+  size_t ininum = reusableURIs.size();
+  _logger->debug("Found %u reusable URIs",
+		 static_cast<unsigned int>(ininum));
+  // Reuse at least num URIs here to avoid to
+  // run this process repeatedly.
+  if(ininum > 0 && ininum < num) {
+    _logger->debug("fewer than num=%u",
+		   num);
+    for(size_t i = 0; i < num/ininum; ++i) {
+      _uris.insert(_uris.end(), reusableURIs.begin(), reusableURIs.end());
+    }
+    _uris.insert(_uris.end(), reusableURIs.begin(),
+		 reusableURIs.begin()+(num%ininum));
+    _logger->debug("Duplication complete: now %u URIs for reuse",
+		   static_cast<unsigned int>(_uris.size()));
+  }
+}
+
 } // namespace aria2

+ 6 - 0
src/FileEntry.h

@@ -225,6 +225,12 @@ public:
   {
     return _singleHostMultiConnection;
   }
+
+  // Reuse URIs which have not emitted error so far.  Thie method
+  // tries to reuse at least num URIs.  If less than num URIs found to
+  // reuse, those URIs are used more than once so that num URIs total
+  // are available to reuse.
+  void reuseUri(size_t num);
 };
 
 typedef SharedHandle<FileEntry> FileEntryHandle;

+ 21 - 0
test/FileEntryTest.cc

@@ -14,6 +14,7 @@ class FileEntryTest : public CppUnit::TestFixture {
   CPPUNIT_TEST(testExtractURIResult);
   CPPUNIT_TEST(testGetRequest);
   CPPUNIT_TEST(testGetRequest_disableSingleHostMultiConnection);
+  CPPUNIT_TEST(testReuseUri);
   CPPUNIT_TEST_SUITE_END();
 public:
   void setUp() {}
@@ -23,6 +24,7 @@ public:
   void testExtractURIResult();
   void testGetRequest();
   void testGetRequest_disableSingleHostMultiConnection();
+  void testReuseUri();
 };
 
 
@@ -128,4 +130,23 @@ void FileEntryTest::testGetRequest_disableSingleHostMultiConnection()
   CPPUNIT_ASSERT(req3rd.isNull());
 }
 
+void FileEntryTest::testReuseUri()
+{
+  SharedHandle<InOrderURISelector> selector(new InOrderURISelector());
+  SharedHandle<FileEntry> fileEntry = createFileEntry();
+  size_t numUris = fileEntry->getRemainingUris().size();
+  for(size_t i = 0; i < numUris; ++i) {
+    fileEntry->getRequest(selector);
+  }
+  CPPUNIT_ASSERT_EQUAL((size_t)0, fileEntry->getRemainingUris().size());
+  fileEntry->addURIResult("http://localhost/aria2.zip",
+			  downloadresultcode::UNKNOWN_ERROR);
+  fileEntry->reuseUri(3);
+  CPPUNIT_ASSERT_EQUAL((size_t)3, fileEntry->getRemainingUris().size());
+  const std::deque<std::string>& uris = fileEntry->getRemainingUris();
+  CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[0]);
+  CPPUNIT_ASSERT_EQUAL(std::string("http://mirror/aria2.zip"), uris[1]);
+  CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[2]);
+}
+
 } // namespace aria2